aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--Documentation/DocBook/kernel-api.tmpl9
-rw-r--r--Documentation/SubmittingPatches10
-rw-r--r--Documentation/accounting/delay-accounting.txt10
-rw-r--r--Documentation/cpu-freq/user-guide.txt5
-rw-r--r--Documentation/cpu-hotplug.txt12
-rw-r--r--Documentation/devices.txt8
-rw-r--r--Documentation/feature-removal-schedule.txt16
-rw-r--r--Documentation/infiniband/ipoib.txt2
-rw-r--r--Documentation/initrd.txt16
-rw-r--r--Documentation/kbuild/makefiles.txt14
-rw-r--r--Documentation/kernel-parameters.txt4
-rw-r--r--Documentation/sysctl/kernel.txt5
-rw-r--r--Documentation/usb/proc_usb_info.txt2
-rw-r--r--Documentation/usb/usb-help.txt3
-rw-r--r--Documentation/x86_64/boot-options.txt7
-rw-r--r--MAINTAINERS40
-rw-r--r--Makefile7
-rw-r--r--arch/alpha/kernel/err_ev7.c8
-rw-r--r--arch/alpha/kernel/osf_sys.c4
-rw-r--r--arch/alpha/kernel/setup.c50
-rw-r--r--arch/alpha/kernel/sys_ruffian.c8
-rw-r--r--arch/alpha/kernel/time.c2
-rw-r--r--arch/arm/common/gic.c3
-rw-r--r--arch/arm/common/locomo.c15
-rw-r--r--arch/arm/common/sa1111.c6
-rw-r--r--arch/arm/common/vic.c3
-rw-r--r--arch/arm/configs/ep93xx_defconfig15
-rw-r--r--arch/arm/kernel/ecard.c3
-rw-r--r--arch/arm/kernel/head.S6
-rw-r--r--arch/arm/kernel/irq.c1
-rw-r--r--arch/arm/kernel/traps.c7
-rw-r--r--arch/arm/mach-at91rm9200/gpio.c3
-rw-r--r--arch/arm/mach-at91rm9200/irq.c3
-rw-r--r--arch/arm/mach-footbridge/cats-hw.c2
-rw-r--r--arch/arm/mach-imx/irq.c6
-rw-r--r--arch/arm/mach-integrator/integrator_ap.c3
-rw-r--r--arch/arm/mach-integrator/integrator_cp.c9
-rw-r--r--arch/arm/mach-iop3xx/iop321-irq.c3
-rw-r--r--arch/arm/mach-iop3xx/iop331-irq.c6
-rw-r--r--arch/arm/mach-lh7a40x/arch-kev7a400.c3
-rw-r--r--arch/arm/mach-lh7a40x/arch-lpd7a40x.c3
-rw-r--r--arch/arm/mach-lh7a40x/irq-kev7a400.c3
-rw-r--r--arch/arm/mach-lh7a40x/irq-lh7a400.c6
-rw-r--r--arch/arm/mach-lh7a40x/irq-lh7a404.c12
-rw-r--r--arch/arm/mach-lh7a40x/irq-lpd7a40x.c3
-rw-r--r--arch/arm/mach-omap1/fpga.c6
-rw-r--r--arch/arm/mach-omap1/irq.c3
-rw-r--r--arch/arm/mach-omap2/irq.c3
-rw-r--r--arch/arm/mach-pxa/irq.c12
-rw-r--r--arch/arm/mach-pxa/lpd270.c3
-rw-r--r--arch/arm/mach-pxa/lubbock.c3
-rw-r--r--arch/arm/mach-pxa/mainstone.c3
-rw-r--r--arch/arm/mach-s3c2410/mach-anubis.c49
-rw-r--r--arch/arm/mach-s3c2410/mach-osiris.c20
-rw-r--r--arch/arm/mach-sa1100/irq.c9
-rw-r--r--arch/arm/mach-shark/irq.c3
-rw-r--r--arch/arm/mach-versatile/core.c3
-rw-r--r--arch/arm/mm/ioremap.c2
-rw-r--r--arch/arm/mm/proc-syms.c8
-rw-r--r--arch/arm/mm/proc-xscale.S30
-rw-r--r--arch/arm/plat-omap/gpio.c8
-rw-r--r--arch/i386/Kconfig2
-rw-r--r--arch/i386/kernel/Makefile3
-rw-r--r--arch/i386/kernel/cpu/cpufreq/Kconfig3
-rw-r--r--arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c3
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c221
-rw-r--r--arch/i386/kernel/cpu/intel_cacheinfo.c2
-rw-r--r--arch/i386/kernel/cpu/mcheck/mce.h2
-rw-r--r--arch/i386/kernel/entry.S2
-rw-r--r--arch/i386/kernel/kprobes.c9
-rw-r--r--arch/i386/kernel/machine_kexec.c13
-rw-r--r--arch/i386/kernel/nmi.c1
-rw-r--r--arch/i386/kernel/process.c4
-rw-r--r--arch/i386/kernel/smpboot.c62
-rw-r--r--arch/i386/kernel/time.c2
-rw-r--r--arch/i386/kernel/traps.c29
-rw-r--r--arch/i386/kernel/vsyscall.lds.S1
-rw-r--r--arch/ia64/configs/sn2_defconfig2
-rw-r--r--arch/ia64/defconfig2
-rw-r--r--arch/ia64/hp/sim/simscsi.c4
-rw-r--r--arch/ia64/kernel/Makefile3
-rw-r--r--arch/ia64/kernel/efi.c6
-rw-r--r--arch/ia64/kernel/gate.lds.S1
-rw-r--r--arch/ia64/kernel/head.S2
-rw-r--r--arch/ia64/kernel/ia64_ksyms.c2
-rw-r--r--arch/ia64/kernel/kprobes.c9
-rw-r--r--arch/ia64/kernel/pal.S18
-rw-r--r--arch/ia64/kernel/palinfo.c47
-rw-r--r--arch/ia64/kernel/topology.c2
-rw-r--r--arch/ia64/kernel/traps.c7
-rw-r--r--arch/ia64/kernel/uncached.c86
-rw-r--r--arch/ia64/lib/Makefile2
-rw-r--r--arch/ia64/mm/contig.c16
-rw-r--r--arch/ia64/mm/discontig.c68
-rw-r--r--arch/ia64/mm/init.c55
-rw-r--r--arch/ia64/mm/ioremap.c6
-rw-r--r--arch/ia64/sn/kernel/xpc_main.c2
-rw-r--r--arch/ia64/sn/pci/tioce_provider.c6
-rw-r--r--arch/parisc/kernel/vmlinux.lds.S1
-rw-r--r--arch/powerpc/Kconfig2
-rw-r--r--arch/powerpc/configs/pmac32_defconfig112
-rw-r--r--arch/powerpc/kernel/head_64.S35
-rw-r--r--arch/powerpc/kernel/legacy_serial.c13
-rw-r--r--arch/powerpc/kernel/misc_64.S2
-rw-r--r--arch/powerpc/kernel/prom_init.c36
-rw-r--r--arch/powerpc/kernel/smp.c24
-rw-r--r--arch/powerpc/kernel/sysfs.c4
-rw-r--r--arch/powerpc/kernel/traps.c10
-rw-r--r--arch/powerpc/kernel/udbg_16550.c6
-rw-r--r--arch/powerpc/kernel/vdso32/Makefile3
-rw-r--r--arch/powerpc/kernel/vdso32/vdso32.lds.S1
-rw-r--r--arch/powerpc/kernel/vdso64/Makefile3
-rw-r--r--arch/powerpc/kernel/vdso64/vdso64.lds.S1
-rw-r--r--arch/powerpc/mm/lmb.c3
-rw-r--r--arch/powerpc/platforms/chrp/setup.c12
-rw-r--r--arch/powerpc/platforms/maple/setup.c17
-rw-r--r--arch/powerpc/platforms/powermac/backlight.c58
-rw-r--r--arch/powerpc/platforms/powermac/bootx_init.c35
-rw-r--r--arch/powerpc/platforms/powermac/cpufreq_64.c78
-rw-r--r--arch/powerpc/platforms/pseries/setup.c6
-rw-r--r--arch/ppc/kernel/vmlinux.lds.S1
-rw-r--r--arch/s390/appldata/appldata_base.c10
-rw-r--r--arch/s390/defconfig44
-rw-r--r--arch/s390/kernel/head31.S4
-rw-r--r--arch/s390/kernel/head64.S4
-rw-r--r--arch/s390/kernel/setup.c46
-rw-r--r--arch/sh/kernel/cpu/sh4/sq.c10
-rw-r--r--arch/sparc/kernel/devices.c25
-rw-r--r--arch/sparc/kernel/irq.c2
-rw-r--r--arch/sparc/kernel/of_device.c34
-rw-r--r--arch/sparc/kernel/prom.c9
-rw-r--r--arch/sparc/kernel/smp.c96
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c1
-rw-r--r--arch/sparc/kernel/sun4d_smp.c103
-rw-r--r--arch/sparc/kernel/sys_sparc.c18
-rw-r--r--arch/sparc/kernel/time.c74
-rw-r--r--arch/sparc/mm/io-unit.c1
-rw-r--r--arch/sparc/prom/tree.c18
-rw-r--r--arch/sparc64/defconfig8
-rw-r--r--arch/sparc64/kernel/devices.c3
-rw-r--r--arch/sparc64/kernel/of_device.c34
-rw-r--r--arch/sparc64/kernel/prom.c12
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c1
-rw-r--r--arch/sparc64/kernel/sys_sparc.c18
-rw-r--r--arch/sparc64/mm/fault.c3
-rw-r--r--arch/sparc64/prom/tree.c85
-rw-r--r--arch/um/kernel/dyn.lds.S1
-rw-r--r--arch/v850/kernel/setup.c6
-rw-r--r--arch/v850/kernel/v850_ksyms.c16
-rw-r--r--arch/x86_64/defconfig9
-rw-r--r--arch/x86_64/ia32/Makefile1
-rw-r--r--arch/x86_64/ia32/ia32entry.S2
-rw-r--r--arch/x86_64/ia32/vsyscall.lds1
-rw-r--r--arch/x86_64/kernel/entry.S18
-rw-r--r--arch/x86_64/kernel/machine_kexec.c13
-rw-r--r--arch/x86_64/kernel/mce.c12
-rw-r--r--arch/x86_64/kernel/mce_amd.c19
-rw-r--r--arch/x86_64/kernel/pci-calgary.c77
-rw-r--r--arch/x86_64/kernel/pci-nommu.c2
-rw-r--r--arch/x86_64/kernel/pci-swiotlb.c5
-rw-r--r--arch/x86_64/kernel/smp.c2
-rw-r--r--arch/x86_64/kernel/tce.c4
-rw-r--r--arch/x86_64/kernel/time.c18
-rw-r--r--arch/x86_64/kernel/traps.c24
-rw-r--r--arch/x86_64/pci/k8-bus.c10
-rw-r--r--arch/xtensa/kernel/traps.c8
-rw-r--r--block/blktrace.c2
-rw-r--r--block/cfq-iosched.c2
-rw-r--r--drivers/acpi/acpi_memhotplug.c13
-rw-r--r--drivers/acpi/dock.c13
-rw-r--r--drivers/base/topology.c2
-rw-r--r--drivers/block/cciss.c86
-rw-r--r--drivers/block/nbd.c19
-rw-r--r--drivers/block/pktcdvd.c6
-rw-r--r--drivers/bluetooth/hci_usb.c25
-rw-r--r--drivers/char/hvsi.c8
-rw-r--r--drivers/char/hw_random/geode-rng.c6
-rw-r--r--drivers/char/hw_random/intel-rng.c2
-rw-r--r--drivers/char/hw_random/omap-rng.c51
-rw-r--r--drivers/char/keyboard.c139
-rw-r--r--drivers/char/pc8736x_gpio.c1
-rw-r--r--drivers/char/pcmcia/synclink_cs.c14
-rw-r--r--drivers/char/snsc.c7
-rw-r--r--drivers/char/synclink.c14
-rw-r--r--drivers/char/synclink_gt.c14
-rw-r--r--drivers/char/synclinkmp.c14
-rw-r--r--drivers/connector/cn_proc.c20
-rw-r--r--drivers/cpufreq/cpufreq.c115
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c2
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c20
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c3
-rw-r--r--drivers/dma/ioatdma.c2
-rw-r--r--drivers/edac/edac_mc.h1
-rw-r--r--drivers/fc4/fc.c4
-rw-r--r--drivers/i2c/busses/scx200_acb.c7
-rw-r--r--drivers/ide/Kconfig15
-rw-r--r--drivers/ide/ide-disk.c2
-rw-r--r--drivers/ide/ide-dma.c2
-rw-r--r--drivers/ide/ide-iops.c2
-rw-r--r--drivers/ide/ide.c5
-rw-r--r--drivers/ide/pci/it821x.c11
-rw-r--r--drivers/ieee1394/sbp2.c3
-rw-r--r--drivers/infiniband/core/addr.c30
-rw-r--r--drivers/infiniband/core/cm.c4
-rw-r--r--drivers/infiniband/core/mad.c22
-rw-r--r--drivers/infiniband/core/user_mad.c87
-rw-r--r--drivers/infiniband/core/uverbs.h2
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c42
-rw-r--r--drivers/infiniband/core/uverbs_main.c8
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c76
-rw-r--r--drivers/infiniband/hw/ipath/ipath_keys.c15
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.c5
-rw-r--r--drivers/infiniband/hw/mthca/mthca_allocator.c15
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c5
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c3
-rw-r--r--drivers/infiniband/ulp/ipoib/Kconfig3
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h1
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c23
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c8
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c19
-rw-r--r--drivers/input/evdev.c10
-rw-r--r--drivers/input/gameport/fm801-gp.c4
-rw-r--r--drivers/input/gameport/gameport.c66
-rw-r--r--drivers/input/input.c57
-rw-r--r--drivers/input/joystick/iforce/iforce-main.c19
-rw-r--r--drivers/input/joystick/spaceball.c2
-rw-r--r--drivers/input/keyboard/atkbd.c103
-rw-r--r--drivers/input/misc/wistron_btns.c20
-rw-r--r--drivers/input/mouse/logips2pp.c3
-rw-r--r--drivers/input/mouse/trackpoint.c52
-rw-r--r--drivers/input/serio/libps2.c5
-rw-r--r--drivers/input/serio/serio.c65
-rw-r--r--drivers/isdn/hardware/eicon/divasync.h1
-rw-r--r--drivers/macintosh/Kconfig13
-rw-r--r--drivers/macintosh/adbhid.c14
-rw-r--r--drivers/macintosh/therm_pm72.c218
-rw-r--r--drivers/macintosh/therm_pm72.h33
-rw-r--r--drivers/macintosh/via-pmu-backlight.c68
-rw-r--r--drivers/macintosh/via-pmu-led.c2
-rw-r--r--drivers/macintosh/via-pmu.c39
-rw-r--r--drivers/md/linear.c6
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c15
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c24
-rw-r--r--drivers/media/dvb/ttpci/av7110.c4
-rw-r--r--drivers/media/dvb/ttpci/av7110_v4l.c12
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c3
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c2
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c57
-rw-r--r--drivers/media/dvb/ttpci/budget-patch.c2
-rw-r--r--drivers/media/dvb/ttpci/budget.c5
-rw-r--r--drivers/media/dvb/ttpci/budget.h7
-rw-r--r--drivers/media/video/Kconfig4
-rw-r--r--drivers/media/video/bt8xx/Kconfig2
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c15
-rw-r--r--drivers/media/video/bt8xx/bttv-vbi.c15
-rw-r--r--drivers/media/video/compat_ioctl32.c24
-rw-r--r--drivers/media/video/cpia2/Kconfig2
-rw-r--r--drivers/media/video/cx88/cx88-input.c2
-rw-r--r--drivers/media/video/cx88/cx88-video.c5
-rw-r--r--drivers/media/video/msp3400-driver.c10
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c8
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-io.c9
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-io.h2
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-ioread.c5
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-sysfs.c85
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c10
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c16
-rw-r--r--drivers/media/video/saa7134/saa7134-oss.c10
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c6
-rw-r--r--drivers/media/video/saa7134/saa7134.h4
-rw-r--r--drivers/media/video/stradis.c1
-rw-r--r--drivers/media/video/tuner-core.c31
-rw-r--r--drivers/media/video/tuner-simple.c19
-rw-r--r--drivers/media/video/usbvideo/Kconfig8
-rw-r--r--drivers/media/video/v4l2-common.c24
-rw-r--r--drivers/media/video/videodev.c29
-rw-r--r--drivers/media/video/vivi.c4
-rw-r--r--drivers/message/fusion/Kconfig2
-rw-r--r--drivers/message/fusion/Makefile1
-rw-r--r--drivers/message/fusion/mptbase.c99
-rw-r--r--drivers/message/fusion/mptbase.h13
-rw-r--r--drivers/message/fusion/mptctl.c4
-rw-r--r--drivers/message/fusion/mptctl.h5
-rw-r--r--drivers/message/fusion/mptfc.c14
-rw-r--r--drivers/message/fusion/mptsas.c109
-rw-r--r--drivers/message/fusion/mptscsih.c118
-rw-r--r--drivers/message/fusion/mptspi.c10
-rw-r--r--drivers/net/appletalk/Kconfig2
-rw-r--r--drivers/net/dummy.c1
-rw-r--r--drivers/net/e1000/e1000.h3
-rw-r--r--drivers/net/e1000/e1000_main.c63
-rw-r--r--drivers/net/ifb.c1
-rw-r--r--drivers/net/myri10ge/myri10ge.c26
-rw-r--r--drivers/net/phy/phy.c8
-rw-r--r--drivers/net/s2io.c386
-rw-r--r--drivers/net/s2io.h10
-rw-r--r--drivers/net/skge.c5
-rw-r--r--drivers/net/sky2.c7
-rw-r--r--drivers/net/spider_net.c580
-rw-r--r--drivers/net/spider_net.h73
-rw-r--r--drivers/net/sunhme.c9
-rw-r--r--drivers/net/sunlance.c8
-rw-r--r--drivers/net/tg3.c122
-rw-r--r--drivers/net/via-velocity.c17
-rw-r--r--drivers/net/wan/c101.c4
-rw-r--r--drivers/net/wan/hdlc_ppp.c1
-rw-r--r--drivers/net/wan/hdlc_raw.c1
-rw-r--r--drivers/net/wan/hdlc_raw_eth.c1
-rw-r--r--drivers/net/wan/hdlc_x25.c1
-rw-r--r--drivers/net/wan/n2.c3
-rw-r--r--drivers/net/wireless/Kconfig1
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c2
-rw-r--r--drivers/net/wireless/orinoco.c4
-rw-r--r--drivers/net/wireless/zd1201.c2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c4
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.h10
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c16
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c7
-rw-r--r--drivers/pci/hotplug/acpiphp_core.c3
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c2
-rw-r--r--drivers/pci/pcie/portdrv_pci.c38
-rw-r--r--drivers/pci/quirks.c7
-rw-r--r--drivers/pci/search.c48
-rw-r--r--drivers/pcmcia/pcmcia_ioctl.c16
-rw-r--r--drivers/pcmcia/pcmcia_resource.c15
-rw-r--r--drivers/pnp/interface.c12
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c8
-rw-r--r--drivers/pnp/pnpbios/core.c2
-rw-r--r--drivers/s390/block/xpram.c17
-rw-r--r--drivers/s390/char/raw3270.c52
-rw-r--r--drivers/s390/char/tape_class.c10
-rw-r--r--drivers/s390/char/tape_core.c18
-rw-r--r--drivers/s390/cio/ccwgroup.c10
-rw-r--r--drivers/s390/cio/cmf.c1
-rw-r--r--drivers/s390/cio/device_fsm.c3
-rw-r--r--drivers/s390/net/ctcmain.c21
-rw-r--r--drivers/s390/net/qeth_main.c7
-rw-r--r--drivers/sbus/sbus.c2
-rw-r--r--drivers/scsi/53c7xx.c8
-rw-r--r--drivers/scsi/NCR53C9x.c18
-rw-r--r--drivers/scsi/NCR_D700.c14
-rw-r--r--drivers/scsi/aha152x.c43
-rw-r--r--drivers/scsi/ahci.c669
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c2
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c21
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c1
-rw-r--r--drivers/scsi/aic7xxx/aicasm/Makefile2
-rw-r--r--drivers/scsi/arm/fas216.c2
-rw-r--r--drivers/scsi/ata_piix.c23
-rw-r--r--drivers/scsi/atari_NCR5380.c2
-rw-r--r--drivers/scsi/constants.c126
-rw-r--r--drivers/scsi/esp.c16
-rw-r--r--drivers/scsi/ibmvscsi/iseries_vscsi.c2
-rw-r--r--drivers/scsi/ibmvscsi/rpa_vscsi.c1
-rw-r--r--drivers/scsi/jazz_esp.c2
-rw-r--r--drivers/scsi/libata-bmdma.c160
-rw-r--r--drivers/scsi/libata-core.c333
-rw-r--r--drivers/scsi/libata-eh.c69
-rw-r--r--drivers/scsi/libata-scsi.c170
-rw-r--r--drivers/scsi/libata.h5
-rw-r--r--drivers/scsi/lpfc/lpfc.h9
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c89
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c65
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c59
-rw-r--r--drivers/scsi/lpfc/lpfc_mem.c5
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c11
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c64
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c55
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/mac53c94.c2
-rw-r--r--drivers/scsi/mesh.c2
-rw-r--r--drivers/scsi/pluto.c2
-rw-r--r--drivers/scsi/qlogicpti.c4
-rw-r--r--drivers/scsi/sata_promise.c7
-rw-r--r--drivers/scsi/sata_sil24.c1
-rw-r--r--drivers/scsi/scsi.c11
-rw-r--r--drivers/scsi/scsi_debug.c72
-rw-r--r--drivers/scsi/scsi_error.c210
-rw-r--r--drivers/scsi/scsi_ioctl.c5
-rw-r--r--drivers/scsi/scsi_lib.c88
-rw-r--r--drivers/scsi/scsi_priv.h1
-rw-r--r--drivers/scsi/scsi_transport_sas.c64
-rw-r--r--drivers/scsi/sd.c3
-rw-r--r--drivers/scsi/seagate.c2
-rw-r--r--drivers/scsi/sr.c5
-rw-r--r--drivers/scsi/st.c7
-rw-r--r--drivers/scsi/sun3_NCR5380.c2
-rw-r--r--drivers/scsi/sun3x_esp.c2
-rw-r--r--drivers/scsi/wd33c93.c2
-rw-r--r--drivers/serial/sunsab.c7
-rw-r--r--drivers/serial/sunzilog.c125
-rw-r--r--drivers/usb/Kconfig2
-rw-r--r--drivers/usb/core/devio.c20
-rw-r--r--drivers/usb/core/file.c13
-rw-r--r--drivers/usb/gadget/Kconfig2
-rw-r--r--drivers/usb/gadget/at91_udc.c176
-rw-r--r--drivers/usb/gadget/at91_udc.h1
-rw-r--r--drivers/usb/gadget/dummy_hcd.c6
-rw-r--r--drivers/usb/host/ehci-hcd.c2
-rw-r--r--drivers/usb/host/ohci-at91.c88
-rw-r--r--drivers/usb/host/ohci-hcd.c3
-rw-r--r--drivers/usb/host/uhci-q.c4
-rw-r--r--drivers/usb/input/ati_remote.c174
-rw-r--r--drivers/usb/input/hid-input.c3
-rw-r--r--drivers/usb/input/hiddev.c72
-rw-r--r--drivers/usb/misc/cypress_cy7c63.c9
-rw-r--r--drivers/usb/net/rtl8150.c83
-rw-r--r--drivers/usb/serial/Kconfig24
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/anydata.c123
-rw-r--r--drivers/usb/serial/ftdi_sio.c1
-rw-r--r--drivers/usb/serial/ftdi_sio.h4
-rw-r--r--drivers/usb/serial/ipaq.c1
-rw-r--r--drivers/usb/serial/option.c76
-rw-r--r--drivers/usb/serial/pl2303.c1
-rw-r--r--drivers/usb/serial/pl2303.h4
-rw-r--r--drivers/usb/storage/unusual_devs.h29
-rw-r--r--drivers/usb/storage/usb.c13
-rw-r--r--drivers/video/Kconfig38
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/aty/aty128fb.c13
-rw-r--r--drivers/video/aty/atyfb_base.c4
-rw-r--r--drivers/video/aty/radeon_base.c18
-rw-r--r--drivers/video/aty/radeon_pm.c146
-rw-r--r--drivers/video/aty/radeonfb.h6
-rw-r--r--drivers/video/au1100fb.c18
-rw-r--r--drivers/video/backlight/Kconfig4
-rw-r--r--drivers/video/console/mdacon.c4
-rw-r--r--drivers/video/fb_notify.c46
-rw-r--r--drivers/video/fbmem.c54
-rw-r--r--drivers/video/nvidia/nvidia.c9
-rw-r--r--drivers/video/offb.c307
-rw-r--r--drivers/video/riva/fbdev.c7
-rw-r--r--fs/9p/conv.c6
-rw-r--r--fs/9p/vfs_inode.c6
-rw-r--r--fs/befs/linuxvfs.c11
-rw-r--r--fs/buffer.c7
-rw-r--r--fs/coda/file.c4
-rw-r--r--fs/efs/symlink.c3
-rw-r--r--fs/ext3/inode.c19
-rw-r--r--fs/ext3/namei.c15
-rw-r--r--fs/freevxfs/vxfs_lookup.c2
-rw-r--r--fs/fuse/control.c4
-rw-r--r--fs/fuse/dir.c47
-rw-r--r--fs/fuse/fuse_i.h2
-rw-r--r--fs/fuse/inode.c2
-rw-r--r--fs/inotify_user.c2
-rw-r--r--fs/lockd/svclock.c12
-rw-r--r--fs/namei.c8
-rw-r--r--fs/nfs/namespace.c4
-rw-r--r--fs/nfs/read.c2
-rw-r--r--fs/nfs/write.c2
-rw-r--r--fs/nfsd/nfsfh.c20
-rw-r--r--fs/partitions/Kconfig2
-rw-r--r--fs/reiserfs/file.c2
-rw-r--r--fs/reiserfs/inode.c26
-rw-r--r--fs/reiserfs/ioctl.c2
-rw-r--r--fs/udf/ialloc.c11
-rw-r--r--fs/ufs/balloc.c2
-rw-r--r--fs/ufs/namei.c3
-rw-r--r--fs/ufs/util.c17
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.h4
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c7
-rw-r--r--fs/xfs/quota/xfs_qm_bhv.c19
-rw-r--r--fs/xfs/xfs_inode.c17
-rw-r--r--fs/xfs/xfs_log.c12
-rw-r--r--fs/xfs/xfs_vfsops.c2
-rw-r--r--include/asm-alpha/libata-portmap.h1
-rw-r--r--include/asm-arm/arch-iop3xx/iop331-irqs.h4
-rw-r--r--include/asm-arm/arch-omap/clock.h2
-rw-r--r--include/asm-generic/libata-portmap.h12
-rw-r--r--include/asm-i386/kprobes.h1
-rw-r--r--include/asm-i386/libata-portmap.h1
-rw-r--r--include/asm-ia64/kprobes.h1
-rw-r--r--include/asm-ia64/libata-portmap.h1
-rw-r--r--include/asm-ia64/meminit.h7
-rw-r--r--include/asm-ia64/pal.h7
-rw-r--r--include/asm-ia64/sn/xpc.h4
-rw-r--r--include/asm-ia64/system.h2
-rw-r--r--include/asm-m68k/oplib.h5
-rw-r--r--include/asm-powerpc/backlight.h4
-rw-r--r--include/asm-powerpc/kprobes.h1
-rw-r--r--include/asm-powerpc/libata-portmap.h1
-rw-r--r--include/asm-s390/system.h9
-rw-r--r--include/asm-s390/timex.h4
-rw-r--r--include/asm-sparc/libata-portmap.h1
-rw-r--r--include/asm-sparc/oplib.h5
-rw-r--r--include/asm-sparc/signal.h2
-rw-r--r--include/asm-sparc64/kprobes.h1
-rw-r--r--include/asm-sparc64/libata-portmap.h1
-rw-r--r--include/asm-sparc64/openprom.h2
-rw-r--r--include/asm-sparc64/oplib.h5
-rw-r--r--include/asm-sparc64/pgtable.h2
-rw-r--r--include/asm-sparc64/sfp-machine.h2
-rw-r--r--include/asm-x86_64/calgary.h5
-rw-r--r--include/asm-x86_64/kprobes.h1
-rw-r--r--include/asm-x86_64/libata-portmap.h1
-rw-r--r--include/asm-x86_64/page.h2
-rw-r--r--include/asm-x86_64/swiotlb.h2
-rw-r--r--include/linux/audit.h43
-rw-r--r--include/linux/cn_proc.h3
-rw-r--r--include/linux/cpu.h6
-rw-r--r--include/linux/cpufreq.h3
-rw-r--r--include/linux/debug_locks.h2
-rw-r--r--include/linux/delayacct.h6
-rw-r--r--include/linux/ext3_fs.h9
-rw-r--r--include/linux/fb.h2
-rw-r--r--include/linux/fsnotify.h6
-rw-r--r--include/linux/futex.h3
-rw-r--r--include/linux/ide.h1
-rw-r--r--include/linux/input.h24
-rw-r--r--include/linux/irq.h5
-rw-r--r--include/linux/jiffies.h4
-rw-r--r--include/linux/kobject.h2
-rw-r--r--include/linux/libata.h37
-rw-r--r--include/linux/lockd/lockd.h1
-rw-r--r--include/linux/netdevice.h6
-rw-r--r--include/linux/netfilter_bridge.h3
-rw-r--r--include/linux/nfs_fs.h6
-rw-r--r--include/linux/pci_ids.h1
-rw-r--r--include/linux/pmu.h3
-rw-r--r--include/linux/sched.h8
-rw-r--r--include/linux/security.h40
-rw-r--r--include/linux/skbuff.h41
-rw-r--r--include/linux/sunrpc/xprt.h2
-rw-r--r--include/linux/usb.h7
-rw-r--r--include/linux/usb_usual.h4
-rw-r--r--include/linux/videodev.h7
-rw-r--r--include/linux/videodev2.h2
-rw-r--r--include/linux/vmstat.h8
-rw-r--r--include/media/v4l2-dev.h7
-rw-r--r--include/net/af_unix.h6
-rw-r--r--include/net/ip6_route.h12
-rw-r--r--include/net/ipv6.h3
-rw-r--r--include/net/netdma.h4
-rw-r--r--include/net/netevent.h33
-rw-r--r--include/net/pkt_sched.h18
-rw-r--r--include/net/red.h2
-rw-r--r--include/net/scm.h29
-rw-r--r--include/net/sctp/structs.h11
-rw-r--r--include/net/sctp/user.h9
-rw-r--r--include/net/tcp.h3
-rw-r--r--include/rdma/ib_mad.h7
-rw-r--r--include/scsi/scsi_cmnd.h9
-rw-r--r--include/scsi/scsi_transport_sas.h7
-rw-r--r--ipc/msg.c389
-rw-r--r--kernel/audit.c4
-rw-r--r--kernel/auditfilter.c26
-rw-r--r--kernel/auditsc.c117
-rw-r--r--kernel/cpu.c75
-rw-r--r--kernel/cpuset.c24
-rw-r--r--kernel/delayacct.c8
-rw-r--r--kernel/fork.c4
-rw-r--r--kernel/futex.c122
-rw-r--r--kernel/futex_compat.c34
-rw-r--r--kernel/hrtimer.c4
-rw-r--r--kernel/irq/manage.c28
-rw-r--r--kernel/kprobes.c1
-rw-r--r--kernel/power/process.c26
-rw-r--r--kernel/printk.c4
-rw-r--r--kernel/rcupdate.c4
-rw-r--r--kernel/resource.c9
-rw-r--r--kernel/rtmutex.c2
-rw-r--r--kernel/sched.c22
-rw-r--r--kernel/signal.c25
-rw-r--r--kernel/softirq.c22
-rw-r--r--kernel/softlockup.c4
-rw-r--r--kernel/taskstats.c32
-rw-r--r--kernel/timer.c8
-rw-r--r--kernel/workqueue.c58
-rw-r--r--lib/kobject_uevent.c4
-rw-r--r--lib/spinlock_debug.c10
-rw-r--r--lib/zlib_inflate/inflate.c5
-rw-r--r--mm/fadvise.c3
-rw-r--r--mm/filemap.c2
-rw-r--r--mm/memory_hotplug.c44
-rw-r--r--mm/slab.c4
-rw-r--r--net/8021q/vlan.c11
-rw-r--r--net/appletalk/ddp.c6
-rw-r--r--net/atm/br2684.c3
-rw-r--r--net/atm/clip.c3
-rw-r--r--net/atm/lec.c3
-rw-r--r--net/atm/mpc.c3
-rw-r--r--net/atm/pppoatm.c3
-rw-r--r--net/atm/resources.c3
-rw-r--r--net/ax25/sysctl_net_ax25.c4
-rw-r--r--net/bluetooth/rfcomm/core.c19
-rw-r--r--net/bridge/br_ioctl.c7
-rw-r--r--net/bridge/br_netfilter.c5
-rw-r--r--net/bridge/br_netlink.c2
-rw-r--r--net/core/Makefile2
-rw-r--r--net/core/dev.c19
-rw-r--r--net/core/ethtool.c2
-rw-r--r--net/core/neighbour.c14
-rw-r--r--net/core/netevent.c69
-rw-r--r--net/core/skbuff.c45
-rw-r--r--net/core/user_dma.c1
-rw-r--r--net/dccp/feat.h2
-rw-r--r--net/dccp/ipv4.c3
-rw-r--r--net/dccp/ipv6.c8
-rw-r--r--net/dccp/options.c2
-rw-r--r--net/decnet/dn_dev.c9
-rw-r--r--net/decnet/dn_fib.c3
-rw-r--r--net/decnet/dn_neigh.c3
-rw-r--r--net/decnet/dn_route.c9
-rw-r--r--net/decnet/dn_rules.c3
-rw-r--r--net/decnet/dn_table.c11
-rw-r--r--net/econet/af_econet.c3
-rw-r--r--net/ieee80211/Kconfig1
-rw-r--r--net/ieee80211/ieee80211_crypt.c3
-rw-r--r--net/ieee80211/ieee80211_crypt_ccmp.c3
-rw-r--r--net/ieee80211/ieee80211_crypt_wep.c3
-rw-r--r--net/ieee80211/ieee80211_wx.c7
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_auth.c28
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_io.c3
-rw-r--r--net/ipv4/ah4.c4
-rw-r--r--net/ipv4/arp.c3
-rw-r--r--net/ipv4/devinet.c6
-rw-r--r--net/ipv4/esp4.c4
-rw-r--r--net/ipv4/fib_hash.c6
-rw-r--r--net/ipv4/fib_rules.c3
-rw-r--r--net/ipv4/fib_semantics.c15
-rw-r--r--net/ipv4/igmp.c12
-rw-r--r--net/ipv4/inet_diag.c3
-rw-r--r--net/ipv4/ip_gre.c1
-rw-r--r--net/ipv4/ip_input.c2
-rw-r--r--net/ipv4/ip_options.c1
-rw-r--r--net/ipv4/ip_output.c7
-rw-r--r--net/ipv4/ip_sockglue.c9
-rw-r--r--net/ipv4/ipcomp.c3
-rw-r--r--net/ipv4/ipip.c1
-rw-r--r--net/ipv4/ipmr.c21
-rw-r--r--net/ipv4/ipvs/ip_vs_ctl.c10
-rw-r--r--net/ipv4/ipvs/ip_vs_est.c3
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_sip.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c4
-rw-r--r--net/ipv4/netfilter/ip_nat_snmp_basic.c4
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c3
-rw-r--r--net/ipv4/netfilter/ipt_hashlimit.c3
-rw-r--r--net/ipv4/raw.c1
-rw-r--r--net/ipv4/route.c8
-rw-r--r--net/ipv4/tcp.c5
-rw-r--r--net/ipv4/tcp_input.c3
-rw-r--r--net/ipv4/tcp_ipv4.c5
-rw-r--r--net/ipv4/tcp_minisocks.c4
-rw-r--r--net/ipv4/tcp_probe.c2
-rw-r--r--net/ipv4/udp.c3
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c1
-rw-r--r--net/ipv6/addrconf.c174
-rw-r--r--net/ipv6/af_inet6.c2
-rw-r--r--net/ipv6/inet6_connection_sock.c2
-rw-r--r--net/ipv6/ip6_input.c2
-rw-r--r--net/ipv6/ip6_output.c129
-rw-r--r--net/ipv6/ip6_tunnel.c3
-rw-r--r--net/ipv6/raw.c1
-rw-r--r--net/ipv6/route.c7
-rw-r--r--net/ipv6/sit.c1
-rw-r--r--net/ipv6/tcp_ipv6.c6
-rw-r--r--net/ipv6/udp.c2
-rw-r--r--net/ipv6/xfrm6_output.c2
-rw-r--r--net/ipv6/xfrm6_tunnel.c140
-rw-r--r--net/irda/af_irda.c2
-rw-r--r--net/irda/ircomm/ircomm_core.c4
-rw-r--r--net/irda/ircomm/ircomm_lmp.c4
-rw-r--r--net/irda/ircomm/ircomm_param.c2
-rw-r--r--net/irda/ircomm/ircomm_tty.c8
-rw-r--r--net/irda/irda_device.c4
-rw-r--r--net/irda/iriap.c9
-rw-r--r--net/irda/iriap_event.c2
-rw-r--r--net/irda/irias_object.c24
-rw-r--r--net/irda/irlan/irlan_common.c16
-rw-r--r--net/irda/irlan/irlan_provider.c2
-rw-r--r--net/irda/irlap.c8
-rw-r--r--net/irda/irlap_frame.c19
-rw-r--r--net/irda/irlmp.c11
-rw-r--r--net/irda/irnet/irnet_ppp.c3
-rw-r--r--net/irda/irttp.c20
-rw-r--r--net/lapb/lapb_iface.c16
-rw-r--r--net/llc/af_llc.c20
-rw-r--r--net/llc/llc_core.c3
-rw-r--r--net/llc/llc_sap.c4
-rw-r--r--net/netfilter/Kconfig4
-rw-r--r--net/netfilter/nf_conntrack_standalone.c4
-rw-r--r--net/netfilter/nf_queue.c9
-rw-r--r--net/netfilter/xt_SECMARK.c2
-rw-r--r--net/netfilter/xt_physdev.c15
-rw-r--r--net/netfilter/xt_pkttype.c12
-rw-r--r--net/netfilter/xt_string.c5
-rw-r--r--net/netlink/af_netlink.c13
-rw-r--r--net/rxrpc/connection.c6
-rw-r--r--net/rxrpc/peer.c3
-rw-r--r--net/rxrpc/transport.c6
-rw-r--r--net/sched/act_api.c9
-rw-r--r--net/sched/act_pedit.c3
-rw-r--r--net/sched/act_police.c6
-rw-r--r--net/sched/cls_basic.c6
-rw-r--r--net/sched/cls_fw.c6
-rw-r--r--net/sched/cls_route.c9
-rw-r--r--net/sched/cls_rsvp.h9
-rw-r--r--net/sched/cls_tcindex.c12
-rw-r--r--net/sched/cls_u32.c15
-rw-r--r--net/sched/em_meta.c3
-rw-r--r--net/sched/ematch.c3
-rw-r--r--net/sched/estimator.c3
-rw-r--r--net/sched/sch_api.c2
-rw-r--r--net/sched/sch_cbq.c3
-rw-r--r--net/sched/sch_generic.c3
-rw-r--r--net/sched/sch_gred.c3
-rw-r--r--net/sched/sch_hfsc.c3
-rw-r--r--net/sched/sch_htb.c3
-rw-r--r--net/sched/sch_netem.c4
-rw-r--r--net/sctp/associola.c27
-rw-r--r--net/sctp/bind_addr.c8
-rw-r--r--net/sctp/endpointola.c11
-rw-r--r--net/sctp/ipv6.c3
-rw-r--r--net/sctp/outqueue.c9
-rw-r--r--net/sctp/protocol.c7
-rw-r--r--net/sctp/sm_make_chunk.c14
-rw-r--r--net/sctp/sm_sideeffect.c12
-rw-r--r--net/sctp/sm_statefuns.c8
-rw-r--r--net/sctp/socket.c74
-rw-r--r--net/sctp/transport.c9
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c9
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_mech.c3
-rw-r--r--net/sunrpc/auth_gss/gss_mech_switch.c3
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_mech.c3
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_token.c3
-rw-r--r--net/sunrpc/cache.c6
-rw-r--r--net/sunrpc/clnt.c55
-rw-r--r--net/sunrpc/rpc_pipe.c6
-rw-r--r--net/sunrpc/stats.c7
-rw-r--r--net/sunrpc/svc.c6
-rw-r--r--net/sunrpc/svcsock.c3
-rw-r--r--net/sunrpc/xprt.c24
-rw-r--r--net/sunrpc/xprtsock.c35
-rw-r--r--net/tipc/bearer.c6
-rw-r--r--net/tipc/cluster.c8
-rw-r--r--net/tipc/discover.c2
-rw-r--r--net/tipc/link.c3
-rw-r--r--net/tipc/name_table.c16
-rw-r--r--net/tipc/net.c5
-rw-r--r--net/tipc/port.c5
-rw-r--r--net/tipc/ref.c2
-rw-r--r--net/tipc/subscr.c3
-rw-r--r--net/tipc/user_reg.c3
-rw-r--r--net/tipc/zone.c3
-rw-r--r--net/unix/af_unix.c20
-rw-r--r--net/wanrouter/af_wanpipe.c9
-rw-r--r--net/wanrouter/wanmain.c9
-rw-r--r--net/xfrm/xfrm_policy.c3
-rw-r--r--net/xfrm/xfrm_state.c3
-rw-r--r--scripts/Kbuild.include10
-rw-r--r--scripts/Makefile.modpost2
-rw-r--r--scripts/kconfig/confdata.c2
-rwxr-xr-xscripts/kernel-doc1
-rw-r--r--scripts/mod/file2alias.c62
-rw-r--r--security/dummy.c14
-rw-r--r--security/selinux/hooks.c38
-rw-r--r--security/selinux/ss/policydb.c12
-rw-r--r--security/selinux/ss/services.c4
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-toonie.c17
-rw-r--r--sound/aoa/core/snd-aoa-gpio-feature.c7
-rw-r--r--sound/aoa/core/snd-aoa-gpio-pmf.c2
-rw-r--r--sound/core/oss/mixer_oss.c3
-rw-r--r--sound/core/oss/pcm_oss.c2
-rw-r--r--sound/core/seq/seq_device.c3
-rw-r--r--sound/core/sgbuf.c9
-rw-r--r--sound/drivers/vx/vx_pcm.c7
-rw-r--r--sound/pci/echoaudio/echoaudio.c4
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c11
-rw-r--r--sound/pci/emu10k1/irq.c6
-rw-r--r--sound/ppc/awacs.c3
-rw-r--r--sound/ppc/daca.c3
-rw-r--r--sound/ppc/keywest.c3
-rw-r--r--sound/ppc/powermac.c13
-rw-r--r--sound/ppc/tumbler.c3
-rw-r--r--sound/usb/usbaudio.c6
782 files changed, 9114 insertions, 6138 deletions
diff --git a/.gitignore b/.gitignore
index 27fd3762125..b1f5b9df2ae 100644
--- a/.gitignore
+++ b/.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/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 1ae4dc0fd85..f8fe882e33d 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -59,6 +59,9 @@
!Iinclude/linux/hrtimer.h
!Ekernel/hrtimer.c
</sect1>
+ <sect1><title>Workqueues and Kevents</title>
+!Ekernel/workqueue.c
+ </sect1>
<sect1><title>Internal Functions</title>
!Ikernel/exit.c
!Ikernel/signal.c
@@ -300,7 +303,7 @@ X!Ekernel/module.c
</sect1>
<sect1><title>Resources Management</title>
-!Ekernel/resource.c
+!Ikernel/resource.c
</sect1>
<sect1><title>MTRR Handling</title>
@@ -312,9 +315,7 @@ X!Ekernel/module.c
!Edrivers/pci/pci-driver.c
!Edrivers/pci/remove.c
!Edrivers/pci/pci-acpi.c
-<!-- kerneldoc does not understand __devinit
-X!Edrivers/pci/search.c
- -->
+!Edrivers/pci/search.c
!Edrivers/pci/msi.c
!Edrivers/pci/bus.c
<!-- FIXME: Removed for now since no structured comments in source
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index c2c85bcb3d4..2cd7f02ffd0 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -10,7 +10,9 @@ kernel, the process can sometimes be daunting if you're not familiar
with "the system." This text is a collection of suggestions which
can greatly increase the chances of your change being accepted.
-If you are submitting a driver, also read Documentation/SubmittingDrivers.
+Read Documentation/SubmitChecklist for a list of items to check
+before submitting code. If you are submitting a driver, also read
+Documentation/SubmittingDrivers.
@@ -74,9 +76,6 @@ There are a number of scripts which can aid in this:
Quilt:
http://savannah.nongnu.org/projects/quilt
-Randy Dunlap's patch scripts:
-http://www.xenotime.net/linux/scripts/patching-scripts-002.tar.gz
-
Andrew Morton's patch scripts:
http://www.zip.com.au/~akpm/linux/patches/
Instead of these scripts, quilt is the recommended patch management
@@ -484,7 +483,7 @@ Greg Kroah-Hartman "How to piss off a kernel subsystem maintainer".
<http://www.kroah.com/log/2005/10/19/>
<http://www.kroah.com/log/2006/01/11/>
-NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!.
+NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
<http://marc.theaimsgroup.com/?l=linux-kernel&m=112112749912944&w=2>
Kernel Documentation/CodingStyle
@@ -493,4 +492,3 @@ Kernel Documentation/CodingStyle
Linus Torvald's mail on the canonical patch format:
<http://lkml.org/lkml/2005/4/7/183>
--
-Last updated on 17 Nov 2005.
diff --git a/Documentation/accounting/delay-accounting.txt b/Documentation/accounting/delay-accounting.txt
index be215e58423..1443cd71d26 100644
--- a/Documentation/accounting/delay-accounting.txt
+++ b/Documentation/accounting/delay-accounting.txt
@@ -64,11 +64,13 @@ Compile the kernel with
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASKSTATS=y
-Enable the accounting at boot time by adding
-the following to the kernel boot options
- delayacct
+Delay accounting is enabled by default at boot up.
+To disable, add
+ nodelayacct
+to the kernel boot options. The rest of the instructions
+below assume this has not been done.
-and after the system has booted up, use a utility
+After the system has booted up, use a utility
similar to getdelays.c to access the delays
seen by a given task or a task group (tgid).
The utility also allows a given command to be
diff --git a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt
index 7fedc00c3d3..555c8cf3650 100644
--- a/Documentation/cpu-freq/user-guide.txt
+++ b/Documentation/cpu-freq/user-guide.txt
@@ -153,10 +153,13 @@ scaling_governor, and by "echoing" the name of another
that some governors won't load - they only
work on some specific architectures or
processors.
-scaling_min_freq and
+scaling_min_freq and
scaling_max_freq show the current "policy limits" (in
kHz). By echoing new values into these
files, you can change these limits.
+ NOTE: when setting a policy you need to
+ first set scaling_max_freq, then
+ scaling_min_freq.
If you have selected the "userspace" governor which allows you to
diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt
index 1bcf69996c9..bc107cb157a 100644
--- a/Documentation/cpu-hotplug.txt
+++ b/Documentation/cpu-hotplug.txt
@@ -251,16 +251,24 @@ A: This is what you would need in your kernel code to receive notifications.
return NOTIFY_OK;
}
- static struct notifier_block foobar_cpu_notifer =
+ static struct notifier_block __cpuinitdata foobar_cpu_notifer =
{
.notifier_call = foobar_cpu_callback,
};
+You need to call register_cpu_notifier() from your init function.
+Init functions could be of two types:
+1. early init (init function called when only the boot processor is online).
+2. late init (init function called _after_ all the CPUs are online).
-In your init function,
+For the first case, you should add the following to your init function
register_cpu_notifier(&foobar_cpu_notifier);
+For the second case, you should add the following to your init function
+
+ register_hotcpu_notifier(&foobar_cpu_notifier);
+
You can fail PREPARE notifiers if something doesn't work to prepare resources.
This will stop the activity and send a following CANCELED event back.
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 4aaf68fafeb..66c725f530f 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -2565,10 +2565,10 @@ Your cooperation is appreciated.
243 = /dev/usb/dabusb3 Fourth dabusb device
180 block USB block devices
- 0 = /dev/uba First USB block device
- 8 = /dev/ubb Second USB block device
- 16 = /dev/ubc Thrid USB block device
- ...
+ 0 = /dev/uba First USB block device
+ 8 = /dev/ubb Second USB block device
+ 16 = /dev/ubc Third USB block device
+ ...
181 char Conrad Electronic parallel port radio clocks
0 = /dev/pcfclock0 First Conrad radio clock
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 9d3a0775a11..87851efb022 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -258,3 +258,19 @@ Why: These drivers never compiled since they were added to the kernel
Who: Jean Delvare <khali@linux-fr.org>
---------------------------
+
+What: Bridge netfilter deferred IPv4/IPv6 output hook calling
+When: January 2007
+Why: The deferred output hooks are a layering violation causing unusual
+ and broken behaviour on bridge devices. Examples of things they
+ break include QoS classifation using the MARK or CLASSIFY targets,
+ the IPsec policy match and connection tracking with VLANs on a
+ bridge. Their only use is to enable bridge output port filtering
+ within iptables with the physdev match, which can also be done by
+ combining iptables and ebtables using netfilter marks. Until it
+ will get removed the hook deferral is disabled by default and is
+ only enabled when needed.
+
+Who: Patrick McHardy <kaber@trash.net>
+
+---------------------------
diff --git a/Documentation/infiniband/ipoib.txt b/Documentation/infiniband/ipoib.txt
index 187035560d7..864ff328378 100644
--- a/Documentation/infiniband/ipoib.txt
+++ b/Documentation/infiniband/ipoib.txt
@@ -51,8 +51,6 @@ Debugging Information
References
- IETF IP over InfiniBand (ipoib) Working Group
- http://ietf.org/html.charters/ipoib-charter.html
Transmission of IP over InfiniBand (IPoIB) (RFC 4391)
http://ietf.org/rfc/rfc4391.txt
IP over InfiniBand (IPoIB) Architecture (RFC 4392)
diff --git a/Documentation/initrd.txt b/Documentation/initrd.txt
index b1b6440237a..15f1b35deb3 100644
--- a/Documentation/initrd.txt
+++ b/Documentation/initrd.txt
@@ -72,6 +72,22 @@ initrd adds the following new options:
initrd is mounted as root, and the normal boot procedure is followed,
with the RAM disk still mounted as root.
+Compressed cpio images
+----------------------
+
+Recent kernels have support for populating a ramdisk from a compressed cpio
+archive, on such systems, the creation of a ramdisk image doesn't need to
+involve special block devices or loopbacks, you merely create a directory on
+disk with the desired initrd content, cd to that directory, and run (as an
+example):
+
+find . | cpio --quiet -c -o | gzip -9 -n > /boot/imagefile.img
+
+Examining the contents of an existing image file is just as simple:
+
+mkdir /tmp/imagefile
+cd /tmp/imagefile
+gzip -cd /boot/imagefile.img | cpio -imd --quiet
Installation
------------
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 14ef3868a32..0706699c9da 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -407,6 +407,20 @@ more details, with real examples.
The second argument is optional, and if supplied will be used
if first argument is not supported.
+ ld-option
+ ld-option is used to check if $(CC) when used to link object files
+ supports the given option. An optional second option may be
+ specified if first option are not supported.
+
+ Example:
+ #arch/i386/kernel/Makefile
+ vsyscall-flags += $(call ld-option, -Wl$(comma)--hash-style=sysv)
+
+ In the above example vsyscall-flags will be assigned the option
+ -Wl$(comma)--hash-style=sysv if it is supported by $(CC).
+ The second argument is optional, and if supplied will be used
+ if first argument is not supported.
+
cc-option
cc-option is used to check if $(CC) support a given option, and not
supported to use an optional second option.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index e11f7728ec6..b50595a0550 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -448,8 +448,6 @@ running once the system is up.
Format: <area>[,<node>]
See also Documentation/networking/decnet.txt.
- delayacct [KNL] Enable per-task delay accounting
-
dhash_entries= [KNL]
Set number of hash buckets for dentry cache.
@@ -1031,6 +1029,8 @@ running once the system is up.
nocache [ARM]
+ nodelayacct [KNL] Disable per-task delay accounting
+
nodisconnect [HW,SCSI,M68K] Disables SCSI disconnects.
noexec [IA-64]
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index b0c7ab93dcb..7345c338080 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -211,9 +211,8 @@ Controls the kernel's behaviour when an oops or BUG is encountered.
0: try to continue operation
-1: delay a few seconds (to give klogd time to record the oops output) and
- then panic. If the `panic' sysctl is also non-zero then the machine will
- be rebooted.
+1: panic immediatly. If the `panic' sysctl is also non-zero then the
+ machine will be rebooted.
==============================================================
diff --git a/Documentation/usb/proc_usb_info.txt b/Documentation/usb/proc_usb_info.txt
index f86550fe38e..22c5331260c 100644
--- a/Documentation/usb/proc_usb_info.txt
+++ b/Documentation/usb/proc_usb_info.txt
@@ -59,7 +59,7 @@ bind to an interface (or perhaps several) using an ioctl call. You
would issue more ioctls to the device to communicate to it using
control, bulk, or other kinds of USB transfers. The IOCTLs are
listed in the <linux/usbdevice_fs.h> file, and at this writing the
-source code (linux/drivers/usb/devio.c) is the primary reference
+source code (linux/drivers/usb/core/devio.c) is the primary reference
for how to access devices through those files.
Note that since by default these BBB/DDD files are writable only by
diff --git a/Documentation/usb/usb-help.txt b/Documentation/usb/usb-help.txt
index b7c32497369..a7408593829 100644
--- a/Documentation/usb/usb-help.txt
+++ b/Documentation/usb/usb-help.txt
@@ -5,8 +5,7 @@ For USB help other than the readme files that are located in
Documentation/usb/*, see the following:
Linux-USB project: http://www.linux-usb.org
- mirrors at http://www.suse.cz/development/linux-usb/
- and http://usb.in.tum.de/linux-usb/
+ mirrors at http://usb.in.tum.de/linux-usb/
and http://it.linux-usb.org
Linux USB Guide: http://linux-usb.sourceforge.net
Linux-USB device overview (working devices and drivers):
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
index 6887d44d266..6da24e7a56c 100644
--- a/Documentation/x86_64/boot-options.txt
+++ b/Documentation/x86_64/boot-options.txt
@@ -238,6 +238,13 @@ Debugging
pagefaulttrace Dump all page faults. Only useful for extreme debugging
and will create a lot of output.
+ call_trace=[old|both|newfallback|new]
+ old: use old inexact backtracer
+ new: use new exact dwarf2 unwinder
+ both: print entries from both
+ newfallback: use new unwinder but fall back to old if it gets
+ stuck (default)
+
Misc
noreplacement Don't replace instructions with more appropriate ones
diff --git a/MAINTAINERS b/MAINTAINERS
index e99028ca2f7..e3e1515ba5a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -214,6 +214,12 @@ W: http://acpi.sourceforge.net/
T: git kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
S: Maintained
+ACPI PCI HOTPLUG DRIVER
+P: Kristen Carlson Accardi
+M: kristen.c.accardi@intel.com
+L: pcihpd-discuss@lists.sourceforge.net
+S: Maintained
+
AD1816 SOUND DRIVER
P: Thorsten Knabe
M: Thorsten Knabe <linux@thorsten-knabe.de>
@@ -292,6 +298,13 @@ L: info-linux@geode.amd.com
W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
S: Supported
+AOA (Apple Onboard Audio) ALSA DRIVER
+P: Johannes Berg
+M: johannes@sipsolutions.net
+L: linuxppc-dev@ozlabs.org
+L: alsa-devel@alsa-project.org
+S: Maintained
+
APM DRIVER
P: Stephen Rothwell
M: sfr@canb.auug.org.au
@@ -968,6 +981,10 @@ P: Andrey V. Savochkin
M: saw@saw.sw.com.sg
S: Maintained
+EFS FILESYSTEM
+W: http://aeschi.ch.eu.org/efs/
+S: Orphan
+
EMU10K1 SOUND DRIVER
P: James Courtier-Dutton
M: James@superbug.demon.co.uk
@@ -1598,7 +1615,7 @@ W: http://jfs.sourceforge.net/
T: git kernel.org:/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git
S: Supported
-JOURNALLING LAYER FOR BLOCK DEVICS (JBD)
+JOURNALLING LAYER FOR BLOCK DEVICES (JBD)
P: Stephen Tweedie, Andrew Morton
M: sct@redhat.com, akpm@osdl.org
L: ext2-devel@lists.sourceforge.net
@@ -1642,9 +1659,8 @@ S: Maintained
KERNEL JANITORS
P: Several
-L: kernel-janitors@osdl.org
+L: kernel-janitors@lists.osdl.org
W: http://www.kerneljanitors.org/
-W: http://sf.net/projects/kernel-janitor/
S: Maintained
KERNEL NFSD
@@ -1676,10 +1692,8 @@ L: linux-kernel@vger.kernel.org
S: Maintained
LAPB module
-P: Henner Eisen
-M: eis@baty.hanse.de
L: linux-x25@vger.kernel.org
-S: Maintained
+S: Orphan
LASI 53c700 driver for PARISC
P: James E.J. Bottomley
@@ -1884,6 +1898,12 @@ S: linux-scsi@vger.kernel.org
W: http://megaraid.lsilogic.com
S: Maintained
+MEMORY MANAGEMENT
+L: linux-mm@kvack.org
+L: linux-kernel@vger.kernel.org
+W: http://www.linux-mm.org
+S: Maintained
+
MEMORY TECHNOLOGY DEVICES (MTD)
P: David Woodhouse
M: dwmw2@infradead.org
@@ -2628,6 +2648,14 @@ M: dbrownell@users.sourceforge.net
L: spi-devel-general@lists.sourceforge.net
S: Maintained
+STABLE BRANCH:
+P: Greg Kroah-Hartman
+M: greg@kroah.com
+P: Chris Wright
+M: chrisw@sous-sol.org
+L: stable@kernel.org
+S: Maintained
+
TPM DEVICE DRIVER
P: Kylene Hall
M: kjhall@us.ibm.com
diff --git a/Makefile b/Makefile
index 1dd58d35d72..c2f78a5a549 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 18
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc4
NAME=Crazed Snow-Weasel
# *DOCUMENTATION*
@@ -310,8 +310,8 @@ CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-fno-strict-aliasing -fno-common
# Force gcc to behave correct even for buggy distributions
-CFLAGS += $(call cc-option, -fno-stack-protector-all \
- -fno-stack-protector)
+CFLAGS += $(call cc-option, -fno-stack-protector)
+
AFLAGS := -D__ASSEMBLY__
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
@@ -368,6 +368,7 @@ endif
no-dot-config-targets := clean mrproper distclean \
cscope TAGS tags help %docs check% \
+ include/linux/version.h headers_% \
kernelrelease kernelversion
config-targets := 0
diff --git a/arch/alpha/kernel/err_ev7.c b/arch/alpha/kernel/err_ev7.c
index bf52ba69195..fed6b3d1b80 100644
--- a/arch/alpha/kernel/err_ev7.c
+++ b/arch/alpha/kernel/err_ev7.c
@@ -274,16 +274,14 @@ ev7_process_pal_subpacket(struct el_subpacket *header)
struct el_subpacket_handler ev7_pal_subpacket_handler =
SUBPACKET_HANDLER_INIT(EL_CLASS__PAL, ev7_process_pal_subpacket);
-void
+void
ev7_register_error_handlers(void)
{
int i;
- for(i = 0;
- i<sizeof(el_ev7_pal_annotations)/sizeof(el_ev7_pal_annotations[1]);
- i++) {
+ for (i = 0; i < ARRAY_SIZE(el_ev7_pal_annotations); i++)
cdl_register_subpacket_annotation(&el_ev7_pal_annotations[i]);
- }
+
cdl_register_subpacket_handler(&ev7_pal_subpacket_handler);
}
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index e15dcf4f3dc..73c7622b529 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -623,12 +623,12 @@ osf_sysinfo(int command, char __user *buf, long count)
long len, err = -EINVAL;
offset = command-1;
- if (offset >= sizeof(sysinfo_table)/sizeof(char *)) {
+ if (offset >= ARRAY_SIZE(sysinfo_table)) {
/* Digital UNIX has a few unpublished interfaces here */
printk("sysinfo(%d)", command);
goto out;
}
-
+
down_read(&uts_sem);
res = sysinfo_table[offset];
len = strlen(res)+1;
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index 2cb9c438011..fd4a8fa0c93 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -114,8 +114,6 @@ struct alpha_machine_vector alpha_mv;
int alpha_using_srm;
#endif
-#define N(a) (sizeof(a)/sizeof(a[0]))
-
static struct alpha_machine_vector *get_sysvec(unsigned long, unsigned long,
unsigned long);
static struct alpha_machine_vector *get_sysvec_byname(const char *);
@@ -240,7 +238,7 @@ reserve_std_resources(void)
standard_io_resources[0].start = RTC_PORT(0);
standard_io_resources[0].end = RTC_PORT(0) + 0x10;
- for (i = 0; i < N(standard_io_resources); ++i)
+ for (i = 0; i < ARRAY_SIZE(standard_io_resources); ++i)
request_resource(io, standard_io_resources+i);
}
@@ -918,13 +916,13 @@ get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu)
/* Search the system tables first... */
vec = NULL;
- if (type < N(systype_vecs)) {
+ if (type < ARRAY_SIZE(systype_vecs)) {
vec = systype_vecs[type];
} else if ((type > ST_API_BIAS) &&
- (type - ST_API_BIAS) < N(api_vecs)) {
+ (type - ST_API_BIAS) < ARRAY_SIZE(api_vecs)) {
vec = api_vecs[type - ST_API_BIAS];
} else if ((type > ST_UNOFFICIAL_BIAS) &&
- (type - ST_UNOFFICIAL_BIAS) < N(unofficial_vecs)) {
+ (type - ST_UNOFFICIAL_BIAS) < ARRAY_SIZE(unofficial_vecs)) {
vec = unofficial_vecs[type - ST_UNOFFICIAL_BIAS];
}
@@ -938,11 +936,11 @@ get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu)
switch (type) {
case ST_DEC_ALCOR:
- if (member < N(alcor_indices))
+ if (member < ARRAY_SIZE(alcor_indices))
vec = alcor_vecs[alcor_indices[member]];
break;
case ST_DEC_EB164:
- if (member < N(eb164_indices))
+ if (member < ARRAY_SIZE(eb164_indices))
vec = eb164_vecs[eb164_indices[member]];
/* PC164 may show as EB164 variation with EV56 CPU,
but, since no true EB164 had anything but EV5... */
@@ -950,24 +948,24 @@ get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu)
vec = &pc164_mv;
break;
case ST_DEC_EB64P:
- if (member < N(eb64p_indices))
+ if (member < ARRAY_SIZE(eb64p_indices))
vec = eb64p_vecs[eb64p_indices[member]];
break;
case ST_DEC_EB66:
- if (member < N(eb66_indices))
+ if (member < ARRAY_SIZE(eb66_indices))
vec = eb66_vecs[eb66_indices[member]];
break;
case ST_DEC_MARVEL:
- if (member < N(marvel_indices))
+ if (member < ARRAY_SIZE(marvel_indices))
vec = marvel_vecs[marvel_indices[member]];
break;
case ST_DEC_TITAN:
vec = titan_vecs[0]; /* default */
- if (member < N(titan_indices))
+ if (member < ARRAY_SIZE(titan_indices))
vec = titan_vecs[titan_indices[member]];
break;
case ST_DEC_TSUNAMI:
- if (member < N(tsunami_indices))
+ if (member < ARRAY_SIZE(tsunami_indices))
vec = tsunami_vecs[tsunami_indices[member]];
break;
case ST_DEC_1000:
@@ -1039,7 +1037,7 @@ get_sysvec_byname(const char *name)
size_t i;
- for (i = 0; i < N(all_vecs); ++i) {
+ for (i = 0; i < ARRAY_SIZE(all_vecs); ++i) {
struct alpha_machine_vector *mv = all_vecs[i];
if (strcasecmp(mv->vector_name, name) == 0)
return mv;
@@ -1055,13 +1053,13 @@ get_sysnames(unsigned long type, unsigned long variation, unsigned long cpu,
/* If not in the tables, make it UNKNOWN,
else set type name to family */
- if (type < N(systype_names)) {
+ if (type < ARRAY_SIZE(systype_names)) {
*type_name = systype_names[type];
} else if ((type > ST_API_BIAS) &&
- (type - ST_API_BIAS) < N(api_names)) {
+ (type - ST_API_BIAS) < ARRAY_SIZE(api_names)) {
*type_name = api_names[type - ST_API_BIAS];
} else if ((type > ST_UNOFFICIAL_BIAS) &&
- (type - ST_UNOFFICIAL_BIAS) < N(unofficial_names)) {
+ (type - ST_UNOFFICIAL_BIAS) < ARRAY_SIZE(unofficial_names)) {
*type_name = unofficial_names[type - ST_UNOFFICIAL_BIAS];
} else {
*type_name = sys_unknown;
@@ -1083,7 +1081,7 @@ get_sysnames(unsigned long type, unsigned long variation, unsigned long cpu,
default: /* default to variation "0" for now */
break;
case ST_DEC_EB164:
- if (member < N(eb164_indices))
+ if (member < ARRAY_SIZE(eb164_indices))
*variation_name = eb164_names[eb164_indices[member]];
/* PC164 may show as EB164 variation, but with EV56 CPU,
so, since no true EB164 had anything but EV5... */
@@ -1091,32 +1089,32 @@ get_sysnames(unsigned long type, unsigned long variation, unsigned long cpu,
*variation_name = eb164_names[1]; /* make it PC164 */
break;
case ST_DEC_ALCOR:
- if (member < N(alcor_indices))
+ if (member < ARRAY_SIZE(alcor_indices))
*variation_name = alcor_names[alcor_indices[member]];
break;
case ST_DEC_EB64P:
- if (member < N(eb64p_indices))
+ if (member < ARRAY_SIZE(eb64p_indices))
*variation_name = eb64p_names[eb64p_indices[member]];
break;
case ST_DEC_EB66:
- if (member < N(eb66_indices))
+ if (member < ARRAY_SIZE(eb66_indices))
*variation_name = eb66_names[eb66_indices[member]];
break;
case ST_DEC_MARVEL:
- if (member < N(marvel_indices))
+ if (member < ARRAY_SIZE(marvel_indices))
*variation_name = marvel_names[marvel_indices[member]];
break;
case ST_DEC_RAWHIDE:
- if (member < N(rawhide_indices))
+ if (member < ARRAY_SIZE(rawhide_indices))
*variation_name = rawhide_names[rawhide_indices[member]];
break;
case ST_DEC_TITAN:
*variation_name = titan_names[0]; /* default */
- if (member < N(titan_indices))
+ if (member < ARRAY_SIZE(titan_indices))
*variation_name = titan_names[titan_indices[member]];
break;
case ST_DEC_TSUNAMI:
- if (member < N(tsunami_indices))
+ if (member < ARRAY_SIZE(tsunami_indices))
*variation_name = tsunami_names[tsunami_indices[member]];
break;
}
@@ -1211,7 +1209,7 @@ show_cpuinfo(struct seq_file *f, void *slot)
cpu_index = (unsigned) (cpu->type - 1);
cpu_name = "Unknown";
- if (cpu_index < N(cpu_names))
+ if (cpu_index < ARRAY_SIZE(cpu_names))
cpu_name = cpu_names[cpu_index];
get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
index 78c30decf3f..5b99cf3cd69 100644
--- a/arch/alpha/kernel/sys_ruffian.c
+++ b/arch/alpha/kernel/sys_ruffian.c
@@ -182,16 +182,16 @@ static unsigned long __init
ruffian_get_bank_size(unsigned long offset)
{
unsigned long bank_addr, bank, ret = 0;
-
+
/* Valid offsets are: 0x800, 0x840 and 0x880
since Ruffian only uses three banks. */
bank_addr = (unsigned long)PYXIS_MCR + offset;
bank = *(vulp)bank_addr;
-
+
/* Check BANK_ENABLE */
if (bank & 0x01) {
static unsigned long size[] __initdata = {
- 0x40000000UL, /* 0x00, 1G */
+ 0x40000000UL, /* 0x00, 1G */
0x20000000UL, /* 0x02, 512M */
0x10000000UL, /* 0x04, 256M */
0x08000000UL, /* 0x06, 128M */
@@ -203,7 +203,7 @@ ruffian_get_bank_size(unsigned long offset)
};
bank = (bank & 0x1e) >> 1;
- if (bank < sizeof(size)/sizeof(*size))
+ if (bank < ARRAY_SIZE(size))
ret = size[bank];
}
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 50eccde2dcd..b191cc75973 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -233,7 +233,7 @@ validate_cc_value(unsigned long cc)
index = cpu->type & 0xffffffff;
/* If index out of bounds, no way to validate. */
- if (index >= sizeof(cpu_hz)/sizeof(cpu_hz[0]))
+ if (index >= ARRAY_SIZE(cpu_hz))
return cc;
/* If index contains no data, no way to validate. */
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index f3c1ebfdd0a..f3e020f2227 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -95,7 +95,8 @@ static void gic_set_cpu(unsigned int irq, cpumask_t mask_val)
}
#endif
-static struct irqchip gic_chip = {
+static struct irq_chip gic_chip = {
+ .name = "GIC",
.ack = gic_ack_irq,
.mask = gic_mask_irq,
.unmask = gic_unmask_irq,
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index 04de83f4f00..4e0dcaef6eb 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -204,7 +204,8 @@ static void locomo_unmask_irq(unsigned int irq)
locomo_writel(r, mapbase + LOCOMO_ICR);
}
-static struct irqchip locomo_chip = {
+static struct irq_chip locomo_chip = {
+ .name = "LOCOMO",
.ack = locomo_ack_irq,
.mask = locomo_mask_irq,
.unmask = locomo_unmask_irq,
@@ -249,7 +250,8 @@ static void locomo_key_unmask_irq(unsigned int irq)
locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
}
-static struct irqchip locomo_key_chip = {
+static struct irq_chip locomo_key_chip = {
+ .name = "LOCOMO-key",
.ack = locomo_key_ack_irq,
.mask = locomo_key_mask_irq,
.unmask = locomo_key_unmask_irq,
@@ -312,7 +314,8 @@ static void locomo_gpio_unmask_irq(unsigned int irq)
locomo_writel(r, mapbase + LOCOMO_GIE);
}
-static struct irqchip locomo_gpio_chip = {
+static struct irq_chip locomo_gpio_chip = {
+ .name = "LOCOMO-gpio",
.ack = locomo_gpio_ack_irq,
.mask = locomo_gpio_mask_irq,
.unmask = locomo_gpio_unmask_irq,
@@ -357,7 +360,8 @@ static void locomo_lt_unmask_irq(unsigned int irq)
locomo_writel(r, mapbase + LOCOMO_LTINT);
}
-static struct irqchip locomo_lt_chip = {
+static struct irq_chip locomo_lt_chip = {
+ .name = "LOCOMO-lt",
.ack = locomo_lt_ack_irq,
.mask = locomo_lt_mask_irq,
.unmask = locomo_lt_unmask_irq,
@@ -418,7 +422,8 @@ static void locomo_spi_unmask_irq(unsigned int irq)
locomo_writel(r, mapbase + LOCOMO_SPIIE);
}
-static struct irqchip locomo_spi_chip = {
+static struct irq_chip locomo_spi_chip = {
+ .name = "LOCOMO-spi",
.ack = locomo_spi_ack_irq,
.mask = locomo_spi_mask_irq,
.unmask = locomo_spi_unmask_irq,
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 1cdb26a47e1..a331c12cead 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -272,7 +272,8 @@ static int sa1111_wake_lowirq(unsigned int irq, unsigned int on)
return 0;
}
-static struct irqchip sa1111_low_chip = {
+static struct irq_chip sa1111_low_chip = {
+ .name = "SA1111-l",
.ack = sa1111_ack_irq,
.mask = sa1111_mask_lowirq,
.unmask = sa1111_unmask_lowirq,
@@ -368,7 +369,8 @@ static int sa1111_wake_highirq(unsigned int irq, unsigned int on)
return 0;
}
-static struct irqchip sa1111_high_chip = {
+static struct irq_chip sa1111_high_chip = {
+ .name = "SA1111-h",
.ack = sa1111_ack_irq,
.mask = sa1111_mask_highirq,
.unmask = sa1111_unmask_highirq,
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index a19bc4a6196..43d27813452 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -39,7 +39,8 @@ static void vic_unmask_irq(unsigned int irq)
writel(1 << irq, base + VIC_INT_ENABLE);
}
-static struct irqchip vic_chip = {
+static struct irq_chip vic_chip = {
+ .name = "VIC",
.ack = vic_mask_irq,
.mask = vic_mask_irq,
.unmask = vic_unmask_irq,
diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig
index c0de6fcd488..2948b4589a8 100644
--- a/arch/arm/configs/ep93xx_defconfig
+++ b/arch/arm/configs/ep93xx_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Sun Jul 9 15:21:30 2006
+# Linux kernel version: 2.6.18-rc1-git9
+# Sat Jul 15 15:08:10 2006
#
CONFIG_ARM=y
CONFIG_MMU=y
@@ -30,6 +30,7 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
@@ -749,7 +750,7 @@ CONFIG_VIDEO_V4L2=y
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
-# CONFIG_USB_ARCH_HAS_OHCI is not set
+CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_USB_ARCH_HAS_EHCI is not set
CONFIG_USB=y
CONFIG_USB_DEBUG=y
@@ -766,6 +767,9 @@ CONFIG_USB_DYNAMIC_MINORS=y
# USB Host Controller Drivers
#
# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_SL811_HCD is not set
#
@@ -855,6 +859,7 @@ CONFIG_USB_SERIAL_CONSOLE=y
CONFIG_USB_SERIAL_PL2303=y
# CONFIG_USB_SERIAL_HP4X is not set
# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
# CONFIG_USB_SERIAL_TI is not set
# CONFIG_USB_SERIAL_CYBERJACK is not set
# CONFIG_USB_SERIAL_XIRCOM is not set
@@ -871,7 +876,7 @@ CONFIG_USB_SERIAL_PL2303=y
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
# CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
# CONFIG_USB_PHIDGETKIT is not set
# CONFIG_USB_PHIDGETSERVO is not set
@@ -916,6 +921,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_X1205 is not set
# CONFIG_RTC_DRV_DS1307 is not set
# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
# CONFIG_RTC_DRV_DS1672 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_PCF8563 is not set
@@ -1023,7 +1029,6 @@ CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index b9a74a741d0..eca248d9eba 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -470,7 +470,8 @@ static void ecard_irq_mask(unsigned int irqnr)
}
}
-static struct irqchip ecard_chip = {
+static struct irq_chip ecard_chip = {
+ .name = "ECARD",
.ack = ecard_irq_mask,
.mask = ecard_irq_mask,
.unmask = ecard_irq_unmask,
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 2242f5f7cb7..4fe386eea4b 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -114,9 +114,9 @@ ENTRY(secondary_startup)
* Use the page tables supplied from __cpu_up.
*/
adr r4, __secondary_data
- ldmia r4, {r5, r6, r13} @ address to jump to after
+ ldmia r4, {r5, r7, r13} @ address to jump to after
sub r4, r4, r5 @ mmu has been enabled
- ldr r4, [r6, r4] @ get secondary_data.pgdir
+ ldr r4, [r7, r4] @ get secondary_data.pgdir
adr lr, __enable_mmu @ return address
add pc, r10, #12 @ initialise processor
@ (return control reg)
@@ -125,7 +125,7 @@ ENTRY(secondary_startup)
* r6 = &secondary_data
*/
ENTRY(__secondary_switched)
- ldr sp, [r6, #4] @ get secondary_data.stack
+ ldr sp, [r7, #4] @ get secondary_data.stack
mov fp, #0
b secondary_start_kernel
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 626feeec0ad..2e1bf830fe1 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -77,6 +77,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_printf(p, "%3d: ", i);
for_each_present_cpu(cpu)
seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
+ seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
seq_printf(p, " %s", action->name);
for (action = action->next; action; action = action->next)
seq_printf(p, ", %s", action->name);
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 35a052fc177..4e29dd03e58 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -232,11 +232,8 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
bust_spinlocks(0);
spin_unlock_irq(&die_lock);
- if (panic_on_oops) {
- printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
- ssleep(5);
- panic("Fatal exception");
- }
+ if (panic_on_oops)
+ panic("Fatal exception: panic_on_oops");
do_exit(SIGSEGV);
}
diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c
index 5783c282ae7..cec199fd672 100644
--- a/arch/arm/mach-at91rm9200/gpio.c
+++ b/arch/arm/mach-at91rm9200/gpio.c
@@ -327,7 +327,8 @@ static int gpio_irq_type(unsigned pin, unsigned type)
return (type == IRQT_BOTHEDGE) ? 0 : -EINVAL;
}
-static struct irqchip gpio_irqchip = {
+static struct irq_chip gpio_irqchip = {
+ .name = "GPIO",
.mask = gpio_irq_mask,
.unmask = gpio_irq_unmask,
.set_type = gpio_irq_type,
diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91rm9200/irq.c
index 9b091132041..c3a5e777f9f 100644
--- a/arch/arm/mach-at91rm9200/irq.c
+++ b/arch/arm/mach-at91rm9200/irq.c
@@ -114,7 +114,8 @@ void at91_irq_resume(void)
#define at91_aic_set_wake NULL
#endif
-static struct irqchip at91_aic_chip = {
+static struct irq_chip at91_aic_chip = {
+ .name = "AIC",
.ack = at91_aic_mask_irq,
.mask = at91_aic_mask_irq,
.unmask = at91_aic_unmask_irq,
diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c
index 5b64d5c5b96..ef6ccc8993e 100644
--- a/arch/arm/mach-footbridge/cats-hw.c
+++ b/arch/arm/mach-footbridge/cats-hw.c
@@ -8,7 +8,7 @@
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/tty.h>
+#include <linux/screen_info.h>
#include <asm/hardware/dec21285.h>
#include <asm/io.h>
diff --git a/arch/arm/mach-imx/irq.c b/arch/arm/mach-imx/irq.c
index a5de5f1da9f..2688bd82c2a 100644
--- a/arch/arm/mach-imx/irq.c
+++ b/arch/arm/mach-imx/irq.c
@@ -204,13 +204,15 @@ imx_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
imx_gpio_handler(mask, irq, desc, regs);
}
-static struct irqchip imx_internal_chip = {
+static struct irq_chip imx_internal_chip = {
+ .name = "MPU",
.ack = imx_mask_irq,
.mask = imx_mask_irq,
.unmask = imx_unmask_irq,
};
-static struct irqchip imx_gpio_chip = {
+static struct irq_chip imx_gpio_chip = {
+ .name = "GPIO",
.ack = imx_gpio_ack_irq,
.mask = imx_gpio_mask_irq,
.unmask = imx_gpio_unmask_irq,
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 6d65c96ebfd..191c57a3b99 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -161,7 +161,8 @@ static void sc_unmask_irq(unsigned int irq)
writel(1 << irq, VA_IC_BASE + IRQ_ENABLE_SET);
}
-static struct irqchip sc_chip = {
+static struct irq_chip sc_chip = {
+ .name = "SC",
.ack = sc_mask_irq,
.mask = sc_mask_irq,
.unmask = sc_unmask_irq,
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 9f55f5ae104..678b6ba2b46 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -156,7 +156,8 @@ static void cic_unmask_irq(unsigned int irq)
cic_writel(1 << irq, INTCP_VA_CIC_BASE + IRQ_ENABLE_SET);
}
-static struct irqchip cic_chip = {
+static struct irq_chip cic_chip = {
+ .name = "CIC",
.ack = cic_mask_irq,
.mask = cic_mask_irq,
.unmask = cic_unmask_irq,
@@ -174,7 +175,8 @@ static void pic_unmask_irq(unsigned int irq)
pic_writel(1 << irq, INTCP_VA_PIC_BASE + IRQ_ENABLE_SET);
}
-static struct irqchip pic_chip = {
+static struct irq_chip pic_chip = {
+ .name = "PIC",
.ack = pic_mask_irq,
.mask = pic_mask_irq,
.unmask = pic_unmask_irq,
@@ -192,7 +194,8 @@ static void sic_unmask_irq(unsigned int irq)
sic_writel(1 << irq, INTCP_VA_SIC_BASE + IRQ_ENABLE_SET);
}
-static struct irqchip sic_chip = {
+static struct irq_chip sic_chip = {
+ .name = "SIC",
.ack = sic_mask_irq,
.mask = sic_mask_irq,
.unmask = sic_unmask_irq,
diff --git a/arch/arm/mach-iop3xx/iop321-irq.c b/arch/arm/mach-iop3xx/iop321-irq.c
index d42aae6aef0..88ac333472c 100644
--- a/arch/arm/mach-iop3xx/iop321-irq.c
+++ b/arch/arm/mach-iop3xx/iop321-irq.c
@@ -52,7 +52,8 @@ iop321_irq_unmask (unsigned int irq)
intctl_write(iop321_mask);
}
-struct irqchip ext_chip = {
+struct irq_chip ext_chip = {
+ .name = "IOP",
.ack = iop321_irq_mask,
.mask = iop321_irq_mask,
.unmask = iop321_irq_unmask,
diff --git a/arch/arm/mach-iop3xx/iop331-irq.c b/arch/arm/mach-iop3xx/iop331-irq.c
index f4d4321737a..cab11722ced 100644
--- a/arch/arm/mach-iop3xx/iop331-irq.c
+++ b/arch/arm/mach-iop3xx/iop331-irq.c
@@ -77,13 +77,15 @@ iop331_irq_unmask2(unsigned int irq)
intctl_write1(iop331_mask1);
}
-struct irqchip iop331_irqchip1 = {
+struct irq_chip iop331_irqchip1 = {
+ .name = "IOP-1",
.ack = iop331_irq_mask1,
.mask = iop331_irq_mask1,
.unmask = iop331_irq_unmask1,
};
-struct irqchip iop331_irqchip2 = {
+struct irq_chip iop331_irqchip2 = {
+ .name = "IOP-2",
.ack = iop331_irq_mask2,
.mask = iop331_irq_mask2,
.unmask = iop331_irq_unmask2,
diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c
index 2cccc27c62e..4f2ab48800a 100644
--- a/arch/arm/mach-lh7a40x/arch-kev7a400.c
+++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c
@@ -63,7 +63,8 @@ static void kev7a400_unmask_cpld_irq (u32 irq)
CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
}
-static struct irqchip kev7a400_cpld_chip = {
+static struct irq_chip kev7a400_cpld_chip = {
+ .name = "CPLD",
.ack = kev7a400_ack_cpld_irq,
.mask = kev7a400_mask_cpld_irq,
.unmask = kev7a400_unmask_cpld_irq,
diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
index 35c3606a207..a6910114b24 100644
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
@@ -200,7 +200,8 @@ static void lh7a40x_unmask_cpld_irq (u32 irq)
}
}
-static struct irqchip lpd7a40x_cpld_chip = {
+static struct irq_chip lpd7a40x_cpld_chip = {
+ .name = "CPLD",
.ack = lh7a40x_ack_cpld_irq,
.mask = lh7a40x_mask_cpld_irq,
.unmask = lh7a40x_unmask_cpld_irq,
diff --git a/arch/arm/mach-lh7a40x/irq-kev7a400.c b/arch/arm/mach-lh7a40x/irq-kev7a400.c
index 8535764d89c..f9b3fe9174a 100644
--- a/arch/arm/mach-lh7a40x/irq-kev7a400.c
+++ b/arch/arm/mach-lh7a40x/irq-kev7a400.c
@@ -43,7 +43,8 @@ lh7a400_unmask_cpld_irq (u32 irq)
}
static struct
-irqchip lh7a400_cpld_chip = {
+irq_chip lh7a400_cpld_chip = {
+ .name = "CPLD",
.ack = lh7a400_ack_cpld_irq,
.mask = lh7a400_mask_cpld_irq,
.unmask = lh7a400_unmask_cpld_irq,
diff --git a/arch/arm/mach-lh7a40x/irq-lh7a400.c b/arch/arm/mach-lh7a40x/irq-lh7a400.c
index f9fdefef6d6..091b2dc58d2 100644
--- a/arch/arm/mach-lh7a40x/irq-lh7a400.c
+++ b/arch/arm/mach-lh7a40x/irq-lh7a400.c
@@ -38,13 +38,15 @@ static void lh7a400_ack_gpio_irq (u32 irq)
INTC_INTENC = (1 << irq);
}
-static struct irqchip lh7a400_internal_chip = {
+static struct irq_chip lh7a400_internal_chip = {
+ .name = "MPU",
.ack = lh7a400_mask_irq, /* Level triggering -> mask is ack */
.mask = lh7a400_mask_irq,
.unmask = lh7a400_unmask_irq,
};
-static struct irqchip lh7a400_gpio_chip = {
+static struct irq_chip lh7a400_gpio_chip = {
+ .name = "GPIO",
.ack = lh7a400_ack_gpio_irq,
.mask = lh7a400_mask_irq,
.unmask = lh7a400_unmask_irq,
diff --git a/arch/arm/mach-lh7a40x/irq-lh7a404.c b/arch/arm/mach-lh7a40x/irq-lh7a404.c
index 2685a81454d..7059b983724 100644
--- a/arch/arm/mach-lh7a40x/irq-lh7a404.c
+++ b/arch/arm/mach-lh7a40x/irq-lh7a404.c
@@ -76,25 +76,29 @@ static void lh7a404_vic2_ack_gpio_irq (u32 irq)
VIC2_INTENCLR = (1 << irq);
}
-static struct irqchip lh7a404_vic1_chip = {
+static struct irq_chip lh7a404_vic1_chip = {
+ .name = "VIC1",
.ack = lh7a404_vic1_mask_irq, /* Because level-triggered */
.mask = lh7a404_vic1_mask_irq,
.unmask = lh7a404_vic1_unmask_irq,
};
-static struct irqchip lh7a404_vic2_chip = {
+static struct irq_chip lh7a404_vic2_chip = {
+ .name = "VIC2",
.ack = lh7a404_vic2_mask_irq, /* Because level-triggered */
.mask = lh7a404_vic2_mask_irq,
.unmask = lh7a404_vic2_unmask_irq,
};
-static struct irqchip lh7a404_gpio_vic1_chip = {
+static struct irq_chip lh7a404_gpio_vic1_chip = {
+ .name = "GPIO-VIC1",
.ack = lh7a404_vic1_ack_gpio_irq,
.mask = lh7a404_vic1_mask_irq,
.unmask = lh7a404_vic1_unmask_irq,
};
-static struct irqchip lh7a404_gpio_vic2_chip = {
+static struct irq_chip lh7a404_gpio_vic2_chip = {
+ .name = "GPIO-VIC2",
.ack = lh7a404_vic2_ack_gpio_irq,
.mask = lh7a404_vic2_mask_irq,
.unmask = lh7a404_vic2_unmask_irq,
diff --git a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
index dcb4e17b941..d6055dde646 100644
--- a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
@@ -50,7 +50,8 @@ static void lh7a40x_unmask_cpld_irq (u32 irq)
}
}
-static struct irqchip lh7a40x_cpld_chip = {
+static struct irq_chip lh7a40x_cpld_chip = {
+ .name = "CPLD",
.ack = lh7a40x_ack_cpld_irq,
.mask = lh7a40x_mask_cpld_irq,
.unmask = lh7a40x_unmask_cpld_irq,
diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c
index 34eb79ee6e6..efe9bfc6e55 100644
--- a/arch/arm/mach-omap1/fpga.c
+++ b/arch/arm/mach-omap1/fpga.c
@@ -106,14 +106,16 @@ void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc,
}
}
-static struct irqchip omap_fpga_irq_ack = {
+static struct irq_chip omap_fpga_irq_ack = {
+ .name = "FPGA-ack",
.ack = fpga_mask_ack_irq,
.mask = fpga_mask_irq,
.unmask = fpga_unmask_irq,
};
-static struct irqchip omap_fpga_irq = {
+static struct irq_chip omap_fpga_irq = {
+ .name = "FPGA",
.ack = fpga_ack_irq,
.mask = fpga_mask_irq,
.unmask = fpga_unmask_irq,
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index 9e039845b50..3ea140bb9eb 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -168,7 +168,8 @@ static struct omap_irq_bank omap1610_irq_banks[] = {
};
#endif
-static struct irqchip omap_irq_chip = {
+static struct irq_chip omap_irq_chip = {
+ .name = "MPU",
.ack = omap_mask_ack_irq,
.mask = omap_mask_irq,
.unmask = omap_unmask_irq,
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 3eed6a737bf..dfc3b35cc1f 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -94,7 +94,8 @@ static void omap_mask_ack_irq(unsigned int irq)
omap_ack_irq(irq);
}
-static struct irqchip omap_irq_chip = {
+static struct irq_chip omap_irq_chip = {
+ .name = "INTC",
.ack = omap_mask_ack_irq,
.mask = omap_mask_irq,
.unmask = omap_unmask_irq,
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index d9635ff4b10..12141e2a50c 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -39,7 +39,8 @@ static void pxa_unmask_low_irq(unsigned int irq)
ICMR |= (1 << (irq + PXA_IRQ_SKIP));
}
-static struct irqchip pxa_internal_chip_low = {
+static struct irq_chip pxa_internal_chip_low = {
+ .name = "SC",
.ack = pxa_mask_low_irq,
.mask = pxa_mask_low_irq,
.unmask = pxa_unmask_low_irq,
@@ -61,7 +62,8 @@ static void pxa_unmask_high_irq(unsigned int irq)
ICMR2 |= (1 << (irq - 32 + PXA_IRQ_SKIP));
}
-static struct irqchip pxa_internal_chip_high = {
+static struct irq_chip pxa_internal_chip_high = {
+ .name = "SC-hi",
.ack = pxa_mask_high_irq,
.mask = pxa_mask_high_irq,
.unmask = pxa_unmask_high_irq,
@@ -129,7 +131,8 @@ static void pxa_ack_low_gpio(unsigned int irq)
GEDR0 = (1 << (irq - IRQ_GPIO0));
}
-static struct irqchip pxa_low_gpio_chip = {
+static struct irq_chip pxa_low_gpio_chip = {
+ .name = "GPIO-l",
.ack = pxa_ack_low_gpio,
.mask = pxa_mask_low_irq,
.unmask = pxa_unmask_low_irq,
@@ -237,7 +240,8 @@ static void pxa_unmask_muxed_gpio(unsigned int irq)
GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
}
-static struct irqchip pxa_muxed_gpio_chip = {
+static struct irq_chip pxa_muxed_gpio_chip = {
+ .name = "GPIO",
.ack = pxa_ack_muxed_gpio,
.mask = pxa_mask_muxed_gpio,
.unmask = pxa_unmask_muxed_gpio,
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index 1a5f5c21481..12479ae26db 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -68,7 +68,8 @@ static void lpd270_unmask_irq(unsigned int irq)
__raw_writew(lpd270_irq_enabled, LPD270_INT_MASK);
}
-static struct irqchip lpd270_irq_chip = {
+static struct irq_chip lpd270_irq_chip = {
+ .name = "CPLD",
.ack = lpd270_mask_irq,
.mask = lpd270_mask_irq,
.unmask = lpd270_unmask_irq,
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 6a9a669d60d..83ff5cee64d 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -78,7 +78,8 @@ static void lubbock_unmask_irq(unsigned int irq)
LUB_IRQ_MASK_EN = (lubbock_irq_enabled |= (1 << lubbock_irq));
}
-static struct irqchip lubbock_irq_chip = {
+static struct irq_chip lubbock_irq_chip = {
+ .name = "FPGA",
.ack = lubbock_mask_irq,
.mask = lubbock_mask_irq,
.unmask = lubbock_unmask_irq,
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 21ddf3de2f6..a7e9b96f258 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -64,7 +64,8 @@ static void mainstone_unmask_irq(unsigned int irq)
MST_INTMSKENA = (mainstone_irq_enabled |= (1 << mainstone_irq));
}
-static struct irqchip mainstone_irq_chip = {
+static struct irq_chip mainstone_irq_chip = {
+ .name = "FPGA",
.ack = mainstone_mask_irq,
.mask = mainstone_mask_irq,
.unmask = mainstone_unmask_irq,
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
index 4a92d6f92d6..60641d452db 100644
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ b/arch/arm/mach-s3c2410/mach-anubis.c
@@ -60,11 +60,12 @@ static struct map_desc anubis_iodesc[] __initdata = {
.virtual = (u32)S3C24XX_VA_ISA_BYTE,
.pfn = __phys_to_pfn(0x0),
.length = SZ_4M,
- .type = MT_DEVICE
+ .type = MT_DEVICE,
}, {
.virtual = (u32)S3C24XX_VA_ISA_WORD,
.pfn = __phys_to_pfn(0x0),
- .length = SZ_4M, MT_DEVICE
+ .length = SZ_4M,
+ .type = MT_DEVICE,
},
/* we could possibly compress the next set down into a set of smaller tables
@@ -78,36 +79,12 @@ static struct map_desc anubis_iodesc[] __initdata = {
.virtual = (u32)ANUBIS_VA_CTRL1,
.pfn = __phys_to_pfn(ANUBIS_PA_CTRL1),
.length = SZ_4K,
- .type = MT_DEVICE
+ .type = MT_DEVICE,
}, {
.virtual = (u32)ANUBIS_VA_CTRL2,
.pfn = __phys_to_pfn(ANUBIS_PA_CTRL2),
.length = SZ_4K,
- .type =MT_DEVICE
- },
-
- /* IDE drives */
-
- {
- .virtual = (u32)ANUBIS_IDEPRI,
- .pfn = __phys_to_pfn(S3C2410_CS3),
- .length = SZ_1M,
- .type = MT_DEVICE
- }, {
- .virtual = (u32)ANUBIS_IDEPRIAUX,
- .pfn = __phys_to_pfn(S3C2410_CS3+(1<<26)),
- .length = SZ_1M,
- .type = MT_DEVICE
- }, {
- .virtual = (u32)ANUBIS_IDESEC,
- .pfn = __phys_to_pfn(S3C2410_CS4),
- .length = SZ_1M,
- .type = MT_DEVICE
- }, {
- .virtual = (u32)ANUBIS_IDESECAUX,
- .pfn = __phys_to_pfn(S3C2410_CS4+(1<<26)),
- .length = SZ_1M,
- .type = MT_DEVICE
+ .type = MT_DEVICE,
},
};
@@ -126,7 +103,7 @@ static struct s3c24xx_uart_clksrc anubis_serial_clocks[] = {
.name = "pclk",
.divisor = 1,
.min_baud = 0,
- .max_baud = 0.
+ .max_baud = 0,
}
};
@@ -139,7 +116,7 @@ static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = {
.ulcon = ULCON,
.ufcon = UFCON,
.clocks = anubis_serial_clocks,
- .clocks_size = ARRAY_SIZE(anubis_serial_clocks)
+ .clocks_size = ARRAY_SIZE(anubis_serial_clocks),
},
[1] = {
.hwport = 2,
@@ -148,7 +125,7 @@ static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = {
.ulcon = ULCON,
.ufcon = UFCON,
.clocks = anubis_serial_clocks,
- .clocks_size = ARRAY_SIZE(anubis_serial_clocks)
+ .clocks_size = ARRAY_SIZE(anubis_serial_clocks),
},
};
@@ -162,7 +139,7 @@ static struct mtd_partition anubis_default_nand_part[] = {
[0] = {
.name = "Boot Agent",
.size = SZ_16K,
- .offset = 0
+ .offset = 0,
},
[1] = {
.name = "/boot",
@@ -194,21 +171,21 @@ static struct s3c2410_nand_set anubis_nand_sets[] = {
.nr_chips = 1,
.nr_map = external_map,
.nr_partitions = ARRAY_SIZE(anubis_default_nand_part),
- .partitions = anubis_default_nand_part
+ .partitions = anubis_default_nand_part,
},
[0] = {
.name = "chip0",
.nr_chips = 1,
.nr_map = chip0_map,
.nr_partitions = ARRAY_SIZE(anubis_default_nand_part),
- .partitions = anubis_default_nand_part
+ .partitions = anubis_default_nand_part,
},
[2] = {
.name = "chip1",
.nr_chips = 1,
.nr_map = chip1_map,
.nr_partitions = ARRAY_SIZE(anubis_default_nand_part),
- .partitions = anubis_default_nand_part
+ .partitions = anubis_default_nand_part,
},
};
@@ -313,7 +290,7 @@ static struct s3c24xx_board anubis_board __initdata = {
.devices = anubis_devices,
.devices_count = ARRAY_SIZE(anubis_devices),
.clocks = anubis_clocks,
- .clocks_count = ARRAY_SIZE(anubis_clocks)
+ .clocks_count = ARRAY_SIZE(anubis_clocks),
};
static void __init anubis_map_io(void)
diff --git a/arch/arm/mach-s3c2410/mach-osiris.c b/arch/arm/mach-s3c2410/mach-osiris.c
index 858fd03c6bc..e193ba69e65 100644
--- a/arch/arm/mach-s3c2410/mach-osiris.c
+++ b/arch/arm/mach-s3c2410/mach-osiris.c
@@ -67,12 +67,12 @@ static struct map_desc osiris_iodesc[] __initdata = {
.virtual = (u32)OSIRIS_VA_CTRL1,
.pfn = __phys_to_pfn(OSIRIS_PA_CTRL1),
.length = SZ_16K,
- .type = MT_DEVICE
+ .type = MT_DEVICE,
}, {
.virtual = (u32)OSIRIS_VA_CTRL2,
.pfn = __phys_to_pfn(OSIRIS_PA_CTRL2),
.length = SZ_16K,
- .type = MT_DEVICE
+ .type = MT_DEVICE,
},
};
@@ -91,7 +91,7 @@ static struct s3c24xx_uart_clksrc osiris_serial_clocks[] = {
.name = "pclk",
.divisor = 1,
.min_baud = 0,
- .max_baud = 0.
+ .max_baud = 0,
}
};
@@ -103,7 +103,7 @@ static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = {
.ulcon = ULCON,
.ufcon = UFCON,
.clocks = osiris_serial_clocks,
- .clocks_size = ARRAY_SIZE(osiris_serial_clocks)
+ .clocks_size = ARRAY_SIZE(osiris_serial_clocks),
},
[1] = {
.hwport = 1,
@@ -112,7 +112,7 @@ static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = {
.ulcon = ULCON,
.ufcon = UFCON,
.clocks = osiris_serial_clocks,
- .clocks_size = ARRAY_SIZE(osiris_serial_clocks)
+ .clocks_size = ARRAY_SIZE(osiris_serial_clocks),
},
};
@@ -126,7 +126,7 @@ static struct mtd_partition osiris_default_nand_part[] = {
[0] = {
.name = "Boot Agent",
.size = SZ_16K,
- .offset = 0
+ .offset = 0,
},
[1] = {
.name = "/boot",
@@ -158,21 +158,21 @@ static struct s3c2410_nand_set osiris_nand_sets[] = {
.nr_chips = 1,
.nr_map = external_map,
.nr_partitions = ARRAY_SIZE(osiris_default_nand_part),
- .partitions = osiris_default_nand_part
+ .partitions = osiris_default_nand_part,
},
[0] = {
.name = "chip0",
.nr_chips = 1,
.nr_map = chip0_map,
.nr_partitions = ARRAY_SIZE(osiris_default_nand_part),
- .partitions = osiris_default_nand_part
+ .partitions = osiris_default_nand_part,
},
[2] = {
.name = "chip1",
.nr_chips = 1,
.nr_map = chip1_map,
.nr_partitions = ARRAY_SIZE(osiris_default_nand_part),
- .partitions = osiris_default_nand_part
+ .partitions = osiris_default_nand_part,
},
};
@@ -245,7 +245,7 @@ static struct s3c24xx_board osiris_board __initdata = {
.devices = osiris_devices,
.devices_count = ARRAY_SIZE(osiris_devices),
.clocks = osiris_clocks,
- .clocks_count = ARRAY_SIZE(osiris_clocks)
+ .clocks_count = ARRAY_SIZE(osiris_clocks),
};
static void __init osiris_map_io(void)
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index 2891b8ca86d..b55b90a2e8f 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -95,7 +95,8 @@ static int sa1100_low_gpio_wake(unsigned int irq, unsigned int on)
return 0;
}
-static struct irqchip sa1100_low_gpio_chip = {
+static struct irq_chip sa1100_low_gpio_chip = {
+ .name = "GPIO-l",
.ack = sa1100_low_gpio_ack,
.mask = sa1100_low_gpio_mask,
.unmask = sa1100_low_gpio_unmask,
@@ -178,7 +179,8 @@ static int sa1100_high_gpio_wake(unsigned int irq, unsigned int on)
return 0;
}
-static struct irqchip sa1100_high_gpio_chip = {
+static struct irq_chip sa1100_high_gpio_chip = {
+ .name = "GPIO-h",
.ack = sa1100_high_gpio_ack,
.mask = sa1100_high_gpio_mask,
.unmask = sa1100_high_gpio_unmask,
@@ -215,7 +217,8 @@ static int sa1100_set_wake(unsigned int irq, unsigned int on)
return -EINVAL;
}
-static struct irqchip sa1100_normal_chip = {
+static struct irq_chip sa1100_normal_chip = {
+ .name = "SC",
.ack = sa1100_mask_irq,
.mask = sa1100_mask_irq,
.unmask = sa1100_unmask_irq,
diff --git a/arch/arm/mach-shark/irq.c b/arch/arm/mach-shark/irq.c
index 6cb67bd3dfd..b227052296c 100644
--- a/arch/arm/mach-shark/irq.c
+++ b/arch/arm/mach-shark/irq.c
@@ -69,7 +69,8 @@ static irqreturn_t bogus_int(int irq, void *dev_id, struct pt_regs *regs)
static struct irqaction cascade;
-static struct irqchip fb_chip = {
+static struct irq_chip fb_chip = {
+ .name = "XT-PIC",
.ack = shark_ack_8259A_irq,
.mask = shark_disable_8259A_irq,
.unmask = shark_enable_8259A_irq,
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 86437717601..c4e3f8c6847 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -69,7 +69,8 @@ static void sic_unmask_irq(unsigned int irq)
writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_SET);
}
-static struct irqchip sic_chip = {
+static struct irq_chip sic_chip = {
+ .name = "SIC",
.ack = sic_mask_irq,
.mask = sic_mask_irq,
.unmask = sic_unmask_irq,
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index dba7dddfe57..88a999df0ab 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -363,7 +363,9 @@ EXPORT_SYMBOL(__ioremap);
void __iounmap(void __iomem *addr)
{
+#ifndef CONFIG_SMP
struct vm_struct **p, *tmp;
+#endif
unsigned int section_mapping = 0;
addr = (void __iomem *)(PAGE_MASK & (unsigned long)addr);
diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c
index 6c5f0fe578a..ab143557e68 100644
--- a/arch/arm/mm/proc-syms.c
+++ b/arch/arm/mm/proc-syms.c
@@ -13,6 +13,7 @@
#include <asm/cacheflush.h>
#include <asm/proc-fns.h>
#include <asm/tlbflush.h>
+#include <asm/page.h>
#ifndef MULTI_CPU
EXPORT_SYMBOL(cpu_dcache_clean_area);
@@ -30,6 +31,13 @@ EXPORT_SYMBOL(__cpuc_coherent_kern_range);
EXPORT_SYMBOL(cpu_cache);
#endif
+#ifndef MULTI_USER
+EXPORT_SYMBOL(__cpu_clear_user_page);
+EXPORT_SYMBOL(__cpu_copy_user_page);
+#else
+EXPORT_SYMBOL(cpu_user);
+#endif
+
/*
* No module should need to touch the TLB (and currently
* no modules do. We export this for "loadkernel" support
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 521538671f4..561bff73a03 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -536,6 +536,11 @@ cpu_80200_name:
.asciz "XScale-80200"
.size cpu_80200_name, . - cpu_80200_name
+ .type cpu_80219_name, #object
+cpu_80219_name:
+ .asciz "XScale-80219"
+ .size cpu_80219_name, . - cpu_80219_name
+
.type cpu_8032x_name, #object
cpu_8032x_name:
.asciz "XScale-IOP8032x Family"
@@ -613,10 +618,33 @@ __80200_proc_info:
.long xscale_cache_fns
.size __80200_proc_info, . - __80200_proc_info
+ .type __80219_proc_info,#object
+__80219_proc_info:
+ .long 0x69052e20
+ .long 0xffffffe0
+ .long PMD_TYPE_SECT | \
+ PMD_SECT_BUFFERABLE | \
+ PMD_SECT_CACHEABLE | \
+ PMD_SECT_AP_WRITE | \
+ PMD_SECT_AP_READ
+ .long PMD_TYPE_SECT | \
+ PMD_SECT_AP_WRITE | \
+ PMD_SECT_AP_READ
+ b __xscale_setup
+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+ .long cpu_80219_name
+ .long xscale_processor_functions
+ .long v4wbi_tlb_fns
+ .long xscale_mc_user_fns
+ .long xscale_cache_fns
+ .size __80219_proc_info, . - __80219_proc_info
+
.type __8032x_proc_info,#object
__8032x_proc_info:
.long 0x69052420
- .long 0xfffff5e0 @ mask should accomodate IOP80219 also
+ .long 0xffffffe0
.long PMD_TYPE_SECT | \
PMD_SECT_BUFFERABLE | \
PMD_SECT_CACHEABLE | \
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index fec7970e564..cd7f973fb28 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -944,7 +944,8 @@ static void mpuio_unmask_irq(unsigned int irq)
_set_gpio_irqenable(bank, gpio, 1);
}
-static struct irqchip gpio_irq_chip = {
+static struct irq_chip gpio_irq_chip = {
+ .name = "GPIO",
.ack = gpio_ack_irq,
.mask = gpio_mask_irq,
.unmask = gpio_unmask_irq,
@@ -952,10 +953,11 @@ static struct irqchip gpio_irq_chip = {
.set_wake = gpio_wake_enable,
};
-static struct irqchip mpuio_irq_chip = {
+static struct irq_chip mpuio_irq_chip = {
+ .name = "MPUIO",
.ack = mpuio_ack_irq,
.mask = mpuio_mask_irq,
- .unmask = mpuio_unmask_irq
+ .unmask = mpuio_unmask_irq
};
static int initialized;
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index daa75ce4b77..f71fb4a029c 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -672,7 +672,7 @@ config MTRR
See <file:Documentation/mtrr.txt> for more information.
config EFI
- bool "Boot from EFI support (EXPERIMENTAL)"
+ bool "Boot from EFI support"
depends on ACPI
default n
---help---
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 1b452a1665c..ab98fc21a54 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -59,7 +59,8 @@ quiet_cmd_syscall = SYSCALL $@
export CPPFLAGS_vsyscall.lds += -P -C -U$(ARCH)
-vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1
+vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1 \
+ $(call ld-option, -Wl$(comma)--hash-style=sysv)
SYSCFLAGS_vsyscall-sysenter.so = $(vsyscall-flags)
SYSCFLAGS_vsyscall-int80.so = $(vsyscall-flags)
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
index e44a4c6a4fe..ccc1edff5c9 100644
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -96,6 +96,7 @@ config X86_POWERNOW_K8_ACPI
config X86_GX_SUSPMOD
tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
+ depends on PCI
help
This add the CPUFreq driver for NatSemi Geode processors which
support suspend modulation.
@@ -202,7 +203,7 @@ config X86_LONGRUN
config X86_LONGHAUL
tristate "VIA Cyrix III Longhaul"
select CPU_FREQ_TABLE
- depends on BROKEN
+ depends on ACPI_PROCESSOR
help
This adds the CPUFreq driver for VIA Samuel/CyrixIII,
VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index 567b39bea07..efb41e81351 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -384,8 +384,7 @@ static int acpi_cpufreq_early_init_acpi(void)
}
/* Do initialization in ACPI core */
- acpi_processor_preregister_performance(acpi_perf_data);
- return 0;
+ return acpi_processor_preregister_performance(acpi_perf_data);
}
static int
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 146f607e9c4..4f2c3aeef72 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -29,11 +29,13 @@
#include <linux/cpufreq.h>
#include <linux/slab.h>
#include <linux/string.h>
-#include <linux/pci.h>
#include <asm/msr.h>
#include <asm/timex.h>
#include <asm/io.h>
+#include <asm/acpi.h>
+#include <linux/acpi.h>
+#include <acpi/processor.h>
#include "longhaul.h"
@@ -56,6 +58,8 @@ static int minvid, maxvid;
static unsigned int minmult, maxmult;
static int can_scale_voltage;
static int vrmrev;
+static struct acpi_processor *pr = NULL;
+static struct acpi_processor_cx *cx = NULL;
/* Module parameters */
static int dont_scale_voltage;
@@ -118,84 +122,65 @@ static int longhaul_get_cpu_mult(void)
return eblcr_table[invalue];
}
+/* For processor with BCR2 MSR */
-static void do_powersaver(union msr_longhaul *longhaul,
- unsigned int clock_ratio_index)
+static void do_longhaul1(int cx_address, unsigned int clock_ratio_index)
{
- struct pci_dev *dev;
- unsigned long flags;
- unsigned int tmp_mask;
- int version;
- int i;
- u16 pci_cmd;
- u16 cmd_state[64];
+ union msr_bcr2 bcr2;
+ u32 t;
- switch (cpu_model) {
- case CPU_EZRA_T:
- version = 3;
- break;
- case CPU_NEHEMIAH:
- version = 0xf;
- break;
- default:
- return;
- }
+ rdmsrl(MSR_VIA_BCR2, bcr2.val);
+ /* Enable software clock multiplier */
+ bcr2.bits.ESOFTBF = 1;
+ bcr2.bits.CLOCKMUL = clock_ratio_index;
- rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
- longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf;
- longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
- longhaul->bits.EnableSoftBusRatio = 1;
- longhaul->bits.RevisionKey = 0;
+ /* Sync to timer tick */
+ safe_halt();
+ ACPI_FLUSH_CPU_CACHE();
+ /* Change frequency on next halt or sleep */
+ wrmsrl(MSR_VIA_BCR2, bcr2.val);
+ /* Invoke C3 */
+ inb(cx_address);
+ /* Dummy op - must do something useless after P_LVL3 read */
+ t = inl(acpi_fadt.xpm_tmr_blk.address);
+
+ /* Disable software clock multiplier */
+ local_irq_disable();
+ rdmsrl(MSR_VIA_BCR2, bcr2.val);
+ bcr2.bits.ESOFTBF = 0;
+ wrmsrl(MSR_VIA_BCR2, bcr2.val);
+}
- preempt_disable();
- local_irq_save(flags);
+/* For processor with Longhaul MSR */
- /*
- * get current pci bus master state for all devices
- * and clear bus master bit
- */
- dev = NULL;
- i = 0;
- do {
- dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
- if (dev != NULL) {
- pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
- cmd_state[i++] = pci_cmd;
- pci_cmd &= ~PCI_COMMAND_MASTER;
- pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
- }
- } while (dev != NULL);
+static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
+{
+ union msr_longhaul longhaul;
+ u32 t;
- tmp_mask=inb(0x21); /* works on C3. save mask. */
- outb(0xFE,0x21); /* TMR0 only */
- outb(0xFF,0x80); /* delay */
+ rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+ longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
+ longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
+ longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
+ longhaul.bits.EnableSoftBusRatio = 1;
+ /* Sync to timer tick */
safe_halt();
- wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
- halt();
-
+ ACPI_FLUSH_CPU_CACHE();
+ /* Change frequency on next halt or sleep */
+ wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+ /* Invoke C3 */
+ inb(cx_address);
+ /* Dummy op - must do something useless after P_LVL3 read */
+ t = inl(acpi_fadt.xpm_tmr_blk.address);
+
+ /* Disable bus ratio bit */
local_irq_disable();
-
- outb(tmp_mask,0x21); /* restore mask */
-
- /* restore pci bus master state for all devices */
- dev = NULL;
- i = 0;
- do {
- dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
- if (dev != NULL) {
- pci_cmd = cmd_state[i++];
- pci_write_config_byte(dev, PCI_COMMAND, pci_cmd);
- }
- } while (dev != NULL);
- local_irq_restore(flags);
- preempt_enable();
-
- /* disable bus ratio bit */
- rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
- longhaul->bits.EnableSoftBusRatio = 0;
- longhaul->bits.RevisionKey = version;
- wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+ longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
+ longhaul.bits.EnableSoftBusRatio = 0;
+ longhaul.bits.EnableSoftBSEL = 0;
+ longhaul.bits.EnableSoftVID = 0;
+ wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
}
/**
@@ -209,9 +194,9 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
{
int speed, mult;
struct cpufreq_freqs freqs;
- union msr_longhaul longhaul;
- union msr_bcr2 bcr2;
static unsigned int old_ratio=-1;
+ unsigned long flags;
+ unsigned int pic1_mask, pic2_mask;
if (old_ratio == clock_ratio_index)
return;
@@ -234,6 +219,20 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
fsb, mult/10, mult%10, print_speed(speed/1000));
+ preempt_disable();
+ local_irq_save(flags);
+
+ pic2_mask = inb(0xA1);
+ pic1_mask = inb(0x21); /* works on C3. save mask. */
+ outb(0xFF,0xA1); /* Overkill */
+ outb(0xFE,0x21); /* TMR0 only */
+
+ /* Disable bus master arbitration */
+ if (pr->flags.bm_check) {
+ acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
+ ACPI_MTX_DO_NOT_LOCK);
+ }
+
switch (longhaul_version) {
/*
@@ -245,20 +244,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
*/
case TYPE_LONGHAUL_V1:
case TYPE_LONGHAUL_V2:
- rdmsrl (MSR_VIA_BCR2, bcr2.val);
- /* Enable software clock multiplier */
- bcr2.bits.ESOFTBF = 1;
- bcr2.bits.CLOCKMUL = clock_ratio_index;
- local_irq_disable();
- wrmsrl (MSR_VIA_BCR2, bcr2.val);
- safe_halt();
-
- /* Disable software clock multiplier */
- rdmsrl (MSR_VIA_BCR2, bcr2.val);
- bcr2.bits.ESOFTBF = 0;
- local_irq_disable();
- wrmsrl (MSR_VIA_BCR2, bcr2.val);
- local_irq_enable();
+ do_longhaul1(cx->address, clock_ratio_index);
break;
/*
@@ -273,10 +259,22 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
* to work in practice.
*/
case TYPE_POWERSAVER:
- do_powersaver(&longhaul, clock_ratio_index);
+ do_powersaver(cx->address, clock_ratio_index);
break;
}
+ /* Enable bus master arbitration */
+ if (pr->flags.bm_check) {
+ acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0,
+ ACPI_MTX_DO_NOT_LOCK);
+ }
+
+ outb(pic2_mask,0xA1); /* restore mask */
+ outb(pic1_mask,0x21);
+
+ local_irq_restore(flags);
+ preempt_enable();
+
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
@@ -324,9 +322,11 @@ static int guess_fsb(void)
static int __init longhaul_get_ranges(void)
{
unsigned long invalue;
- unsigned int multipliers[32]= {
- 50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65,
- -1,110,120,-1,135,115,125,105,130,150,160,140,-1,155,-1,145 };
+ unsigned int ezra_t_multipliers[32]= {
+ 90, 30, 40, 100, 55, 35, 45, 95,
+ 50, 70, 80, 60, 120, 75, 85, 65,
+ -1, 110, 120, -1, 135, 115, 125, 105,
+ 130, 150, 160, 140, -1, 155, -1, 145 };
unsigned int j, k = 0;
union msr_longhaul longhaul;
unsigned long lo, hi;
@@ -355,13 +355,13 @@ static int __init longhaul_get_ranges(void)
invalue = longhaul.bits.MaxMHzBR;
if (longhaul.bits.MaxMHzBR4)
invalue += 16;
- maxmult=multipliers[invalue];
+ maxmult=ezra_t_multipliers[invalue];
invalue = longhaul.bits.MinMHzBR;
if (longhaul.bits.MinMHzBR4 == 1)
minmult = 30;
else
- minmult = multipliers[invalue];
+ minmult = ezra_t_multipliers[invalue];
fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
break;
}
@@ -527,6 +527,18 @@ static unsigned int longhaul_get(unsigned int cpu)
return calc_speed(longhaul_get_cpu_mult());
}
+static acpi_status longhaul_walk_callback(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context, void **return_value)
+{
+ struct acpi_device *d;
+
+ if ( acpi_bus_get_device(obj_handle, &d) ) {
+ return 0;
+ }
+ *return_value = (void *)acpi_driver_data(d);
+ return 1;
+}
static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
{
@@ -534,6 +546,15 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
char *cpuname=NULL;
int ret;
+ /* Check ACPI support for C3 state */
+ acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+ &longhaul_walk_callback, NULL, (void *)&pr);
+ if (pr == NULL) goto err_acpi;
+
+ cx = &pr->power.states[ACPI_STATE_C3];
+ if (cx->address == 0 || cx->latency > 1000) goto err_acpi;
+
+ /* Now check what we have on this motherboard */
switch (c->x86_model) {
case 6:
cpu_model = CPU_SAMUEL;
@@ -634,6 +655,10 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu);
return 0;
+
+err_acpi:
+ printk(KERN_ERR PFX "No ACPI support for CPU frequency changes.\n");
+ return -ENODEV;
}
static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy)
@@ -666,6 +691,18 @@ static int __init longhaul_init(void)
if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6)
return -ENODEV;
+#ifdef CONFIG_SMP
+ if (num_online_cpus() > 1) {
+ return -ENODEV;
+ printk(KERN_ERR PFX "More than 1 CPU detected, longhaul disabled.\n");
+ }
+#endif
+#ifdef CONFIG_X86_IO_APIC
+ if (cpu_has_apic) {
+ printk(KERN_ERR PFX "APIC detected. Longhaul is currently broken in this configuration.\n");
+ return -ENODEV;
+ }
+#endif
switch (c->x86_model) {
case 6 ... 9:
return cpufreq_register_driver(&longhaul_driver);
@@ -699,6 +736,6 @@ MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
MODULE_LICENSE ("GPL");
-module_init(longhaul_init);
+late_initcall(longhaul_init);
module_exit(longhaul_exit);
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index e9f0b928b0a..5c43be47587 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -759,7 +759,7 @@ static int __cpuinit cache_sysfs_init(void)
if (num_cache_leaves == 0)
return 0;
- register_cpu_notifier(&cacheinfo_cpu_notifier);
+ register_hotcpu_notifier(&cacheinfo_cpu_notifier);
for_each_online_cpu(i) {
cacheinfo_cpu_callback(&cacheinfo_cpu_notifier, CPU_ONLINE,
diff --git a/arch/i386/kernel/cpu/mcheck/mce.h b/arch/i386/kernel/cpu/mcheck/mce.h
index dc2416dfef1..84fd4cf7d0f 100644
--- a/arch/i386/kernel/cpu/mcheck/mce.h
+++ b/arch/i386/kernel/cpu/mcheck/mce.h
@@ -9,6 +9,6 @@ void winchip_mcheck_init(struct cpuinfo_x86 *c);
/* Call the installed machine check handler for this CPU setup. */
extern fastcall void (*machine_check_vector)(struct pt_regs *, long error_code);
-extern int mce_disabled __initdata;
+extern int mce_disabled;
extern int nr_mce_banks;
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index d9a260f2efb..37a7d2eaf4a 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -204,7 +204,7 @@ VM_MASK = 0x00020000
ENTRY(ret_from_fork)
CFI_STARTPROC
pushl %eax
- CFI_ADJUST_CFA_OFFSET -4
+ CFI_ADJUST_CFA_OFFSET 4
call schedule_tail
GET_THREAD_INFO(%ebp)
popl %eax
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index de2e16e561c..afe6505ca0b 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -256,11 +256,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
int ret = 0;
kprobe_opcode_t *addr;
struct kprobe_ctlblk *kcb;
-#ifdef CONFIG_PREEMPT
- unsigned pre_preempt_count = preempt_count();
-#else
- unsigned pre_preempt_count = 1;
-#endif
addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t));
@@ -338,13 +333,15 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
return 1;
ss_probe:
- if (pre_preempt_count && p->ainsn.boostable == 1 && !p->post_handler){
+#ifndef CONFIG_PREEMPT
+ if (p->ainsn.boostable == 1 && !p->post_handler){
/* Boost up -- we can execute copied instructions directly */
reset_current_kprobe();
regs->eip = (unsigned long)p->ainsn.insn;
preempt_enable_no_resched();
return 1;
}
+#endif
prepare_singlestep(p, regs);
kcb->kprobe_status = KPROBE_HIT_SS;
return 1;
diff --git a/arch/i386/kernel/machine_kexec.c b/arch/i386/kernel/machine_kexec.c
index 511abe52a94..6b1ae6ba76f 100644
--- a/arch/i386/kernel/machine_kexec.c
+++ b/arch/i386/kernel/machine_kexec.c
@@ -189,14 +189,11 @@ NORET_TYPE void machine_kexec(struct kimage *image)
memcpy((void *)reboot_code_buffer, relocate_new_kernel,
relocate_new_kernel_size);
- /* The segment registers are funny things, they are
- * automatically loaded from a table, in memory wherever you
- * set them to a specific selector, but this table is never
- * accessed again you set the segment to a different selector.
- *
- * The more common model is are caches where the behide
- * the scenes work is done, but is also dropped at arbitrary
- * times.
+ /* The segment registers are funny things, they have both a
+ * visible and an invisible part. Whenever the visible part is
+ * set to a specific selector, the invisible part is loaded
+ * with from a table in memory. At no other time is the
+ * descriptor table in memory accessed.
*
* I take advantage of this here by force loading the
* segments, before I zap the gdt with an invalid value.
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 2dd928a8464..acb351478e4 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -575,6 +575,7 @@ void touch_nmi_watchdog (void)
*/
touch_softlockup_watchdog();
}
+EXPORT_SYMBOL(touch_nmi_watchdog);
extern void die_nmi(struct pt_regs *, const char *msg);
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 923bb292f47..8657c739656 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -690,8 +690,8 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
/*
* Now maybe handle debug registers and/or IO bitmaps
*/
- if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW))
- || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP))
+ if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW)
+ || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)))
__switch_to_xtra(next_p, tss);
disable_tsc(prev_p, next_p);
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 6f5fea05f1d..f948419c888 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -212,14 +212,20 @@ valid_k7:
* then we print a warning if not, and always resync.
*/
-static atomic_t tsc_start_flag = ATOMIC_INIT(0);
-static atomic_t tsc_count_start = ATOMIC_INIT(0);
-static atomic_t tsc_count_stop = ATOMIC_INIT(0);
-static unsigned long long tsc_values[NR_CPUS];
+static struct {
+ atomic_t start_flag;
+ atomic_t count_start;
+ atomic_t count_stop;
+ unsigned long long values[NR_CPUS];
+} tsc __initdata = {
+ .start_flag = ATOMIC_INIT(0),
+ .count_start = ATOMIC_INIT(0),
+ .count_stop = ATOMIC_INIT(0),
+};
#define NR_LOOPS 5
-static void __init synchronize_tsc_bp (void)
+static void __init synchronize_tsc_bp(void)
{
int i;
unsigned long long t0;
@@ -233,7 +239,7 @@ static void __init synchronize_tsc_bp (void)
/* convert from kcyc/sec to cyc/usec */
one_usec = cpu_khz / 1000;
- atomic_set(&tsc_start_flag, 1);
+ atomic_set(&tsc.start_flag, 1);
wmb();
/*
@@ -250,16 +256,16 @@ static void __init synchronize_tsc_bp (void)
/*
* all APs synchronize but they loop on '== num_cpus'
*/
- while (atomic_read(&tsc_count_start) != num_booting_cpus()-1)
+ while (atomic_read(&tsc.count_start) != num_booting_cpus()-1)
cpu_relax();
- atomic_set(&tsc_count_stop, 0);
+ atomic_set(&tsc.count_stop, 0);
wmb();
/*
* this lets the APs save their current TSC:
*/
- atomic_inc(&tsc_count_start);
+ atomic_inc(&tsc.count_start);
- rdtscll(tsc_values[smp_processor_id()]);
+ rdtscll(tsc.values[smp_processor_id()]);
/*
* We clear the TSC in the last loop:
*/
@@ -269,56 +275,54 @@ static void __init synchronize_tsc_bp (void)
/*
* Wait for all APs to leave the synchronization point:
*/
- while (atomic_read(&tsc_count_stop) != num_booting_cpus()-1)
+ while (atomic_read(&tsc.count_stop) != num_booting_cpus()-1)
cpu_relax();
- atomic_set(&tsc_count_start, 0);
+ atomic_set(&tsc.count_start, 0);
wmb();
- atomic_inc(&tsc_count_stop);
+ atomic_inc(&tsc.count_stop);
}
sum = 0;
for (i = 0; i < NR_CPUS; i++) {
if (cpu_isset(i, cpu_callout_map)) {
- t0 = tsc_values[i];
+ t0 = tsc.values[i];
sum += t0;
}
}
avg = sum;
do_div(avg, num_booting_cpus());
- sum = 0;
for (i = 0; i < NR_CPUS; i++) {
if (!cpu_isset(i, cpu_callout_map))
continue;
- delta = tsc_values[i] - avg;
+ delta = tsc.values[i] - avg;
if (delta < 0)
delta = -delta;
/*
* We report bigger than 2 microseconds clock differences.
*/
if (delta > 2*one_usec) {
- long realdelta;
+ long long realdelta;
+
if (!buggy) {
buggy = 1;
printk("\n");
}
realdelta = delta;
do_div(realdelta, one_usec);
- if (tsc_values[i] < avg)
+ if (tsc.values[i] < avg)
realdelta = -realdelta;
- if (realdelta > 0)
- printk(KERN_INFO "CPU#%d had %ld usecs TSC "
+ if (realdelta)
+ printk(KERN_INFO "CPU#%d had %Ld usecs TSC "
"skew, fixed it up.\n", i, realdelta);
}
-
- sum += delta;
}
if (!buggy)
printk("passed.\n");
}
-static void __init synchronize_tsc_ap (void)
+static void __init synchronize_tsc_ap(void)
{
int i;
@@ -327,20 +331,20 @@ static void __init synchronize_tsc_ap (void)
* this gets called, so we first wait for the BP to
* finish SMP initialization:
*/
- while (!atomic_read(&tsc_start_flag))
+ while (!atomic_read(&tsc.start_flag))
cpu_relax();
for (i = 0; i < NR_LOOPS; i++) {
- atomic_inc(&tsc_count_start);
- while (atomic_read(&tsc_count_start) != num_booting_cpus())
+ atomic_inc(&tsc.count_start);
+ while (atomic_read(&tsc.count_start) != num_booting_cpus())
cpu_relax();
- rdtscll(tsc_values[smp_processor_id()]);
+ rdtscll(tsc.values[smp_processor_id()]);
if (i == NR_LOOPS-1)
write_tsc(0, 0);
- atomic_inc(&tsc_count_stop);
- while (atomic_read(&tsc_count_stop) != num_booting_cpus())
+ atomic_inc(&tsc.count_stop);
+ while (atomic_read(&tsc.count_stop) != num_booting_cpus())
cpu_relax();
}
}
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 8705c0f0578..edd00f6cee3 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -135,7 +135,7 @@ unsigned long profile_pc(struct pt_regs *regs)
{
unsigned long pc = instruction_pointer(regs);
- if (in_lock_functions(pc))
+ if (!user_mode_vm(regs) && in_lock_functions(pc))
return *(unsigned long *)(regs->ebp + 4);
return pc;
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 313ac1f7dc5..0d4005dc06c 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -187,10 +187,21 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
if (unwind_init_blocked(&info, task) == 0)
unw_ret = show_trace_unwind(&info, log_lvl);
}
- if (unw_ret > 0) {
- if (call_trace > 0)
+ if (unw_ret > 0 && !arch_unw_user_mode(&info)) {
+#ifdef CONFIG_STACK_UNWIND
+ print_symbol("DWARF2 unwinder stuck at %s\n",
+ UNW_PC(&info));
+ if (call_trace == 1) {
+ printk("Leftover inexact backtrace:\n");
+ if (UNW_SP(&info))
+ stack = (void *)UNW_SP(&info);
+ } else if (call_trace > 1)
return;
- printk("%sLegacy call trace:\n", log_lvl);
+ else
+ printk("Full inexact backtrace again:\n");
+#else
+ printk("Inexact backtrace:\n");
+#endif
}
}
@@ -442,11 +453,9 @@ void die(const char * str, struct pt_regs * regs, long err)
if (in_interrupt())
panic("Fatal exception in interrupt");
- if (panic_on_oops) {
- printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
- ssleep(5);
- panic("Fatal exception");
- }
+ if (panic_on_oops)
+ panic("Fatal exception: panic_on_oops");
+
oops_exit();
do_exit(SIGSEGV);
}
@@ -1238,8 +1247,10 @@ static int __init call_trace_setup(char *s)
call_trace = -1;
else if (strcmp(s, "both") == 0)
call_trace = 0;
- else if (strcmp(s, "new") == 0)
+ else if (strcmp(s, "newfallback") == 0)
call_trace = 1;
+ else if (strcmp(s, "new") == 2)
+ call_trace = 2;
return 1;
}
__setup("call_trace=", call_trace_setup);
diff --git a/arch/i386/kernel/vsyscall.lds.S b/arch/i386/kernel/vsyscall.lds.S
index e26975fc68b..f66cd11adb7 100644
--- a/arch/i386/kernel/vsyscall.lds.S
+++ b/arch/i386/kernel/vsyscall.lds.S
@@ -10,6 +10,7 @@ SECTIONS
. = VDSO_PRELINK + SIZEOF_HEADERS;
.hash : { *(.hash) } :text
+ .gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index 9ea35398e10..0f14a82b856 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -363,7 +363,7 @@ CONFIG_BLK_DEV_IDECD=y
#
CONFIG_IDE_GENERIC=y
CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
+CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_BLK_DEV_OFFBOARD is not set
# CONFIG_BLK_DEV_GENERIC is not set
# CONFIG_BLK_DEV_OPTI621 is not set
diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig
index 6cba55da572..9001b3fbaa3 100644
--- a/arch/ia64/defconfig
+++ b/arch/ia64/defconfig
@@ -366,7 +366,7 @@ CONFIG_BLK_DEV_IDESCSI=m
# CONFIG_IDE_GENERIC is not set
# CONFIG_BLK_DEV_IDEPNP is not set
CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
+CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
index a3fe9753113..8a4f0d0d17a 100644
--- a/arch/ia64/hp/sim/simscsi.c
+++ b/arch/ia64/hp/sim/simscsi.c
@@ -151,7 +151,7 @@ static void
simscsi_sg_readwrite (struct scsi_cmnd *sc, int mode, unsigned long offset)
{
int list_len = sc->use_sg;
- struct scatterlist *sl = (struct scatterlist *)sc->buffer;
+ struct scatterlist *sl = (struct scatterlist *)sc->request_buffer;
struct disk_stat stat;
struct disk_req req;
@@ -244,7 +244,7 @@ static void simscsi_fillresult(struct scsi_cmnd *sc, char *buf, unsigned len)
if (scatterlen == 0)
memcpy(sc->request_buffer, buf, len);
- else for (slp = (struct scatterlist *)sc->buffer; scatterlen-- > 0 && len > 0; slp++) {
+ else for (slp = (struct scatterlist *)sc->request_buffer; scatterlen-- > 0 && len > 0; slp++) {
unsigned thislen = min(len, slp->length);
memcpy(page_address(slp->page) + slp->offset, buf, thislen);
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 0e4553f320b..ad8215a3c58 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -45,7 +45,8 @@ CPPFLAGS_gate.lds := -P -C -U$(ARCH)
quiet_cmd_gate = GATE $@
cmd_gate = $(CC) -nostdlib $(GATECFLAGS_$(@F)) -Wl,-T,$(filter-out FORCE,$^) -o $@
-GATECFLAGS_gate.so = -shared -s -Wl,-soname=linux-gate.so.1
+GATECFLAGS_gate.so = -shared -s -Wl,-soname=linux-gate.so.1 \
+ $(call ld-option, -Wl$(comma)--hash-style=sysv)
$(obj)/gate.so: $(obj)/gate.lds $(obj)/gate.o FORCE
$(call if_changed,gate)
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index e4bfa9dafbc..bb8770a177b 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -632,7 +632,7 @@ kern_memory_descriptor (unsigned long phys_addr)
if (phys_addr - md->start < (md->num_pages << EFI_PAGE_SHIFT))
return md;
}
- return 0;
+ return NULL;
}
static efi_memory_desc_t *
@@ -652,7 +652,7 @@ efi_memory_descriptor (unsigned long phys_addr)
if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
return md;
}
- return 0;
+ return NULL;
}
u32
@@ -923,7 +923,7 @@ find_memmap_space (void)
void
efi_memmap_init(unsigned long *s, unsigned long *e)
{
- struct kern_memdesc *k, *prev = 0;
+ struct kern_memdesc *k, *prev = NULL;
u64 contig_low=0, contig_high=0;
u64 as, ae, lim;
void *efi_map_start, *efi_map_end, *p, *q;
diff --git a/arch/ia64/kernel/gate.lds.S b/arch/ia64/kernel/gate.lds.S
index cc35cddfd4c..6d198339bf8 100644
--- a/arch/ia64/kernel/gate.lds.S
+++ b/arch/ia64/kernel/gate.lds.S
@@ -12,6 +12,7 @@ SECTIONS
. = GATE_ADDR + SIZEOF_HEADERS;
.hash : { *(.hash) } :readable
+ .gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index 561b8f1d3bc..29236f0c62b 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -853,7 +853,6 @@ END(__ia64_init_fpu)
*/
GLOBAL_ENTRY(ia64_switch_mode_phys)
{
- alloc r2=ar.pfs,0,0,0,0
rsm psr.i | psr.ic // disable interrupts and interrupt collection
mov r15=ip
}
@@ -902,7 +901,6 @@ END(ia64_switch_mode_phys)
*/
GLOBAL_ENTRY(ia64_switch_mode_virt)
{
- alloc r2=ar.pfs,0,0,0,0
rsm psr.i | psr.ic // disable interrupts and interrupt collection
mov r15=ip
}
diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
index b7cf651ceb1..3ead20fb6f4 100644
--- a/arch/ia64/kernel/ia64_ksyms.c
+++ b/arch/ia64/kernel/ia64_ksyms.c
@@ -62,7 +62,7 @@ EXPORT_SYMBOL(__udivdi3);
EXPORT_SYMBOL(__moddi3);
EXPORT_SYMBOL(__umoddi3);
-#if defined(CONFIG_MD_RAID5) || defined(CONFIG_MD_RAID5_MODULE)
+#if defined(CONFIG_MD_RAID456) || defined(CONFIG_MD_RAID456_MODULE)
extern void xor_ia64_2(void);
extern void xor_ia64_3(void);
extern void xor_ia64_4(void);
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 00d9c83b802..781960f80b6 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -448,11 +448,20 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
return 0;
}
+void __kprobes flush_insn_slot(struct kprobe *p)
+{
+ unsigned long arm_addr;
+
+ arm_addr = ((unsigned long)&p->opcode.bundle) & ~0xFULL;
+ flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+}
+
void __kprobes arch_arm_kprobe(struct kprobe *p)
{
unsigned long addr = (unsigned long)p->addr;
unsigned long arm_addr = addr & ~0xFULL;
+ flush_insn_slot(p);
memcpy((char *)arm_addr, &p->ainsn.insn.bundle, sizeof(bundle_t));
flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
}
diff --git a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S
index 5018c7f2e7a..ebaf1e685f5 100644
--- a/arch/ia64/kernel/pal.S
+++ b/arch/ia64/kernel/pal.S
@@ -217,12 +217,7 @@ GLOBAL_ENTRY(ia64_pal_call_phys_stacked)
.body
;;
ld8 loc2 = [loc2] // loc2 <- entry point
- mov out0 = in0 // first argument
- mov out1 = in1 // copy arg2
- mov out2 = in2 // copy arg3
- mov out3 = in3 // copy arg3
- ;;
- mov loc3 = psr // save psr
+ mov loc3 = psr // save psr
;;
mov loc4=ar.rsc // save RSE configuration
dep.z loc2=loc2,0,61 // convert pal entry point to physical
@@ -236,18 +231,23 @@ GLOBAL_ENTRY(ia64_pal_call_phys_stacked)
;;
andcm r16=loc3,r16 // removes bits to clear from psr
br.call.sptk.many rp=ia64_switch_mode_phys
-.ret6:
+
+ mov out0 = in0 // first argument
+ mov out1 = in1 // copy arg2
+ mov out2 = in2 // copy arg3
+ mov out3 = in3 // copy arg3
mov loc5 = r19
mov loc6 = r20
+
br.call.sptk.many rp=b7 // now make the call
-.ret7:
+
mov ar.rsc=0 // put RSE in enforced lazy, LE mode
mov r16=loc3 // r16= original psr
mov r19=loc5
mov r20=loc6
br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
-.ret8: mov psr.l = loc3 // restore init PSR
+ mov psr.l = loc3 // restore init PSR
mov ar.pfs = loc1
mov rp = loc0
;;
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index 3f5bac59209..0b546e2b36a 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -566,29 +566,23 @@ version_info(char *page)
pal_version_u_t min_ver, cur_ver;
char *p = page;
- /* The PAL_VERSION call is advertised as being able to support
- * both physical and virtual mode calls. This seems to be a documentation
- * bug rather than firmware bug. In fact, it does only support physical mode.
- * So now the code reflects this fact and the pal_version() has been updated
- * accordingly.
- */
- if (ia64_pal_version(&min_ver, &cur_ver) != 0) return 0;
+ if (ia64_pal_version(&min_ver, &cur_ver) != 0)
+ return 0;
p += sprintf(p,
"PAL_vendor : 0x%02x (min=0x%02x)\n"
- "PAL_A : %x.%x.%x (min=%x.%x.%x)\n"
- "PAL_B : %x.%x.%x (min=%x.%x.%x)\n",
- cur_ver.pal_version_s.pv_pal_vendor, min_ver.pal_version_s.pv_pal_vendor,
-
- cur_ver.pal_version_s.pv_pal_a_model>>4,
- cur_ver.pal_version_s.pv_pal_a_model&0xf, cur_ver.pal_version_s.pv_pal_a_rev,
- min_ver.pal_version_s.pv_pal_a_model>>4,
- min_ver.pal_version_s.pv_pal_a_model&0xf, min_ver.pal_version_s.pv_pal_a_rev,
-
- cur_ver.pal_version_s.pv_pal_b_model>>4,
- cur_ver.pal_version_s.pv_pal_b_model&0xf, cur_ver.pal_version_s.pv_pal_b_rev,
- min_ver.pal_version_s.pv_pal_b_model>>4,
- min_ver.pal_version_s.pv_pal_b_model&0xf, min_ver.pal_version_s.pv_pal_b_rev);
+ "PAL_A : %02x.%02x (min=%02x.%02x)\n"
+ "PAL_B : %02x.%02x (min=%02x.%02x)\n",
+ cur_ver.pal_version_s.pv_pal_vendor,
+ min_ver.pal_version_s.pv_pal_vendor,
+ cur_ver.pal_version_s.pv_pal_a_model,
+ cur_ver.pal_version_s.pv_pal_a_rev,
+ min_ver.pal_version_s.pv_pal_a_model,
+ min_ver.pal_version_s.pv_pal_a_rev,
+ cur_ver.pal_version_s.pv_pal_b_model,
+ cur_ver.pal_version_s.pv_pal_b_rev,
+ min_ver.pal_version_s.pv_pal_b_model,
+ min_ver.pal_version_s.pv_pal_b_rev);
return p - page;
}
@@ -958,9 +952,9 @@ remove_palinfo_proc_entries(unsigned int hcpu)
}
}
-static int __cpuinit palinfo_cpu_callback(struct notifier_block *nfb,
- unsigned long action,
- void *hcpu)
+#ifdef CONFIG_HOTPLUG_CPU
+static int palinfo_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
{
unsigned int hotcpu = (unsigned long)hcpu;
@@ -968,20 +962,19 @@ static int __cpuinit palinfo_cpu_callback(struct notifier_block *nfb,
case CPU_ONLINE:
create_palinfo_proc_entries(hotcpu);
break;
-#ifdef CONFIG_HOTPLUG_CPU
case CPU_DEAD:
remove_palinfo_proc_entries(hotcpu);
break;
-#endif
}
return NOTIFY_OK;
}
-static struct notifier_block __cpuinitdata palinfo_cpu_notifier =
+static struct notifier_block palinfo_cpu_notifier =
{
.notifier_call = palinfo_cpu_callback,
.priority = 0,
};
+#endif
static int __init
palinfo_init(void)
@@ -1020,7 +1013,7 @@ palinfo_exit(void)
/*
* Unregister from cpu notifier callbacks
*/
- unregister_cpu_notifier(&palinfo_cpu_notifier);
+ unregister_hotcpu_notifier(&palinfo_cpu_notifier);
}
module_init(palinfo_init);
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index b146f1cfad3..d24fa393b18 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -435,7 +435,7 @@ static int __cpuinit cache_sysfs_init(void)
(void *)(long)i);
}
- register_cpu_notifier(&cache_cpu_notifier);
+ register_hotcpu_notifier(&cache_cpu_notifier);
return 0;
}
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index e7bbb0f40aa..5a0420464c6 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -117,11 +117,8 @@ die (const char *str, struct pt_regs *regs, long err)
die.lock_owner = -1;
spin_unlock_irq(&die.lock);
- if (panic_on_oops) {
- printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
- ssleep(5);
- panic("Fatal exception");
- }
+ if (panic_on_oops)
+ panic("Fatal exception: panic_on_oops");
do_exit(SIGSEGV);
}
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
index 5f03b9e524d..4c73a676366 100644
--- a/arch/ia64/kernel/uncached.c
+++ b/arch/ia64/kernel/uncached.c
@@ -32,32 +32,38 @@
extern void __init efi_memmap_walk_uc(efi_freemem_callback_t, void *);
-#define MAX_UNCACHED_GRANULES 5
-static int allocated_granules;
+struct uncached_pool {
+ struct gen_pool *pool;
+ struct mutex add_chunk_mutex; /* serialize adding a converted chunk */
+ int nchunks_added; /* #of converted chunks added to pool */
+ atomic_t status; /* smp called function's return status*/
+};
+
+#define MAX_CONVERTED_CHUNKS_PER_NODE 2
-struct gen_pool *uncached_pool[MAX_NUMNODES];
+struct uncached_pool uncached_pools[MAX_NUMNODES];
static void uncached_ipi_visibility(void *data)
{
int status;
+ struct uncached_pool *uc_pool = (struct uncached_pool *)data;
status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL);
if ((status != PAL_VISIBILITY_OK) &&
(status != PAL_VISIBILITY_OK_REMOTE_NEEDED))
- printk(KERN_DEBUG "pal_prefetch_visibility() returns %i on "
- "CPU %i\n", status, raw_smp_processor_id());
+ atomic_inc(&uc_pool->status);
}
static void uncached_ipi_mc_drain(void *data)
{
int status;
+ struct uncached_pool *uc_pool = (struct uncached_pool *)data;
status = ia64_pal_mc_drain();
- if (status)
- printk(KERN_WARNING "ia64_pal_mc_drain() failed with %i on "
- "CPU %i\n", status, raw_smp_processor_id());
+ if (status != PAL_STATUS_SUCCESS)
+ atomic_inc(&uc_pool->status);
}
@@ -70,21 +76,34 @@ static void uncached_ipi_mc_drain(void *data)
* This is accomplished by first allocating a granule of cached memory pages
* and then converting them to uncached memory pages.
*/
-static int uncached_add_chunk(struct gen_pool *pool, int nid)
+static int uncached_add_chunk(struct uncached_pool *uc_pool, int nid)
{
struct page *page;
- int status, i;
+ int status, i, nchunks_added = uc_pool->nchunks_added;
unsigned long c_addr, uc_addr;
- if (allocated_granules >= MAX_UNCACHED_GRANULES)
+ if (mutex_lock_interruptible(&uc_pool->add_chunk_mutex) != 0)
+ return -1; /* interrupted by a signal */
+
+ if (uc_pool->nchunks_added > nchunks_added) {
+ /* someone added a new chunk while we were waiting */
+ mutex_unlock(&uc_pool->add_chunk_mutex);
+ return 0;
+ }
+
+ if (uc_pool->nchunks_added >= MAX_CONVERTED_CHUNKS_PER_NODE) {
+ mutex_unlock(&uc_pool->add_chunk_mutex);
return -1;
+ }
/* attempt to allocate a granule's worth of cached memory pages */
page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO,
IA64_GRANULE_SHIFT-PAGE_SHIFT);
- if (!page)
+ if (!page) {
+ mutex_unlock(&uc_pool->add_chunk_mutex);
return -1;
+ }
/* convert the memory pages from cached to uncached */
@@ -102,11 +121,14 @@ static int uncached_add_chunk(struct gen_pool *pool, int nid)
flush_tlb_kernel_range(uc_addr, uc_adddr + IA64_GRANULE_SIZE);
status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL);
- if (!status) {
- status = smp_call_function(uncached_ipi_visibility, NULL, 0, 1);
- if (status)
+ if (status == PAL_VISIBILITY_OK_REMOTE_NEEDED) {
+ atomic_set(&uc_pool->status, 0);
+ status = smp_call_function(uncached_ipi_visibility, uc_pool,
+ 0, 1);
+ if (status || atomic_read(&uc_pool->status))
goto failed;
- }
+ } else if (status != PAL_VISIBILITY_OK)
+ goto failed;
preempt_disable();
@@ -120,20 +142,24 @@ static int uncached_add_chunk(struct gen_pool *pool, int nid)
preempt_enable();
- ia64_pal_mc_drain();
- status = smp_call_function(uncached_ipi_mc_drain, NULL, 0, 1);
- if (status)
+ status = ia64_pal_mc_drain();
+ if (status != PAL_STATUS_SUCCESS)
+ goto failed;
+ atomic_set(&uc_pool->status, 0);
+ status = smp_call_function(uncached_ipi_mc_drain, uc_pool, 0, 1);
+ if (status || atomic_read(&uc_pool->status))
goto failed;
/*
* The chunk of memory pages has been converted to uncached so now we
* can add it to the pool.
*/
- status = gen_pool_add(pool, uc_addr, IA64_GRANULE_SIZE, nid);
+ status = gen_pool_add(uc_pool->pool, uc_addr, IA64_GRANULE_SIZE, nid);
if (status)
goto failed;
- allocated_granules++;
+ uc_pool->nchunks_added++;
+ mutex_unlock(&uc_pool->add_chunk_mutex);
return 0;
/* failed to convert or add the chunk so give it back to the kernel */
@@ -142,6 +168,7 @@ failed:
ClearPageUncached(&page[i]);
free_pages(c_addr, IA64_GRANULE_SHIFT-PAGE_SHIFT);
+ mutex_unlock(&uc_pool->add_chunk_mutex);
return -1;
}
@@ -158,7 +185,7 @@ failed:
unsigned long uncached_alloc_page(int starting_nid)
{
unsigned long uc_addr;
- struct gen_pool *pool;
+ struct uncached_pool *uc_pool;
int nid;
if (unlikely(starting_nid >= MAX_NUMNODES))
@@ -171,14 +198,14 @@ unsigned long uncached_alloc_page(int starting_nid)
do {
if (!node_online(nid))
continue;
- pool = uncached_pool[nid];
- if (pool == NULL)
+ uc_pool = &uncached_pools[nid];
+ if (uc_pool->pool == NULL)
continue;
do {
- uc_addr = gen_pool_alloc(pool, PAGE_SIZE);
+ uc_addr = gen_pool_alloc(uc_pool->pool, PAGE_SIZE);
if (uc_addr != 0)
return uc_addr;
- } while (uncached_add_chunk(pool, nid) == 0);
+ } while (uncached_add_chunk(uc_pool, nid) == 0);
} while ((nid = (nid + 1) % MAX_NUMNODES) != starting_nid);
@@ -197,7 +224,7 @@ EXPORT_SYMBOL(uncached_alloc_page);
void uncached_free_page(unsigned long uc_addr)
{
int nid = paddr_to_nid(uc_addr - __IA64_UNCACHED_OFFSET);
- struct gen_pool *pool = uncached_pool[nid];
+ struct gen_pool *pool = uncached_pools[nid].pool;
if (unlikely(pool == NULL))
return;
@@ -224,7 +251,7 @@ static int __init uncached_build_memmap(unsigned long uc_start,
unsigned long uc_end, void *arg)
{
int nid = paddr_to_nid(uc_start - __IA64_UNCACHED_OFFSET);
- struct gen_pool *pool = uncached_pool[nid];
+ struct gen_pool *pool = uncached_pools[nid].pool;
size_t size = uc_end - uc_start;
touch_softlockup_watchdog();
@@ -242,7 +269,8 @@ static int __init uncached_init(void)
int nid;
for_each_online_node(nid) {
- uncached_pool[nid] = gen_pool_create(PAGE_SHIFT, nid);
+ uncached_pools[nid].pool = gen_pool_create(PAGE_SHIFT, nid);
+ mutex_init(&uncached_pools[nid].add_chunk_mutex);
}
efi_memmap_walk_uc(uncached_build_memmap, NULL);
diff --git a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile
index d8536a2c22a..38fa6e49e79 100644
--- a/arch/ia64/lib/Makefile
+++ b/arch/ia64/lib/Makefile
@@ -14,7 +14,7 @@ lib-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \
lib-$(CONFIG_ITANIUM) += copy_page.o copy_user.o memcpy.o
lib-$(CONFIG_MCKINLEY) += copy_page_mck.o memcpy_mck.o
lib-$(CONFIG_PERFMON) += carta_random.o
-lib-$(CONFIG_MD_RAID5) += xor.o
+lib-$(CONFIG_MD_RAID456) += xor.o
AFLAGS___divdi3.o =
AFLAGS___udivdi3.o = -DUNSIGNED
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index 2a88cdd6d92..e004143ba86 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -27,6 +27,7 @@
#ifdef CONFIG_VIRTUAL_MEM_MAP
static unsigned long num_dma_physpages;
+static unsigned long max_gap;
#endif
/**
@@ -45,9 +46,15 @@ show_mem (void)
printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
i = max_mapnr;
- while (i-- > 0) {
- if (!pfn_valid(i))
+ for (i = 0; i < max_mapnr; i++) {
+ if (!pfn_valid(i)) {
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+ if (max_gap < LARGE_GAP)
+ continue;
+ i = vmemmap_find_next_valid_pfn(0, i) - 1;
+#endif
continue;
+ }
total++;
if (PageReserved(mem_map+i))
reserved++;
@@ -234,7 +241,6 @@ paging_init (void)
unsigned long zones_size[MAX_NR_ZONES];
#ifdef CONFIG_VIRTUAL_MEM_MAP
unsigned long zholes_size[MAX_NR_ZONES];
- unsigned long max_gap;
#endif
/* initialize mem_map[] */
@@ -266,7 +272,6 @@ paging_init (void)
}
}
- max_gap = 0;
efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
if (max_gap < LARGE_GAP) {
vmem_map = (struct page *) 0;
@@ -277,7 +282,8 @@ paging_init (void)
/* allocate virtual_mem_map */
- map_size = PAGE_ALIGN(max_low_pfn * sizeof(struct page));
+ map_size = PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) *
+ sizeof(struct page));
vmalloc_end -= map_size;
vmem_map = (struct page *) vmalloc_end;
efi_memmap_walk(create_mem_map_page_table, NULL);
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 99bd9e30db9..d260bffa01a 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -534,68 +534,6 @@ void __cpuinit *per_cpu_init(void)
}
#endif /* CONFIG_SMP */
-#ifdef CONFIG_VIRTUAL_MEM_MAP
-static inline int find_next_valid_pfn_for_pgdat(pg_data_t *pgdat, int i)
-{
- unsigned long end_address, hole_next_pfn;
- unsigned long stop_address;
-
- end_address = (unsigned long) &vmem_map[pgdat->node_start_pfn + i];
- end_address = PAGE_ALIGN(end_address);
-
- stop_address = (unsigned long) &vmem_map[
- pgdat->node_start_pfn + pgdat->node_spanned_pages];
-
- do {
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
-
- pgd = pgd_offset_k(end_address);
- if (pgd_none(*pgd)) {
- end_address += PGDIR_SIZE;
- continue;
- }
-
- pud = pud_offset(pgd, end_address);
- if (pud_none(*pud)) {
- end_address += PUD_SIZE;
- continue;
- }
-
- pmd = pmd_offset(pud, end_address);
- if (pmd_none(*pmd)) {
- end_address += PMD_SIZE;
- continue;
- }
-
- pte = pte_offset_kernel(pmd, end_address);
-retry_pte:
- if (pte_none(*pte)) {
- end_address += PAGE_SIZE;
- pte++;
- if ((end_address < stop_address) &&
- (end_address != ALIGN(end_address, 1UL << PMD_SHIFT)))
- goto retry_pte;
- continue;
- }
- /* Found next valid vmem_map page */
- break;
- } while (end_address < stop_address);
-
- end_address = min(end_address, stop_address);
- end_address = end_address - (unsigned long) vmem_map + sizeof(struct page) - 1;
- hole_next_pfn = end_address / sizeof(struct page);
- return hole_next_pfn - pgdat->node_start_pfn;
-}
-#else
-static inline int find_next_valid_pfn_for_pgdat(pg_data_t *pgdat, int i)
-{
- return i + 1;
-}
-#endif
-
/**
* show_mem - give short summary of memory stats
*
@@ -625,7 +563,8 @@ void show_mem(void)
if (pfn_valid(pgdat->node_start_pfn + i))
page = pfn_to_page(pgdat->node_start_pfn + i);
else {
- i = find_next_valid_pfn_for_pgdat(pgdat, i) - 1;
+ i = vmemmap_find_next_valid_pfn(pgdat->node_id,
+ i) - 1;
continue;
}
if (PageReserved(page))
@@ -751,7 +690,8 @@ void __init paging_init(void)
efi_memmap_walk(filter_rsvd_memory, count_node_pages);
#ifdef CONFIG_VIRTUAL_MEM_MAP
- vmalloc_end -= PAGE_ALIGN(max_low_pfn * sizeof(struct page));
+ vmalloc_end -= PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) *
+ sizeof(struct page));
vmem_map = (struct page *) vmalloc_end;
efi_memmap_walk(create_mem_map_page_table, NULL);
printk("Virtual mem_map starts at 0x%p\n", vmem_map);
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 2f50c064513..30617ccb4f7 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -415,6 +415,61 @@ ia64_mmu_init (void *my_cpu_data)
}
#ifdef CONFIG_VIRTUAL_MEM_MAP
+int vmemmap_find_next_valid_pfn(int node, int i)
+{
+ unsigned long end_address, hole_next_pfn;
+ unsigned long stop_address;
+ pg_data_t *pgdat = NODE_DATA(node);
+
+ end_address = (unsigned long) &vmem_map[pgdat->node_start_pfn + i];
+ end_address = PAGE_ALIGN(end_address);
+
+ stop_address = (unsigned long) &vmem_map[
+ pgdat->node_start_pfn + pgdat->node_spanned_pages];
+
+ do {
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ pgd = pgd_offset_k(end_address);
+ if (pgd_none(*pgd)) {
+ end_address += PGDIR_SIZE;
+ continue;
+ }
+
+ pud = pud_offset(pgd, end_address);
+ if (pud_none(*pud)) {
+ end_address += PUD_SIZE;
+ continue;
+ }
+
+ pmd = pmd_offset(pud, end_address);
+ if (pmd_none(*pmd)) {
+ end_address += PMD_SIZE;
+ continue;
+ }
+
+ pte = pte_offset_kernel(pmd, end_address);
+retry_pte:
+ if (pte_none(*pte)) {
+ end_address += PAGE_SIZE;
+ pte++;
+ if ((end_address < stop_address) &&
+ (end_address != ALIGN(end_address, 1UL << PMD_SHIFT)))
+ goto retry_pte;
+ continue;
+ }
+ /* Found next valid vmem_map page */
+ break;
+ } while (end_address < stop_address);
+
+ end_address = min(end_address, stop_address);
+ end_address = end_address - (unsigned long) vmem_map + sizeof(struct page) - 1;
+ hole_next_pfn = end_address / sizeof(struct page);
+ return hole_next_pfn - pgdat->node_start_pfn;
+}
int __init
create_mem_map_page_table (u64 start, u64 end, void *arg)
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c
index 07bd02b6c37..4280c074d64 100644
--- a/arch/ia64/mm/ioremap.c
+++ b/arch/ia64/mm/ioremap.c
@@ -32,7 +32,7 @@ ioremap (unsigned long offset, unsigned long size)
*/
attr = kern_mem_attribute(offset, size);
if (attr & EFI_MEMORY_WB)
- return phys_to_virt(offset);
+ return (void __iomem *) phys_to_virt(offset);
else if (attr & EFI_MEMORY_UC)
return __ioremap(offset, size);
@@ -43,7 +43,7 @@ ioremap (unsigned long offset, unsigned long size)
gran_base = GRANULEROUNDDOWN(offset);
gran_size = GRANULEROUNDUP(offset + size) - gran_base;
if (efi_mem_attribute(gran_base, gran_size) & EFI_MEMORY_WB)
- return phys_to_virt(offset);
+ return (void __iomem *) phys_to_virt(offset);
return __ioremap(offset, size);
}
@@ -53,7 +53,7 @@ void __iomem *
ioremap_nocache (unsigned long offset, unsigned long size)
{
if (kern_mem_attribute(offset, size) & EFI_MEMORY_WB)
- return 0;
+ return NULL;
return __ioremap(offset, size);
}
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index 99b123a6421..5e8e59efb34 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -480,7 +480,7 @@ xpc_activating(void *__partid)
partid_t partid = (u64) __partid;
struct xpc_partition *part = &xpc_partitions[partid];
unsigned long irq_flags;
- struct sched_param param = { sched_priority: MAX_RT_PRIO - 1 };
+ struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
int ret;
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index 17cd3428488..af7171adcd2 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -74,7 +74,7 @@ tioce_mmr_war_pre(struct tioce_kernel *kern, void *mmr_addr)
else
mmr_war_offset = 0x158;
- readq_relaxed((void *)(mmr_base + mmr_war_offset));
+ readq_relaxed((void __iomem *)(mmr_base + mmr_war_offset));
}
}
@@ -92,8 +92,8 @@ tioce_mmr_war_post(struct tioce_kernel *kern, void *mmr_addr)
if (mmr_offset < 0x45000) {
if (mmr_offset == 0x100)
- readq_relaxed((void *)(mmr_base + 0x38));
- readq_relaxed((void *)(mmr_base + 0xb050));
+ readq_relaxed((void __iomem *)(mmr_base + 0x38));
+ readq_relaxed((void __iomem *)(mmr_base + 0xb050));
}
}
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 9989495a51d..b3677fc8eef 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -204,6 +204,7 @@ SECTIONS
*(.dynstr)
*(.dynamic)
*(.hash)
+ *(.gnu.hash)
#endif
}
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 2643dbc3f28..13e583f16ed 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -504,7 +504,7 @@ config CPU_FREQ_PMAC
config CPU_FREQ_PMAC64
bool "Support for some Apple G5s"
- depends on CPU_FREQ && PMAC_SMU && PPC64
+ depends on CPU_FREQ && PPC64
select CPU_FREQ_TABLE
help
This adds support for frequency switching on Apple iMac G5,
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
index addc79381c3..3545af9896a 100644
--- a/arch/powerpc/configs/pmac32_defconfig
+++ b/arch/powerpc/configs/pmac32_defconfig
@@ -1,16 +1,18 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc5
-# Mon May 29 14:47:49 2006
+# Linux kernel version: 2.6.17
+# Mon Jul 3 14:20:49 2006
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
CONFIG_PPC_MERGE=y
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
@@ -29,6 +31,7 @@ CONFIG_CLASSIC32=y
# CONFIG_PPC_82xx is not set
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
# CONFIG_8xx is not set
@@ -39,6 +42,7 @@ CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
# CONFIG_SMP is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
# Code maturity level options
@@ -72,10 +76,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -119,6 +125,9 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_APUS is not set
# CONFIG_PPC_CHRP is not set
CONFIG_PPC_PMAC=y
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_UDBG_RTAS_CONSOLE is not set
CONFIG_MPIC=y
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
@@ -154,6 +163,7 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# CONFIG_KEXEC is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -164,6 +174,7 @@ CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
CONFIG_PM=y
@@ -182,6 +193,7 @@ CONFIG_GENERIC_ISA_DMA=y
CONFIG_PPC_INDIRECT_PCI=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
# CONFIG_PCI_DEBUG is not set
#
@@ -256,6 +268,8 @@ CONFIG_INET_ESP=y
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -268,6 +282,7 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -292,9 +307,11 @@ CONFIG_NETFILTER_XT_MATCH_MARK=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
CONFIG_NETFILTER_XT_MATCH_REALM=m
CONFIG_NETFILTER_XT_MATCH_SCTP=m
CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
CONFIG_NETFILTER_XT_MATCH_STRING=m
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
@@ -313,6 +330,7 @@ CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
CONFIG_IP_NF_PPTP=m
CONFIG_IP_NF_H323=m
+# CONFIG_IP_NF_SIP is not set
# CONFIG_IP_NF_QUEUE is not set
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_IPRANGE=m
@@ -457,6 +475,7 @@ CONFIG_IRTTY_SIR=m
# CONFIG_ALI_FIR is not set
# CONFIG_VLSI_FIR is not set
# CONFIG_VIA_FIR is not set
+# CONFIG_MCS_FIR is not set
CONFIG_BT=m
CONFIG_BT_L2CAP=m
CONFIG_BT_SCO=m
@@ -500,6 +519,7 @@ CONFIG_WIRELESS_EXT=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
@@ -600,7 +620,6 @@ CONFIG_BLK_DEV_PDC202XX_NEW=y
CONFIG_BLK_DEV_IDE_PMAC=y
CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
CONFIG_BLK_DEV_IDEDMA_PMAC=y
-CONFIG_BLK_DEV_IDE_PMAC_BLINK=y
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
@@ -661,6 +680,7 @@ CONFIG_SCSI_AIC7XXX_OLD=m
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
@@ -705,9 +725,7 @@ CONFIG_MD_LINEAR=m
CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
CONFIG_MD_RAID10=m
-CONFIG_MD_RAID5=m
-CONFIG_MD_RAID5_RESHAPE=y
-CONFIG_MD_RAID6=m
+# CONFIG_MD_RAID456 is not set
CONFIG_MD_MULTIPATH=m
CONFIG_MD_FAULTY=m
CONFIG_BLK_DEV_DM=m
@@ -750,7 +768,6 @@ CONFIG_IEEE1394_OHCI1394=m
#
CONFIG_IEEE1394_VIDEO1394=m
CONFIG_IEEE1394_SBP2=m
-# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
# CONFIG_IEEE1394_ETH1394 is not set
CONFIG_IEEE1394_DV1394=m
CONFIG_IEEE1394_RAWIO=m
@@ -766,9 +783,12 @@ CONFIG_IEEE1394_RAWIO=m
CONFIG_ADB=y
CONFIG_ADB_CUDA=y
CONFIG_ADB_PMU=y
+CONFIG_ADB_PMU_LED=y
+CONFIG_ADB_PMU_LED_IDE=y
CONFIG_PMAC_APM_EMU=m
CONFIG_PMAC_MEDIABAY=y
CONFIG_PMAC_BACKLIGHT=y
+CONFIG_PMAC_BACKLIGHT_LEGACY=y
CONFIG_INPUT_ADBHID=y
CONFIG_MAC_EMUMOUSEBTN=y
CONFIG_THERM_WINDTUNNEL=m
@@ -858,6 +878,7 @@ CONFIG_PCNET32=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
#
# Token Ring devices
@@ -908,6 +929,7 @@ CONFIG_APPLE_AIRPORT=m
# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
#
CONFIG_PRISM54=m
+# CONFIG_USB_ZD1201 is not set
# CONFIG_HOSTAP is not set
CONFIG_NET_WIRELESS=y
@@ -998,6 +1020,7 @@ CONFIG_SERIO=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -1029,6 +1052,7 @@ CONFIG_LEGACY_PTY_COUNT=256
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
CONFIG_NVRAM=y
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
@@ -1040,6 +1064,7 @@ CONFIG_GEN_RTC=y
# Ftape, the floppy tape device driver
#
CONFIG_AGP=m
+# CONFIG_AGP_SIS is not set
# CONFIG_AGP_VIA is not set
CONFIG_AGP_UNINORTH=m
CONFIG_DRM=m
@@ -1092,6 +1117,7 @@ CONFIG_I2C_ALGOBIT=y
CONFIG_I2C_POWERMAC=y
# CONFIG_I2C_MPC is not set
# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
@@ -1156,12 +1182,13 @@ CONFIG_VIDEO_V4L2=y
#
# Graphics support
#
+# CONFIG_FIRMWARE_EDID is not set
CONFIG_FB=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
CONFIG_FB_MACMODES=y
-CONFIG_FB_FIRMWARE_EDID=y
+CONFIG_FB_BACKLIGHT=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_CIRRUS is not set
@@ -1178,6 +1205,7 @@ CONFIG_FB_IMSTT=y
# CONFIG_FB_S1D13XXX is not set
CONFIG_FB_NVIDIA=y
CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_NVIDIA_BACKLIGHT=y
# CONFIG_FB_RIVA is not set
CONFIG_FB_MATROX=y
CONFIG_FB_MATROX_MILLENIUM=y
@@ -1187,12 +1215,15 @@ CONFIG_FB_MATROX_MYSTIQUE=y
# CONFIG_FB_MATROX_MULTIHEAD is not set
CONFIG_FB_RADEON=y
CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
# CONFIG_FB_RADEON_DEBUG is not set
CONFIG_FB_ATY128=y
+CONFIG_FB_ATY128_BACKLIGHT=y
CONFIG_FB_ATY=y
CONFIG_FB_ATY_CT=y
# CONFIG_FB_ATY_GENERIC_LCD is not set
CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_BACKLIGHT=y
# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_NEOMAGIC is not set
@@ -1221,7 +1252,11 @@ CONFIG_LOGO=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
#
# Sound
@@ -1278,6 +1313,18 @@ CONFIG_SND_DUMMY=m
# CONFIG_SND_CMIPCI is not set
# CONFIG_SND_CS4281 is not set
# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
# CONFIG_SND_EMU10K1 is not set
# CONFIG_SND_EMU10K1X is not set
# CONFIG_SND_ENS1370 is not set
@@ -1315,6 +1362,17 @@ CONFIG_SND_POWERMAC=m
CONFIG_SND_POWERMAC_AUTO_DRC=y
#
+# Apple Onboard Audio driver
+#
+CONFIG_SND_AOA=m
+CONFIG_SND_AOA_FABRIC_LAYOUT=m
+CONFIG_SND_AOA_ONYX=m
+CONFIG_SND_AOA_TAS=m
+CONFIG_SND_AOA_TOONIE=m
+CONFIG_SND_AOA_SOUNDBUS=m
+CONFIG_SND_AOA_SOUNDBUS_I2S=m
+
+#
# USB devices
#
CONFIG_SND_USB_AUDIO=m
@@ -1355,6 +1413,7 @@ CONFIG_USB_DYNAMIC_MINORS=y
CONFIG_USB_EHCI_HCD=m
CONFIG_USB_EHCI_SPLIT_ISO=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
# CONFIG_USB_ISP116X_HCD is not set
CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_OHCI_BIG_ENDIAN is not set
@@ -1431,7 +1490,6 @@ CONFIG_USB_NET_NET1080=m
# CONFIG_USB_NET_RNDIS_HOST is not set
# CONFIG_USB_NET_CDC_SUBSET is not set
CONFIG_USB_NET_ZAURUS=m
-# CONFIG_USB_ZD1201 is not set
CONFIG_USB_MON=y
#
@@ -1499,10 +1557,12 @@ CONFIG_USB_EZUSB=y
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
# CONFIG_USB_LED is not set
+# CONFIG_USB_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
# CONFIG_USB_PHIDGETKIT is not set
# CONFIG_USB_PHIDGETSERVO is not set
# CONFIG_USB_IDMOUSE is not set
+CONFIG_USB_APPLEDISPLAY=m
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
# CONFIG_USB_TEST is not set
@@ -1524,7 +1584,8 @@ CONFIG_USB_EZUSB=y
#
# LED devices
#
-# CONFIG_NEW_LEDS is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
#
# LED drivers
@@ -1533,6 +1594,10 @@ CONFIG_USB_EZUSB=y
#
# LED Triggers
#
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
#
# InfiniBand support
@@ -1549,6 +1614,19 @@ CONFIG_USB_EZUSB=y
# CONFIG_RTC_CLASS is not set
#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1569,6 +1647,7 @@ CONFIG_FS_POSIX_ACL=y
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -1649,6 +1728,7 @@ CONFIG_RPCSEC_GSS_KRB5=y
CONFIG_SMB_FS=m
# CONFIG_SMB_NLS_DEFAULT is not set
# CONFIG_CIFS is not set
+# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -1732,6 +1812,7 @@ CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
#
# Instrumentation Support
@@ -1744,12 +1825,15 @@ CONFIG_OPROFILE=y
#
# CONFIG_PRINTK_TIME is not set
# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -1763,11 +1847,7 @@ CONFIG_XMON=y
CONFIG_XMON_DEFAULT=y
# CONFIG_BDI_SWITCH is not set
CONFIG_BOOTX_TEXT=y
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
#
# Security options
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index e16eb2a3317..6ff3cf50608 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -191,6 +191,37 @@ exception_marker:
ori reg,reg,(label)@l; /* virt addr of handler ... */
#endif
+/*
+ * Equal to EXCEPTION_PROLOG_PSERIES, except that it forces 64bit mode.
+ * The firmware calls the registered system_reset_fwnmi and
+ * machine_check_fwnmi handlers in 32bit mode if the cpu happens to run
+ * a 32bit application at the time of the event.
+ * This firmware bug is present on POWER4 and JS20.
+ */
+#define EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(area, label) \
+ mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
+ std r9,area+EX_R9(r13); /* save r9 - r12 */ \
+ std r10,area+EX_R10(r13); \
+ std r11,area+EX_R11(r13); \
+ std r12,area+EX_R12(r13); \
+ mfspr r9,SPRN_SPRG1; \
+ std r9,area+EX_R13(r13); \
+ mfcr r9; \
+ clrrdi r12,r13,32; /* get high part of &label */ \
+ mfmsr r10; \
+ /* force 64bit mode */ \
+ li r11,5; /* MSR_SF_LG|MSR_ISF_LG */ \
+ rldimi r10,r11,61,0; /* insert into top 3 bits */ \
+ /* done 64bit mode */ \
+ mfspr r11,SPRN_SRR0; /* save SRR0 */ \
+ LOAD_HANDLER(r12,label) \
+ ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \
+ mtspr SPRN_SRR0,r12; \
+ mfspr r12,SPRN_SRR1; /* and SRR1 */ \
+ mtspr SPRN_SRR1,r10; \
+ rfid; \
+ b . /* prevent speculative execution */
+
#define EXCEPTION_PROLOG_PSERIES(area, label) \
mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
std r9,area+EX_R9(r13); /* save r9 - r12 */ \
@@ -604,14 +635,14 @@ slb_miss_user_pseries:
system_reset_fwnmi:
HMT_MEDIUM
mtspr SPRN_SPRG1,r13 /* save r13 */
- EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
+ EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXGEN, system_reset_common)
.globl machine_check_fwnmi
.align 7
machine_check_fwnmi:
HMT_MEDIUM
mtspr SPRN_SPRG1,r13 /* save r13 */
- EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
+ EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXMC, machine_check_common)
#ifdef CONFIG_PPC_ISERIES
/*** ISeries-LPAR interrupt handlers ***/
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index 7e98e778b52..359ab89748e 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -112,7 +112,7 @@ static int __init add_legacy_port(struct device_node *np, int want_index,
static int __init add_legacy_soc_port(struct device_node *np,
struct device_node *soc_dev)
{
- phys_addr_t addr;
+ u64 addr;
u32 *addrp;
upf_t flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
@@ -143,7 +143,7 @@ static int __init add_legacy_isa_port(struct device_node *np,
u32 *reg;
char *typep;
int index = -1;
- phys_addr_t taddr;
+ u64 taddr;
DBG(" -> add_legacy_isa_port(%s)\n", np->full_name);
@@ -165,10 +165,13 @@ static int __init add_legacy_isa_port(struct device_node *np,
if (typep && *typep == 'S')
index = simple_strtol(typep+1, NULL, 0) - 1;
- /* Translate ISA address */
+ /* Translate ISA address. If it fails, we still register the port
+ * with no translated address so that it can be picked up as an IO
+ * port later by the serial driver
+ */
taddr = of_translate_address(np, reg);
if (taddr == OF_BAD_ADDR)
- return -1;
+ taddr = 0;
/* Add port, irq will be dealt with later */
return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr,
@@ -180,7 +183,7 @@ static int __init add_legacy_isa_port(struct device_node *np,
static int __init add_legacy_pci_port(struct device_node *np,
struct device_node *pci_dev)
{
- phys_addr_t addr, base;
+ u64 addr, base;
u32 *addrp;
unsigned int flags;
int iotype, index = -1, lindex = 0;
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index bfb407fc1aa..e3ed21cd3d9 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -687,7 +687,7 @@ _GLOBAL(kexec_sequence)
/* clear out hardware hash page table and tlb */
ld r5,0(r27) /* deref function descriptor */
mtctr r5
- bctrl /* ppc_md.hash_clear_all(void); */
+ bctrl /* ppc_md.hpte_clear_all(void); */
/*
* kexec image calling is:
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index ebd501a59ab..462bced40c1 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -557,7 +557,9 @@ unsigned long prom_memparse(const char *ptr, const char **retptr)
static void __init early_cmdline_parse(void)
{
struct prom_t *_prom = &RELOC(prom);
+#ifdef CONFIG_PPC64
const char *opt;
+#endif
char *p;
int l = 0;
@@ -2030,6 +2032,39 @@ static void __init fixup_device_tree_maple(void)
#define fixup_device_tree_maple()
#endif
+#ifdef CONFIG_PPC_CHRP
+/* Pegasos lacks the "ranges" property in the isa node */
+static void __init fixup_device_tree_chrp(void)
+{
+ phandle isa;
+ u32 isa_ranges[6];
+ char *name;
+ int rc;
+
+ name = "/pci@80000000/isa@c";
+ isa = call_prom("finddevice", 1, 1, ADDR(name));
+ if (!PHANDLE_VALID(isa))
+ return;
+
+ rc = prom_getproplen(isa, "ranges");
+ if (rc != 0 && rc != PROM_ERROR)
+ return;
+
+ prom_printf("Fixing up missing ISA range on Pegasos...\n");
+
+ isa_ranges[0] = 0x1;
+ isa_ranges[1] = 0x0;
+ isa_ranges[2] = 0x01006000;
+ isa_ranges[3] = 0x0;
+ isa_ranges[4] = 0x0;
+ isa_ranges[5] = 0x00010000;
+ prom_setprop(isa, name, "ranges",
+ isa_ranges, sizeof(isa_ranges));
+}
+#else
+#define fixup_device_tree_chrp()
+#endif
+
#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
static void __init fixup_device_tree_pmac(void)
{
@@ -2077,6 +2112,7 @@ static void __init fixup_device_tree_pmac(void)
static void __init fixup_device_tree(void)
{
fixup_device_tree_maple();
+ fixup_device_tree_chrp();
fixup_device_tree_pmac();
}
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 46c56cfd1b2..6a9bc9ce54e 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -144,13 +144,15 @@ void smp_message_recv(int msg, struct pt_regs *regs)
void smp_send_reschedule(int cpu)
{
- smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE);
+ if (likely(smp_ops))
+ smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE);
}
#ifdef CONFIG_DEBUGGER
void smp_send_debugger_break(int cpu)
{
- smp_ops->message_pass(cpu, PPC_MSG_DEBUGGER_BREAK);
+ if (likely(smp_ops))
+ smp_ops->message_pass(cpu, PPC_MSG_DEBUGGER_BREAK);
}
#endif
@@ -158,7 +160,7 @@ void smp_send_debugger_break(int cpu)
void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *))
{
crash_ipi_function_ptr = crash_ipi_callback;
- if (crash_ipi_callback) {
+ if (crash_ipi_callback && smp_ops) {
mb();
smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_DEBUGGER_BREAK);
}
@@ -220,6 +222,9 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
/* Can deadlock when called with interrupts disabled */
WARN_ON(irqs_disabled());
+ if (unlikely(smp_ops == NULL))
+ return -1;
+
data.func = func;
data.info = info;
atomic_set(&data.started, 0);
@@ -357,7 +362,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
smp_store_cpu_info(boot_cpuid);
cpu_callin_map[boot_cpuid] = 1;
- max_cpus = smp_ops->probe();
+ if (smp_ops)
+ max_cpus = smp_ops->probe();
+ else
+ max_cpus = 1;
smp_space_timers(max_cpus);
@@ -453,7 +461,7 @@ void generic_mach_cpu_die(void)
static int __devinit cpu_enable(unsigned int cpu)
{
- if (smp_ops->cpu_enable)
+ if (smp_ops && smp_ops->cpu_enable)
return smp_ops->cpu_enable(cpu);
return -ENOSYS;
@@ -467,7 +475,8 @@ int __devinit __cpu_up(unsigned int cpu)
if (!cpu_enable(cpu))
return 0;
- if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))
+ if (smp_ops == NULL ||
+ (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)))
return -EINVAL;
/* Make sure callin-map entry is 0 (can be leftover a CPU
@@ -568,7 +577,8 @@ void __init smp_cpus_done(unsigned int max_cpus)
old_mask = current->cpus_allowed;
set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid));
- smp_ops->setup_cpu(boot_cpuid);
+ if (smp_ops)
+ smp_ops->setup_cpu(boot_cpuid);
set_cpus_allowed(current, old_mask);
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 01043509555..fec228cd016 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -278,7 +278,7 @@ static void unregister_cpu_online(unsigned int cpu)
}
#endif /* CONFIG_HOTPLUG_CPU */
-static int __devinit sysfs_cpu_notify(struct notifier_block *self,
+static int __cpuinit sysfs_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned int)(long)hcpu;
@@ -296,7 +296,7 @@ static int __devinit sysfs_cpu_notify(struct notifier_block *self,
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata sysfs_cpu_nb = {
+static struct notifier_block __cpuinitdata sysfs_cpu_nb = {
.notifier_call = sysfs_cpu_notify,
};
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 3c668078e52..2105767fcc5 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -150,13 +150,9 @@ int die(const char *str, struct pt_regs *regs, long err)
if (in_interrupt())
panic("Fatal exception in interrupt");
- if (panic_on_oops) {
-#ifdef CONFIG_PPC64
- printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
- ssleep(5);
-#endif
- panic("Fatal exception");
- }
+ if (panic_on_oops)
+ panic("Fatal exception: panic_on_oops");
+
do_exit(err);
return 0;
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c
index 0835b4841de..2d17f2b8eda 100644
--- a/arch/powerpc/kernel/udbg_16550.c
+++ b/arch/powerpc/kernel/udbg_16550.c
@@ -81,10 +81,14 @@ static int udbg_550_getc(void)
void udbg_init_uart(void __iomem *comport, unsigned int speed,
unsigned int clock)
{
- unsigned int dll, base_bauds = clock / 16;
+ unsigned int dll, base_bauds;
+ if (clock == 0)
+ clock = 1843200;
if (speed == 0)
speed = 9600;
+
+ base_bauds = clock / 16;
dll = base_bauds / speed;
if (comport) {
diff --git a/arch/powerpc/kernel/vdso32/Makefile b/arch/powerpc/kernel/vdso32/Makefile
index 8a3bed5f143..3726358faae 100644
--- a/arch/powerpc/kernel/vdso32/Makefile
+++ b/arch/powerpc/kernel/vdso32/Makefile
@@ -14,7 +14,8 @@ obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32))
EXTRA_CFLAGS := -shared -s -fno-common -fno-builtin
-EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso32.so.1
+EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso32.so.1 \
+ $(call ld-option, -Wl$(comma)--hash-style=sysv)
EXTRA_AFLAGS := -D__VDSO32__ -s
obj-y += vdso32_wrapper.o
diff --git a/arch/powerpc/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S
index f4bad720cb0..6187af2d54c 100644
--- a/arch/powerpc/kernel/vdso32/vdso32.lds.S
+++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S
@@ -14,6 +14,7 @@ SECTIONS
{
. = VDSO32_LBASE + SIZEOF_HEADERS;
.hash : { *(.hash) } :text
+ .gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
diff --git a/arch/powerpc/kernel/vdso64/Makefile b/arch/powerpc/kernel/vdso64/Makefile
index ab39988452c..43af9b2a6f3 100644
--- a/arch/powerpc/kernel/vdso64/Makefile
+++ b/arch/powerpc/kernel/vdso64/Makefile
@@ -8,7 +8,8 @@ targets := $(obj-vdso64) vdso64.so
obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64))
EXTRA_CFLAGS := -shared -s -fno-common -fno-builtin
-EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso64.so.1
+EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso64.so.1 \
+ $(call ld-option, -Wl$(comma)--hash-style=sysv)
EXTRA_AFLAGS := -D__VDSO64__ -s
obj-y += vdso64_wrapper.o
diff --git a/arch/powerpc/kernel/vdso64/vdso64.lds.S b/arch/powerpc/kernel/vdso64/vdso64.lds.S
index 4bdf224464a..4a2b6dc0960 100644
--- a/arch/powerpc/kernel/vdso64/vdso64.lds.S
+++ b/arch/powerpc/kernel/vdso64/vdso64.lds.S
@@ -12,6 +12,7 @@ SECTIONS
{
. = VDSO64_LBASE + SIZEOF_HEADERS;
.hash : { *(.hash) } :text
+ .gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c
index 4b17a735992..716a2906a24 100644
--- a/arch/powerpc/mm/lmb.c
+++ b/arch/powerpc/mm/lmb.c
@@ -320,7 +320,8 @@ void __init lmb_enforce_memory_limit(unsigned long memory_limit)
break;
}
- lmb.rmo_size = lmb.memory.region[0].size;
+ if (lmb.memory.region[0].size < lmb.rmo_size)
+ lmb.rmo_size = lmb.memory.region[0].size;
/* And truncate any reserves above the limit also. */
for (i = 0; i < lmb.reserved.cnt; i++) {
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 538e337d63e..9c08ff32229 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -291,10 +291,6 @@ void __init chrp_setup_arch(void)
pci_create_OF_bus_map();
-#ifdef CONFIG_SMP
- smp_ops = &chrp_smp_ops;
-#endif /* CONFIG_SMP */
-
/*
* Print the banner, then scroll down so boot progress
* can be printed. -- Cort
@@ -479,6 +475,14 @@ void __init chrp_init_IRQ(void)
chrp_find_openpic();
chrp_find_8259();
+#ifdef CONFIG_SMP
+ /* Pegasos has no MPIC, those ops would make it crash. It might be an
+ * option to move setting them to after we probe the PIC though
+ */
+ if (chrp_mpic != NULL)
+ smp_ops = &chrp_smp_ops;
+#endif /* CONFIG_SMP */
+
if (_chrp_type == _CHRP_Pegasos)
ppc_md.get_irq = i8259_irq;
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index cb528c9de4c..57567dfb981 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -221,10 +221,17 @@ static void __init maple_init_IRQ(void)
* in Maple device-tree where the type of the controller is
* open-pic and not interrupt-controller
*/
- for_each_node_by_type(np, "open-pic") {
- mpic_node = np;
- break;
- }
+
+ for_each_node_by_type(np, "interrupt-controller")
+ if (device_is_compatible(np, "open-pic")) {
+ mpic_node = np;
+ break;
+ }
+ if (mpic_node == NULL)
+ for_each_node_by_type(np, "open-pic") {
+ mpic_node = np;
+ break;
+ }
if (mpic_node == NULL) {
printk(KERN_ERR
"Failed to locate the MPIC interrupt controller\n");
@@ -252,6 +259,8 @@ static void __init maple_init_IRQ(void)
/* XXX Maple specific bits */
flags |= MPIC_BROKEN_U3 | MPIC_WANTS_RESET;
+ /* All U3/U4 are big-endian, older SLOF firmware doesn't encode this */
+ flags |= MPIC_BIG_ENDIAN;
/* Setup the openpic driver. More device-tree junks, we hard code no
* ISUs for now. I'll have to revisit some stuffs with the folks doing
diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c
index 74eed6b74cd..d6641549105 100644
--- a/arch/powerpc/platforms/powermac/backlight.c
+++ b/arch/powerpc/platforms/powermac/backlight.c
@@ -10,19 +10,32 @@
#include <linux/kernel.h>
#include <linux/fb.h>
#include <linux/backlight.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <asm/atomic.h>
#include <asm/prom.h>
#include <asm/backlight.h>
#define OLD_BACKLIGHT_MAX 15
static void pmac_backlight_key_worker(void *data);
+static void pmac_backlight_set_legacy_worker(void *data);
+
static DECLARE_WORK(pmac_backlight_key_work, pmac_backlight_key_worker, NULL);
+static DECLARE_WORK(pmac_backlight_set_legacy_work, pmac_backlight_set_legacy_worker, NULL);
-/* Although this variable is used in interrupt context, it makes no sense to
- * protect it. No user is able to produce enough key events per second and
+/* Although these variables are used in interrupt context, it makes no sense to
+ * protect them. No user is able to produce enough key events per second and
* notice the errors that might happen.
*/
static int pmac_backlight_key_queued;
+static int pmac_backlight_set_legacy_queued;
+
+/* The via-pmu code allows the backlight to be grabbed, in which case the
+ * in-kernel control of the brightness needs to be disabled. This should
+ * only be used by really old PowerBooks.
+ */
+static atomic_t kernel_backlight_disabled = ATOMIC_INIT(0);
/* Protect the pmac_backlight variable */
DEFINE_MUTEX(pmac_backlight_mutex);
@@ -82,6 +95,9 @@ int pmac_backlight_curve_lookup(struct fb_info *info, int value)
static void pmac_backlight_key_worker(void *data)
{
+ if (atomic_read(&kernel_backlight_disabled))
+ return;
+
mutex_lock(&pmac_backlight_mutex);
if (pmac_backlight) {
struct backlight_properties *props;
@@ -107,8 +123,12 @@ static void pmac_backlight_key_worker(void *data)
mutex_unlock(&pmac_backlight_mutex);
}
+/* This function is called in interrupt context */
void pmac_backlight_key(int direction)
{
+ if (atomic_read(&kernel_backlight_disabled))
+ return;
+
/* we can receive multiple interrupts here, but the scheduled work
* will run only once, with the last value
*/
@@ -116,7 +136,7 @@ void pmac_backlight_key(int direction)
schedule_work(&pmac_backlight_key_work);
}
-int pmac_backlight_set_legacy_brightness(int brightness)
+static int __pmac_backlight_set_legacy_brightness(int brightness)
{
int error = -ENXIO;
@@ -145,6 +165,28 @@ int pmac_backlight_set_legacy_brightness(int brightness)
return error;
}
+static void pmac_backlight_set_legacy_worker(void *data)
+{
+ if (atomic_read(&kernel_backlight_disabled))
+ return;
+
+ __pmac_backlight_set_legacy_brightness(pmac_backlight_set_legacy_queued);
+}
+
+/* This function is called in interrupt context */
+void pmac_backlight_set_legacy_brightness_pmu(int brightness) {
+ if (atomic_read(&kernel_backlight_disabled))
+ return;
+
+ pmac_backlight_set_legacy_queued = brightness;
+ schedule_work(&pmac_backlight_set_legacy_work);
+}
+
+int pmac_backlight_set_legacy_brightness(int brightness)
+{
+ return __pmac_backlight_set_legacy_brightness(brightness);
+}
+
int pmac_backlight_get_legacy_brightness()
{
int result = -ENXIO;
@@ -167,6 +209,16 @@ int pmac_backlight_get_legacy_brightness()
return result;
}
+void pmac_backlight_disable()
+{
+ atomic_inc(&kernel_backlight_disabled);
+}
+
+void pmac_backlight_enable()
+{
+ atomic_dec(&kernel_backlight_disabled);
+}
+
EXPORT_SYMBOL_GPL(pmac_backlight);
EXPORT_SYMBOL_GPL(pmac_backlight_mutex);
EXPORT_SYMBOL_GPL(pmac_has_backlight_type);
diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c
index 871b002c9f9..6a026c733f6 100644
--- a/arch/powerpc/platforms/powermac/bootx_init.c
+++ b/arch/powerpc/platforms/powermac/bootx_init.c
@@ -181,13 +181,18 @@ static void __init bootx_add_chosen_props(unsigned long base,
}
static void __init bootx_add_display_props(unsigned long base,
- unsigned long *mem_end)
+ unsigned long *mem_end,
+ int has_real_node)
{
boot_infos_t *bi = bootx_info;
u32 tmp;
- bootx_dt_add_prop("linux,boot-display", NULL, 0, mem_end);
- bootx_dt_add_prop("linux,opened", NULL, 0, mem_end);
+ if (has_real_node) {
+ bootx_dt_add_prop("linux,boot-display", NULL, 0, mem_end);
+ bootx_dt_add_prop("linux,opened", NULL, 0, mem_end);
+ } else
+ bootx_dt_add_prop("linux,bootx-noscreen", NULL, 0, mem_end);
+
tmp = bi->dispDeviceDepth;
bootx_dt_add_prop("linux,bootx-depth", &tmp, 4, mem_end);
tmp = bi->dispDeviceRect[2] - bi->dispDeviceRect[0];
@@ -241,11 +246,6 @@ static void __init bootx_scan_dt_build_strings(unsigned long base,
DBG(" detected display ! adding properties names !\n");
bootx_dt_add_string("linux,boot-display", mem_end);
bootx_dt_add_string("linux,opened", mem_end);
- bootx_dt_add_string("linux,bootx-depth", mem_end);
- bootx_dt_add_string("linux,bootx-width", mem_end);
- bootx_dt_add_string("linux,bootx-height", mem_end);
- bootx_dt_add_string("linux,bootx-linebytes", mem_end);
- bootx_dt_add_string("linux,bootx-addr", mem_end);
strncpy(bootx_disp_path, namep, 255);
}
@@ -329,10 +329,13 @@ static void __init bootx_scan_dt_build_struct(unsigned long base,
ppp = &pp->next;
}
- if (node == bootx_node_chosen)
+ if (node == bootx_node_chosen) {
bootx_add_chosen_props(base, mem_end);
- if (node == bootx_info->dispDeviceRegEntryOffset)
- bootx_add_display_props(base, mem_end);
+ if (bootx_info->dispDeviceRegEntryOffset == 0)
+ bootx_add_display_props(base, mem_end, 0);
+ }
+ else if (node == bootx_info->dispDeviceRegEntryOffset)
+ bootx_add_display_props(base, mem_end, 1);
/* do all our children */
cpp = &np->child;
@@ -374,6 +377,14 @@ static unsigned long __init bootx_flatten_dt(unsigned long start)
mem_end += 4;
bootx_dt_strend = mem_end;
bootx_scan_dt_build_strings(base, 4, &mem_end);
+ /* Add some strings */
+ bootx_dt_add_string("linux,bootx-noscreen", &mem_end);
+ bootx_dt_add_string("linux,bootx-depth", &mem_end);
+ bootx_dt_add_string("linux,bootx-width", &mem_end);
+ bootx_dt_add_string("linux,bootx-height", &mem_end);
+ bootx_dt_add_string("linux,bootx-linebytes", &mem_end);
+ bootx_dt_add_string("linux,bootx-addr", &mem_end);
+ /* Wrap up strings */
hdr->off_dt_strings = bootx_dt_strbase - mem_start;
hdr->dt_strings_size = bootx_dt_strend - bootx_dt_strbase;
@@ -471,6 +482,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4)
if (bi->dispDeviceDepth == 16)
bi->dispDeviceDepth = 15;
+
#ifdef CONFIG_BOOTX_TEXT
ptr = (unsigned long)bi->logicalDisplayBase;
ptr += bi->dispDeviceRect[1] * bi->dispDeviceRowBytes;
@@ -508,6 +520,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4)
#ifdef CONFIG_BOOTX_TEXT
btext_welcome(bi);
#endif
+
/* New BootX enters kernel with MMU off, i/os are not allowed
* here. This hack will have been done by the boostrap anyway.
*/
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c
index f08a1451613..7b1156ea534 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_64.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_64.c
@@ -10,6 +10,8 @@
* that is iMac G5 and latest single CPU desktop.
*/
+#undef DEBUG
+
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
@@ -30,13 +32,7 @@
#include <asm/smu.h>
#include <asm/pmac_pfunc.h>
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(fmt...) printk(fmt)
-#else
-#define DBG(fmt...)
-#endif
+#define DBG(fmt...) pr_debug(fmt)
/* see 970FX user manual */
@@ -82,8 +78,6 @@ static struct freq_attr* g5_cpu_freqs_attr[] = {
/* Power mode data is an array of the 32 bits PCR values to use for
* the various frequencies, retrieved from the device-tree
*/
-static u32 *g5_pmode_data;
-static int g5_pmode_max;
static int g5_pmode_cur;
static void (*g5_switch_volt)(int speed_mode);
@@ -93,6 +87,11 @@ static int (*g5_query_freq)(void);
static DEFINE_MUTEX(g5_switch_mutex);
+#ifdef CONFIG_PMAC_SMU
+
+static u32 *g5_pmode_data;
+static int g5_pmode_max;
+
static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */
static int g5_fvt_count; /* number of op. points */
static int g5_fvt_cur; /* current op. point */
@@ -210,6 +209,16 @@ static int g5_scom_query_freq(void)
}
/*
+ * Fake voltage switching for platforms with missing support
+ */
+
+static void g5_dummy_switch_volt(int speed_mode)
+{
+}
+
+#endif /* CONFIG_PMAC_SMU */
+
+/*
* Platform function based voltage switching for PowerMac7,2 & 7,3
*/
@@ -248,6 +257,9 @@ static int g5_pfunc_switch_freq(int speed_mode)
struct pmf_args args;
u32 done = 0;
unsigned long timeout;
+ int rc;
+
+ DBG("g5_pfunc_switch_freq(%d)\n", speed_mode);
/* If frequency is going up, first ramp up the voltage */
if (speed_mode < g5_pmode_cur)
@@ -255,9 +267,12 @@ static int g5_pfunc_switch_freq(int speed_mode)
/* Do it */
if (speed_mode == CPUFREQ_HIGH)
- pmf_call_one(pfunc_cpu_setfreq_high, NULL);
+ rc = pmf_call_one(pfunc_cpu_setfreq_high, NULL);
else
- pmf_call_one(pfunc_cpu_setfreq_low, NULL);
+ rc = pmf_call_one(pfunc_cpu_setfreq_low, NULL);
+
+ if (rc)
+ printk(KERN_WARNING "cpufreq: pfunc switch error %d\n", rc);
/* It's an irq GPIO so we should be able to just block here,
* I'll do that later after I've properly tested the IRQ code for
@@ -296,13 +311,6 @@ static int g5_pfunc_query_freq(void)
return val ? CPUFREQ_HIGH : CPUFREQ_LOW;
}
-/*
- * Fake voltage switching for platforms with missing support
- */
-
-static void g5_dummy_switch_volt(int speed_mode)
-{
-}
/*
* Common interface to the cpufreq core
@@ -375,6 +383,8 @@ static struct cpufreq_driver g5_cpufreq_driver = {
};
+#ifdef CONFIG_PMAC_SMU
+
static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
{
struct device_node *cpunode;
@@ -525,6 +535,9 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
return rc;
}
+#endif /* CONFIG_PMAC_SMU */
+
+
static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
{
struct device_node *cpuid = NULL, *hwclock = NULL, *cpunode = NULL;
@@ -533,6 +546,9 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
u64 max_freq, min_freq, ih, il;
int has_volt = 1, rc = 0;
+ DBG("cpufreq: Initializing for PowerMac7,2, PowerMac7,3 and"
+ " RackMac3,1...\n");
+
/* Get first CPU node */
for (cpunode = NULL;
(cpunode = of_get_next_child(cpus, cpunode)) != NULL;) {
@@ -636,6 +652,15 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
*/
ih = *((u32 *)(eeprom + 0x10));
il = *((u32 *)(eeprom + 0x20));
+
+ /* Check for machines with no useful settings */
+ if (il == ih) {
+ printk(KERN_WARNING "cpufreq: No low frequency mode available"
+ " on this model !\n");
+ rc = -ENODEV;
+ goto bail;
+ }
+
min_freq = 0;
if (ih != 0 && il != 0)
min_freq = (max_freq * il) / ih;
@@ -643,7 +668,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
/* Sanity check */
if (min_freq >= max_freq || min_freq < 1000) {
printk(KERN_ERR "cpufreq: Can't calculate low frequency !\n");
- rc = -ENODEV;
+ rc = -ENXIO;
goto bail;
}
g5_cpu_freqs[0].frequency = max_freq;
@@ -690,16 +715,10 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
return rc;
}
-static int __init g5_rm31_cpufreq_init(struct device_node *cpus)
-{
- /* NYI */
- return 0;
-}
-
static int __init g5_cpufreq_init(void)
{
struct device_node *cpus;
- int rc;
+ int rc = 0;
cpus = of_find_node_by_path("/cpus");
if (cpus == NULL) {
@@ -708,12 +727,13 @@ static int __init g5_cpufreq_init(void)
}
if (machine_is_compatible("PowerMac7,2") ||
- machine_is_compatible("PowerMac7,3"))
+ machine_is_compatible("PowerMac7,3") ||
+ machine_is_compatible("RackMac3,1"))
rc = g5_pm72_cpufreq_init(cpus);
- else if (machine_is_compatible("RackMac3,1"))
- rc = g5_rm31_cpufreq_init(cpus);
+#ifdef CONFIG_PMAC_SMU
else
rc = g5_neo2_cpufreq_init(cpus);
+#endif /* CONFIG_PMAC_SMU */
of_node_put(cpus);
return rc;
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 54a52437265..71c634e0b87 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -501,7 +501,8 @@ static void pseries_dedicated_idle_sleep(void)
}
/*
- * Cede if the other thread is not idle, so that it can
+ * If not SMT, cede processor. If CPU is running SMT
+ * cede if the other thread is not idle, so that it can
* go single-threaded. If the other thread is idle,
* we ask the hypervisor if it has pending work it
* wants to do and cede if it does. Otherwise we keep
@@ -514,7 +515,8 @@ static void pseries_dedicated_idle_sleep(void)
* very low priority. The cede enables interrupts, which
* doesn't matter here.
*/
- if (!lppaca[cpu ^ 1].idle || poll_pending() == H_PENDING)
+ if (!cpu_has_feature(CPU_FTR_SMT) || !lppaca[cpu ^ 1].idle
+ || poll_pending() == H_PENDING)
cede_processor();
out:
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
index 09c6525cfa6..095fd332332 100644
--- a/arch/ppc/kernel/vmlinux.lds.S
+++ b/arch/ppc/kernel/vmlinux.lds.S
@@ -8,6 +8,7 @@ SECTIONS
. = + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.rel.text : { *(.rel.text) }
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index d0f82c995af..6a4b5f9715c 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -617,7 +617,8 @@ appldata_offline_cpu(int cpu)
spin_unlock(&appldata_timer_lock);
}
-static int __cpuinit
+#ifdef CONFIG_HOTPLUG_CPU
+static int
appldata_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
@@ -625,20 +626,19 @@ appldata_cpu_notify(struct notifier_block *self,
case CPU_ONLINE:
appldata_online_cpu((long) hcpu);
break;
-#ifdef CONFIG_HOTPLUG_CPU
case CPU_DEAD:
appldata_offline_cpu((long) hcpu);
break;
-#endif
default:
break;
}
return NOTIFY_OK;
}
-static struct notifier_block __devinitdata appldata_nb = {
+static struct notifier_block appldata_nb = {
.notifier_call = appldata_cpu_notify,
};
+#endif
/*
* appldata_init()
@@ -662,7 +662,7 @@ static int __init appldata_init(void)
appldata_online_cpu(i);
/* Register cpu hotplug notifier */
- register_cpu_notifier(&appldata_nb);
+ register_hotcpu_notifier(&appldata_nb);
appldata_sysctl_header = register_sysctl_table(appldata_dir_table, 1);
#ifdef MODULE
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index f4dfc10026d..f1d4591eddb 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,13 +1,16 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc1
-# Mon Apr 3 14:34:15 2006
+# Linux kernel version: 2.6.18-rc2
+# Thu Jul 27 13:51:07 2006
#
CONFIG_MMU=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_S390=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
# Code maturity level options
@@ -25,6 +28,7 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
CONFIG_SYSCTL=y
CONFIG_AUDIT=y
# CONFIG_AUDITSYSCALL is not set
@@ -43,10 +47,12 @@ CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -94,7 +100,6 @@ CONFIG_HOTPLUG_CPU=y
CONFIG_DEFAULT_MIGRATION_COST=1000000
CONFIG_COMPAT=y
CONFIG_SYSVIPC_COMPAT=y
-CONFIG_BINFMT_ELF32=y
#
# Code generation options
@@ -115,6 +120,7 @@ CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
#
# I/O subsystem configuration
@@ -142,6 +148,7 @@ CONFIG_VIRT_CPU_ACCOUNTING=y
# CONFIG_APPLDATA_BASE is not set
CONFIG_NO_IDLE_HZ=y
CONFIG_NO_IDLE_HZ_INIT=y
+CONFIG_S390_HYPFS_FS=y
CONFIG_KEXEC=y
#
@@ -174,6 +181,8 @@ CONFIG_IP_FIB_HASH=y
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -186,7 +195,10 @@ CONFIG_IPV6=y
# CONFIG_INET6_IPCOMP is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
#
@@ -263,6 +275,7 @@ CONFIG_NET_ESTIMATOR=y
# Network testing
#
# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
@@ -276,6 +289,7 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
+CONFIG_SYS_HYPERVISOR=y
#
# Connector - unified userspace <-> kernelspace linker
@@ -334,6 +348,7 @@ CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
@@ -359,9 +374,7 @@ CONFIG_MD_LINEAR=m
CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
# CONFIG_MD_RAID10 is not set
-CONFIG_MD_RAID5=m
-# CONFIG_MD_RAID5_RESHAPE is not set
-# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_RAID456 is not set
CONFIG_MD_MULTIPATH=m
# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=y
@@ -419,7 +432,8 @@ CONFIG_S390_TAPE_34XX=m
#
# Cryptographic devices
#
-CONFIG_Z90CRYPT=m
+CONFIG_ZCRYPT=m
+# CONFIG_ZCRYPT_MONOLITHIC is not set
#
# Network device support
@@ -509,6 +523,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -614,26 +629,36 @@ CONFIG_MSDOS_PARTITION=y
# Instrumentation Support
#
# CONFIG_PROFILING is not set
-# CONFIG_STATISTICS is not set
+CONFIG_STATISTICS=y
+CONFIG_KPROBES=y
#
# Kernel hacking
#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=17
# CONFIG_DETECT_SOFTLOCKUP is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
CONFIG_DEBUG_PREEMPT=y
-CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
+# CONFIG_FRAME_POINTER is not set
# CONFIG_UNWIND_INFO is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
@@ -688,3 +713,4 @@ CONFIG_CRYPTO=y
# CONFIG_CRC16 is not set
CONFIG_CRC32=m
# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index d00de17b377..a4dc61f3285 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -273,7 +273,7 @@ startup_continue:
.Lbss_end: .long _end
.Lparmaddr: .long PARMAREA
.Lsccbaddr: .long .Lsccb
- .align 4096
+ .org 0x12000
.Lsccb:
.hword 0x1000 # length, one page
.byte 0x00,0x00,0x00
@@ -290,7 +290,7 @@ startup_continue:
.Lscpincr2:
.quad 0x00
.fill 3984,1,0
- .align 4096
+ .org 0x13000
#ifdef CONFIG_SHARED_KERNEL
.org 0x100000
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 47744fcca93..9d80c5b1ef9 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -268,7 +268,7 @@ startup_continue:
.Lparmaddr:
.quad PARMAREA
- .align 4096
+ .org 0x12000
.Lsccb:
.hword 0x1000 # length, one page
.byte 0x00,0x00,0x00
@@ -285,7 +285,7 @@ startup_continue:
.Lscpincr2:
.quad 0x00
.fill 3984,1,0
- .align 4096
+ .org 0x13000
#ifdef CONFIG_SHARED_KERNEL
.org 0x100000
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 1ca34f54ea8..c902f059c7a 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -877,31 +877,57 @@ static struct bin_attribute ipl_scp_data_attr = {
static decl_subsys(ipl, NULL, NULL);
+static int ipl_register_fcp_files(void)
+{
+ int rc;
+
+ rc = sysfs_create_group(&ipl_subsys.kset.kobj,
+ &ipl_fcp_attr_group);
+ if (rc)
+ goto out;
+ rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
+ &ipl_parameter_attr);
+ if (rc)
+ goto out_ipl_parm;
+ rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
+ &ipl_scp_data_attr);
+ if (!rc)
+ goto out;
+
+ sysfs_remove_bin_file(&ipl_subsys.kset.kobj, &ipl_parameter_attr);
+
+out_ipl_parm:
+ sysfs_remove_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group);
+out:
+ return rc;
+}
+
static int __init
ipl_device_sysfs_register(void) {
int rc;
rc = firmware_register(&ipl_subsys);
if (rc)
- return rc;
+ goto out;
switch (get_ipl_type()) {
case ipl_type_ccw:
- sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_ccw_attr_group);
+ rc = sysfs_create_group(&ipl_subsys.kset.kobj,
+ &ipl_ccw_attr_group);
break;
case ipl_type_fcp:
- sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group);
- sysfs_create_bin_file(&ipl_subsys.kset.kobj,
- &ipl_parameter_attr);
- sysfs_create_bin_file(&ipl_subsys.kset.kobj,
- &ipl_scp_data_attr);
+ rc = ipl_register_fcp_files();
break;
default:
- sysfs_create_group(&ipl_subsys.kset.kobj,
- &ipl_unknown_attr_group);
+ rc = sysfs_create_group(&ipl_subsys.kset.kobj,
+ &ipl_unknown_attr_group);
break;
}
- return 0;
+
+ if (rc)
+ firmware_unregister(&ipl_subsys);
+out:
+ return rc;
}
__initcall(ipl_device_sysfs_register);
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index 781dbb11c03..b09805f3ee2 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -421,18 +421,22 @@ static struct miscdevice sq_dev = {
static int __init sq_api_init(void)
{
+ int ret;
printk(KERN_NOTICE "sq: Registering store queue API.\n");
-#ifdef CONFIG_PROC_FS
create_proc_read_entry("sq_mapping", 0, 0, sq_mapping_read_proc, 0);
-#endif
- return misc_register(&sq_dev);
+ ret = misc_register(&sq_dev);
+ if (ret)
+ remove_proc_entry("sq_mapping", NULL);
+
+ return ret;
}
static void __exit sq_api_exit(void)
{
misc_deregister(&sq_dev);
+ remove_proc_entry("sq_mapping", NULL);
}
module_init(sq_api_init);
diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c
index adba9dfee35..af90a5f9ab5 100644
--- a/arch/sparc/kernel/devices.c
+++ b/arch/sparc/kernel/devices.c
@@ -15,6 +15,7 @@
#include <asm/page.h>
#include <asm/oplib.h>
+#include <asm/prom.h>
#include <asm/smp.h>
#include <asm/system.h>
#include <asm/cpudata.h>
@@ -34,12 +35,6 @@ static int check_cpu_node(int nd, int *cur_inst,
int (*compare)(int, int, void *), void *compare_arg,
int *prom_node, int *mid)
{
- char node_str[128];
-
- prom_getstring(nd, "device_type", node_str, sizeof(node_str));
- if (strcmp(node_str, "cpu"))
- return -ENODEV;
-
if (!compare(nd, *cur_inst, compare_arg)) {
if (prom_node)
*prom_node = nd;
@@ -59,20 +54,14 @@ static int check_cpu_node(int nd, int *cur_inst,
static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
int *prom_node, int *mid)
{
- int nd, cur_inst, err;
+ struct device_node *dp;
+ int cur_inst;
- nd = prom_root_node;
cur_inst = 0;
-
- err = check_cpu_node(nd, &cur_inst, compare, compare_arg,
- prom_node, mid);
- if (!err)
- return 0;
-
- nd = prom_getchild(nd);
- while ((nd = prom_getsibling(nd)) != 0) {
- err = check_cpu_node(nd, &cur_inst, compare, compare_arg,
- prom_node, mid);
+ for_each_node_by_type(dp, "cpu") {
+ int err = check_cpu_node(dp->node, &cur_inst,
+ compare, compare_arg,
+ prom_node, mid);
if (!err)
return 0;
}
diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
index cde73327ca9..72f0201051a 100644
--- a/arch/sparc/kernel/irq.c
+++ b/arch/sparc/kernel/irq.c
@@ -329,7 +329,7 @@ void handler_irq(int irq, struct pt_regs * regs)
disable_pil_irq(irq);
#ifdef CONFIG_SMP
/* Only rotate on lower priority IRQ's (scsi, ethernet, etc.). */
- if(irq < 10)
+ if((sparc_cpu_model==sun4m) && (irq < 10))
smp4m_irq_rotate(cpu);
#endif
action = sparc_irq[irq].action;
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c
index 5a2faad5d04..97bf87e8cdd 100644
--- a/arch/sparc/kernel/of_device.c
+++ b/arch/sparc/kernel/of_device.c
@@ -596,14 +596,41 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
static int pil_to_sbus[] = {
0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0,
};
- struct device_node *busp = dp->parent;
+ struct device_node *io_unit, *sbi = dp->parent;
struct linux_prom_registers *regs;
- int board = of_getintprop_default(busp, "board#", 0);
- int slot;
+ int board, slot;
+
+ while (sbi) {
+ if (!strcmp(sbi->name, "sbi"))
+ break;
+
+ sbi = sbi->parent;
+ }
+ if (!sbi)
+ goto build_resources;
regs = of_get_property(dp, "reg", NULL);
+ if (!regs)
+ goto build_resources;
+
slot = regs->which_io;
+ /* If SBI's parent is not io-unit or the io-unit lacks
+ * a "board#" property, something is very wrong.
+ */
+ if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) {
+ printk("%s: Error, parent is not io-unit.\n",
+ sbi->full_name);
+ goto build_resources;
+ }
+ io_unit = sbi->parent;
+ board = of_getintprop_default(io_unit, "board#", -1);
+ if (board == -1) {
+ printk("%s: Error, lacks board# property.\n",
+ io_unit->full_name);
+ goto build_resources;
+ }
+
for (i = 0; i < op->num_irqs; i++) {
int this_irq = op->irqs[i];
int sbusl = pil_to_sbus[this_irq];
@@ -617,6 +644,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
}
}
+build_resources:
build_device_resources(op, parent);
op->dev.parent = parent;
diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c
index 4b06dcb00eb..4ca9e5fc97f 100644
--- a/arch/sparc/kernel/prom.c
+++ b/arch/sparc/kernel/prom.c
@@ -444,6 +444,7 @@ static struct property * __init build_one_prop(phandle node, char *prev, char *s
static struct property *tmp = NULL;
struct property *p;
int len;
+ const char *name;
if (tmp) {
p = tmp;
@@ -456,19 +457,21 @@ static struct property * __init build_one_prop(phandle node, char *prev, char *s
p->name = (char *) (p + 1);
if (special_name) {
+ strcpy(p->name, special_name);
p->length = special_len;
p->value = prom_early_alloc(special_len);
memcpy(p->value, special_val, special_len);
} else {
if (prev == NULL) {
- prom_firstprop(node, p->name);
+ name = prom_firstprop(node, NULL);
} else {
- prom_nextprop(node, prev, p->name);
+ name = prom_nextprop(node, prev, NULL);
}
- if (strlen(p->name) == 0) {
+ if (strlen(name) == 0) {
tmp = p;
return NULL;
}
+ strcpy(p->name, name);
p->length = prom_getproplen(node, p->name);
if (p->length <= 0) {
p->length = 0;
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 6135d4faeee..e311ade1b49 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -87,6 +87,7 @@ void __cpuinit smp_store_cpu_info(int id)
void __init smp_cpus_done(unsigned int max_cpus)
{
extern void smp4m_smp_done(void);
+ extern void smp4d_smp_done(void);
unsigned long bogosum = 0;
int cpu, num;
@@ -100,8 +101,34 @@ void __init smp_cpus_done(unsigned int max_cpus)
num, bogosum/(500000/HZ),
(bogosum/(5000/HZ))%100);
- BUG_ON(sparc_cpu_model != sun4m);
- smp4m_smp_done();
+ switch(sparc_cpu_model) {
+ case sun4:
+ printk("SUN4\n");
+ BUG();
+ break;
+ case sun4c:
+ printk("SUN4C\n");
+ BUG();
+ break;
+ case sun4m:
+ smp4m_smp_done();
+ break;
+ case sun4d:
+ smp4d_smp_done();
+ break;
+ case sun4e:
+ printk("SUN4E\n");
+ BUG();
+ break;
+ case sun4u:
+ printk("SUN4U\n");
+ BUG();
+ break;
+ default:
+ printk("UNKNOWN!\n");
+ BUG();
+ break;
+ };
}
void cpu_panic(void)
@@ -267,9 +294,9 @@ int setup_profiling_timer(unsigned int multiplier)
void __init smp_prepare_cpus(unsigned int max_cpus)
{
extern void smp4m_boot_cpus(void);
+ extern void smp4d_boot_cpus(void);
int i, cpuid, extra;
- BUG_ON(sparc_cpu_model != sun4m);
printk("Entering SMP Mode...\n");
extra = 0;
@@ -283,7 +310,34 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
smp_store_cpu_info(boot_cpu_id);
- smp4m_boot_cpus();
+ switch(sparc_cpu_model) {
+ case sun4:
+ printk("SUN4\n");
+ BUG();
+ break;
+ case sun4c:
+ printk("SUN4C\n");
+ BUG();
+ break;
+ case sun4m:
+ smp4m_boot_cpus();
+ break;
+ case sun4d:
+ smp4d_boot_cpus();
+ break;
+ case sun4e:
+ printk("SUN4E\n");
+ BUG();
+ break;
+ case sun4u:
+ printk("SUN4U\n");
+ BUG();
+ break;
+ default:
+ printk("UNKNOWN!\n");
+ BUG();
+ break;
+ };
}
/* Set this up early so that things like the scheduler can init
@@ -323,9 +377,37 @@ void __init smp_prepare_boot_cpu(void)
int __cpuinit __cpu_up(unsigned int cpu)
{
extern int smp4m_boot_one_cpu(int);
- int ret;
-
- ret = smp4m_boot_one_cpu(cpu);
+ extern int smp4d_boot_one_cpu(int);
+ int ret=0;
+
+ switch(sparc_cpu_model) {
+ case sun4:
+ printk("SUN4\n");
+ BUG();
+ break;
+ case sun4c:
+ printk("SUN4C\n");
+ BUG();
+ break;
+ case sun4m:
+ ret = smp4m_boot_one_cpu(cpu);
+ break;
+ case sun4d:
+ ret = smp4d_boot_one_cpu(cpu);
+ break;
+ case sun4e:
+ printk("SUN4E\n");
+ BUG();
+ break;
+ case sun4u:
+ printk("SUN4U\n");
+ BUG();
+ break;
+ default:
+ printk("UNKNOWN!\n");
+ BUG();
+ break;
+ };
if (!ret) {
cpu_set(cpu, smp_commenced_mask);
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 5fb987fc3d6..4d441a554d3 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -237,7 +237,6 @@ EXPORT_SYMBOL(prom_node_has_property);
EXPORT_SYMBOL(prom_setprop);
EXPORT_SYMBOL(saved_command_line);
EXPORT_SYMBOL(prom_apply_obio_ranges);
-EXPORT_SYMBOL(prom_getname);
EXPORT_SYMBOL(prom_feval);
EXPORT_SYMBOL(prom_getbool);
EXPORT_SYMBOL(prom_getstring);
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index b141b7ee671..ba843f6a283 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -43,15 +43,10 @@ extern ctxd_t *srmmu_ctx_table_phys;
extern void calibrate_delay(void);
extern volatile int smp_processors_ready;
-extern int smp_num_cpus;
static int smp_highest_cpu;
extern volatile unsigned long cpu_callin_map[NR_CPUS];
extern cpuinfo_sparc cpu_data[NR_CPUS];
extern unsigned char boot_cpu_id;
-extern int smp_activated;
-extern volatile int __cpu_number_map[NR_CPUS];
-extern volatile int __cpu_logical_map[NR_CPUS];
-extern volatile unsigned long ipi_count;
extern volatile int smp_process_available;
extern cpumask_t smp_commenced_mask;
@@ -144,6 +139,8 @@ void __init smp4d_callin(void)
spin_lock_irqsave(&sun4d_imsk_lock, flags);
cc_set_imsk(cc_get_imsk() & ~0x4000); /* Allow PIL 14 as well */
spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
+ cpu_set(cpuid, cpu_online_map);
+
}
extern void init_IRQ(void);
@@ -160,51 +157,24 @@ extern unsigned long trapbase_cpu3[];
void __init smp4d_boot_cpus(void)
{
- int cpucount = 0;
- int i, mid;
-
- printk("Entering SMP Mode...\n");
-
if (boot_cpu_id)
current_set[0] = NULL;
-
- local_irq_enable();
- cpus_clear(cpu_present_map);
-
- /* XXX This whole thing has to go. See sparc64. */
- for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++)
- cpu_set(mid, cpu_present_map);
- SMP_PRINTK(("cpu_present_map %08lx\n", cpus_addr(cpu_present_map)[0]));
- for(i=0; i < NR_CPUS; i++)
- __cpu_number_map[i] = -1;
- for(i=0; i < NR_CPUS; i++)
- __cpu_logical_map[i] = -1;
- __cpu_number_map[boot_cpu_id] = 0;
- __cpu_logical_map[0] = boot_cpu_id;
- current_thread_info()->cpu = boot_cpu_id;
- smp_store_cpu_info(boot_cpu_id);
smp_setup_percpu_timer();
local_flush_cache_all();
- if (cpu_find_by_instance(1, NULL, NULL))
- return; /* Not an MP box. */
- SMP_PRINTK(("Iterating over CPUs\n"));
- for(i = 0; i < NR_CPUS; i++) {
- if(i == boot_cpu_id)
- continue;
-
- if (cpu_isset(i, cpu_present_map)) {
+}
+
+int smp4d_boot_one_cpu(int i)
+{
extern unsigned long sun4d_cpu_startup;
unsigned long *entry = &sun4d_cpu_startup;
struct task_struct *p;
int timeout;
- int no;
+ int cpu_node;
+ cpu_find_by_instance(i, &cpu_node,NULL);
/* Cook up an idler for this guy. */
p = fork_idle(i);
- cpucount++;
current_set[i] = task_thread_info(p);
- for (no = 0; !cpu_find_by_instance(no, NULL, &mid)
- && mid != i; no++) ;
/*
* Initialize the contexts table
@@ -216,9 +186,9 @@ void __init smp4d_boot_cpus(void)
smp_penguin_ctable.reg_size = 0;
/* whirrr, whirrr, whirrrrrrrrr... */
- SMP_PRINTK(("Starting CPU %d at %p task %d node %08x\n", i, entry, cpucount, cpu_data(no).prom_node));
+ SMP_PRINTK(("Starting CPU %d at %p \n", i, entry));
local_flush_cache_all();
- prom_startcpu(cpu_data(no).prom_node,
+ prom_startcpu(cpu_node,
&smp_penguin_ctable, 0, (char *)entry);
SMP_PRINTK(("prom_startcpu returned :)\n"));
@@ -230,39 +200,30 @@ void __init smp4d_boot_cpus(void)
udelay(200);
}
- if(cpu_callin_map[i]) {
- /* Another "Red Snapper". */
- __cpu_number_map[i] = cpucount;
- __cpu_logical_map[cpucount] = i;
- } else {
- cpucount--;
- printk("Processor %d is stuck.\n", i);
- }
- }
- if(!(cpu_callin_map[i])) {
- cpu_clear(i, cpu_present_map);
- __cpu_number_map[i] = -1;
- }
+ if (!(cpu_callin_map[i])) {
+ printk("Processor %d is stuck.\n", i);
+ return -ENODEV;
+
}
local_flush_cache_all();
- if(cpucount == 0) {
- printk("Error: only one Processor found.\n");
- cpu_present_map = cpumask_of_cpu(hard_smp4d_processor_id());
- } else {
- unsigned long bogosum = 0;
-
- for_each_present_cpu(i) {
- bogosum += cpu_data(i).udelay_val;
- smp_highest_cpu = i;
+ return 0;
+}
+
+void __init smp4d_smp_done(void)
+{
+ int i, first;
+ int *prev;
+
+ /* setup cpu list for irq rotation */
+ first = 0;
+ prev = &first;
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_online(i)) {
+ *prev = i;
+ prev = &cpu_data(i).next;
}
- SMP_PRINTK(("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", cpucount + 1, bogosum/(500000/HZ), (bogosum/(5000/HZ))%100));
- printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n",
- cpucount + 1,
- bogosum/(500000/HZ),
- (bogosum/(5000/HZ))%100);
- smp_activated = 1;
- smp_num_cpus = cpucount + 1;
- }
+ *prev = first;
+ local_flush_cache_all();
/* Free unneeded trap tables */
ClearPageReserved(virt_to_page(trapbase_cpu1));
@@ -334,7 +295,7 @@ void smp4d_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
register int i;
mask = cpumask_of_cpu(hard_smp4d_processor_id());
- cpus_andnot(mask, cpu_present_map, mask);
+ cpus_andnot(mask, cpu_online_map, mask);
for(i = 0; i <= high; i++) {
if (cpu_isset(i, mask)) {
ccall_info.processors_in[i] = 0;
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
index 0cdfc9d294b..a41c8a5c200 100644
--- a/arch/sparc/kernel/sys_sparc.c
+++ b/arch/sparc/kernel/sys_sparc.c
@@ -465,21 +465,21 @@ sys_rt_sigaction(int sig,
asmlinkage int sys_getdomainname(char __user *name, int len)
{
- int nlen;
- int err = -EFAULT;
+ int nlen, err;
+ if (len < 0 || len > __NEW_UTS_LEN)
+ return -EINVAL;
+
down_read(&uts_sem);
nlen = strlen(system_utsname.domainname) + 1;
-
if (nlen < len)
len = nlen;
- if (len > __NEW_UTS_LEN)
- goto done;
- if (copy_to_user(name, system_utsname.domainname, len))
- goto done;
- err = 0;
-done:
+
+ err = -EFAULT;
+ if (!copy_to_user(name, system_utsname.domainname, len))
+ err = 0;
+
up_read(&uts_sem);
return err;
}
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 04eb1eab6e3..845081b0126 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -225,6 +225,32 @@ static __inline__ int has_low_battery(void)
return (data1 == data2); /* Was the write blocked? */
}
+static void __init mostek_set_system_time(void)
+{
+ unsigned int year, mon, day, hour, min, sec;
+ struct mostek48t02 *mregs;
+
+ mregs = (struct mostek48t02 *)mstk48t02_regs;
+ if(!mregs) {
+ prom_printf("Something wrong, clock regs not mapped yet.\n");
+ prom_halt();
+ }
+ spin_lock_irq(&mostek_lock);
+ mregs->creg |= MSTK_CREG_READ;
+ sec = MSTK_REG_SEC(mregs);
+ min = MSTK_REG_MIN(mregs);
+ hour = MSTK_REG_HOUR(mregs);
+ day = MSTK_REG_DOM(mregs);
+ mon = MSTK_REG_MONTH(mregs);
+ year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
+ xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+ xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
+ mregs->creg &= ~MSTK_CREG_READ;
+ spin_unlock_irq(&mostek_lock);
+}
+
/* Probe for the real time clock chip on Sun4 */
static __inline__ void sun4_clock_probe(void)
{
@@ -273,6 +299,7 @@ static __inline__ void sun4_clock_probe(void)
#endif
}
+#ifndef CONFIG_SUN4
static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match)
{
struct device_node *dp = op->node;
@@ -307,6 +334,8 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id
if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP)
kick_start_clock();
+ mostek_set_system_time();
+
return 0;
}
@@ -325,56 +354,37 @@ static struct of_platform_driver clock_driver = {
/* Probe for the mostek real time clock chip. */
-static void clock_init(void)
+static int __init clock_init(void)
{
- of_register_driver(&clock_driver, &of_bus_type);
+ return of_register_driver(&clock_driver, &of_bus_type);
}
+/* Must be after subsys_initcall() so that busses are probed. Must
+ * be before device_initcall() because things like the RTC driver
+ * need to see the clock registers.
+ */
+fs_initcall(clock_init);
+#endif /* !CONFIG_SUN4 */
+
void __init sbus_time_init(void)
{
- unsigned int year, mon, day, hour, min, sec;
- struct mostek48t02 *mregs;
-
-#ifdef CONFIG_SUN4
- int temp;
- struct intersil *iregs;
-#endif
BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM);
btfixup();
if (ARCH_SUN4)
sun4_clock_probe();
- else
- clock_init();
sparc_init_timers(timer_interrupt);
#ifdef CONFIG_SUN4
if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) {
-#endif
- mregs = (struct mostek48t02 *)mstk48t02_regs;
- if(!mregs) {
- prom_printf("Something wrong, clock regs not mapped yet.\n");
- prom_halt();
- }
- spin_lock_irq(&mostek_lock);
- mregs->creg |= MSTK_CREG_READ;
- sec = MSTK_REG_SEC(mregs);
- min = MSTK_REG_MIN(mregs);
- hour = MSTK_REG_HOUR(mregs);
- day = MSTK_REG_DOM(mregs);
- mon = MSTK_REG_MONTH(mregs);
- year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
- xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
- xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
- set_normalized_timespec(&wall_to_monotonic,
- -xtime.tv_sec, -xtime.tv_nsec);
- mregs->creg &= ~MSTK_CREG_READ;
- spin_unlock_irq(&mostek_lock);
-#ifdef CONFIG_SUN4
+ mostek_set_system_time();
} else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) {
/* initialise the intersil on sun4 */
+ unsigned int year, mon, day, hour, min, sec;
+ int temp;
+ struct intersil *iregs;
iregs=intersil_clock;
if(!iregs) {
diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c
index 42c1c700c0a..2bb1309003d 100644
--- a/arch/sparc/mm/io-unit.c
+++ b/arch/sparc/mm/io-unit.c
@@ -64,6 +64,7 @@ iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus)
sbus->iommu = (struct iommu_struct *)iounit;
iounit->page_table = xpt;
+ spin_lock_init(&iounit->lock);
for (xptend = iounit->page_table + (16 * PAGE_SIZE) / sizeof(iopte_t);
xpt < xptend;)
diff --git a/arch/sparc/prom/tree.c b/arch/sparc/prom/tree.c
index 2bf03ee8cde..5ec246573a9 100644
--- a/arch/sparc/prom/tree.c
+++ b/arch/sparc/prom/tree.c
@@ -205,24 +205,6 @@ int prom_searchsiblings(int node_start, char *nodename)
return 0;
}
-/* Gets name in the form prom v2+ uses it (name@x,yyyyy or name (if no reg)) */
-int prom_getname (int node, char *buffer, int len)
-{
- int i;
- struct linux_prom_registers reg[PROMREG_MAX];
-
- i = prom_getproperty (node, "name", buffer, len);
- if (i <= 0) return -1;
- buffer [i] = 0;
- len -= i;
- i = prom_getproperty (node, "reg", (char *)reg, sizeof (reg));
- if (i <= 0) return 0;
- if (len < 11) return -1;
- buffer = strchr (buffer, 0);
- sprintf (buffer, "@%x,%x", reg[0].which_io, (uint)reg[0].phys_addr);
- return 0;
-}
-
/* Interal version of nextprop that does not alter return values. */
char * __prom_nextprop(int node, char * oprop)
{
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 38353621069..43d9229fca0 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Wed Jul 12 14:00:58 2006
+# Linux kernel version: 2.6.18-rc2
+# Fri Jul 21 14:19:24 2006
#
CONFIG_SPARC=y
CONFIG_SPARC64=y
@@ -36,6 +36,7 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
@@ -1120,7 +1121,7 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
# CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
# CONFIG_USB_PHIDGETKIT is not set
# CONFIG_USB_PHIDGETSERVO is not set
@@ -1279,7 +1280,6 @@ CONFIG_RAMFS=y
# CONFIG_NFSD is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c
index f8ef2f2b9b3..ec10f7edcf8 100644
--- a/arch/sparc64/kernel/devices.c
+++ b/arch/sparc64/kernel/devices.c
@@ -66,9 +66,6 @@ static int check_cpu_node(struct device_node *dp, int *cur_inst,
void *compare_arg,
struct device_node **dev_node, int *mid)
{
- if (strcmp(dp->type, "cpu"))
- return -ENODEV;
-
if (!compare(dp, *cur_inst, compare_arg)) {
if (dev_node)
*dev_node = dp;
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index 7064cee290a..238bbf6de07 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -542,9 +542,17 @@ static void __init build_device_resources(struct of_device *op,
/* Convert to num-cells. */
num_reg /= 4;
- /* Conver to num-entries. */
+ /* Convert to num-entries. */
num_reg /= na + ns;
+ /* Prevent overruning the op->resources[] array. */
+ if (num_reg > PROMREG_MAX) {
+ printk(KERN_WARNING "%s: Too many regs (%d), "
+ "limiting to %d.\n",
+ op->node->full_name, num_reg, PROMREG_MAX);
+ num_reg = PROMREG_MAX;
+ }
+
for (index = 0; index < num_reg; index++) {
struct resource *r = &op->resource[index];
u32 addr[OF_MAX_ADDR_CELLS];
@@ -650,8 +658,22 @@ apply_interrupt_map(struct device_node *dp, struct device_node *pp,
next:
imap += (na + 3);
}
- if (i == imlen)
+ if (i == imlen) {
+ /* Psycho and Sabre PCI controllers can have 'interrupt-map'
+ * properties that do not include the on-board device
+ * interrupts. Instead, the device's 'interrupts' property
+ * is already a fully specified INO value.
+ *
+ * Handle this by deciding that, if we didn't get a
+ * match in the parent's 'interrupt-map', and the
+ * parent is an IRQ translater, then use the parent as
+ * our IRQ controller.
+ */
+ if (pp->irq_trans)
+ return pp;
+
return NULL;
+ }
*irq_p = irq;
cp = of_find_node_by_phandle(handle);
@@ -803,6 +825,14 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
op->num_irqs = 0;
}
+ /* Prevent overruning the op->irqs[] array. */
+ if (op->num_irqs > PROMINTR_MAX) {
+ printk(KERN_WARNING "%s: Too many irqs (%d), "
+ "limiting to %d.\n",
+ dp->full_name, op->num_irqs, PROMINTR_MAX);
+ op->num_irqs = PROMINTR_MAX;
+ }
+
build_device_resources(op, parent);
for (i = 0; i < op->num_irqs; i++)
op->irqs[i] = build_one_device_irq(op, parent, op->irqs[i]);
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index c86007a2aa3..5cc5ab63293 100644
--- a/arch/sparc64/kernel/prom.c
+++ b/arch/sparc64/kernel/prom.c
@@ -344,10 +344,12 @@ static unsigned long __psycho_onboard_imap_off[] = {
/*0x2f*/ PSYCHO_IMAP_CE,
/*0x30*/ PSYCHO_IMAP_A_ERR,
/*0x31*/ PSYCHO_IMAP_B_ERR,
-/*0x32*/ PSYCHO_IMAP_PMGMT
+/*0x32*/ PSYCHO_IMAP_PMGMT,
+/*0x33*/ PSYCHO_IMAP_GFX,
+/*0x34*/ PSYCHO_IMAP_EUPA,
};
#define PSYCHO_ONBOARD_IRQ_BASE 0x20
-#define PSYCHO_ONBOARD_IRQ_LAST 0x32
+#define PSYCHO_ONBOARD_IRQ_LAST 0x34
#define psycho_onboard_imap_offset(__ino) \
__psycho_onboard_imap_off[(__ino) - PSYCHO_ONBOARD_IRQ_BASE]
@@ -529,6 +531,10 @@ static unsigned long __sabre_onboard_imap_off[] = {
/*0x2e*/ SABRE_IMAP_UE,
/*0x2f*/ SABRE_IMAP_CE,
/*0x30*/ SABRE_IMAP_PCIERR,
+/*0x31*/ 0 /* reserved */,
+/*0x32*/ 0 /* reserved */,
+/*0x33*/ SABRE_IMAP_GFX,
+/*0x34*/ SABRE_IMAP_EUPA,
};
#define SABRE_ONBOARD_IRQ_BASE 0x20
#define SABRE_ONBOARD_IRQ_LAST 0x30
@@ -895,6 +901,8 @@ static unsigned long sysio_irq_offsets[] = {
SYSIO_IMAP_CE,
SYSIO_IMAP_SBERR,
SYSIO_IMAP_PMGMT,
+ SYSIO_IMAP_GFX,
+ SYSIO_IMAP_EUPA,
};
#undef bogon
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 237524d87ca..beffc82a1e8 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -254,7 +254,6 @@ EXPORT_SYMBOL(prom_getproperty);
EXPORT_SYMBOL(prom_node_has_property);
EXPORT_SYMBOL(prom_setprop);
EXPORT_SYMBOL(saved_command_line);
-EXPORT_SYMBOL(prom_getname);
EXPORT_SYMBOL(prom_finddevice);
EXPORT_SYMBOL(prom_feval);
EXPORT_SYMBOL(prom_getbool);
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index 51c056df528..054d0abdb7e 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -701,21 +701,21 @@ extern void check_pending(int signum);
asmlinkage long sys_getdomainname(char __user *name, int len)
{
- int nlen;
- int err = -EFAULT;
+ int nlen, err;
+
+ if (len < 0 || len > __NEW_UTS_LEN)
+ return -EINVAL;
down_read(&uts_sem);
nlen = strlen(system_utsname.domainname) + 1;
-
if (nlen < len)
len = nlen;
- if (len > __NEW_UTS_LEN)
- goto done;
- if (copy_to_user(name, system_utsname.domainname, len))
- goto done;
- err = 0;
-done:
+
+ err = -EFAULT;
+ if (!copy_to_user(name, system_utsname.domainname, len))
+ err = 0;
+
up_read(&uts_sem);
return err;
}
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index 1605967cce9..55ae802dc0a 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -132,6 +133,8 @@ static void bad_kernel_pc(struct pt_regs *regs, unsigned long vaddr)
printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n",
regs->tpc);
+ printk(KERN_CRIT "OOPS: RPC [%016lx]\n", regs->u_regs[15]);
+ print_symbol("RPC: <%s>\n", regs->u_regs[15]);
printk(KERN_CRIT "OOPS: Fault was to vaddr[%lx]\n", vaddr);
__asm__("mov %%sp, %0" : "=r" (ksp));
show_stack(current, ksp);
diff --git a/arch/sparc64/prom/tree.c b/arch/sparc64/prom/tree.c
index 49075abd7cb..500f05e2cfc 100644
--- a/arch/sparc64/prom/tree.c
+++ b/arch/sparc64/prom/tree.c
@@ -193,91 +193,6 @@ prom_searchsiblings(int node_start, const char *nodename)
return 0;
}
-/* Gets name in the {name@x,yyyyy|name (if no reg)} form */
-int
-prom_getname (int node, char *buffer, int len)
-{
- int i, sbus = 0;
- int pci = 0, ebus = 0, ide = 0;
- struct linux_prom_registers *reg;
- struct linux_prom64_registers reg64[PROMREG_MAX];
-
- for (sbus = prom_getparent (node); sbus; sbus = prom_getparent (sbus)) {
- i = prom_getproperty (sbus, "name", buffer, len);
- if (i > 0) {
- buffer [i] = 0;
- if (!strcmp (buffer, "sbus"))
- goto getit;
- }
- }
- if ((pci = prom_getparent (node))) {
- i = prom_getproperty (pci, "name", buffer, len);
- if (i > 0) {
- buffer [i] = 0;
- if (!strcmp (buffer, "pci"))
- goto getit;
- }
- pci = 0;
- }
- if ((ebus = prom_getparent (node))) {
- i = prom_getproperty (ebus, "name", buffer, len);
- if (i > 0) {
- buffer[i] = 0;
- if (!strcmp (buffer, "ebus"))
- goto getit;
- }
- ebus = 0;
- }
- if ((ide = prom_getparent (node))) {
- i = prom_getproperty (ide, "name", buffer, len);
- if (i > 0) {
- buffer [i] = 0;
- if (!strcmp (buffer, "ide"))
- goto getit;
- }
- ide = 0;
- }
-getit:
- i = prom_getproperty (node, "name", buffer, len);
- if (i <= 0) {
- buffer [0] = 0;
- return -1;
- }
- buffer [i] = 0;
- len -= i;
- i = prom_getproperty (node, "reg", (char *)reg64, sizeof (reg64));
- if (i <= 0) return 0;
- if (len < 16) return -1;
- buffer = strchr (buffer, 0);
- if (sbus) {
- reg = (struct linux_prom_registers *)reg64;
- sprintf (buffer, "@%x,%x", reg[0].which_io, (uint)reg[0].phys_addr);
- } else if (pci) {
- int dev, fn;
- reg = (struct linux_prom_registers *)reg64;
- fn = (reg[0].which_io >> 8) & 0x07;
- dev = (reg[0].which_io >> 11) & 0x1f;
- if (fn)
- sprintf (buffer, "@%x,%x", dev, fn);
- else
- sprintf (buffer, "@%x", dev);
- } else if (ebus) {
- reg = (struct linux_prom_registers *)reg64;
- sprintf (buffer, "@%x,%x", reg[0].which_io, reg[0].phys_addr);
- } else if (ide) {
- reg = (struct linux_prom_registers *)reg64;
- sprintf (buffer, "@%x,%x", reg[0].which_io, reg[0].phys_addr);
- } else if (i == 4) { /* Happens on 8042's children on Ultra/PCI. */
- reg = (struct linux_prom_registers *)reg64;
- sprintf (buffer, "@%x", reg[0].which_io);
- } else {
- sprintf (buffer, "@%x,%x",
- (unsigned int)(reg64[0].phys_addr >> 36),
- (unsigned int)(reg64[0].phys_addr));
- }
- return 0;
-}
-
/* Return the first property type for node 'node'.
* buffer should be at least 32B in length
*/
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 2517ecb8bf2..68ed24df5c8 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -26,6 +26,7 @@ SECTIONS
/* Read-only sections, merged into text segment: */
.hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
diff --git a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c
index 62bdb8d29fc..1bf672a2569 100644
--- a/arch/v850/kernel/setup.c
+++ b/arch/v850/kernel/setup.c
@@ -1,8 +1,8 @@
/*
* arch/v850/kernel/setup.c -- Arch-dependent initialization functions
*
- * Copyright (C) 2001,02,03,05 NEC Electronics Corporation
- * Copyright (C) 2001,02,03,05 Miles Bader <miles@gnu.org>
+ * Copyright (C) 2001,02,03,05,06 NEC Electronics Corporation
+ * Copyright (C) 2001,02,03,05,06 Miles Bader <miles@gnu.org>
*
* 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
@@ -190,7 +190,7 @@ void free_initmem (void)
for (addr = start; addr < end; addr += PAGE_SIZE) {
struct page *page = virt_to_page (addr);
ClearPageReserved (page);
- set_page_count (page, 1);
+ init_page_count (page);
__free_page (page);
total_ram_pages++;
}
diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
index c03ad6ed61c..67bc48e57c6 100644
--- a/arch/v850/kernel/v850_ksyms.c
+++ b/arch/v850/kernel/v850_ksyms.c
@@ -21,9 +21,6 @@ EXPORT_SYMBOL (trap_table);
/* platform dependent support */
EXPORT_SYMBOL (kernel_thread);
-EXPORT_SYMBOL (enable_irq);
-EXPORT_SYMBOL (disable_irq);
-EXPORT_SYMBOL (disable_irq_nosync);
EXPORT_SYMBOL (__bug);
/* Networking helper routines. */
@@ -33,22 +30,9 @@ EXPORT_SYMBOL (ip_compute_csum);
EXPORT_SYMBOL (ip_fast_csum);
/* string / mem functions */
-EXPORT_SYMBOL (strcpy);
-EXPORT_SYMBOL (strncpy);
-EXPORT_SYMBOL (strcat);
-EXPORT_SYMBOL (strncat);
-EXPORT_SYMBOL (strcmp);
-EXPORT_SYMBOL (strncmp);
-EXPORT_SYMBOL (strchr);
-EXPORT_SYMBOL (strlen);
-EXPORT_SYMBOL (strnlen);
-EXPORT_SYMBOL (strrchr);
-EXPORT_SYMBOL (strstr);
EXPORT_SYMBOL (memset);
EXPORT_SYMBOL (memcpy);
EXPORT_SYMBOL (memmove);
-EXPORT_SYMBOL (memcmp);
-EXPORT_SYMBOL (memscan);
/* semaphores */
EXPORT_SYMBOL (__down);
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 83d389b8ebd..840d5d93d5c 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-git22
-# Tue Jul 4 14:24:40 2006
+# Linux kernel version: 2.6.18-rc2
+# Tue Jul 18 17:13:20 2006
#
CONFIG_X86_64=y
CONFIG_64BIT=y
@@ -37,6 +37,7 @@ CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
@@ -413,6 +414,7 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -1195,7 +1197,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
# CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
# CONFIG_USB_PHIDGETKIT is not set
# CONFIG_USB_PHIDGETSERVO is not set
@@ -1373,7 +1375,6 @@ CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile
index 62bc5f56da9..cdae36435e2 100644
--- a/arch/x86_64/ia32/Makefile
+++ b/arch/x86_64/ia32/Makefile
@@ -23,6 +23,7 @@ targets := $(foreach F,sysenter syscall,vsyscall-$F.o vsyscall-$F.so)
# The DSO images are built using a special linker script
quiet_cmd_syscall = SYSCALL $@
cmd_syscall = $(CC) -m32 -nostdlib -shared -s \
+ $(call ld-option, -Wl$(comma)--hash-style=sysv) \
-Wl,-soname=linux-gate.so.1 -o $@ \
-Wl,-T,$(filter-out FORCE,$^)
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 9b5bb413a6e..5d4a7d125ed 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -103,7 +103,7 @@ ENTRY(ia32_sysenter_target)
pushq %rax
CFI_ADJUST_CFA_OFFSET 8
cld
- SAVE_ARGS 0,0,1
+ SAVE_ARGS 0,0,0
/* no need to do an access_ok check here because rbp has been
32bit zero extended */
1: movl (%rbp),%r9d
diff --git a/arch/x86_64/ia32/vsyscall.lds b/arch/x86_64/ia32/vsyscall.lds
index f2e75ed4c6c..1dc86ff5bcb 100644
--- a/arch/x86_64/ia32/vsyscall.lds
+++ b/arch/x86_64/ia32/vsyscall.lds
@@ -11,6 +11,7 @@ SECTIONS
. = VSYSCALL_BASE + SIZEOF_HEADERS;
.hash : { *(.hash) } :text
+ .gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index d464dded68c..6f810424df4 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -513,6 +513,7 @@ END(stub_rt_sigreturn)
swapgs
1: incl %gs:pda_irqcount # RED-PEN should check preempt count
cmoveq %gs:pda_irqstackptr,%rsp
+ push %rbp # backlink for old unwinder
/*
* We entered an interrupt context - irqs are off:
*/
@@ -1139,18 +1140,21 @@ ENTRY(machine_check)
END(machine_check)
#endif
+/* Call softirq on interrupt stack. Interrupts are off. */
ENTRY(call_softirq)
CFI_STARTPROC
- movq %gs:pda_irqstackptr,%rax
- movq %rsp,%rdx
- CFI_DEF_CFA_REGISTER rdx
+ push %rbp
+ CFI_ADJUST_CFA_OFFSET 8
+ CFI_REL_OFFSET rbp,0
+ mov %rsp,%rbp
+ CFI_DEF_CFA_REGISTER rbp
incl %gs:pda_irqcount
- cmove %rax,%rsp
- pushq %rdx
- /*todo CFI_DEF_CFA_EXPRESSION ...*/
+ cmove %gs:pda_irqstackptr,%rsp
+ push %rbp # backlink for old unwinder
call __do_softirq
- popq %rsp
+ leaveq
CFI_DEF_CFA_REGISTER rsp
+ CFI_ADJUST_CFA_OFFSET -8
decl %gs:pda_irqcount
ret
CFI_ENDPROC
diff --git a/arch/x86_64/kernel/machine_kexec.c b/arch/x86_64/kernel/machine_kexec.c
index 83fb24a0282..106076b370f 100644
--- a/arch/x86_64/kernel/machine_kexec.c
+++ b/arch/x86_64/kernel/machine_kexec.c
@@ -207,14 +207,11 @@ NORET_TYPE void machine_kexec(struct kimage *image)
__flush_tlb();
- /* The segment registers are funny things, they are
- * automatically loaded from a table, in memory wherever you
- * set them to a specific selector, but this table is never
- * accessed again unless you set the segment to a different selector.
- *
- * The more common model are caches where the behide
- * the scenes work is done, but is also dropped at arbitrary
- * times.
+ /* The segment registers are funny things, they have both a
+ * visible and an invisible part. Whenever the visible part is
+ * set to a specific selector, the invisible part is loaded
+ * with from a table in memory. At no other time is the
+ * descriptor table in memory accessed.
*
* I take advantage of this here by force loading the
* segments, before I zap the gdt with an invalid value.
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 88845674c66..4e017fb30fb 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -615,7 +615,7 @@ static __cpuinit int mce_create_device(unsigned int cpu)
}
#ifdef CONFIG_HOTPLUG_CPU
-static __cpuinit void mce_remove_device(unsigned int cpu)
+static void mce_remove_device(unsigned int cpu)
{
int i;
@@ -626,10 +626,9 @@ static __cpuinit void mce_remove_device(unsigned int cpu)
sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_check_interval);
sysdev_unregister(&per_cpu(device_mce,cpu));
}
-#endif
/* Get notified when a cpu comes on/off. Be hotplug friendly. */
-static __cpuinit int
+static int
mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
@@ -638,18 +637,17 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
case CPU_ONLINE:
mce_create_device(cpu);
break;
-#ifdef CONFIG_HOTPLUG_CPU
case CPU_DEAD:
mce_remove_device(cpu);
break;
-#endif
}
return NOTIFY_OK;
}
-static struct notifier_block __cpuinitdata mce_cpu_notifier = {
+static struct notifier_block mce_cpu_notifier = {
.notifier_call = mce_cpu_callback,
};
+#endif
static __init int mce_init_device(void)
{
@@ -664,7 +662,7 @@ static __init int mce_init_device(void)
mce_create_device(i);
}
- register_cpu_notifier(&mce_cpu_notifier);
+ register_hotcpu_notifier(&mce_cpu_notifier);
misc_register(&mce_log_device);
return err;
}
diff --git a/arch/x86_64/kernel/mce_amd.c b/arch/x86_64/kernel/mce_amd.c
index db2acbf7ad2..883fe747f64 100644
--- a/arch/x86_64/kernel/mce_amd.c
+++ b/arch/x86_64/kernel/mce_amd.c
@@ -558,7 +558,7 @@ out:
* of shared sysfs dir/files, and rest of the cores will be symlinked to it.
*/
-static __cpuinit void deallocate_threshold_block(unsigned int cpu,
+static void deallocate_threshold_block(unsigned int cpu,
unsigned int bank)
{
struct threshold_block *pos = NULL;
@@ -578,7 +578,7 @@ static __cpuinit void deallocate_threshold_block(unsigned int cpu,
per_cpu(threshold_banks, cpu)[bank]->blocks = NULL;
}
-static __cpuinit void threshold_remove_bank(unsigned int cpu, int bank)
+static void threshold_remove_bank(unsigned int cpu, int bank)
{
int i = 0;
struct threshold_bank *b;
@@ -618,7 +618,7 @@ free_out:
per_cpu(threshold_banks, cpu)[bank] = NULL;
}
-static __cpuinit void threshold_remove_device(unsigned int cpu)
+static void threshold_remove_device(unsigned int cpu)
{
unsigned int bank;
@@ -629,14 +629,8 @@ static __cpuinit void threshold_remove_device(unsigned int cpu)
}
}
-#else /* !CONFIG_HOTPLUG_CPU */
-static void threshold_remove_device(unsigned int cpu)
-{
-}
-#endif
-
/* get notified when a cpu comes on/off */
-static int __cpuinit threshold_cpu_callback(struct notifier_block *nfb,
+static int threshold_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
/* cpu was unsigned int to begin with */
@@ -659,9 +653,10 @@ static int __cpuinit threshold_cpu_callback(struct notifier_block *nfb,
return NOTIFY_OK;
}
-static struct notifier_block threshold_cpu_notifier __cpuinitdata = {
+static struct notifier_block threshold_cpu_notifier = {
.notifier_call = threshold_cpu_callback,
};
+#endif /* CONFIG_HOTPLUG_CPU */
static __init int threshold_init_device(void)
{
@@ -673,7 +668,7 @@ static __init int threshold_init_device(void)
if (err)
return err;
}
- register_cpu_notifier(&threshold_cpu_notifier);
+ register_hotcpu_notifier(&threshold_cpu_notifier);
return 0;
}
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
index e71ed53b08f..146924ba5df 100644
--- a/arch/x86_64/kernel/pci-calgary.c
+++ b/arch/x86_64/kernel/pci-calgary.c
@@ -85,7 +85,8 @@
#define CSR_AGENT_MASK 0xffe0ffff
#define MAX_NUM_OF_PHBS 8 /* how many PHBs in total? */
-#define MAX_PHB_BUS_NUM (MAX_NUM_OF_PHBS * 2) /* max dev->bus->number */
+#define MAX_NUM_CHASSIS 8 /* max number of chassis */
+#define MAX_PHB_BUS_NUM (MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2) /* max dev->bus->number */
#define PHBS_PER_CALGARY 4
/* register offsets in Calgary's internal register space */
@@ -110,7 +111,8 @@ static const unsigned long phb_offsets[] = {
0xB000 /* PHB3 */
};
-void* tce_table_kva[MAX_NUM_OF_PHBS * MAX_NUMNODES];
+static char bus_to_phb[MAX_PHB_BUS_NUM];
+void* tce_table_kva[MAX_PHB_BUS_NUM];
unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED;
static int translate_empty_slots __read_mostly = 0;
static int calgary_detected __read_mostly = 0;
@@ -119,7 +121,7 @@ static int calgary_detected __read_mostly = 0;
* the bitmap of PHBs the user requested that we disable
* translation on.
*/
-static DECLARE_BITMAP(translation_disabled, MAX_NUMNODES * MAX_PHB_BUS_NUM);
+static DECLARE_BITMAP(translation_disabled, MAX_PHB_BUS_NUM);
static void tce_cache_blast(struct iommu_table *tbl);
@@ -452,7 +454,7 @@ static struct dma_mapping_ops calgary_dma_ops = {
static inline int busno_to_phbid(unsigned char num)
{
- return bus_to_phb(num) % PHBS_PER_CALGARY;
+ return bus_to_phb[num];
}
static inline unsigned long split_queue_offset(unsigned char num)
@@ -812,7 +814,7 @@ static int __init calgary_init(void)
int i, ret = -ENODEV;
struct pci_dev *dev = NULL;
- for (i = 0; i <= num_online_nodes() * MAX_NUM_OF_PHBS; i++) {
+ for (i = 0; i < MAX_PHB_BUS_NUM; i++) {
dev = pci_get_device(PCI_VENDOR_ID_IBM,
PCI_DEVICE_ID_IBM_CALGARY,
dev);
@@ -822,7 +824,7 @@ static int __init calgary_init(void)
calgary_init_one_nontraslated(dev);
continue;
}
- if (!tce_table_kva[i] && !translate_empty_slots) {
+ if (!tce_table_kva[dev->bus->number] && !translate_empty_slots) {
pci_dev_put(dev);
continue;
}
@@ -842,7 +844,7 @@ error:
pci_dev_put(dev);
continue;
}
- if (!tce_table_kva[i] && !translate_empty_slots)
+ if (!tce_table_kva[dev->bus->number] && !translate_empty_slots)
continue;
calgary_disable_translation(dev);
calgary_free_tar(dev);
@@ -876,9 +878,10 @@ static inline int __init determine_tce_table_size(u64 ram)
void __init detect_calgary(void)
{
u32 val;
- int bus, table_idx;
+ int bus;
void *tbl;
- int detected = 0;
+ int calgary_found = 0;
+ int phb = -1;
/*
* if the user specified iommu=off or iommu=soft or we found
@@ -889,38 +892,46 @@ void __init detect_calgary(void)
specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE);
- for (bus = 0, table_idx = 0;
- bus <= num_online_nodes() * MAX_PHB_BUS_NUM;
- bus++) {
- BUG_ON(bus > MAX_NUMNODES * MAX_PHB_BUS_NUM);
+ for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
+ int dev;
+
+ tce_table_kva[bus] = NULL;
+ bus_to_phb[bus] = -1;
+
if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY)
continue;
+
+ /*
+ * There are 4 PHBs per Calgary chip. Set phb to which phb (0-3)
+ * it is connected to releative to the clagary chip.
+ */
+ phb = (phb + 1) % PHBS_PER_CALGARY;
+
if (test_bit(bus, translation_disabled)) {
printk(KERN_INFO "Calgary: translation is disabled for "
"PHB 0x%x\n", bus);
/* skip this phb, don't allocate a tbl for it */
- tce_table_kva[table_idx] = NULL;
- table_idx++;
continue;
}
/*
- * scan the first slot of the PCI bus to see if there
- * are any devices present
+ * Scan the slots of the PCI bus to see if there is a device present.
+ * The parent bus will be the zero-ith device, so start at 1.
*/
- val = read_pci_config(bus, 1, 0, 0);
- if (val != 0xffffffff || translate_empty_slots) {
- tbl = alloc_tce_table();
- if (!tbl)
- goto cleanup;
- detected = 1;
- } else
- tbl = NULL;
-
- tce_table_kva[table_idx] = tbl;
- table_idx++;
+ for (dev = 1; dev < 8; dev++) {
+ val = read_pci_config(bus, dev, 0, 0);
+ if (val != 0xffffffff || translate_empty_slots) {
+ tbl = alloc_tce_table();
+ if (!tbl)
+ goto cleanup;
+ tce_table_kva[bus] = tbl;
+ bus_to_phb[bus] = phb;
+ calgary_found = 1;
+ break;
+ }
+ }
}
- if (detected) {
+ if (calgary_found) {
iommu_detected = 1;
calgary_detected = 1;
printk(KERN_INFO "PCI-DMA: Calgary IOMMU detected. "
@@ -929,9 +940,9 @@ void __init detect_calgary(void)
return;
cleanup:
- for (--table_idx; table_idx >= 0; --table_idx)
- if (tce_table_kva[table_idx])
- free_tce_table(tce_table_kva[table_idx]);
+ for (--bus; bus >= 0; --bus)
+ if (tce_table_kva[bus])
+ free_tce_table(tce_table_kva[bus]);
}
int __init calgary_iommu_init(void)
@@ -1002,7 +1013,7 @@ static int __init calgary_parse_options(char *p)
if (p == endp)
break;
- if (bridge <= (num_online_nodes() * MAX_PHB_BUS_NUM)) {
+ if (bridge < MAX_PHB_BUS_NUM) {
printk(KERN_INFO "Calgary: disabling "
"translation for PHB 0x%x\n", bridge);
set_bit(bridge, translation_disabled);
diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c
index c4c3cc36ac5..aad7609d8e9 100644
--- a/arch/x86_64/kernel/pci-nommu.c
+++ b/arch/x86_64/kernel/pci-nommu.c
@@ -92,5 +92,7 @@ void __init no_iommu_init(void)
{
if (dma_ops)
return;
+
+ force_iommu = 0; /* no HW IOMMU */
dma_ops = &nommu_dma_ops;
}
diff --git a/arch/x86_64/kernel/pci-swiotlb.c b/arch/x86_64/kernel/pci-swiotlb.c
index ebdb77fe205..6a55f87ba97 100644
--- a/arch/x86_64/kernel/pci-swiotlb.c
+++ b/arch/x86_64/kernel/pci-swiotlb.c
@@ -31,9 +31,10 @@ struct dma_mapping_ops swiotlb_dma_ops = {
void pci_swiotlb_init(void)
{
/* don't initialize swiotlb if iommu=off (no_iommu=1) */
- if (!iommu_detected && !no_iommu &&
- (end_pfn > MAX_DMA32_PFN || force_iommu))
+ if (!iommu_detected && !no_iommu && end_pfn > MAX_DMA32_PFN)
swiotlb = 1;
+ if (swiotlb_force)
+ swiotlb = 1;
if (swiotlb) {
printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n");
swiotlb_init();
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index 5a1c0a3bf87..06af6ca6012 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -203,7 +203,7 @@ int __cpuinit init_smp_flush(void)
{
int i;
for_each_cpu_mask(i, cpu_possible_map) {
- spin_lock_init(&per_cpu(flush_state.tlbstate_lock, i));
+ spin_lock_init(&per_cpu(flush_state, i).tlbstate_lock);
}
return 0;
}
diff --git a/arch/x86_64/kernel/tce.c b/arch/x86_64/kernel/tce.c
index d3a9e79e954..5530dda3f27 100644
--- a/arch/x86_64/kernel/tce.c
+++ b/arch/x86_64/kernel/tce.c
@@ -96,7 +96,6 @@ static inline unsigned int table_size_to_number_of_entries(unsigned char size)
static int tce_table_setparms(struct pci_dev *dev, struct iommu_table *tbl)
{
unsigned int bitmapsz;
- unsigned int tce_table_index;
unsigned long bmppages;
int ret;
@@ -105,8 +104,7 @@ static int tce_table_setparms(struct pci_dev *dev, struct iommu_table *tbl)
/* set the tce table size - measured in entries */
tbl->it_size = table_size_to_number_of_entries(specified_table_size);
- tce_table_index = bus_to_phb(tbl->it_busno);
- tbl->it_base = (unsigned long)tce_table_kva[tce_table_index];
+ tbl->it_base = (unsigned long)tce_table_kva[dev->bus->number];
if (!tbl->it_base) {
printk(KERN_ERR "Calgary: iommu_table_setparms: "
"no table allocated?!\n");
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index b9ff75992c1..7a9b1822418 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -28,6 +28,7 @@
#include <linux/acpi.h>
#ifdef CONFIG_ACPI
#include <acpi/achware.h> /* for PM timer frequency */
+#include <acpi/acpi_bus.h>
#endif
#include <asm/8253pit.h>
#include <asm/pgtable.h>
@@ -193,7 +194,7 @@ unsigned long profile_pc(struct pt_regs *regs)
is just accounted to the spinlock function.
Better would be to write these functions in assembler again
and check exactly. */
- if (in_lock_functions(pc)) {
+ if (!user_mode(regs) && in_lock_functions(pc)) {
char *v = *(char **)regs->rsp;
if ((v >= _stext && v <= _etext) ||
(v >= _sinittext && v <= _einittext) ||
@@ -953,11 +954,18 @@ __cpuinit int unsynchronized_tsc(void)
#ifdef CONFIG_SMP
if (apic_is_clustered_box())
return 1;
- /* Intel systems are normally all synchronized. Exceptions
- are handled in the check above. */
- if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
- return 0;
#endif
+ /* Most intel systems have synchronized TSCs except for
+ multi node systems */
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
+#ifdef CONFIG_ACPI
+ /* But TSC doesn't tick in C3 so don't use it there */
+ if (acpi_fadt.length > 0 && acpi_fadt.plvl3_lat < 100)
+ return 1;
+#endif
+ return 0;
+ }
+
/* Assume multi socket systems are not synchronized */
return num_present_cpus() > 1;
}
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index eb39a277523..4e9938dee06 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -254,7 +254,6 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
{
const unsigned cpu = safe_smp_processor_id();
unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
- int i = 11;
unsigned used = 0;
printk("\nCall Trace:\n");
@@ -275,11 +274,20 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
if (unwind_init_blocked(&info, tsk) == 0)
unw_ret = show_trace_unwind(&info, NULL);
}
- if (unw_ret > 0) {
- if (call_trace > 0)
+ if (unw_ret > 0 && !arch_unw_user_mode(&info)) {
+#ifdef CONFIG_STACK_UNWIND
+ unsigned long rip = info.regs.rip;
+ print_symbol("DWARF2 unwinder stuck at %s\n", rip);
+ if (call_trace == 1) {
+ printk("Leftover inexact backtrace:\n");
+ stack = (unsigned long *)info.regs.rsp;
+ } else if (call_trace > 1)
return;
- printk("Legacy call trace:");
- i = 18;
+ else
+ printk("Full inexact backtrace again:\n");
+#else
+ printk("Inexact backtrace:\n");
+#endif
}
}
@@ -521,7 +529,7 @@ void __kprobes oops_end(unsigned long flags)
/* Nest count reaches zero, release the lock. */
spin_unlock_irqrestore(&die_lock, flags);
if (panic_on_oops)
- panic("Oops");
+ panic("Fatal exception: panic_on_oops");
}
void __kprobes __die(const char * str, struct pt_regs * regs, long err)
@@ -1118,8 +1126,10 @@ static int __init call_trace_setup(char *s)
call_trace = -1;
else if (strcmp(s, "both") == 0)
call_trace = 0;
- else if (strcmp(s, "new") == 0)
+ else if (strcmp(s, "newfallback") == 0)
call_trace = 1;
+ else if (strcmp(s, "new") == 0)
+ call_trace = 2;
return 1;
}
__setup("call_trace=", call_trace_setup);
diff --git a/arch/x86_64/pci/k8-bus.c b/arch/x86_64/pci/k8-bus.c
index b50a7c7c47f..3acf60ded2a 100644
--- a/arch/x86_64/pci/k8-bus.c
+++ b/arch/x86_64/pci/k8-bus.c
@@ -2,7 +2,6 @@
#include <linux/pci.h>
#include <asm/mpspec.h>
#include <linux/cpumask.h>
-#include <asm/k8.h>
/*
* This discovers the pcibus <-> node mapping on AMD K8.
@@ -19,6 +18,7 @@
#define NR_LDT_BUS_NUMBER_REGISTERS 3
#define SECONDARY_LDT_BUS_NUMBER(dword) ((dword >> 8) & 0xFF)
#define SUBORDINATE_LDT_BUS_NUMBER(dword) ((dword >> 16) & 0xFF)
+#define PCI_DEVICE_ID_K8HTCONFIG 0x1100
/**
* fill_mp_bus_to_cpumask()
@@ -28,7 +28,8 @@
__init static int
fill_mp_bus_to_cpumask(void)
{
- int i, j, k;
+ struct pci_dev *nb_dev = NULL;
+ int i, j;
u32 ldtbus, nid;
static int lbnr[3] = {
LDT_BUS_NUMBER_REGISTER_0,
@@ -36,9 +37,8 @@ fill_mp_bus_to_cpumask(void)
LDT_BUS_NUMBER_REGISTER_2
};
- cache_k8_northbridges();
- for (k = 0; k < num_k8_northbridges; k++) {
- struct pci_dev *nb_dev = k8_northbridges[k];
+ while ((nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+ PCI_DEVICE_ID_K8HTCONFIG, nb_dev))) {
pci_read_config_dword(nb_dev, NODE_ID_REGISTER, &nid);
for (i = 0; i < NR_LDT_BUS_NUMBER_REGISTERS; i++) {
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 27e409089a7..9734960a245 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -487,11 +487,9 @@ void die(const char * str, struct pt_regs * regs, long err)
if (in_interrupt())
panic("Fatal exception in interrupt");
- if (panic_on_oops) {
- printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
- ssleep(5);
- panic("Fatal exception");
- }
+ if (panic_on_oops)
+ panic("Fatal exception: panic_on_oops");
+
do_exit(err);
}
diff --git a/block/blktrace.c b/block/blktrace.c
index b8c0702777f..265f7a83061 100644
--- a/block/blktrace.c
+++ b/block/blktrace.c
@@ -80,7 +80,7 @@ static u32 bio_act[5] __read_mostly = { 0, BLK_TC_ACT(BLK_TC_BARRIER), BLK_TC_AC
#define trace_sync_bit(rw) \
(((rw) & (1 << BIO_RW_SYNC)) >> (BIO_RW_SYNC - 1))
#define trace_ahead_bit(rw) \
- (((rw) & (1 << BIO_RW_AHEAD)) << (BIO_RW_AHEAD - 0))
+ (((rw) & (1 << BIO_RW_AHEAD)) << (2 - BIO_RW_AHEAD))
/*
* The worker for the various blk_add_trace*() types. Fills out a
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 102ebc2c5c3..aae3123bf3e 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -936,7 +936,7 @@ static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
* seeks. so allow a little bit of time for him to submit a new rq
*/
if (sample_valid(cic->seek_samples) && CIC_SEEKY(cic))
- sl = 2;
+ sl = min(sl, msecs_to_jiffies(2));
mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
return 1;
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 81e970adeab..b0d4b147b19 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -129,11 +129,15 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
struct acpi_memory_info *info, *n;
+ if (!list_empty(&mem_device->res_list))
+ return 0;
+
status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS,
acpi_memory_get_resource, mem_device);
if (ACPI_FAILURE(status)) {
list_for_each_entry_safe(info, n, &mem_device->res_list, list)
kfree(info);
+ INIT_LIST_HEAD(&mem_device->res_list);
return -EINVAL;
}
@@ -230,17 +234,10 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
* (i.e. memory-hot-remove function)
*/
list_for_each_entry(info, &mem_device->res_list, list) {
- u64 start_pfn, end_pfn;
-
- start_pfn = info->start_addr >> PAGE_SHIFT;
- end_pfn = (info->start_addr + info->length - 1) >> PAGE_SHIFT;
-
- if (pfn_valid(start_pfn) || pfn_valid(end_pfn)) {
- /* already enabled. try next area */
+ if (info->enabled) { /* just sanity check...*/
num_enabled++;
continue;
}
-
result = add_memory(node, info->start_addr, info->length);
if (result)
continue;
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 1c0a39d8b04..578b99b71d9 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -58,8 +58,8 @@ struct dock_dependent_device {
};
#define DOCK_DOCKING 0x00000001
-#define DOCK_EVENT KOBJ_DOCK
-#define UNDOCK_EVENT KOBJ_UNDOCK
+#define DOCK_EVENT 3
+#define UNDOCK_EVENT 2
static struct dock_station *dock_station;
@@ -322,11 +322,10 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
static void dock_event(struct dock_station *ds, u32 event, int num)
{
- struct acpi_device *device;
-
- device = dock_create_acpi_device(ds->handle);
- if (device)
- kobject_uevent(&device->kobj, num);
+ /*
+ * we don't do events until someone tells me that
+ * they would like to have them.
+ */
}
/**
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index c2d62163238..3ef9d514b91 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -139,7 +139,7 @@ static int __cpuinit topology_sysfs_init(void)
(void *)(long)i);
}
- register_cpu_notifier(&topology_cpu_notifier);
+ register_hotcpu_notifier(&topology_cpu_notifier);
return 0;
}
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 1c4df22dfd2..7b0eca703a6 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1233,6 +1233,50 @@ static inline void complete_buffers(struct bio *bio, int status)
}
}
+static void cciss_check_queues(ctlr_info_t *h)
+{
+ int start_queue = h->next_to_run;
+ int i;
+
+ /* check to see if we have maxed out the number of commands that can
+ * be placed on the queue. If so then exit. We do this check here
+ * in case the interrupt we serviced was from an ioctl and did not
+ * free any new commands.
+ */
+ if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS)
+ return;
+
+ /* We have room on the queue for more commands. Now we need to queue
+ * them up. We will also keep track of the next queue to run so
+ * that every queue gets a chance to be started first.
+ */
+ for (i = 0; i < h->highest_lun + 1; i++) {
+ int curr_queue = (start_queue + i) % (h->highest_lun + 1);
+ /* make sure the disk has been added and the drive is real
+ * because this can be called from the middle of init_one.
+ */
+ if (!(h->drv[curr_queue].queue) || !(h->drv[curr_queue].heads))
+ continue;
+ blk_start_queue(h->gendisk[curr_queue]->queue);
+
+ /* check to see if we have maxed out the number of commands
+ * that can be placed on the queue.
+ */
+ if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS) {
+ if (curr_queue == start_queue) {
+ h->next_to_run =
+ (start_queue + 1) % (h->highest_lun + 1);
+ break;
+ } else {
+ h->next_to_run = curr_queue;
+ break;
+ }
+ } else {
+ curr_queue = (curr_queue + 1) % (h->highest_lun + 1);
+ }
+ }
+}
+
static void cciss_softirq_done(struct request *rq)
{
CommandList_struct *cmd = rq->completion_data;
@@ -1264,6 +1308,7 @@ static void cciss_softirq_done(struct request *rq)
spin_lock_irqsave(&h->lock, flags);
end_that_request_last(rq, rq->errors);
cmd_free(h, cmd, 1);
+ cciss_check_queues(h);
spin_unlock_irqrestore(&h->lock, flags);
}
@@ -2528,8 +2573,6 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
CommandList_struct *c;
unsigned long flags;
__u32 a, a1, a2;
- int j;
- int start_queue = h->next_to_run;
if (interrupt_not_for_us(h))
return IRQ_NONE;
@@ -2588,45 +2631,6 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
}
}
- /* check to see if we have maxed out the number of commands that can
- * be placed on the queue. If so then exit. We do this check here
- * in case the interrupt we serviced was from an ioctl and did not
- * free any new commands.
- */
- if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS)
- goto cleanup;
-
- /* We have room on the queue for more commands. Now we need to queue
- * them up. We will also keep track of the next queue to run so
- * that every queue gets a chance to be started first.
- */
- for (j = 0; j < h->highest_lun + 1; j++) {
- int curr_queue = (start_queue + j) % (h->highest_lun + 1);
- /* make sure the disk has been added and the drive is real
- * because this can be called from the middle of init_one.
- */
- if (!(h->drv[curr_queue].queue) || !(h->drv[curr_queue].heads))
- continue;
- blk_start_queue(h->gendisk[curr_queue]->queue);
-
- /* check to see if we have maxed out the number of commands
- * that can be placed on the queue.
- */
- if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS) {
- if (curr_queue == start_queue) {
- h->next_to_run =
- (start_queue + 1) % (h->highest_lun + 1);
- goto cleanup;
- } else {
- h->next_to_run = curr_queue;
- goto cleanup;
- }
- } else {
- curr_queue = (curr_queue + 1) % (h->highest_lun + 1);
- }
- }
-
- cleanup:
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
return IRQ_HANDLED;
}
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 0a1b1ea36dd..bdbade9a5cf 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -300,6 +300,15 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
lo->disk->disk_name, result);
goto harderror;
}
+
+ if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
+ printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
+ lo->disk->disk_name,
+ (unsigned long)ntohl(reply.magic));
+ result = -EPROTO;
+ goto harderror;
+ }
+
req = nbd_find_request(lo, reply.handle);
if (unlikely(IS_ERR(req))) {
result = PTR_ERR(req);
@@ -312,13 +321,6 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
goto harderror;
}
- if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
- printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
- lo->disk->disk_name,
- (unsigned long)ntohl(reply.magic));
- result = -EPROTO;
- goto harderror;
- }
if (ntohl(reply.error)) {
printk(KERN_ERR "%s: Other side returned error (%d)\n",
lo->disk->disk_name, ntohl(reply.error));
@@ -339,7 +341,8 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
printk(KERN_ERR "%s: Receive data failed (result %d)\n",
lo->disk->disk_name,
result);
- goto harderror;
+ req->errors++;
+ return req;
}
dprintk(DBG_RX, "%s: request %p: got %d bytes data\n",
lo->disk->disk_name, req, bvec->bv_len);
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index bde2c64b634..451b996bba9 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2577,19 +2577,19 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm
case PKT_CTRL_CMD_SETUP:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- mutex_lock(&ctl_mutex);
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
ret = pkt_setup_dev(&ctrl_cmd);
mutex_unlock(&ctl_mutex);
break;
case PKT_CTRL_CMD_TEARDOWN:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- mutex_lock(&ctl_mutex);
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
ret = pkt_remove_dev(&ctrl_cmd);
mutex_unlock(&ctl_mutex);
break;
case PKT_CTRL_CMD_STATUS:
- mutex_lock(&ctl_mutex);
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
pkt_get_status(&ctrl_cmd);
mutex_unlock(&ctl_mutex);
break;
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 6a0c2230f82..e2d4beac742 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -67,6 +67,8 @@ static int ignore = 0;
static int ignore_dga = 0;
static int ignore_csr = 0;
static int ignore_sniffer = 0;
+static int disable_scofix = 0;
+static int force_scofix = 0;
static int reset = 0;
#ifdef CONFIG_BT_HCIUSB_SCO
@@ -107,9 +109,12 @@ static struct usb_device_id blacklist_ids[] = {
{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE },
/* Broadcom BCM2035 */
- { USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET | HCI_BROKEN_ISOC },
+ { USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = HCI_BCM92035 },
+ /* IBM/Lenovo ThinkPad with Broadcom chip */
+ { USB_DEVICE(0x0a5c, 0x201e), .driver_info = HCI_WRONG_SCO_MTU },
+
/* Microsoft Wireless Transceiver for Bluetooth 2.0 */
{ USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET },
@@ -119,11 +124,13 @@ static struct usb_device_id blacklist_ids[] = {
/* ISSC Bluetooth Adapter v3.1 */
{ USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET },
- /* RTX Telecom based adapter with buggy SCO support */
+ /* RTX Telecom based adapters with buggy SCO support */
{ USB_DEVICE(0x0400, 0x0807), .driver_info = HCI_BROKEN_ISOC },
+ { USB_DEVICE(0x0400, 0x080a), .driver_info = HCI_BROKEN_ISOC },
- /* Belkin F8T012 */
+ /* Belkin F8T012 and F8T013 devices */
{ USB_DEVICE(0x050d, 0x0012), .driver_info = HCI_WRONG_SCO_MTU },
+ { USB_DEVICE(0x050d, 0x0013), .driver_info = HCI_WRONG_SCO_MTU },
/* Digianswer devices */
{ USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER },
@@ -990,8 +997,10 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id
if (reset || id->driver_info & HCI_RESET)
set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
- if (id->driver_info & HCI_WRONG_SCO_MTU)
- set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
+ if (force_scofix || id->driver_info & HCI_WRONG_SCO_MTU) {
+ if (!disable_scofix)
+ set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
+ }
if (id->driver_info & HCI_SNIFFER) {
if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
@@ -1161,6 +1170,12 @@ MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001");
module_param(ignore_sniffer, bool, 0644);
MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002");
+module_param(disable_scofix, bool, 0644);
+MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size");
+
+module_param(force_scofix, bool, 0644);
+MODULE_PARM_DESC(force_scofix, "Force fixup of wrong SCO buffers size");
+
module_param(reset, bool, 0644);
MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index 41db8060e8f..017f755632a 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -311,7 +311,8 @@ static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet,
/* CD went away; no more connection */
pr_debug("hvsi%i: CD dropped\n", hp->index);
hp->mctrl &= TIOCM_CD;
- if (!(hp->tty->flags & CLOCAL))
+ /* If userland hasn't done an open(2) yet, hp->tty is NULL. */
+ if (hp->tty && !(hp->tty->flags & CLOCAL))
*to_hangup = hp->tty;
}
break;
@@ -986,10 +987,7 @@ static void hvsi_write_worker(void *arg)
start_j = 0;
#endif /* DEBUG */
wake_up_all(&hp->emptyq);
- if (test_bit(TTY_DO_WRITE_WAKEUP, &hp->tty->flags)
- && hp->tty->ldisc.write_wakeup)
- hp->tty->ldisc.write_wakeup(hp->tty);
- wake_up_interruptible(&hp->tty->write_wait);
+ tty_wakeup(hp->tty);
}
out:
diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c
index be61f22ee7b..d37ced0d132 100644
--- a/drivers/char/hw_random/geode-rng.c
+++ b/drivers/char/hw_random/geode-rng.c
@@ -107,10 +107,14 @@ found:
if (err) {
printk(KERN_ERR PFX "RNG registering failed (%d)\n",
err);
- goto out;
+ goto err_unmap;
}
out:
return err;
+
+err_unmap:
+ iounmap(mem);
+ goto out;
}
static void __exit mod_exit(void)
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
index 6594bd5645f..ccd7e710223 100644
--- a/drivers/char/hw_random/intel-rng.c
+++ b/drivers/char/hw_random/intel-rng.c
@@ -164,7 +164,7 @@ static int __init mod_init(void)
if (err) {
printk(KERN_ERR PFX "RNG registering failed (%d)\n",
err);
- goto out;
+ goto err_unmap;
}
out:
return err;
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 819516b35a7..a01d796d1ee 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -25,12 +25,12 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/random.h>
+#include <linux/clk.h>
#include <linux/err.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/hw_random.h>
#include <asm/io.h>
-#include <asm/hardware/clock.h>
#define RNG_OUT_REG 0x00 /* Output register */
#define RNG_STAT_REG 0x04 /* Status register
@@ -52,7 +52,7 @@
static void __iomem *rng_base;
static struct clk *rng_ick;
-static struct device *rng_dev;
+static struct platform_device *rng_dev;
static u32 omap_rng_read_reg(int reg)
{
@@ -83,9 +83,8 @@ static struct hwrng omap_rng_ops = {
.data_read = omap_rng_data_read,
};
-static int __init omap_rng_probe(struct device *dev)
+static int __init omap_rng_probe(struct platform_device *pdev)
{
- struct platform_device *pdev = to_platform_device(dev);
struct resource *res, *mem;
int ret;
@@ -95,16 +94,14 @@ static int __init omap_rng_probe(struct device *dev)
*/
BUG_ON(rng_dev);
- if (cpu_is_omap24xx()) {
+ if (cpu_is_omap24xx()) {
rng_ick = clk_get(NULL, "rng_ick");
if (IS_ERR(rng_ick)) {
- dev_err(dev, "Could not get rng_ick\n");
+ dev_err(&pdev->dev, "Could not get rng_ick\n");
ret = PTR_ERR(rng_ick);
return ret;
- }
- else {
- clk_use(rng_ick);
- }
+ } else
+ clk_enable(rng_ick);
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -117,7 +114,7 @@ static int __init omap_rng_probe(struct device *dev)
if (mem == NULL)
return -EBUSY;
- dev_set_drvdata(dev, mem);
+ dev_set_drvdata(&pdev->dev, mem);
rng_base = (u32 __iomem *)io_p2v(res->start);
ret = hwrng_register(&omap_rng_ops);
@@ -127,25 +124,25 @@ static int __init omap_rng_probe(struct device *dev)
return ret;
}
- dev_info(dev, "OMAP Random Number Generator ver. %02x\n",
+ dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n",
omap_rng_read_reg(RNG_REV_REG));
omap_rng_write_reg(RNG_MASK_REG, 0x1);
- rng_dev = dev;
+ rng_dev = pdev;
return 0;
}
-static int __exit omap_rng_remove(struct device *dev)
+static int __exit omap_rng_remove(struct platform_device *pdev)
{
- struct resource *mem = dev_get_drvdata(dev);
+ struct resource *mem = dev_get_drvdata(&pdev->dev);
hwrng_unregister(&omap_rng_ops);
omap_rng_write_reg(RNG_MASK_REG, 0x0);
if (cpu_is_omap24xx()) {
- clk_unuse(rng_ick);
+ clk_disable(rng_ick);
clk_put(rng_ick);
}
@@ -157,18 +154,16 @@ static int __exit omap_rng_remove(struct device *dev)
#ifdef CONFIG_PM
-static int omap_rng_suspend(struct device *dev, pm_message_t message, u32 level)
+static int omap_rng_suspend(struct platform_device *pdev, pm_message_t message)
{
omap_rng_write_reg(RNG_MASK_REG, 0x0);
-
return 0;
}
-static int omap_rng_resume(struct device *dev, pm_message_t message, u32 level)
+static int omap_rng_resume(struct platform_device *pdev)
{
omap_rng_write_reg(RNG_MASK_REG, 0x1);
-
- return 1;
+ return 0;
}
#else
@@ -179,9 +174,11 @@ static int omap_rng_resume(struct device *dev, pm_message_t message, u32 level)
#endif
-static struct device_driver omap_rng_driver = {
- .name = "omap_rng",
- .bus = &platform_bus_type,
+static struct platform_driver omap_rng_driver = {
+ .driver = {
+ .name = "omap_rng",
+ .owner = THIS_MODULE,
+ },
.probe = omap_rng_probe,
.remove = __exit_p(omap_rng_remove),
.suspend = omap_rng_suspend,
@@ -193,12 +190,12 @@ static int __init omap_rng_init(void)
if (!cpu_is_omap16xx() && !cpu_is_omap24xx())
return -ENODEV;
- return driver_register(&omap_rng_driver);
+ return platform_driver_register(&omap_rng_driver);
}
static void __exit omap_rng_exit(void)
{
- driver_unregister(&omap_rng_driver);
+ platform_driver_unregister(&omap_rng_driver);
}
module_init(omap_rng_init);
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 056ebe84b81..3e90aac3751 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -107,7 +107,6 @@ const int NR_TYPES = ARRAY_SIZE(max_vals);
struct kbd_struct kbd_table[MAX_NR_CONSOLES];
static struct kbd_struct *kbd = kbd_table;
-static struct kbd_struct kbd0;
int spawnpid, spawnsig;
@@ -223,13 +222,13 @@ static void kd_nosound(unsigned long ignored)
{
struct list_head *node;
- list_for_each(node,&kbd_handler.h_list) {
+ list_for_each(node, &kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
if (test_bit(EV_SND, handle->dev->evbit)) {
if (test_bit(SND_TONE, handle->dev->sndbit))
- input_event(handle->dev, EV_SND, SND_TONE, 0);
+ input_inject_event(handle, EV_SND, SND_TONE, 0);
if (test_bit(SND_BELL, handle->dev->sndbit))
- input_event(handle->dev, EV_SND, SND_BELL, 0);
+ input_inject_event(handle, EV_SND, SND_BELL, 0);
}
}
}
@@ -247,11 +246,11 @@ void kd_mksound(unsigned int hz, unsigned int ticks)
struct input_handle *handle = to_handle_h(node);
if (test_bit(EV_SND, handle->dev->evbit)) {
if (test_bit(SND_TONE, handle->dev->sndbit)) {
- input_event(handle->dev, EV_SND, SND_TONE, hz);
+ input_inject_event(handle, EV_SND, SND_TONE, hz);
break;
}
if (test_bit(SND_BELL, handle->dev->sndbit)) {
- input_event(handle->dev, EV_SND, SND_BELL, 1);
+ input_inject_event(handle, EV_SND, SND_BELL, 1);
break;
}
}
@@ -272,15 +271,15 @@ int kbd_rate(struct kbd_repeat *rep)
unsigned int d = 0;
unsigned int p = 0;
- list_for_each(node,&kbd_handler.h_list) {
+ list_for_each(node, &kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
struct input_dev *dev = handle->dev;
if (test_bit(EV_REP, dev->evbit)) {
if (rep->delay > 0)
- input_event(dev, EV_REP, REP_DELAY, rep->delay);
+ input_inject_event(handle, EV_REP, REP_DELAY, rep->delay);
if (rep->period > 0)
- input_event(dev, EV_REP, REP_PERIOD, rep->period);
+ input_inject_event(handle, EV_REP, REP_PERIOD, rep->period);
d = dev->rep[REP_DELAY];
p = dev->rep[REP_PERIOD];
}
@@ -988,7 +987,7 @@ static inline unsigned char getleds(void)
* interrupt routines for this thing allows us to easily mask
* this when we don't want any of the above to happen.
* This allows for easy and efficient race-condition prevention
- * for kbd_refresh_leds => input_event(dev, EV_LED, ...) => ...
+ * for kbd_start => input_inject_event(dev, EV_LED, ...) => ...
*/
static void kbd_bh(unsigned long dummy)
@@ -998,11 +997,11 @@ static void kbd_bh(unsigned long dummy)
if (leds != ledstate) {
list_for_each(node, &kbd_handler.h_list) {
- struct input_handle * handle = to_handle_h(node);
- input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
- input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02));
- input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04));
- input_sync(handle->dev);
+ struct input_handle *handle = to_handle_h(node);
+ input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
+ input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
+ input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
+ input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
}
}
@@ -1011,23 +1010,6 @@ static void kbd_bh(unsigned long dummy)
DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
-/*
- * This allows a newly plugged keyboard to pick the LED state.
- */
-static void kbd_refresh_leds(struct input_handle *handle)
-{
- unsigned char leds = ledstate;
-
- tasklet_disable(&keyboard_tasklet);
- if (leds != 0xff) {
- input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
- input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02));
- input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04));
- input_sync(handle->dev);
- }
- tasklet_enable(&keyboard_tasklet);
-}
-
#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
@@ -1043,7 +1025,7 @@ static const unsigned short x86_keycodes[256] =
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92,
- 284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339,
+ 284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339,
367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361,
@@ -1065,38 +1047,55 @@ extern void sun_do_break(void);
static int emulate_raw(struct vc_data *vc, unsigned int keycode,
unsigned char up_flag)
{
- if (keycode > 255 || !x86_keycodes[keycode])
- return -1;
+ int code;
switch (keycode) {
case KEY_PAUSE:
put_queue(vc, 0xe1);
put_queue(vc, 0x1d | up_flag);
put_queue(vc, 0x45 | up_flag);
- return 0;
+ break;
+
case KEY_HANGEUL:
if (!up_flag)
put_queue(vc, 0xf2);
- return 0;
+ break;
+
case KEY_HANJA:
if (!up_flag)
put_queue(vc, 0xf1);
- return 0;
- }
+ break;
- if (keycode == KEY_SYSRQ && sysrq_alt) {
- put_queue(vc, 0x54 | up_flag);
- return 0;
- }
+ case KEY_SYSRQ:
+ /*
+ * Real AT keyboards (that's what we're trying
+ * to emulate here emit 0xe0 0x2a 0xe0 0x37 when
+ * pressing PrtSc/SysRq alone, but simply 0x54
+ * when pressing Alt+PrtSc/SysRq.
+ */
+ if (sysrq_alt) {
+ put_queue(vc, 0x54 | up_flag);
+ } else {
+ put_queue(vc, 0xe0);
+ put_queue(vc, 0x2a | up_flag);
+ put_queue(vc, 0xe0);
+ put_queue(vc, 0x37 | up_flag);
+ }
+ break;
+
+ default:
+ if (keycode > 255)
+ return -1;
- if (x86_keycodes[keycode] & 0x100)
- put_queue(vc, 0xe0);
+ code = x86_keycodes[keycode];
+ if (!code)
+ return -1;
- put_queue(vc, (x86_keycodes[keycode] & 0x7f) | up_flag);
+ if (code & 0x100)
+ put_queue(vc, 0xe0);
+ put_queue(vc, (code & 0x7f) | up_flag);
- if (keycode == KEY_SYSRQ) {
- put_queue(vc, 0xe0);
- put_queue(vc, 0x37 | up_flag);
+ break;
}
return 0;
@@ -1298,16 +1297,15 @@ static struct input_handle *kbd_connect(struct input_handler *handler,
if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
return NULL;
- if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
+ handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
+ if (!handle)
return NULL;
- memset(handle, 0, sizeof(struct input_handle));
handle->dev = dev;
handle->handler = handler;
handle->name = "kbd";
input_open_device(handle);
- kbd_refresh_leds(handle);
return handle;
}
@@ -1318,6 +1316,24 @@ static void kbd_disconnect(struct input_handle *handle)
kfree(handle);
}
+/*
+ * Start keyboard handler on the new keyboard by refreshing LED state to
+ * match the rest of the system.
+ */
+static void kbd_start(struct input_handle *handle)
+{
+ unsigned char leds = ledstate;
+
+ tasklet_disable(&keyboard_tasklet);
+ if (leds != 0xff) {
+ input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
+ input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
+ input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
+ input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
+ }
+ tasklet_enable(&keyboard_tasklet);
+}
+
static struct input_device_id kbd_ids[] = {
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
@@ -1338,6 +1354,7 @@ static struct input_handler kbd_handler = {
.event = kbd_event,
.connect = kbd_connect,
.disconnect = kbd_disconnect,
+ .start = kbd_start,
.name = "kbd",
.id_table = kbd_ids,
};
@@ -1346,15 +1363,15 @@ int __init kbd_init(void)
{
int i;
- kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
- kbd0.ledmode = LED_SHOW_FLAGS;
- kbd0.lockstate = KBD_DEFLOCK;
- kbd0.slockstate = 0;
- kbd0.modeflags = KBD_DEFMODE;
- kbd0.kbdmode = VC_XLATE;
-
- for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
- kbd_table[i] = kbd0;
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ kbd_table[i].ledflagstate = KBD_DEFLEDS;
+ kbd_table[i].default_ledflagstate = KBD_DEFLEDS;
+ kbd_table[i].ledmode = LED_SHOW_FLAGS;
+ kbd_table[i].lockstate = KBD_DEFLOCK;
+ kbd_table[i].slockstate = 0;
+ kbd_table[i].modeflags = KBD_DEFMODE;
+ kbd_table[i].kbdmode = VC_XLATE;
+ }
input_register_handler(&kbd_handler);
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c
index 645eb81cb5a..84e5a68635f 100644
--- a/drivers/char/pc8736x_gpio.c
+++ b/drivers/char/pc8736x_gpio.c
@@ -221,7 +221,6 @@ static struct nsc_gpio_ops pc8736x_gpio_ops = {
.gpio_change = pc8736x_gpio_change,
.gpio_current = pc8736x_gpio_current
};
-EXPORT_SYMBOL(pc8736x_gpio_ops);
static int pc8736x_gpio_open(struct inode *inode, struct file *file)
{
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 17bc8abd5df..00f574cbb0d 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -1174,8 +1174,12 @@ static void dcd_change(MGSLPC_INFO *info)
else
info->input_signal_events.dcd_down++;
#ifdef CONFIG_HDLC
- if (info->netcount)
- hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, info->netdev);
+ if (info->netcount) {
+ if (info->serial_signals & SerialSignal_DCD)
+ netif_carrier_on(info->netdev);
+ else
+ netif_carrier_off(info->netdev);
+ }
#endif
wake_up_interruptible(&info->status_event_wait_q);
wake_up_interruptible(&info->event_wait_q);
@@ -4251,8 +4255,10 @@ static int hdlcdev_open(struct net_device *dev)
spin_lock_irqsave(&info->lock, flags);
get_signals(info);
spin_unlock_irqrestore(&info->lock, flags);
- hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev);
-
+ if (info->serial_signals & SerialSignal_DCD)
+ netif_carrier_on(dev);
+ else
+ netif_carrier_off(dev);
return 0;
}
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index afc6eda602f..07e0b75f233 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -374,7 +374,12 @@ scdrv_init(void)
struct sysctl_data_s *scd;
void *salbuf;
dev_t first_dev, dev;
- nasid_t event_nasid = ia64_sn_get_console_nasid();
+ nasid_t event_nasid;
+
+ if (!ia64_platform_is("sn2"))
+ return -ENODEV;
+
+ event_nasid = ia64_sn_get_console_nasid();
if (alloc_chrdev_region(&first_dev, 0, num_cnodes,
SYSCTL_BASENAME) < 0) {
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index df782dd1098..78b1b1a2732 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -1344,8 +1344,12 @@ static void mgsl_isr_io_pin( struct mgsl_struct *info )
} else
info->input_signal_events.dcd_down++;
#ifdef CONFIG_HDLC
- if (info->netcount)
- hdlc_set_carrier(status & MISCSTATUS_DCD, info->netdev);
+ if (info->netcount) {
+ if (status & MISCSTATUS_DCD)
+ netif_carrier_on(info->netdev);
+ else
+ netif_carrier_off(info->netdev);
+ }
#endif
}
if (status & MISCSTATUS_CTS_LATCHED)
@@ -7844,8 +7848,10 @@ static int hdlcdev_open(struct net_device *dev)
spin_lock_irqsave(&info->irq_spinlock, flags);
usc_get_serial_signals(info);
spin_unlock_irqrestore(&info->irq_spinlock, flags);
- hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev);
-
+ if (info->serial_signals & SerialSignal_DCD)
+ netif_carrier_on(dev);
+ else
+ netif_carrier_off(dev);
return 0;
}
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index e829594195c..b2dbbdb1bf8 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -1497,8 +1497,10 @@ static int hdlcdev_open(struct net_device *dev)
spin_lock_irqsave(&info->lock, flags);
get_signals(info);
spin_unlock_irqrestore(&info->lock, flags);
- hdlc_set_carrier(info->signals & SerialSignal_DCD, dev);
-
+ if (info->signals & SerialSignal_DCD)
+ netif_carrier_on(dev);
+ else
+ netif_carrier_off(dev);
return 0;
}
@@ -1997,8 +1999,12 @@ static void dcd_change(struct slgt_info *info)
info->input_signal_events.dcd_down++;
}
#ifdef CONFIG_HDLC
- if (info->netcount)
- hdlc_set_carrier(info->signals & SerialSignal_DCD, info->netdev);
+ if (info->netcount) {
+ if (info->signals & SerialSignal_DCD)
+ netif_carrier_on(info->netdev);
+ else
+ netif_carrier_off(info->netdev);
+ }
#endif
wake_up_interruptible(&info->status_event_wait_q);
wake_up_interruptible(&info->event_wait_q);
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 1e443a233f5..66f3754fbbd 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -1752,8 +1752,10 @@ static int hdlcdev_open(struct net_device *dev)
spin_lock_irqsave(&info->lock, flags);
get_signals(info);
spin_unlock_irqrestore(&info->lock, flags);
- hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev);
-
+ if (info->serial_signals & SerialSignal_DCD)
+ netif_carrier_on(dev);
+ else
+ netif_carrier_off(dev);
return 0;
}
@@ -2522,8 +2524,12 @@ void isr_io_pin( SLMP_INFO *info, u16 status )
} else
info->input_signal_events.dcd_down++;
#ifdef CONFIG_HDLC
- if (info->netcount)
- hdlc_set_carrier(status & SerialSignal_DCD, info->netdev);
+ if (info->netcount) {
+ if (status & SerialSignal_DCD)
+ netif_carrier_on(info->netdev);
+ else
+ netif_carrier_off(info->netdev);
+ }
#endif
}
if (status & MISCSTATUS_CTS_LATCHED)
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 498aa37bca2..3ece6923134 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -51,6 +51,7 @@ void proc_fork_connector(struct task_struct *task)
struct cn_msg *msg;
struct proc_event *ev;
__u8 buffer[CN_PROC_MSG_SIZE];
+ struct timespec ts;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
@@ -58,7 +59,8 @@ void proc_fork_connector(struct task_struct *task)
msg = (struct cn_msg*)buffer;
ev = (struct proc_event*)msg->data;
get_seq(&msg->seq, &ev->cpu);
- ktime_get_ts(&ev->timestamp); /* get high res monotonic timestamp */
+ ktime_get_ts(&ts); /* get high res monotonic timestamp */
+ ev->timestamp_ns = timespec_to_ns(&ts);
ev->what = PROC_EVENT_FORK;
ev->event_data.fork.parent_pid = task->real_parent->pid;
ev->event_data.fork.parent_tgid = task->real_parent->tgid;
@@ -76,6 +78,7 @@ void proc_exec_connector(struct task_struct *task)
{
struct cn_msg *msg;
struct proc_event *ev;
+ struct timespec ts;
__u8 buffer[CN_PROC_MSG_SIZE];
if (atomic_read(&proc_event_num_listeners) < 1)
@@ -84,7 +87,8 @@ void proc_exec_connector(struct task_struct *task)
msg = (struct cn_msg*)buffer;
ev = (struct proc_event*)msg->data;
get_seq(&msg->seq, &ev->cpu);
- ktime_get_ts(&ev->timestamp);
+ ktime_get_ts(&ts); /* get high res monotonic timestamp */
+ ev->timestamp_ns = timespec_to_ns(&ts);
ev->what = PROC_EVENT_EXEC;
ev->event_data.exec.process_pid = task->pid;
ev->event_data.exec.process_tgid = task->tgid;
@@ -100,6 +104,7 @@ void proc_id_connector(struct task_struct *task, int which_id)
struct cn_msg *msg;
struct proc_event *ev;
__u8 buffer[CN_PROC_MSG_SIZE];
+ struct timespec ts;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
@@ -118,7 +123,8 @@ void proc_id_connector(struct task_struct *task, int which_id)
} else
return;
get_seq(&msg->seq, &ev->cpu);
- ktime_get_ts(&ev->timestamp);
+ ktime_get_ts(&ts); /* get high res monotonic timestamp */
+ ev->timestamp_ns = timespec_to_ns(&ts);
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
msg->ack = 0; /* not used */
@@ -131,6 +137,7 @@ void proc_exit_connector(struct task_struct *task)
struct cn_msg *msg;
struct proc_event *ev;
__u8 buffer[CN_PROC_MSG_SIZE];
+ struct timespec ts;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
@@ -138,7 +145,8 @@ void proc_exit_connector(struct task_struct *task)
msg = (struct cn_msg*)buffer;
ev = (struct proc_event*)msg->data;
get_seq(&msg->seq, &ev->cpu);
- ktime_get_ts(&ev->timestamp);
+ ktime_get_ts(&ts); /* get high res monotonic timestamp */
+ ev->timestamp_ns = timespec_to_ns(&ts);
ev->what = PROC_EVENT_EXIT;
ev->event_data.exit.process_pid = task->pid;
ev->event_data.exit.process_tgid = task->tgid;
@@ -164,6 +172,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
struct cn_msg *msg;
struct proc_event *ev;
__u8 buffer[CN_PROC_MSG_SIZE];
+ struct timespec ts;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
@@ -171,7 +180,8 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
msg = (struct cn_msg*)buffer;
ev = (struct proc_event*)msg->data;
msg->seq = rcvd_seq;
- ktime_get_ts(&ev->timestamp);
+ ktime_get_ts(&ts); /* get high res monotonic timestamp */
+ ev->timestamp_ns = timespec_to_ns(&ts);
ev->cpu = -1;
ev->what = PROC_EVENT_NONE;
ev->event_data.ack.err = err;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 8d328186f77..b3df613ae4e 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -284,39 +284,69 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
* SYSFS INTERFACE *
*********************************************************************/
+static struct cpufreq_governor *__find_governor(const char *str_governor)
+{
+ struct cpufreq_governor *t;
+
+ list_for_each_entry(t, &cpufreq_governor_list, governor_list)
+ if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN))
+ return t;
+
+ return NULL;
+}
+
/**
* cpufreq_parse_governor - parse a governor string
*/
static int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
struct cpufreq_governor **governor)
{
+ int err = -EINVAL;
+
if (!cpufreq_driver)
- return -EINVAL;
+ goto out;
+
if (cpufreq_driver->setpolicy) {
if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
*policy = CPUFREQ_POLICY_PERFORMANCE;
- return 0;
+ err = 0;
} else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
*policy = CPUFREQ_POLICY_POWERSAVE;
- return 0;
+ err = 0;
}
- return -EINVAL;
- } else {
+ } else if (cpufreq_driver->target) {
struct cpufreq_governor *t;
+
mutex_lock(&cpufreq_governor_mutex);
- if (!cpufreq_driver || !cpufreq_driver->target)
- goto out;
- list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
- if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
- *governor = t;
+
+ t = __find_governor(str_governor);
+
+ if (t == NULL) {
+ char *name = kasprintf(GFP_KERNEL, "cpufreq_%s", str_governor);
+
+ if (name) {
+ int ret;
+
mutex_unlock(&cpufreq_governor_mutex);
- return 0;
+ ret = request_module(name);
+ mutex_lock(&cpufreq_governor_mutex);
+
+ if (ret == 0)
+ t = __find_governor(str_governor);
}
+
+ kfree(name);
}
-out:
+
+ if (t != NULL) {
+ *governor = t;
+ err = 0;
+ }
+
mutex_unlock(&cpufreq_governor_mutex);
}
- return -EINVAL;
+ out:
+ return err;
}
@@ -364,10 +394,12 @@ static ssize_t store_##file_name \
if (ret != 1) \
return -EINVAL; \
\
+ lock_cpu_hotplug(); \
mutex_lock(&policy->lock); \
ret = __cpufreq_set_policy(policy, &new_policy); \
policy->user_policy.object = policy->object; \
mutex_unlock(&policy->lock); \
+ unlock_cpu_hotplug(); \
\
return ret ? ret : count; \
}
@@ -1197,20 +1229,18 @@ EXPORT_SYMBOL(cpufreq_unregister_notifier);
*********************************************************************/
+/* Must be called with lock_cpu_hotplug held */
int __cpufreq_driver_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
int retval = -EINVAL;
- lock_cpu_hotplug();
dprintk("target for CPU %u: %u kHz, relation %u\n", policy->cpu,
target_freq, relation);
if (cpu_online(policy->cpu) && cpufreq_driver->target)
retval = cpufreq_driver->target(policy, target_freq, relation);
- unlock_cpu_hotplug();
-
return retval;
}
EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
@@ -1225,17 +1255,23 @@ int cpufreq_driver_target(struct cpufreq_policy *policy,
if (!policy)
return -EINVAL;
+ lock_cpu_hotplug();
mutex_lock(&policy->lock);
ret = __cpufreq_driver_target(policy, target_freq, relation);
mutex_unlock(&policy->lock);
+ unlock_cpu_hotplug();
cpufreq_cpu_put(policy);
return ret;
}
EXPORT_SYMBOL_GPL(cpufreq_driver_target);
+/*
+ * Locking: Must be called with the lock_cpu_hotplug() lock held
+ * when "event" is CPUFREQ_GOV_LIMITS
+ */
static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
{
@@ -1257,43 +1293,23 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
}
-int cpufreq_governor(unsigned int cpu, unsigned int event)
-{
- int ret = 0;
- struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
-
- if (!policy)
- return -EINVAL;
-
- mutex_lock(&policy->lock);
- ret = __cpufreq_governor(policy, event);
- mutex_unlock(&policy->lock);
-
- cpufreq_cpu_put(policy);
- return ret;
-}
-EXPORT_SYMBOL_GPL(cpufreq_governor);
-
-
int cpufreq_register_governor(struct cpufreq_governor *governor)
{
- struct cpufreq_governor *t;
+ int err;
if (!governor)
return -EINVAL;
mutex_lock(&cpufreq_governor_mutex);
- list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
- if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) {
- mutex_unlock(&cpufreq_governor_mutex);
- return -EBUSY;
- }
+ err = -EBUSY;
+ if (__find_governor(governor->name) == NULL) {
+ err = 0;
+ list_add(&governor->governor_list, &cpufreq_governor_list);
}
- list_add(&governor->governor_list, &cpufreq_governor_list);
mutex_unlock(&cpufreq_governor_mutex);
- return 0;
+ return err;
}
EXPORT_SYMBOL_GPL(cpufreq_register_governor);
@@ -1342,6 +1358,9 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
EXPORT_SYMBOL(cpufreq_get_policy);
+/*
+ * Locking: Must be called with the lock_cpu_hotplug() lock held
+ */
static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy)
{
int ret = 0;
@@ -1352,6 +1371,11 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo));
+ if (policy->min > data->min && policy->min > policy->max) {
+ ret = -EINVAL;
+ goto error_out;
+ }
+
/* verify the cpu speed can be set within this limit */
ret = cpufreq_driver->verify(policy);
if (ret)
@@ -1436,6 +1460,8 @@ int cpufreq_set_policy(struct cpufreq_policy *policy)
if (!data)
return -EINVAL;
+ lock_cpu_hotplug();
+
/* lock this CPU */
mutex_lock(&data->lock);
@@ -1446,6 +1472,8 @@ int cpufreq_set_policy(struct cpufreq_policy *policy)
data->user_policy.governor = data->governor;
mutex_unlock(&data->lock);
+
+ unlock_cpu_hotplug();
cpufreq_cpu_put(data);
return ret;
@@ -1469,6 +1497,7 @@ int cpufreq_update_policy(unsigned int cpu)
if (!data)
return -ENODEV;
+ lock_cpu_hotplug();
mutex_lock(&data->lock);
dprintk("updating policy for CPU %u\n", cpu);
@@ -1494,7 +1523,7 @@ int cpufreq_update_policy(unsigned int cpu)
ret = __cpufreq_set_policy(data, &policy);
mutex_unlock(&data->lock);
-
+ unlock_cpu_hotplug();
cpufreq_cpu_put(data);
return ret;
}
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index b3ebc8f0197..c4c578defab 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -525,7 +525,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
break;
case CPUFREQ_GOV_LIMITS:
- lock_cpu_hotplug();
mutex_lock(&dbs_mutex);
if (policy->max < this_dbs_info->cur_policy->cur)
__cpufreq_driver_target(
@@ -536,7 +535,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
this_dbs_info->cur_policy,
policy->min, CPUFREQ_RELATION_L);
mutex_unlock(&dbs_mutex);
- unlock_cpu_hotplug();
break;
}
return 0;
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 87299924e73..52cf1f02182 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -239,6 +239,8 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
total_ticks = (unsigned int) cputime64_sub(cur_jiffies,
this_dbs_info->prev_cpu_wall);
this_dbs_info->prev_cpu_wall = cur_jiffies;
+ if (!total_ticks)
+ return;
/*
* Every sampling_rate, we check, if current idle time is less
* than 20% (default), then we try to increase frequency
@@ -304,7 +306,12 @@ static void do_dbs_timer(void *data)
unsigned int cpu = smp_processor_id();
struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu);
+ if (!dbs_info->enable)
+ return;
+
+ lock_cpu_hotplug();
dbs_check_cpu(dbs_info);
+ unlock_cpu_hotplug();
queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work,
usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
}
@@ -319,11 +326,11 @@ static inline void dbs_timer_init(unsigned int cpu)
return;
}
-static inline void dbs_timer_exit(unsigned int cpu)
+static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
{
- struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu);
-
- cancel_rearming_delayed_workqueue(kondemand_wq, &dbs_info->work);
+ dbs_info->enable = 0;
+ cancel_delayed_work(&dbs_info->work);
+ flush_workqueue(kondemand_wq);
}
static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
@@ -396,8 +403,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
case CPUFREQ_GOV_STOP:
mutex_lock(&dbs_mutex);
- dbs_timer_exit(policy->cpu);
- this_dbs_info->enable = 0;
+ dbs_timer_exit(this_dbs_info);
sysfs_remove_group(&policy->kobj, &dbs_attr_group);
dbs_enable--;
if (dbs_enable == 0)
@@ -408,7 +414,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
break;
case CPUFREQ_GOV_LIMITS:
- lock_cpu_hotplug();
mutex_lock(&dbs_mutex);
if (policy->max < this_dbs_info->cur_policy->cur)
__cpufreq_driver_target(this_dbs_info->cur_policy,
@@ -419,7 +424,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
policy->min,
CPUFREQ_RELATION_L);
mutex_unlock(&dbs_mutex);
- unlock_cpu_hotplug();
break;
}
return 0;
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index 44ae5e5b94c..a06c204589c 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -18,6 +18,7 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/cpufreq.h>
+#include <linux/cpu.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/sysfs.h>
@@ -70,6 +71,7 @@ static int cpufreq_set(unsigned int freq, struct cpufreq_policy *policy)
dprintk("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
+ lock_cpu_hotplug();
mutex_lock(&userspace_mutex);
if (!cpu_is_managed[policy->cpu])
goto err;
@@ -92,6 +94,7 @@ static int cpufreq_set(unsigned int freq, struct cpufreq_policy *policy)
err:
mutex_unlock(&userspace_mutex);
+ unlock_cpu_hotplug();
return ret;
}
diff --git a/drivers/dma/ioatdma.c b/drivers/dma/ioatdma.c
index 78bf46d917b..dbd4d6c3698 100644
--- a/drivers/dma/ioatdma.c
+++ b/drivers/dma/ioatdma.c
@@ -828,7 +828,7 @@ static int __init ioat_init_module(void)
/* if forced, worst case is that rmmod hangs */
__unsafe(THIS_MODULE);
- return pci_module_init(&ioat_pci_drv);
+ return pci_register_driver(&ioat_pci_drv);
}
module_init(ioat_init_module);
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
index bf6ab8a8d5e..a1cfd4e3c97 100644
--- a/drivers/edac/edac_mc.h
+++ b/drivers/edac/edac_mc.h
@@ -29,6 +29,7 @@
#include <linux/rcupdate.h>
#include <linux/completion.h>
#include <linux/kobject.h>
+#include <linux/platform_device.h>
#define EDAC_MC_LABEL_LEN 31
#define MC_PROC_NAME_MAX_LEN 7
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c
index 66d03f242d3..1a159e8843c 100644
--- a/drivers/fc4/fc.c
+++ b/drivers/fc4/fc.c
@@ -429,7 +429,7 @@ static inline void fcp_scsi_receive(fc_channel *fc, int token, int status, fc_hd
if (fcmd->data) {
if (SCpnt->use_sg)
- dma_unmap_sg(fc->dev, (struct scatterlist *)SCpnt->buffer,
+ dma_unmap_sg(fc->dev, (struct scatterlist *)SCpnt->request_buffer,
SCpnt->use_sg,
SCpnt->sc_data_direction);
else
@@ -810,7 +810,7 @@ static int fcp_scsi_queue_it(fc_channel *fc, Scsi_Cmnd *SCpnt, fcp_cmnd *fcmd, i
SCpnt->request_bufflen,
SCpnt->sc_data_direction);
} else {
- struct scatterlist *sg = (struct scatterlist *)SCpnt->buffer;
+ struct scatterlist *sg = (struct scatterlist *)SCpnt->request_buffer;
int nents;
FCD(("XXX: Use_sg %d %d\n", SCpnt->use_sg, sg->length))
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index ced309ff056..eae9e81be37 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -232,7 +232,7 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface)
unsigned long timeout;
timeout = jiffies + POLL_TIMEOUT;
- while (time_before(jiffies, timeout)) {
+ while (1) {
status = inb(ACBST);
/* Reset the status register to avoid the hang */
@@ -242,7 +242,10 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface)
scx200_acb_machine(iface, status);
return;
}
- yield();
+ if (time_after(jiffies, timeout))
+ break;
+ cpu_relax();
+ cond_resched();
}
dev_err(&iface->adapter.dev, "timeout in state %s\n",
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index d1266fe2d1a..b6fb167e20f 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -682,6 +682,7 @@ config BLK_DEV_SVWKS
config BLK_DEV_SGIIOC4
tristate "Silicon Graphics IOC4 chipset ATA/ATAPI support"
depends on (IA64_SGI_SN2 || IA64_GENERIC) && SGI_IOC4
+ select IDEPCI_SHARE_IRQ
help
This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4
chipset, which has one channel and can support two devices.
@@ -773,20 +774,6 @@ config BLK_DEV_IDEDMA_PMAC
to transfer data to and from memory. Saying Y is safe and improves
performance.
-config BLK_DEV_IDE_PMAC_BLINK
- bool "Blink laptop LED on drive activity (DEPRECATED)"
- depends on BLK_DEV_IDE_PMAC && ADB_PMU
- select ADB_PMU_LED
- select LEDS_TRIGGERS
- select LEDS_TRIGGER_IDE_DISK
- help
- This option enables the use of the sleep LED as a hard drive
- activity LED.
- This option is deprecated, it only selects ADB_PMU_LED and
- LEDS_TRIGGER_IDE_DISK and changes the code in the new led class
- device to default to the ide-disk trigger (which should be set
- from userspace via sysfs).
-
config BLK_DEV_IDE_SWARM
tristate "IDE for Sibyte evaluation boards"
depends on SIBYTE_SB1xxx_SOC
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index f712e4cfd9d..7cf3eb02352 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -776,7 +776,7 @@ static void update_ordered(ide_drive_t *drive)
* not available so we don't need to recheck that.
*/
capacity = idedisk_capacity(drive);
- barrier = ide_id_has_flush_cache(id) &&
+ barrier = ide_id_has_flush_cache(id) && !drive->noflush &&
(drive->addressing == 0 || capacity <= (1ULL << 28) ||
ide_id_has_flush_cache_ext(id));
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 98918fb6b2c..7c3a13e1cf6 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -750,7 +750,7 @@ void ide_dma_verbose(ide_drive_t *drive)
goto bug_dma_off;
printk(", DMA");
} else if (id->field_valid & 1) {
- printk(", BUG");
+ goto bug_dma_off;
}
return;
bug_dma_off:
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 657165297dc..77703acaec1 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -23,6 +23,7 @@
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/bitops.h>
+#include <linux/nmi.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
@@ -1243,6 +1244,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
if (stat == 0xff)
return -ENODEV;
touch_softlockup_watchdog();
+ touch_nmi_watchdog();
}
return -EBUSY;
}
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 05fbd9298db..defd4b4bd37 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1539,7 +1539,7 @@ static int __init ide_setup(char *s)
const char *hd_words[] = {
"none", "noprobe", "nowerr", "cdrom", "serialize",
"autotune", "noautotune", "minus8", "swapdata", "bswap",
- "minus11", "remap", "remap63", "scsi", NULL };
+ "noflush", "remap", "remap63", "scsi", NULL };
unit = s[2] - 'a';
hw = unit / MAX_DRIVES;
unit = unit % MAX_DRIVES;
@@ -1578,6 +1578,9 @@ static int __init ide_setup(char *s)
case -10: /* "bswap" */
drive->bswap = 1;
goto done;
+ case -11: /* noflush */
+ drive->noflush = 1;
+ goto done;
case -12: /* "remap" */
drive->remap_0_to_1 = 1;
goto done;
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 3cb04424d35..e9bad185968 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -498,9 +498,14 @@ static int config_chipset_for_dma (ide_drive_t *drive)
{
u8 speed = ide_dma_speed(drive, it821x_ratemask(drive));
- config_it821x_chipset_for_pio(drive, !speed);
- it821x_tune_chipset(drive, speed);
- return ide_dma_enable(drive);
+ if (speed) {
+ config_it821x_chipset_for_pio(drive, 0);
+ it821x_tune_chipset(drive, speed);
+
+ return ide_dma_enable(drive);
+ }
+
+ return 0;
}
/**
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index aaa74f293aa..b08755e2e68 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -2515,6 +2515,9 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev)
sdev->skip_ms_page_8 = 1;
if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
sdev->fix_capacity = 1;
+ if (scsi_id->ne->guid_vendor_id == 0x0010b9 && /* Maxtor's OUI */
+ (sdev->type == TYPE_DISK || sdev->type == TYPE_RBC))
+ sdev->allow_restart = 1;
return 0;
}
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index d294bbc42f0..1205e802782 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -35,6 +35,7 @@
#include <net/arp.h>
#include <net/neighbour.h>
#include <net/route.h>
+#include <net/netevent.h>
#include <rdma/ib_addr.h>
MODULE_AUTHOR("Sean Hefty");
@@ -326,25 +327,22 @@ void rdma_addr_cancel(struct rdma_dev_addr *addr)
}
EXPORT_SYMBOL(rdma_addr_cancel);
-static int addr_arp_recv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pkt, struct net_device *orig_dev)
+static int netevent_callback(struct notifier_block *self, unsigned long event,
+ void *ctx)
{
- struct arphdr *arp_hdr;
+ if (event == NETEVENT_NEIGH_UPDATE) {
+ struct neighbour *neigh = ctx;
- arp_hdr = (struct arphdr *) skb->nh.raw;
-
- if (arp_hdr->ar_op == htons(ARPOP_REQUEST) ||
- arp_hdr->ar_op == htons(ARPOP_REPLY))
- set_timeout(jiffies);
-
- kfree_skb(skb);
+ if (neigh->dev->type == ARPHRD_INFINIBAND &&
+ (neigh->nud_state & NUD_VALID)) {
+ set_timeout(jiffies);
+ }
+ }
return 0;
}
-static struct packet_type addr_arp = {
- .type = __constant_htons(ETH_P_ARP),
- .func = addr_arp_recv,
- .af_packet_priv = (void*) 1,
+static struct notifier_block nb = {
+ .notifier_call = netevent_callback
};
static int addr_init(void)
@@ -353,13 +351,13 @@ static int addr_init(void)
if (!addr_wq)
return -ENOMEM;
- dev_add_pack(&addr_arp);
+ register_netevent_notifier(&nb);
return 0;
}
static void addr_cleanup(void)
{
- dev_remove_pack(&addr_arp);
+ unregister_netevent_notifier(&nb);
destroy_workqueue(addr_wq);
}
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index f85c97f7500..0de335b7bfc 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -975,8 +975,10 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,
cm_id_priv->timewait_info = cm_create_timewait_info(cm_id_priv->
id.local_id);
- if (IS_ERR(cm_id_priv->timewait_info))
+ if (IS_ERR(cm_id_priv->timewait_info)) {
+ ret = PTR_ERR(cm_id_priv->timewait_info);
goto out;
+ }
ret = cm_init_av_by_path(param->primary_path, &cm_id_priv->av);
if (ret)
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 5ed4dab52a6..1c3cfbbe6a9 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -167,6 +167,15 @@ static int is_vendor_method_in_use(
return 0;
}
+int ib_response_mad(struct ib_mad *mad)
+{
+ return ((mad->mad_hdr.method & IB_MGMT_METHOD_RESP) ||
+ (mad->mad_hdr.method == IB_MGMT_METHOD_TRAP_REPRESS) ||
+ ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_BM) &&
+ (mad->mad_hdr.attr_mod & IB_BM_ATTR_MOD_RESP)));
+}
+EXPORT_SYMBOL(ib_response_mad);
+
/*
* ib_register_mad_agent - Register to send/receive MADs
*/
@@ -570,13 +579,6 @@ int ib_unregister_mad_agent(struct ib_mad_agent *mad_agent)
}
EXPORT_SYMBOL(ib_unregister_mad_agent);
-static inline int response_mad(struct ib_mad *mad)
-{
- /* Trap represses are responses although response bit is reset */
- return ((mad->mad_hdr.method == IB_MGMT_METHOD_TRAP_REPRESS) ||
- (mad->mad_hdr.method & IB_MGMT_METHOD_RESP));
-}
-
static void dequeue_mad(struct ib_mad_list_head *mad_list)
{
struct ib_mad_queue *mad_queue;
@@ -723,7 +725,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
switch (ret)
{
case IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY:
- if (response_mad(&mad_priv->mad.mad) &&
+ if (ib_response_mad(&mad_priv->mad.mad) &&
mad_agent_priv->agent.recv_handler) {
local->mad_priv = mad_priv;
local->recv_mad_agent = mad_agent_priv;
@@ -1551,7 +1553,7 @@ find_mad_agent(struct ib_mad_port_private *port_priv,
unsigned long flags;
spin_lock_irqsave(&port_priv->reg_lock, flags);
- if (response_mad(mad)) {
+ if (ib_response_mad(mad)) {
u32 hi_tid;
struct ib_mad_agent_private *entry;
@@ -1799,7 +1801,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
}
/* Complete corresponding request */
- if (response_mad(mad_recv_wc->recv_buf.mad)) {
+ if (ib_response_mad(mad_recv_wc->recv_buf.mad)) {
spin_lock_irqsave(&mad_agent_priv->lock, flags);
mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc);
if (!mad_send_wr) {
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index afe70a549c2..1273f8807e8 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -112,8 +112,10 @@ struct ib_umad_device {
struct ib_umad_file {
struct ib_umad_port *port;
struct list_head recv_list;
+ struct list_head send_list;
struct list_head port_list;
spinlock_t recv_lock;
+ spinlock_t send_lock;
wait_queue_head_t recv_wait;
struct ib_mad_agent *agent[IB_UMAD_MAX_AGENTS];
int agents_dead;
@@ -177,12 +179,21 @@ static int queue_packet(struct ib_umad_file *file,
return ret;
}
+static void dequeue_send(struct ib_umad_file *file,
+ struct ib_umad_packet *packet)
+ {
+ spin_lock_irq(&file->send_lock);
+ list_del(&packet->list);
+ spin_unlock_irq(&file->send_lock);
+ }
+
static void send_handler(struct ib_mad_agent *agent,
struct ib_mad_send_wc *send_wc)
{
struct ib_umad_file *file = agent->context;
struct ib_umad_packet *packet = send_wc->send_buf->context[0];
+ dequeue_send(file, packet);
ib_destroy_ah(packet->msg->ah);
ib_free_send_mad(packet->msg);
@@ -370,6 +381,51 @@ static int copy_rmpp_mad(struct ib_mad_send_buf *msg, const char __user *buf)
return 0;
}
+static int same_destination(struct ib_user_mad_hdr *hdr1,
+ struct ib_user_mad_hdr *hdr2)
+{
+ if (!hdr1->grh_present && !hdr2->grh_present)
+ return (hdr1->lid == hdr2->lid);
+
+ if (hdr1->grh_present && hdr2->grh_present)
+ return !memcmp(hdr1->gid, hdr2->gid, 16);
+
+ return 0;
+}
+
+static int is_duplicate(struct ib_umad_file *file,
+ struct ib_umad_packet *packet)
+{
+ struct ib_umad_packet *sent_packet;
+ struct ib_mad_hdr *sent_hdr, *hdr;
+
+ hdr = (struct ib_mad_hdr *) packet->mad.data;
+ list_for_each_entry(sent_packet, &file->send_list, list) {
+ sent_hdr = (struct ib_mad_hdr *) sent_packet->mad.data;
+
+ if ((hdr->tid != sent_hdr->tid) ||
+ (hdr->mgmt_class != sent_hdr->mgmt_class))
+ continue;
+
+ /*
+ * No need to be overly clever here. If two new operations have
+ * the same TID, reject the second as a duplicate. This is more
+ * restrictive than required by the spec.
+ */
+ if (!ib_response_mad((struct ib_mad *) hdr)) {
+ if (!ib_response_mad((struct ib_mad *) sent_hdr))
+ return 1;
+ continue;
+ } else if (!ib_response_mad((struct ib_mad *) sent_hdr))
+ continue;
+
+ if (same_destination(&packet->mad.hdr, &sent_packet->mad.hdr))
+ return 1;
+ }
+
+ return 0;
+}
+
static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
size_t count, loff_t *pos)
{
@@ -379,7 +435,6 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
struct ib_ah_attr ah_attr;
struct ib_ah *ah;
struct ib_rmpp_mad *rmpp_mad;
- u8 method;
__be64 *tid;
int ret, data_len, hdr_len, copy_offset, rmpp_active;
@@ -473,28 +528,36 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
}
/*
- * If userspace is generating a request that will generate a
- * response, we need to make sure the high-order part of the
- * transaction ID matches the agent being used to send the
- * MAD.
+ * Set the high-order part of the transaction ID to make MADs from
+ * different agents unique, and allow routing responses back to the
+ * original requestor.
*/
- method = ((struct ib_mad_hdr *) packet->msg->mad)->method;
-
- if (!(method & IB_MGMT_METHOD_RESP) &&
- method != IB_MGMT_METHOD_TRAP_REPRESS &&
- method != IB_MGMT_METHOD_SEND) {
+ if (!ib_response_mad(packet->msg->mad)) {
tid = &((struct ib_mad_hdr *) packet->msg->mad)->tid;
*tid = cpu_to_be64(((u64) agent->hi_tid) << 32 |
(be64_to_cpup(tid) & 0xffffffff));
+ rmpp_mad->mad_hdr.tid = *tid;
+ }
+
+ spin_lock_irq(&file->send_lock);
+ ret = is_duplicate(file, packet);
+ if (!ret)
+ list_add_tail(&packet->list, &file->send_list);
+ spin_unlock_irq(&file->send_lock);
+ if (ret) {
+ ret = -EINVAL;
+ goto err_msg;
}
ret = ib_post_send_mad(packet->msg, NULL);
if (ret)
- goto err_msg;
+ goto err_send;
up_read(&file->port->mutex);
return count;
+err_send:
+ dequeue_send(file, packet);
err_msg:
ib_free_send_mad(packet->msg);
err_ah:
@@ -657,7 +720,9 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
}
spin_lock_init(&file->recv_lock);
+ spin_lock_init(&file->send_lock);
INIT_LIST_HEAD(&file->recv_list);
+ INIT_LIST_HEAD(&file->send_list);
init_waitqueue_head(&file->recv_wait);
file->port = port;
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index bb9bee56a82..102a59c033f 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -42,6 +42,7 @@
#include <linux/kref.h>
#include <linux/idr.h>
#include <linux/mutex.h>
+#include <linux/completion.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_user_verbs.h>
@@ -69,6 +70,7 @@
struct ib_uverbs_device {
struct kref ref;
+ struct completion comp;
int devnum;
struct cdev *dev;
struct class_device *class_dev;
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index bdf5d509819..30923eb68ec 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -42,6 +42,13 @@
#include "uverbs.h"
+static struct lock_class_key pd_lock_key;
+static struct lock_class_key mr_lock_key;
+static struct lock_class_key cq_lock_key;
+static struct lock_class_key qp_lock_key;
+static struct lock_class_key ah_lock_key;
+static struct lock_class_key srq_lock_key;
+
#define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \
do { \
(udata)->inbuf = (void __user *) (ibuf); \
@@ -76,12 +83,13 @@
*/
static void init_uobj(struct ib_uobject *uobj, u64 user_handle,
- struct ib_ucontext *context)
+ struct ib_ucontext *context, struct lock_class_key *key)
{
uobj->user_handle = user_handle;
uobj->context = context;
kref_init(&uobj->ref);
init_rwsem(&uobj->mutex);
+ lockdep_set_class(&uobj->mutex, key);
uobj->live = 0;
}
@@ -470,7 +478,7 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
if (!uobj)
return -ENOMEM;
- init_uobj(uobj, 0, file->ucontext);
+ init_uobj(uobj, 0, file->ucontext, &pd_lock_key);
down_write(&uobj->mutex);
pd = file->device->ib_dev->alloc_pd(file->device->ib_dev,
@@ -591,7 +599,7 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
if (!obj)
return -ENOMEM;
- init_uobj(&obj->uobject, 0, file->ucontext);
+ init_uobj(&obj->uobject, 0, file->ucontext, &mr_lock_key);
down_write(&obj->uobject.mutex);
/*
@@ -770,7 +778,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
if (!obj)
return -ENOMEM;
- init_uobj(&obj->uobject, cmd.user_handle, file->ucontext);
+ init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &cq_lock_key);
down_write(&obj->uobject.mutex);
if (cmd.comp_channel >= 0) {
@@ -1051,13 +1059,14 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
if (!obj)
return -ENOMEM;
- init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext);
+ init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
down_write(&obj->uevent.uobject.mutex);
+ srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL;
pd = idr_read_pd(cmd.pd_handle, file->ucontext);
scq = idr_read_cq(cmd.send_cq_handle, file->ucontext);
- rcq = idr_read_cq(cmd.recv_cq_handle, file->ucontext);
- srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL;
+ rcq = cmd.recv_cq_handle == cmd.send_cq_handle ?
+ scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext);
if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) {
ret = -EINVAL;
@@ -1125,7 +1134,8 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
put_pd_read(pd);
put_cq_read(scq);
- put_cq_read(rcq);
+ if (rcq != scq)
+ put_cq_read(rcq);
if (srq)
put_srq_read(srq);
@@ -1150,7 +1160,7 @@ err_put:
put_pd_read(pd);
if (scq)
put_cq_read(scq);
- if (rcq)
+ if (rcq && rcq != scq)
put_cq_read(rcq);
if (srq)
put_srq_read(srq);
@@ -1751,7 +1761,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
if (!uobj)
return -ENOMEM;
- init_uobj(uobj, cmd.user_handle, file->ucontext);
+ init_uobj(uobj, cmd.user_handle, file->ucontext, &ah_lock_key);
down_write(&uobj->mutex);
pd = idr_read_pd(cmd.pd_handle, file->ucontext);
@@ -1775,7 +1785,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
ah = ib_create_ah(pd, &attr);
if (IS_ERR(ah)) {
ret = PTR_ERR(ah);
- goto err;
+ goto err_put;
}
ah->uobject = uobj;
@@ -1811,6 +1821,9 @@ err_copy:
err_destroy:
ib_destroy_ah(ah);
+err_put:
+ put_pd_read(pd);
+
err:
put_uobj_write(uobj);
return ret;
@@ -1963,7 +1976,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
if (!obj)
return -ENOMEM;
- init_uobj(&obj->uobject, cmd.user_handle, file->ucontext);
+ init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &srq_lock_key);
down_write(&obj->uobject.mutex);
pd = idr_read_pd(cmd.pd_handle, file->ucontext);
@@ -1984,7 +1997,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
srq = pd->device->create_srq(pd, &attr, &udata);
if (IS_ERR(srq)) {
ret = PTR_ERR(srq);
- goto err;
+ goto err_put;
}
srq->device = pd->device;
@@ -2029,6 +2042,9 @@ err_copy:
err_destroy:
ib_destroy_srq(srq);
+err_put:
+ put_pd_read(pd);
+
err:
put_uobj_write(&obj->uobject);
return ret;
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index e725cccc7cd..4e16314e8e6 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -122,7 +122,7 @@ static void ib_uverbs_release_dev(struct kref *ref)
struct ib_uverbs_device *dev =
container_of(ref, struct ib_uverbs_device, ref);
- kfree(dev);
+ complete(&dev->comp);
}
void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
@@ -740,6 +740,7 @@ static void ib_uverbs_add_one(struct ib_device *device)
return;
kref_init(&uverbs_dev->ref);
+ init_completion(&uverbs_dev->comp);
spin_lock(&map_lock);
uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -793,6 +794,8 @@ err_cdev:
err:
kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
+ wait_for_completion(&uverbs_dev->comp);
+ kfree(uverbs_dev);
return;
}
@@ -812,7 +815,10 @@ static void ib_uverbs_remove_one(struct ib_device *device)
spin_unlock(&map_lock);
clear_bit(uverbs_dev->devnum, dev_map);
+
kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
+ wait_for_completion(&uverbs_dev->comp);
+ kfree(uverbs_dev);
}
static int uverbs_event_get_sb(struct file_system_type *fs_type, int flags,
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index 823131d58b3..f98518d912b 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -859,6 +859,38 @@ static void ipath_rcv_layer(struct ipath_devdata *dd, u32 etail,
__ipath_layer_rcv_lid(dd, hdr);
}
+static void ipath_rcv_hdrerr(struct ipath_devdata *dd,
+ u32 eflags,
+ u32 l,
+ u32 etail,
+ u64 *rc)
+{
+ char emsg[128];
+ struct ipath_message_header *hdr;
+
+ get_rhf_errstring(eflags, emsg, sizeof emsg);
+ hdr = (struct ipath_message_header *)&rc[1];
+ ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u "
+ "tlen=%x opcode=%x egridx=%x: %s\n",
+ eflags, l,
+ ipath_hdrget_rcv_type((__le32 *) rc),
+ ipath_hdrget_length_in_bytes((__le32 *) rc),
+ be32_to_cpu(hdr->bth[0]) >> 24,
+ etail, emsg);
+
+ /* Count local link integrity errors. */
+ if (eflags & (INFINIPATH_RHF_H_ICRCERR | INFINIPATH_RHF_H_VCRCERR)) {
+ u8 n = (dd->ipath_ibcctrl >>
+ INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) &
+ INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK;
+
+ if (++dd->ipath_lli_counter > n) {
+ dd->ipath_lli_counter = 0;
+ dd->ipath_lli_errors++;
+ }
+ }
+}
+
/*
* ipath_kreceive - receive a packet
* @dd: the infinipath device
@@ -875,7 +907,6 @@ void ipath_kreceive(struct ipath_devdata *dd)
struct ipath_message_header *hdr;
u32 eflags, i, etype, tlen, pkttot = 0, updegr=0, reloop=0;
static u64 totcalls; /* stats, may eventually remove */
- char emsg[128];
if (!dd->ipath_hdrqtailptr) {
ipath_dev_err(dd,
@@ -938,26 +969,9 @@ reloop:
"%x\n", etype);
}
- if (eflags & ~(INFINIPATH_RHF_H_TIDERR |
- INFINIPATH_RHF_H_IHDRERR)) {
- get_rhf_errstring(eflags, emsg, sizeof emsg);
- ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u "
- "tlen=%x opcode=%x egridx=%x: %s\n",
- eflags, l, etype, tlen, bthbytes[0],
- ipath_hdrget_index((__le32 *) rc), emsg);
- /* Count local link integrity errors. */
- if (eflags & (INFINIPATH_RHF_H_ICRCERR |
- INFINIPATH_RHF_H_VCRCERR)) {
- u8 n = (dd->ipath_ibcctrl >>
- INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) &
- INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK;
-
- if (++dd->ipath_lli_counter > n) {
- dd->ipath_lli_counter = 0;
- dd->ipath_lli_errors++;
- }
- }
- } else if (etype == RCVHQ_RCV_TYPE_NON_KD) {
+ if (unlikely(eflags))
+ ipath_rcv_hdrerr(dd, eflags, l, etail, rc);
+ else if (etype == RCVHQ_RCV_TYPE_NON_KD) {
int ret = __ipath_verbs_rcv(dd, rc + 1,
ebuf, tlen);
if (ret == -ENODEV)
@@ -981,25 +995,7 @@ reloop:
else if (etype == RCVHQ_RCV_TYPE_EXPECTED)
ipath_dbg("Bug: Expected TID, opcode %x; ignored\n",
be32_to_cpu(hdr->bth[0]) & 0xff);
- else if (eflags & (INFINIPATH_RHF_H_TIDERR |
- INFINIPATH_RHF_H_IHDRERR)) {
- /*
- * This is a type 3 packet, only the LRH is in the
- * rcvhdrq, the rest of the header is in the eager
- * buffer.
- */
- u8 opcode;
- if (ebuf) {
- bthbytes = (u8 *) ebuf;
- opcode = *bthbytes;
- }
- else
- opcode = 0;
- get_rhf_errstring(eflags, emsg, sizeof emsg);
- ipath_dbg("Err %x (%s), opcode %x, egrbuf %x, "
- "len %x\n", eflags, emsg, opcode, etail,
- tlen);
- } else {
+ else {
/*
* error packet, type of error unknown.
* Probably type 3, but we don't know, so don't
diff --git a/drivers/infiniband/hw/ipath/ipath_keys.c b/drivers/infiniband/hw/ipath/ipath_keys.c
index 46773c673a1..a5ca279370a 100644
--- a/drivers/infiniband/hw/ipath/ipath_keys.c
+++ b/drivers/infiniband/hw/ipath/ipath_keys.c
@@ -197,6 +197,21 @@ int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
size_t off;
int ret;
+ /*
+ * We use RKEY == zero for physical addresses
+ * (see ipath_get_dma_mr).
+ */
+ if (rkey == 0) {
+ sge->mr = NULL;
+ sge->vaddr = phys_to_virt(vaddr);
+ sge->length = len;
+ sge->sge_length = len;
+ ss->sg_list = NULL;
+ ss->num_sge = 1;
+ ret = 1;
+ goto bail;
+ }
+
mr = rkt->table[(rkey >> (32 - ib_ipath_lkey_table_size))];
if (unlikely(mr == NULL || mr->lkey != rkey)) {
ret = 0;
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
index 56ac336dd1e..d70a9b6b523 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -191,10 +191,6 @@ void ipath_skip_sge(struct ipath_sge_state *ss, u32 length)
{
struct ipath_sge *sge = &ss->sge;
- while (length > sge->sge_length) {
- length -= sge->sge_length;
- ss->sge = *ss->sg_list++;
- }
while (length) {
u32 len = sge->length;
@@ -627,6 +623,7 @@ static int ipath_query_device(struct ib_device *ibdev,
props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR |
IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT |
IB_DEVICE_SYS_IMAGE_GUID;
+ props->page_size_cap = PAGE_SIZE;
props->vendor_id = ipath_layer_get_vendorid(dev->dd);
props->vendor_part_id = ipath_layer_get_deviceid(dev->dd);
props->hw_ver = ipath_layer_get_pcirev(dev->dd);
diff --git a/drivers/infiniband/hw/mthca/mthca_allocator.c b/drivers/infiniband/hw/mthca/mthca_allocator.c
index 9ba3211cef7..25157f57a6d 100644
--- a/drivers/infiniband/hw/mthca/mthca_allocator.c
+++ b/drivers/infiniband/hw/mthca/mthca_allocator.c
@@ -108,14 +108,15 @@ void mthca_alloc_cleanup(struct mthca_alloc *alloc)
* serialize access to the array.
*/
+#define MTHCA_ARRAY_MASK (PAGE_SIZE / sizeof (void *) - 1)
+
void *mthca_array_get(struct mthca_array *array, int index)
{
int p = (index * sizeof (void *)) >> PAGE_SHIFT;
- if (array->page_list[p].page) {
- int i = index & (PAGE_SIZE / sizeof (void *) - 1);
- return array->page_list[p].page[i];
- } else
+ if (array->page_list[p].page)
+ return array->page_list[p].page[index & MTHCA_ARRAY_MASK];
+ else
return NULL;
}
@@ -130,8 +131,7 @@ int mthca_array_set(struct mthca_array *array, int index, void *value)
if (!array->page_list[p].page)
return -ENOMEM;
- array->page_list[p].page[index & (PAGE_SIZE / sizeof (void *) - 1)] =
- value;
+ array->page_list[p].page[index & MTHCA_ARRAY_MASK] = value;
++array->page_list[p].used;
return 0;
@@ -144,7 +144,8 @@ void mthca_array_clear(struct mthca_array *array, int index)
if (--array->page_list[p].used == 0) {
free_page((unsigned long) array->page_list[p].page);
array->page_list[p].page = NULL;
- }
+ } else
+ array->page_list[p].page[index & MTHCA_ARRAY_MASK] = NULL;
if (array->page_list[p].used < 0)
pr_debug("Array %p index %d page %d with ref count %d < 0\n",
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index d0f7731802c..deabc14b4ea 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -778,11 +778,12 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
((dev->fw_ver & 0xffff0000ull) >> 16) |
((dev->fw_ver & 0x0000ffffull) << 16);
+ MTHCA_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET);
+ dev->cmd.max_cmds = 1 << lg;
+
mthca_dbg(dev, "FW version %012llx, max commands %d\n",
(unsigned long long) dev->fw_ver, dev->cmd.max_cmds);
- MTHCA_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET);
- dev->cmd.max_cmds = 1 << lg;
MTHCA_GET(dev->catas_err.addr, outbox, QUERY_FW_ERR_START_OFFSET);
MTHCA_GET(dev->catas_err.size, outbox, QUERY_FW_ERR_SIZE_OFFSET);
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index fab417c5cf4..b60a9d79ae5 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -370,7 +370,8 @@ int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
return -EINVAL;
if (attr_mask & IB_SRQ_LIMIT) {
- if (attr->srq_limit > srq->max)
+ u32 max_wr = mthca_is_memfree(dev) ? srq->max - 1 : srq->max;
+ if (attr->srq_limit > max_wr)
return -EINVAL;
mutex_lock(&srq->mutex);
diff --git a/drivers/infiniband/ulp/ipoib/Kconfig b/drivers/infiniband/ulp/ipoib/Kconfig
index 13d6d01c72c..d74653d7de1 100644
--- a/drivers/infiniband/ulp/ipoib/Kconfig
+++ b/drivers/infiniband/ulp/ipoib/Kconfig
@@ -6,8 +6,7 @@ config INFINIBAND_IPOIB
transports IP packets over InfiniBand so you can use your IB
device as a fancy NIC.
- The IPoIB protocol is defined by the IETF ipoib working
- group: <http://www.ietf.org/html.charters/ipoib-charter.html>.
+ See Documentation/infiniband/ipoib.txt for more information
config INFINIBAND_IPOIB_DEBUG
bool "IP-over-InfiniBand debugging" if EMBEDDED
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 3f89f5e1903..474aa214ab5 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -212,6 +212,7 @@ struct ipoib_path {
struct ipoib_neigh {
struct ipoib_ah *ah;
+ union ib_gid dgid;
struct sk_buff_head queue;
struct neighbour *neighbour;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 1c6ea1c682a..cf71d2a5515 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -404,6 +404,8 @@ static void path_rec_completion(int status,
list_for_each_entry(neigh, &path->neigh_list, list) {
kref_get(&path->ah->ref);
neigh->ah = path->ah;
+ memcpy(&neigh->dgid.raw, &path->pathrec.dgid.raw,
+ sizeof(union ib_gid));
while ((skb = __skb_dequeue(&neigh->queue)))
__skb_queue_tail(&skqueue, skb);
@@ -510,6 +512,8 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
if (path->ah) {
kref_get(&path->ah->ref);
neigh->ah = path->ah;
+ memcpy(&neigh->dgid.raw, &path->pathrec.dgid.raw,
+ sizeof(union ib_gid));
ipoib_send(dev, skb, path->ah,
be32_to_cpup((__be32 *) skb->dst->neighbour->ha));
@@ -633,6 +637,25 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
neigh = *to_ipoib_neigh(skb->dst->neighbour);
if (likely(neigh->ah)) {
+ if (unlikely(memcmp(&neigh->dgid.raw,
+ skb->dst->neighbour->ha + 4,
+ sizeof(union ib_gid)))) {
+ spin_lock(&priv->lock);
+ /*
+ * It's safe to call ipoib_put_ah() inside
+ * priv->lock here, because we know that
+ * path->ah will always hold one more reference,
+ * so ipoib_put_ah() will never do more than
+ * decrement the ref count.
+ */
+ ipoib_put_ah(neigh->ah);
+ list_del(&neigh->list);
+ ipoib_neigh_free(neigh);
+ spin_unlock(&priv->lock);
+ ipoib_path_lookup(skb, dev);
+ goto out;
+ }
+
ipoib_send(dev, skb, neigh->ah,
be32_to_cpup((__be32 *) skb->dst->neighbour->ha));
goto out;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index ab40488182b..b5e6a7be603 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -264,6 +264,10 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
if (!ah) {
ipoib_warn(priv, "ib_address_create failed\n");
} else {
+ spin_lock_irq(&priv->lock);
+ mcast->ah = ah;
+ spin_unlock_irq(&priv->lock);
+
ipoib_dbg_mcast(priv, "MGID " IPOIB_GID_FMT
" AV %p, LID 0x%04x, SL %d\n",
IPOIB_GID_ARG(mcast->mcmember.mgid),
@@ -271,10 +275,6 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
be16_to_cpu(mcast->mcmember.mlid),
mcast->mcmember.sl);
}
-
- spin_lock_irq(&priv->lock);
- mcast->ah = ah;
- spin_unlock_irq(&priv->lock);
}
/* actually send any queued packets */
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 8f472e7113b..8257d5a2c8f 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -77,6 +77,14 @@ MODULE_PARM_DESC(topspin_workarounds,
static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad };
+static int mellanox_workarounds = 1;
+
+module_param(mellanox_workarounds, int, 0444);
+MODULE_PARM_DESC(mellanox_workarounds,
+ "Enable workarounds for Mellanox SRP target bugs if != 0");
+
+static const u8 mellanox_oui[3] = { 0x00, 0x02, 0xc9 };
+
static void srp_add_one(struct ib_device *device);
static void srp_remove_one(struct ib_device *device);
static void srp_completion(struct ib_cq *cq, void *target_ptr);
@@ -526,8 +534,10 @@ static int srp_reconnect_target(struct srp_target_port *target)
while (ib_poll_cq(target->cq, 1, &wc) > 0)
; /* nothing */
+ spin_lock_irq(target->scsi_host->host_lock);
list_for_each_entry_safe(req, tmp, &target->req_queue, list)
srp_reset_req(target, req);
+ spin_unlock_irq(target->scsi_host->host_lock);
target->rx_head = 0;
target->tx_head = 0;
@@ -567,7 +577,7 @@ err:
return ret;
}
-static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat,
+static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat,
int sg_cnt, struct srp_request *req,
struct srp_direct_buf *buf)
{
@@ -577,10 +587,15 @@ static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat,
int page_cnt;
int i, j;
int ret;
+ struct srp_device *dev = target->srp_host->dev;
if (!dev->fmr_pool)
return -ENODEV;
+ if ((sg_dma_address(&scat[0]) & ~dev->fmr_page_mask) &&
+ mellanox_workarounds && !memcmp(&target->ioc_guid, mellanox_oui, 3))
+ return -EINVAL;
+
len = page_cnt = 0;
for (i = 0; i < sg_cnt; ++i) {
if (sg_dma_address(&scat[i]) & ~dev->fmr_page_mask) {
@@ -683,7 +698,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
buf->va = cpu_to_be64(sg_dma_address(scat));
buf->key = cpu_to_be32(target->srp_host->dev->mr->rkey);
buf->len = cpu_to_be32(sg_dma_len(scat));
- } else if (srp_map_fmr(target->srp_host->dev, scat, count, req,
+ } else if (srp_map_fmr(target, scat, count, req,
(void *) cmd->add_data)) {
/*
* FMR mapping failed, and the scatterlist has more
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index a29d5ceb00c..4bf48188cc9 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -127,14 +127,10 @@ static int evdev_open(struct inode * inode, struct file * file)
{
struct evdev_list *list;
int i = iminor(inode) - EVDEV_MINOR_BASE;
- int accept_err;
if (i >= EVDEV_MINORS || !evdev_table[i] || !evdev_table[i]->exist)
return -ENODEV;
- if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file)))
- return accept_err;
-
if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL)))
return -ENOMEM;
@@ -260,7 +256,7 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_
if (evdev_event_from_user(buffer + retval, &event))
return -EFAULT;
- input_event(list->evdev->handle.dev, event.type, event.code, event.value);
+ input_inject_event(&list->evdev->handle, event.type, event.code, event.value);
retval += evdev_event_size();
}
@@ -428,8 +424,8 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
if (get_user(v, ip + 1))
return -EFAULT;
- input_event(dev, EV_REP, REP_DELAY, u);
- input_event(dev, EV_REP, REP_PERIOD, v);
+ input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u);
+ input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v);
return 0;
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
index 47e93daa0fa..90de5afe03c 100644
--- a/drivers/input/gameport/fm801-gp.c
+++ b/drivers/input/gameport/fm801-gp.c
@@ -106,10 +106,10 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device
gp->gameport = port;
gp->res_port = request_region(port->io, 0x10, "FM801 GP");
if (!gp->res_port) {
- kfree(gp);
- gameport_free_port(port);
printk(KERN_DEBUG "fm801-gp: unable to grab region 0x%x-0x%x\n",
port->io, port->io + 0x0f);
+ gameport_free_port(port);
+ kfree(gp);
return -EBUSY;
}
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 36644bff379..3f47ae55c6f 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -53,6 +53,7 @@ static LIST_HEAD(gameport_list);
static struct bus_type gameport_bus;
+static void gameport_add_driver(struct gameport_driver *drv);
static void gameport_add_port(struct gameport *gameport);
static void gameport_destroy_port(struct gameport *gameport);
static void gameport_reconnect_port(struct gameport *gameport);
@@ -211,8 +212,14 @@ static void gameport_release_driver(struct gameport *gameport)
static void gameport_find_driver(struct gameport *gameport)
{
+ int error;
+
down_write(&gameport_bus.subsys.rwsem);
- device_attach(&gameport->dev);
+ error = device_attach(&gameport->dev);
+ if (error < 0)
+ printk(KERN_WARNING
+ "gameport: device_attach() failed for %s (%s), error: %d\n",
+ gameport->phys, gameport->name, error);
up_write(&gameport_bus.subsys.rwsem);
}
@@ -316,7 +323,6 @@ static void gameport_remove_duplicate_events(struct gameport_event *event)
spin_unlock_irqrestore(&gameport_event_lock, flags);
}
-
static struct gameport_event *gameport_get_event(void)
{
struct gameport_event *event;
@@ -342,7 +348,6 @@ static struct gameport_event *gameport_get_event(void)
static void gameport_handle_event(void)
{
struct gameport_event *event;
- struct gameport_driver *gameport_drv;
mutex_lock(&gameport_mutex);
@@ -369,8 +374,7 @@ static void gameport_handle_event(void)
break;
case GAMEPORT_REGISTER_DRIVER:
- gameport_drv = event->object;
- driver_register(&gameport_drv->driver);
+ gameport_add_driver(event->object);
break;
default:
@@ -532,6 +536,7 @@ static void gameport_init_port(struct gameport *gameport)
if (gameport->parent)
gameport->dev.parent = &gameport->parent->dev;
+ INIT_LIST_HEAD(&gameport->node);
spin_lock_init(&gameport->timer_lock);
init_timer(&gameport->poll_timer);
gameport->poll_timer.function = gameport_run_poll_handler;
@@ -544,6 +549,8 @@ static void gameport_init_port(struct gameport *gameport)
*/
static void gameport_add_port(struct gameport *gameport)
{
+ int error;
+
if (gameport->parent)
gameport->parent->child = gameport;
@@ -558,8 +565,13 @@ static void gameport_add_port(struct gameport *gameport)
printk(KERN_INFO "gameport: %s is %s, speed %dkHz\n",
gameport->name, gameport->phys, gameport->speed);
- device_add(&gameport->dev);
- gameport->registered = 1;
+ error = device_add(&gameport->dev);
+ if (error)
+ printk(KERN_ERR
+ "gameport: device_add() failed for %s (%s), error: %d\n",
+ gameport->phys, gameport->name, error);
+ else
+ gameport->registered = 1;
}
/*
@@ -583,10 +595,11 @@ static void gameport_destroy_port(struct gameport *gameport)
if (gameport->registered) {
device_del(&gameport->dev);
- list_del_init(&gameport->node);
gameport->registered = 0;
}
+ list_del_init(&gameport->node);
+
gameport_remove_pending_events(gameport);
put_device(&gameport->dev);
}
@@ -704,11 +717,22 @@ static int gameport_driver_remove(struct device *dev)
}
static struct bus_type gameport_bus = {
- .name = "gameport",
- .probe = gameport_driver_probe,
- .remove = gameport_driver_remove,
+ .name = "gameport",
+ .probe = gameport_driver_probe,
+ .remove = gameport_driver_remove,
};
+static void gameport_add_driver(struct gameport_driver *drv)
+{
+ int error;
+
+ error = driver_register(&drv->driver);
+ if (error)
+ printk(KERN_ERR
+ "gameport: driver_register() failed for %s, error: %d\n",
+ drv->driver.name, error);
+}
+
void __gameport_register_driver(struct gameport_driver *drv, struct module *owner)
{
drv->driver.bus = &gameport_bus;
@@ -778,16 +802,24 @@ void gameport_close(struct gameport *gameport)
static int __init gameport_init(void)
{
- gameport_task = kthread_run(gameport_thread, NULL, "kgameportd");
- if (IS_ERR(gameport_task)) {
- printk(KERN_ERR "gameport: Failed to start kgameportd\n");
- return PTR_ERR(gameport_task);
- }
+ int error;
gameport_bus.dev_attrs = gameport_device_attrs;
gameport_bus.drv_attrs = gameport_driver_attrs;
gameport_bus.match = gameport_bus_match;
- bus_register(&gameport_bus);
+ error = bus_register(&gameport_bus);
+ if (error) {
+ printk(KERN_ERR "gameport: failed to register gameport bus, error: %d\n", error);
+ return error;
+ }
+
+ gameport_task = kthread_run(gameport_thread, NULL, "kgameportd");
+ if (IS_ERR(gameport_task)) {
+ bus_unregister(&gameport_bus);
+ error = PTR_ERR(gameport_task);
+ printk(KERN_ERR "gameport: Failed to start kgameportd, error: %d\n", error);
+ return error;
+ }
return 0;
}
diff --git a/drivers/input/input.c b/drivers/input/input.c
index a90486f5e49..9cb4b9a54f0 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -35,6 +35,16 @@ static LIST_HEAD(input_handler_list);
static struct input_handler *input_table[8];
+/**
+ * input_event() - report new input event
+ * @handle: device that generated the event
+ * @type: type of the event
+ * @code: event code
+ * @value: value of the event
+ *
+ * This function should be used by drivers implementing various input devices
+ * See also input_inject_event()
+ */
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct input_handle *handle;
@@ -183,6 +193,23 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
}
EXPORT_SYMBOL(input_event);
+/**
+ * input_inject_event() - send input event from input handler
+ * @handle: input handle to send event through
+ * @type: type of the event
+ * @code: event code
+ * @value: value of the event
+ *
+ * Similar to input_event() but will ignore event if device is "grabbed" and handle
+ * injecting event is not the one that owns the device.
+ */
+void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
+{
+ if (!handle->dev->grab || handle->dev->grab == handle)
+ input_event(handle->dev, type, code, value);
+}
+EXPORT_SYMBOL(input_inject_event);
+
static void input_repeat_key(unsigned long data)
{
struct input_dev *dev = (void *) data;
@@ -197,15 +224,6 @@ static void input_repeat_key(unsigned long data)
mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD]));
}
-int input_accept_process(struct input_handle *handle, struct file *file)
-{
- if (handle->dev->accept)
- return handle->dev->accept(handle->dev, file);
-
- return 0;
-}
-EXPORT_SYMBOL(input_accept_process);
-
int input_grab_device(struct input_handle *handle)
{
if (handle->dev->grab)
@@ -218,8 +236,15 @@ EXPORT_SYMBOL(input_grab_device);
void input_release_device(struct input_handle *handle)
{
- if (handle->dev->grab == handle)
- handle->dev->grab = NULL;
+ struct input_dev *dev = handle->dev;
+
+ if (dev->grab == handle) {
+ dev->grab = NULL;
+
+ list_for_each_entry(handle, &dev->h_list, d_node)
+ if (handle->handler->start)
+ handle->handler->start(handle);
+ }
}
EXPORT_SYMBOL(input_release_device);
@@ -963,8 +988,11 @@ int input_register_device(struct input_dev *dev)
list_for_each_entry(handler, &input_handler_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((id = input_match_device(handler->id_table, dev)))
- if ((handle = handler->connect(handler, dev, id)))
+ if ((handle = handler->connect(handler, dev, id))) {
input_link_handle(handle);
+ if (handler->start)
+ handler->start(handle);
+ }
input_wakeup_procfs_readers();
@@ -1028,8 +1056,11 @@ void input_register_handler(struct input_handler *handler)
list_for_each_entry(dev, &input_dev_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((id = input_match_device(handler->id_table, dev)))
- if ((handle = handler->connect(handler, dev, id)))
+ if ((handle = handler->connect(handler, dev, id))) {
input_link_handle(handle);
+ if (handler->start)
+ handler->start(handle);
+ }
input_wakeup_procfs_readers();
}
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 6d99e3c3788..b4914e7231f 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -79,6 +79,7 @@ static struct iforce_device iforce_device[] = {
{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //?
+ { 0x06d6, 0x29bc, "Trust Force Feedback Race Master", btn_wheel, abs_wheel, ff_iforce },
{ 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce }
};
@@ -222,22 +223,22 @@ static int iforce_erase_effect(struct input_dev *dev, int effect_id)
int err = 0;
struct iforce_core_effect* core_effect;
- /* Check who is trying to erase this effect */
- if (iforce->core_effects[effect_id].owner != current->pid) {
- printk(KERN_WARNING "iforce-main.c: %d tried to erase an effect belonging to %d\n", current->pid, iforce->core_effects[effect_id].owner);
- return -EACCES;
- }
-
if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX)
return -EINVAL;
- core_effect = iforce->core_effects + effect_id;
+ core_effect = &iforce->core_effects[effect_id];
+
+ /* Check who is trying to erase this effect */
+ if (core_effect->owner != current->pid) {
+ printk(KERN_WARNING "iforce-main.c: %d tried to erase an effect belonging to %d\n", current->pid, core_effect->owner);
+ return -EACCES;
+ }
if (test_bit(FF_MOD1_IS_USED, core_effect->flags))
- err = release_resource(&(iforce->core_effects[effect_id].mod1_chunk));
+ err = release_resource(&core_effect->mod1_chunk);
if (!err && test_bit(FF_MOD2_IS_USED, core_effect->flags))
- err = release_resource(&(iforce->core_effects[effect_id].mod2_chunk));
+ err = release_resource(&core_effect->mod2_chunk);
/*TODO: remember to change that if more FF_MOD* bits are added */
core_effect->flags[0] = 0;
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index 75eb5ca5999..7a19ee05297 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -50,7 +50,7 @@ MODULE_LICENSE("GPL");
*/
#define SPACEBALL_MAX_LENGTH 128
-#define SPACEBALL_MAX_ID 8
+#define SPACEBALL_MAX_ID 9
#define SPACEBALL_1003 1
#define SPACEBALL_2003B 3
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index ce1f10e8984..6bfa0cf4b1d 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -482,13 +482,7 @@ out:
return IRQ_HANDLED;
}
-/*
- * atkbd_event_work() is used to complete processing of events that
- * can not be processed by input_event() which is often called from
- * interrupt context.
- */
-
-static void atkbd_event_work(void *data)
+static int atkbd_set_repeat_rate(struct atkbd *atkbd)
{
const short period[32] =
{ 33, 37, 42, 46, 50, 54, 58, 63, 67, 75, 83, 92, 100, 109, 116, 125,
@@ -496,41 +490,64 @@ static void atkbd_event_work(void *data)
const short delay[4] =
{ 250, 500, 750, 1000 };
- struct atkbd *atkbd = data;
+ struct input_dev *dev = atkbd->dev;
+ unsigned char param;
+ int i = 0, j = 0;
+
+ while (i < ARRAY_SIZE(period) - 1 && period[i] < dev->rep[REP_PERIOD])
+ i++;
+ dev->rep[REP_PERIOD] = period[i];
+
+ while (j < ARRAY_SIZE(period) - 1 && delay[j] < dev->rep[REP_DELAY])
+ j++;
+ dev->rep[REP_DELAY] = delay[j];
+
+ param = i | (j << 5);
+ return ps2_command(&atkbd->ps2dev, &param, ATKBD_CMD_SETREP);
+}
+
+static int atkbd_set_leds(struct atkbd *atkbd)
+{
struct input_dev *dev = atkbd->dev;
unsigned char param[2];
- int i, j;
- mutex_lock(&atkbd->event_mutex);
+ param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
+ | (test_bit(LED_NUML, dev->led) ? 2 : 0)
+ | (test_bit(LED_CAPSL, dev->led) ? 4 : 0);
+ if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS))
+ return -1;
- if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) {
- param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
- | (test_bit(LED_NUML, dev->led) ? 2 : 0)
- | (test_bit(LED_CAPSL, dev->led) ? 4 : 0);
- ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS);
-
- if (atkbd->extra) {
- param[0] = 0;
- param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)
- | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0)
- | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)
- | (test_bit(LED_MISC, dev->led) ? 0x10 : 0)
- | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0);
- ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS);
- }
+ if (atkbd->extra) {
+ param[0] = 0;
+ param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)
+ | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0)
+ | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)
+ | (test_bit(LED_MISC, dev->led) ? 0x10 : 0)
+ | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0);
+ if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS))
+ return -1;
}
- if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask)) {
- i = j = 0;
- while (i < 31 && period[i] < dev->rep[REP_PERIOD])
- i++;
- while (j < 3 && delay[j] < dev->rep[REP_DELAY])
- j++;
- dev->rep[REP_PERIOD] = period[i];
- dev->rep[REP_DELAY] = delay[j];
- param[0] = i | (j << 5);
- ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP);
- }
+ return 0;
+}
+
+/*
+ * atkbd_event_work() is used to complete processing of events that
+ * can not be processed by input_event() which is often called from
+ * interrupt context.
+ */
+
+static void atkbd_event_work(void *data)
+{
+ struct atkbd *atkbd = data;
+
+ mutex_lock(&atkbd->event_mutex);
+
+ if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask))
+ atkbd_set_leds(atkbd);
+
+ if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask))
+ atkbd_set_repeat_rate(atkbd);
mutex_unlock(&atkbd->event_mutex);
}
@@ -975,7 +992,6 @@ static int atkbd_reconnect(struct serio *serio)
{
struct atkbd *atkbd = serio_get_drvdata(serio);
struct serio_driver *drv = serio->drv;
- unsigned char param[1];
if (!atkbd || !drv) {
printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
@@ -985,10 +1001,6 @@ static int atkbd_reconnect(struct serio *serio)
atkbd_disable(atkbd);
if (atkbd->write) {
- param[0] = (test_bit(LED_SCROLLL, atkbd->dev->led) ? 1 : 0)
- | (test_bit(LED_NUML, atkbd->dev->led) ? 2 : 0)
- | (test_bit(LED_CAPSL, atkbd->dev->led) ? 4 : 0);
-
if (atkbd_probe(atkbd))
return -1;
if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra))
@@ -996,8 +1008,13 @@ static int atkbd_reconnect(struct serio *serio)
atkbd_activate(atkbd);
- if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS))
- return -1;
+/*
+ * Restore repeat rate and LEDs (that were reset by atkbd_activate)
+ * to pre-resume state
+ */
+ if (!atkbd->softrepeat)
+ atkbd_set_repeat_rate(atkbd);
+ atkbd_set_leds(atkbd);
}
atkbd_enable(atkbd);
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index ccf0faeee5c..a8efc1af36c 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -94,7 +94,7 @@ static void call_bios(struct regs *regs)
static ssize_t __init locate_wistron_bios(void __iomem *base)
{
- static const unsigned char __initdata signature[] =
+ static unsigned char __initdata signature[] =
{ 0x42, 0x21, 0x55, 0x30 };
ssize_t offset;
@@ -259,11 +259,11 @@ static int __init dmi_matched(struct dmi_system_id *dmi)
return 1;
}
-static struct key_entry keymap_empty[] = {
+static struct key_entry keymap_empty[] __initdata = {
{ KE_END, 0 }
};
-static struct key_entry keymap_fs_amilo_pro_v2000[] = {
+static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = {
{ KE_KEY, 0x01, KEY_HELP },
{ KE_KEY, 0x11, KEY_PROG1 },
{ KE_KEY, 0x12, KEY_PROG2 },
@@ -273,7 +273,7 @@ static struct key_entry keymap_fs_amilo_pro_v2000[] = {
{ KE_END, 0 }
};
-static struct key_entry keymap_fujitsu_n3510[] = {
+static struct key_entry keymap_fujitsu_n3510[] __initdata = {
{ KE_KEY, 0x11, KEY_PROG1 },
{ KE_KEY, 0x12, KEY_PROG2 },
{ KE_KEY, 0x36, KEY_WWW },
@@ -285,7 +285,7 @@ static struct key_entry keymap_fujitsu_n3510[] = {
{ KE_END, 0 }
};
-static struct key_entry keymap_wistron_ms2111[] = {
+static struct key_entry keymap_wistron_ms2111[] __initdata = {
{ KE_KEY, 0x11, KEY_PROG1 },
{ KE_KEY, 0x12, KEY_PROG2 },
{ KE_KEY, 0x13, KEY_PROG3 },
@@ -294,7 +294,7 @@ static struct key_entry keymap_wistron_ms2111[] = {
{ KE_END, 0 }
};
-static struct key_entry keymap_wistron_ms2141[] = {
+static struct key_entry keymap_wistron_ms2141[] __initdata = {
{ KE_KEY, 0x11, KEY_PROG1 },
{ KE_KEY, 0x12, KEY_PROG2 },
{ KE_WIFI, 0x30, 0 },
@@ -307,7 +307,7 @@ static struct key_entry keymap_wistron_ms2141[] = {
{ KE_END, 0 }
};
-static struct key_entry keymap_acer_aspire_1500[] = {
+static struct key_entry keymap_acer_aspire_1500[] __initdata = {
{ KE_KEY, 0x11, KEY_PROG1 },
{ KE_KEY, 0x12, KEY_PROG2 },
{ KE_WIFI, 0x30, 0 },
@@ -317,7 +317,7 @@ static struct key_entry keymap_acer_aspire_1500[] = {
{ KE_END, 0 }
};
-static struct key_entry keymap_acer_travelmate_240[] = {
+static struct key_entry keymap_acer_travelmate_240[] __initdata = {
{ KE_KEY, 0x31, KEY_MAIL },
{ KE_KEY, 0x36, KEY_WWW },
{ KE_KEY, 0x11, KEY_PROG1 },
@@ -327,7 +327,7 @@ static struct key_entry keymap_acer_travelmate_240[] = {
{ KE_END, 0 }
};
-static struct key_entry keymap_aopen_1559as[] = {
+static struct key_entry keymap_aopen_1559as[] __initdata = {
{ KE_KEY, 0x01, KEY_HELP },
{ KE_KEY, 0x06, KEY_PROG3 },
{ KE_KEY, 0x11, KEY_PROG1 },
@@ -343,7 +343,7 @@ static struct key_entry keymap_aopen_1559as[] = {
* a list of buttons and their key codes (reported when loading this module
* with force=1) and the output of dmidecode to $MODULE_AUTHOR.
*/
-static struct dmi_system_id dmi_ids[] = {
+static struct dmi_system_id dmi_ids[] __initdata = {
{
.callback = dmi_matched,
.ident = "Fujitsu-Siemens Amilo Pro V2000",
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 2f0d2884081..54b696cfe1e 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -238,8 +238,7 @@ static struct ps2pp_info *get_model_info(unsigned char model)
{ 100, PS2PP_KIND_MX, /* MX510 */
PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
- { 111, PS2PP_KIND_MX, /* MX300 */
- PS2PP_WHEEL | PS2PP_EXTRA_BTN | PS2PP_TASK_BTN },
+ { 111, PS2PP_KIND_MX, PS2PP_WHEEL | PS2PP_SIDE_BTN }, /* MX300 reports task button as side */
{ 112, PS2PP_KIND_MX, /* MX500 */
PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index 6d9ec9ab1b9..ae5871a0e06 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -183,21 +183,26 @@ static struct attribute_group trackpoint_attr_group = {
.attrs = trackpoint_attrs,
};
-static void trackpoint_disconnect(struct psmouse *psmouse)
+static int trackpoint_start_protocol(struct psmouse *psmouse, unsigned char *firmware_id)
{
- sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group);
+ unsigned char param[2] = { 0 };
- kfree(psmouse->private);
- psmouse->private = NULL;
+ if (ps2_command(&psmouse->ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID)))
+ return -1;
+
+ if (param[0] != TP_MAGIC_IDENT)
+ return -1;
+
+ if (firmware_id)
+ *firmware_id = param[1];
+
+ return 0;
}
static int trackpoint_sync(struct psmouse *psmouse)
{
- unsigned char toggle;
struct trackpoint_data *tp = psmouse->private;
-
- if (!tp)
- return -1;
+ unsigned char toggle;
/* Disable features that may make device unusable with this driver */
trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, &toggle);
@@ -263,27 +268,38 @@ static void trackpoint_defaults(struct trackpoint_data *tp)
tp->ext_dev = TP_DEF_EXT_DEV;
}
+static void trackpoint_disconnect(struct psmouse *psmouse)
+{
+ sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group);
+
+ kfree(psmouse->private);
+ psmouse->private = NULL;
+}
+
+static int trackpoint_reconnect(struct psmouse *psmouse)
+{
+ if (trackpoint_start_protocol(psmouse, NULL))
+ return -1;
+
+ if (trackpoint_sync(psmouse))
+ return -1;
+
+ return 0;
+}
+
int trackpoint_detect(struct psmouse *psmouse, int set_properties)
{
struct trackpoint_data *priv;
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char firmware_id;
unsigned char button_info;
- unsigned char param[2];
-
- param[0] = param[1] = 0;
- if (ps2_command(ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID)))
- return -1;
-
- if (param[0] != TP_MAGIC_IDENT)
+ if (trackpoint_start_protocol(psmouse, &firmware_id))
return -1;
if (!set_properties)
return 0;
- firmware_id = param[1];
-
if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) {
printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n");
button_info = 0;
@@ -296,7 +312,7 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties)
psmouse->vendor = "IBM";
psmouse->name = "TrackPoint";
- psmouse->reconnect = trackpoint_sync;
+ psmouse->reconnect = trackpoint_reconnect;
psmouse->disconnect = trackpoint_disconnect;
trackpoint_defaults(priv);
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 61a6f977846..ed202f2f251 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -177,6 +177,11 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
return -1;
}
+ if (send && !param) {
+ WARN_ON(1);
+ return -1;
+ }
+
mutex_lock_nested(&ps2dev->cmd_mutex, SINGLE_DEPTH_NESTING);
serio_pause_rx(ps2dev->serio);
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 6521034bc93..3e76ad71c9a 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -62,6 +62,7 @@ static LIST_HEAD(serio_list);
static struct bus_type serio_bus;
+static void serio_add_driver(struct serio_driver *drv);
static void serio_add_port(struct serio *serio);
static void serio_destroy_port(struct serio *serio);
static void serio_reconnect_port(struct serio *serio);
@@ -140,8 +141,14 @@ static void serio_release_driver(struct serio *serio)
static void serio_find_driver(struct serio *serio)
{
+ int error;
+
down_write(&serio_bus.subsys.rwsem);
- device_attach(&serio->dev);
+ error = device_attach(&serio->dev);
+ if (error < 0)
+ printk(KERN_WARNING
+ "serio: device_attach() failed for %s (%s), error: %d\n",
+ serio->phys, serio->name, error);
up_write(&serio_bus.subsys.rwsem);
}
@@ -272,7 +279,6 @@ static struct serio_event *serio_get_event(void)
static void serio_handle_event(void)
{
struct serio_event *event;
- struct serio_driver *serio_drv;
mutex_lock(&serio_mutex);
@@ -304,8 +310,7 @@ static void serio_handle_event(void)
break;
case SERIO_REGISTER_DRIVER:
- serio_drv = event->object;
- driver_register(&serio_drv->driver);
+ serio_add_driver(event->object);
break;
default:
@@ -525,6 +530,7 @@ static void serio_init_port(struct serio *serio)
__module_get(THIS_MODULE);
+ INIT_LIST_HEAD(&serio->node);
spin_lock_init(&serio->lock);
mutex_init(&serio->drv_mutex);
device_initialize(&serio->dev);
@@ -542,6 +548,8 @@ static void serio_init_port(struct serio *serio)
*/
static void serio_add_port(struct serio *serio)
{
+ int error;
+
if (serio->parent) {
serio_pause_rx(serio->parent);
serio->parent->child = serio;
@@ -551,9 +559,19 @@ static void serio_add_port(struct serio *serio)
list_add_tail(&serio->node, &serio_list);
if (serio->start)
serio->start(serio);
- device_add(&serio->dev);
- sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group);
- serio->registered = 1;
+ error = device_add(&serio->dev);
+ if (error)
+ printk(KERN_ERR
+ "serio: device_add() failed for %s (%s), error: %d\n",
+ serio->phys, serio->name, error);
+ else {
+ serio->registered = 1;
+ error = sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group);
+ if (error)
+ printk(KERN_ERR
+ "serio: sysfs_create_group() failed for %s (%s), error: %d\n",
+ serio->phys, serio->name, error);
+ }
}
/*
@@ -583,10 +601,10 @@ static void serio_destroy_port(struct serio *serio)
if (serio->registered) {
sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group);
device_del(&serio->dev);
- list_del_init(&serio->node);
serio->registered = 0;
}
+ list_del_init(&serio->node);
serio_remove_pending_events(serio);
put_device(&serio->dev);
}
@@ -756,6 +774,17 @@ static struct bus_type serio_bus = {
.remove = serio_driver_remove,
};
+static void serio_add_driver(struct serio_driver *drv)
+{
+ int error;
+
+ error = driver_register(&drv->driver);
+ if (error)
+ printk(KERN_ERR
+ "serio: driver_register() failed for %s, error: %d\n",
+ drv->driver.name, error);
+}
+
void __serio_register_driver(struct serio_driver *drv, struct module *owner)
{
drv->driver.bus = &serio_bus;
@@ -903,18 +932,26 @@ irqreturn_t serio_interrupt(struct serio *serio,
static int __init serio_init(void)
{
- serio_task = kthread_run(serio_thread, NULL, "kseriod");
- if (IS_ERR(serio_task)) {
- printk(KERN_ERR "serio: Failed to start kseriod\n");
- return PTR_ERR(serio_task);
- }
+ int error;
serio_bus.dev_attrs = serio_device_attrs;
serio_bus.drv_attrs = serio_driver_attrs;
serio_bus.match = serio_bus_match;
serio_bus.uevent = serio_uevent;
serio_bus.resume = serio_resume;
- bus_register(&serio_bus);
+ error = bus_register(&serio_bus);
+ if (error) {
+ printk(KERN_ERR "serio: failed to register serio bus, error: %d\n", error);
+ return error;
+ }
+
+ serio_task = kthread_run(serio_thread, NULL, "kseriod");
+ if (IS_ERR(serio_task)) {
+ bus_unregister(&serio_bus);
+ error = PTR_ERR(serio_task);
+ printk(KERN_ERR "serio: Failed to start kseriod, error: %d\n", error);
+ return error;
+ }
return 0;
}
diff --git a/drivers/isdn/hardware/eicon/divasync.h b/drivers/isdn/hardware/eicon/divasync.h
index 0a5be7f969f..af3eb9e795b 100644
--- a/drivers/isdn/hardware/eicon/divasync.h
+++ b/drivers/isdn/hardware/eicon/divasync.h
@@ -256,7 +256,6 @@ typedef struct
#define NO_ORDER_CHECK_MASK 0x00000010
#define LOW_CHANNEL_MASK 0x00000020
#define NO_HSCX30_MASK 0x00000040
-#define MODE_MASK 0x00000080
#define SET_BOARD 0x00001000
#define SET_CRC4 0x00030000
#define SET_L1_TRISTATE 0x00040000
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index f5fe7fb4b3a..d5d649f5ccd 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -90,6 +90,15 @@ config ADB_PMU_LED
and the ide-disk LED trigger and configure appropriately through
sysfs.
+config ADB_PMU_LED_IDE
+ bool "Use front LED as IDE LED by default"
+ depends on ADB_PMU_LED
+ select LEDS_TRIGGERS
+ select LEDS_TRIGGER_IDE_DISK
+ help
+ This option makes the front LED default to the IDE trigger
+ so that it blinks on IDE activity.
+
config PMAC_SMU
bool "Support for SMU based PowerMacs"
depends on PPC_PMAC64
@@ -100,7 +109,7 @@ config PMAC_SMU
config PMAC_APM_EMU
tristate "APM emulation"
- depends on PPC_PMAC && PPC32 && PM
+ depends on PPC_PMAC && PPC32 && PM && ADB_PMU
config PMAC_MEDIABAY
bool "Support PowerBook hotswap media bay"
@@ -115,8 +124,6 @@ config PMAC_BACKLIGHT
bool "Backlight control for LCD screens"
depends on ADB_PMU && FB = y && (BROKEN || !PPC64)
select FB_BACKLIGHT
- select BACKLIGHT_CLASS_DEVICE
- select BACKLIGHT_LCD_SUPPORT
help
Say Y here to enable Macintosh specific extensions of the generic
backlight code. With this enabled, the brightness keys on older
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index 545be1ed692..c69d23bb255 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -45,14 +45,11 @@
#include <linux/pmu.h>
#include <asm/machdep.h>
+#include <asm/backlight.h>
#ifdef CONFIG_PPC_PMAC
#include <asm/pmac_feature.h>
#endif
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/backlight.h>
-#endif
-
MODULE_AUTHOR("Franz Sirl <Franz.Sirl-kernel@lauterbach.com>");
#define KEYB_KEYREG 0 /* register # for key up/down data */
@@ -237,11 +234,6 @@ static struct adb_ids keyboard_ids;
static struct adb_ids mouse_ids;
static struct adb_ids buttons_ids;
-#ifdef CONFIG_PMAC_BACKLIGHT
-/* Exported to via-pmu.c */
-int disable_kernel_backlight = 0;
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
/* Kind of keyboard, see Apple technote 1152 */
#define ADB_KEYBOARD_UNKNOWN 0
#define ADB_KEYBOARD_ANSI 0x0100
@@ -527,7 +519,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
case 0xa: /* brightness decrease */
#ifdef CONFIG_PMAC_BACKLIGHT
- if (!disable_kernel_backlight && down)
+ if (down)
pmac_backlight_key_down();
#endif
input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down);
@@ -535,7 +527,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
case 0x9: /* brightness increase */
#ifdef CONFIG_PMAC_BACKLIGHT
- if (!disable_kernel_backlight && down)
+ if (down)
pmac_backlight_key_up();
#endif
input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down);
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index c1fe0b368f7..20bf67244e2 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -95,6 +95,17 @@
* - Use min/max macros here or there
* - Latest darwin updated U3H min fan speed to 20% PWM
*
+ * July. 06, 2006 : 1.3
+ * - Fix setting of RPM fans on Xserve G5 (they were going too fast)
+ * - Add missing slots fan control loop for Xserve G5
+ * - Lower fixed slots fan speed from 50% to 40% on desktop G5s. We
+ * still can't properly implement the control loop for these, so let's
+ * reduce the noise a little bit, it appears that 40% still gives us
+ * a pretty good air flow
+ * - Add code to "tickle" the FCU regulary so it doesn't think that
+ * we are gone while in fact, the machine just didn't need any fan
+ * speed change lately
+ *
*/
#include <linux/types.h>
@@ -121,7 +132,7 @@
#include "therm_pm72.h"
-#define VERSION "1.2b2"
+#define VERSION "1.3"
#undef DEBUG
@@ -146,6 +157,7 @@ static struct basckside_pid_params backside_params;
static struct backside_pid_state backside_state;
static struct drives_pid_state drives_state;
static struct dimm_pid_state dimms_state;
+static struct slots_pid_state slots_state;
static int state;
static int cpu_count;
static int cpu_pid_type;
@@ -154,7 +166,8 @@ static struct completion ctrl_complete;
static int critical_state;
static int rackmac;
static s32 dimm_output_clamp;
-
+static int fcu_rpm_shift;
+static int fcu_tickle_ticks;
static DECLARE_MUTEX(driver_lock);
/*
@@ -495,13 +508,20 @@ static int start_fcu(void)
rc = fan_write_reg(0x2e, &buf, 1);
if (rc < 0)
return -EIO;
+ rc = fan_read_reg(0, &buf, 1);
+ if (rc < 0)
+ return -EIO;
+ fcu_rpm_shift = (buf == 1) ? 2 : 3;
+ printk(KERN_DEBUG "FCU Initialized, RPM fan shift is %d\n",
+ fcu_rpm_shift);
+
return 0;
}
static int set_rpm_fan(int fan_index, int rpm)
{
unsigned char buf[2];
- int rc, id;
+ int rc, id, min, max;
if (fcu_fans[fan_index].type != FCU_FAN_RPM)
return -EINVAL;
@@ -509,12 +529,15 @@ static int set_rpm_fan(int fan_index, int rpm)
if (id == FCU_FAN_ABSENT_ID)
return -EINVAL;
- if (rpm < 300)
- rpm = 300;
- else if (rpm > 8191)
- rpm = 8191;
- buf[0] = rpm >> 5;
- buf[1] = rpm << 3;
+ min = 2400 >> fcu_rpm_shift;
+ max = 56000 >> fcu_rpm_shift;
+
+ if (rpm < min)
+ rpm = min;
+ else if (rpm > max)
+ rpm = max;
+ buf[0] = rpm >> (8 - fcu_rpm_shift);
+ buf[1] = rpm << fcu_rpm_shift;
rc = fan_write_reg(0x10 + (id * 2), buf, 2);
if (rc < 0)
return -EIO;
@@ -551,7 +574,7 @@ static int get_rpm_fan(int fan_index, int programmed)
if (rc != 2)
return -EIO;
- return (buf[0] << 5) | buf[1] >> 3;
+ return (buf[0] << (8 - fcu_rpm_shift)) | buf[1] >> fcu_rpm_shift;
}
static int set_pwm_fan(int fan_index, int pwm)
@@ -609,6 +632,26 @@ static int get_pwm_fan(int fan_index)
return (buf[0] * 1000) / 2559;
}
+static void tickle_fcu(void)
+{
+ int pwm;
+
+ pwm = get_pwm_fan(SLOTS_FAN_PWM_INDEX);
+
+ DBG("FCU Tickle, slots fan is: %d\n", pwm);
+ if (pwm < 0)
+ pwm = 100;
+
+ if (!rackmac) {
+ pwm = SLOTS_FAN_DEFAULT_PWM;
+ } else if (pwm < SLOTS_PID_OUTPUT_MIN)
+ pwm = SLOTS_PID_OUTPUT_MIN;
+
+ /* That is hopefully enough to make the FCU happy */
+ set_pwm_fan(SLOTS_FAN_PWM_INDEX, pwm);
+}
+
+
/*
* Utility routine to read the CPU calibration EEPROM data
* from the device-tree
@@ -715,6 +758,9 @@ BUILD_SHOW_FUNC_INT(backside_fan_pwm, backside_state.pwm)
BUILD_SHOW_FUNC_FIX(drives_temperature, drives_state.last_temp)
BUILD_SHOW_FUNC_INT(drives_fan_rpm, drives_state.rpm)
+BUILD_SHOW_FUNC_FIX(slots_temperature, slots_state.last_temp)
+BUILD_SHOW_FUNC_INT(slots_fan_pwm, slots_state.pwm)
+
BUILD_SHOW_FUNC_FIX(dimms_temperature, dimms_state.last_temp)
static DEVICE_ATTR(cpu0_temperature,S_IRUGO,show_cpu0_temperature,NULL);
@@ -735,6 +781,9 @@ static DEVICE_ATTR(backside_fan_pwm,S_IRUGO,show_backside_fan_pwm,NULL);
static DEVICE_ATTR(drives_temperature,S_IRUGO,show_drives_temperature,NULL);
static DEVICE_ATTR(drives_fan_rpm,S_IRUGO,show_drives_fan_rpm,NULL);
+static DEVICE_ATTR(slots_temperature,S_IRUGO,show_slots_temperature,NULL);
+static DEVICE_ATTR(slots_fan_pwm,S_IRUGO,show_slots_fan_pwm,NULL);
+
static DEVICE_ATTR(dimms_temperature,S_IRUGO,show_dimms_temperature,NULL);
/*
@@ -1076,6 +1125,9 @@ static void do_monitor_cpu_rack(struct cpu_pid_state *state)
fan_min = dimm_output_clamp;
fan_min = max(fan_min, (int)state->mpu.rminn_intake_fan);
+ DBG(" CPU min mpu = %d, min dimm = %d\n",
+ state->mpu.rminn_intake_fan, dimm_output_clamp);
+
state->rpm = max(state->rpm, (int)fan_min);
state->rpm = min(state->rpm, (int)state->mpu.rmaxn_intake_fan);
state->intake_rpm = state->rpm;
@@ -1374,7 +1426,8 @@ static void do_monitor_drives(struct drives_pid_state *state)
DBG(" current rpm: %d\n", state->rpm);
/* Get some sensor readings */
- temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, DS1775_TEMP)) << 8;
+ temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor,
+ DS1775_TEMP)) << 8;
state->last_temp = temp;
DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
FIX32TOPRINT(DRIVES_PID_INPUT_TARGET));
@@ -1575,7 +1628,7 @@ static int init_dimms_state(struct dimm_pid_state *state)
}
/*
- * Dispose of the state data for the drives control loop
+ * Dispose of the state data for the DIMM control loop
*/
static void dispose_dimms_state(struct dimm_pid_state *state)
{
@@ -1588,6 +1641,127 @@ static void dispose_dimms_state(struct dimm_pid_state *state)
state->monitor = NULL;
}
+/*
+ * Slots fan control loop
+ */
+static void do_monitor_slots(struct slots_pid_state *state)
+{
+ s32 temp, integral, derivative;
+ s64 integ_p, deriv_p, prop_p, sum;
+ int i, rc;
+
+ if (--state->ticks != 0)
+ return;
+ state->ticks = SLOTS_PID_INTERVAL;
+
+ DBG("slots:\n");
+
+ /* Check fan status */
+ rc = get_pwm_fan(SLOTS_FAN_PWM_INDEX);
+ if (rc < 0) {
+ printk(KERN_WARNING "Error %d reading slots fan !\n", rc);
+ /* XXX What do we do now ? */
+ } else
+ state->pwm = rc;
+ DBG(" current pwm: %d\n", state->pwm);
+
+ /* Get some sensor readings */
+ temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor,
+ DS1775_TEMP)) << 8;
+ state->last_temp = temp;
+ DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
+ FIX32TOPRINT(SLOTS_PID_INPUT_TARGET));
+
+ /* Store temperature and error in history array */
+ state->cur_sample = (state->cur_sample + 1) % SLOTS_PID_HISTORY_SIZE;
+ state->sample_history[state->cur_sample] = temp;
+ state->error_history[state->cur_sample] = temp - SLOTS_PID_INPUT_TARGET;
+
+ /* If first loop, fill the history table */
+ if (state->first) {
+ for (i = 0; i < (SLOTS_PID_HISTORY_SIZE - 1); i++) {
+ state->cur_sample = (state->cur_sample + 1) %
+ SLOTS_PID_HISTORY_SIZE;
+ state->sample_history[state->cur_sample] = temp;
+ state->error_history[state->cur_sample] =
+ temp - SLOTS_PID_INPUT_TARGET;
+ }
+ state->first = 0;
+ }
+
+ /* Calculate the integral term */
+ sum = 0;
+ integral = 0;
+ for (i = 0; i < SLOTS_PID_HISTORY_SIZE; i++)
+ integral += state->error_history[i];
+ integral *= SLOTS_PID_INTERVAL;
+ DBG(" integral: %08x\n", integral);
+ integ_p = ((s64)SLOTS_PID_G_r) * (s64)integral;
+ DBG(" integ_p: %d\n", (int)(integ_p >> 36));
+ sum += integ_p;
+
+ /* Calculate the derivative term */
+ derivative = state->error_history[state->cur_sample] -
+ state->error_history[(state->cur_sample + SLOTS_PID_HISTORY_SIZE - 1)
+ % SLOTS_PID_HISTORY_SIZE];
+ derivative /= SLOTS_PID_INTERVAL;
+ deriv_p = ((s64)SLOTS_PID_G_d) * (s64)derivative;
+ DBG(" deriv_p: %d\n", (int)(deriv_p >> 36));
+ sum += deriv_p;
+
+ /* Calculate the proportional term */
+ prop_p = ((s64)SLOTS_PID_G_p) * (s64)(state->error_history[state->cur_sample]);
+ DBG(" prop_p: %d\n", (int)(prop_p >> 36));
+ sum += prop_p;
+
+ /* Scale sum */
+ sum >>= 36;
+
+ DBG(" sum: %d\n", (int)sum);
+ state->pwm = (s32)sum;
+
+ state->pwm = max(state->pwm, SLOTS_PID_OUTPUT_MIN);
+ state->pwm = min(state->pwm, SLOTS_PID_OUTPUT_MAX);
+
+ DBG("** DRIVES PWM: %d\n", (int)state->pwm);
+ set_pwm_fan(SLOTS_FAN_PWM_INDEX, state->pwm);
+}
+
+/*
+ * Initialize the state structure for the slots bay fan control loop
+ */
+static int init_slots_state(struct slots_pid_state *state)
+{
+ state->ticks = 1;
+ state->first = 1;
+ state->pwm = 50;
+
+ state->monitor = attach_i2c_chip(XSERVE_SLOTS_LM75, "slots_temp");
+ if (state->monitor == NULL)
+ return -ENODEV;
+
+ device_create_file(&of_dev->dev, &dev_attr_slots_temperature);
+ device_create_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
+
+ return 0;
+}
+
+/*
+ * Dispose of the state data for the slots control loop
+ */
+static void dispose_slots_state(struct slots_pid_state *state)
+{
+ if (state->monitor == NULL)
+ return;
+
+ device_remove_file(&of_dev->dev, &dev_attr_slots_temperature);
+ device_remove_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
+
+ detach_i2c_chip(state->monitor);
+ state->monitor = NULL;
+}
+
+
static int call_critical_overtemp(void)
{
char *argv[] = { critical_overtemp_path, NULL };
@@ -1617,14 +1791,17 @@ static int main_control_loop(void *x)
goto out;
}
- /* Set the PCI fan once for now */
- set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
+ /* Set the PCI fan once for now on non-RackMac */
+ if (!rackmac)
+ set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
/* Initialize ADCs */
initialize_adc(&cpu_state[0]);
if (cpu_state[1].monitor != NULL)
initialize_adc(&cpu_state[1]);
+ fcu_tickle_ticks = FCU_TICKLE_TICKS;
+
up(&driver_lock);
while (state == state_attached) {
@@ -1634,6 +1811,12 @@ static int main_control_loop(void *x)
down(&driver_lock);
+ /* Tickle the FCU just in case */
+ if (--fcu_tickle_ticks < 0) {
+ fcu_tickle_ticks = FCU_TICKLE_TICKS;
+ tickle_fcu();
+ }
+
/* First, we always calculate the new DIMMs state on an Xserve */
if (rackmac)
do_monitor_dimms(&dimms_state);
@@ -1654,7 +1837,9 @@ static int main_control_loop(void *x)
}
/* Then, the rest */
do_monitor_backside(&backside_state);
- if (!rackmac)
+ if (rackmac)
+ do_monitor_slots(&slots_state);
+ else
do_monitor_drives(&drives_state);
up(&driver_lock);
@@ -1696,6 +1881,7 @@ static void dispose_control_loops(void)
dispose_cpu_state(&cpu_state[1]);
dispose_backside_state(&backside_state);
dispose_drives_state(&drives_state);
+ dispose_slots_state(&slots_state);
dispose_dimms_state(&dimms_state);
}
@@ -1745,6 +1931,8 @@ static int create_control_loops(void)
goto fail;
if (rackmac && init_dimms_state(&dimms_state))
goto fail;
+ if (rackmac && init_slots_state(&slots_state))
+ goto fail;
if (!rackmac && init_drives_state(&drives_state))
goto fail;
diff --git a/drivers/macintosh/therm_pm72.h b/drivers/macintosh/therm_pm72.h
index fc7e9b7ecaf..393cc9df94e 100644
--- a/drivers/macintosh/therm_pm72.h
+++ b/drivers/macintosh/therm_pm72.h
@@ -105,6 +105,7 @@ static char * critical_overtemp_path = "/sbin/critical_overtemp";
#define DRIVES_DALLAS_ID 0x94
#define BACKSIDE_MAX_ID 0x98
#define XSERVE_DIMMS_LM87 0x25a
+#define XSERVE_SLOTS_LM75 0x290
/*
* Some MAX6690, DS1775, LM87 register definitions
@@ -198,7 +199,7 @@ struct drives_pid_state
#define SLOTS_FAN_PWM_DEFAULT_ID 2
#define SLOTS_FAN_PWM_INDEX 2
-#define SLOTS_FAN_DEFAULT_PWM 50 /* Do better here ! */
+#define SLOTS_FAN_DEFAULT_PWM 40 /* Do better here ! */
/*
@@ -206,7 +207,7 @@ struct drives_pid_state
*/
#define DIMM_PID_G_d 0
#define DIMM_PID_G_p 0
-#define DIMM_PID_G_r 0x6553600
+#define DIMM_PID_G_r 0x06553600
#define DIMM_PID_INPUT_TARGET 3276800
#define DIMM_PID_INTERVAL 1
#define DIMM_PID_OUTPUT_MAX 14000
@@ -226,6 +227,31 @@ struct dimm_pid_state
};
+/*
+ * PID factors for the Xserve Slots control loop
+ */
+#define SLOTS_PID_G_d 0
+#define SLOTS_PID_G_p 0
+#define SLOTS_PID_G_r 0x00100000
+#define SLOTS_PID_INPUT_TARGET 3200000
+#define SLOTS_PID_INTERVAL 1
+#define SLOTS_PID_OUTPUT_MAX 100
+#define SLOTS_PID_OUTPUT_MIN 20
+#define SLOTS_PID_HISTORY_SIZE 20
+
+struct slots_pid_state
+{
+ int ticks;
+ struct i2c_client * monitor;
+ s32 sample_history[SLOTS_PID_HISTORY_SIZE];
+ s32 error_history[SLOTS_PID_HISTORY_SIZE];
+ int cur_sample;
+ s32 last_temp;
+ int first;
+ int pwm;
+};
+
+
/* Desktops */
@@ -283,6 +309,9 @@ struct cpu_pid_state
s32 pump_max;
};
+/* Tickle FCU every 10 seconds */
+#define FCU_TICKLE_TICKS 10
+
/*
* Driver state
*/
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
index b42d05f2aaf..d3f8d75bcbb 100644
--- a/drivers/macintosh/via-pmu-backlight.c
+++ b/drivers/macintosh/via-pmu-backlight.c
@@ -15,8 +15,9 @@
#define MAX_PMU_LEVEL 0xFF
-static struct device_node *vias;
static struct backlight_properties pmu_backlight_data;
+static spinlock_t pmu_backlight_lock;
+static int sleeping;
static int pmu_backlight_get_level_brightness(struct fb_info *info,
int level)
@@ -40,23 +41,36 @@ static int pmu_backlight_update_status(struct backlight_device *bd)
{
struct fb_info *info = class_get_devdata(&bd->class_dev);
struct adb_request req;
- int pmulevel, level = bd->props->brightness;
+ unsigned long flags;
+ int level = bd->props->brightness;
- if (vias == NULL)
- return -ENODEV;
+ spin_lock_irqsave(&pmu_backlight_lock, flags);
+
+ /* Don't update brightness when sleeping */
+ if (sleeping)
+ goto out;
if (bd->props->power != FB_BLANK_UNBLANK ||
bd->props->fb_blank != FB_BLANK_UNBLANK)
level = 0;
- pmulevel = pmu_backlight_get_level_brightness(info, level);
+ if (level > 0) {
+ int pmulevel = pmu_backlight_get_level_brightness(info, level);
- pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel);
- pmu_wait_complete(&req);
+ pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel);
+ pmu_wait_complete(&req);
- pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
- PMU_POW_BACKLIGHT | (level > 0 ? PMU_POW_ON : PMU_POW_OFF));
- pmu_wait_complete(&req);
+ pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+ PMU_POW_BACKLIGHT | PMU_POW_ON);
+ pmu_wait_complete(&req);
+ } else {
+ pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+ PMU_POW_BACKLIGHT | PMU_POW_OFF);
+ pmu_wait_complete(&req);
+ }
+
+out:
+ spin_unlock_irqrestore(&pmu_backlight_lock, flags);
return 0;
}
@@ -73,15 +87,39 @@ static struct backlight_properties pmu_backlight_data = {
.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
};
-void __init pmu_backlight_init(struct device_node *in_vias)
+#ifdef CONFIG_PM
+static int pmu_backlight_sleep_call(struct pmu_sleep_notifier *self, int when)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&pmu_backlight_lock, flags);
+
+ switch (when) {
+ case PBOOK_SLEEP_REQUEST:
+ sleeping = 1;
+ break;
+ case PBOOK_WAKE:
+ sleeping = 0;
+ break;
+ }
+
+ spin_unlock_irqrestore(&pmu_backlight_lock, flags);
+
+ return PBOOK_SLEEP_OK;
+}
+
+static struct pmu_sleep_notifier pmu_backlight_sleep_notif = {
+ .notifier_call = pmu_backlight_sleep_call,
+};
+#endif
+
+void __init pmu_backlight_init()
{
struct backlight_device *bd;
struct fb_info *info;
char name[10];
int level, autosave;
- vias = in_vias;
-
/* Special case for the old PowerBook since I can't test on it */
autosave =
machine_is_compatible("AAPL,3400/2400") ||
@@ -141,6 +179,10 @@ void __init pmu_backlight_init(struct device_node *in_vias)
pmac_backlight = bd;
mutex_unlock(&pmac_backlight_mutex);
+#ifdef CONFIG_PM
+ pmu_register_sleep_notifier(&pmu_backlight_sleep_notif);
+#endif
+
printk("pmubl: Backlight initialized (%s)\n", name);
return;
diff --git a/drivers/macintosh/via-pmu-led.c b/drivers/macintosh/via-pmu-led.c
index af8375ed0f5..5189d5454b1 100644
--- a/drivers/macintosh/via-pmu-led.c
+++ b/drivers/macintosh/via-pmu-led.c
@@ -74,7 +74,7 @@ static void pmu_led_set(struct led_classdev *led_cdev,
static struct led_classdev pmu_led = {
.name = "pmu-front-led",
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
+#ifdef CONFIG_ADB_PMU_LED_IDE
.default_trigger = "ide-disk",
#endif
.brightness_set = pmu_led_set,
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 06ca80bfd6b..ea386801e21 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -16,7 +16,6 @@
* a sleep or a freq. switch
* - Move sleep code out of here to pmac_pm, merge into new
* common PM infrastructure
- * - Move backlight code out as well
* - Save/Restore PCI space properly
*
*/
@@ -60,9 +59,7 @@
#include <asm/mmu_context.h>
#include <asm/cputable.h>
#include <asm/time.h>
-#ifdef CONFIG_PMAC_BACKLIGHT
#include <asm/backlight.h>
-#endif
#include "via-pmu-event.h"
@@ -177,10 +174,6 @@ static int query_batt_timer = BATTERY_POLLING_COUNT;
static struct adb_request batt_req;
static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES];
-#if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
-extern int disable_kernel_backlight;
-#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */
-
int __fake_sleep;
int asleep;
BLOCKING_NOTIFIER_HEAD(sleep_notifier_list);
@@ -466,7 +459,7 @@ static int __init via_pmu_dev_init(void)
#ifdef CONFIG_PMAC_BACKLIGHT
/* Initialize backlight */
- pmu_backlight_init(vias);
+ pmu_backlight_init();
#endif
#ifdef CONFIG_PPC32
@@ -1403,11 +1396,8 @@ next:
else if ((1 << pirq) & PMU_INT_SNDBRT) {
#ifdef CONFIG_PMAC_BACKLIGHT
if (len == 3)
-#ifdef CONFIG_INPUT_ADBHID
- if (!disable_kernel_backlight)
-#endif /* CONFIG_INPUT_ADBHID */
- pmac_backlight_set_legacy_brightness(data[1] >> 4);
-#endif /* CONFIG_PMAC_BACKLIGHT */
+ pmac_backlight_set_legacy_brightness_pmu(data[1] >> 4);
+#endif
}
/* Tick interrupt */
else if ((1 << pirq) & PMU_INT_TICK) {
@@ -2414,7 +2404,7 @@ struct pmu_private {
spinlock_t lock;
#if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
int backlight_locker;
-#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */
+#endif
};
static LIST_HEAD(all_pmu_pvt);
@@ -2464,7 +2454,7 @@ pmu_open(struct inode *inode, struct file *file)
spin_lock_irqsave(&all_pvt_lock, flags);
#if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
pp->backlight_locker = 0;
-#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */
+#endif
list_add(&pp->list, &all_pmu_pvt);
spin_unlock_irqrestore(&all_pvt_lock, flags);
file->private_data = pp;
@@ -2559,13 +2549,12 @@ pmu_release(struct inode *inode, struct file *file)
spin_lock_irqsave(&all_pvt_lock, flags);
list_del(&pp->list);
spin_unlock_irqrestore(&all_pvt_lock, flags);
+
#if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
- if (pp->backlight_locker) {
- spin_lock_irqsave(&pmu_lock, flags);
- disable_kernel_backlight--;
- spin_unlock_irqrestore(&pmu_lock, flags);
- }
-#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */
+ if (pp->backlight_locker)
+ pmac_backlight_enable();
+#endif
+
kfree(pp);
}
unlock_kernel();
@@ -2642,18 +2631,18 @@ pmu_ioctl(struct inode * inode, struct file *filp,
#ifdef CONFIG_INPUT_ADBHID
case PMU_IOC_GRAB_BACKLIGHT: {
struct pmu_private *pp = filp->private_data;
- unsigned long flags;
if (pp->backlight_locker)
return 0;
+
pp->backlight_locker = 1;
- spin_lock_irqsave(&pmu_lock, flags);
- disable_kernel_backlight++;
- spin_unlock_irqrestore(&pmu_lock, flags);
+ pmac_backlight_disable();
+
return 0;
}
#endif /* CONFIG_INPUT_ADBHID */
#endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */
+
case PMU_IOC_GET_MODEL:
return put_user(pmu_kind, argp);
case PMU_IOC_HAS_ADB:
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index ff83c9b5979..b99c19c7eb2 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -162,7 +162,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
goto out;
}
- min_spacing = mddev->array_size;
+ min_spacing = conf->array_size;
sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *));
/* min_spacing is the minimum spacing that will fit the hash
@@ -171,7 +171,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
* that is larger than min_spacing as use the size of that as
* the actual spacing
*/
- conf->hash_spacing = mddev->array_size;
+ conf->hash_spacing = conf->array_size;
for (i=0; i < cnt-1 ; i++) {
sector_t sz = 0;
int j;
@@ -228,7 +228,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
curr_offset = 0;
i = 0;
for (curr_offset = 0;
- curr_offset < mddev->array_size;
+ curr_offset < conf->array_size;
curr_offset += conf->hash_spacing) {
while (i < mddev->raid_disks-1 &&
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 59ac35ddd51..57b34cda99f 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -526,7 +526,9 @@ static int dvb_frontend_thread(void *data)
fepriv->delay = 3*HZ;
fepriv->status = 0;
fepriv->wakeup = 0;
- fepriv->reinitialise = 1;
+ fepriv->reinitialise = 0;
+
+ dvb_frontend_init(fe);
while (1) {
up(&fepriv->sem); /* is locked when we enter the thread... */
@@ -1013,17 +1015,18 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
return ret;
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+
+ /* normal tune mode when opened R/W */
+ fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
+ fepriv->tone = -1;
+ fepriv->voltage = -1;
+
ret = dvb_frontend_start (fe);
if (ret)
dvb_generic_release (inode, file);
/* empty event queue */
fepriv->events.eventr = fepriv->events.eventw = 0;
-
- /* normal tune mode when opened R/W */
- fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
- fepriv->tone = -1;
- fepriv->voltage = -1;
}
return ret;
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index a189683454b..2be33f27c69 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -194,11 +194,11 @@ struct dvb_pll_desc dvb_pll_tda665x = {
{ 253834000, 36249333, 166667, 0xca, 0x62 /* 011 0 0 0 10 */ },
{ 383834000, 36249333, 166667, 0xca, 0xa2 /* 101 0 0 0 10 */ },
{ 443834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ },
- { 444000000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ },
- { 583834000, 36249333, 166667, 0xca, 0x63 /* 011 0 0 0 11 */ },
- { 793834000, 36249333, 166667, 0xca, 0xa3 /* 101 0 0 0 11 */ },
- { 444834000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ },
- { 861000000, 36249333, 166667, 0xca, 0xe3 /* 111 0 0 0 11 */ },
+ { 444000000, 36249333, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ },
+ { 583834000, 36249333, 166667, 0xca, 0x64 /* 011 0 0 1 00 */ },
+ { 793834000, 36249333, 166667, 0xca, 0xa4 /* 101 0 0 1 00 */ },
+ { 444834000, 36249333, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ },
+ { 861000000, 36249333, 166667, 0xca, 0xe4 /* 111 0 0 1 00 */ },
}
};
EXPORT_SYMBOL(dvb_pll_tda665x);
@@ -613,7 +613,21 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = {
int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
{
+ u8 b1 [] = { 0 };
+ struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 };
struct dvb_pll_priv *priv = NULL;
+ int ret;
+
+ if (i2c != NULL) {
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ ret = i2c_transfer (i2c, &msg, 1);
+ if (ret != 1)
+ return -1;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
if (priv == NULL)
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 500f15c10aa..4506165c5de 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -2203,8 +2203,8 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
/* set TDA9819 into DVB mode */
- saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
- saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
+ saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
+ saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
/* tuner on this needs a slower i2c bus speed */
av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index 64055461559..6ffe53fdcf5 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -272,8 +272,8 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
dprintk(1, "setting band in demodulator failed.\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
- saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD)
- saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF)
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9819 pin9(STD)
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9819 pin30(VIF)
}
if (i2c_writereg(av7110, 0x48, 0x02, 0xd0) != 1)
dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
@@ -308,8 +308,8 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
if (ves1820_writereg(dev, 0x09, 0x0f, 0x20))
dprintk(1, "setting band in demodulator failed.\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
- saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
- saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
}
}
@@ -750,8 +750,8 @@ int av7110_init_analog_module(struct av7110 *av7110)
if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20))
dprintk(1, "setting band in demodulator failed.\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
- saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
- saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
+ saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
+ saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
}
/* init the saa7113 */
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 5f111d40773..2d21fec23b4 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -1303,6 +1303,9 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
budget_av->budget.dvb_adapter.priv = budget_av;
frontend_init(budget_av);
ciintf_init(budget_av);
+
+ ttpci_budget_init_hooks(&budget_av->budget);
+
return 0;
}
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 4b966eea383..ffbbb3e34be 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -1101,6 +1101,8 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
budget_ci->budget.dvb_adapter.priv = budget_ci;
frontend_init(budget_ci);
+ ttpci_budget_init_hooks(&budget_ci->budget);
+
return 0;
}
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index e4cf7775e07..e15562f8166 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -63,9 +63,6 @@ static int stop_ts_capture(struct budget *budget)
{
dprintk(2, "budget: %p\n", budget);
- if (--budget->feeding)
- return budget->feeding;
-
saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off
SAA7146_IER_DISABLE(budget->dev, MASK_10);
return 0;
@@ -77,8 +74,8 @@ static int start_ts_capture(struct budget *budget)
dprintk(2, "budget: %p\n", budget);
- if (budget->feeding)
- return ++budget->feeding;
+ if (!budget->feeding || !budget->fe_synced)
+ return 0;
saa7146_write(dev, MC1, MASK_20); // DMA3 off
@@ -139,7 +136,33 @@ static int start_ts_capture(struct budget *budget)
SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
saa7146_write(dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
- return ++budget->feeding;
+ return 0;
+}
+
+static int budget_read_fe_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct budget *budget = (struct budget *) fe->dvb->priv;
+ int synced;
+ int ret;
+
+ if (budget->read_fe_status)
+ ret = budget->read_fe_status(fe, status);
+ else
+ ret = -EINVAL;
+
+ if (!ret) {
+ synced = (*status & FE_HAS_LOCK);
+ if (synced != budget->fe_synced) {
+ budget->fe_synced = synced;
+ spin_lock(&budget->feedlock);
+ if (synced)
+ start_ts_capture(budget);
+ else
+ stop_ts_capture(budget);
+ spin_unlock(&budget->feedlock);
+ }
+ }
+ return ret;
}
static void vpeirq(unsigned long data)
@@ -267,7 +290,7 @@ static int budget_start_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
struct budget *budget = (struct budget *) demux->priv;
- int status;
+ int status = 0;
dprintk(2, "budget: %p\n", budget);
@@ -276,7 +299,8 @@ static int budget_start_feed(struct dvb_demux_feed *feed)
spin_lock(&budget->feedlock);
feed->pusi_seen = 0; /* have a clean section start */
- status = start_ts_capture(budget);
+ if (budget->feeding++ == 0)
+ status = start_ts_capture(budget);
spin_unlock(&budget->feedlock);
return status;
}
@@ -285,12 +309,13 @@ static int budget_stop_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
struct budget *budget = (struct budget *) demux->priv;
- int status;
+ int status = 0;
dprintk(2, "budget: %p\n", budget);
spin_lock(&budget->feedlock);
- status = stop_ts_capture(budget);
+ if (--budget->feeding == 0)
+ status = stop_ts_capture(budget);
spin_unlock(&budget->feedlock);
return status;
}
@@ -470,6 +495,14 @@ err:
return ret;
}
+void ttpci_budget_init_hooks(struct budget *budget)
+{
+ if (budget->dvb_frontend && !budget->read_fe_status) {
+ budget->read_fe_status = budget->dvb_frontend->ops.read_status;
+ budget->dvb_frontend->ops.read_status = budget_read_fe_status;
+ }
+}
+
int ttpci_budget_deinit(struct budget *budget)
{
struct saa7146_dev *dev = budget->dev;
@@ -508,11 +541,8 @@ void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port)
spin_lock(&budget->feedlock);
budget->video_port = video_port;
if (budget->feeding) {
- int oldfeeding = budget->feeding;
- budget->feeding = 1;
stop_ts_capture(budget);
start_ts_capture(budget);
- budget->feeding = oldfeeding;
}
spin_unlock(&budget->feedlock);
}
@@ -520,6 +550,7 @@ void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port)
EXPORT_SYMBOL_GPL(ttpci_budget_debiread);
EXPORT_SYMBOL_GPL(ttpci_budget_debiwrite);
EXPORT_SYMBOL_GPL(ttpci_budget_init);
+EXPORT_SYMBOL_GPL(ttpci_budget_init_hooks);
EXPORT_SYMBOL_GPL(ttpci_budget_deinit);
EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler);
EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port);
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index ee60ce90a40..57227441891 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -617,6 +617,8 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
budget->dvb_adapter.priv = budget;
frontend_init(budget);
+ ttpci_budget_init_hooks(budget);
+
return 0;
}
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index 35761f13c12..863dffb4ed8 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -375,9 +375,6 @@ static void frontend_init(struct budget *budget)
if (budget->dvb_frontend) {
budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
- budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
- budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
- budget->dvb_frontend->ops.set_tone = budget_set_tone;
break;
}
break;
@@ -474,6 +471,8 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_
budget->dvb_adapter.priv = budget;
frontend_init(budget);
+ ttpci_budget_init_hooks(budget);
+
return 0;
}
diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
index ecea3a13030..e8a5c79178e 100644
--- a/drivers/media/dvb/ttpci/budget.h
+++ b/drivers/media/dvb/ttpci/budget.h
@@ -52,9 +52,6 @@ struct budget {
struct dmx_frontend hw_frontend;
struct dmx_frontend mem_frontend;
- int fe_synced;
- struct mutex pid_mutex;
-
int ci_present;
int video_port;
@@ -74,6 +71,9 @@ struct budget {
struct dvb_adapter dvb_adapter;
struct dvb_frontend *dvb_frontend;
+ int (*read_fe_status)(struct dvb_frontend *fe, fe_status_t *status);
+ int fe_synced;
+
void *priv;
};
@@ -106,6 +106,7 @@ static struct saa7146_pci_extension_data x_var = { \
extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
struct saa7146_pci_extension_data *info,
struct module *owner);
+extern void ttpci_budget_init_hooks(struct budget *budget);
extern int ttpci_budget_deinit(struct budget *budget);
extern void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr);
extern void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port);
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 6d532f170ce..fe56862d51e 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -145,7 +145,7 @@ config VIDEO_SAA5246A
config VIDEO_SAA5249
tristate "SAA5249 Teletext processor"
- depends on VIDEO_DEV && I2C
+ depends on VIDEO_DEV && I2C && VIDEO_V4L1
help
Support for I2C bus based teletext using the SAA5249 chip. At the
moment this is only useful on some European WinTV cards.
@@ -155,7 +155,7 @@ config VIDEO_SAA5249
config TUNER_3036
tristate "SAB3036 tuner"
- depends on VIDEO_DEV && I2C
+ depends on VIDEO_DEV && I2C && VIDEO_V4L1
help
Say Y here to include support for Philips SAB3036 compatible tuners.
If in doubt, say N.
diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig
index 153f6a4a96c..cdcf5565071 100644
--- a/drivers/media/video/bt8xx/Kconfig
+++ b/drivers/media/video/bt8xx/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_BT848
tristate "BT848 Video For Linux"
- depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2
+ depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L1
select I2C_ALGOBIT
select FW_LOADER
select VIDEO_BTCX
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 5764a89d356..20dff7c316e 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -3923,7 +3923,12 @@ static int __devinit bttv_register_video(struct bttv *btv)
goto err;
printk(KERN_INFO "bttv%d: registered device video%d\n",
btv->c.nr,btv->video_dev->minor & 0x1f);
- video_device_create_file(btv->video_dev, &class_device_attr_card);
+ if (class_device_create_file(&btv->video_dev->class_dev,
+ &class_device_attr_card)<0) {
+ printk(KERN_ERR "bttv%d: class_device_create_file 'card' "
+ "failed\n", btv->c.nr);
+ goto err;
+ }
/* vbi */
btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi");
@@ -4287,6 +4292,8 @@ static struct pci_driver bttv_pci_driver = {
static int bttv_init_module(void)
{
+ int ret;
+
bttv_num = 0;
printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n",
@@ -4308,7 +4315,11 @@ static int bttv_init_module(void)
bttv_check_chipset();
- bus_register(&bttv_sub_bus_type);
+ ret = bus_register(&bttv_sub_bus_type);
+ if (ret < 0) {
+ printk(KERN_WARNING "bttv: bus_register error: %d\n", ret);
+ return ret;
+ }
return pci_register_driver(&bttv_pci_driver);
}
diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
index 8c9f0f7cf46..63676e7bd63 100644
--- a/drivers/media/video/bt8xx/bttv-vbi.c
+++ b/drivers/media/video/bt8xx/bttv-vbi.c
@@ -31,11 +31,16 @@
#include <asm/io.h>
#include "bttvp.h"
-/* Offset from line sync pulse leading edge (0H) in 1 / sampling_rate:
- bt8x8 /HRESET pulse starts at 0H and has length 64 / fCLKx1 (E|O_VTC
- HSFMT = 0). VBI_HDELAY (always 0) is an offset from the trailing edge
- of /HRESET in 1 / fCLKx1, and the sampling_rate tvnorm->Fsc is fCLKx2. */
-#define VBI_OFFSET ((64 + 0) * 2)
+/* Offset from line sync pulse leading edge (0H) to start of VBI capture,
+ in fCLKx2 pixels. According to the datasheet, VBI capture starts
+ VBI_HDELAY fCLKx1 pixels from the tailing edgeof /HRESET, and /HRESET
+ is 64 fCLKx1 pixels wide. VBI_HDELAY is set to 0, so this should be
+ (64 + 0) * 2 = 128 fCLKx2 pixels. But it's not! The datasheet is
+ Just Plain Wrong. The real value appears to be different for
+ different revisions of the bt8x8 chips, and to be affected by the
+ horizontal scaling factor. Experimentally, the value is measured
+ to be about 244. */
+#define VBI_OFFSET 244
#define VBI_DEFLINES 16
#define VBI_MAXLINES 32
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c
index 353d02b67c3..9dddff42ec1 100644
--- a/drivers/media/video/compat_ioctl32.c
+++ b/drivers/media/video/compat_ioctl32.c
@@ -490,6 +490,23 @@ static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user
return 0;
}
+struct video_code32
+{
+ char loadwhat[16]; /* name or tag of file being passed */
+ compat_int_t datasize;
+ unsigned char *data;
+};
+
+static inline int microcode32(struct video_code *kp, struct video_code32 __user *up)
+{
+ if(!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) ||
+ copy_from_user(kp->loadwhat, up->loadwhat, sizeof (up->loadwhat)) ||
+ get_user(kp->datasize, &up->datasize) ||
+ copy_from_user(kp->data, up->data, up->datasize))
+ return -EFAULT;
+ return 0;
+}
+
#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32)
#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32)
#define VIDIOCGWIN32 _IOR('v',9, struct video_window32)
@@ -498,6 +515,7 @@ static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user
#define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32)
#define VIDIOCGFREQ32 _IOR('v',14, u32)
#define VIDIOCSFREQ32 _IOW('v',15, u32)
+#define VIDIOCSMICROCODE32 _IOW('v',27, struct video_code32)
/* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */
#define VIDIOC_ENUMINPUT32 VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4)
@@ -590,6 +608,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
struct video_tuner vt;
struct video_buffer vb;
struct video_window vw;
+ struct video_code vc;
struct v4l2_format v2f;
struct v4l2_buffer v2b;
struct v4l2_framebuffer v2fb;
@@ -628,6 +647,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
+ case VIDIOCSMICROCODE32: cmd = VIDIOCSMICROCODE; break;
};
switch(cmd) {
@@ -703,6 +723,10 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
case VIDIOC_G_FBUF:
case VIDIOC_G_INPUT:
compatible_arg = 0;
+ case VIDIOCSMICROCODE:
+ err = microcode32(&karg.vc, up);
+ compatible_arg = 0;
+ break;
};
if(err)
diff --git a/drivers/media/video/cpia2/Kconfig b/drivers/media/video/cpia2/Kconfig
index 513cc092738..e39a9615200 100644
--- a/drivers/media/video/cpia2/Kconfig
+++ b/drivers/media/video/cpia2/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_CPIA2
tristate "CPiA2 Video For Linux"
- depends on VIDEO_DEV && USB
+ depends on VIDEO_DEV && USB && VIDEO_V4L1
---help---
This is the video4linux driver for cameras based on Vision's CPiA2
(Colour Processor Interface ASIC), such as the Digital Blue QX5
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index 72b630a91f4..c2556464899 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -89,7 +89,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
auxgpio = cx_read(MO_GP1_IO);
/* Take out the parity part */
- gpio+=(gpio & 0x7fd) + (auxgpio & 0xef);
+ gpio=(gpio & 0x7fd) + (auxgpio & 0xef);
} else
auxgpio = gpio;
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 2225d4b9414..547cdbdb644 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1180,7 +1180,6 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING |
V4L2_CAP_VBI_CAPTURE |
- V4L2_CAP_VIDEO_OVERLAY |
0;
if (UNSET != core->tuner_type)
cap->capabilities |= V4L2_CAP_TUNER;
@@ -1226,7 +1225,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
struct v4l2_format *f = arg;
return cx8800_try_fmt(dev,fh,f);
}
-#ifdef HAVE_V4L1
+#ifdef CONFIG_V4L1_COMPAT
/* --- streaming capture ------------------------------------- */
case VIDIOCGMBUF:
{
@@ -1585,7 +1584,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
*id = 0;
return 0;
}
-#ifdef HAVE_V4L1
+#ifdef CONFIG_V4L1_COMPAT
case VIDIOCSTUNER:
{
struct video_tuner *v = arg;
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index dbb75a7db19..56246b8578f 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -362,7 +362,7 @@ int msp_sleep(struct msp_state *state, int timeout)
}
/* ------------------------------------------------------------------------ */
-
+#ifdef CONFIG_VIDEO_V4L1
static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode)
{
if (rxsubchans == V4L2_TUNER_SUB_MONO)
@@ -384,6 +384,7 @@ static int msp_mode_v4l1_to_v4l2(int mode)
return V4L2_TUNER_MODE_LANG1;
return V4L2_TUNER_MODE_MONO;
}
+#endif
static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
{
@@ -509,6 +510,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
/* --- v4l ioctls --- */
/* take care: bttv does userspace copying, we'll get a
kernel pointer here... */
+#ifdef CONFIG_VIDEO_V4L1
case VIDIOCGAUDIO:
{
struct video_audio *va = arg;
@@ -577,6 +579,12 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
}
case VIDIOCSFREQ:
+ {
+ /* new channel -- kick audio carrier scan */
+ msp_wake_thread(client);
+ break;
+ }
+#endif
case VIDIOC_S_FREQUENCY:
{
/* new channel -- kick audio carrier scan */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 9b48abcf608..be1e5cc7808 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -852,7 +852,6 @@ unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *hdw)
return hdw->serial_number;
}
-
int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw)
{
return hdw->unit_number;
@@ -2318,7 +2317,6 @@ void pvr2_hdw_poll_trigger_unlocked(struct pvr2_hdw *hdw)
}
}
-
/* Return name for this driver instance */
const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
{
@@ -2542,6 +2540,10 @@ static void pvr2_ctl_timeout(unsigned long data)
}
+/* Issue a command and get a response from the device. This extended
+ version includes a probe flag (which if set means that device errors
+ should not be logged or treated as fatal) and a timeout in jiffies.
+ This can be used to non-lethally probe the health of endpoint 1. */
static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
unsigned int timeout,int probe_fl,
void *write_data,unsigned int write_len,
@@ -2970,6 +2972,7 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
}
+/* Stop / start video stream transport */
static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
{
int status;
@@ -3068,6 +3071,7 @@ int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val)
}
+/* Find I2C address of eeprom */
static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
{
int result;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c
index 681f79c8064..1e393762546 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-io.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-io.c
@@ -26,6 +26,8 @@
#include <linux/slab.h>
#include <linux/mutex.h>
+static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state);
+
#define BUFFER_SIG 0x47653271
// #define SANITY_CHECK_BUFFERS
@@ -515,6 +517,10 @@ void pvr2_stream_set_callback(struct pvr2_stream *sp,
}
/* Query / set the nominal buffer count */
+int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
+{
+ return sp->buffer_target_count;
+}
int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
{
@@ -553,7 +559,6 @@ int pvr2_stream_get_ready_count(struct pvr2_stream *sp)
return sp->r_count;
}
-
void pvr2_stream_kill(struct pvr2_stream *sp)
{
struct pvr2_buffer *bp;
@@ -607,7 +612,6 @@ int pvr2_buffer_queue(struct pvr2_buffer *bp)
return ret;
}
-
int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt)
{
int ret = 0;
@@ -646,7 +650,6 @@ int pvr2_buffer_get_status(struct pvr2_buffer *bp)
return bp->status;
}
-
int pvr2_buffer_get_id(struct pvr2_buffer *bp)
{
return bp->id;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.h b/drivers/media/video/pvrusb2/pvrusb2-io.h
index 96285ad234a..93279cc2a35 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-io.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-io.h
@@ -47,6 +47,7 @@ void pvr2_stream_set_callback(struct pvr2_stream *,
void *data);
/* Query / set the nominal buffer count */
+int pvr2_stream_get_buffer_count(struct pvr2_stream *);
int pvr2_stream_set_buffer_count(struct pvr2_stream *,unsigned int);
/* Get a pointer to a buffer that is either idle, ready, or is specified
@@ -58,6 +59,7 @@ struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id);
/* Find out how many buffers are idle or ready */
int pvr2_stream_get_ready_count(struct pvr2_stream *);
+
/* Kill all pending buffers and throw away any ready buffers as well */
void pvr2_stream_kill(struct pvr2_stream *);
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
index f7a2e225a00..b71f9a961f8 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ioread.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
@@ -213,7 +213,9 @@ int pvr2_ioread_setup(struct pvr2_ioread *cp,struct pvr2_stream *sp)
" pvr2_ioread_setup (tear-down) id=%p",cp);
pvr2_ioread_stop(cp);
pvr2_stream_kill(cp->stream);
- pvr2_stream_set_buffer_count(cp->stream,0);
+ if (pvr2_stream_get_buffer_count(cp->stream)) {
+ pvr2_stream_set_buffer_count(cp->stream,0);
+ }
cp->stream = NULL;
}
if (sp) {
@@ -251,7 +253,6 @@ int pvr2_ioread_set_enabled(struct pvr2_ioread *cp,int fl)
return ret;
}
-
static int pvr2_ioread_get_buffer(struct pvr2_ioread *cp)
{
int stat;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index 6af55a8b6f0..d1dda5caf40 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -44,12 +44,16 @@ struct pvr2_sysfs {
struct kobj_type ktype;
struct class_device_attribute attr_v4l_minor_number;
struct class_device_attribute attr_unit_number;
+ int v4l_minor_number_created_ok;
+ int unit_number_created_ok;
};
#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
struct pvr2_sysfs_debugifc {
struct class_device_attribute attr_debugcmd;
struct class_device_attribute attr_debuginfo;
+ int debugcmd_created_ok;
+ int debuginfo_created_ok;
};
#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
@@ -67,6 +71,7 @@ struct pvr2_sysfs_ctl_item {
struct pvr2_sysfs_ctl_item *item_next;
struct attribute *attr_gen[7];
struct attribute_group grp;
+ int created_ok;
char name[80];
};
@@ -487,6 +492,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
struct pvr2_sysfs_func_set *fp;
struct pvr2_ctrl *cptr;
unsigned int cnt,acnt;
+ int ret;
if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) {
return;
@@ -589,7 +595,13 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
cip->grp.name = cip->name;
cip->grp.attrs = cip->attr_gen;
- sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
+ ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
+ if (ret) {
+ printk(KERN_WARNING "%s: sysfs_create_group error: %d\n",
+ __FUNCTION__, ret);
+ return;
+ }
+ cip->created_ok = !0;
}
#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
@@ -600,6 +612,8 @@ static ssize_t debugcmd_store(struct class_device *,const char *,size_t count);
static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
{
struct pvr2_sysfs_debugifc *dip;
+ int ret;
+
dip = kmalloc(sizeof(*dip),GFP_KERNEL);
if (!dip) return;
memset(dip,0,sizeof(*dip));
@@ -613,17 +627,34 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
dip->attr_debuginfo.attr.mode = S_IRUGO;
dip->attr_debuginfo.show = debuginfo_show;
sfp->debugifc = dip;
- class_device_create_file(sfp->class_dev,&dip->attr_debugcmd);
- class_device_create_file(sfp->class_dev,&dip->attr_debuginfo);
+ ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd);
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+ __FUNCTION__, ret);
+ } else {
+ dip->debugcmd_created_ok = !0;
+ }
+ ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo);
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+ __FUNCTION__, ret);
+ } else {
+ dip->debuginfo_created_ok = !0;
+ }
}
static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp)
{
if (!sfp->debugifc) return;
- class_device_remove_file(sfp->class_dev,
- &sfp->debugifc->attr_debuginfo);
- class_device_remove_file(sfp->class_dev,&sfp->debugifc->attr_debugcmd);
+ if (sfp->debugifc->debuginfo_created_ok) {
+ class_device_remove_file(sfp->class_dev,
+ &sfp->debugifc->attr_debuginfo);
+ }
+ if (sfp->debugifc->debugcmd_created_ok) {
+ class_device_remove_file(sfp->class_dev,
+ &sfp->debugifc->attr_debugcmd);
+ }
kfree(sfp->debugifc);
sfp->debugifc = NULL;
}
@@ -645,7 +676,9 @@ static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp)
struct pvr2_sysfs_ctl_item *cip1,*cip2;
for (cip1 = sfp->item_first; cip1; cip1 = cip2) {
cip2 = cip1->item_next;
- sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
+ if (cip1->created_ok) {
+ sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
+ }
pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1);
kfree(cip1);
}
@@ -675,8 +708,14 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp)
pvr2_sysfs_tear_down_debugifc(sfp);
#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
pvr2_sysfs_tear_down_controls(sfp);
- class_device_remove_file(sfp->class_dev,&sfp->attr_v4l_minor_number);
- class_device_remove_file(sfp->class_dev,&sfp->attr_unit_number);
+ if (sfp->v4l_minor_number_created_ok) {
+ class_device_remove_file(sfp->class_dev,
+ &sfp->attr_v4l_minor_number);
+ }
+ if (sfp->unit_number_created_ok) {
+ class_device_remove_file(sfp->class_dev,
+ &sfp->attr_unit_number);
+ }
pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
sfp->class_dev->class_data = NULL;
class_device_unregister(sfp->class_dev);
@@ -709,6 +748,8 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
{
struct usb_device *usb_dev;
struct class_device *class_dev;
+ int ret;
+
usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw);
if (!usb_dev) return;
class_dev = kmalloc(sizeof(*class_dev),GFP_KERNEL);
@@ -733,20 +774,40 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
sfp->class_dev = class_dev;
class_dev->class_data = sfp;
- class_device_register(class_dev);
+ ret = class_device_register(class_dev);
+ if (ret) {
+ printk(KERN_ERR "%s: class_device_register failed\n",
+ __FUNCTION__);
+ kfree(class_dev);
+ return;
+ }
sfp->attr_v4l_minor_number.attr.owner = THIS_MODULE;
sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number";
sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
sfp->attr_v4l_minor_number.store = NULL;
- class_device_create_file(sfp->class_dev,&sfp->attr_v4l_minor_number);
+ ret = class_device_create_file(sfp->class_dev,
+ &sfp->attr_v4l_minor_number);
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+ __FUNCTION__, ret);
+ } else {
+ sfp->v4l_minor_number_created_ok = !0;
+ }
+
sfp->attr_unit_number.attr.owner = THIS_MODULE;
sfp->attr_unit_number.attr.name = "unit_number";
sfp->attr_unit_number.attr.mode = S_IRUGO;
sfp->attr_unit_number.show = unit_number_show;
sfp->attr_unit_number.store = NULL;
- class_device_create_file(sfp->class_dev,&sfp->attr_unit_number);
+ ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number);
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+ __FUNCTION__, ret);
+ } else {
+ sfp->unit_number_created_ok = !0;
+ }
pvr2_sysfs_add_controls(sfp);
#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index f1fd69e7f11..d73cff1970a 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -997,9 +997,9 @@ static int saa7134_alsa_init(void)
struct saa7134_dev *dev = NULL;
struct list_head *list;
- if (!dmasound_init && !dmasound_exit) {
- dmasound_init = alsa_device_init;
- dmasound_exit = alsa_device_exit;
+ if (!saa7134_dmasound_init && !saa7134_dmasound_exit) {
+ saa7134_dmasound_init = alsa_device_init;
+ saa7134_dmasound_exit = alsa_device_exit;
} else {
printk(KERN_WARNING "saa7134 ALSA: can't load, DMA sound handler already assigned (probably to OSS)\n");
return -EBUSY;
@@ -1036,8 +1036,8 @@ static void saa7134_alsa_exit(void)
snd_card_free(snd_saa7134_cards[idx]);
}
- dmasound_init = NULL;
- dmasound_exit = NULL;
+ saa7134_dmasound_init = NULL;
+ saa7134_dmasound_exit = NULL;
printk(KERN_INFO "saa7134 ALSA driver for DMA sound unloaded\n");
return;
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 6e97cc84ba8..be3a81fc90a 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -95,8 +95,8 @@ LIST_HEAD(saa7134_devlist);
static LIST_HEAD(mops_list);
static unsigned int saa7134_devcount;
-int (*dmasound_init)(struct saa7134_dev *dev);
-int (*dmasound_exit)(struct saa7134_dev *dev);
+int (*saa7134_dmasound_init)(struct saa7134_dev *dev);
+int (*saa7134_dmasound_exit)(struct saa7134_dev *dev);
#define dprintk(fmt, arg...) if (core_debug) \
printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg)
@@ -1008,8 +1008,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
/* check for signal */
saa7134_irq_video_intl(dev);
- if (dmasound_init && !dev->dmasound.priv_data) {
- dmasound_init(dev);
+ if (saa7134_dmasound_init && !dev->dmasound.priv_data) {
+ saa7134_dmasound_init(dev);
}
return 0;
@@ -1036,8 +1036,8 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
struct saa7134_mpeg_ops *mops;
/* Release DMA sound modules if present */
- if (dmasound_exit && dev->dmasound.priv_data) {
- dmasound_exit(dev);
+ if (saa7134_dmasound_exit && dev->dmasound.priv_data) {
+ saa7134_dmasound_exit(dev);
}
/* debugging ... */
@@ -1169,8 +1169,8 @@ EXPORT_SYMBOL(saa7134_boards);
/* ----------------- for the DMA sound modules --------------- */
-EXPORT_SYMBOL(dmasound_init);
-EXPORT_SYMBOL(dmasound_exit);
+EXPORT_SYMBOL(saa7134_dmasound_init);
+EXPORT_SYMBOL(saa7134_dmasound_exit);
EXPORT_SYMBOL(saa7134_pgtable_free);
EXPORT_SYMBOL(saa7134_pgtable_build);
EXPORT_SYMBOL(saa7134_pgtable_alloc);
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index 3895d05804a..2e3ba5f3145 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -993,9 +993,9 @@ static int saa7134_oss_init(void)
struct saa7134_dev *dev = NULL;
struct list_head *list;
- if (!dmasound_init && !dmasound_exit) {
- dmasound_init = oss_device_init;
- dmasound_exit = oss_device_exit;
+ if (!saa7134_dmasound_init && !saa7134_dmasound_exit) {
+ saa7134_dmasound_init = oss_device_init;
+ saa7134_dmasound_exit = oss_device_exit;
} else {
printk(KERN_WARNING "saa7134 OSS: can't load, DMA sound handler already assigned (probably to ALSA)\n");
return -EBUSY;
@@ -1037,8 +1037,8 @@ static void saa7134_oss_exit(void)
}
- dmasound_init = NULL;
- dmasound_exit = NULL;
+ saa7134_dmasound_init = NULL;
+ saa7134_dmasound_exit = NULL;
printk(KERN_INFO "saa7134 OSS driver for DMA sound unloaded\n");
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index e4156ec9c6d..8656f2400e1 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -40,7 +40,7 @@
static unsigned int video_debug = 0;
static unsigned int gbuffers = 8;
-static unsigned int noninterlaced = 0;
+static unsigned int noninterlaced = 1;
static unsigned int gbufsize = 720*576*4;
static unsigned int gbufsize_max = 720*576*4;
module_param(video_debug, int, 0644);
@@ -48,7 +48,7 @@ MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
module_param(gbuffers, int, 0444);
MODULE_PARM_DESC(gbuffers,"number of capture buffers, range 2-32");
module_param(noninterlaced, int, 0644);
-MODULE_PARM_DESC(noninterlaced,"video input is noninterlaced");
+MODULE_PARM_DESC(noninterlaced,"capture non interlaced video");
#define dprintk(fmt, arg...) if (video_debug) \
printk(KERN_DEBUG "%s/video: " fmt, dev->name , ## arg)
@@ -2087,7 +2087,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
struct v4l2_format *f = arg;
return saa7134_try_fmt(dev,fh,f);
}
-#ifdef HAVE_V4L1
+#ifdef CONFIG_V4L1_COMPAT
case VIDIOCGMBUF:
{
struct video_mbuf *mbuf = arg;
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index d5ee99c574c..c04ce6152fd 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -586,8 +586,8 @@ void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf);
int saa7134_set_dmabits(struct saa7134_dev *dev);
-extern int (*dmasound_init)(struct saa7134_dev *dev);
-extern int (*dmasound_exit)(struct saa7134_dev *dev);
+extern int (*saa7134_dmasound_init)(struct saa7134_dev *dev);
+extern int (*saa7134_dmasound_exit)(struct saa7134_dev *dev);
/* ----------------------------------------------------------- */
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index b36ba9fa3a2..5686547ba76 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -2181,7 +2181,6 @@ static struct pci_device_id stradis_pci_tbl[] = {
{ 0 }
};
-MODULE_DEVICE_TABLE(pci, stradis_pci_tbl);
static struct pci_driver stradis_driver = {
.name = "stradis",
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index f7eb402d5f2..40590bae5ff 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -196,14 +196,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
i2c_master_send(c, buffer, 4);
default_tuner_init(c);
break;
- case TUNER_LG_TDVS_H06XF:
- /* Set the Auxiliary Byte. */
- buffer[2] &= ~0x20;
- buffer[2] |= 0x18;
- buffer[3] = 0x20;
- i2c_master_send(c, buffer, 4);
- default_tuner_init(c);
- break;
case TUNER_PHILIPS_TD1316:
buffer[0] = 0x0b;
buffer[1] = 0xdc;
@@ -598,6 +590,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (t->standby)
t->standby (client);
break;
+#ifdef CONFIG_VIDEO_V4L1
case VIDIOCSAUDIO:
if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
return 0;
@@ -607,17 +600,6 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
/* Should be implemented, since bttv calls it */
tuner_dbg("VIDIOCSAUDIO not implemented.\n");
break;
- case TDA9887_SET_CONFIG:
- if (t->type == TUNER_TDA9887) {
- int *i = arg;
-
- t->tda9887_config = *i;
- set_freq(client, t->tv_freq);
- }
- break;
- /* --- v4l ioctls --- */
- /* take care: bttv does userspace copying, we'll get a
- kernel pointer here... */
case VIDIOCSCHAN:
{
static const v4l2_std_id map[] = {
@@ -701,7 +683,18 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
return 0;
}
+#endif
+ case TDA9887_SET_CONFIG:
+ if (t->type == TUNER_TDA9887) {
+ int *i = arg;
+ t->tda9887_config = *i;
+ set_freq(client, t->tv_freq);
+ }
+ break;
+ /* --- v4l ioctls --- */
+ /* take care: bttv does userspace copying, we'll get a
+ kernel pointer here... */
case VIDIOC_S_STD:
{
v4l2_std_id *id = arg;
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index d071c5cbf01..abe37cf632c 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -339,7 +339,20 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
if (4 != (rc = i2c_master_send(c,buffer,4)))
tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
- if (t->type == TUNER_MICROTUNE_4042FI5) {
+ switch (t->type) {
+ case TUNER_LG_TDVS_H06XF:
+ /* Set the Auxiliary Byte. */
+ buffer[0] = buffer[2];
+ buffer[0] &= ~0x20;
+ buffer[0] |= 0x18;
+ buffer[1] = 0x20;
+ tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]);
+
+ if (2 != (rc = i2c_master_send(c,buffer,2)))
+ tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
+ break;
+ case TUNER_MICROTUNE_4042FI5:
+ {
// FIXME - this may also work for other tuners
unsigned long timeout = jiffies + msecs_to_jiffies(1);
u8 status_byte = 0;
@@ -364,10 +377,12 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
buffer[2] = config;
buffer[3] = cb;
tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
- buffer[0],buffer[1],buffer[2],buffer[3]);
+ buffer[0],buffer[1],buffer[2],buffer[3]);
if (4 != (rc = i2c_master_send(c,buffer,4)))
tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
+ break;
+ }
}
}
diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig
index 59fb899f31f..a0fd82b924f 100644
--- a/drivers/media/video/usbvideo/Kconfig
+++ b/drivers/media/video/usbvideo/Kconfig
@@ -3,7 +3,7 @@ config VIDEO_USBVIDEO
config USB_VICAM
tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)"
- depends on USB && VIDEO_V4L1 && EXPERIMENTAL
+ depends on USB && VIDEO_DEV && VIDEO_V4L1 && EXPERIMENTAL
select VIDEO_USBVIDEO
---help---
Say Y here if you have 3com homeconnect camera (vicam).
@@ -13,7 +13,7 @@ config USB_VICAM
config USB_IBMCAM
tristate "USB IBM (Xirlink) C-it Camera support"
- depends on USB && VIDEO_V4L1
+ depends on USB && VIDEO_DEV && VIDEO_V4L1
select VIDEO_USBVIDEO
---help---
Say Y here if you want to connect a IBM "C-It" camera, also known as
@@ -28,7 +28,7 @@ config USB_IBMCAM
config USB_KONICAWC
tristate "USB Konica Webcam support"
- depends on USB && VIDEO_V4L1
+ depends on USB && VIDEO_DEV && VIDEO_V4L1
select VIDEO_USBVIDEO
---help---
Say Y here if you want support for webcams based on a Konica
@@ -39,7 +39,7 @@ config USB_KONICAWC
config USB_QUICKCAM_MESSENGER
tristate "USB Logitech Quickcam Messenger"
- depends on USB && VIDEO_DEV
+ depends on USB && VIDEO_DEV && VIDEO_V4L1
select VIDEO_USBVIDEO
---help---
Say Y or M here to enable support for the USB Logitech Quickcam
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index f06dc19e504..2ecbeffb559 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -202,7 +202,7 @@ static char *v4l2_memory_names[] = {
/* ------------------------------------------------------------------ */
/* debug help functions */
-#ifdef HAVE_V4L1
+#ifdef CONFIG_V4L1_COMPAT
static const char *v4l1_ioctls[] = {
[_IOC_NR(VIDIOCGCAP)] = "VIDIOCGCAP",
[_IOC_NR(VIDIOCGCHAN)] = "VIDIOCGCHAN",
@@ -301,7 +301,7 @@ static const char *v4l2_ioctls[] = {
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
static const char *v4l2_int_ioctls[] = {
-#ifdef HAVE_VIDEO_DECODER
+#ifdef CONFIG_V4L1_COMPAT
[_IOC_NR(DECODER_GET_CAPABILITIES)] = "DECODER_GET_CAPABILITIES",
[_IOC_NR(DECODER_GET_STATUS)] = "DECODER_GET_STATUS",
[_IOC_NR(DECODER_SET_NORM)] = "DECODER_SET_NORM",
@@ -367,7 +367,7 @@ void v4l_printk_ioctl(unsigned int cmd)
(_IOC_NR(cmd) < V4L2_INT_IOCTLS) ?
v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
break;
-#ifdef HAVE_V4L1
+#ifdef CONFIG_V4L1_COMPAT
case 'v':
printk("v4l1 ioctl %s, dir=%s (0x%08x)\n",
(_IOC_NR(cmd) < V4L1_IOCTLS) ?
@@ -414,6 +414,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
printk ("%s: tuner type=%d\n", s, *p);
break;
}
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
case DECODER_SET_VBI_BYPASS:
case DECODER_ENABLE_OUTPUT:
case DECODER_GET_STATUS:
@@ -424,6 +425,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
case VIDIOCCAPTURE:
case VIDIOCSYNC:
case VIDIOCSWRITEMODE:
+#endif
case TUNER_SET_TYPE_ADDR:
case TUNER_SET_STANDBY:
case TDA9887_SET_CONFIG:
@@ -755,6 +757,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
p->afc);
break;
}
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
case VIDIOCGVBIFMT:
case VIDIOCSVBIFMT:
{
@@ -924,6 +927,14 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
p->clipcount);
break;
}
+ case VIDIOCGFREQ:
+ case VIDIOCSFREQ:
+ {
+ unsigned long *p=arg;
+ printk ("%s: value=%lu\n", s, *p);
+ break;
+ }
+#endif
case VIDIOC_INT_AUDIO_CLOCK_FREQ:
case VIDIOC_INT_I2S_CLOCK_FREQ:
case VIDIOC_INT_S_STANDBY:
@@ -933,13 +944,6 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
printk ("%s: value=%d\n", s, *p);
break;
}
- case VIDIOCGFREQ:
- case VIDIOCSFREQ:
- {
- unsigned long *p=arg;
- printk ("%s: value=%lu\n", s, *p);
- break;
- }
case VIDIOC_G_STD:
case VIDIOC_S_STD:
case VIDIOC_QUERYSTD:
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index b26ebaff226..0fc90cd393f 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -760,7 +760,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
ret=vfd->vidioc_overlay(file, fh, *i);
break;
}
-#ifdef HAVE_V4L1
+#ifdef CONFIG_V4L1_COMPAT
/* --- streaming capture ------------------------------------- */
case VIDIOCGMBUF:
{
@@ -1512,6 +1512,7 @@ int video_register_device(struct video_device *vfd, int type, int nr)
int i=0;
int base;
int end;
+ int ret;
char *name_base;
switch(type)
@@ -1537,6 +1538,8 @@ int video_register_device(struct video_device *vfd, int type, int nr)
name_base = "radio";
break;
default:
+ printk(KERN_ERR "%s called with unknown type: %d\n",
+ __FUNCTION__, type);
return -1;
}
@@ -1571,9 +1574,18 @@ int video_register_device(struct video_device *vfd, int type, int nr)
vfd->class_dev.class = &video_class;
vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor);
sprintf(vfd->class_dev.class_id, "%s%d", name_base, i - base);
- class_device_register(&vfd->class_dev);
- class_device_create_file(&vfd->class_dev,
- &class_device_attr_name);
+ ret = class_device_register(&vfd->class_dev);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: class_device_register failed\n",
+ __FUNCTION__);
+ goto fail_minor;
+ }
+ ret = class_device_create_file(&vfd->class_dev, &class_device_attr_name);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: class_device_create_file 'name' failed\n",
+ __FUNCTION__);
+ goto fail_classdev;
+ }
#if 1
/* needed until all drivers are fixed */
@@ -1583,6 +1595,15 @@ int video_register_device(struct video_device *vfd, int type, int nr)
"http://lwn.net/Articles/36850/\n", vfd->name);
#endif
return 0;
+
+fail_classdev:
+ class_device_unregister(&vfd->class_dev);
+fail_minor:
+ mutex_lock(&videodev_lock);
+ video_device[vfd->minor] = NULL;
+ vfd->minor = -1;
+ mutex_unlock(&videodev_lock);
+ return ret;
}
/**
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 41d23c8acbd..38bd0c1018c 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -986,7 +986,7 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
file->f_flags & O_NONBLOCK));
}
-#ifdef HAVE_V4L1
+#ifdef CONFIG_V4L1_COMPAT
static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf)
{
struct vivi_fh *fh=priv;
@@ -1328,7 +1328,7 @@ static struct video_device vivi = {
.vidioc_s_ctrl = vidioc_s_ctrl,
.vidioc_streamon = vidioc_streamon,
.vidioc_streamoff = vidioc_streamoff,
-#ifdef HAVE_V4L1
+#ifdef CONFIG_V4L1_COMPAT
.vidiocgmbuf = vidiocgmbuf,
#endif
.tvnorms = tvnorms,
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
index bbc22985288..ea31d847051 100644
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -48,10 +48,8 @@ config FUSION_SAS
List of supported controllers:
LSISAS1064
- LSISAS1066
LSISAS1068
LSISAS1064E
- LSISAS1066E
LSISAS1068E
config FUSION_MAX_SGE
diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile
index b114236f439..341691390e8 100644
--- a/drivers/message/fusion/Makefile
+++ b/drivers/message/fusion/Makefile
@@ -9,7 +9,6 @@
#EXTRA_CFLAGS += -DMPT_DEBUG_EXIT
#EXTRA_CFLAGS += -DMPT_DEBUG_FAIL
-
#
# driver/module specifics...
#
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 43308df6462..29d0635cce1 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -436,8 +436,6 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
*/
if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
freereq = 0;
- devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
- ioc->name, pEvReply));
} else {
devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
ioc->name, pEvReply));
@@ -678,19 +676,19 @@ int
mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
{
MPT_ADAPTER *ioc;
+ const struct pci_device_id *id;
- if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
+ if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
return -EINVAL;
- }
MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
/* call per pci device probe entry point */
list_for_each_entry(ioc, &ioc_list, list) {
- if(dd_cbfunc->probe) {
- dd_cbfunc->probe(ioc->pcidev,
- ioc->pcidev->driver->id_table);
- }
+ id = ioc->pcidev->driver ?
+ ioc->pcidev->driver->id_table : NULL;
+ if (dd_cbfunc->probe)
+ dd_cbfunc->probe(ioc->pcidev, id);
}
return 0;
@@ -1056,9 +1054,8 @@ mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
dinitprintk((MYIOC_s_INFO_FMT
"host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
- ioc->name,
- ioc->HostPageBuffer,
- ioc->HostPageBuffer_dma,
+ ioc->name, ioc->HostPageBuffer,
+ (u32)ioc->HostPageBuffer_dma,
host_page_buffer_sz));
ioc->alloc_total += host_page_buffer_sz;
ioc->HostPageBuffer_sz = host_page_buffer_sz;
@@ -1380,6 +1377,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
printk(KERN_WARNING MYNAM
": WARNING - %s did not initialize properly! (%d)\n",
ioc->name, r);
+
list_del(&ioc->list);
if (ioc->alt_ioc)
ioc->alt_ioc->alt_ioc = NULL;
@@ -1762,9 +1760,9 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
* chips (mpt_adapter_disable,
* mpt_diag_reset)
*/
- ioc->cached_fw = NULL;
ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n",
ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
+ ioc->alt_ioc->cached_fw = NULL;
}
} else {
printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
@@ -1885,7 +1883,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
/* FIXME? Examine results here? */
}
-out:
+ out:
if ((ret != 0) && irq_allocated) {
free_irq(ioc->pci_irq, ioc);
if (mpt_msi_enable)
@@ -2670,6 +2668,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
ioc->name, count));
+ ioc->aen_event_read_flag=0;
return r;
}
@@ -2737,6 +2736,8 @@ mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
+ ioc->alloc_total += size;
+ ioc->alt_ioc->alloc_total -= size;
} else {
if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
ioc->alloc_total += size;
@@ -3166,6 +3167,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
static int
mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
{
+ MPT_ADAPTER *iocp=NULL;
u32 diag0val;
u32 doorbell;
int hard_reset_done = 0;
@@ -3301,17 +3303,23 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
/* FIXME? Examine results here? */
}
- if (ioc->cached_fw) {
+ if (ioc->cached_fw)
+ iocp = ioc;
+ else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
+ iocp = ioc->alt_ioc;
+ if (iocp) {
/* If the DownloadBoot operation fails, the
* IOC will be left unusable. This is a fatal error
* case. _diag_reset will return < 0
*/
for (count = 0; count < 30; count ++) {
- diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+ diag0val = CHIPREG_READ32(&iocp->chip->Diagnostic);
if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
break;
}
+ dprintk((MYIOC_s_INFO_FMT "cached_fw: diag0val=%x count=%d\n",
+ iocp->name, diag0val, count));
/* wait 1 sec */
if (sleepFlag == CAN_SLEEP) {
msleep (1000);
@@ -3320,7 +3328,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
}
}
if ((count = mpt_downloadboot(ioc,
- (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) {
+ (MpiFwHeader_t *)iocp->cached_fw, sleepFlag)) < 0) {
printk(KERN_WARNING MYNAM
": firmware downloadboot failure (%d)!\n", count);
}
@@ -3907,18 +3915,18 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
if (sleepFlag == CAN_SLEEP) {
while (--cntdn) {
+ msleep (1);
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
break;
- msleep (1);
count++;
}
} else {
while (--cntdn) {
+ mdelay (1);
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
break;
- mdelay (1);
count++;
}
}
@@ -4883,6 +4891,7 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
if (!pIoc4)
return;
+ ioc->alloc_total += iocpage4sz;
} else {
ioc4_dma = ioc->spi_data.IocPg4_dma;
iocpage4sz = ioc->spi_data.IocPg4Sz;
@@ -4899,6 +4908,7 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
} else {
pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
ioc->spi_data.pIocPg4 = NULL;
+ ioc->alloc_total -= iocpage4sz;
}
}
@@ -5030,19 +5040,18 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
EventAck_t *pAck;
if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
- printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK "
- "request frame for Event=%x EventContext=%x EventData=%x!\n",
- ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext),
- le32_to_cpu(evnp->Data[0]));
+ dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
+ ioc->name,__FUNCTION__));
return -1;
}
- memset(pAck, 0, sizeof(*pAck));
- dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
+ devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
pAck->Function = MPI_FUNCTION_EVENT_ACK;
pAck->ChainOffset = 0;
+ pAck->Reserved[0] = pAck->Reserved[1] = 0;
pAck->MsgFlags = 0;
+ pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0;
pAck->Event = evnp->Event;
pAck->EventContext = evnp->EventContext;
@@ -5704,9 +5713,9 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
break;
case MPI_EVENT_EVENT_CHANGE:
if (evData0)
- ds = "Events(ON) Change";
+ ds = "Events ON";
else
- ds = "Events(OFF) Change";
+ ds = "Events OFF";
break;
case MPI_EVENT_INTEGRATED_RAID:
{
@@ -5777,8 +5786,27 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
break;
case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
snprintf(evStr, EVENT_DESCR_STR_SZ,
- "SAS Device Status Change: No Persistancy "
- "Added: id=%d", id);
+ "SAS Device Status Change: No Persistancy: id=%d", id);
+ break;
+ case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS Device Status Change: Internal Device Reset : id=%d", id);
+ break;
+ case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS Device Status Change: Internal Task Abort : id=%d", id);
+ break;
+ case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS Device Status Change: Internal Abort Task Set : id=%d", id);
+ break;
+ case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS Device Status Change: Internal Clear Task Set : id=%d", id);
+ break;
+ case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
+ "SAS Device Status Change: Internal Query Task : id=%d", id);
break;
default:
snprintf(evStr, EVENT_DESCR_STR_SZ,
@@ -6034,7 +6062,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
* @ioc: Pointer to MPT_ADAPTER structure
* @log_info: U32 LogInfo reply word from the IOC
*
- * Refer to lsi/fc_log.h.
+ * Refer to lsi/mpi_log_fc.h.
*/
static void
mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
@@ -6131,8 +6159,10 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
"Invalid SAS Address", /* 01h */
NULL, /* 02h */
"Invalid Page", /* 03h */
- NULL, /* 04h */
- "Task Terminated" /* 05h */
+ "Diag Message Error", /* 04h */
+ "Task Terminated", /* 05h */
+ "Enclosure Management", /* 06h */
+ "Target Mode" /* 07h */
};
static char *pl_code_str[] = {
NULL, /* 00h */
@@ -6158,7 +6188,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
"IO Executed", /* 14h */
"Persistant Reservation Out Not Affiliation Owner", /* 15h */
"Open Transmit DMA Abort", /* 16h */
- NULL, /* 17h */
+ "IO Device Missing Delay Retry", /* 17h */
NULL, /* 18h */
NULL, /* 19h */
NULL, /* 1Ah */
@@ -6238,7 +6268,7 @@ static void
mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
{
u32 status = ioc_status & MPI_IOCSTATUS_MASK;
- char *desc = "";
+ char *desc = NULL;
switch (status) {
case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
@@ -6348,7 +6378,7 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
desc = "Others";
break;
}
- if (desc != "")
+ if (desc != NULL)
printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
}
@@ -6386,7 +6416,6 @@ EXPORT_SYMBOL(mpt_alloc_fw_memory);
EXPORT_SYMBOL(mpt_free_fw_memory);
EXPORT_SYMBOL(mptbase_sas_persist_operation);
-
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* fusion_init - Fusion MPT base driver initialization routine.
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index a5ce10b67d0..d4cb144ab40 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -75,8 +75,8 @@
#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "3.04.00"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.00"
+#define MPT_LINUX_VERSION_COMMON "3.04.01"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.01"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@@ -307,8 +307,8 @@ typedef struct _SYSIF_REGS
u32 HostIndex; /* 50 Host Index register */
u32 Reserved4[15]; /* 54-8F */
u32 Fubar; /* 90 For Fubar usage */
- u32 Reserved5[1050];/* 94-10F8 */
- u32 Reset_1078; /* 10FC Reset 1078 */
+ u32 Reserved5[1050];/* 94-10F8 */
+ u32 Reset_1078; /* 10FC Reset 1078 */
} SYSIF_REGS;
/*
@@ -363,6 +363,7 @@ typedef struct _VirtDevice {
#define MPT_TARGET_FLAGS_VALID_56 0x10
#define MPT_TARGET_FLAGS_SAF_TE_ISSUED 0x20
#define MPT_TARGET_FLAGS_RAID_COMPONENT 0x40
+#define MPT_TARGET_FLAGS_LED_ON 0x80
/*
* /proc/mpt interface
@@ -634,7 +635,6 @@ typedef struct _MPT_ADAPTER
u16 handle;
int sas_index; /* index refrencing */
MPT_SAS_MGMT sas_mgmt;
- int num_ports;
struct work_struct sas_persist_task;
struct work_struct fc_setup_reset_work;
@@ -644,7 +644,6 @@ typedef struct _MPT_ADAPTER
struct work_struct fc_rescan_work;
char fc_rescan_work_q_name[KOBJ_NAME_LEN];
struct workqueue_struct *fc_rescan_work_q;
- u8 port_serial_number;
} MPT_ADAPTER;
/*
@@ -982,7 +981,7 @@ typedef struct _MPT_SCSI_HOST {
wait_queue_head_t scandv_waitq;
int scandv_wait_done;
long last_queue_full;
- u8 mpt_pq_filter;
+ u16 tm_iocstatus;
} MPT_SCSI_HOST;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index b4967bb8a7d..30975ccd994 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -2332,7 +2332,7 @@ done_free_mem:
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* Prototype Routine for the HP HOST INFO command.
+/* Prototype Routine for the HOST INFO command.
*
* Outputs: None.
* Return: 0 if successful
@@ -2568,7 +2568,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* Prototype Routine for the HP TARGET INFO command.
+/* Prototype Routine for the TARGET INFO command.
*
* Outputs: None.
* Return: 0 if successful
diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h
index a2f8a97992e..043941882c6 100644
--- a/drivers/message/fusion/mptctl.h
+++ b/drivers/message/fusion/mptctl.h
@@ -354,9 +354,6 @@ struct mpt_ioctl_command32 {
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * HP Specific IOCTL Defines and Structures
- */
#define CPQFCTS_IOC_MAGIC 'Z'
#define HP_IOC_MAGIC 'Z'
@@ -364,8 +361,6 @@ struct mpt_ioctl_command32 {
#define HP_GETHOSTINFO1 _IOR(HP_IOC_MAGIC, 20, hp_host_info_rev0_t)
#define HP_GETTARGETINFO _IOR(HP_IOC_MAGIC, 21, hp_target_info_t)
-/* All HP IOCTLs must include this header
- */
typedef struct _hp_header {
unsigned int iocnum;
unsigned int host;
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index a8f2fa98545..90da7d63b08 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -77,10 +77,6 @@ MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
/* Command line args */
-static int mpt_pq_filter = 0;
-module_param(mpt_pq_filter, int, 0);
-MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
-
#define MPTFC_DEV_LOSS_TMO (60)
static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; /* reasonable default */
module_param(mptfc_dev_loss_tmo, int, 0);
@@ -513,8 +509,7 @@ mptfc_slave_alloc(struct scsi_device *sdev)
if (vtarget->num_luns == 0) {
vtarget->ioc_id = hd->ioc->id;
- vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
- MPT_TARGET_FLAGS_VALID_INQUIRY;
+ vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
hd->Targets[sdev->id] = vtarget;
}
@@ -1129,13 +1124,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hd->timer.data = (unsigned long) hd;
hd->timer.function = mptscsih_timer_expired;
- hd->mpt_pq_filter = mpt_pq_filter;
-
- ddvprintk((MYIOC_s_INFO_FMT
- "mpt_pq_filter %x\n",
- ioc->name,
- mpt_pq_filter));
-
init_waitqueue_head(&hd->scandv_waitq);
hd->scandv_wait_done = 0;
hd->last_queue_full = 0;
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index f7bd8b11ed3..f66f2203143 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -67,20 +67,19 @@
#define my_VERSION MPT_LINUX_VERSION_COMMON
#define MYNAM "mptsas"
+/*
+ * Reserved channel for integrated raid
+ */
+#define MPTSAS_RAID_CHANNEL 1
+
MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
-static int mpt_pq_filter;
-module_param(mpt_pq_filter, int, 0);
-MODULE_PARM_DESC(mpt_pq_filter,
- "Enable peripheral qualifier filter: enable=1 "
- "(default=0)");
-
static int mpt_pt_clear;
module_param(mpt_pt_clear, int, 0);
MODULE_PARM_DESC(mpt_pt_clear,
- "Clear persistency table: enable=1 "
+ " Clear persistency table: enable=1 "
"(default=MPTSCSIH_PT_CLEAR=0)");
static int mptsasDoneCtx = -1;
@@ -144,7 +143,6 @@ struct mptsas_devinfo {
* Specific details on ports, wide/narrow
*/
struct mptsas_portinfo_details{
- u8 port_id; /* port number provided to transport */
u16 num_phys; /* number of phys belong to this port */
u64 phy_bitmask; /* TODO, extend support for 255 phys */
struct sas_rphy *rphy; /* transport layer rphy object */
@@ -350,10 +348,10 @@ mptsas_port_delete(struct mptsas_portinfo_details * port_details)
port_info = port_details->port_info;
phy_info = port_info->phy_info;
- dsaswideprintk((KERN_DEBUG "%s: [%p]: port=%02d num_phys=%02d "
+ dsaswideprintk((KERN_DEBUG "%s: [%p]: num_phys=%02d "
"bitmask=0x%016llX\n",
- __FUNCTION__, port_details, port_details->port_id,
- port_details->num_phys, port_details->phy_bitmask));
+ __FUNCTION__, port_details, port_details->num_phys,
+ port_details->phy_bitmask));
for (i = 0; i < port_info->num_phys; i++, phy_info++) {
if(phy_info->port_details != port_details)
@@ -462,9 +460,8 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
* phy be removed by firmware events.
*/
dsaswideprintk((KERN_DEBUG
- "%s: [%p]: port=%d deleting phy = %d\n",
- __FUNCTION__, port_details,
- port_details->port_id, i));
+ "%s: [%p]: deleting phy = %d\n",
+ __FUNCTION__, port_details, i));
port_details->num_phys--;
port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
@@ -493,7 +490,6 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
goto out;
port_details->num_phys = 1;
port_details->port_info = port_info;
- port_details->port_id = ioc->port_serial_number++;
if (phy_info->phy_id < 64 )
port_details->phy_bitmask |=
(1 << phy_info->phy_id);
@@ -525,12 +521,8 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
mptsas_get_port(phy_info_cmp);
port_details->starget =
mptsas_get_starget(phy_info_cmp);
- port_details->port_id =
- phy_info_cmp->port_details->port_id;
port_details->num_phys =
phy_info_cmp->port_details->num_phys;
-// port_info->port_serial_number--;
- ioc->port_serial_number--;
if (!phy_info_cmp->port_details->num_phys)
kfree(phy_info_cmp->port_details);
} else
@@ -554,11 +546,11 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
if (!port_details)
continue;
dsaswideprintk((KERN_DEBUG
- "%s: [%p]: phy_id=%02d port_id=%02d num_phys=%02d "
+ "%s: [%p]: phy_id=%02d num_phys=%02d "
"bitmask=0x%016llX\n",
__FUNCTION__,
- port_details, i, port_details->port_id,
- port_details->num_phys, port_details->phy_bitmask));
+ port_details, i, port_details->num_phys,
+ port_details->phy_bitmask));
dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n",
port_details->port, port_details->rphy));
}
@@ -651,16 +643,13 @@ mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
static int
mptsas_slave_configure(struct scsi_device *sdev)
{
- struct Scsi_Host *host = sdev->host;
- MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
- /*
- * RAID volumes placed beyond the last expected port.
- * Ignore sending sas mode pages in that case..
- */
- if (sdev->channel < hd->ioc->num_ports)
- sas_read_port_mode_page(sdev);
+ if (sdev->channel == MPTSAS_RAID_CHANNEL)
+ goto out;
+
+ sas_read_port_mode_page(sdev);
+ out:
return mptscsih_slave_configure(sdev);
}
@@ -689,10 +678,7 @@ mptsas_target_alloc(struct scsi_target *starget)
hd->Targets[target_id] = vtarget;
- /*
- * RAID volumes placed beyond the last expected port.
- */
- if (starget->channel == hd->ioc->num_ports)
+ if (starget->channel == MPTSAS_RAID_CHANNEL)
goto out;
rphy = dev_to_rphy(starget->dev.parent);
@@ -743,7 +729,7 @@ mptsas_target_destroy(struct scsi_target *starget)
if (!starget->hostdata)
return;
- if (starget->channel == hd->ioc->num_ports)
+ if (starget->channel == MPTSAS_RAID_CHANNEL)
goto out;
rphy = dev_to_rphy(starget->dev.parent);
@@ -783,10 +769,7 @@ mptsas_slave_alloc(struct scsi_device *sdev)
starget = scsi_target(sdev);
vdev->vtarget = starget->hostdata;
- /*
- * RAID volumes placed beyond the last expected port.
- */
- if (sdev->channel == hd->ioc->num_ports)
+ if (sdev->channel == MPTSAS_RAID_CHANNEL)
goto out;
rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
@@ -1608,11 +1591,7 @@ static int mptsas_probe_one_phy(struct device *dev,
if (phy_info->sas_port_add_phy) {
if (!port) {
- port = sas_port_alloc(dev,
- phy_info->port_details->port_id);
- dsaswideprintk((KERN_DEBUG
- "sas_port_alloc: port=%p dev=%p port_id=%d\n",
- port, dev, phy_info->port_details->port_id));
+ port = sas_port_alloc_num(dev);
if (!port) {
error = -ENOMEM;
goto out;
@@ -1625,6 +1604,9 @@ static int mptsas_probe_one_phy(struct device *dev,
goto out;
}
mptsas_set_port(phy_info, port);
+ dsaswideprintk((KERN_DEBUG
+ "sas_port_alloc: port=%p dev=%p port_id=%d\n",
+ port, dev, port->port_identifier));
}
dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
phy_info->phy_id));
@@ -1736,7 +1718,6 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
hba = NULL;
}
mutex_unlock(&ioc->sas_topology_mutex);
- ioc->num_ports = port_info->num_phys;
for (i = 0; i < port_info->num_phys; i++) {
mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
@@ -1939,7 +1920,8 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
expander_sas_address)
continue;
#ifdef MPT_DEBUG_SAS_WIDE
- dev_printk(KERN_DEBUG, &port->dev, "delete\n");
+ dev_printk(KERN_DEBUG, &port->dev,
+ "delete port (%d)\n", port->port_identifier);
#endif
sas_port_delete(port);
mptsas_port_delete(phy_info->port_details);
@@ -1984,7 +1966,7 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
goto out;
for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
- scsi_add_device(ioc->sh, ioc->num_ports,
+ scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
}
out:
@@ -2185,7 +2167,8 @@ mptsas_hotplug_work(void *arg)
ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
#ifdef MPT_DEBUG_SAS_WIDE
- dev_printk(KERN_DEBUG, &port->dev, "delete\n");
+ dev_printk(KERN_DEBUG, &port->dev,
+ "delete port (%d)\n", port->port_identifier);
#endif
sas_port_delete(port);
mptsas_port_delete(phy_info->port_details);
@@ -2289,35 +2272,26 @@ mptsas_hotplug_work(void *arg)
mptsas_set_rphy(phy_info, rphy);
break;
case MPTSAS_ADD_RAID:
- sdev = scsi_device_lookup(
- ioc->sh,
- ioc->num_ports,
- ev->id,
- 0);
+ sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
+ ev->id, 0);
if (sdev) {
scsi_device_put(sdev);
break;
}
printk(MYIOC_s_INFO_FMT
"attaching raid volume, channel %d, id %d\n",
- ioc->name, ioc->num_ports, ev->id);
- scsi_add_device(ioc->sh,
- ioc->num_ports,
- ev->id,
- 0);
+ ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
+ scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
mpt_findImVolumes(ioc);
break;
case MPTSAS_DEL_RAID:
- sdev = scsi_device_lookup(
- ioc->sh,
- ioc->num_ports,
- ev->id,
- 0);
+ sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
+ ev->id, 0);
if (!sdev)
break;
printk(MYIOC_s_INFO_FMT
"removing raid volume, channel %d, id %d\n",
- ioc->name, ioc->num_ports, ev->id);
+ ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
vdevice = sdev->hostdata;
vdevice->vtarget->deleted = 1;
mptsas_target_reset(ioc, vdevice->vtarget);
@@ -2723,7 +2697,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hd->timer.data = (unsigned long) hd;
hd->timer.function = mptscsih_timer_expired;
- hd->mpt_pq_filter = mpt_pq_filter;
ioc->sas_data.ptClear = mpt_pt_clear;
if (ioc->sas_data.ptClear==1) {
@@ -2731,12 +2704,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
}
- ddvprintk((MYIOC_s_INFO_FMT
- "mpt_pq_filter %x mpt_pq_filter %x\n",
- ioc->name,
- mpt_pq_filter,
- mpt_pq_filter));
-
init_waitqueue_head(&hd->scandv_waitq);
hd->scandv_wait_done = 0;
hd->last_queue_full = 0;
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 8242b16e316..30524dc54b1 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -66,6 +66,7 @@
#include "mptbase.h"
#include "mptscsih.h"
+#include "lsi/mpi_log_sas.h"
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#define my_NAME "Fusion MPT SCSI Host driver"
@@ -127,7 +128,7 @@ static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
-static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
+static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
@@ -497,6 +498,34 @@ nextSGEset:
return SUCCESS;
} /* mptscsih_AddSGE() */
+static void
+mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
+ U32 SlotStatus)
+{
+ MPT_FRAME_HDR *mf;
+ SEPRequest_t *SEPMsg;
+
+ if (ioc->bus_type == FC)
+ return;
+
+ if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
+ dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
+ ioc->name,__FUNCTION__));
+ return;
+ }
+
+ SEPMsg = (SEPRequest_t *)mf;
+ SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
+ SEPMsg->Bus = vtarget->bus_id;
+ SEPMsg->TargetID = vtarget->target_id;
+ SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
+ SEPMsg->SlotStatus = SlotStatus;
+ devtverboseprintk((MYIOC_s_WARN_FMT
+ "Sending SEP cmd=%x id=%d bus=%d\n",
+ ioc->name, SlotStatus, SEPMsg->TargetID, SEPMsg->Bus));
+ mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
+}
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mptscsih_io_done - Main SCSI IO callback routine registered to
@@ -520,6 +549,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
SCSIIORequest_t *pScsiReq;
SCSIIOReply_t *pScsiReply;
u16 req_idx, req_idx_MR;
+ VirtDevice *vdev;
+ VirtTarget *vtarget;
hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
@@ -538,6 +569,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
}
sc = hd->ScsiLookup[req_idx];
+ hd->ScsiLookup[req_idx] = NULL;
if (sc == NULL) {
MPIHeader_t *hdr = (MPIHeader_t *)mf;
@@ -553,6 +585,12 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
return 1;
}
+ if ((unsigned char *)mf != sc->host_scribble) {
+ mptscsih_freeChainBuffers(ioc, req_idx);
+ return 1;
+ }
+
+ sc->host_scribble = NULL;
sc->result = DID_OK << 16; /* Set default reply as OK */
pScsiReq = (SCSIIORequest_t *) mf;
pScsiReply = (SCSIIOReply_t *) mr;
@@ -640,10 +678,36 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
hd->sel_timeout[pScsiReq->TargetID]++;
+
+ vdev = sc->device->hostdata;
+ if (!vdev)
+ break;
+ vtarget = vdev->vtarget;
+ if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
+ mptscsih_issue_sep_command(ioc, vtarget,
+ MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
+ vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
+ }
break;
- case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
+ if ( ioc->bus_type == SAS ) {
+ u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
+ if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
+ u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
+ log_info &=SAS_LOGINFO_MASK;
+ if (log_info == SAS_LOGINFO_NEXUS_LOSS) {
+ sc->result = (DID_BUS_BUSY << 16);
+ break;
+ }
+ }
+ }
+
+ /*
+ * Allow non-SAS & non-NEXUS_LOSS to drop into below code
+ */
+
+ case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
/* Linux handles an unsolicited DID_RESET better
* than an unsolicited DID_ABORT.
@@ -658,7 +722,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
sc->result=DID_SOFT_ERROR << 16;
else /* Sufficient data transfer occurred */
sc->result = (DID_OK << 16) | scsi_status;
- dreplyprintk((KERN_NOTICE
+ dreplyprintk((KERN_NOTICE
"RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
break;
@@ -784,8 +848,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
sc->request_bufflen, sc->sc_data_direction);
}
- hd->ScsiLookup[req_idx] = NULL;
-
sc->scsi_done(sc); /* Issue the command callback */
/* Free Chain buffers */
@@ -827,9 +889,17 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
mf, SCpnt));
+ /* Free Chain buffers */
+ mptscsih_freeChainBuffers(ioc, ii);
+
+ /* Free Message frames */
+ mpt_free_msg_frame(ioc, mf);
+
+ if ((unsigned char *)mf != SCpnt->host_scribble)
+ continue;
+
/* Set status, free OS resources (SG DMA buffers)
* Do OS callback
- * Free driver resources (chain, msg buffers)
*/
if (SCpnt->use_sg) {
pci_unmap_sg(ioc->pcidev,
@@ -845,12 +915,6 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
SCpnt->result = DID_RESET << 16;
SCpnt->host_scribble = NULL;
- /* Free Chain buffers */
- mptscsih_freeChainBuffers(ioc, ii);
-
- /* Free Message frames */
- mpt_free_msg_frame(ioc, mf);
-
SCpnt->scsi_done(SCpnt); /* Issue the command callback */
}
}
@@ -887,10 +951,10 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
if ((sc = hd->ScsiLookup[ii]) != NULL) {
mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
-
+ if (mf == NULL)
+ continue;
dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
-
if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
continue;
@@ -899,6 +963,8 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
hd->ScsiLookup[ii] = NULL;
mptscsih_freeChainBuffers(hd->ioc, ii);
mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
+ if ((unsigned char *)mf != sc->host_scribble)
+ continue;
if (sc->use_sg) {
pci_unmap_sg(hd->ioc->pcidev,
(struct scatterlist *) sc->request_buffer,
@@ -1341,8 +1407,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
goto fail;
}
+ SCpnt->host_scribble = (unsigned char *)mf;
hd->ScsiLookup[my_idx] = SCpnt;
- SCpnt->host_scribble = NULL;
mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
@@ -1529,6 +1595,12 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
}
+ /*
+ * Check IOCStatus from TM reply message
+ */
+ if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS)
+ rc = FAILED;
+
dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
return rc;
@@ -1654,6 +1726,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
int scpnt_idx;
int retval;
VirtDevice *vdev;
+ ulong sn = SCpnt->serial_number;
/* If we can't locate our host adapter structure, return FAILED status.
*/
@@ -1707,6 +1780,11 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
+ if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
+ SCpnt->serial_number == sn) {
+ retval = FAILED;
+ }
+
printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
hd->ioc->name,
((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
@@ -2023,6 +2101,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+ hd->tm_iocstatus = iocstatus;
dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
/* Error? (anything non-zero?) */
@@ -2401,6 +2480,13 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
ioc->eventContext++;
+ if (hd->ioc->pcidev->vendor ==
+ PCI_VENDOR_ID_IBM) {
+ mptscsih_issue_sep_command(hd->ioc,
+ vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
+ vdev->vtarget->tflags |=
+ MPT_TARGET_FLAGS_LED_ON;
+ }
}
}
} else {
@@ -2409,7 +2495,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
}
}
-static u32
+static int
SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
{
MPT_SCSI_HOST *hd;
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 0a1ff762205..e4cc3dd5fc9 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -83,10 +83,6 @@ static int mpt_saf_te = MPTSCSIH_SAF_TE;
module_param(mpt_saf_te, int, 0);
MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)");
-static int mpt_pq_filter = 0;
-module_param(mpt_pq_filter, int, 0);
-MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
-
static void mptspi_write_offset(struct scsi_target *, int);
static void mptspi_write_width(struct scsi_target *, int);
static int mptspi_write_spi_device_pg1(struct scsi_target *,
@@ -1047,14 +1043,12 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hd->timer.function = mptscsih_timer_expired;
ioc->spi_data.Saf_Te = mpt_saf_te;
- hd->mpt_pq_filter = mpt_pq_filter;
hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
ddvprintk((MYIOC_s_INFO_FMT
- "saf_te %x mpt_pq_filter %x\n",
+ "saf_te %x\n",
ioc->name,
- mpt_saf_te,
- mpt_pq_filter));
+ mpt_saf_te));
ioc->spi_data.noQas = 0;
init_waitqueue_head(&hd->scandv_waitq);
diff --git a/drivers/net/appletalk/Kconfig b/drivers/net/appletalk/Kconfig
index b14e89004c3..0a0e0cd81a2 100644
--- a/drivers/net/appletalk/Kconfig
+++ b/drivers/net/appletalk/Kconfig
@@ -29,7 +29,7 @@ config ATALK
even politically correct people are allowed to say Y here.
config DEV_APPLETALK
- bool "Appletalk interfaces support"
+ tristate "Appletalk interfaces support"
depends on ATALK
help
AppleTalk is the protocol that Apple computers can use to communicate
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 36d511729f7..2146cf74425 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -132,6 +132,7 @@ static int __init dummy_init_module(void)
for (i = 0; i < numdummies && !err; i++)
err = dummy_init_one(i);
if (err) {
+ i--;
while (--i >= 0)
dummy_free_one(i);
}
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index f411bbb44f8..d304297c496 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -110,6 +110,9 @@ struct e1000_adapter;
#define E1000_MIN_RXD 80
#define E1000_MAX_82544_RXD 4096
+/* this is the size past which hardware will drop packets when setting LPE=0 */
+#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
+
/* Supported Rx Buffer Sizes */
#define E1000_RXBUFFER_128 128 /* Used for packet split */
#define E1000_RXBUFFER_256 256 /* Used for packet split */
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 6d3d4193450..627f224d78b 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -36,7 +36,7 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-#define DRV_VERSION "7.1.9-k2"DRIVERNAPI
+#define DRV_VERSION "7.1.9-k4"DRIVERNAPI
char e1000_driver_version[] = DRV_VERSION;
static char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
@@ -1068,7 +1068,7 @@ e1000_sw_init(struct e1000_adapter *adapter)
pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
- adapter->rx_buffer_len = MAXIMUM_ETHERNET_FRAME_SIZE;
+ adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
adapter->rx_ps_bsize0 = E1000_RXBUFFER_128;
hw->max_frame_size = netdev->mtu +
ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
@@ -3127,7 +3127,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
break;
}
- /* NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
+ /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
* means we reserve 2 more, this pushes us to allocate from the next
* larger slab size
* i.e. RXBUFFER_2048 --> size-4096 slab */
@@ -3148,7 +3148,6 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
adapter->rx_buffer_len = E1000_RXBUFFER_16384;
/* adjust allocation if LPE protects us, and we aren't using SBP */
-#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
if (!adapter->hw.tbi_compatibility_on &&
((max_frame == MAXIMUM_ETHERNET_FRAME_SIZE) ||
(max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
@@ -3387,8 +3386,8 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
E1000_WRITE_REG(hw, IMC, ~0);
E1000_WRITE_FLUSH(hw);
}
- if (likely(netif_rx_schedule_prep(&adapter->polling_netdev[0])))
- __netif_rx_schedule(&adapter->polling_netdev[0]);
+ if (likely(netif_rx_schedule_prep(netdev)))
+ __netif_rx_schedule(netdev);
else
e1000_irq_enable(adapter);
#else
@@ -3431,34 +3430,26 @@ e1000_clean(struct net_device *poll_dev, int *budget)
{
struct e1000_adapter *adapter;
int work_to_do = min(*budget, poll_dev->quota);
- int tx_cleaned = 0, i = 0, work_done = 0;
+ int tx_cleaned = 0, work_done = 0;
/* Must NOT use netdev_priv macro here. */
adapter = poll_dev->priv;
/* Keep link state information with original netdev */
- if (!netif_carrier_ok(adapter->netdev))
+ if (!netif_carrier_ok(poll_dev))
goto quit_polling;
- while (poll_dev != &adapter->polling_netdev[i]) {
- i++;
- BUG_ON(i == adapter->num_rx_queues);
+ /* e1000_clean is called per-cpu. This lock protects
+ * tx_ring[0] from being cleaned by multiple cpus
+ * simultaneously. A failure obtaining the lock means
+ * tx_ring[0] is currently being cleaned anyway. */
+ if (spin_trylock(&adapter->tx_queue_lock)) {
+ tx_cleaned = e1000_clean_tx_irq(adapter,
+ &adapter->tx_ring[0]);
+ spin_unlock(&adapter->tx_queue_lock);
}
- if (likely(adapter->num_tx_queues == 1)) {
- /* e1000_clean is called per-cpu. This lock protects
- * tx_ring[0] from being cleaned by multiple cpus
- * simultaneously. A failure obtaining the lock means
- * tx_ring[0] is currently being cleaned anyway. */
- if (spin_trylock(&adapter->tx_queue_lock)) {
- tx_cleaned = e1000_clean_tx_irq(adapter,
- &adapter->tx_ring[0]);
- spin_unlock(&adapter->tx_queue_lock);
- }
- } else
- tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[i]);
-
- adapter->clean_rx(adapter, &adapter->rx_ring[i],
+ adapter->clean_rx(adapter, &adapter->rx_ring[0],
&work_done, work_to_do);
*budget -= work_done;
@@ -3466,7 +3457,7 @@ e1000_clean(struct net_device *poll_dev, int *budget)
/* If no Tx and not enough Rx work done, exit the polling mode */
if ((!tx_cleaned && (work_done == 0)) ||
- !netif_running(adapter->netdev)) {
+ !netif_running(poll_dev)) {
quit_polling:
netif_rx_complete(poll_dev);
e1000_irq_enable(adapter);
@@ -3681,6 +3672,9 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
length = le16_to_cpu(rx_desc->length);
+ /* adjust length to remove Ethernet CRC */
+ length -= 4;
+
if (unlikely(!(status & E1000_RXD_STAT_EOP))) {
/* All receives must fit into a single buffer */
E1000_DBG("%s: Receive packet consumed multiple"
@@ -3714,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;
@@ -3885,8 +3879,9 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
pci_dma_sync_single_for_device(pdev,
ps_page_dma->ps_page_dma[0],
PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ /* remove the CRC */
+ l1 -= 4;
skb_put(skb, l1);
- length += l1;
goto copydone;
} /* if */
}
@@ -3905,6 +3900,10 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
skb->truesize += length;
}
+ /* strip the ethernet crc, problem is we're using pages now so
+ * this whole operation can get a little cpu intensive */
+ pskb_trim(skb, skb->len - 4);
+
copydone:
e1000_rx_checksum(adapter, staterr,
le16_to_cpu(rx_desc->wb.lower.hi_dword.csum_ip.csum), skb);
@@ -3980,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;
@@ -3998,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);
@@ -4122,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++;
@@ -4752,6 +4752,7 @@ static void
e1000_netpoll(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+
disable_irq(adapter->pdev->irq);
e1000_intr(adapter->pdev->irq, netdev, NULL);
e1000_clean_tx_irq(adapter, adapter->tx_ring);
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 3a42afab503..43e3f33ed5e 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -271,6 +271,7 @@ static int __init ifb_init_module(void)
for (i = 0; i < numifbs && !err; i++)
err = ifb_init_one(i);
if (err) {
+ i--;
while (--i >= 0)
ifb_free_one(i);
}
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 07ca9480a6f..06440a86bae 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/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;
}
@@ -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/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 7d5c2233c25..f5aad77288f 100644
--- a/drivers/net/phy/phy.c
+++ b/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/drivers/net/s2io.c b/drivers/net/s2io.c
index e1fe3a0a7b0..132ed32bce1 100644
--- a/drivers/net/s2io.c
+++ b/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 <raghavendra.koushik@neterion.com>");
+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 @@ no_rx:
}
#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 <raghavendra.koushik@neterion.com>");
-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/drivers/net/s2io.h b/drivers/net/s2io.h
index 217097bc22f..5ed49c3be1e 100644
--- a/drivers/net/s2io.h
+++ b/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/drivers/net/skge.c b/drivers/net/skge.c
index 82200bfaa8e..7de9a07b2ac 100644
--- a/drivers/net/skge.c
+++ b/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/drivers/net/sky2.c b/drivers/net/sky2.c
index d98f28c34e5..de91609ca11 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -50,7 +50,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "1.4"
+#define DRV_VERSION "1.5"
#define PFX DRV_NAME " "
/*
@@ -2204,9 +2204,6 @@ static int sky2_poll(struct net_device *dev0, int *budget)
int work_done = 0;
u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
- if (!~status)
- goto out;
-
if (status & Y2_IS_HW_ERR)
sky2_hw_intr(hw);
@@ -2243,7 +2240,7 @@ static int sky2_poll(struct net_device *dev0, int *budget)
if (sky2_more_work(hw))
return 1;
-out:
+
netif_rx_complete(dev0);
sky2_read32(hw, B0_Y2_SP_LISR);
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index fb1d5a8a45c..647f62e9707 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -84,7 +84,7 @@ MODULE_DEVICE_TABLE(pci, spider_net_pci_tbl);
*
* returns the content of the specified SMMIO register.
*/
-static u32
+static inline u32
spider_net_read_reg(struct spider_net_card *card, u32 reg)
{
u32 value;
@@ -101,7 +101,7 @@ spider_net_read_reg(struct spider_net_card *card, u32 reg)
* @reg: register to write to
* @value: value to write into the specified SMMIO register
*/
-static void
+static inline void
spider_net_write_reg(struct spider_net_card *card, u32 reg, u32 value)
{
value = cpu_to_le32(value);
@@ -259,39 +259,10 @@ spider_net_get_mac_address(struct net_device *netdev)
*
* returns the status as in the dmac_cmd_status field of the descriptor
*/
-static enum spider_net_descr_status
+static inline int
spider_net_get_descr_status(struct spider_net_descr *descr)
{
- u32 cmd_status;
-
- cmd_status = descr->dmac_cmd_status;
- cmd_status >>= SPIDER_NET_DESCR_IND_PROC_SHIFT;
- /* no need to mask out any bits, as cmd_status is 32 bits wide only
- * (and unsigned) */
- return cmd_status;
-}
-
-/**
- * spider_net_set_descr_status -- sets the status of a descriptor
- * @descr: descriptor to change
- * @status: status to set in the descriptor
- *
- * changes the status to the specified value. Doesn't change other bits
- * in the status
- */
-static void
-spider_net_set_descr_status(struct spider_net_descr *descr,
- enum spider_net_descr_status status)
-{
- u32 cmd_status;
- /* read the status */
- cmd_status = descr->dmac_cmd_status;
- /* clean the upper 4 bits */
- cmd_status &= SPIDER_NET_DESCR_IND_PROC_MASKO;
- /* add the status to it */
- cmd_status |= ((u32)status)<<SPIDER_NET_DESCR_IND_PROC_SHIFT;
- /* and write it back */
- descr->dmac_cmd_status = cmd_status;
+ return descr->dmac_cmd_status & SPIDER_NET_DESCR_IND_PROC_MASK;
}
/**
@@ -328,24 +299,23 @@ spider_net_free_chain(struct spider_net_card *card,
static int
spider_net_init_chain(struct spider_net_card *card,
struct spider_net_descr_chain *chain,
- struct spider_net_descr *start_descr, int no)
+ struct spider_net_descr *start_descr,
+ int direction, int no)
{
int i;
struct spider_net_descr *descr;
dma_addr_t buf;
- atomic_set(&card->rx_chain_refill,0);
-
descr = start_descr;
memset(descr, 0, sizeof(*descr) * no);
/* set up the hardware pointers in each descriptor */
for (i=0; i<no; i++, descr++) {
- spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
+ descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
buf = pci_map_single(card->pdev, descr,
SPIDER_NET_DESCR_SIZE,
- PCI_DMA_BIDIRECTIONAL);
+ direction);
if (buf == DMA_ERROR_CODE)
goto iommu_error;
@@ -360,10 +330,11 @@ spider_net_init_chain(struct spider_net_card *card,
start_descr->prev = descr-1;
descr = start_descr;
- for (i=0; i < no; i++, descr++) {
- descr->next_descr_addr = descr->next->bus_addr;
- }
+ if (direction == PCI_DMA_FROMDEVICE)
+ for (i=0; i < no; i++, descr++)
+ descr->next_descr_addr = descr->next->bus_addr;
+ spin_lock_init(&chain->lock);
chain->head = start_descr;
chain->tail = start_descr;
@@ -375,7 +346,7 @@ iommu_error:
if (descr->bus_addr)
pci_unmap_single(card->pdev, descr->bus_addr,
SPIDER_NET_DESCR_SIZE,
- PCI_DMA_BIDIRECTIONAL);
+ direction);
return -ENOMEM;
}
@@ -396,7 +367,7 @@ spider_net_free_rx_chain_contents(struct spider_net_card *card)
dev_kfree_skb(descr->skb);
pci_unmap_single(card->pdev, descr->buf_addr,
SPIDER_NET_MAX_FRAME,
- PCI_DMA_BIDIRECTIONAL);
+ PCI_DMA_FROMDEVICE);
}
descr = descr->next;
}
@@ -446,15 +417,16 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
skb_reserve(descr->skb, SPIDER_NET_RXBUF_ALIGN - offset);
/* io-mmu-map the skb */
buf = pci_map_single(card->pdev, descr->skb->data,
- SPIDER_NET_MAX_FRAME, PCI_DMA_BIDIRECTIONAL);
+ SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
descr->buf_addr = buf;
if (buf == DMA_ERROR_CODE) {
dev_kfree_skb_any(descr->skb);
if (netif_msg_rx_err(card) && net_ratelimit())
pr_err("Could not iommu-map rx buffer\n");
- spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
+ descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
} else {
- descr->dmac_cmd_status = SPIDER_NET_DMAC_RX_CARDOWNED;
+ descr->dmac_cmd_status = SPIDER_NET_DESCR_CARDOWNED |
+ SPIDER_NET_DMAC_NOINTR_COMPLETE;
}
return error;
@@ -468,7 +440,7 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
* chip by writing to the appropriate register. DMA is enabled in
* spider_net_enable_rxdmac.
*/
-static void
+static inline void
spider_net_enable_rxchtails(struct spider_net_card *card)
{
/* assume chain is aligned correctly */
@@ -483,7 +455,7 @@ spider_net_enable_rxchtails(struct spider_net_card *card)
* spider_net_enable_rxdmac enables the DMA controller by setting RX_DMA_EN
* in the GDADMACCNTR register
*/
-static void
+static inline void
spider_net_enable_rxdmac(struct spider_net_card *card)
{
wmb();
@@ -500,23 +472,24 @@ spider_net_enable_rxdmac(struct spider_net_card *card)
static void
spider_net_refill_rx_chain(struct spider_net_card *card)
{
- struct spider_net_descr_chain *chain;
-
- chain = &card->rx_chain;
+ struct spider_net_descr_chain *chain = &card->rx_chain;
+ unsigned long flags;
/* one context doing the refill (and a second context seeing that
* and omitting it) is ok. If called by NAPI, we'll be called again
* as spider_net_decode_one_descr is called several times. If some
* interrupt calls us, the NAPI is about to clean up anyway. */
- if (atomic_inc_return(&card->rx_chain_refill) == 1)
- while (spider_net_get_descr_status(chain->head) ==
- SPIDER_NET_DESCR_NOT_IN_USE) {
- if (spider_net_prepare_rx_descr(card, chain->head))
- break;
- chain->head = chain->head->next;
- }
+ if (!spin_trylock_irqsave(&chain->lock, flags))
+ return;
+
+ while (spider_net_get_descr_status(chain->head) ==
+ SPIDER_NET_DESCR_NOT_IN_USE) {
+ if (spider_net_prepare_rx_descr(card, chain->head))
+ break;
+ chain->head = chain->head->next;
+ }
- atomic_dec(&card->rx_chain_refill);
+ spin_unlock_irqrestore(&chain->lock, flags);
}
/**
@@ -554,111 +527,6 @@ error:
}
/**
- * spider_net_release_tx_descr - processes a used tx descriptor
- * @card: card structure
- * @descr: descriptor to release
- *
- * releases a used tx descriptor (unmapping, freeing of skb)
- */
-static void
-spider_net_release_tx_descr(struct spider_net_card *card,
- struct spider_net_descr *descr)
-{
- struct sk_buff *skb;
-
- /* unmap the skb */
- skb = descr->skb;
- pci_unmap_single(card->pdev, descr->buf_addr, skb->len,
- PCI_DMA_BIDIRECTIONAL);
-
- dev_kfree_skb_any(skb);
-
- /* set status to not used */
- spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
-}
-
-/**
- * spider_net_release_tx_chain - processes sent tx descriptors
- * @card: adapter structure
- * @brutal: if set, don't care about whether descriptor seems to be in use
- *
- * returns 0 if the tx ring is empty, otherwise 1.
- *
- * spider_net_release_tx_chain releases the tx descriptors that spider has
- * finished with (if non-brutal) or simply release tx descriptors (if brutal).
- * If some other context is calling this function, we return 1 so that we're
- * scheduled again (if we were scheduled) and will not loose initiative.
- */
-static int
-spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
-{
- struct spider_net_descr_chain *tx_chain = &card->tx_chain;
- enum spider_net_descr_status status;
-
- if (atomic_inc_return(&card->tx_chain_release) != 1) {
- atomic_dec(&card->tx_chain_release);
- return 1;
- }
-
- for (;;) {
- status = spider_net_get_descr_status(tx_chain->tail);
- switch (status) {
- case SPIDER_NET_DESCR_CARDOWNED:
- if (!brutal)
- goto out;
- /* fallthrough, if we release the descriptors
- * brutally (then we don't care about
- * SPIDER_NET_DESCR_CARDOWNED) */
- case SPIDER_NET_DESCR_RESPONSE_ERROR:
- case SPIDER_NET_DESCR_PROTECTION_ERROR:
- case SPIDER_NET_DESCR_FORCE_END:
- if (netif_msg_tx_err(card))
- pr_err("%s: forcing end of tx descriptor "
- "with status x%02x\n",
- card->netdev->name, status);
- card->netdev_stats.tx_dropped++;
- break;
-
- case SPIDER_NET_DESCR_COMPLETE:
- card->netdev_stats.tx_packets++;
- card->netdev_stats.tx_bytes +=
- tx_chain->tail->skb->len;
- break;
-
- default: /* any other value (== SPIDER_NET_DESCR_NOT_IN_USE) */
- goto out;
- }
- spider_net_release_tx_descr(card, tx_chain->tail);
- tx_chain->tail = tx_chain->tail->next;
- }
-out:
- atomic_dec(&card->tx_chain_release);
-
- netif_wake_queue(card->netdev);
-
- if (status == SPIDER_NET_DESCR_CARDOWNED)
- return 1;
- return 0;
-}
-
-/**
- * spider_net_cleanup_tx_ring - cleans up the TX ring
- * @card: card structure
- *
- * spider_net_cleanup_tx_ring is called by the tx_timer (as we don't use
- * interrupts to cleanup our TX ring) and returns sent packets to the stack
- * by freeing them
- */
-static void
-spider_net_cleanup_tx_ring(struct spider_net_card *card)
-{
- if ( (spider_net_release_tx_chain(card, 0)) &&
- (card->netdev->flags & IFF_UP) ) {
- mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
- }
-}
-
-/**
* spider_net_get_multicast_hash - generates hash for multicast filter table
* @addr: multicast address
*
@@ -761,97 +629,6 @@ spider_net_disable_rxdmac(struct spider_net_card *card)
}
/**
- * spider_net_stop - called upon ifconfig down
- * @netdev: interface device structure
- *
- * always returns 0
- */
-int
-spider_net_stop(struct net_device *netdev)
-{
- struct spider_net_card *card = netdev_priv(netdev);
-
- tasklet_kill(&card->rxram_full_tl);
- netif_poll_disable(netdev);
- netif_carrier_off(netdev);
- netif_stop_queue(netdev);
- del_timer_sync(&card->tx_timer);
-
- /* disable/mask all interrupts */
- spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
- spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
- spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
-
- /* free_irq(netdev->irq, netdev);*/
- free_irq(to_pci_dev(netdev->class_dev.dev)->irq, netdev);
-
- spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
- SPIDER_NET_DMA_TX_FEND_VALUE);
-
- /* turn off DMA, force end */
- spider_net_disable_rxdmac(card);
-
- /* release chains */
- spider_net_release_tx_chain(card, 1);
-
- spider_net_free_chain(card, &card->tx_chain);
- spider_net_free_chain(card, &card->rx_chain);
-
- return 0;
-}
-
-/**
- * spider_net_get_next_tx_descr - returns the next available tx descriptor
- * @card: device structure to get descriptor from
- *
- * returns the address of the next descriptor, or NULL if not available.
- */
-static struct spider_net_descr *
-spider_net_get_next_tx_descr(struct spider_net_card *card)
-{
- /* check, if head points to not-in-use descr */
- if ( spider_net_get_descr_status(card->tx_chain.head) ==
- SPIDER_NET_DESCR_NOT_IN_USE ) {
- return card->tx_chain.head;
- } else {
- return NULL;
- }
-}
-
-/**
- * spider_net_set_txdescr_cmdstat - sets the tx descriptor command field
- * @descr: descriptor structure to fill out
- * @skb: packet to consider
- *
- * fills out the command and status field of the descriptor structure,
- * depending on hardware checksum settings.
- */
-static void
-spider_net_set_txdescr_cmdstat(struct spider_net_descr *descr,
- struct sk_buff *skb)
-{
- /* make sure the other fields in the descriptor are written */
- wmb();
-
- if (skb->ip_summed != CHECKSUM_HW) {
- descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_NOCS;
- return;
- }
-
- /* is packet ip?
- * if yes: tcp? udp? */
- if (skb->protocol == htons(ETH_P_IP)) {
- if (skb->nh.iph->protocol == IPPROTO_TCP)
- descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_TCPCS;
- else if (skb->nh.iph->protocol == IPPROTO_UDP)
- descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_UDPCS;
- else /* the stack should checksum non-tcp and non-udp
- packets on his own: NETIF_F_IP_CSUM */
- descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_NOCS;
- }
-}
-
-/**
* spider_net_prepare_tx_descr - fill tx descriptor with skb data
* @card: card structure
* @descr: descriptor structure to fill out
@@ -864,13 +641,12 @@ spider_net_set_txdescr_cmdstat(struct spider_net_descr *descr,
*/
static int
spider_net_prepare_tx_descr(struct spider_net_card *card,
- struct spider_net_descr *descr,
struct sk_buff *skb)
{
+ struct spider_net_descr *descr = card->tx_chain.head;
dma_addr_t buf;
- buf = pci_map_single(card->pdev, skb->data,
- skb->len, PCI_DMA_BIDIRECTIONAL);
+ buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
if (buf == DMA_ERROR_CODE) {
if (netif_msg_tx_err(card) && net_ratelimit())
pr_err("could not iommu-map packet (%p, %i). "
@@ -880,10 +656,101 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
descr->buf_addr = buf;
descr->buf_size = skb->len;
+ descr->next_descr_addr = 0;
descr->skb = skb;
descr->data_status = 0;
- spider_net_set_txdescr_cmdstat(descr,skb);
+ descr->dmac_cmd_status =
+ SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS;
+ if (skb->protocol == htons(ETH_P_IP))
+ switch (skb->nh.iph->protocol) {
+ case IPPROTO_TCP:
+ descr->dmac_cmd_status |= SPIDER_NET_DMAC_TCP;
+ break;
+ case IPPROTO_UDP:
+ descr->dmac_cmd_status |= SPIDER_NET_DMAC_UDP;
+ break;
+ }
+
+ descr->prev->next_descr_addr = descr->bus_addr;
+
+ return 0;
+}
+
+/**
+ * spider_net_release_tx_descr - processes a used tx descriptor
+ * @card: card structure
+ * @descr: descriptor to release
+ *
+ * releases a used tx descriptor (unmapping, freeing of skb)
+ */
+static inline void
+spider_net_release_tx_descr(struct spider_net_card *card)
+{
+ struct spider_net_descr *descr = card->tx_chain.tail;
+ struct sk_buff *skb;
+
+ card->tx_chain.tail = card->tx_chain.tail->next;
+ descr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE;
+
+ /* unmap the skb */
+ skb = descr->skb;
+ pci_unmap_single(card->pdev, descr->buf_addr, skb->len,
+ PCI_DMA_TODEVICE);
+ dev_kfree_skb_any(skb);
+}
+
+/**
+ * spider_net_release_tx_chain - processes sent tx descriptors
+ * @card: adapter structure
+ * @brutal: if set, don't care about whether descriptor seems to be in use
+ *
+ * returns 0 if the tx ring is empty, otherwise 1.
+ *
+ * spider_net_release_tx_chain releases the tx descriptors that spider has
+ * finished with (if non-brutal) or simply release tx descriptors (if brutal).
+ * If some other context is calling this function, we return 1 so that we're
+ * scheduled again (if we were scheduled) and will not loose initiative.
+ */
+static int
+spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
+{
+ struct spider_net_descr_chain *chain = &card->tx_chain;
+ int status;
+
+ spider_net_read_reg(card, SPIDER_NET_GDTDMACCNTR);
+
+ while (chain->tail != chain->head) {
+ status = spider_net_get_descr_status(chain->tail);
+ switch (status) {
+ case SPIDER_NET_DESCR_COMPLETE:
+ card->netdev_stats.tx_packets++;
+ card->netdev_stats.tx_bytes += chain->tail->skb->len;
+ break;
+
+ case SPIDER_NET_DESCR_CARDOWNED:
+ if (!brutal)
+ return 1;
+ /* fallthrough, if we release the descriptors
+ * brutally (then we don't care about
+ * SPIDER_NET_DESCR_CARDOWNED) */
+
+ case SPIDER_NET_DESCR_RESPONSE_ERROR:
+ case SPIDER_NET_DESCR_PROTECTION_ERROR:
+ case SPIDER_NET_DESCR_FORCE_END:
+ if (netif_msg_tx_err(card))
+ pr_err("%s: forcing end of tx descriptor "
+ "with status x%02x\n",
+ card->netdev->name, status);
+ card->netdev_stats.tx_errors++;
+ break;
+
+ default:
+ card->netdev_stats.tx_dropped++;
+ return 1;
+ }
+ spider_net_release_tx_descr(card);
+ }
return 0;
}
@@ -896,18 +763,32 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
* spider_net_kick_tx_dma writes the current tx chain head as start address
* of the tx descriptor chain and enables the transmission DMA engine
*/
-static void
-spider_net_kick_tx_dma(struct spider_net_card *card,
- struct spider_net_descr *descr)
+static inline void
+spider_net_kick_tx_dma(struct spider_net_card *card)
{
- /* this is the only descriptor in the output chain.
- * Enable TX DMA */
+ struct spider_net_descr *descr;
- spider_net_write_reg(card, SPIDER_NET_GDTDCHA,
- descr->bus_addr);
+ if (spider_net_read_reg(card, SPIDER_NET_GDTDMACCNTR) &
+ SPIDER_NET_TX_DMA_EN)
+ goto out;
- spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
- SPIDER_NET_DMA_TX_VALUE);
+ descr = card->tx_chain.tail;
+ for (;;) {
+ if (spider_net_get_descr_status(descr) ==
+ SPIDER_NET_DESCR_CARDOWNED) {
+ spider_net_write_reg(card, SPIDER_NET_GDTDCHA,
+ descr->bus_addr);
+ spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
+ SPIDER_NET_DMA_TX_VALUE);
+ break;
+ }
+ if (descr == card->tx_chain.head)
+ break;
+ descr = descr->next;
+ }
+
+out:
+ mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
}
/**
@@ -915,47 +796,69 @@ spider_net_kick_tx_dma(struct spider_net_card *card,
* @skb: packet to send out
* @netdev: interface device structure
*
- * returns 0 on success, <0 on failure
+ * returns 0 on success, !0 on failure
*/
static int
spider_net_xmit(struct sk_buff *skb, struct net_device *netdev)
{
struct spider_net_card *card = netdev_priv(netdev);
- struct spider_net_descr *descr;
+ struct spider_net_descr_chain *chain = &card->tx_chain;
+ struct spider_net_descr *descr = chain->head;
+ unsigned long flags;
int result;
+ spin_lock_irqsave(&chain->lock, flags);
+
spider_net_release_tx_chain(card, 0);
- descr = spider_net_get_next_tx_descr(card);
+ if (chain->head->next == chain->tail->prev) {
+ card->netdev_stats.tx_dropped++;
+ result = NETDEV_TX_LOCKED;
+ goto out;
+ }
- if (!descr)
- goto error;
+ if (spider_net_get_descr_status(descr) != SPIDER_NET_DESCR_NOT_IN_USE) {
+ result = NETDEV_TX_LOCKED;
+ goto out;
+ }
- result = spider_net_prepare_tx_descr(card, descr, skb);
- if (result)
- goto error;
+ if (spider_net_prepare_tx_descr(card, skb) != 0) {
+ card->netdev_stats.tx_dropped++;
+ result = NETDEV_TX_BUSY;
+ goto out;
+ }
+
+ result = NETDEV_TX_OK;
+ spider_net_kick_tx_dma(card);
card->tx_chain.head = card->tx_chain.head->next;
- if (spider_net_get_descr_status(descr->prev) !=
- SPIDER_NET_DESCR_CARDOWNED) {
- /* make sure the current descriptor is in memory. Then
- * kicking it on again makes sense, if the previous is not
- * card-owned anymore. Check the previous descriptor twice
- * to omit an mb() in heavy traffic cases */
- mb();
- if (spider_net_get_descr_status(descr->prev) !=
- SPIDER_NET_DESCR_CARDOWNED)
- spider_net_kick_tx_dma(card, descr);
- }
+out:
+ spin_unlock_irqrestore(&chain->lock, flags);
+ netif_wake_queue(netdev);
+ return result;
+}
- mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
+/**
+ * spider_net_cleanup_tx_ring - cleans up the TX ring
+ * @card: card structure
+ *
+ * spider_net_cleanup_tx_ring is called by the tx_timer (as we don't use
+ * interrupts to cleanup our TX ring) and returns sent packets to the stack
+ * by freeing them
+ */
+static void
+spider_net_cleanup_tx_ring(struct spider_net_card *card)
+{
+ unsigned long flags;
- return NETDEV_TX_OK;
+ spin_lock_irqsave(&card->tx_chain.lock, flags);
-error:
- card->netdev_stats.tx_dropped++;
- return NETDEV_TX_BUSY;
+ if ((spider_net_release_tx_chain(card, 0) != 0) &&
+ (card->netdev->flags & IFF_UP))
+ spider_net_kick_tx_dma(card);
+
+ spin_unlock_irqrestore(&card->tx_chain.lock, flags);
}
/**
@@ -1002,7 +905,7 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
/* unmap descriptor */
pci_unmap_single(card->pdev, descr->buf_addr, SPIDER_NET_MAX_FRAME,
- PCI_DMA_BIDIRECTIONAL);
+ PCI_DMA_FROMDEVICE);
/* the cases we'll throw away the packet immediately */
if (data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
@@ -1067,14 +970,11 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
static int
spider_net_decode_one_descr(struct spider_net_card *card, int napi)
{
- enum spider_net_descr_status status;
- struct spider_net_descr *descr;
- struct spider_net_descr_chain *chain;
+ struct spider_net_descr_chain *chain = &card->rx_chain;
+ struct spider_net_descr *descr = chain->tail;
+ int status;
int result;
- chain = &card->rx_chain;
- descr = chain->tail;
-
status = spider_net_get_descr_status(descr);
if (status == SPIDER_NET_DESCR_CARDOWNED) {
@@ -1103,7 +1003,7 @@ spider_net_decode_one_descr(struct spider_net_card *card, int napi)
card->netdev->name, status);
card->netdev_stats.rx_dropped++;
pci_unmap_single(card->pdev, descr->buf_addr,
- SPIDER_NET_MAX_FRAME, PCI_DMA_BIDIRECTIONAL);
+ SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
dev_kfree_skb_irq(descr->skb);
goto refill;
}
@@ -1119,7 +1019,7 @@ spider_net_decode_one_descr(struct spider_net_card *card, int napi)
/* ok, we've got a packet in descr */
result = spider_net_pass_skb_up(descr, card, napi);
refill:
- spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
+ descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
/* change the descriptor state: */
if (!napi)
spider_net_refill_rx_chain(card);
@@ -1291,21 +1191,6 @@ spider_net_set_mac(struct net_device *netdev, void *p)
}
/**
- * spider_net_enable_txdmac - enables a TX DMA controller
- * @card: card structure
- *
- * spider_net_enable_txdmac enables the TX DMA controller by setting the
- * descriptor chain tail address
- */
-static void
-spider_net_enable_txdmac(struct spider_net_card *card)
-{
- /* assume chain is aligned correctly */
- spider_net_write_reg(card, SPIDER_NET_GDTDCHA,
- card->tx_chain.tail->bus_addr);
-}
-
-/**
* spider_net_handle_rxram_full - cleans up RX ring upon RX RAM full interrupt
* @card: card structure
*
@@ -1653,7 +1538,6 @@ spider_net_enable_card(struct spider_net_card *card)
{ SPIDER_NET_GMRWOLCTRL, 0 },
{ SPIDER_NET_GTESTMD, 0x10000000 },
{ SPIDER_NET_GTTQMSK, 0x00400040 },
- { SPIDER_NET_GTESTMD, 0 },
{ SPIDER_NET_GMACINTEN, 0 },
@@ -1692,9 +1576,6 @@ spider_net_enable_card(struct spider_net_card *card)
spider_net_write_reg(card, SPIDER_NET_GRXDMAEN, SPIDER_NET_WOL_VALUE);
- /* set chain tail adress for TX chain */
- spider_net_enable_txdmac(card);
-
spider_net_write_reg(card, SPIDER_NET_GMACLENLMT,
SPIDER_NET_LENLMT_VALUE);
spider_net_write_reg(card, SPIDER_NET_GMACMODE,
@@ -1709,6 +1590,9 @@ spider_net_enable_card(struct spider_net_card *card)
SPIDER_NET_INT1_MASK_VALUE);
spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK,
SPIDER_NET_INT2_MASK_VALUE);
+
+ spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
+ SPIDER_NET_GDTDCEIDIS);
}
/**
@@ -1728,10 +1612,12 @@ spider_net_open(struct net_device *netdev)
result = -ENOMEM;
if (spider_net_init_chain(card, &card->tx_chain,
- card->descr, tx_descriptors))
+ card->descr,
+ PCI_DMA_TODEVICE, tx_descriptors))
goto alloc_tx_failed;
if (spider_net_init_chain(card, &card->rx_chain,
- card->descr + tx_descriptors, rx_descriptors))
+ card->descr + tx_descriptors,
+ PCI_DMA_FROMDEVICE, rx_descriptors))
goto alloc_rx_failed;
/* allocate rx skbs */
@@ -1938,7 +1824,7 @@ spider_net_workaround_rxramfull(struct spider_net_card *card)
/* empty sequencer data */
for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS;
sequencer++) {
- spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
+ spider_net_write_reg(card, SPIDER_NET_GSnPRGADR +
sequencer * 8, 0x0);
for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) {
spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
@@ -1955,6 +1841,49 @@ spider_net_workaround_rxramfull(struct spider_net_card *card)
}
/**
+ * spider_net_stop - called upon ifconfig down
+ * @netdev: interface device structure
+ *
+ * always returns 0
+ */
+int
+spider_net_stop(struct net_device *netdev)
+{
+ struct spider_net_card *card = netdev_priv(netdev);
+
+ tasklet_kill(&card->rxram_full_tl);
+ netif_poll_disable(netdev);
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ del_timer_sync(&card->tx_timer);
+
+ /* disable/mask all interrupts */
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
+
+ /* free_irq(netdev->irq, netdev);*/
+ free_irq(to_pci_dev(netdev->class_dev.dev)->irq, netdev);
+
+ spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
+ SPIDER_NET_DMA_TX_FEND_VALUE);
+
+ /* turn off DMA, force end */
+ spider_net_disable_rxdmac(card);
+
+ /* release chains */
+ if (spin_trylock(&card->tx_chain.lock)) {
+ spider_net_release_tx_chain(card, 1);
+ spin_unlock(&card->tx_chain.lock);
+ }
+
+ spider_net_free_chain(card, &card->tx_chain);
+ spider_net_free_chain(card, &card->rx_chain);
+
+ return 0;
+}
+
+/**
* spider_net_tx_timeout_task - task scheduled by the watchdog timeout
* function (to be called not under interrupt status)
* @data: data, is interface device structure
@@ -1982,7 +1911,7 @@ spider_net_tx_timeout_task(void *data)
goto out;
spider_net_open(netdev);
- spider_net_kick_tx_dma(card, card->tx_chain.head);
+ spider_net_kick_tx_dma(card);
netif_device_attach(netdev);
out:
@@ -2065,7 +1994,6 @@ spider_net_setup_netdev(struct spider_net_card *card)
pci_set_drvdata(card->pdev, netdev);
- atomic_set(&card->tx_chain_release,0);
card->rxram_full_tl.data = (unsigned long) card;
card->rxram_full_tl.func =
(void (*)(unsigned long)) spider_net_handle_rxram_full;
@@ -2079,7 +2007,7 @@ spider_net_setup_netdev(struct spider_net_card *card)
spider_net_setup_netdev_ops(netdev);
- netdev->features = NETIF_F_HW_CSUM;
+ netdev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX;
/* some time: NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
* NETIF_F_HW_VLAN_FILTER */
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
index 3b8d951cf73..f6dcf180ae3 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/spider_net.h
@@ -208,7 +208,10 @@ extern char spider_net_driver_name[];
#define SPIDER_NET_DMA_RX_VALUE 0x80000000
#define SPIDER_NET_DMA_RX_FEND_VALUE 0x00030003
/* to set TX_DMA_EN */
-#define SPIDER_NET_DMA_TX_VALUE 0x80000000
+#define SPIDER_NET_TX_DMA_EN 0x80000000
+#define SPIDER_NET_GDTDCEIDIS 0x00000002
+#define SPIDER_NET_DMA_TX_VALUE SPIDER_NET_TX_DMA_EN | \
+ SPIDER_NET_GDTDCEIDIS
#define SPIDER_NET_DMA_TX_FEND_VALUE 0x00030003
/* SPIDER_NET_UA_DESCR_VALUE is OR'ed with the unicast address */
@@ -329,55 +332,23 @@ enum spider_net_int2_status {
(~SPIDER_NET_TXINT) & \
(~SPIDER_NET_RXINT) )
-#define SPIDER_NET_GPREXEC 0x80000000
-#define SPIDER_NET_GPRDAT_MASK 0x0000ffff
+#define SPIDER_NET_GPREXEC 0x80000000
+#define SPIDER_NET_GPRDAT_MASK 0x0000ffff
-/* descriptor bits
- *
- * 1010 descriptor ready
- * 0 descr in middle of chain
- * 000 fixed to 0
- *
- * 0 no interrupt on completion
- * 000 fixed to 0
- * 1 no ipsec processing
- * 1 last descriptor for this frame
- * 00 no checksum
- * 10 tcp checksum
- * 11 udp checksum
- *
- * 00 fixed to 0
- * 0 fixed to 0
- * 0 no interrupt on response errors
- * 0 no interrupt on invalid descr
- * 0 no interrupt on dma process termination
- * 0 no interrupt on descr chain end
- * 0 no interrupt on descr complete
- *
- * 000 fixed to 0
- * 0 response error interrupt status
- * 0 invalid descr status
- * 0 dma termination status
- * 0 descr chain end status
- * 0 descr complete status */
-#define SPIDER_NET_DMAC_CMDSTAT_NOCS 0xa00c0000
-#define SPIDER_NET_DMAC_CMDSTAT_TCPCS 0xa00e0000
-#define SPIDER_NET_DMAC_CMDSTAT_UDPCS 0xa00f0000
-#define SPIDER_NET_DESCR_IND_PROC_SHIFT 28
-#define SPIDER_NET_DESCR_IND_PROC_MASKO 0x0fffffff
-
-/* descr ready, descr is in middle of chain, get interrupt on completion */
-#define SPIDER_NET_DMAC_RX_CARDOWNED 0xa0800000
-
-enum spider_net_descr_status {
- SPIDER_NET_DESCR_COMPLETE = 0x00, /* used in rx and tx */
- SPIDER_NET_DESCR_RESPONSE_ERROR = 0x01, /* used in rx and tx */
- SPIDER_NET_DESCR_PROTECTION_ERROR = 0x02, /* used in rx and tx */
- SPIDER_NET_DESCR_FRAME_END = 0x04, /* used in rx */
- SPIDER_NET_DESCR_FORCE_END = 0x05, /* used in rx and tx */
- SPIDER_NET_DESCR_CARDOWNED = 0x0a, /* used in rx and tx */
- SPIDER_NET_DESCR_NOT_IN_USE /* any other value */
-};
+#define SPIDER_NET_DMAC_NOINTR_COMPLETE 0x00800000
+#define SPIDER_NET_DMAC_NOCS 0x00040000
+#define SPIDER_NET_DMAC_TCP 0x00020000
+#define SPIDER_NET_DMAC_UDP 0x00030000
+#define SPIDER_NET_TXDCEST 0x08000000
+
+#define SPIDER_NET_DESCR_IND_PROC_MASK 0xF0000000
+#define SPIDER_NET_DESCR_COMPLETE 0x00000000 /* used in rx and tx */
+#define SPIDER_NET_DESCR_RESPONSE_ERROR 0x10000000 /* used in rx and tx */
+#define SPIDER_NET_DESCR_PROTECTION_ERROR 0x20000000 /* used in rx and tx */
+#define SPIDER_NET_DESCR_FRAME_END 0x40000000 /* used in rx */
+#define SPIDER_NET_DESCR_FORCE_END 0x50000000 /* used in rx and tx */
+#define SPIDER_NET_DESCR_CARDOWNED 0xA0000000 /* used in rx and tx */
+#define SPIDER_NET_DESCR_NOT_IN_USE 0xF0000000
struct spider_net_descr {
/* as defined by the hardware */
@@ -398,7 +369,7 @@ struct spider_net_descr {
} __attribute__((aligned(32)));
struct spider_net_descr_chain {
- /* we walk from tail to head */
+ spinlock_t lock;
struct spider_net_descr *head;
struct spider_net_descr *tail;
};
@@ -453,8 +424,6 @@ struct spider_net_card {
struct spider_net_descr_chain tx_chain;
struct spider_net_descr_chain rx_chain;
- atomic_t rx_chain_refill;
- atomic_t tx_chain_release;
struct net_device_stats netdev_stats;
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 8673fd4c08c..c6f5bc3c042 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -3255,12 +3255,7 @@ static void __devexit happy_meal_pci_remove(struct pci_dev *pdev)
}
static struct pci_device_id happymeal_pci_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_SUN,
- .device = PCI_DEVICE_ID_SUN_HAPPYMEAL,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_HAPPYMEAL) },
{ } /* Terminating entry */
};
@@ -3275,7 +3270,7 @@ static struct pci_driver hme_pci_driver = {
static int __init happy_meal_pci_init(void)
{
- return pci_module_init(&hme_pci_driver);
+ return pci_register_driver(&hme_pci_driver);
}
static void happy_meal_pci_exit(void)
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 1ef9fd39a79..0e3fdf7c6dd 100644
--- a/drivers/net/sunlance.c
+++ b/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/drivers/net/tg3.c b/drivers/net/tg3.c
index ce6f3be86da..6f97962dd06 100644
--- a/drivers/net/tg3.c
+++ b/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.64"
+#define DRV_MODULE_RELDATE "July 31, 2006"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -3097,7 +3097,7 @@ 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;
@@ -3270,7 +3270,7 @@ 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;
@@ -3590,6 +3590,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 +3652,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);
@@ -4124,6 +4148,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 +4169,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 +4258,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 +4307,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 +5861,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 +5879,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 +5889,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 +5989,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 +8005,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 +8029,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 +8051,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 +8075,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 +8618,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 +8717,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 +8793,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);
@@ -11699,7 +11752,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 +11761,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 +11788,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/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index f5b0078eb4a..aa9cd92f46b 100644
--- a/drivers/net/via-velocity.c
+++ b/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, &regs->PHYSR0) ? 0 : 1;
+ return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, &regs->PHYSR0) ? 1 : 0;
}
static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c
index 2c09ec908a3..435e91ec462 100644
--- a/drivers/net/wan/c101.c
+++ b/drivers/net/wan/c101.c
@@ -197,7 +197,6 @@ static int c101_open(struct net_device *dev)
sca_out(IE0_TXINT, MSCI0_OFFSET + IE0, port);
set_carrier(port);
- printk(KERN_DEBUG "0x%X\n", sca_in(MSCI1_OFFSET + ST3, port));
/* enable MSCI1 CDCD interrupt */
sca_out(IE1_CDCD, MSCI1_OFFSET + IE1, port);
@@ -449,4 +448,5 @@ module_exit(c101_cleanup);
MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
MODULE_DESCRIPTION("Moxa C101 serial port driver");
MODULE_LICENSE("GPL v2");
-module_param(hw, charp, 0444); /* hw=irq,ram:irq,... */
+module_param(hw, charp, 0444);
+MODULE_PARM_DESC(hw, "irq,ram:irq,...");
diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c
index b81263eaede..fbaab5bf71e 100644
--- a/drivers/net/wan/hdlc_ppp.c
+++ b/drivers/net/wan/hdlc_ppp.c
@@ -107,6 +107,7 @@ int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
dev->hard_header = NULL;
dev->type = ARPHRD_PPP;
dev->addr_len = 0;
+ netif_dormant_off(dev);
return 0;
}
diff --git a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c
index 9456d31cb1c..f15aa6ba77f 100644
--- a/drivers/net/wan/hdlc_raw.c
+++ b/drivers/net/wan/hdlc_raw.c
@@ -82,6 +82,7 @@ int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr)
dev->type = ARPHRD_RAWHDLC;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
dev->addr_len = 0;
+ netif_dormant_off(dev);
return 0;
}
diff --git a/drivers/net/wan/hdlc_raw_eth.c b/drivers/net/wan/hdlc_raw_eth.c
index b1285cc8fee..d1884987f94 100644
--- a/drivers/net/wan/hdlc_raw_eth.c
+++ b/drivers/net/wan/hdlc_raw_eth.c
@@ -100,6 +100,7 @@ int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
dev->tx_queue_len = old_qlen;
memcpy(dev->dev_addr, "\x00\x01", 2);
get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2);
+ netif_dormant_off(dev);
return 0;
}
diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c
index 07e5eef1fe0..a867fb411f8 100644
--- a/drivers/net/wan/hdlc_x25.c
+++ b/drivers/net/wan/hdlc_x25.c
@@ -212,6 +212,7 @@ int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr)
dev->hard_header = NULL;
dev->type = ARPHRD_X25;
dev->addr_len = 0;
+ netif_dormant_off(dev);
return 0;
}
diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c
index e013b817cab..dcf46add3ad 100644
--- a/drivers/net/wan/n2.c
+++ b/drivers/net/wan/n2.c
@@ -564,4 +564,5 @@ module_exit(n2_cleanup);
MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
MODULE_DESCRIPTION("RISCom/N2 serial port driver");
MODULE_LICENSE("GPL v2");
-module_param(hw, charp, 0444); /* hw=io,irq,ram,ports:io,irq,... */
+module_param(hw, charp, 0444);
+MODULE_PARM_DESC(hw, "io,irq,ram,ports:io,irq,...");
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index fa9d2c4edc9..2e8ac995d56 100644
--- a/drivers/net/wireless/Kconfig
+++ b/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/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 3889f79e712..df317c1e12a 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/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/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index d6ed5781b93..317ace7f9aa 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/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/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c
index 662ecc8a33f..c52e9bcf8d0 100644
--- a/drivers/net/wireless/zd1201.c
+++ b/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/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index efc9c4bd826..da9d06bdb81 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/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/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index 805121093ab..069d2b46733 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/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/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 3bdc54d128d..d6f3e02a0b5 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/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/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 72f90525bf6..6320984126c 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/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/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index 34de5697983..e2fef60c2d0 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/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 <gregkh@us.ibm.com>,
- * <t-kochi@bq.jp.nec.com>
+ * Send feedback to <kristen.c.accardi@intel.com>
*
*/
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index ef95d12fb32..ae67a8f55ba 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/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 <t-kochi@bq.jp.nec.com>
+ * Send feedback to <kristen.c.accardi@intel.com>
*
*/
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 50bfc1b2f3b..478d0d28f7a 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/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/drivers/pci/quirks.c b/drivers/pci/quirks.c
index e3c78c39b7e..fb08bc951ac 100644
--- a/drivers/pci/quirks.c
+++ b/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/drivers/pci/search.c b/drivers/pci/search.c
index 622b3f8ba82..d529462d1b5 100644
--- a/drivers/pci/search.c
+++ b/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 @@ exit:
* @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 @@ exit:
* 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 @@ exit:
* 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/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 738b1ef595a..9ad18e62658 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/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/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 7bf25b88ea3..c8323399e9e 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/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/drivers/pnp/interface.c b/drivers/pnp/interface.c
index 3163e3d73da..9d8b415eca7 100644
--- a/drivers/pnp/interface.c
+++ b/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/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 21226888185..dc79b0a0059 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/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/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index b154b3f52cb..551f58e2981 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/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/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index 4cd879cb9bd..1140302ff11 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -304,6 +304,7 @@ static int __init xpram_setup_sizes(unsigned long pages)
{
unsigned long mem_needed;
unsigned long mem_auto;
+ unsigned long long size;
int mem_auto_no;
int i;
@@ -321,9 +322,19 @@ static int __init xpram_setup_sizes(unsigned long pages)
mem_needed = 0;
mem_auto_no = 0;
for (i = 0; i < xpram_devs; i++) {
- if (sizes[i])
- xpram_sizes[i] =
- (memparse(sizes[i], &sizes[i]) + 3) & -4UL;
+ if (sizes[i]) {
+ size = simple_strtoull(sizes[i], &sizes[i], 0);
+ switch (sizes[i][0]) {
+ case 'g':
+ case 'G':
+ size <<= 20;
+ break;
+ case 'm':
+ case 'M':
+ size <<= 10;
+ }
+ xpram_sizes[i] = (size + 3) & -4UL;
+ }
if (xpram_sizes[i])
mem_needed += xpram_sizes[i];
else
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 95e285b2e25..7a84014f203 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -1106,10 +1106,10 @@ raw3270_delete_device(struct raw3270 *rp)
/* Remove from device chain. */
mutex_lock(&raw3270_mutex);
- if (rp->clttydev)
+ if (rp->clttydev && !IS_ERR(rp->clttydev))
class_device_destroy(class3270,
MKDEV(IBM_TTY3270_MAJOR, rp->minor));
- if (rp->cltubdev)
+ if (rp->cltubdev && !IS_ERR(rp->cltubdev))
class_device_destroy(class3270,
MKDEV(IBM_FS3270_MAJOR, rp->minor));
list_del_init(&rp->list);
@@ -1173,21 +1173,37 @@ static struct attribute_group raw3270_attr_group = {
.attrs = raw3270_attrs,
};
-static void
-raw3270_create_attributes(struct raw3270 *rp)
+static int raw3270_create_attributes(struct raw3270 *rp)
{
- //FIXME: check return code
- sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
- rp->clttydev =
- class_device_create(class3270, NULL,
- MKDEV(IBM_TTY3270_MAJOR, rp->minor),
- &rp->cdev->dev, "tty%s",
- rp->cdev->dev.bus_id);
- rp->cltubdev =
- class_device_create(class3270, NULL,
- MKDEV(IBM_FS3270_MAJOR, rp->minor),
- &rp->cdev->dev, "tub%s",
- rp->cdev->dev.bus_id);
+ int rc;
+
+ rc = sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
+ if (rc)
+ goto out;
+
+ rp->clttydev = class_device_create(class3270, NULL,
+ MKDEV(IBM_TTY3270_MAJOR, rp->minor),
+ &rp->cdev->dev, "tty%s",
+ rp->cdev->dev.bus_id);
+ if (IS_ERR(rp->clttydev)) {
+ rc = PTR_ERR(rp->clttydev);
+ goto out_ttydev;
+ }
+
+ rp->cltubdev = class_device_create(class3270, NULL,
+ MKDEV(IBM_FS3270_MAJOR, rp->minor),
+ &rp->cdev->dev, "tub%s",
+ rp->cdev->dev.bus_id);
+ if (!IS_ERR(rp->cltubdev))
+ goto out;
+
+ rc = PTR_ERR(rp->cltubdev);
+ class_device_destroy(class3270, MKDEV(IBM_TTY3270_MAJOR, rp->minor));
+
+out_ttydev:
+ sysfs_remove_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
+out:
+ return rc;
}
/*
@@ -1255,7 +1271,9 @@ raw3270_set_online (struct ccw_device *cdev)
rc = raw3270_reset_device(rp);
if (rc)
goto failure;
- raw3270_create_attributes(rp);
+ rc = raw3270_create_attributes(rp);
+ if (rc)
+ goto failure;
set_bit(RAW3270_FLAGS_READY, &rp->flags);
mutex_lock(&raw3270_mutex);
list_for_each_entry(np, &raw3270_notifier, list)
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index a5c68e60fcf..643b6d07856 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -76,14 +76,22 @@ struct tape_class_device *register_tape_dev(
device,
"%s", tcd->device_name
);
- sysfs_create_link(
+ rc = PTR_ERR(tcd->class_device);
+ if (rc)
+ goto fail_with_cdev;
+ rc = sysfs_create_link(
&device->kobj,
&tcd->class_device->kobj,
tcd->mode_name
);
+ if (rc)
+ goto fail_with_class_device;
return tcd;
+fail_with_class_device:
+ class_device_destroy(tape_class, tcd->char_device->dev);
+
fail_with_cdev:
cdev_del(tcd->char_device);
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 122b4d8965c..2826aed9104 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -543,20 +543,24 @@ int
tape_generic_probe(struct ccw_device *cdev)
{
struct tape_device *device;
+ int ret;
device = tape_alloc_device();
if (IS_ERR(device))
return -ENODEV;
- PRINT_INFO("tape device %s found\n", cdev->dev.bus_id);
+ ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP);
+ ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group);
+ if (ret) {
+ tape_put_device(device);
+ PRINT_ERR("probe failed for tape device %s\n", cdev->dev.bus_id);
+ return ret;
+ }
cdev->dev.driver_data = device;
+ cdev->handler = __tape_do_irq;
device->cdev = cdev;
device->cdev_id = busid_to_int(cdev->dev.bus_id);
- cdev->handler = __tape_do_irq;
-
- ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP);
- sysfs_create_group(&cdev->dev.kobj, &tape_attr_group);
-
- return 0;
+ PRINT_INFO("tape device %s found\n", cdev->dev.bus_id);
+ return ret;
}
static inline void
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index f26a2ee3aad..3cba6c9fab1 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/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 @@ error:
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/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 0df3af1f08d..828b2d334f0 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -1068,6 +1068,7 @@ cmb_show_avg_sample_interval(struct device *dev, struct device_attribute *attr,
if (count) {
interval = cmb_data->last_update -
cdev->private->cmb_start_time;
+ interval = (interval * 1000) >> 12;
interval /= count;
} else
interval = -1;
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index ac6e0c7e43d..7a39e0b0386 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/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. */
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 20c8eb16f46..8a4b5812014 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -2686,9 +2686,17 @@ static struct attribute_group ctc_attr_group = {
static int
ctc_add_attributes(struct device *dev)
{
- device_create_file(dev, &dev_attr_loglevel);
- device_create_file(dev, &dev_attr_stats);
- return 0;
+ int rc;
+
+ rc = device_create_file(dev, &dev_attr_loglevel);
+ if (rc)
+ goto out;
+ rc = device_create_file(dev, &dev_attr_stats);
+ if (!rc)
+ goto out;
+ device_remove_file(dev, &dev_attr_loglevel);
+out:
+ return rc;
}
static void
@@ -2901,7 +2909,12 @@ ctc_new_device(struct ccwgroup_device *cgdev)
goto out;
}
- ctc_add_attributes(&cgdev->dev);
+ if (ctc_add_attributes(&cgdev->dev)) {
+ ctc_netdev_unregister(dev);
+ dev->priv = NULL;
+ ctc_free_netdevice(dev, 1);
+ goto out;
+ }
strlcpy(privptr->fsm->name, dev->name, sizeof (privptr->fsm->name));
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 103c41470bd..5fff1f93973 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -8451,10 +8451,11 @@ __qeth_reboot_event_card(struct device *dev, void *data)
static int
qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
{
+ int ret;
- driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
- __qeth_reboot_event_card);
- return NOTIFY_DONE;
+ ret = driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+ __qeth_reboot_event_card);
+ return ret ? NOTIFY_BAD : NOTIFY_DONE;
}
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
index 16b59773c0b..935952ef88f 100644
--- a/drivers/sbus/sbus.c
+++ b/drivers/sbus/sbus.c
@@ -233,7 +233,7 @@ static void __init build_one_sbus(struct device_node *dp, int num_sbus)
sbus->ofdev.node = dp;
sbus->ofdev.dev.parent = NULL;
sbus->ofdev.dev.bus = &sbus_bus_type;
- strcpy(sbus->ofdev.dev.bus_id, dp->path_component_name);
+ sprintf(sbus->ofdev.dev.bus_id, "sbus%d", num_sbus);
if (of_device_register(&sbus->ofdev) != 0)
printk(KERN_DEBUG "sbus: device registration error for %s!\n",
diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c
index c690c2b89e4..acf292736b4 100644
--- a/drivers/scsi/53c7xx.c
+++ b/drivers/scsi/53c7xx.c
@@ -3451,12 +3451,12 @@ create_cmd (Scsi_Cmnd *cmd) {
for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; cmd_datain += 4,
cmd_dataout += 4, ++i) {
u32 vbuf = cmd->use_sg
- ? (u32)page_address(((struct scatterlist *)cmd->buffer)[i].page)+
- ((struct scatterlist *)cmd->buffer)[i].offset
+ ? (u32)page_address(((struct scatterlist *)cmd->request_buffer)[i].page)+
+ ((struct scatterlist *)cmd->request_buffer)[i].offset
: (u32)(cmd->request_buffer);
u32 bbuf = virt_to_bus((void *)vbuf);
u32 count = cmd->use_sg ?
- ((struct scatterlist *)cmd->buffer)[i].length :
+ ((struct scatterlist *)cmd->request_buffer)[i].length :
cmd->request_bufflen;
/*
@@ -5417,7 +5417,7 @@ insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) {
if ((buffers = cmd->use_sg)) {
for (offset = 0,
- segment = (struct scatterlist *) cmd->buffer;
+ segment = (struct scatterlist *) cmd->request_buffer;
buffers && !((found = ((ptr >= (char *)page_address(segment->page)+segment->offset) &&
(ptr < ((char *)page_address(segment->page)+segment->offset+segment->length)))));
--buffers, offset += segment->length, ++segment)
diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
index 8a4659e9410..bdc6bb262bc 100644
--- a/drivers/scsi/NCR53C9x.c
+++ b/drivers/scsi/NCR53C9x.c
@@ -911,7 +911,7 @@ static void esp_get_dmabufs(struct NCR_ESP *esp, Scsi_Cmnd *sp)
sp->SCp.ptr =
(char *) virt_to_phys(sp->request_buffer);
} else {
- sp->SCp.buffer = (struct scatterlist *) sp->buffer;
+ sp->SCp.buffer = (struct scatterlist *) sp->request_buffer;
sp->SCp.buffers_residual = sp->use_sg - 1;
sp->SCp.this_residual = sp->SCp.buffer->length;
if (esp->dma_mmu_get_scsi_sgl)
@@ -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/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c
index a06f547e87f..d05681f9d81 100644
--- a/drivers/scsi/NCR_D700.c
+++ b/drivers/scsi/NCR_D700.c
@@ -114,7 +114,7 @@ MODULE_DESCRIPTION("NCR Dual700 SCSI Driver");
MODULE_LICENSE("GPL");
module_param(NCR_D700, charp, 0);
-static __u8 __initdata id_array[2*(MCA_MAX_SLOT_NR + 1)] =
+static __u8 __devinitdata id_array[2*(MCA_MAX_SLOT_NR + 1)] =
{ [0 ... 2*(MCA_MAX_SLOT_NR + 1)-1] = 7 };
#ifdef MODULE
@@ -173,7 +173,7 @@ struct NCR_D700_private {
char pad;
};
-static int
+static int __devinit
NCR_D700_probe_one(struct NCR_D700_private *p, int siop, int irq,
int slot, u32 region, int differential)
{
@@ -243,7 +243,7 @@ NCR_D700_intr(int irq, void *data, struct pt_regs *regs)
* essentially connectecd to the MCA bus independently, it is easier
* to set them up as two separate host adapters, rather than one
* adapter with two channels */
-static int
+static int __devinit
NCR_D700_probe(struct device *dev)
{
struct NCR_D700_private *p;
@@ -329,7 +329,7 @@ NCR_D700_probe(struct device *dev)
for (i = 0; i < 2; i++) {
int err;
- if ((err = NCR_D700_probe_one(p, i, slot, irq,
+ if ((err = NCR_D700_probe_one(p, i, irq, slot,
offset_addr + (0x80 * i),
differential)) != 0)
printk("D700: SIOP%d: probe failed, error = %d\n",
@@ -349,7 +349,7 @@ NCR_D700_probe(struct device *dev)
return 0;
}
-static void
+static void __devexit
NCR_D700_remove_one(struct Scsi_Host *host)
{
scsi_remove_host(host);
@@ -359,7 +359,7 @@ NCR_D700_remove_one(struct Scsi_Host *host)
release_region(host->base, 64);
}
-static int
+static int __devexit
NCR_D700_remove(struct device *dev)
{
struct NCR_D700_private *p = dev_get_drvdata(dev);
@@ -380,7 +380,7 @@ static struct mca_driver NCR_D700_driver = {
.name = "NCR_D700",
.bus = &mca_bus_type,
.probe = NCR_D700_probe,
- .remove = NCR_D700_remove,
+ .remove = __devexit_p(NCR_D700_remove),
},
};
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 36e63f82d9f..f974869ea32 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -551,6 +551,11 @@ struct aha152x_hostdata {
struct aha152x_scdata {
Scsi_Cmnd *next; /* next sc in queue */
struct semaphore *sem; /* semaphore to block on */
+ unsigned char cmd_len;
+ unsigned char cmnd[MAX_COMMAND_SIZE];
+ unsigned short use_sg;
+ unsigned request_bufflen;
+ void *request_buffer;
};
@@ -1006,11 +1011,20 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int p
return FAILED;
}
} else {
+ struct aha152x_scdata *sc;
+
SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC);
if(SCpnt->host_scribble==0) {
printk(ERR_LEAD "allocation failed\n", CMDINFO(SCpnt));
return FAILED;
}
+
+ sc = SCDATA(SCpnt);
+ memcpy(sc->cmnd, SCpnt->cmnd, sizeof(sc->cmnd));
+ sc->request_buffer = SCpnt->request_buffer;
+ sc->request_bufflen = SCpnt->request_bufflen;
+ sc->use_sg = SCpnt->use_sg;
+ sc->cmd_len = SCpnt->cmd_len;
}
SCNEXT(SCpnt) = NULL;
@@ -1165,6 +1179,10 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
DECLARE_MUTEX_LOCKED(sem);
struct timer_list timer;
int ret, issued, disconnected;
+ unsigned char old_cmd_len = SCpnt->cmd_len;
+ unsigned short old_use_sg = SCpnt->use_sg;
+ void *old_buffer = SCpnt->request_buffer;
+ unsigned old_bufflen = SCpnt->request_bufflen;
unsigned long flags;
#if defined(AHA152X_DEBUG)
@@ -1198,11 +1216,11 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
add_timer(&timer);
down(&sem);
del_timer(&timer);
-
- SCpnt->cmd_len = SCpnt->old_cmd_len;
- SCpnt->use_sg = SCpnt->old_use_sg;
- SCpnt->request_buffer = SCpnt->buffer;
- SCpnt->request_bufflen = SCpnt->bufflen;
+
+ SCpnt->cmd_len = old_cmd_len;
+ SCpnt->use_sg = old_use_sg;
+ SCpnt->request_buffer = old_buffer;
+ SCpnt->request_bufflen = old_bufflen;
DO_LOCK(flags);
@@ -1565,6 +1583,9 @@ static void busfree_run(struct Scsi_Host *shpnt)
#endif
if(DONE_SC->SCp.phase & check_condition) {
+ struct scsi_cmnd *cmd = HOSTDATA(shpnt)->done_SC;
+ struct aha152x_scdata *sc = SCDATA(cmd);
+
#if 0
if(HOSTDATA(shpnt)->debug & debug_eh) {
printk(ERR_LEAD "received sense: ", CMDINFO(DONE_SC));
@@ -1573,13 +1594,13 @@ static void busfree_run(struct Scsi_Host *shpnt)
#endif
/* restore old command */
- memcpy((void *) DONE_SC->cmnd, (void *) DONE_SC->data_cmnd, sizeof(DONE_SC->data_cmnd));
- DONE_SC->request_buffer = DONE_SC->buffer;
- DONE_SC->request_bufflen = DONE_SC->bufflen;
- DONE_SC->use_sg = DONE_SC->old_use_sg;
- DONE_SC->cmd_len = DONE_SC->old_cmd_len;
+ memcpy(cmd->cmnd, sc->cmnd, sizeof(sc->cmnd));
+ cmd->request_buffer = sc->request_buffer;
+ cmd->request_bufflen = sc->request_bufflen;
+ cmd->use_sg = sc->use_sg;
+ cmd->cmd_len = sc->cmd_len;
- DONE_SC->SCp.Status = 0x02;
+ cmd->SCp.Status = 0x02;
HOSTDATA(shpnt)->commands--;
if (!HOSTDATA(shpnt)->commands)
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 77e7202a0eb..68fd7667a08 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -92,7 +92,9 @@ enum {
HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
/* HOST_CAP bits */
+ HOST_CAP_SSC = (1 << 14), /* Slumber capable */
HOST_CAP_CLO = (1 << 24), /* Command List Override support */
+ HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
@@ -155,6 +157,7 @@ enum {
PORT_CMD_SPIN_UP = (1 << 1), /* Spin up device */
PORT_CMD_START = (1 << 0), /* Enable port DMA engine */
+ PORT_CMD_ICC_MASK = (0xf << 28), /* i/f ICC state mask */
PORT_CMD_ICC_ACTIVE = (0x1 << 28), /* Put i/f in active state */
PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */
PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */
@@ -212,6 +215,10 @@ static void ahci_freeze(struct ata_port *ap);
static void ahci_thaw(struct ata_port *ap);
static void ahci_error_handler(struct ata_port *ap);
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
+static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
+static int ahci_port_resume(struct ata_port *ap);
+static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
+static int ahci_pci_device_resume(struct pci_dev *pdev);
static void ahci_remove_one (struct pci_dev *pdev);
static struct scsi_host_template ahci_sht = {
@@ -231,6 +238,8 @@ static struct scsi_host_template ahci_sht = {
.slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
+ .suspend = ata_scsi_device_suspend,
+ .resume = ata_scsi_device_resume,
};
static const struct ata_port_operations ahci_ops = {
@@ -257,6 +266,9 @@ static const struct ata_port_operations ahci_ops = {
.error_handler = ahci_error_handler,
.post_internal_cmd = ahci_post_internal_cmd,
+ .port_suspend = ahci_port_suspend,
+ .port_resume = ahci_port_resume,
+
.port_start = ahci_port_start,
.port_stop = ahci_port_stop,
};
@@ -350,6 +362,14 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VENDOR_ID_NVIDIA, 0x044f, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* MCP65 */
+ /* SiS */
+ { PCI_VENDOR_ID_SI, 0x1184, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* SiS 966 */
+ { PCI_VENDOR_ID_SI, 0x1185, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* SiS 966 */
+ { PCI_VENDOR_ID_SI, 0x0186, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* SiS 968 */
+
{ } /* terminate list */
};
@@ -358,6 +378,8 @@ static struct pci_driver ahci_pci_driver = {
.name = DRV_NAME,
.id_table = ahci_pci_tbl,
.probe = ahci_init_one,
+ .suspend = ahci_pci_device_suspend,
+ .resume = ahci_pci_device_resume,
.remove = ahci_remove_one,
};
@@ -372,177 +394,288 @@ static inline void __iomem *ahci_port_base (void __iomem *base, unsigned int por
return (void __iomem *) ahci_port_base_ul((unsigned long)base, port);
}
-static int ahci_port_start(struct ata_port *ap)
+static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
{
- struct device *dev = ap->host_set->dev;
- struct ahci_host_priv *hpriv = ap->host_set->private_data;
- struct ahci_port_priv *pp;
- void __iomem *mmio = ap->host_set->mmio_base;
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
- void *mem;
- dma_addr_t mem_dma;
- int rc;
-
- pp = kmalloc(sizeof(*pp), GFP_KERNEL);
- if (!pp)
- return -ENOMEM;
- memset(pp, 0, sizeof(*pp));
+ unsigned int sc_reg;
- rc = ata_pad_alloc(ap, dev);
- if (rc) {
- kfree(pp);
- return rc;
+ switch (sc_reg_in) {
+ case SCR_STATUS: sc_reg = 0; break;
+ case SCR_CONTROL: sc_reg = 1; break;
+ case SCR_ERROR: sc_reg = 2; break;
+ case SCR_ACTIVE: sc_reg = 3; break;
+ default:
+ return 0xffffffffU;
}
- mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
- if (!mem) {
- ata_pad_free(ap, dev);
- kfree(pp);
- return -ENOMEM;
- }
- memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
+ return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+}
- /*
- * First item in chunk of DMA memory: 32-slot command table,
- * 32 bytes each in size
- */
- pp->cmd_slot = mem;
- pp->cmd_slot_dma = mem_dma;
- mem += AHCI_CMD_SLOT_SZ;
- mem_dma += AHCI_CMD_SLOT_SZ;
+static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
+ u32 val)
+{
+ unsigned int sc_reg;
- /*
- * Second item: Received-FIS area
- */
- pp->rx_fis = mem;
- pp->rx_fis_dma = mem_dma;
+ switch (sc_reg_in) {
+ case SCR_STATUS: sc_reg = 0; break;
+ case SCR_CONTROL: sc_reg = 1; break;
+ case SCR_ERROR: sc_reg = 2; break;
+ case SCR_ACTIVE: sc_reg = 3; break;
+ default:
+ return;
+ }
- mem += AHCI_RX_FIS_SZ;
- mem_dma += AHCI_RX_FIS_SZ;
+ writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+}
- /*
- * Third item: data area for storing a single command
- * and its scatter-gather table
- */
- pp->cmd_tbl = mem;
- pp->cmd_tbl_dma = mem_dma;
+static void ahci_start_engine(void __iomem *port_mmio)
+{
+ u32 tmp;
- ap->private_data = pp;
+ /* start DMA */
+ tmp = readl(port_mmio + PORT_CMD);
+ tmp |= PORT_CMD_START;
+ writel(tmp, port_mmio + PORT_CMD);
+ readl(port_mmio + PORT_CMD); /* flush */
+}
- if (hpriv->cap & HOST_CAP_64)
- writel((pp->cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI);
- writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
- readl(port_mmio + PORT_LST_ADDR); /* flush */
+static int ahci_stop_engine(void __iomem *port_mmio)
+{
+ u32 tmp;
- if (hpriv->cap & HOST_CAP_64)
- writel((pp->rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI);
- writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
- readl(port_mmio + PORT_FIS_ADDR); /* flush */
+ tmp = readl(port_mmio + PORT_CMD);
- writel(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
- PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
- PORT_CMD_START, port_mmio + PORT_CMD);
- readl(port_mmio + PORT_CMD); /* flush */
+ /* check if the HBA is idle */
+ if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
+ return 0;
+
+ /* setting HBA to idle */
+ tmp &= ~PORT_CMD_START;
+ writel(tmp, port_mmio + PORT_CMD);
+
+ /* wait for engine to stop. This could be as long as 500 msec */
+ tmp = ata_wait_register(port_mmio + PORT_CMD,
+ PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
+ if (tmp & PORT_CMD_LIST_ON)
+ return -EIO;
return 0;
}
+static void ahci_start_fis_rx(void __iomem *port_mmio, u32 cap,
+ dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
+{
+ u32 tmp;
-static void ahci_port_stop(struct ata_port *ap)
+ /* set FIS registers */
+ if (cap & HOST_CAP_64)
+ writel((cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI);
+ writel(cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
+
+ if (cap & HOST_CAP_64)
+ writel((rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI);
+ writel(rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
+
+ /* enable FIS reception */
+ tmp = readl(port_mmio + PORT_CMD);
+ tmp |= PORT_CMD_FIS_RX;
+ writel(tmp, port_mmio + PORT_CMD);
+
+ /* flush */
+ readl(port_mmio + PORT_CMD);
+}
+
+static int ahci_stop_fis_rx(void __iomem *port_mmio)
{
- struct device *dev = ap->host_set->dev;
- struct ahci_port_priv *pp = ap->private_data;
- void __iomem *mmio = ap->host_set->mmio_base;
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
u32 tmp;
+ /* disable FIS reception */
tmp = readl(port_mmio + PORT_CMD);
- tmp &= ~(PORT_CMD_START | PORT_CMD_FIS_RX);
+ tmp &= ~PORT_CMD_FIS_RX;
writel(tmp, port_mmio + PORT_CMD);
- readl(port_mmio + PORT_CMD); /* flush */
- /* spec says 500 msecs for each PORT_CMD_{START,FIS_RX} bit, so
- * this is slightly incorrect.
- */
- msleep(500);
+ /* wait for completion, spec says 500ms, give it 1000 */
+ tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
+ PORT_CMD_FIS_ON, 10, 1000);
+ if (tmp & PORT_CMD_FIS_ON)
+ return -EBUSY;
- ap->private_data = NULL;
- dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
- pp->cmd_slot, pp->cmd_slot_dma);
- ata_pad_free(ap, dev);
- kfree(pp);
+ return 0;
}
-static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
+static void ahci_power_up(void __iomem *port_mmio, u32 cap)
{
- unsigned int sc_reg;
+ u32 cmd;
- switch (sc_reg_in) {
- case SCR_STATUS: sc_reg = 0; break;
- case SCR_CONTROL: sc_reg = 1; break;
- case SCR_ERROR: sc_reg = 2; break;
- case SCR_ACTIVE: sc_reg = 3; break;
- default:
- return 0xffffffffU;
+ cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
+
+ /* spin up device */
+ if (cap & HOST_CAP_SSS) {
+ cmd |= PORT_CMD_SPIN_UP;
+ writel(cmd, port_mmio + PORT_CMD);
}
- return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ /* wake up link */
+ writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
}
+static void ahci_power_down(void __iomem *port_mmio, u32 cap)
+{
+ u32 cmd, scontrol;
-static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
- u32 val)
+ cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
+
+ if (cap & HOST_CAP_SSC) {
+ /* enable transitions to slumber mode */
+ scontrol = readl(port_mmio + PORT_SCR_CTL);
+ if ((scontrol & 0x0f00) > 0x100) {
+ scontrol &= ~0xf00;
+ writel(scontrol, port_mmio + PORT_SCR_CTL);
+ }
+
+ /* put device into slumber mode */
+ writel(cmd | PORT_CMD_ICC_SLUMBER, port_mmio + PORT_CMD);
+
+ /* wait for the transition to complete */
+ ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_ICC_SLUMBER,
+ PORT_CMD_ICC_SLUMBER, 1, 50);
+ }
+
+ /* put device into listen mode */
+ if (cap & HOST_CAP_SSS) {
+ /* first set PxSCTL.DET to 0 */
+ scontrol = readl(port_mmio + PORT_SCR_CTL);
+ scontrol &= ~0xf;
+ writel(scontrol, port_mmio + PORT_SCR_CTL);
+
+ /* then set PxCMD.SUD to 0 */
+ cmd &= ~PORT_CMD_SPIN_UP;
+ writel(cmd, port_mmio + PORT_CMD);
+ }
+}
+
+static void ahci_init_port(void __iomem *port_mmio, u32 cap,
+ dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
{
- unsigned int sc_reg;
+ /* power up */
+ ahci_power_up(port_mmio, cap);
- switch (sc_reg_in) {
- case SCR_STATUS: sc_reg = 0; break;
- case SCR_CONTROL: sc_reg = 1; break;
- case SCR_ERROR: sc_reg = 2; break;
- case SCR_ACTIVE: sc_reg = 3; break;
- default:
- return;
+ /* enable FIS reception */
+ ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma);
+
+ /* enable DMA */
+ ahci_start_engine(port_mmio);
+}
+
+static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg)
+{
+ int rc;
+
+ /* disable DMA */
+ rc = ahci_stop_engine(port_mmio);
+ if (rc) {
+ *emsg = "failed to stop engine";
+ return rc;
}
- writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ /* disable FIS reception */
+ rc = ahci_stop_fis_rx(port_mmio);
+ if (rc) {
+ *emsg = "failed stop FIS RX";
+ return rc;
+ }
+
+ /* put device into slumber mode */
+ ahci_power_down(port_mmio, cap);
+
+ return 0;
}
-static int ahci_stop_engine(struct ata_port *ap)
+static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
{
- void __iomem *mmio = ap->host_set->mmio_base;
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
- int work;
- u32 tmp;
+ u32 cap_save, tmp;
- tmp = readl(port_mmio + PORT_CMD);
- tmp &= ~PORT_CMD_START;
- writel(tmp, port_mmio + PORT_CMD);
+ cap_save = readl(mmio + HOST_CAP);
+ cap_save &= ( (1<<28) | (1<<17) );
+ cap_save |= (1 << 27);
- /* wait for engine to stop. TODO: this could be
- * as long as 500 msec
+ /* global controller reset */
+ tmp = readl(mmio + HOST_CTL);
+ if ((tmp & HOST_RESET) == 0) {
+ writel(tmp | HOST_RESET, mmio + HOST_CTL);
+ readl(mmio + HOST_CTL); /* flush */
+ }
+
+ /* reset must complete within 1 second, or
+ * the hardware should be considered fried.
*/
- work = 1000;
- while (work-- > 0) {
- tmp = readl(port_mmio + PORT_CMD);
- if ((tmp & PORT_CMD_LIST_ON) == 0)
- return 0;
- udelay(10);
+ ssleep(1);
+
+ tmp = readl(mmio + HOST_CTL);
+ if (tmp & HOST_RESET) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "controller reset failed (0x%x)\n", tmp);
+ return -EIO;
+ }
+
+ writel(HOST_AHCI_EN, mmio + HOST_CTL);
+ (void) readl(mmio + HOST_CTL); /* flush */
+ writel(cap_save, mmio + HOST_CAP);
+ writel(0xf, mmio + HOST_PORTS_IMPL);
+ (void) readl(mmio + HOST_PORTS_IMPL); /* flush */
+
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
+ u16 tmp16;
+
+ /* configure PCS */
+ pci_read_config_word(pdev, 0x92, &tmp16);
+ tmp16 |= 0xf;
+ pci_write_config_word(pdev, 0x92, tmp16);
}
- return -EIO;
+ return 0;
}
-static void ahci_start_engine(struct ata_port *ap)
+static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
+ int n_ports, u32 cap)
{
- void __iomem *mmio = ap->host_set->mmio_base;
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+ int i, rc;
u32 tmp;
- tmp = readl(port_mmio + PORT_CMD);
- tmp |= PORT_CMD_START;
- writel(tmp, port_mmio + PORT_CMD);
- readl(port_mmio + PORT_CMD); /* flush */
+ for (i = 0; i < n_ports; i++) {
+ void __iomem *port_mmio = ahci_port_base(mmio, i);
+ const char *emsg = NULL;
+
+#if 0 /* BIOSen initialize this incorrectly */
+ if (!(hpriv->port_map & (1 << i)))
+ continue;
+#endif
+
+ /* make sure port is not active */
+ rc = ahci_deinit_port(port_mmio, cap, &emsg);
+ if (rc)
+ dev_printk(KERN_WARNING, &pdev->dev,
+ "%s (%d)\n", emsg, rc);
+
+ /* clear SError */
+ tmp = readl(port_mmio + PORT_SCR_ERR);
+ VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
+ writel(tmp, port_mmio + PORT_SCR_ERR);
+
+ /* clear port IRQ */
+ tmp = readl(port_mmio + PORT_IRQ_STAT);
+ VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
+ if (tmp)
+ writel(tmp, port_mmio + PORT_IRQ_STAT);
+
+ writel(1 << i, mmio + HOST_IRQ_STAT);
+ }
+
+ tmp = readl(mmio + HOST_CTL);
+ VPRINTK("HOST_CTL 0x%x\n", tmp);
+ writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
+ tmp = readl(mmio + HOST_CTL);
+ VPRINTK("HOST_CTL 0x%x\n", tmp);
}
static unsigned int ahci_dev_classify(struct ata_port *ap)
@@ -626,7 +759,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
}
/* prepare for SRST (AHCI-1.1 10.4.1) */
- rc = ahci_stop_engine(ap);
+ rc = ahci_stop_engine(port_mmio);
if (rc) {
reason = "failed to stop engine";
goto fail_restart;
@@ -647,7 +780,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
}
/* restart engine */
- ahci_start_engine(ap);
+ ahci_start_engine(port_mmio);
ata_tf_init(ap->device, &tf);
fis = pp->cmd_tbl;
@@ -706,7 +839,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
return 0;
fail_restart:
- ahci_start_engine(ap);
+ ahci_start_engine(port_mmio);
fail:
ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
return rc;
@@ -717,11 +850,13 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
struct ahci_port_priv *pp = ap->private_data;
u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
struct ata_taskfile tf;
+ void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
int rc;
DPRINTK("ENTER\n");
- ahci_stop_engine(ap);
+ ahci_stop_engine(port_mmio);
/* clear D2H reception area to properly wait for D2H FIS */
ata_tf_init(ap->device, &tf);
@@ -730,7 +865,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
rc = sata_std_hardreset(ap, class);
- ahci_start_engine(ap);
+ ahci_start_engine(port_mmio);
if (rc == 0 && ata_port_online(ap))
*class = ahci_dev_classify(ap);
@@ -940,14 +1075,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 "
@@ -1052,10 +1181,13 @@ static void ahci_thaw(struct ata_port *ap)
static void ahci_error_handler(struct ata_port *ap)
{
+ void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+
if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
/* restart engine */
- ahci_stop_engine(ap);
- ahci_start_engine(ap);
+ ahci_stop_engine(port_mmio);
+ ahci_start_engine(port_mmio);
}
/* perform recovery */
@@ -1066,15 +1198,176 @@ static void ahci_error_handler(struct ata_port *ap)
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
+ void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
if (qc->flags & ATA_QCFLAG_FAILED)
qc->err_mask |= AC_ERR_OTHER;
if (qc->err_mask) {
/* make DMA engine forget about the failed command */
- ahci_stop_engine(ap);
- ahci_start_engine(ap);
+ ahci_stop_engine(port_mmio);
+ ahci_start_engine(port_mmio);
+ }
+}
+
+static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
+{
+ struct ahci_host_priv *hpriv = ap->host_set->private_data;
+ struct ahci_port_priv *pp = ap->private_data;
+ void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+ const char *emsg = NULL;
+ int rc;
+
+ rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
+ if (rc) {
+ ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
+ ahci_init_port(port_mmio, hpriv->cap,
+ pp->cmd_slot_dma, pp->rx_fis_dma);
+ }
+
+ return rc;
+}
+
+static int ahci_port_resume(struct ata_port *ap)
+{
+ struct ahci_port_priv *pp = ap->private_data;
+ struct ahci_host_priv *hpriv = ap->host_set->private_data;
+ void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+
+ ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
+
+ return 0;
+}
+
+static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+ struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
+ void __iomem *mmio = host_set->mmio_base;
+ u32 ctl;
+
+ if (mesg.event == PM_EVENT_SUSPEND) {
+ /* AHCI spec rev1.1 section 8.3.3:
+ * Software must disable interrupts prior to requesting a
+ * transition of the HBA to D3 state.
+ */
+ ctl = readl(mmio + HOST_CTL);
+ ctl &= ~HOST_IRQ_EN;
+ writel(ctl, mmio + HOST_CTL);
+ readl(mmio + HOST_CTL); /* flush */
}
+
+ return ata_pci_device_suspend(pdev, mesg);
+}
+
+static int ahci_pci_device_resume(struct pci_dev *pdev)
+{
+ struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
+ struct ahci_host_priv *hpriv = host_set->private_data;
+ void __iomem *mmio = host_set->mmio_base;
+ int rc;
+
+ ata_pci_device_do_resume(pdev);
+
+ if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
+ rc = ahci_reset_controller(mmio, pdev);
+ if (rc)
+ return rc;
+
+ ahci_init_controller(mmio, pdev, host_set->n_ports, hpriv->cap);
+ }
+
+ ata_host_set_resume(host_set);
+
+ return 0;
+}
+
+static int ahci_port_start(struct ata_port *ap)
+{
+ struct device *dev = ap->host_set->dev;
+ struct ahci_host_priv *hpriv = ap->host_set->private_data;
+ struct ahci_port_priv *pp;
+ void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+ void *mem;
+ dma_addr_t mem_dma;
+ int rc;
+
+ pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+ if (!pp)
+ return -ENOMEM;
+ memset(pp, 0, sizeof(*pp));
+
+ rc = ata_pad_alloc(ap, dev);
+ if (rc) {
+ kfree(pp);
+ return rc;
+ }
+
+ mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
+ if (!mem) {
+ ata_pad_free(ap, dev);
+ kfree(pp);
+ return -ENOMEM;
+ }
+ memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
+
+ /*
+ * First item in chunk of DMA memory: 32-slot command table,
+ * 32 bytes each in size
+ */
+ pp->cmd_slot = mem;
+ pp->cmd_slot_dma = mem_dma;
+
+ mem += AHCI_CMD_SLOT_SZ;
+ mem_dma += AHCI_CMD_SLOT_SZ;
+
+ /*
+ * Second item: Received-FIS area
+ */
+ pp->rx_fis = mem;
+ pp->rx_fis_dma = mem_dma;
+
+ mem += AHCI_RX_FIS_SZ;
+ mem_dma += AHCI_RX_FIS_SZ;
+
+ /*
+ * Third item: data area for storing a single command
+ * and its scatter-gather table
+ */
+ pp->cmd_tbl = mem;
+ pp->cmd_tbl_dma = mem_dma;
+
+ ap->private_data = pp;
+
+ /* initialize port */
+ ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
+
+ return 0;
+}
+
+static void ahci_port_stop(struct ata_port *ap)
+{
+ struct device *dev = ap->host_set->dev;
+ struct ahci_host_priv *hpriv = ap->host_set->private_data;
+ struct ahci_port_priv *pp = ap->private_data;
+ void __iomem *mmio = ap->host_set->mmio_base;
+ void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+ const char *emsg = NULL;
+ int rc;
+
+ /* de-initialize port */
+ rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
+ if (rc)
+ ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
+
+ ap->private_data = NULL;
+ dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
+ pp->cmd_slot, pp->cmd_slot_dma);
+ ata_pad_free(ap, dev);
+ kfree(pp);
}
static void ahci_setup_port(struct ata_ioports *port, unsigned long base,
@@ -1095,47 +1388,12 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
struct ahci_host_priv *hpriv = probe_ent->private_data;
struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
void __iomem *mmio = probe_ent->mmio_base;
- u32 tmp, cap_save;
- unsigned int i, j, using_dac;
+ unsigned int i, using_dac;
int rc;
- void __iomem *port_mmio;
- cap_save = readl(mmio + HOST_CAP);
- cap_save &= ( (1<<28) | (1<<17) );
- cap_save |= (1 << 27);
-
- /* global controller reset */
- tmp = readl(mmio + HOST_CTL);
- if ((tmp & HOST_RESET) == 0) {
- writel(tmp | HOST_RESET, mmio + HOST_CTL);
- readl(mmio + HOST_CTL); /* flush */
- }
-
- /* reset must complete within 1 second, or
- * the hardware should be considered fried.
- */
- ssleep(1);
-
- tmp = readl(mmio + HOST_CTL);
- if (tmp & HOST_RESET) {
- dev_printk(KERN_ERR, &pdev->dev,
- "controller reset failed (0x%x)\n", tmp);
- return -EIO;
- }
-
- writel(HOST_AHCI_EN, mmio + HOST_CTL);
- (void) readl(mmio + HOST_CTL); /* flush */
- writel(cap_save, mmio + HOST_CAP);
- writel(0xf, mmio + HOST_PORTS_IMPL);
- (void) readl(mmio + HOST_PORTS_IMPL); /* flush */
-
- if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
- u16 tmp16;
-
- pci_read_config_word(pdev, 0x92, &tmp16);
- tmp16 |= 0xf;
- pci_write_config_word(pdev, 0x92, tmp16);
- }
+ rc = ahci_reset_controller(mmio, pdev);
+ if (rc)
+ return rc;
hpriv->cap = readl(mmio + HOST_CAP);
hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
@@ -1171,63 +1429,10 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
}
}
- for (i = 0; i < probe_ent->n_ports; i++) {
-#if 0 /* BIOSen initialize this incorrectly */
- if (!(hpriv->port_map & (1 << i)))
- continue;
-#endif
-
- port_mmio = ahci_port_base(mmio, i);
- VPRINTK("mmio %p port_mmio %p\n", mmio, port_mmio);
-
- ahci_setup_port(&probe_ent->port[i],
- (unsigned long) mmio, i);
-
- /* make sure port is not active */
- tmp = readl(port_mmio + PORT_CMD);
- VPRINTK("PORT_CMD 0x%x\n", tmp);
- if (tmp & (PORT_CMD_LIST_ON | PORT_CMD_FIS_ON |
- PORT_CMD_FIS_RX | PORT_CMD_START)) {
- tmp &= ~(PORT_CMD_LIST_ON | PORT_CMD_FIS_ON |
- PORT_CMD_FIS_RX | PORT_CMD_START);
- writel(tmp, port_mmio + PORT_CMD);
- readl(port_mmio + PORT_CMD); /* flush */
-
- /* spec says 500 msecs for each bit, so
- * this is slightly incorrect.
- */
- msleep(500);
- }
-
- writel(PORT_CMD_SPIN_UP, port_mmio + PORT_CMD);
-
- j = 0;
- while (j < 100) {
- msleep(10);
- tmp = readl(port_mmio + PORT_SCR_STAT);
- if ((tmp & 0xf) == 0x3)
- break;
- j++;
- }
-
- tmp = readl(port_mmio + PORT_SCR_ERR);
- VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
- writel(tmp, port_mmio + PORT_SCR_ERR);
+ for (i = 0; i < probe_ent->n_ports; i++)
+ ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i);
- /* ack any pending irq events for this port */
- tmp = readl(port_mmio + PORT_IRQ_STAT);
- VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
- if (tmp)
- writel(tmp, port_mmio + PORT_IRQ_STAT);
-
- writel(1 << i, mmio + HOST_IRQ_STAT);
- }
-
- tmp = readl(mmio + HOST_CTL);
- VPRINTK("HOST_CTL 0x%x\n", tmp);
- writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
- tmp = readl(mmio + HOST_CTL);
- VPRINTK("HOST_CTL 0x%x\n", tmp);
+ ahci_init_controller(mmio, pdev, probe_ent->n_ports, hpriv->cap);
pci_set_master(pdev);
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index a1e8ca75859..653818d2f80 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -7289,7 +7289,7 @@ ahd_reset_cmds_pending(struct ahd_softc *ahd)
ahd->flags &= ~AHD_UPDATE_PEND_CMDS;
}
-void
+static void
ahd_done_with_status(struct ahd_softc *ahd, struct scb *scb, uint32_t status)
{
cam_status ostat;
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index b244c712417..998999c0a97 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -243,25 +243,6 @@ ahd_print_path(struct ahd_softc *ahd, struct scb *scb)
static uint32_t aic79xx_no_reset;
/*
- * Certain PCI motherboards will scan PCI devices from highest to lowest,
- * others scan from lowest to highest, and they tend to do all kinds of
- * strange things when they come into contact with PCI bridge chips. The
- * net result of all this is that the PCI card that is actually used to boot
- * the machine is very hard to detect. Most motherboards go from lowest
- * PCI slot number to highest, and the first SCSI controller found is the
- * one you boot from. The only exceptions to this are when a controller
- * has its BIOS disabled. So, we by default sort all of our SCSI controllers
- * from lowest PCI slot number to highest PCI slot number. We also force
- * all controllers with their BIOS disabled to the end of the list. This
- * works on *almost* all computers. Where it doesn't work, we have this
- * option. Setting this option to non-0 will reverse the order of the sort
- * to highest first, then lowest, but will still leave cards with their BIOS
- * disabled at the very end. That should fix everyone up unless there are
- * really strange cirumstances.
- */
-static uint32_t aic79xx_reverse_scan;
-
-/*
* Should we force EXTENDED translation on a controller.
* 0 == Use whatever is in the SEEPROM or default to off
* 1 == Use whatever is in the SEEPROM or default to on
@@ -350,7 +331,6 @@ MODULE_PARM_DESC(aic79xx,
" periodically to prevent tag starvation.\n"
" This may be required by some older disk\n"
" or drives/RAID arrays.\n"
-" reverse_scan Sort PCI devices highest Bus/Slot to lowest\n"
" tag_info:<tag_str> Set per-target tag depth\n"
" global_tag_depth:<int> Global tag depth for all targets on all buses\n"
" slewrate:<slewrate_list>Set the signal slew rate (0-15).\n"
@@ -1031,7 +1011,6 @@ aic79xx_setup(char *s)
#ifdef AHD_DEBUG
{ "debug", &ahd_debug },
#endif
- { "reverse_scan", &aic79xx_reverse_scan },
{ "periodic_otag", &aic79xx_periodic_otag },
{ "pci_parity", &aic79xx_pci_parity },
{ "seltime", &aic79xx_seltime },
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index debf3e2a079..aa4be8a3141 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -353,7 +353,6 @@ MODULE_PARM_DESC(aic7xxx,
" periodically to prevent tag starvation.\n"
" This may be required by some older disk\n"
" drives or RAID arrays.\n"
-" reverse_scan Sort PCI devices highest Bus/Slot to lowest\n"
" tag_info:<tag_str> Set per-target tag depth\n"
" global_tag_depth:<int> Global tag depth for every target\n"
" on every bus\n"
diff --git a/drivers/scsi/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile
index 8c91fda6482..b98c5c1056c 100644
--- a/drivers/scsi/aic7xxx/aicasm/Makefile
+++ b/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/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index 3e1053f111d..4cf7afc31cc 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/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/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 19745a31072..501755a606e 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -487,7 +487,7 @@ static void piix_pata_cbl_detect(struct ata_port *ap)
goto cbl40;
/* check BIOS cable detect results */
- mask = ap->hard_port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
+ mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
pci_read_config_byte(pdev, PIIX_IOCFG, &tmp);
if ((tmp & mask) == 0)
goto cbl40;
@@ -513,7 +513,7 @@ static int piix_pata_prereset(struct ata_port *ap)
{
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
- if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) {
+ if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) {
ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n");
ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
return 0;
@@ -550,7 +550,7 @@ static int piix_sata_prereset(struct ata_port *ap)
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
struct piix_host_priv *hpriv = ap->host_set->private_data;
const unsigned int *map = hpriv->map;
- int base = 2 * ap->hard_port_no;
+ int base = 2 * ap->port_no;
unsigned int present = 0;
int port, i;
u16 pcs;
@@ -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");
@@ -601,7 +601,7 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
unsigned int pio = adev->pio_mode - XFER_PIO_0;
struct pci_dev *dev = to_pci_dev(ap->host_set->dev);
unsigned int is_slave = (adev->devno != 0);
- unsigned int master_port= ap->hard_port_no ? 0x42 : 0x40;
+ unsigned int master_port= ap->port_no ? 0x42 : 0x40;
unsigned int slave_port = 0x44;
u16 master_data;
u8 slave_data;
@@ -619,10 +619,10 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
/* enable PPE, IE and TIME */
master_data |= 0x0070;
pci_read_config_byte(dev, slave_port, &slave_data);
- slave_data &= (ap->hard_port_no ? 0x0f : 0xf0);
+ slave_data &= (ap->port_no ? 0x0f : 0xf0);
slave_data |=
(timings[pio][0] << 2) |
- (timings[pio][1] << (ap->hard_port_no ? 4 : 0));
+ (timings[pio][1] << (ap->port_no ? 4 : 0));
} else {
master_data &= 0xccf8;
/* enable PPE, IE and TIME */
@@ -652,9 +652,9 @@ static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
{
unsigned int udma = adev->dma_mode; /* FIXME: MWDMA too */
struct pci_dev *dev = to_pci_dev(ap->host_set->dev);
- u8 maslave = ap->hard_port_no ? 0x42 : 0x40;
+ u8 maslave = ap->port_no ? 0x42 : 0x40;
u8 speed = udma;
- unsigned int drive_dn = (ap->hard_port_no ? 2 : 0) + adev->devno;
+ unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno;
int a_speed = 3 << (drive_dn * 4);
int u_flag = 1 << drive_dn;
int v_flag = 0x01 << drive_dn;
@@ -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;
@@ -931,8 +932,6 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
static void piix_host_stop(struct ata_host_set *host_set)
{
- if (host_set->next == NULL)
- kfree(host_set->private_data);
ata_host_stop(host_set);
}
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index 007a14e5c3f..e397129c90d 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -507,7 +507,7 @@ static __inline__ void initialize_SCp(Scsi_Cmnd *cmd)
*/
if (cmd->use_sg) {
- cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;
+ cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
cmd->SCp.buffers_residual = cmd->use_sg - 1;
cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page)+
cmd->SCp.buffer->offset;
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index dddd2acce76..61f6024b61b 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -5,6 +5,7 @@
* Additions for SCSI 3+ (SPC-3 T10/1416-D Rev 07 3 May 2002)
* by D. Gilbert and aeb (20020609)
* Additions for SPC-3 T10/1416-D Rev 21 22 Sept 2004, D. Gilbert 20041025
+ * Update to SPC-4 T10/1713-D Rev 5a, 14 June 2006, D. Gilbert 20060702
*/
#include <linux/blkdev.h>
@@ -36,55 +37,56 @@ static const char * cdb_byte0_names[] = {
/* 00-03 */ "Test Unit Ready", "Rezero Unit/Rewind", NULL, "Request Sense",
/* 04-07 */ "Format Unit/Medium", "Read Block Limits", NULL,
"Reasssign Blocks",
-/* 08-0d */ "Read (6)", NULL, "Write (6)", "Seek (6)", NULL, NULL,
+/* 08-0d */ "Read(6)", NULL, "Write(6)", "Seek(6)", NULL, NULL,
/* 0e-12 */ NULL, "Read Reverse", "Write Filemarks", "Space", "Inquiry",
-/* 13-16 */ "Verify (6)", "Recover Buffered Data", "Mode Select (6)",
- "Reserve (6)",
-/* 17-1a */ "Release (6)", "Copy", "Erase", "Mode Sense (6)",
+/* 13-16 */ "Verify(6)", "Recover Buffered Data", "Mode Select(6)",
+ "Reserve(6)",
+/* 17-1a */ "Release(6)", "Copy", "Erase", "Mode Sense(6)",
/* 1b-1d */ "Start/Stop Unit", "Receive Diagnostic", "Send Diagnostic",
/* 1e-1f */ "Prevent/Allow Medium Removal", NULL,
/* 20-22 */ NULL, NULL, NULL,
/* 23-28 */ "Read Format Capacities", "Set Window",
- "Read Capacity (10)", NULL, NULL, "Read (10)",
-/* 29-2d */ "Read Generation", "Write (10)", "Seek (10)", "Erase (10)",
- "Read updated block",
-/* 2e-31 */ "Write Verify (10)", "Verify (10)", "Search High", "Search Equal",
+ "Read Capacity(10)", NULL, NULL, "Read(10)",
+/* 29-2d */ "Read Generation", "Write(10)", "Seek(10)", "Erase(10)",
+ "Read updated block",
+/* 2e-31 */ "Write Verify(10)", "Verify(10)", "Search High", "Search Equal",
/* 32-34 */ "Search Low", "Set Limits", "Prefetch/Read Position",
-/* 35-37 */ "Synchronize Cache (10)", "Lock/Unlock Cache (10)",
+/* 35-37 */ "Synchronize Cache(10)", "Lock/Unlock Cache(10)",
"Read Defect Data(10)",
/* 38-3c */ "Medium Scan", "Compare", "Copy Verify", "Write Buffer",
"Read Buffer",
-/* 3d-3f */ "Update Block", "Read Long (10)", "Write Long (10)",
-/* 40-41 */ "Change Definition", "Write Same (10)",
+/* 3d-3f */ "Update Block", "Read Long(10)", "Write Long(10)",
+/* 40-41 */ "Change Definition", "Write Same(10)",
/* 42-48 */ "Read sub-channel", "Read TOC/PMA/ATIP", "Read density support",
- "Play audio (10)", "Get configuration", "Play audio msf",
+ "Play audio(10)", "Get configuration", "Play audio msf",
"Play audio track/index",
-/* 49-4f */ "Play track relative (10)", "Get event status notification",
+/* 49-4f */ "Play track relative(10)", "Get event status notification",
"Pause/resume", "Log Select", "Log Sense", "Stop play/scan",
NULL,
/* 50-55 */ "Xdwrite", "Xpwrite, Read disk info", "Xdread, Read track info",
- "Reserve track", "Send OPC info", "Mode Select (10)",
-/* 56-5b */ "Reserve (10)", "Release (10)", "Repair track", "Read master cue",
- "Mode Sense (10)", "Close track/session",
+ "Reserve track", "Send OPC info", "Mode Select(10)",
+/* 56-5b */ "Reserve(10)", "Release(10)", "Repair track", "Read master cue",
+ "Mode Sense(10)", "Close track/session",
/* 5c-5f */ "Read buffer capacity", "Send cue sheet", "Persistent reserve in",
"Persistent reserve out",
/* 60-67 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* 68-6f */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* 70-77 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* 78-7f */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Variable length",
-/* 80-84 */ "Xdwrite (16)", "Rebuild (16)", "Regenerate (16)", "Extended copy",
+/* 80-84 */ "Xdwrite(16)", "Rebuild(16)", "Regenerate(16)", "Extended copy",
"Receive copy results",
-/* 85-89 */ "Memory Export In (16)", "Access control in", "Access control out",
- "Read (16)", "Memory Export Out (16)",
-/* 8a-8f */ "Write (16)", NULL, "Read attributes", "Write attributes",
- "Write and verify (16)", "Verify (16)",
-/* 90-94 */ "Pre-fetch (16)", "Synchronize cache (16)",
- "Lock/unlock cache (16)", "Write same (16)", NULL,
+/* 85-89 */ "ATA command pass through(16)", "Access control in",
+ "Access control out", "Read(16)", "Memory Export Out(16)",
+/* 8a-8f */ "Write(16)", NULL, "Read attributes", "Write attributes",
+ "Write and verify(16)", "Verify(16)",
+/* 90-94 */ "Pre-fetch(16)", "Synchronize cache(16)",
+ "Lock/unlock cache(16)", "Write same(16)", NULL,
/* 95-99 */ NULL, NULL, NULL, NULL, NULL,
-/* 9a-9f */ NULL, NULL, NULL, NULL, "Service action in (16)",
- "Service action out (16)",
-/* a0-a5 */ "Report luns", "Blank", "Send event", "Maintenance in",
- "Maintenance out", "Move medium/play audio(12)",
+/* 9a-9f */ NULL, NULL, NULL, NULL, "Service action in(16)",
+ "Service action out(16)",
+/* a0-a5 */ "Report luns", "ATA command pass through(12)/Blank",
+ "Security protocol in", "Maintenance in", "Maintenance out",
+ "Move medium/play audio(12)",
/* a6-a9 */ "Exchange medium", "Move medium attached", "Read(12)",
"Play track relative(12)",
/* aa-ae */ "Write(12)", NULL, "Erase(12), Get Performance",
@@ -92,12 +94,12 @@ static const char * cdb_byte0_names[] = {
/* af-b1 */ "Verify(12)", "Search data high(12)", "Search data equal(12)",
/* b2-b4 */ "Search data low(12)", "Set limits(12)",
"Read element status attached",
-/* b5-b6 */ "Request volume element address", "Send volume tag, set streaming",
+/* b5-b6 */ "Security protocol out", "Send volume tag, set streaming",
/* b7-b9 */ "Read defect data(12)", "Read element status", "Read CD msf",
/* ba-bc */ "Redundancy group (in), Scan",
- "Redundancy group (out), Set cd-rom speed", "Spare in, Play cd",
-/* bd-bf */ "Spare out, Mechanism status", "Volume set in, Read cd",
- "Volume set out, Send DVD structure",
+ "Redundancy group (out), Set cd-rom speed", "Spare (in), Play cd",
+/* bd-bf */ "Spare (out), Mechanism status", "Volume set (in), Read cd",
+ "Volume set (out), Send DVD structure",
};
struct value_name_pair {
@@ -112,6 +114,7 @@ static const struct value_name_pair maint_in_arr[] = {
{0xc, "Report supported operation codes"},
{0xd, "Report supported task management functions"},
{0xe, "Report priority"},
+ {0xf, "Report timestamp"},
};
#define MAINT_IN_SZ ARRAY_SIZE(maint_in_arr)
@@ -120,6 +123,7 @@ static const struct value_name_pair maint_out_arr[] = {
{0xa, "Set target port groups"},
{0xb, "Change aliases"},
{0xe, "Set priority"},
+ {0xe, "Set timestamp"},
};
#define MAINT_OUT_SZ ARRAY_SIZE(maint_out_arr)
@@ -427,6 +431,7 @@ static struct error_info additional[] =
{0x001A, "Rewind operation in progress"},
{0x001B, "Set capacity operation in progress"},
{0x001C, "Verify operation in progress"},
+ {0x001D, "ATA pass through information available"},
{0x0100, "No index/sector signal"},
@@ -438,7 +443,7 @@ static struct error_info additional[] =
{0x0400, "Logical unit not ready, cause not reportable"},
{0x0401, "Logical unit is in process of becoming ready"},
- {0x0402, "Logical unit not ready, initializing cmd. required"},
+ {0x0402, "Logical unit not ready, initializing command required"},
{0x0403, "Logical unit not ready, manual intervention required"},
{0x0404, "Logical unit not ready, format in progress"},
{0x0405, "Logical unit not ready, rebuild in progress"},
@@ -478,6 +483,9 @@ static struct error_info additional[] =
{0x0B00, "Warning"},
{0x0B01, "Warning - specified temperature exceeded"},
{0x0B02, "Warning - enclosure degraded"},
+ {0x0B03, "Warning - background self-test failed"},
+ {0x0B04, "Warning - background pre-scan detected medium error"},
+ {0x0B05, "Warning - background medium scan detected medium error"},
{0x0C00, "Write error"},
{0x0C01, "Write error - recovered with auto reallocation"},
@@ -493,6 +501,7 @@ static struct error_info additional[] =
{0x0C0B, "Auxiliary memory write error"},
{0x0C0C, "Write error - unexpected unsolicited data"},
{0x0C0D, "Write error - not enough unsolicited data"},
+ {0x0C0F, "Defects in error window"},
{0x0D00, "Error detected by third party temporary initiator"},
{0x0D01, "Third party device failure"},
@@ -504,11 +513,12 @@ static struct error_info additional[] =
{0x0E00, "Invalid information unit"},
{0x0E01, "Information unit too short"},
{0x0E02, "Information unit too long"},
+ {0x0E03, "Invalid field in command information unit"},
{0x1000, "Id CRC or ECC error"},
- {0x1001, "Data block guard check failed"},
- {0x1002, "Data block application tag check failed"},
- {0x1003, "Data block reference tag check failed"},
+ {0x1001, "Logical block guard check failed"},
+ {0x1002, "Logical block application tag check failed"},
+ {0x1003, "Logical block reference tag check failed"},
{0x1100, "Unrecovered read error"},
{0x1101, "Read retries exhausted"},
@@ -530,6 +540,7 @@ static struct error_info additional[] =
{0x1111, "Read error - loss of streaming"},
{0x1112, "Auxiliary memory read error"},
{0x1113, "Read error - failed retransmission request"},
+ {0x1114, "Read error - lba marked bad by application client"},
{0x1200, "Address mark not found for id field"},
@@ -610,11 +621,14 @@ static struct error_info additional[] =
{0x2100, "Logical block address out of range"},
{0x2101, "Invalid element address"},
{0x2102, "Invalid address for write"},
+ {0x2103, "Invalid write crossing layer jump"},
{0x2200, "Illegal function (use 20 00, 24 00, or 26 00)"},
{0x2400, "Invalid field in cdb"},
{0x2401, "CDB decryption error"},
+ {0x2402, "Obsolete"},
+ {0x2403, "Obsolete"},
{0x2404, "Security audit value frozen"},
{0x2405, "Security working key frozen"},
{0x2406, "Nonce not unique"},
@@ -637,7 +651,10 @@ static struct error_info additional[] =
{0x260C, "Invalid operation for copy source or destination"},
{0x260D, "Copy segment granularity violation"},
{0x260E, "Invalid parameter while port is enabled"},
- {0x260F, "Invalid data-out buffer integrity"},
+ {0x260F, "Invalid data-out buffer integrity check value"},
+ {0x2610, "Data decryption key fail limit reached"},
+ {0x2611, "Incomplete key-associated data set"},
+ {0x2612, "Vendor specific key reference not found"},
{0x2700, "Write protected"},
{0x2701, "Hardware write protected"},
@@ -649,6 +666,7 @@ static struct error_info additional[] =
{0x2800, "Not ready to ready change, medium may have changed"},
{0x2801, "Import or export element accessed"},
+ {0x2802, "Format-layer may have changed"},
{0x2900, "Power on, reset, or bus device reset occurred"},
{0x2901, "Power on occurred"},
@@ -669,6 +687,11 @@ static struct error_info additional[] =
{0x2A07, "Implicit asymmetric access state transition failed"},
{0x2A08, "Priority changed"},
{0x2A09, "Capacity data has changed"},
+ {0x2A10, "Timestamp changed"},
+ {0x2A11, "Data encryption parameters changed by another i_t nexus"},
+ {0x2A12, "Data encryption parameters changed by vendor specific "
+ "event"},
+ {0x2A13, "Data encryption key instance counter has changed"},
{0x2B00, "Copy cannot execute since host cannot disconnect"},
@@ -690,6 +713,7 @@ static struct error_info additional[] =
{0x2E00, "Insufficient time for operation"},
{0x2F00, "Commands cleared by another initiator"},
+ {0x2F01, "Commands cleared by power loss notification"},
{0x3000, "Incompatible medium installed"},
{0x3001, "Cannot read medium - unknown format"},
@@ -702,7 +726,8 @@ static struct error_info additional[] =
{0x3008, "Cannot write - application code mismatch"},
{0x3009, "Current session not fixated for append"},
{0x300A, "Cleaning request rejected"},
- {0x300C, "WORM medium, overwrite attempted"},
+ {0x300C, "WORM medium - overwrite attempted"},
+ {0x300D, "WORM medium - integrity check"},
{0x3010, "Medium not formatted"},
{0x3100, "Medium format corrupted"},
@@ -790,6 +815,9 @@ static struct error_info additional[] =
{0x3F0F, "Echo buffer overwritten"},
{0x3F10, "Medium loadable"},
{0x3F11, "Medium auxiliary memory accessible"},
+ {0x3F12, "iSCSI IP address added"},
+ {0x3F13, "iSCSI IP address removed"},
+ {0x3F14, "iSCSI IP address changed"},
/*
* {0x40NN, "Ram failure"},
* {0x40NN, "Diagnostic failure on component nn"},
@@ -799,6 +827,7 @@ static struct error_info additional[] =
{0x4300, "Message error"},
{0x4400, "Internal target failure"},
+ {0x4471, "ATA device failed set features"},
{0x4500, "Select or reselect failure"},
@@ -807,9 +836,10 @@ static struct error_info additional[] =
{0x4700, "Scsi parity error"},
{0x4701, "Data phase CRC error detected"},
{0x4702, "Scsi parity error detected during st data phase"},
- {0x4703, "Information unit CRC error detected"},
+ {0x4703, "Information unit iuCRC error detected"},
{0x4704, "Asynchronous information protection error detected"},
{0x4705, "Protocol service CRC error"},
+ {0x4706, "Phy test function in progress"},
{0x477f, "Some commands cleared by iSCSI Protocol event"},
{0x4800, "Initiator detected error message received"},
@@ -844,6 +874,8 @@ static struct error_info additional[] =
{0x5300, "Media load or eject failed"},
{0x5301, "Unload tape failure"},
{0x5302, "Medium removal prevented"},
+ {0x5303, "Medium removal prevented by data transfer element"},
+ {0x5304, "Medium thread or unthread failure"},
{0x5400, "Scsi to host system interface failure"},
@@ -855,6 +887,7 @@ static struct error_info additional[] =
{0x5505, "Insufficient access control resources"},
{0x5506, "Auxiliary memory out of space"},
{0x5507, "Quota error"},
+ {0x5508, "Maximum number of supplemental decryption keys exceeded"},
{0x5700, "Unable to recover table-of-contents"},
@@ -1004,6 +1037,7 @@ static struct error_info additional[] =
{0x6708, "Assign failure occurred"},
{0x6709, "Multiply assigned logical unit"},
{0x670A, "Set target port groups command failed"},
+ {0x670B, "ATA device feature not enabled"},
{0x6800, "Logical unit not configured"},
@@ -1030,6 +1064,8 @@ static struct error_info additional[] =
{0x6F03, "Read of scrambled sector without authentication"},
{0x6F04, "Media region code is mismatched to logical unit region"},
{0x6F05, "Drive region must be permanent/region reset count error"},
+ {0x6F06, "Insufficient block count for binding nonce recording"},
+ {0x6F07, "Conflict in binding nonce recording"},
/*
* {0x70NN, "Decompression exception short algorithm id of nn"},
*/
@@ -1041,6 +1077,8 @@ static struct error_info additional[] =
{0x7203, "Session fixation error - incomplete track in session"},
{0x7204, "Empty or partially written reserved track"},
{0x7205, "No more track reservations allowed"},
+ {0x7206, "RMZ extension is not allowed"},
+ {0x7207, "No more test zone extensions are allowed"},
{0x7300, "Cd control error"},
{0x7301, "Power calibration area almost full"},
@@ -1049,6 +1087,18 @@ static struct error_info additional[] =
{0x7304, "Program memory area update failure"},
{0x7305, "Program memory area is full"},
{0x7306, "RMA/PMA is almost full"},
+ {0x7310, "Current power calibration area almost full"},
+ {0x7311, "Current power calibration area is full"},
+ {0x7317, "RDZ is full"},
+
+ {0x7400, "Security error"},
+ {0x7401, "Unable to decrypt data"},
+ {0x7402, "Unencrypted data encountered while decrypting"},
+ {0x7403, "Incorrect data encryption key"},
+ {0x7404, "Cryptographic integrity validation failed"},
+ {0x7405, "Error decrypting data"},
+ {0x7471, "Logical unit access not authorized"},
+
{0, NULL}
};
diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c
index 10573c24a50..98bd22714d0 100644
--- a/drivers/scsi/esp.c
+++ b/drivers/scsi/esp.c
@@ -1397,7 +1397,7 @@ static void esp_get_dmabufs(struct esp *esp, struct scsi_cmnd *sp)
sp->SCp.ptr = NULL;
}
} else {
- sp->SCp.buffer = (struct scatterlist *) sp->buffer;
+ sp->SCp.buffer = (struct scatterlist *) sp->request_buffer;
sp->SCp.buffers_residual = sbus_map_sg(esp->sdev,
sp->SCp.buffer,
sp->use_sg,
@@ -1410,7 +1410,7 @@ static void esp_get_dmabufs(struct esp *esp, struct scsi_cmnd *sp)
static void esp_release_dmabufs(struct esp *esp, struct scsi_cmnd *sp)
{
if (sp->use_sg) {
- sbus_unmap_sg(esp->sdev, sp->buffer, sp->use_sg,
+ sbus_unmap_sg(esp->sdev, sp->request_buffer, sp->use_sg,
sp->sc_data_direction);
} else if (sp->request_bufflen) {
sbus_unmap_single(esp->sdev,
@@ -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/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c
index 7eed0b09817..6aeb5f003c3 100644
--- a/drivers/scsi/ibmvscsi/iseries_vscsi.c
+++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c
@@ -81,7 +81,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
int rc;
single_host_data = hostdata;
- rc = viopath_open(viopath_hostLp, viomajorsubtype_scsi, 0);
+ rc = viopath_open(viopath_hostLp, viomajorsubtype_scsi, max_requests);
if (rc < 0) {
printk("viopath_open failed with rc %d in open_event_path\n",
rc);
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
index 242b8873b33..ed22b96580c 100644
--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
@@ -238,6 +238,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
if (rc == 2) {
/* Adapter is good, but other end is not ready */
printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
+ retrc = 0;
} else if (rc != 0) {
printk(KERN_WARNING "ibmvscsi: Error %d opening adapter\n", rc);
goto reg_crq_failed;
diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c
index 3fd8a96f2af..bfac4441d89 100644
--- a/drivers/scsi/jazz_esp.c
+++ b/drivers/scsi/jazz_esp.c
@@ -257,7 +257,7 @@ static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp)
static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp)
{
int sz = sp->use_sg - 1;
- struct scatterlist *sg = (struct scatterlist *)sp->buffer;
+ struct scatterlist *sg = (struct scatterlist *)sp->request_buffer;
while(sz >= 0) {
vdma_free(sg[sz].dma_address);
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c
index 9ce221f2595..158f62dbf21 100644
--- a/drivers/scsi/libata-bmdma.c
+++ b/drivers/scsi/libata-bmdma.c
@@ -797,32 +797,6 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
}
#ifdef CONFIG_PCI
-static struct ata_probe_ent *
-ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
-{
- struct ata_probe_ent *probe_ent;
-
- probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
- if (!probe_ent) {
- printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
- kobject_name(&(dev->kobj)));
- return NULL;
- }
-
- INIT_LIST_HEAD(&probe_ent->node);
- probe_ent->dev = dev;
-
- probe_ent->sht = port->sht;
- probe_ent->host_flags = port->host_flags;
- probe_ent->pio_mask = port->pio_mask;
- probe_ent->mwdma_mask = port->mwdma_mask;
- probe_ent->udma_mask = port->udma_mask;
- probe_ent->port_ops = port->port_ops;
-
- return probe_ent;
-}
-
-
/**
* ata_pci_init_native_mode - Initialize native-mode driver
* @pdev: pci device to be initialized
@@ -880,7 +854,7 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
if (bmdma) {
bmdma += 8;
if(inb(bmdma + 2) & 0x80)
- probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+ probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
probe_ent->port[p].bmdma_addr = bmdma;
}
ata_std_ports(&probe_ent->port[p]);
@@ -893,44 +867,48 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
- struct ata_port_info *port, int port_num)
+ struct ata_port_info **port, int port_mask)
{
struct ata_probe_ent *probe_ent;
- unsigned long bmdma;
+ unsigned long bmdma = pci_resource_start(pdev, 4);
- probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port);
+ probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
if (!probe_ent)
return NULL;
- probe_ent->legacy_mode = 1;
- probe_ent->n_ports = 1;
- probe_ent->hard_port_no = port_num;
- probe_ent->private_data = port->private_data;
-
- switch(port_num)
- {
- case 0:
- probe_ent->irq = 14;
- probe_ent->port[0].cmd_addr = 0x1f0;
- probe_ent->port[0].altstatus_addr =
- probe_ent->port[0].ctl_addr = 0x3f6;
- break;
- case 1:
- probe_ent->irq = 15;
- probe_ent->port[0].cmd_addr = 0x170;
- probe_ent->port[0].altstatus_addr =
- probe_ent->port[0].ctl_addr = 0x376;
- break;
- }
+ probe_ent->n_ports = 2;
+ probe_ent->private_data = port[0]->private_data;
- bmdma = pci_resource_start(pdev, 4);
- if (bmdma != 0) {
- bmdma += 8 * port_num;
- probe_ent->port[0].bmdma_addr = bmdma;
- if (inb(bmdma + 2) & 0x80)
- probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
- }
- ata_std_ports(&probe_ent->port[0]);
+ if (port_mask & ATA_PORT_PRIMARY) {
+ probe_ent->irq = 14;
+ probe_ent->port[0].cmd_addr = ATA_PRIMARY_CMD;
+ probe_ent->port[0].altstatus_addr =
+ probe_ent->port[0].ctl_addr = ATA_PRIMARY_CTL;
+ if (bmdma) {
+ probe_ent->port[0].bmdma_addr = bmdma;
+ if (inb(bmdma + 2) & 0x80)
+ probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+ }
+ ata_std_ports(&probe_ent->port[0]);
+ } else
+ probe_ent->dummy_port_mask |= ATA_PORT_PRIMARY;
+
+ if (port_mask & ATA_PORT_SECONDARY) {
+ if (probe_ent->irq)
+ probe_ent->irq2 = 15;
+ else
+ probe_ent->irq = 15;
+ probe_ent->port[1].cmd_addr = ATA_SECONDARY_CMD;
+ probe_ent->port[1].altstatus_addr =
+ probe_ent->port[1].ctl_addr = ATA_SECONDARY_CTL;
+ if (bmdma) {
+ probe_ent->port[1].bmdma_addr = bmdma + 8;
+ if (inb(bmdma + 10) & 0x80)
+ probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+ }
+ ata_std_ports(&probe_ent->port[1]);
+ } else
+ probe_ent->dummy_port_mask |= ATA_PORT_SECONDARY;
return probe_ent;
}
@@ -950,6 +928,10 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
* regions, sets the dma mask, enables bus master mode, and calls
* ata_device_add()
*
+ * ASSUMPTION:
+ * Nobody makes a single channel controller that appears solely as
+ * the secondary legacy port on PCI.
+ *
* LOCKING:
* Inherited from PCI layer (may sleep).
*
@@ -960,7 +942,7 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
unsigned int n_ports)
{
- struct ata_probe_ent *probe_ent = NULL, *probe_ent2 = NULL;
+ struct ata_probe_ent *probe_ent = NULL;
struct ata_port_info *port[2];
u8 tmp8, mask;
unsigned int legacy_mode = 0;
@@ -1009,35 +991,34 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
goto err_out;
}
- /* FIXME: Should use platform specific mappers for legacy port ranges */
if (legacy_mode) {
- if (!request_region(0x1f0, 8, "libata")) {
+ if (!request_region(ATA_PRIMARY_CMD, 8, "libata")) {
struct resource *conflict, res;
- res.start = 0x1f0;
- res.end = 0x1f0 + 8 - 1;
+ res.start = ATA_PRIMARY_CMD;
+ res.end = ATA_PRIMARY_CMD + 8 - 1;
conflict = ____request_resource(&ioport_resource, &res);
if (!strcmp(conflict->name, "libata"))
- legacy_mode |= (1 << 0);
+ legacy_mode |= ATA_PORT_PRIMARY;
else {
disable_dev_on_err = 0;
- printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n");
+ printk(KERN_WARNING "ata: 0x%0X IDE port busy\n", ATA_PRIMARY_CMD);
}
} else
- legacy_mode |= (1 << 0);
+ legacy_mode |= ATA_PORT_PRIMARY;
- if (!request_region(0x170, 8, "libata")) {
+ if (!request_region(ATA_SECONDARY_CMD, 8, "libata")) {
struct resource *conflict, res;
- res.start = 0x170;
- res.end = 0x170 + 8 - 1;
+ res.start = ATA_SECONDARY_CMD;
+ res.end = ATA_SECONDARY_CMD + 8 - 1;
conflict = ____request_resource(&ioport_resource, &res);
if (!strcmp(conflict->name, "libata"))
- legacy_mode |= (1 << 1);
+ legacy_mode |= ATA_PORT_SECONDARY;
else {
disable_dev_on_err = 0;
- printk(KERN_WARNING "ata: 0x170 IDE port busy\n");
+ printk(KERN_WARNING "ata: 0x%X IDE port busy\n", ATA_SECONDARY_CMD);
}
} else
- legacy_mode |= (1 << 1);
+ legacy_mode |= ATA_PORT_SECONDARY;
}
/* we have legacy mode, but all ports are unavailable */
@@ -1055,17 +1036,14 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
goto err_out_regions;
if (legacy_mode) {
- if (legacy_mode & (1 << 0))
- probe_ent = ata_pci_init_legacy_port(pdev, port[0], 0);
- if (legacy_mode & (1 << 1))
- probe_ent2 = ata_pci_init_legacy_port(pdev, port[1], 1);
+ probe_ent = ata_pci_init_legacy_port(pdev, port, legacy_mode);
} else {
if (n_ports == 2)
probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
else
probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY);
}
- if (!probe_ent && !probe_ent2) {
+ if (!probe_ent) {
rc = -ENOMEM;
goto err_out_regions;
}
@@ -1073,35 +1051,17 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
pci_set_master(pdev);
/* FIXME: check ata_device_add return */
- if (legacy_mode) {
- struct device *dev = &pdev->dev;
- struct ata_host_set *host_set = NULL;
-
- if (legacy_mode & (1 << 0)) {
- ata_device_add(probe_ent);
- host_set = dev_get_drvdata(dev);
- }
-
- if (legacy_mode & (1 << 1)) {
- ata_device_add(probe_ent2);
- if (host_set) {
- host_set->next = dev_get_drvdata(dev);
- dev_set_drvdata(dev, host_set);
- }
- }
- } else
- ata_device_add(probe_ent);
+ ata_device_add(probe_ent);
kfree(probe_ent);
- kfree(probe_ent2);
return 0;
err_out_regions:
- if (legacy_mode & (1 << 0))
- release_region(0x1f0, 8);
- if (legacy_mode & (1 << 1))
- release_region(0x170, 8);
+ if (legacy_mode & ATA_PORT_PRIMARY)
+ release_region(ATA_PRIMARY_CMD, 8);
+ if (legacy_mode & ATA_PORT_SECONDARY)
+ release_region(ATA_SECONDARY_CMD, 8);
pci_release_regions(pdev);
err_out:
if (disable_dev_on_err)
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 386e5f21e19..3f963f206d4 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1528,7 +1528,7 @@ err_out_nosup:
* Zero on success, negative errno otherwise.
*/
-static int ata_bus_probe(struct ata_port *ap)
+int ata_bus_probe(struct ata_port *ap)
{
unsigned int classes[ATA_MAX_DEVICES];
int tries[ATA_MAX_DEVICES];
@@ -3040,10 +3040,6 @@ static int ata_dma_blacklisted(const struct ata_device *dev)
* known limits including host controller limits, device
* blacklist, etc...
*
- * FIXME: The current implementation limits all transfer modes to
- * the fastest of the lowested device on the port. This is not
- * required on most controllers.
- *
* LOCKING:
* None.
*/
@@ -3052,8 +3048,8 @@ static void ata_dev_xfermask(struct ata_device *dev)
struct ata_port *ap = dev->ap;
struct ata_host_set *hs = ap->host_set;
unsigned long xfer_mask;
- int i;
+ /* controller modes available */
xfer_mask = ata_pack_xfermask(ap->pio_mask,
ap->mwdma_mask, ap->udma_mask);
@@ -3063,34 +3059,20 @@ static void ata_dev_xfermask(struct ata_device *dev)
if (ap->cbl == ATA_CBL_PATA40)
xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
- /* FIXME: Use port-wide xfermask for now */
- for (i = 0; i < ATA_MAX_DEVICES; i++) {
- struct ata_device *d = &ap->device[i];
-
- if (ata_dev_absent(d))
- continue;
-
- if (ata_dev_disabled(d)) {
- /* to avoid violating device selection timing */
- xfer_mask &= ata_pack_xfermask(d->pio_mask,
- UINT_MAX, UINT_MAX);
- continue;
- }
-
- xfer_mask &= ata_pack_xfermask(d->pio_mask,
- d->mwdma_mask, d->udma_mask);
- xfer_mask &= ata_id_xfermask(d->id);
- if (ata_dma_blacklisted(d))
- xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
- }
+ xfer_mask &= ata_pack_xfermask(dev->pio_mask,
+ dev->mwdma_mask, dev->udma_mask);
+ xfer_mask &= ata_id_xfermask(dev->id);
- if (ata_dma_blacklisted(dev))
+ if (ata_dma_blacklisted(dev)) {
+ xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
ata_dev_printk(dev, KERN_WARNING,
"device is on DMA blacklist, disabling DMA\n");
+ }
- if (hs->flags & ATA_HOST_SIMPLEX) {
- if (hs->simplex_claimed)
- xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+ if ((hs->flags & ATA_HOST_SIMPLEX) && hs->simplex_claimed) {
+ xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+ ata_dev_printk(dev, KERN_WARNING, "simplex DMA is claimed by "
+ "other device, disabling DMA\n");
}
if (ap->ops->mode_filter)
@@ -5185,28 +5167,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
@@ -5240,41 +5200,29 @@ void ata_dev_init(struct ata_device *dev)
}
/**
- * ata_host_init - Initialize an ata_port structure
+ * ata_port_init - Initialize an ata_port structure
* @ap: Structure to initialize
- * @host: associated SCSI mid-layer structure
* @host_set: Collection of hosts to which @ap belongs
* @ent: Probe information provided by low-level driver
* @port_no: Port number associated with this ata_port
*
- * Initialize a new ata_port structure, and its associated
- * scsi_host.
+ * Initialize a new ata_port structure.
*
* LOCKING:
* Inherited from caller.
*/
-static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
- struct ata_host_set *host_set,
- const struct ata_probe_ent *ent, unsigned int port_no)
+void ata_port_init(struct ata_port *ap, struct ata_host_set *host_set,
+ const struct ata_probe_ent *ent, unsigned int port_no)
{
unsigned int i;
- host->max_id = 16;
- host->max_lun = 1;
- host->max_channel = 1;
- host->unique_id = ata_unique_id++;
- host->max_cmd_len = 12;
-
ap->lock = &host_set->lock;
ap->flags = ATA_FLAG_DISABLED;
- ap->id = host->unique_id;
- ap->host = host;
+ ap->id = ata_unique_id++;
ap->ctl = ATA_DEVCTL_OBS;
ap->host_set = host_set;
ap->dev = ent->dev;
ap->port_no = port_no;
- ap->hard_port_no =
- ent->legacy_mode ? ent->hard_port_no : port_no;
ap->pio_mask = ent->pio_mask;
ap->mwdma_mask = ent->mwdma_mask;
ap->udma_mask = ent->udma_mask;
@@ -5320,7 +5268,28 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
}
/**
- * ata_host_add - Attach low-level ATA driver to system
+ * ata_port_init_shost - Initialize SCSI host associated with ATA port
+ * @ap: ATA port to initialize SCSI host for
+ * @shost: SCSI host associated with @ap
+ *
+ * Initialize SCSI host @shost associated with ATA port @ap.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+static void ata_port_init_shost(struct ata_port *ap, struct Scsi_Host *shost)
+{
+ ap->host = shost;
+
+ shost->unique_id = ap->id;
+ shost->max_id = 16;
+ shost->max_lun = 1;
+ shost->max_channel = 1;
+ shost->max_cmd_len = 12;
+}
+
+/**
+ * ata_port_add - Attach low-level ATA driver to system
* @ent: Information provided by low-level driver
* @host_set: Collections of ports to which we add
* @port_no: Port number associated with this host
@@ -5333,14 +5302,12 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
* RETURNS:
* New ata_port on success, for NULL on error.
*/
-
-static struct ata_port * ata_host_add(const struct ata_probe_ent *ent,
+static struct ata_port * ata_port_add(const struct ata_probe_ent *ent,
struct ata_host_set *host_set,
unsigned int port_no)
{
- struct Scsi_Host *host;
+ struct Scsi_Host *shost;
struct ata_port *ap;
- int rc;
DPRINTK("ENTER\n");
@@ -5351,25 +5318,40 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent,
return NULL;
}
- host = scsi_host_alloc(ent->sht, sizeof(struct ata_port));
- if (!host)
+ shost = scsi_host_alloc(ent->sht, sizeof(struct ata_port));
+ if (!shost)
return NULL;
- host->transportt = &ata_scsi_transport_template;
+ shost->transportt = &ata_scsi_transport_template;
- ap = ata_shost_to_port(host);
+ ap = ata_shost_to_port(shost);
- ata_host_init(ap, host, host_set, ent, port_no);
-
- rc = ap->ops->port_start(ap);
- if (rc)
- goto err_out;
+ ata_port_init(ap, host_set, ent, port_no);
+ ata_port_init_shost(ap, shost);
return ap;
+}
-err_out:
- scsi_host_put(host);
- return NULL;
+/**
+ * ata_sas_host_init - Initialize a host_set struct
+ * @host_set: host_set to initialize
+ * @dev: device host_set is attached to
+ * @flags: host_set flags
+ * @ops: port_ops
+ *
+ * LOCKING:
+ * PCI/etc. bus probe sem.
+ *
+ */
+
+void ata_host_set_init(struct ata_host_set *host_set,
+ struct device *dev, unsigned long flags,
+ const struct ata_port_operations *ops)
+{
+ spin_lock_init(&host_set->lock);
+ host_set->dev = dev;
+ host_set->flags = flags;
+ host_set->ops = ops;
}
/**
@@ -5392,7 +5374,7 @@ err_out:
*/
int ata_device_add(const struct ata_probe_ent *ent)
{
- unsigned int count = 0, i;
+ unsigned int i;
struct device *dev = ent->dev;
struct ata_host_set *host_set;
int rc;
@@ -5403,50 +5385,65 @@ int ata_device_add(const struct ata_probe_ent *ent)
(ent->n_ports * sizeof(void *)), GFP_KERNEL);
if (!host_set)
return 0;
- spin_lock_init(&host_set->lock);
- host_set->dev = dev;
+ ata_host_set_init(host_set, dev, ent->host_set_flags, ent->port_ops);
host_set->n_ports = ent->n_ports;
host_set->irq = ent->irq;
+ host_set->irq2 = ent->irq2;
host_set->mmio_base = ent->mmio_base;
host_set->private_data = ent->private_data;
- host_set->ops = ent->port_ops;
- host_set->flags = ent->host_set_flags;
/* register each port bound to this device */
- for (i = 0; i < ent->n_ports; i++) {
+ for (i = 0; i < host_set->n_ports; i++) {
struct ata_port *ap;
unsigned long xfer_mode_mask;
+ int irq_line = ent->irq;
- ap = ata_host_add(ent, host_set, i);
+ ap = ata_port_add(ent, host_set, i);
if (!ap)
goto err_out;
host_set->ports[i] = ap;
+
+ /* dummy? */
+ if (ent->dummy_port_mask & (1 << i)) {
+ ata_port_printk(ap, KERN_INFO, "DUMMY\n");
+ ap->ops = &ata_dummy_port_ops;
+ continue;
+ }
+
+ /* start port */
+ rc = ap->ops->port_start(ap);
+ if (rc) {
+ host_set->ports[i] = NULL;
+ scsi_host_put(ap->host);
+ goto err_out;
+ }
+
+ /* Report the secondary IRQ for second channel legacy */
+ if (i == 1 && ent->irq2)
+ irq_line = ent->irq2;
+
xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) |
(ap->mwdma_mask << ATA_SHIFT_MWDMA) |
(ap->pio_mask << ATA_SHIFT_PIO);
/* print per-port info to dmesg */
ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%lX "
- "ctl 0x%lX bmdma 0x%lX irq %lu\n",
+ "ctl 0x%lX bmdma 0x%lX irq %d\n",
ap->flags & ATA_FLAG_SATA ? 'S' : 'P',
ata_mode_string(xfer_mode_mask),
ap->ioaddr.cmd_addr,
ap->ioaddr.ctl_addr,
ap->ioaddr.bmdma_addr,
- ent->irq);
+ irq_line);
ata_chk_status(ap);
host_set->ops->irq_clear(ap);
ata_eh_freeze_port(ap); /* freeze port before requesting IRQ */
- count++;
}
- if (!count)
- goto err_free_ret;
-
- /* obtain irq, that is shared between channels */
+ /* obtain irq, that may be shared between channels */
rc = request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags,
DRV_NAME, host_set);
if (rc) {
@@ -5455,15 +5452,28 @@ int ata_device_add(const struct ata_probe_ent *ent)
goto err_out;
}
+ /* do we have a second IRQ for the other channel, eg legacy mode */
+ if (ent->irq2) {
+ /* We will get weird core code crashes later if this is true
+ so trap it now */
+ BUG_ON(ent->irq == ent->irq2);
+
+ rc = request_irq(ent->irq2, ent->port_ops->irq_handler, ent->irq_flags,
+ DRV_NAME, host_set);
+ if (rc) {
+ dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n",
+ ent->irq2, rc);
+ goto err_out_free_irq;
+ }
+ }
+
/* perform each probe synchronously */
DPRINTK("probe begin\n");
- for (i = 0; i < count; i++) {
- struct ata_port *ap;
+ for (i = 0; i < host_set->n_ports; i++) {
+ struct ata_port *ap = host_set->ports[i];
u32 scontrol;
int rc;
- ap = host_set->ports[i];
-
/* init sata_spd_limit to the current value */
if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
int spd = (scontrol >> 4) & 0xf;
@@ -5519,7 +5529,7 @@ int ata_device_add(const struct ata_probe_ent *ent)
/* probes are done, now scan each port's disk(s) */
DPRINTK("host probe begin\n");
- for (i = 0; i < count; i++) {
+ for (i = 0; i < host_set->n_ports; i++) {
struct ata_port *ap = host_set->ports[i];
ata_scsi_scan_host(ap);
@@ -5530,12 +5540,17 @@ int ata_device_add(const struct ata_probe_ent *ent)
VPRINTK("EXIT, returning %u\n", ent->n_ports);
return ent->n_ports; /* success */
+err_out_free_irq:
+ free_irq(ent->irq, host_set);
err_out:
- for (i = 0; i < count; i++) {
- ata_host_remove(host_set->ports[i], 1);
- scsi_host_put(host_set->ports[i]->host);
+ for (i = 0; i < host_set->n_ports; i++) {
+ 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);
VPRINTK("EXIT, returning 0\n");
return 0;
@@ -5558,7 +5573,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 +5609,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);
}
@@ -5617,6 +5633,8 @@ void ata_host_set_remove(struct ata_host_set *host_set)
ata_port_detach(host_set->ports[i]);
free_irq(host_set->irq, host_set);
+ if (host_set->irq2)
+ free_irq(host_set->irq2, host_set);
for (i = 0; i < host_set->n_ports; i++) {
struct ata_port *ap = host_set->ports[i];
@@ -5626,10 +5644,11 @@ void ata_host_set_remove(struct ata_host_set *host_set)
if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) {
struct ata_ioports *ioaddr = &ap->ioaddr;
- if (ioaddr->cmd_addr == 0x1f0)
- release_region(0x1f0, 8);
- else if (ioaddr->cmd_addr == 0x170)
- release_region(0x170, 8);
+ /* FIXME: Add -ac IDE pci mods to remove these special cases */
+ if (ioaddr->cmd_addr == ATA_PRIMARY_CMD)
+ release_region(ATA_PRIMARY_CMD, 8);
+ else if (ioaddr->cmd_addr == ATA_SECONDARY_CMD)
+ release_region(ATA_SECONDARY_CMD, 8);
}
scsi_host_put(ap->host);
@@ -5662,12 +5681,37 @@ 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;
}
+struct ata_probe_ent *
+ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
+{
+ struct ata_probe_ent *probe_ent;
+
+ probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
+ if (!probe_ent) {
+ printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
+ kobject_name(&(dev->kobj)));
+ return NULL;
+ }
+
+ INIT_LIST_HEAD(&probe_ent->node);
+ probe_ent->dev = dev;
+
+ probe_ent->sht = port->sht;
+ probe_ent->host_flags = port->host_flags;
+ probe_ent->pio_mask = port->pio_mask;
+ probe_ent->mwdma_mask = port->mwdma_mask;
+ probe_ent->udma_mask = port->udma_mask;
+ probe_ent->port_ops = port->port_ops;
+
+ return probe_ent;
+}
+
/**
* ata_std_ports - initialize ioaddr with standard port offsets.
* @ioaddr: IO address structure to be initialized
@@ -5722,11 +5766,8 @@ void ata_pci_remove_one (struct pci_dev *pdev)
{
struct device *dev = pci_dev_to_dev(pdev);
struct ata_host_set *host_set = dev_get_drvdata(dev);
- struct ata_host_set *host_set2 = host_set->next;
ata_host_set_remove(host_set);
- if (host_set2)
- ata_host_set_remove(host_set2);
pci_release_regions(pdev);
pci_disable_device(pdev);
@@ -5767,11 +5808,11 @@ int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
return (tmp == bits->val) ? 1 : 0;
}
-void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t state)
+void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg)
{
pci_save_state(pdev);
- if (state.event == PM_EVENT_SUSPEND) {
+ if (mesg.event == PM_EVENT_SUSPEND) {
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
}
@@ -5785,24 +5826,16 @@ void ata_pci_device_do_resume(struct pci_dev *pdev)
pci_set_master(pdev);
}
-int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state)
+int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
{
struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
int rc = 0;
- rc = ata_host_set_suspend(host_set, state);
+ rc = ata_host_set_suspend(host_set, mesg);
if (rc)
return rc;
- if (host_set->next) {
- rc = ata_host_set_suspend(host_set->next, state);
- if (rc) {
- ata_host_set_resume(host_set);
- return rc;
- }
- }
-
- ata_pci_device_do_suspend(pdev, state);
+ ata_pci_device_do_suspend(pdev, mesg);
return 0;
}
@@ -5813,9 +5846,6 @@ int ata_pci_device_resume(struct pci_dev *pdev)
ata_pci_device_do_resume(pdev);
ata_host_set_resume(host_set);
- if (host_set->next)
- ata_host_set_resume(host_set->next);
-
return 0;
}
#endif /* CONFIG_PCI */
@@ -5915,6 +5945,39 @@ u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
}
/*
+ * Dummy port_ops
+ */
+static void ata_dummy_noret(struct ata_port *ap) { }
+static int ata_dummy_ret0(struct ata_port *ap) { return 0; }
+static void ata_dummy_qc_noret(struct ata_queued_cmd *qc) { }
+
+static u8 ata_dummy_check_status(struct ata_port *ap)
+{
+ return ATA_DRDY;
+}
+
+static unsigned int ata_dummy_qc_issue(struct ata_queued_cmd *qc)
+{
+ return AC_ERR_SYSTEM;
+}
+
+const struct ata_port_operations ata_dummy_port_ops = {
+ .port_disable = ata_port_disable,
+ .check_status = ata_dummy_check_status,
+ .check_altstatus = ata_dummy_check_status,
+ .dev_select = ata_noop_dev_select,
+ .qc_prep = ata_noop_qc_prep,
+ .qc_issue = ata_dummy_qc_issue,
+ .freeze = ata_dummy_noret,
+ .thaw = ata_dummy_noret,
+ .error_handler = ata_dummy_noret,
+ .post_internal_cmd = ata_dummy_qc_noret,
+ .irq_clear = ata_dummy_noret,
+ .port_start = ata_dummy_ret0,
+ .port_stop = ata_dummy_noret,
+};
+
+/*
* libata is essentially a library of internal helper functions for
* low-level ATA host controller drivers. As such, the API/ABI is
* likely to change as new drivers are added and updated.
@@ -5924,8 +5987,10 @@ u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
EXPORT_SYMBOL_GPL(sata_deb_timing_normal);
EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug);
EXPORT_SYMBOL_GPL(sata_deb_timing_long);
+EXPORT_SYMBOL_GPL(ata_dummy_port_ops);
EXPORT_SYMBOL_GPL(ata_std_bios_param);
EXPORT_SYMBOL_GPL(ata_std_ports);
+EXPORT_SYMBOL_GPL(ata_host_set_init);
EXPORT_SYMBOL_GPL(ata_device_add);
EXPORT_SYMBOL_GPL(ata_port_detach);
EXPORT_SYMBOL_GPL(ata_host_set_remove);
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 4b6aa30f4d6..29f59345305 100644
--- a/drivers/scsi/libata-eh.c
+++ b/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/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 7ced41ecde8..d168e341366 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -400,7 +400,7 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf)
/**
* ata_scsi_device_suspend - suspend ATA device associated with sdev
* @sdev: the SCSI device to suspend
- * @state: target power management state
+ * @mesg: target power management message
*
* Request suspend EH action on the ATA device associated with
* @sdev and wait for the operation to complete.
@@ -411,7 +411,7 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf)
* RETURNS:
* 0 on success, -errno otherwise.
*/
-int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
+int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t mesg)
{
struct ata_port *ap = ata_shost_to_port(sdev->host);
struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
@@ -438,7 +438,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
/* request suspend */
action = ATA_EH_SUSPEND;
- if (state.event != PM_EVENT_SUSPEND)
+ if (mesg.event != PM_EVENT_SUSPEND)
action |= ATA_EH_PM_FREEZE;
ap->eh_info.dev_action[dev->devno] |= action;
ap->eh_info.flags |= ATA_EHI_QUIET;
@@ -463,7 +463,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
spin_unlock_irqrestore(ap->lock, flags);
out:
if (rc == 0)
- sdev->sdev_gendev.power.power_state = state;
+ sdev->sdev_gendev.power.power_state = mesg;
return rc;
}
@@ -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);
@@ -3158,3 +3171,152 @@ void ata_scsi_dev_rescan(void *data)
scsi_rescan_device(&(dev->sdev->sdev_gendev));
}
}
+
+/**
+ * ata_sas_port_alloc - Allocate port for a SAS attached SATA device
+ * @pdev: PCI device that the scsi device is attached to
+ * @port_info: Information from low-level host driver
+ * @host: SCSI host that the scsi device is attached to
+ *
+ * LOCKING:
+ * PCI/etc. bus probe sem.
+ *
+ * RETURNS:
+ * ata_port pointer on success / NULL on failure.
+ */
+
+struct ata_port *ata_sas_port_alloc(struct ata_host_set *host_set,
+ struct ata_port_info *port_info,
+ struct Scsi_Host *host)
+{
+ struct ata_port *ap = kzalloc(sizeof(*ap), GFP_KERNEL);
+ struct ata_probe_ent *ent;
+
+ if (!ap)
+ return NULL;
+
+ ent = ata_probe_ent_alloc(host_set->dev, port_info);
+ if (!ent) {
+ kfree(ap);
+ return NULL;
+ }
+
+ ata_port_init(ap, host_set, ent, 0);
+ ap->lock = host->host_lock;
+ kfree(ent);
+ return ap;
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_alloc);
+
+/**
+ * ata_sas_port_start - Set port up for dma.
+ * @ap: Port to initialize
+ *
+ * Called just after data structures for each port are
+ * initialized. Allocates DMA pad.
+ *
+ * May be used as the port_start() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+int ata_sas_port_start(struct ata_port *ap)
+{
+ return ata_pad_alloc(ap, ap->dev);
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_start);
+
+/**
+ * ata_port_stop - Undo ata_sas_port_start()
+ * @ap: Port to shut down
+ *
+ * Frees the DMA pad.
+ *
+ * May be used as the port_stop() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
+void ata_sas_port_stop(struct ata_port *ap)
+{
+ ata_pad_free(ap, ap->dev);
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_stop);
+
+/**
+ * ata_sas_port_init - Initialize a SATA device
+ * @ap: SATA port to initialize
+ *
+ * LOCKING:
+ * PCI/etc. bus probe sem.
+ *
+ * RETURNS:
+ * Zero on success, non-zero on error.
+ */
+
+int ata_sas_port_init(struct ata_port *ap)
+{
+ int rc = ap->ops->port_start(ap);
+
+ if (!rc)
+ rc = ata_bus_probe(ap);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_init);
+
+/**
+ * ata_sas_port_destroy - Destroy a SATA port allocated by ata_sas_port_alloc
+ * @ap: SATA port to destroy
+ *
+ */
+
+void ata_sas_port_destroy(struct ata_port *ap)
+{
+ ap->ops->port_stop(ap);
+ kfree(ap);
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_destroy);
+
+/**
+ * ata_sas_slave_configure - Default slave_config routine for libata devices
+ * @sdev: SCSI device to configure
+ * @ap: ATA port to which SCSI device is attached
+ *
+ * RETURNS:
+ * Zero.
+ */
+
+int ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap)
+{
+ ata_scsi_sdev_config(sdev);
+ ata_scsi_dev_config(sdev, ap->device);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ata_sas_slave_configure);
+
+/**
+ * ata_sas_queuecmd - Issue SCSI cdb to libata-managed device
+ * @cmd: SCSI command to be sent
+ * @done: Completion function, called when command is complete
+ * @ap: ATA port to which the command is being sent
+ *
+ * RETURNS:
+ * Zero.
+ */
+
+int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
+ struct ata_port *ap)
+{
+ ata_scsi_dump_cdb(ap, cmd);
+
+ if (likely(ata_scsi_dev_enabled(ap->device)))
+ __ata_scsi_queuecmd(cmd, done, ap->device);
+ else {
+ cmd->result = (DID_BAD_TARGET << 16);
+ done(cmd);
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ata_sas_queuecmd);
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index c325679d9b5..d4a4f82360e 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -69,6 +69,10 @@ extern int ata_flush_cache(struct ata_device *dev);
extern void ata_dev_init(struct ata_device *dev);
extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
+extern void ata_port_init(struct ata_port *ap, struct ata_host_set *host_set,
+ const struct ata_probe_ent *ent, unsigned int port_no);
+extern struct ata_probe_ent *ata_probe_ent_alloc(struct device *dev,
+ const struct ata_port_info *port);
/* libata-scsi.c */
@@ -107,6 +111,7 @@ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
u8 *rbuf, unsigned int buflen));
extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
extern void ata_scsi_dev_rescan(void *data);
+extern int ata_bus_probe(struct ata_port *ap);
/* libata-eh.c */
extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index f81691fcf17..d44f9aac6b8 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -21,10 +21,12 @@
struct lpfc_sli2_slim;
-#define LPFC_MAX_TARGET 256 /* max targets supported */
-#define LPFC_MAX_DISC_THREADS 64 /* max outstanding discovery els req */
-#define LPFC_MAX_NS_RETRY 3 /* max NameServer retries */
+#define LPFC_MAX_TARGET 256 /* max number of targets supported */
+#define LPFC_MAX_DISC_THREADS 64 /* max outstanding discovery els
+ requests */
+#define LPFC_MAX_NS_RETRY 3 /* Number of retry attempts to contact
+ the NameServer before giving up. */
#define LPFC_DFT_HBA_Q_DEPTH 2048 /* max cmds per hba */
#define LPFC_LC_HBA_Q_DEPTH 1024 /* max cmds per low cost hba */
#define LPFC_LP101_HBA_Q_DEPTH 128 /* max cmds per low cost hba */
@@ -41,7 +43,6 @@ struct lpfc_sli2_slim;
(( (u64)(high)<<16 ) << 16)|( (u64)(low))))
/* Provide maximum configuration definitions. */
#define LPFC_DRVR_TIMEOUT 16 /* driver iocb timeout value in sec */
-#define MAX_FCP_TARGET 256 /* max num of FCP targets supported */
#define FC_MAX_ADPTMSG 64
#define MAX_HBAEVT 32
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index b62a72dfab2..5c68cdd8736 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -219,9 +219,19 @@ lpfc_issue_lip(struct Scsi_Host *host)
return -ENOMEM;
memset((void *)pmboxq, 0, sizeof (LPFC_MBOXQ_t));
- lpfc_init_link(phba, pmboxq, phba->cfg_topology, phba->cfg_link_speed);
+ pmboxq->mb.mbxCommand = MBX_DOWN_LINK;
+ pmboxq->mb.mbxOwner = OWN_HOST;
+
mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
+ if ((mbxstatus == MBX_SUCCESS) && (pmboxq->mb.mbxStatus == 0)) {
+ memset((void *)pmboxq, 0, sizeof (LPFC_MBOXQ_t));
+ lpfc_init_link(phba, pmboxq, phba->cfg_topology,
+ phba->cfg_link_speed);
+ mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq,
+ phba->fc_ratov * 2);
+ }
+
if (mbxstatus == MBX_TIMEOUT)
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
else
@@ -233,51 +243,53 @@ lpfc_issue_lip(struct Scsi_Host *host)
return 0;
}
-static ssize_t
-lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
+static int
+lpfc_selective_reset(struct lpfc_hba *phba)
{
- struct Scsi_Host *host = class_to_shost(cdev);
- struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
- return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
+ struct completion online_compl;
+ int status = 0;
+
+ init_completion(&online_compl);
+ lpfc_workq_post_event(phba, &status, &online_compl,
+ LPFC_EVT_OFFLINE);
+ wait_for_completion(&online_compl);
+
+ if (status != 0)
+ return -EIO;
+
+ init_completion(&online_compl);
+ lpfc_workq_post_event(phba, &status, &online_compl,
+ LPFC_EVT_ONLINE);
+ wait_for_completion(&online_compl);
+
+ if (status != 0)
+ return -EIO;
+
+ return 0;
}
static ssize_t
-lpfc_board_online_show(struct class_device *cdev, char *buf)
+lpfc_issue_reset(struct class_device *cdev, const char *buf, size_t count)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+ int status = -EINVAL;
- if (phba->fc_flag & FC_OFFLINE_MODE)
- return snprintf(buf, PAGE_SIZE, "0\n");
+ if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
+ status = lpfc_selective_reset(phba);
+
+ if (status == 0)
+ return strlen(buf);
else
- return snprintf(buf, PAGE_SIZE, "1\n");
+ return status;
}
static ssize_t
-lpfc_board_online_store(struct class_device *cdev, const char *buf,
- size_t count)
+lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
{
struct Scsi_Host *host = class_to_shost(cdev);
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
- struct completion online_compl;
- int val=0, status=0;
-
- if (sscanf(buf, "%d", &val) != 1)
- return -EINVAL;
-
- init_completion(&online_compl);
-
- if (val)
- lpfc_workq_post_event(phba, &status, &online_compl,
- LPFC_EVT_ONLINE);
- else
- lpfc_workq_post_event(phba, &status, &online_compl,
- LPFC_EVT_OFFLINE);
- wait_for_completion(&online_compl);
- if (!status)
- return strlen(buf);
- else
- return -EIO;
+ return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
}
static ssize_t
@@ -532,10 +544,9 @@ static CLASS_DEVICE_ATTR(lpfc_drvr_version, S_IRUGO, lpfc_drvr_version_show,
NULL);
static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show,
NULL);
-static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR,
- lpfc_board_online_show, lpfc_board_online_store);
static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
lpfc_board_mode_show, lpfc_board_mode_store);
+static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
static int lpfc_poll = 0;
module_param(lpfc_poll, int, 0);
@@ -695,12 +706,12 @@ LPFC_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands "
"during discovery");
/*
-# lpfc_max_luns: maximum number of LUNs per target driver will support
-# Value range is [1,32768]. Default value is 256.
-# NOTE: The SCSI layer will scan each target for this many luns
+# lpfc_max_luns: maximum allowed LUN.
+# Value range is [0,65535]. Default value is 255.
+# NOTE: The SCSI layer might probe all allowed LUN on some old targets.
*/
-LPFC_ATTR_R(max_luns, 256, 1, 32768,
- "Maximum number of LUNs per target driver will support");
+LPFC_ATTR_R(max_luns, 255, 0, 65535,
+ "Maximum allowed LUN");
/*
# lpfc_poll_tmo: .Milliseconds driver will wait between polling FCP ring.
@@ -739,8 +750,8 @@ struct class_device_attribute *lpfc_host_attrs[] = {
&class_device_attr_lpfc_max_luns,
&class_device_attr_nport_evt_cnt,
&class_device_attr_management_version,
- &class_device_attr_board_online,
&class_device_attr_board_mode,
+ &class_device_attr_issue_reset,
&class_device_attr_lpfc_poll,
&class_device_attr_lpfc_poll_tmo,
NULL,
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index ee22173fce4..517e9e4dd46 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -147,6 +147,7 @@ int lpfc_sli_hba_setup(struct lpfc_hba *);
int lpfc_sli_hba_down(struct lpfc_hba *);
int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
int lpfc_sli_handle_mb_event(struct lpfc_hba *);
+int lpfc_sli_flush_mbox_queue(struct lpfc_hba *);
int lpfc_sli_handle_slow_ring_event(struct lpfc_hba *,
struct lpfc_sli_ring *, uint32_t);
void lpfc_sli_def_mbox_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 4126fd87956..b89f6cb641e 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -648,33 +648,32 @@ lpfc_more_plogi(struct lpfc_hba * phba)
}
static struct lpfc_nodelist *
-lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
+lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp,
struct lpfc_nodelist *ndlp)
{
struct lpfc_nodelist *new_ndlp;
- struct lpfc_dmabuf *pcmd, *prsp;
uint32_t *lp;
struct serv_parm *sp;
uint8_t name[sizeof (struct lpfc_name)];
uint32_t rc;
- pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
- prsp = (struct lpfc_dmabuf *) pcmd->list.next;
lp = (uint32_t *) prsp->virt;
sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
+ memset(name, 0, sizeof (struct lpfc_name));
/* Now we to find out if the NPort we are logging into, matches the WWPN
* we have for that ndlp. If not, we have some work to do.
*/
new_ndlp = lpfc_findnode_wwpn(phba, NLP_SEARCH_ALL, &sp->portName);
- memset(name, 0, sizeof (struct lpfc_name));
- rc = memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name));
- if (!rc || (new_ndlp == ndlp)) {
+ if (new_ndlp == ndlp)
return ndlp;
- }
if (!new_ndlp) {
+ rc =
+ memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name));
+ if (!rc)
+ return ndlp;
new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
if (!new_ndlp)
return ndlp;
@@ -683,17 +682,21 @@ lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
}
lpfc_unreg_rpi(phba, new_ndlp);
- new_ndlp->nlp_prev_state = ndlp->nlp_state;
new_ndlp->nlp_DID = ndlp->nlp_DID;
- new_ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
- lpfc_nlp_list(phba, new_ndlp, NLP_PLOGI_LIST);
+ new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
+ new_ndlp->nlp_state = ndlp->nlp_state;
+ lpfc_nlp_list(phba, new_ndlp, ndlp->nlp_flag & NLP_LIST_MASK);
/* Move this back to NPR list */
- lpfc_unreg_rpi(phba, ndlp);
- ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
- ndlp->nlp_state = NLP_STE_NPR_NODE;
- lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
-
+ if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) {
+ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+ }
+ else {
+ lpfc_unreg_rpi(phba, ndlp);
+ ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
+ ndlp->nlp_state = NLP_STE_NPR_NODE;
+ lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
+ }
return new_ndlp;
}
@@ -703,6 +706,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
{
IOCB_t *irsp;
struct lpfc_nodelist *ndlp;
+ struct lpfc_dmabuf *prsp;
int disc, rc, did, type;
@@ -769,7 +773,10 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
}
} else {
/* Good status, call state machine */
- ndlp = lpfc_plogi_confirm_nport(phba, cmdiocb, ndlp);
+ prsp = list_entry(((struct lpfc_dmabuf *)
+ cmdiocb->context2)->list.next,
+ struct lpfc_dmabuf, list);
+ ndlp = lpfc_plogi_confirm_nport(phba, prsp, ndlp);
rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,
NLP_EVT_CMPL_PLOGI);
}
@@ -3282,10 +3289,9 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
} else
lpfc_sli_release_iocbq(phba, piocb);
}
- if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) {
- phba->els_tmofunc.expires = jiffies + HZ * timeout;
- add_timer(&phba->els_tmofunc);
- }
+ if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
+ mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
+
spin_unlock_irq(phba->host->host_lock);
}
@@ -3442,6 +3448,8 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) {
ndlp->nlp_type |= NLP_FABRIC;
}
+ ndlp->nlp_state = NLP_STE_UNUSED_NODE;
+ lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
}
phba->fc_stat.elsRcvFrame++;
@@ -3463,13 +3471,14 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
rjt_err = 1;
break;
}
+ ndlp = lpfc_plogi_confirm_nport(phba, mp, ndlp);
lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PLOGI);
break;
case ELS_CMD_FLOGI:
phba->fc_stat.elsRcvFLOGI++;
lpfc_els_rcv_flogi(phba, elsiocb, ndlp, newnode);
if (newnode) {
- mempool_free( ndlp, phba->nlp_mem_pool);
+ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
}
break;
case ELS_CMD_LOGO:
@@ -3492,7 +3501,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
phba->fc_stat.elsRcvRSCN++;
lpfc_els_rcv_rscn(phba, elsiocb, ndlp, newnode);
if (newnode) {
- mempool_free( ndlp, phba->nlp_mem_pool);
+ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
}
break;
case ELS_CMD_ADISC:
@@ -3535,28 +3544,28 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
phba->fc_stat.elsRcvLIRR++;
lpfc_els_rcv_lirr(phba, elsiocb, ndlp);
if (newnode) {
- mempool_free( ndlp, phba->nlp_mem_pool);
+ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
}
break;
case ELS_CMD_RPS:
phba->fc_stat.elsRcvRPS++;
lpfc_els_rcv_rps(phba, elsiocb, ndlp);
if (newnode) {
- mempool_free( ndlp, phba->nlp_mem_pool);
+ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
}
break;
case ELS_CMD_RPL:
phba->fc_stat.elsRcvRPL++;
lpfc_els_rcv_rpl(phba, elsiocb, ndlp);
if (newnode) {
- mempool_free( ndlp, phba->nlp_mem_pool);
+ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
}
break;
case ELS_CMD_RNID:
phba->fc_stat.elsRcvRNID++;
lpfc_els_rcv_rnid(phba, elsiocb, ndlp);
if (newnode) {
- mempool_free( ndlp, phba->nlp_mem_pool);
+ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
}
break;
default:
@@ -3568,7 +3577,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
"%d:0115 Unknown ELS command x%x received from "
"NPORT x%x\n", phba->brd_no, cmd, did);
if (newnode) {
- mempool_free( ndlp, phba->nlp_mem_pool);
+ lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
}
break;
}
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index adb086009ae..4d6cf990c4f 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1084,7 +1084,7 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
fc_remote_port_rolechg(rport, rport_ids.roles);
if ((rport->scsi_target_id != -1) &&
- (rport->scsi_target_id < MAX_FCP_TARGET)) {
+ (rport->scsi_target_id < LPFC_MAX_TARGET)) {
ndlp->nlp_sid = rport->scsi_target_id;
}
@@ -1313,7 +1313,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
if ((rport_add == mapped) &&
((!nlp->rport) ||
(nlp->rport->scsi_target_id == -1) ||
- (nlp->rport->scsi_target_id >= MAX_FCP_TARGET))) {
+ (nlp->rport->scsi_target_id >= LPFC_MAX_TARGET))) {
nlp->nlp_state = NLP_STE_UNMAPPED_NODE;
spin_lock_irq(phba->host->host_lock);
nlp->nlp_flag |= NLP_TGT_NO_SCSIID;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 81755a3f7c6..ef47b824cbe 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -71,6 +71,7 @@ lpfc_config_port_prep(struct lpfc_hba * phba)
uint16_t offset = 0;
static char licensed[56] =
"key unlock for use with gnu public licensed code only\0";
+ static int init_key = 1;
pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!pmb) {
@@ -82,10 +83,13 @@ lpfc_config_port_prep(struct lpfc_hba * phba)
phba->hba_state = LPFC_INIT_MBX_CMDS;
if (lpfc_is_LC_HBA(phba->pcidev->device)) {
- uint32_t *ptext = (uint32_t *) licensed;
+ if (init_key) {
+ uint32_t *ptext = (uint32_t *) licensed;
- for (i = 0; i < 56; i += sizeof (uint32_t), ptext++)
- *ptext = cpu_to_be32(*ptext);
+ for (i = 0; i < 56; i += sizeof (uint32_t), ptext++)
+ *ptext = cpu_to_be32(*ptext);
+ init_key = 0;
+ }
lpfc_read_nv(phba, pmb);
memset((char*)mb->un.varRDnvp.rsvd3, 0,
@@ -405,19 +409,26 @@ lpfc_config_port_post(struct lpfc_hba * phba)
}
/* MBOX buffer will be freed in mbox compl */
- i = 0;
+ return (0);
+}
+
+static int
+lpfc_discovery_wait(struct lpfc_hba *phba)
+{
+ int i = 0;
+
while ((phba->hba_state != LPFC_HBA_READY) ||
(phba->num_disc_nodes) || (phba->fc_prli_sent) ||
((phba->fc_map_cnt == 0) && (i<2)) ||
- (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE)) {
+ (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE)) {
/* Check every second for 30 retries. */
i++;
if (i > 30) {
- break;
+ return -ETIMEDOUT;
}
if ((i >= 15) && (phba->hba_state <= LPFC_LINK_DOWN)) {
/* The link is down. Set linkdown timeout */
- break;
+ return -ETIMEDOUT;
}
/* Delay for 1 second to give discovery time to complete. */
@@ -425,12 +436,7 @@ lpfc_config_port_post(struct lpfc_hba * phba)
}
- /* Since num_disc_nodes keys off of PLOGI, delay a bit to let
- * any potential PRLIs to flush thru the SLI sub-system.
- */
- msleep(50);
-
- return (0);
+ return 0;
}
/************************************************************************/
@@ -1339,7 +1345,8 @@ lpfc_offline(struct lpfc_hba * phba)
struct lpfc_sli_ring *pring;
struct lpfc_sli *psli;
unsigned long iflag;
- int i = 0;
+ int i;
+ int cnt = 0;
if (!phba)
return 0;
@@ -1348,17 +1355,27 @@ lpfc_offline(struct lpfc_hba * phba)
return 0;
psli = &phba->sli;
- pring = &psli->ring[psli->fcp_ring];
lpfc_linkdown(phba);
+ lpfc_sli_flush_mbox_queue(phba);
- /* The linkdown event takes 30 seconds to timeout. */
- while (pring->txcmplq_cnt) {
- mdelay(10);
- if (i++ > 3000)
- break;
+ for (i = 0; i < psli->num_rings; i++) {
+ pring = &psli->ring[i];
+ /* The linkdown event takes 30 seconds to timeout. */
+ while (pring->txcmplq_cnt) {
+ mdelay(10);
+ if (cnt++ > 3000) {
+ lpfc_printf_log(phba,
+ KERN_WARNING, LOG_INIT,
+ "%d:0466 Outstanding IO when "
+ "bringing Adapter offline\n",
+ phba->brd_no);
+ break;
+ }
+ }
}
+
/* stop all timers associated with this hba */
lpfc_stop_timer(phba);
phba->work_hba_events = 0;
@@ -1639,6 +1656,8 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
goto out_free_irq;
}
+ lpfc_discovery_wait(phba);
+
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
spin_lock_irq(phba->host->host_lock);
lpfc_poll_start_timer(phba);
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index 07017658ac5..066292d3995 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -133,6 +133,11 @@ lpfc_mem_free(struct lpfc_hba * phba)
pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
pci_pool_destroy(phba->lpfc_mbuf_pool);
+
+ /* Free the iocb lookup array */
+ kfree(psli->iocbq_lookup);
+ psli->iocbq_lookup = NULL;
+
}
void *
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 27d60ad897c..bd0b0e293d6 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -1110,6 +1110,17 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
phba->brd_no,
did, mb->mbxStatus, phba->hba_state);
+ /*
+ * If RegLogin failed due to lack of HBA resources do not
+ * retry discovery.
+ */
+ if (mb->mbxStatus == MBXERR_RPI_FULL) {
+ ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
+ ndlp->nlp_state = NLP_STE_UNUSED_NODE;
+ lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
+ return ndlp->nlp_state;
+ }
+
/* Put ndlp in npr list set plogi timer for 1 sec */
mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
spin_lock_irq(phba->host->host_lock);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index aea1ee472f3..a760a44173d 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -153,22 +153,6 @@ static void
lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
{
unsigned long iflag = 0;
- /*
- * There are only two special cases to consider. (1) the scsi command
- * requested scatter-gather usage or (2) the scsi command allocated
- * a request buffer, but did not request use_sg. There is a third
- * case, but it does not require resource deallocation.
- */
- if ((psb->seg_cnt > 0) && (psb->pCmd->use_sg)) {
- dma_unmap_sg(&phba->pcidev->dev, psb->pCmd->request_buffer,
- psb->seg_cnt, psb->pCmd->sc_data_direction);
- } else {
- if ((psb->nonsg_phys) && (psb->pCmd->request_bufflen)) {
- dma_unmap_single(&phba->pcidev->dev, psb->nonsg_phys,
- psb->pCmd->request_bufflen,
- psb->pCmd->sc_data_direction);
- }
- }
spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
psb->pCmd = NULL;
@@ -282,6 +266,27 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd)
}
static void
+lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
+{
+ /*
+ * There are only two special cases to consider. (1) the scsi command
+ * requested scatter-gather usage or (2) the scsi command allocated
+ * a request buffer, but did not request use_sg. There is a third
+ * case, but it does not require resource deallocation.
+ */
+ if ((psb->seg_cnt > 0) && (psb->pCmd->use_sg)) {
+ dma_unmap_sg(&phba->pcidev->dev, psb->pCmd->request_buffer,
+ psb->seg_cnt, psb->pCmd->sc_data_direction);
+ } else {
+ if ((psb->nonsg_phys) && (psb->pCmd->request_bufflen)) {
+ dma_unmap_single(&phba->pcidev->dev, psb->nonsg_phys,
+ psb->pCmd->request_bufflen,
+ psb->pCmd->sc_data_direction);
+ }
+ }
+}
+
+static void
lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd)
{
struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
@@ -454,6 +459,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
cmd->scsi_done(cmd);
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
+ lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
lpfc_release_scsi_buf(phba, lpfc_cmd);
return;
}
@@ -511,6 +517,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
}
}
+ lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
lpfc_release_scsi_buf(phba, lpfc_cmd);
}
@@ -609,6 +616,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd,
static int
lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
struct lpfc_scsi_buf *lpfc_cmd,
+ unsigned int lun,
uint8_t task_mgmt_cmd)
{
struct lpfc_sli *psli;
@@ -627,8 +635,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
piocb = &piocbq->iocb;
fcp_cmnd = lpfc_cmd->fcp_cmnd;
- int_to_scsilun(lpfc_cmd->pCmd->device->lun,
- &lpfc_cmd->fcp_cmnd->fcp_lun);
+ int_to_scsilun(lun, &lpfc_cmd->fcp_cmnd->fcp_lun);
fcp_cmnd->fcpCntl2 = task_mgmt_cmd;
piocb->ulpCommand = CMD_FCP_ICMND64_CR;
@@ -655,14 +662,16 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
static int
lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
- unsigned tgt_id, struct lpfc_rport_data *rdata)
+ unsigned tgt_id, unsigned int lun,
+ struct lpfc_rport_data *rdata)
{
struct lpfc_iocbq *iocbq;
struct lpfc_iocbq *iocbqrsp;
int ret;
lpfc_cmd->rdata = rdata;
- ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_TARGET_RESET);
+ ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, lun,
+ FCP_TARGET_RESET);
if (!ret)
return FAILED;
@@ -822,6 +831,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
return 0;
out_host_busy_free_buf:
+ lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
lpfc_release_scsi_buf(phba, lpfc_cmd);
out_host_busy:
return SCSI_MLQUEUE_HOST_BUSY;
@@ -969,12 +979,12 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
if (lpfc_cmd == NULL)
goto out;
- lpfc_cmd->pCmd = cmnd;
lpfc_cmd->timeout = 60;
lpfc_cmd->scsi_hba = phba;
lpfc_cmd->rdata = rdata;
- ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_LUN_RESET);
+ ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun,
+ FCP_LUN_RESET);
if (!ret)
goto out_free_scsi_buf;
@@ -1001,7 +1011,6 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
cmd_status = iocbqrsp->iocb.ulpStatus;
lpfc_sli_release_iocbq(phba, iocbqrsp);
- lpfc_release_scsi_buf(phba, lpfc_cmd);
/*
* All outstanding txcmplq I/Os should have been aborted by the device.
@@ -1040,6 +1049,8 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
}
out_free_scsi_buf:
+ lpfc_release_scsi_buf(phba, lpfc_cmd);
+
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"%d:0713 SCSI layer issued LUN reset (%d, %d) "
"Data: x%x x%x x%x\n",
@@ -1070,7 +1081,6 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
/* The lpfc_cmd storage is reused. Set all loop invariants. */
lpfc_cmd->timeout = 60;
- lpfc_cmd->pCmd = cmnd;
lpfc_cmd->scsi_hba = phba;
/*
@@ -1078,7 +1088,7 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
* targets known to the driver. Should any target reset
* fail, this routine returns failure to the midlayer.
*/
- for (i = 0; i < MAX_FCP_TARGET; i++) {
+ for (i = 0; i < LPFC_MAX_TARGET; i++) {
/* Search the mapped list for this target ID */
match = 0;
list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
@@ -1090,8 +1100,8 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
if (!match)
continue;
- ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba,
- i, ndlp->rport->dd_data);
+ ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba, i, cmnd->device->lun,
+ ndlp->rport->dd_data);
if (ret != SUCCESS) {
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"%d:0713 Bus Reset on target %d failed\n",
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index bb69a7a1ec5..350a625fa22 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -191,35 +191,12 @@ static int
lpfc_sli_ringtxcmpl_put(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring, struct lpfc_iocbq * piocb)
{
- uint16_t iotag;
-
list_add_tail(&piocb->list, &pring->txcmplq);
pring->txcmplq_cnt++;
if (unlikely(pring->ringno == LPFC_ELS_RING))
mod_timer(&phba->els_tmofunc,
jiffies + HZ * (phba->fc_ratov << 1));
- if (pring->fast_lookup) {
- /* Setup fast lookup based on iotag for completion */
- iotag = piocb->iocb.ulpIoTag;
- if (iotag && (iotag < pring->fast_iotag))
- *(pring->fast_lookup + iotag) = piocb;
- else {
-
- /* Cmd ring <ringno> put: iotag <iotag> greater then
- configured max <fast_iotag> wd0 <icmd> */
- lpfc_printf_log(phba,
- KERN_ERR,
- LOG_SLI,
- "%d:0316 Cmd ring %d put: iotag x%x "
- "greater then configured max x%x "
- "wd0 x%x\n",
- phba->brd_no,
- pring->ringno, iotag,
- pring->fast_iotag,
- *(((uint32_t *)(&piocb->iocb)) + 7));
- }
- }
return (0);
}
@@ -601,7 +578,7 @@ lpfc_sli_handle_mb_event(struct lpfc_hba * phba)
/* Stray Mailbox Interrupt, mbxCommand <cmd> mbxStatus
<status> */
lpfc_printf_log(phba,
- KERN_ERR,
+ KERN_WARNING,
LOG_MBOX | LOG_SLI,
"%d:0304 Stray Mailbox Interrupt "
"mbxCommand x%x mbxStatus x%x\n",
@@ -1570,8 +1547,8 @@ lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask)
void lpfc_reset_barrier(struct lpfc_hba * phba)
{
- uint32_t * resp_buf;
- uint32_t * mbox_buf;
+ uint32_t __iomem *resp_buf;
+ uint32_t __iomem *mbox_buf;
volatile uint32_t mbox;
uint32_t hc_copy;
int i;
@@ -1587,7 +1564,7 @@ void lpfc_reset_barrier(struct lpfc_hba * phba)
* Tell the other part of the chip to suspend temporarily all
* its DMA activity.
*/
- resp_buf = (uint32_t *)phba->MBslimaddr;
+ resp_buf = phba->MBslimaddr;
/* Disable the error attention */
hc_copy = readl(phba->HCregaddr);
@@ -1605,7 +1582,7 @@ void lpfc_reset_barrier(struct lpfc_hba * phba)
((MAILBOX_t *)&mbox)->mbxOwner = OWN_CHIP;
writel(BARRIER_TEST_PATTERN, (resp_buf + 1));
- mbox_buf = (uint32_t *)phba->MBslimaddr;
+ mbox_buf = phba->MBslimaddr;
writel(mbox, mbox_buf);
for (i = 0;
@@ -1805,7 +1782,7 @@ lpfc_sli_brdrestart(struct lpfc_hba * phba)
skip_post = 0;
word0 = 0; /* This is really setting up word1 */
}
- to_slim = (uint8_t *) phba->MBslimaddr + sizeof (uint32_t);
+ to_slim = phba->MBslimaddr + sizeof (uint32_t);
writel(*(uint32_t *) mb, to_slim);
readl(to_slim); /* flush */
@@ -2659,8 +2636,6 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
INIT_LIST_HEAD(&(pring->txq));
- kfree(pring->fast_lookup);
- pring->fast_lookup = NULL;
}
spin_unlock_irqrestore(phba->host->host_lock, flags);
@@ -3110,6 +3085,24 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
return retval;
}
+int
+lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba)
+{
+ int i = 0;
+
+ while (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE && !phba->stopped) {
+ if (i++ > LPFC_MBOX_TMO * 1000)
+ return 1;
+
+ if (lpfc_sli_handle_mb_event(phba) == 0)
+ i = 0;
+
+ msleep(1);
+ }
+
+ return (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) ? 1 : 0;
+}
+
irqreturn_t
lpfc_intr_handler(int irq, void *dev_id, struct pt_regs * regs)
{
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index a52d6c6cf08..d8ef0d2894d 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -135,8 +135,6 @@ struct lpfc_sli_ring {
uint32_t fast_iotag; /* max fastlookup based iotag */
uint32_t iotag_ctr; /* keeps track of the next iotag to use */
uint32_t iotag_max; /* max iotag value to use */
- struct lpfc_iocbq ** fast_lookup; /* array of IOCB ptrs indexed by
- iotag */
struct list_head txq;
uint16_t txq_cnt; /* current length of queue */
uint16_t txq_max; /* max length */
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 6b737568b83..10e89c6ae82 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "8.1.6"
+#define LPFC_DRIVER_VERSION "8.1.7"
#define LPFC_DRIVER_NAME "lpfc"
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 93edaa8696c..89ef34df5a1 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -378,7 +378,7 @@ static void set_dma_cmds(struct fsc_state *state, struct scsi_cmnd *cmd)
int nseg;
total = 0;
- scl = (struct scatterlist *) cmd->buffer;
+ scl = (struct scatterlist *) cmd->request_buffer;
nseg = pci_map_sg(state->pdev, scl, cmd->use_sg,
cmd->sc_data_direction);
for (i = 0; i < nseg; ++i) {
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index c88717727be..5572981a9f9 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -1268,7 +1268,7 @@ static void set_dma_cmds(struct mesh_state *ms, struct scsi_cmnd *cmd)
if (cmd->use_sg > 0) {
int nseg;
total = 0;
- scl = (struct scatterlist *) cmd->buffer;
+ scl = (struct scatterlist *) cmd->request_buffer;
off = ms->data_ptr;
nseg = pci_map_sg(ms->pdev, scl, cmd->use_sg,
cmd->sc_data_direction);
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
index 7abf64d1bfc..0bd9c60e645 100644
--- a/drivers/scsi/pluto.c
+++ b/drivers/scsi/pluto.c
@@ -169,8 +169,6 @@ int __init pluto_detect(struct scsi_host_template *tpnt)
SCpnt->request->rq_status = RQ_SCSI_BUSY;
SCpnt->done = pluto_detect_done;
- SCpnt->bufflen = 256;
- SCpnt->buffer = fcs[i].inquiry;
SCpnt->request_bufflen = 256;
SCpnt->request_buffer = fcs[i].inquiry;
PLD(("set up %d %08lx\n", i, (long)SCpnt))
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index 69e0551a81d..5b2f0741a55 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -874,7 +874,7 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd,
if (Cmnd->use_sg) {
int sg_count;
- sg = (struct scatterlist *) Cmnd->buffer;
+ sg = (struct scatterlist *) Cmnd->request_buffer;
sg_count = sbus_map_sg(qpti->sdev, sg, Cmnd->use_sg, Cmnd->sc_data_direction);
ds = cmd->dataseg;
@@ -1278,7 +1278,7 @@ static struct scsi_cmnd *qlogicpti_intr_handler(struct qlogicpti *qpti)
if (Cmnd->use_sg) {
sbus_unmap_sg(qpti->sdev,
- (struct scatterlist *)Cmnd->buffer,
+ (struct scatterlist *)Cmnd->request_buffer,
Cmnd->use_sg,
Cmnd->sc_data_direction);
} else {
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 64631bd3895..4776f4e5583 100644
--- a/drivers/scsi/sata_promise.c
+++ b/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/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index 2e0f4a4076a..3f368c7d3ef 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/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/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 2ab7df0dcfe..b332caddd5b 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -346,7 +346,7 @@ void scsi_log_send(struct scsi_cmnd *cmd)
if (level > 3) {
printk(KERN_INFO "buffer = 0x%p, bufflen = %d,"
" done = 0x%p, queuecommand 0x%p\n",
- cmd->buffer, cmd->bufflen,
+ cmd->request_buffer, cmd->request_bufflen,
cmd->done,
sdev->host->hostt->queuecommand);
@@ -661,11 +661,6 @@ void __scsi_done(struct scsi_cmnd *cmd)
*/
int scsi_retry_command(struct scsi_cmnd *cmd)
{
- /*
- * Restore the SCSI command state.
- */
- scsi_setup_cmd_retry(cmd);
-
/*
* Zero the sense information from the last time we tried
* this command.
@@ -711,10 +706,6 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
"Notifying upper driver of completion "
"(result %x)\n", cmd->result));
- /*
- * We can get here with use_sg=0, causing a panic in the upper level
- */
- cmd->use_sg = cmd->old_use_sg;
cmd->done(cmd);
}
EXPORT_SYMBOL(scsi_finish_command);
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 9c63b00773c..a80303c6b3f 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -286,7 +286,7 @@ static int inquiry_evpd_83(unsigned char * arr, int target_dev_id,
int dev_id_num, const char * dev_id_str,
int dev_id_str_len);
static int inquiry_evpd_88(unsigned char * arr, int target_dev_id);
-static void do_create_driverfs_files(void);
+static int do_create_driverfs_files(void);
static void do_remove_driverfs_files(void);
static int sdebug_add_adapter(void);
@@ -2487,19 +2487,22 @@ static ssize_t sdebug_add_host_store(struct device_driver * ddp,
DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show,
sdebug_add_host_store);
-static void do_create_driverfs_files(void)
+static int do_create_driverfs_files(void)
{
- driver_create_file(&sdebug_driverfs_driver, &driver_attr_add_host);
- driver_create_file(&sdebug_driverfs_driver, &driver_attr_delay);
- driver_create_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb);
- driver_create_file(&sdebug_driverfs_driver, &driver_attr_dsense);
- driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth);
- driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns);
- driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_tgts);
- driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_parts);
- driver_create_file(&sdebug_driverfs_driver, &driver_attr_ptype);
- driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts);
- driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level);
+ int ret;
+
+ ret = driver_create_file(&sdebug_driverfs_driver, &driver_attr_add_host);
+ ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_delay);
+ ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb);
+ ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dsense);
+ ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth);
+ ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns);
+ ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_tgts);
+ ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_parts);
+ ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_ptype);
+ ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts);
+ ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level);
+ return ret;
}
static void do_remove_driverfs_files(void)
@@ -2522,6 +2525,7 @@ static int __init scsi_debug_init(void)
unsigned int sz;
int host_to_add;
int k;
+ int ret;
if (scsi_debug_dev_size_mb < 1)
scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */
@@ -2560,12 +2564,32 @@ static int __init scsi_debug_init(void)
if (scsi_debug_num_parts > 0)
sdebug_build_parts(fake_storep);
- init_all_queued();
+ ret = device_register(&pseudo_primary);
+ if (ret < 0) {
+ printk(KERN_WARNING "scsi_debug: device_register error: %d\n",
+ ret);
+ goto free_vm;
+ }
+ ret = bus_register(&pseudo_lld_bus);
+ if (ret < 0) {
+ printk(KERN_WARNING "scsi_debug: bus_register error: %d\n",
+ ret);
+ goto dev_unreg;
+ }
+ ret = driver_register(&sdebug_driverfs_driver);
+ if (ret < 0) {
+ printk(KERN_WARNING "scsi_debug: driver_register error: %d\n",
+ ret);
+ goto bus_unreg;
+ }
+ ret = do_create_driverfs_files();
+ if (ret < 0) {
+ printk(KERN_WARNING "scsi_debug: driver_create_file error: %d\n",
+ ret);
+ goto del_files;
+ }
- device_register(&pseudo_primary);
- bus_register(&pseudo_lld_bus);
- driver_register(&sdebug_driverfs_driver);
- do_create_driverfs_files();
+ init_all_queued();
sdebug_driver_template.proc_name = (char *)sdebug_proc_name;
@@ -2585,6 +2609,18 @@ static int __init scsi_debug_init(void)
scsi_debug_add_host);
}
return 0;
+
+del_files:
+ do_remove_driverfs_files();
+ driver_unregister(&sdebug_driverfs_driver);
+bus_unreg:
+ bus_unregister(&pseudo_lld_bus);
+dev_unreg:
+ device_unregister(&pseudo_primary);
+free_vm:
+ vfree(fake_storep);
+
+ return ret;
}
static void __exit scsi_debug_exit(void)
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 6683d596234..6a5b731bd5b 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -460,19 +460,67 @@ static void scsi_eh_done(struct scsi_cmnd *scmd)
* Return value:
* SUCCESS or FAILED or NEEDS_RETRY
**/
-static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
+static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout, int copy_sense)
{
struct scsi_device *sdev = scmd->device;
struct Scsi_Host *shost = sdev->host;
+ int old_result = scmd->result;
DECLARE_COMPLETION(done);
unsigned long timeleft;
unsigned long flags;
+ unsigned char old_cmnd[MAX_COMMAND_SIZE];
+ enum dma_data_direction old_data_direction;
+ unsigned short old_use_sg;
+ unsigned char old_cmd_len;
+ unsigned old_bufflen;
+ void *old_buffer;
int rtn;
+ /*
+ * We need saved copies of a number of fields - this is because
+ * error handling may need to overwrite these with different values
+ * to run different commands, and once error handling is complete,
+ * we will need to restore these values prior to running the actual
+ * command.
+ */
+ old_buffer = scmd->request_buffer;
+ old_bufflen = scmd->request_bufflen;
+ memcpy(old_cmnd, scmd->cmnd, sizeof(scmd->cmnd));
+ old_data_direction = scmd->sc_data_direction;
+ old_cmd_len = scmd->cmd_len;
+ old_use_sg = scmd->use_sg;
+
+ if (copy_sense) {
+ int gfp_mask = GFP_ATOMIC;
+
+ if (shost->hostt->unchecked_isa_dma)
+ gfp_mask |= __GFP_DMA;
+
+ scmd->sc_data_direction = DMA_FROM_DEVICE;
+ scmd->request_bufflen = 252;
+ scmd->request_buffer = kzalloc(scmd->request_bufflen, gfp_mask);
+ if (!scmd->request_buffer)
+ return FAILED;
+ } else {
+ scmd->request_buffer = NULL;
+ scmd->request_bufflen = 0;
+ scmd->sc_data_direction = DMA_NONE;
+ }
+
+ scmd->underflow = 0;
+ scmd->use_sg = 0;
+ scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
+
if (sdev->scsi_level <= SCSI_2)
scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) |
(sdev->lun << 5 & 0xe0);
+ /*
+ * Zero the sense buffer. The scsi spec mandates that any
+ * untransferred sense data should be interpreted as being zero.
+ */
+ memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
+
shost->eh_action = &done;
spin_lock_irqsave(shost->host_lock, flags);
@@ -522,6 +570,29 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
rtn = FAILED;
}
+
+ /*
+ * Last chance to have valid sense data.
+ */
+ if (copy_sense) {
+ if (!SCSI_SENSE_VALID(scmd)) {
+ memcpy(scmd->sense_buffer, scmd->request_buffer,
+ sizeof(scmd->sense_buffer));
+ }
+ kfree(scmd->request_buffer);
+ }
+
+
+ /*
+ * Restore original data
+ */
+ scmd->request_buffer = old_buffer;
+ scmd->request_bufflen = old_bufflen;
+ memcpy(scmd->cmnd, old_cmnd, sizeof(scmd->cmnd));
+ scmd->sc_data_direction = old_data_direction;
+ scmd->cmd_len = old_cmd_len;
+ scmd->use_sg = old_use_sg;
+ scmd->result = old_result;
return rtn;
}
@@ -537,56 +608,10 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
static int scsi_request_sense(struct scsi_cmnd *scmd)
{
static unsigned char generic_sense[6] =
- {REQUEST_SENSE, 0, 0, 0, 252, 0};
- unsigned char *scsi_result;
- int saved_result;
- int rtn;
+ {REQUEST_SENSE, 0, 0, 0, 252, 0};
memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense));
-
- scsi_result = kmalloc(252, GFP_ATOMIC | ((scmd->device->host->hostt->unchecked_isa_dma) ? __GFP_DMA : 0));
-
-
- if (unlikely(!scsi_result)) {
- printk(KERN_ERR "%s: cannot allocate scsi_result.\n",
- __FUNCTION__);
- return FAILED;
- }
-
- /*
- * zero the sense buffer. some host adapters automatically always
- * request sense, so it is not a good idea that
- * scmd->request_buffer and scmd->sense_buffer point to the same
- * address (db). 0 is not a valid sense code.
- */
- memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
- memset(scsi_result, 0, 252);
-
- saved_result = scmd->result;
- scmd->request_buffer = scsi_result;
- scmd->request_bufflen = 252;
- scmd->use_sg = 0;
- scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
- scmd->sc_data_direction = DMA_FROM_DEVICE;
- scmd->underflow = 0;
-
- rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT);
-
- /* last chance to have valid sense data */
- if(!SCSI_SENSE_VALID(scmd)) {
- memcpy(scmd->sense_buffer, scmd->request_buffer,
- sizeof(scmd->sense_buffer));
- }
-
- kfree(scsi_result);
-
- /*
- * when we eventually call scsi_finish, we really wish to complete
- * the original request, so let's restore the original data. (db)
- */
- scsi_setup_cmd_retry(scmd);
- scmd->result = saved_result;
- return rtn;
+ return scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT, 1);
}
/**
@@ -605,12 +630,6 @@ void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
{
scmd->device->host->host_failed--;
scmd->eh_eflags = 0;
-
- /*
- * set this back so that the upper level can correctly free up
- * things.
- */
- scsi_setup_cmd_retry(scmd);
list_move_tail(&scmd->eh_entry, done_q);
}
EXPORT_SYMBOL(scsi_eh_finish_cmd);
@@ -715,47 +734,26 @@ static int scsi_eh_tur(struct scsi_cmnd *scmd)
{
static unsigned char tur_command[6] = {TEST_UNIT_READY, 0, 0, 0, 0, 0};
int retry_cnt = 1, rtn;
- int saved_result;
retry_tur:
memcpy(scmd->cmnd, tur_command, sizeof(tur_command));
- /*
- * zero the sense buffer. the scsi spec mandates that any
- * untransferred sense data should be interpreted as being zero.
- */
- memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
-
- saved_result = scmd->result;
- scmd->request_buffer = NULL;
- scmd->request_bufflen = 0;
- scmd->use_sg = 0;
- scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
- scmd->underflow = 0;
- scmd->sc_data_direction = DMA_NONE;
- rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT);
+ rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT, 0);
- /*
- * when we eventually call scsi_finish, we really wish to complete
- * the original request, so let's restore the original data. (db)
- */
- scsi_setup_cmd_retry(scmd);
- scmd->result = saved_result;
-
- /*
- * hey, we are done. let's look to see what happened.
- */
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
__FUNCTION__, scmd, rtn));
- if (rtn == SUCCESS)
- return 0;
- else if (rtn == NEEDS_RETRY) {
+
+ switch (rtn) {
+ case NEEDS_RETRY:
if (retry_cnt--)
goto retry_tur;
+ /*FALLTHRU*/
+ case SUCCESS:
return 0;
+ default:
+ return 1;
}
- return 1;
}
/**
@@ -837,44 +835,16 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
{
static unsigned char stu_command[6] = {START_STOP, 0, 0, 0, 1, 0};
- int rtn;
- int saved_result;
- if (!scmd->device->allow_restart)
- return 1;
-
- memcpy(scmd->cmnd, stu_command, sizeof(stu_command));
-
- /*
- * zero the sense buffer. the scsi spec mandates that any
- * untransferred sense data should be interpreted as being zero.
- */
- memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
-
- saved_result = scmd->result;
- scmd->request_buffer = NULL;
- scmd->request_bufflen = 0;
- scmd->use_sg = 0;
- scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
- scmd->underflow = 0;
- scmd->sc_data_direction = DMA_NONE;
+ if (scmd->device->allow_restart) {
+ int rtn;
- rtn = scsi_send_eh_cmnd(scmd, START_UNIT_TIMEOUT);
-
- /*
- * when we eventually call scsi_finish, we really wish to complete
- * the original request, so let's restore the original data. (db)
- */
- scsi_setup_cmd_retry(scmd);
- scmd->result = saved_result;
+ memcpy(scmd->cmnd, stu_command, sizeof(stu_command));
+ rtn = scsi_send_eh_cmnd(scmd, START_UNIT_TIMEOUT, 0);
+ if (rtn == SUCCESS)
+ return 0;
+ }
- /*
- * hey, we are done. let's look to see what happened.
- */
- SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
- __FUNCTION__, scmd, rtn));
- if (rtn == SUCCESS)
- return 0;
return 1;
}
@@ -1684,8 +1654,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
scmd->scsi_done = scsi_reset_provider_done_command;
scmd->done = NULL;
- scmd->buffer = NULL;
- scmd->bufflen = 0;
scmd->request_buffer = NULL;
scmd->request_bufflen = 0;
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index a89c4115cfb..32293f45166 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/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/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 08af9aae7df..077c1c69121 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -436,60 +436,16 @@ EXPORT_SYMBOL_GPL(scsi_execute_async);
*
* Arguments: cmd - command that is ready to be queued.
*
- * Returns: Nothing
- *
* Notes: This function has the job of initializing a number of
* fields related to error handling. Typically this will
* be called once for each command, as required.
*/
-static int scsi_init_cmd_errh(struct scsi_cmnd *cmd)
+static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
{
cmd->serial_number = 0;
-
memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer);
-
if (cmd->cmd_len == 0)
cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
-
- /*
- * We need saved copies of a number of fields - this is because
- * error handling may need to overwrite these with different values
- * to run different commands, and once error handling is complete,
- * we will need to restore these values prior to running the actual
- * command.
- */
- cmd->old_use_sg = cmd->use_sg;
- cmd->old_cmd_len = cmd->cmd_len;
- cmd->sc_old_data_direction = cmd->sc_data_direction;
- cmd->old_underflow = cmd->underflow;
- memcpy(cmd->data_cmnd, cmd->cmnd, sizeof(cmd->cmnd));
- cmd->buffer = cmd->request_buffer;
- cmd->bufflen = cmd->request_bufflen;
-
- return 1;
-}
-
-/*
- * Function: scsi_setup_cmd_retry()
- *
- * Purpose: Restore the command state for a retry
- *
- * Arguments: cmd - command to be restored
- *
- * Returns: Nothing
- *
- * Notes: Immediately prior to retrying a command, we need
- * to restore certain fields that we saved above.
- */
-void scsi_setup_cmd_retry(struct scsi_cmnd *cmd)
-{
- memcpy(cmd->cmnd, cmd->data_cmnd, sizeof(cmd->data_cmnd));
- cmd->request_buffer = cmd->buffer;
- cmd->request_bufflen = cmd->bufflen;
- cmd->use_sg = cmd->old_use_sg;
- cmd->cmd_len = cmd->old_cmd_len;
- cmd->sc_data_direction = cmd->sc_old_data_direction;
- cmd->underflow = cmd->old_underflow;
}
void scsi_device_unbusy(struct scsi_device *sdev)
@@ -807,22 +763,13 @@ static void scsi_free_sgtable(struct scatterlist *sgl, int index)
*/
static void scsi_release_buffers(struct scsi_cmnd *cmd)
{
- struct request *req = cmd->request;
-
- /*
- * Free up any indirection buffers we allocated for DMA purposes.
- */
if (cmd->use_sg)
scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
- else if (cmd->request_buffer != req->buffer)
- kfree(cmd->request_buffer);
/*
* Zero these out. They now point to freed memory, and it is
* dangerous to hang onto the pointers.
*/
- cmd->buffer = NULL;
- cmd->bufflen = 0;
cmd->request_buffer = NULL;
cmd->request_bufflen = 0;
}
@@ -858,7 +805,7 @@ static void scsi_release_buffers(struct scsi_cmnd *cmd)
void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
{
int result = cmd->result;
- int this_count = cmd->bufflen;
+ int this_count = cmd->request_bufflen;
request_queue_t *q = cmd->device->request_queue;
struct request *req = cmd->request;
int clear_errors = 1;
@@ -866,28 +813,14 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
int sense_valid = 0;
int sense_deferred = 0;
- /*
- * Free up any indirection buffers we allocated for DMA purposes.
- * For the case of a READ, we need to copy the data out of the
- * bounce buffer and into the real buffer.
- */
- if (cmd->use_sg)
- scsi_free_sgtable(cmd->buffer, cmd->sglist_len);
- else if (cmd->buffer != req->buffer) {
- if (rq_data_dir(req) == READ) {
- unsigned long flags;
- char *to = bio_kmap_irq(req->bio, &flags);
- memcpy(to, cmd->buffer, cmd->bufflen);
- bio_kunmap_irq(to, &flags);
- }
- kfree(cmd->buffer);
- }
+ scsi_release_buffers(cmd);
if (result) {
sense_valid = scsi_command_normalize_sense(cmd, &sshdr);
if (sense_valid)
sense_deferred = scsi_sense_is_deferred(&sshdr);
}
+
if (blk_pc_request(req)) { /* SG_IO ioctl from block level */
req->errors = result;
if (result) {
@@ -908,15 +841,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
}
/*
- * Zero these out. They now point to freed memory, and it is
- * dangerous to hang onto the pointers.
- */
- cmd->buffer = NULL;
- cmd->bufflen = 0;
- cmd->request_buffer = NULL;
- cmd->request_bufflen = 0;
-
- /*
* Next deal with any sectors which we were able to correctly
* handle.
*/
@@ -1012,7 +936,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
if (!(req->flags & REQ_QUIET)) {
scmd_printk(KERN_INFO, cmd,
"Volume overflow, CDB: ");
- __scsi_print_command(cmd->data_cmnd);
+ __scsi_print_command(cmd->cmnd);
scsi_print_sense("", cmd);
}
/* See SSC3rXX or current. */
@@ -1143,7 +1067,7 @@ static void scsi_blk_pc_done(struct scsi_cmnd *cmd)
* successfully. Since this is a REQ_BLOCK_PC command the
* caller should check the request's errors value
*/
- scsi_io_completion(cmd, cmd->bufflen);
+ scsi_io_completion(cmd, cmd->request_bufflen);
}
static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index e2fbe9a9d5a..ae24c85aaee 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -57,7 +57,6 @@ extern int scsi_eh_scmd_add(struct scsi_cmnd *, int);
/* scsi_lib.c */
extern int scsi_maybe_unblock_host(struct scsi_device *sdev);
-extern void scsi_setup_cmd_retry(struct scsi_cmnd *cmd);
extern void scsi_device_unbusy(struct scsi_device *sdev);
extern int scsi_queue_insert(struct scsi_cmnd *cmd, int reason);
extern void scsi_next_command(struct scsi_cmnd *cmd);
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index dd075627e60..5a625c3fdda 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -41,6 +41,7 @@ struct sas_host_attrs {
struct mutex lock;
u32 next_target_id;
u32 next_expander_id;
+ int next_port_id;
};
#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data)
@@ -146,6 +147,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev,
mutex_init(&sas_host->lock);
sas_host->next_target_id = 0;
sas_host->next_expander_id = 0;
+ sas_host->next_port_id = 0;
return 0;
}
@@ -327,7 +329,7 @@ sas_phy_protocol_attr(identify.target_port_protocols,
sas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
unsigned long long);
sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
-//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", u8);
+//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", int);
sas_phy_linkspeed_attr(negotiated_linkrate);
sas_phy_linkspeed_attr(minimum_linkrate_hw);
sas_phy_linkspeed_attr(minimum_linkrate);
@@ -590,6 +592,38 @@ struct sas_port *sas_port_alloc(struct device *parent, int port_id)
}
EXPORT_SYMBOL(sas_port_alloc);
+/** sas_port_alloc_num - allocate and initialize a SAS port structure
+ *
+ * @parent: parent device
+ *
+ * Allocates a SAS port structure and a number to go with it. This
+ * interface is really for adapters where the port number has no
+ * meansing, so the sas class should manage them. It will be added to
+ * the device tree below the device specified by @parent which must be
+ * either a Scsi_Host or a sas_expander_device.
+ *
+ * Returns %NULL on error
+ */
+struct sas_port *sas_port_alloc_num(struct device *parent)
+{
+ int index;
+ struct Scsi_Host *shost = dev_to_shost(parent);
+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+
+ /* FIXME: use idr for this eventually */
+ mutex_lock(&sas_host->lock);
+ if (scsi_is_sas_expander_device(parent)) {
+ struct sas_rphy *rphy = dev_to_rphy(parent);
+ struct sas_expander_device *exp = rphy_to_expander_device(rphy);
+
+ index = exp->next_port_id++;
+ } else
+ index = sas_host->next_port_id++;
+ mutex_unlock(&sas_host->lock);
+ return sas_port_alloc(parent, index);
+}
+EXPORT_SYMBOL(sas_port_alloc_num);
+
/**
* sas_port_add - add a SAS port to the device hierarchy
*
@@ -658,6 +692,13 @@ void sas_port_delete(struct sas_port *port)
}
mutex_unlock(&port->phy_list_mutex);
+ if (port->is_backlink) {
+ struct device *parent = port->dev.parent;
+
+ sysfs_remove_link(&port->dev.kobj, parent->bus_id);
+ port->is_backlink = 0;
+ }
+
transport_remove_device(dev);
device_del(dev);
transport_destroy_device(dev);
@@ -733,6 +774,19 @@ void sas_port_delete_phy(struct sas_port *port, struct sas_phy *phy)
}
EXPORT_SYMBOL(sas_port_delete_phy);
+void sas_port_mark_backlink(struct sas_port *port)
+{
+ struct device *parent = port->dev.parent->parent->parent;
+
+ if (port->is_backlink)
+ return;
+ port->is_backlink = 1;
+ sysfs_create_link(&port->dev.kobj, &parent->kobj,
+ parent->bus_id);
+
+}
+EXPORT_SYMBOL(sas_port_mark_backlink);
+
/*
* SAS remote PHY attributes.
*/
@@ -1140,7 +1194,7 @@ int sas_rphy_add(struct sas_rphy *rphy)
if (identify->device_type == SAS_END_DEVICE &&
rphy->scsi_target_id != -1) {
- scsi_scan_target(&rphy->dev, parent->port_identifier,
+ scsi_scan_target(&rphy->dev, 0,
rphy->scsi_target_id, ~0, 0);
}
@@ -1242,15 +1296,13 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
mutex_lock(&sas_host->lock);
list_for_each_entry(rphy, &sas_host->rphy_list, list) {
- struct sas_port *parent = dev_to_sas_port(rphy->dev.parent);
-
if (rphy->identify.device_type != SAS_END_DEVICE ||
rphy->scsi_target_id == -1)
continue;
- if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) &&
+ if ((channel == SCAN_WILD_CARD || channel == 0) &&
(id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) {
- scsi_scan_target(&rphy->dev, parent->port_identifier,
+ scsi_scan_target(&rphy->dev, 0,
rphy->scsi_target_id, lun, 1);
}
}
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 3225d31449e..98bd3aab973 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -502,8 +502,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
SCpnt->cmnd[4] = (unsigned char) this_count;
SCpnt->cmnd[5] = 0;
}
- SCpnt->request_bufflen = SCpnt->bufflen =
- this_count * sdp->sector_size;
+ SCpnt->request_bufflen = this_count * sdp->sector_size;
/*
* We shouldn't disconnect in the middle of a sector, so with a dumb
diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c
index 3f312a84c6a..2679ea8bff1 100644
--- a/drivers/scsi/seagate.c
+++ b/drivers/scsi/seagate.c
@@ -1002,7 +1002,7 @@ connect_loop:
}
#endif
- buffer = (struct scatterlist *) SCint->buffer;
+ buffer = (struct scatterlist *) SCint->request_buffer;
len = buffer->length;
data = page_address(buffer->page) + buffer->offset;
} else {
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index fd94408577e..fae6e95a629 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -360,7 +360,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
"mismatch count %d, bytes %d\n",
size, SCpnt->request_bufflen);
if (SCpnt->request_bufflen > size)
- SCpnt->request_bufflen = SCpnt->bufflen = size;
+ SCpnt->request_bufflen = size;
}
}
@@ -387,8 +387,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
if (this_count > 0xffff) {
this_count = 0xffff;
- SCpnt->request_bufflen = SCpnt->bufflen =
- this_count * s_size;
+ SCpnt->request_bufflen = this_count * s_size;
}
SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 756ceb93ddc..7f669b60067 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -368,7 +368,7 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
if (cmdstatp->have_sense)
- __scsi_print_sense("st", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
+ __scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
} ) /* end DEB */
if (!debugging) { /* Abnormal conditions for tape */
if (!cmdstatp->have_sense)
@@ -384,9 +384,8 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
scode != VOLUME_OVERFLOW &&
SRpnt->cmd[0] != MODE_SENSE &&
SRpnt->cmd[0] != TEST_UNIT_READY) {
- printk(KERN_WARNING "%s: Error with sense data: ", name);
- __scsi_print_sense("st", SRpnt->sense,
- SCSI_SENSE_BUFFERSIZE);
+
+ __scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
}
}
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c
index 2ebe0d66389..2f8073b73bf 100644
--- a/drivers/scsi/sun3_NCR5380.c
+++ b/drivers/scsi/sun3_NCR5380.c
@@ -517,7 +517,7 @@ static __inline__ void initialize_SCp(Scsi_Cmnd *cmd)
*/
if (cmd->use_sg) {
- cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;
+ cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
cmd->SCp.buffers_residual = cmd->use_sg - 1;
cmd->SCp.ptr = (char *) SGADDR(cmd->SCp.buffer);
cmd->SCp.this_residual = cmd->SCp.buffer->length;
diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
index 1f328cae5c0..6b60536ac92 100644
--- a/drivers/scsi/sun3x_esp.c
+++ b/drivers/scsi/sun3x_esp.c
@@ -347,7 +347,7 @@ static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp)
static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp)
{
int sz = sp->use_sg - 1;
- struct scatterlist *sg = (struct scatterlist *)sp->buffer;
+ struct scatterlist *sg = (struct scatterlist *)sp->request_buffer;
while(sz >= 0) {
dvma_unmap((char *)sg[sz].dma_address);
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index 680f38ab60d..2083454db51 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -373,7 +373,7 @@ wd33c93_queuecommand(struct scsi_cmnd *cmd,
*/
if (cmd->use_sg) {
- cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;
+ cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
cmd->SCp.buffers_residual = cmd->use_sg - 1;
cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) +
cmd->SCp.buffer->offset;
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 979497f108c..dc673e1b6fd 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -1047,12 +1047,13 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id *
up = &sunsab_ports[inst * 2];
err = sunsab_init_one(&up[0], op,
- sizeof(union sab82532_async_regs),
+ 0,
(inst * 2) + 0);
if (err)
return err;
- err = sunsab_init_one(&up[1], op, 0,
+ err = sunsab_init_one(&up[1], op,
+ sizeof(union sab82532_async_regs),
(inst * 2) + 1);
if (err) {
of_iounmap(up[0].port.membase,
@@ -1117,7 +1118,7 @@ static int __init sunsab_init(void)
int err;
num_channels = 0;
- for_each_node_by_name(dp, "su")
+ for_each_node_by_name(dp, "se")
num_channels += 2;
for_each_node_by_name(dp, "serial") {
if (of_device_is_compatible(dp, "sab82532"))
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index a1456d9352c..47bc3d57e01 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -68,9 +68,6 @@ static int num_sunzilog;
#define NUM_SUNZILOG num_sunzilog
#define NUM_CHANNELS (NUM_SUNZILOG * 2)
-#define KEYBOARD_LINE 0x2
-#define MOUSE_LINE 0x3
-
#define ZS_CLOCK 4915200 /* Zilog input clock rate. */
#define ZS_CLOCK_DIVISOR 16 /* Divisor this driver uses. */
@@ -1225,12 +1222,10 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
{
int baud, brg;
- if (channel == KEYBOARD_LINE) {
- up->flags |= SUNZILOG_FLAG_CONS_KEYB;
+ if (up->flags & SUNZILOG_FLAG_CONS_KEYB) {
up->cflag = B1200 | CS8 | CLOCAL | CREAD;
baud = 1200;
} else {
- up->flags |= SUNZILOG_FLAG_CONS_MOUSE;
up->cflag = B4800 | CS8 | CLOCAL | CREAD;
baud = 4800;
}
@@ -1243,14 +1238,14 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
}
#ifdef CONFIG_SERIO
-static void __init sunzilog_register_serio(struct uart_sunzilog_port *up, int channel)
+static void __init sunzilog_register_serio(struct uart_sunzilog_port *up)
{
struct serio *serio = &up->serio;
serio->port_data = up;
serio->id.type = SERIO_RS232;
- if (channel == KEYBOARD_LINE) {
+ if (up->flags & SUNZILOG_FLAG_CONS_KEYB) {
serio->id.proto = SERIO_SUNKBD;
strlcpy(serio->name, "zskbd", sizeof(serio->name));
} else {
@@ -1259,7 +1254,8 @@ static void __init sunzilog_register_serio(struct uart_sunzilog_port *up, int ch
strlcpy(serio->name, "zsms", sizeof(serio->name));
}
strlcpy(serio->phys,
- (channel == KEYBOARD_LINE ? "zs/serio0" : "zs/serio1"),
+ ((up->flags & SUNZILOG_FLAG_CONS_KEYB) ?
+ "zs/serio0" : "zs/serio1"),
sizeof(serio->phys));
serio->write = sunzilog_serio_write;
@@ -1286,8 +1282,8 @@ static void __init sunzilog_init_hw(struct uart_sunzilog_port *up)
(void) read_zsreg(channel, R0);
}
- if (up->port.line == KEYBOARD_LINE ||
- up->port.line == MOUSE_LINE) {
+ if (up->flags & (SUNZILOG_FLAG_CONS_KEYB |
+ SUNZILOG_FLAG_CONS_MOUSE)) {
sunzilog_init_kbdms(up, up->port.line);
up->curregs[R9] |= (NV | MIE);
write_zsreg(channel, R9, up->curregs[R9]);
@@ -1313,37 +1309,26 @@ static void __init sunzilog_init_hw(struct uart_sunzilog_port *up)
spin_unlock_irqrestore(&up->port.lock, flags);
#ifdef CONFIG_SERIO
- if (up->port.line == KEYBOARD_LINE || up->port.line == MOUSE_LINE)
- sunzilog_register_serio(up, up->port.line);
+ if (up->flags & (SUNZILOG_FLAG_CONS_KEYB |
+ SUNZILOG_FLAG_CONS_MOUSE))
+ sunzilog_register_serio(up);
#endif
}
-static int __devinit zs_get_instance(struct device_node *dp)
-{
- int ret;
-
- ret = of_getintprop_default(dp, "slave", -1);
- if (ret != -1)
- return ret;
-
- if (of_find_property(dp, "keyboard", NULL))
- ret = 1;
- else
- ret = 0;
-
- return ret;
-}
-
static int zilog_irq = -1;
-static int __devinit zs_probe(struct of_device *dev, const struct of_device_id *match)
+static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match)
{
- struct of_device *op = to_of_device(&dev->dev);
+ static int inst;
struct uart_sunzilog_port *up;
struct zilog_layout __iomem *rp;
- int inst = zs_get_instance(dev->node);
+ int keyboard_mouse;
int err;
+ keyboard_mouse = 0;
+ if (of_find_property(op->node, "keyboard", NULL))
+ keyboard_mouse = 1;
+
sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0,
sizeof(struct zilog_layout),
"zs");
@@ -1352,16 +1337,8 @@ static int __devinit zs_probe(struct of_device *dev, const struct of_device_id *
rp = sunzilog_chip_regs[inst];
- if (zilog_irq == -1) {
+ if (zilog_irq == -1)
zilog_irq = op->irqs[0];
- err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
- "zs", sunzilog_irq_chain);
- if (err) {
- of_iounmap(rp, sizeof(struct zilog_layout));
-
- return err;
- }
- }
up = &sunzilog_port_table[inst * 2];
@@ -1378,7 +1355,7 @@ static int __devinit zs_probe(struct of_device *dev, const struct of_device_id *
up[0].port.line = (inst * 2) + 0;
up[0].port.dev = &op->dev;
up[0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A;
- if (inst == 1)
+ if (keyboard_mouse)
up[0].flags |= SUNZILOG_FLAG_CONS_KEYB;
sunzilog_init_hw(&up[0]);
@@ -1395,11 +1372,11 @@ static int __devinit zs_probe(struct of_device *dev, const struct of_device_id *
up[1].port.line = (inst * 2) + 1;
up[1].port.dev = &op->dev;
up[1].flags |= 0;
- if (inst == 1)
+ if (keyboard_mouse)
up[1].flags |= SUNZILOG_FLAG_CONS_MOUSE;
sunzilog_init_hw(&up[1]);
- if (inst != 1) {
+ if (!keyboard_mouse) {
err = uart_add_one_port(&sunzilog_reg, &up[0].port);
if (err) {
of_iounmap(rp, sizeof(struct zilog_layout));
@@ -1411,9 +1388,18 @@ static int __devinit zs_probe(struct of_device *dev, const struct of_device_id *
of_iounmap(rp, sizeof(struct zilog_layout));
return err;
}
+ } else {
+ printk(KERN_INFO "%s: Keyboard at MMIO %lx (irq = %d) "
+ "is a zs\n",
+ op->dev.bus_id, up[0].port.mapbase, op->irqs[0]);
+ printk(KERN_INFO "%s: Mouse at MMIO %lx (irq = %d) "
+ "is a zs\n",
+ op->dev.bus_id, up[1].port.mapbase, op->irqs[0]);
}
- dev_set_drvdata(&dev->dev, &up[0]);
+ dev_set_drvdata(&op->dev, &up[0]);
+
+ inst++;
return 0;
}
@@ -1462,36 +1448,65 @@ static struct of_platform_driver zs_driver = {
static int __init sunzilog_init(void)
{
struct device_node *dp;
- int err;
+ int err, uart_count;
+ int num_keybms;
NUM_SUNZILOG = 0;
- for_each_node_by_name(dp, "zs")
+ num_keybms = 0;
+ for_each_node_by_name(dp, "zs") {
NUM_SUNZILOG++;
+ if (of_find_property(dp, "keyboard", NULL))
+ num_keybms++;
+ }
+ uart_count = 0;
if (NUM_SUNZILOG) {
int uart_count;
err = sunzilog_alloc_tables();
if (err)
- return err;
+ goto out;
- /* Subtract 1 for keyboard, 1 for mouse. */
- uart_count = (NUM_SUNZILOG * 2) - 2;
+ uart_count = (NUM_SUNZILOG * 2) - (2 * num_keybms);
sunzilog_reg.nr = uart_count;
sunzilog_reg.minor = sunserial_current_minor;
err = uart_register_driver(&sunzilog_reg);
- if (err) {
- sunzilog_free_tables();
- return err;
- }
+ if (err)
+ goto out_free_tables;
+
sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64;
sunzilog_reg.cons = SUNZILOG_CONSOLE();
sunserial_current_minor += uart_count;
}
- return of_register_driver(&zs_driver, &of_bus_type);
+ err = of_register_driver(&zs_driver, &of_bus_type);
+ if (err)
+ goto out_unregister_uart;
+
+ if (zilog_irq != -1) {
+ err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
+ "zs", sunzilog_irq_chain);
+ if (err)
+ goto out_unregister_driver;
+ }
+
+out:
+ return err;
+
+out_unregister_driver:
+ of_unregister_driver(&zs_driver);
+
+out_unregister_uart:
+ if (NUM_SUNZILOG) {
+ uart_unregister_driver(&sunzilog_reg);
+ sunzilog_reg.cons = NULL;
+ }
+
+out_free_tables:
+ sunzilog_free_tables();
+ goto out;
}
static void __exit sunzilog_exit(void)
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 2ee742d40c4..00504319752 100644
--- a/drivers/usb/Kconfig
+++ b/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/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index f7bdd94b3aa..218621b9958 100644
--- a/drivers/usb/core/devio.c
+++ b/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/drivers/usb/core/file.c b/drivers/usb/core/file.c
index abee0f5b6a6..8de4f8c99d6 100644
--- a/drivers/usb/core/file.c
+++ b/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/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 363b2ad74ae..1a32d96774b 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/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/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 1c459ff037c..cfebca05ead 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/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/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
index 5a4799cedd1..882af42e86c 100644
--- a/drivers/usb/gadget/at91_udc.h
+++ b/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/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 4be47195bd3..7d1c22c3495 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/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/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 85b0b4ad4c1..d63177a8eae 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/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/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index cdbafb71000..85cc059705a 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -4,7 +4,7 @@
* Copyright (C) 2004 SAN People (Pty) Ltd.
* Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
*
- * 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 <asm/hardware.h>
#include <asm/arch/board.h>
-#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/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index afef5ac35b4..94d8cf4b36c 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/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/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index c9d72ac0a1d..66c3f61bc9d 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/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/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index 05d2d6012eb..3719fcb04b8 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/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;
@@ -413,6 +414,43 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2)
}
/*
+ * 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
*/
static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)
@@ -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/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 028e1ad89f5..7208839f2db 100644
--- a/drivers/usb/input/hid-input.c
+++ b/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/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index 70477f02cc2..f6b839c257a 100644
--- a/drivers/usb/input/hiddev.c
+++ b/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/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c
index e091d327bd9..a4062a6adbb 100644
--- a/drivers/usb/misc/cypress_cy7c63.c
+++ b/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/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index e5e6e4f3ef8..bd09232ce13 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/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/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index ac33bd47cfc..f5b9438c94f 100644
--- a/drivers/usb/serial/Kconfig
+++ b/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/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 35d4acc7f1d..8efed2ce1ba 100644
--- a/drivers/usb/serial/Makefile
+++ b/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/drivers/usb/serial/anydata.c b/drivers/usb/serial/anydata.c
deleted file mode 100644
index 01843ef8c11..00000000000
--- a/drivers/usb/serial/anydata.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * AnyData CDMA Serial USB driver
- *
- * Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de>
- *
- * 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 <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/tty.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/usb/serial.h>
-
-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/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index b458aedc5fb..a20da8528a5 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -337,6 +337,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/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 04ef90fcb87..9f7343a4542 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -182,6 +182,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/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 59c5d999009..7e1bd5d6dfa 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -250,6 +250,7 @@ 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(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/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index f0530c1d7b7..c856e6f40e2 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -9,40 +9,14 @@
Portions copied from the Keyspan driver by Hugh Blemings <hugh@blemings.org>
- 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 <info@sigos.de>
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 @@ failed_1port_device_register:
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/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 259db31b65c..efbbc0adb89 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/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/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index d9c1e6e0b4b..a692ac66ca6 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/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/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index a5ca449f6e6..2793f9a912b 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/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 <mariorettig@web.de> */
+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 <sumedhaswamy@gmail.com> and
* Einar Th. Einarsson <einarthered@gmail.com> */
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
- * <Torsten.Eriksson@bergianska.se> 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 <phil@ipom.com>
- */
-UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200,
- "LaCie",
- "USB Hard Disk",
- US_SC_DEVICE, US_PR_CB, NULL, 0 ),
-
/* Submitted by Joel Bourquard <numlock@freesurf.ch>
* 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",
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 5ee19be52f6..8d7bdcb5924 100644
--- a/drivers/usb/storage/usb.c
+++ b/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/drivers/video/Kconfig b/drivers/video/Kconfig
index 6533b0f3923..c40b9b8b1e7 100644
--- a/drivers/video/Kconfig
+++ b/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
@@ -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/drivers/video/Makefile b/drivers/video/Makefile
index 95563c9c6b9..481c6c9695f 100644
--- a/drivers/video/Makefile
+++ b/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/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index c64a717e2d4..3e827e04a2a 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/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/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 1507d19f481..053ff63365b 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/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/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 8d85fc58142..8e3400d5dd2 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/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 \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
+#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/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index c7091761cef..f31e606a2de 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/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<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT)); // 440BX
- } else {
- OUTREG(BUS_CNTL1, INREG(BUS_CNTL1));
- OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000);
+ /* BUS_CNTL1__MOBILE_PLATORM_SEL setting is northbridge chipset
+ * and radeon chip dependent. Thus we only enable it on Mac for
+ * now (until we get more info on how to compute the correct
+ * value for various X86 bridges).
+ */
+#ifdef CONFIG_PPC_PMAC
+ if (machine_is(powermac)) {
+ /* 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<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT)); // 440BX
+ } else {
+ OUTREG(BUS_CNTL1, INREG(BUS_CNTL1));
+ OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000);
+ }
}
+#endif
OUTREG(CRTC_OFFSET_CNTL, (INREG(CRTC_OFFSET_CNTL)
& ~CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN));
@@ -2713,7 +2814,7 @@ static void radeonfb_early_resume(void *data)
#endif /* CONFIG_PM */
-void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
+void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep)
{
/* Find PM registers in config space if any*/
rinfo->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/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 38657b2d10e..d5ff224a625 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/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/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index a92a91fef16..f25d5d64833 100644
--- a/drivers/video/au1100fb.c
+++ b/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/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 022f9d3473f..02f15297a02 100644
--- a/drivers/video/backlight/Kconfig
+++ b/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/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
index 52ed12b12ac..eb4d03fa539 100644
--- a/drivers/video/console/mdacon.c
+++ b/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/drivers/video/fb_notify.c b/drivers/video/fb_notify.c
new file mode 100644
index 00000000000..8c020389e4f
--- /dev/null
+++ b/drivers/video/fb_notify.c
@@ -0,0 +1,46 @@
+/*
+ * linux/drivers/video/fb_notify.c
+ *
+ * Copyright (C) 2006 Antonino Daplas <adaplas@pol.net>
+ *
+ * 2001 - Documented with DocBook
+ * - Brad Douglas <brad@neruo.com>
+ *
+ * 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 <linux/fb.h>
+#include <linux/notifier.h>
+
+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/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 4fc9df426c1..17961e3ecaa 100644
--- a/drivers/video/fbmem.c
+++ b/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 = &blank;
- 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,30 +1358,11 @@ 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
* @state: 0 = resuming, !=0 = suspending
@@ -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/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 9f2066f0745..d4f85011787 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/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/drivers/video/offb.c b/drivers/video/offb.c
index ce5f3031b99..0013311e056 100644
--- a/drivers/video/offb.c
+++ b/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/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 33dddbae542..76fc9d355eb 100644
--- a/drivers/video/riva/fbdev.c
+++ b/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/fs/9p/conv.c b/fs/9p/conv.c
index 1e898144eb7..56d88c1a09c 100644
--- a/fs/9p/conv.c
+++ b/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/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 2f580a197b8..eae50c9d6dc 100644
--- a/fs/9p/vfs_inode.c
+++ b/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/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index fcaeead9696..50cfca5c7ef 100644
--- a/fs/befs/linuxvfs.c
+++ b/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/fs/buffer.c b/fs/buffer.c
index 3660dcb9759..71649ef9b65 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -470,13 +470,18 @@ out:
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/fs/coda/file.c b/fs/coda/file.c
index cc66c681bd1..dbfbcfa5b3c 100644
--- a/fs/coda/file.c
+++ b/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/fs/efs/symlink.c b/fs/efs/symlink.c
index e249cf733a6..1d30d2ff440 100644
--- a/fs/efs/symlink.c
+++ b/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/fs/ext3/inode.c b/fs/ext3/inode.c
index f804d5e9d60..c5ee9f0691e 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1158,7 +1158,7 @@ retry:
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/fs/ext3/namei.c b/fs/ext3/namei.c
index d9176dba369..2aa7101b27c 100644
--- a/fs/ext3/namei.c
+++ b/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/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 29cce456c7c..43886fa00a2 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/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/fs/fuse/control.c b/fs/fuse/control.c
index a3bce3a7725..46fe60b2da2 100644
--- a/fs/fuse/control.c
+++ b/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/fs/fuse/dir.c b/fs/fuse/dir.c
index 72a74cde6de..409ce6a7cca 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -14,6 +14,33 @@
#include <linux/sched.h>
#include <linux/namei.h>
+#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/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 0dbf9662184..69c7750d55b 100644
--- a/fs/fuse/fuse_i.h
+++ b/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/fs/fuse/inode.c b/fs/fuse/inode.c
index dcaaabd3b9c..7d25092262a 100644
--- a/fs/fuse/inode.c
+++ b/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/fs/inotify_user.c b/fs/inotify_user.c
index f2386442ade..017cb0f134d 100644
--- a/fs/inotify_user.c
+++ b/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/fs/lockd/svclock.c b/fs/lockd/svclock.c
index baf5ae51348..c9d419703cf 100644
--- a/fs/lockd/svclock.c
+++ b/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/fs/namei.c b/fs/namei.c
index e01070d7bf5..55a131230f9 100644
--- a/fs/namei.c
+++ b/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 @@ do_last:
* 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 @@ do_last:
if (flag & O_NOFOLLOW)
goto exit_dput;
}
+
error = -ENOENT;
if (!path.dentry->d_inode)
goto exit_dput;
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 19b98ca468e..86b3169c8ca 100644
--- a/fs/nfs/namespace.c
+++ b/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/fs/nfs/read.c b/fs/nfs/read.c
index 52bf634260a..65c0c5b3235 100644
--- a/fs/nfs/read.c
+++ b/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/fs/nfs/write.c b/fs/nfs/write.c
index 86bac6a5008..50774991f8d 100644
--- a/fs/nfs/write.c
+++ b/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/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index ecc439d2565..501d8388453 100644
--- a/fs/nfsd/nfsfh.c
+++ b/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/fs/partitions/Kconfig b/fs/partitions/Kconfig
index c9a47809928..e478f194183 100644
--- a/fs/partitions/Kconfig
+++ b/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/fs/reiserfs/file.c b/fs/reiserfs/file.c
index f318b58510f..1627edd5081 100644
--- a/fs/reiserfs/file.c
+++ b/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/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 12dfdcfbee3..52f1e213654 100644
--- a/fs/reiserfs/inode.c
+++ b/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/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
index 745c8810089..a986b5e1e28 100644
--- a/fs/reiserfs/ioctl.c
+++ b/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/fs/udf/ialloc.c b/fs/udf/ialloc.c
index 3873c672cb4..33323473e3c 100644
--- a/fs/udf/ialloc.c
+++ b/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/fs/ufs/balloc.c b/fs/ufs/balloc.c
index b01804baa12..b8238147577 100644
--- a/fs/ufs/balloc.c
+++ b/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/fs/ufs/namei.c b/fs/ufs/namei.c
index abd5f23a426..d344b411e26 100644
--- a/fs/ufs/namei.c
+++ b/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/fs/ufs/util.c b/fs/ufs/util.c
index 337cf2c46d1..22f820a9b15 100644
--- a/fs/ufs/util.c
+++ b/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 @@ try_again:
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 @@ try_again:
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/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index ceda3a2859d..7858703ed84 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/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/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 9bdef9d5190..4754f342a5d 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/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/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index e95e99f7168..f137856c326 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/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/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 86c1bf0bba9..1f8ecff8553 100644
--- a/fs/xfs/xfs_inode.c
+++ b/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/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index e730328636c..21ac1a67e3e 100644
--- a/fs/xfs/xfs_log.c
+++ b/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/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 6c96391f3f1..b427d220a16 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/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/include/asm-alpha/libata-portmap.h b/include/asm-alpha/libata-portmap.h
new file mode 100644
index 00000000000..75484ef0c74
--- /dev/null
+++ b/include/asm-alpha/libata-portmap.h
@@ -0,0 +1 @@
+#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-arm/arch-iop3xx/iop331-irqs.h b/include/asm-arm/arch-iop3xx/iop331-irqs.h
index 8ff73d48722..7135ad7e335 100644
--- a/include/asm-arm/arch-iop3xx/iop331-irqs.h
+++ b/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/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h
index 3c4eb9fbe48..f83003f5287 100644
--- a/include/asm-arm/arch-omap/clock.h
+++ b/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/include/asm-generic/libata-portmap.h b/include/asm-generic/libata-portmap.h
new file mode 100644
index 00000000000..9202fd02d5b
--- /dev/null
+++ b/include/asm-generic/libata-portmap.h
@@ -0,0 +1,12 @@
+#ifndef __ASM_GENERIC_LIBATA_PORTMAP_H
+#define __ASM_GENERIC_LIBATA_PORTMAP_H
+
+#define ATA_PRIMARY_CMD 0x1F0
+#define ATA_PRIMARY_CTL 0x3F6
+#define ATA_PRIMARY_IRQ 14
+
+#define ATA_SECONDARY_CMD 0x170
+#define ATA_SECONDARY_CTL 0x376
+#define ATA_SECONDARY_IRQ 15
+
+#endif
diff --git a/include/asm-i386/kprobes.h b/include/asm-i386/kprobes.h
index 0730a20f6db..8774d06689d 100644
--- a/include/asm-i386/kprobes.h
+++ b/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/include/asm-i386/libata-portmap.h b/include/asm-i386/libata-portmap.h
new file mode 100644
index 00000000000..75484ef0c74
--- /dev/null
+++ b/include/asm-i386/libata-portmap.h
@@ -0,0 +1 @@
+#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
index 2418a787c40..93890491011 100644
--- a/include/asm-ia64/kprobes.h
+++ b/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/include/asm-ia64/libata-portmap.h b/include/asm-ia64/libata-portmap.h
new file mode 100644
index 00000000000..75484ef0c74
--- /dev/null
+++ b/include/asm-ia64/libata-portmap.h
@@ -0,0 +1 @@
+#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-ia64/meminit.h b/include/asm-ia64/meminit.h
index 894bc4d89dc..6a33a07b3f1 100644
--- a/include/asm-ia64/meminit.h
+++ b/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/include/asm-ia64/pal.h b/include/asm-ia64/pal.h
index 37e52a2836b..20a8d618c84 100644
--- a/include/asm-ia64/pal.h
+++ b/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/include/asm-ia64/sn/xpc.h b/include/asm-ia64/sn/xpc.h
index 8406f1ef4ca..b72af597878 100644
--- a/include/asm-ia64/sn/xpc.h
+++ b/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/include/asm-ia64/system.h b/include/asm-ia64/system.h
index fc9677bc87e..384fbf7f2a0 100644
--- a/include/asm-ia64/system.h
+++ b/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/include/asm-m68k/oplib.h b/include/asm-m68k/oplib.h
index c3594f473ef..06caa2d0845 100644
--- a/include/asm-m68k/oplib.h
+++ b/include/asm-m68k/oplib.h
@@ -244,11 +244,6 @@ extern void prom_getstring(int node, char *prop, char *buf, int bufsize);
/* Does the passed node have the given "name"? YES=1 NO=0 */
extern int prom_nodematch(int thisnode, char *name);
-/* Puts in buffer a prom name in the form name@x,y or name (x for which_io
- * and y for first regs phys address
- */
-extern int prom_getname(int node, char *buf, int buflen);
-
/* Search all siblings starting at the passed node for "name" matching
* the given string. Returns the node on success, zero on failure.
*/
diff --git a/include/asm-powerpc/backlight.h b/include/asm-powerpc/backlight.h
index 58d4b6f8d82..8cf5c37c381 100644
--- a/include/asm-powerpc/backlight.h
+++ b/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/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h
index 2d0af52c823..34e1f89a5fa 100644
--- a/include/asm-powerpc/kprobes.h
+++ b/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/include/asm-powerpc/libata-portmap.h b/include/asm-powerpc/libata-portmap.h
new file mode 100644
index 00000000000..75484ef0c74
--- /dev/null
+++ b/include/asm-powerpc/libata-portmap.h
@@ -0,0 +1 @@
+#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
index 36a3a85d611..16040048cd1 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
@@ -128,8 +128,13 @@ extern void account_system_vtime(struct task_struct *);
#define nop() __asm__ __volatile__ ("nop")
-#define xchg(ptr,x) \
- ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(void *)(ptr),sizeof(*(ptr))))
+#define xchg(ptr,x) \
+({ \
+ __typeof__(*(ptr)) __ret; \
+ __ret = (__typeof__(*(ptr))) \
+ __xchg((unsigned long)(x), (void *)(ptr),sizeof(*(ptr))); \
+ __ret; \
+})
static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
{
diff --git a/include/asm-s390/timex.h b/include/asm-s390/timex.h
index 4848057dafe..5d0332a4c2b 100644
--- a/include/asm-s390/timex.h
+++ b/include/asm-s390/timex.h
@@ -19,7 +19,7 @@ static inline cycles_t get_cycles(void)
{
cycles_t cycles;
- __asm__("stck 0(%1)" : "=m" (cycles) : "a" (&cycles) : "cc");
+ __asm__ __volatile__ ("stck 0(%1)" : "=m" (cycles) : "a" (&cycles) : "cc");
return cycles >> 2;
}
@@ -27,7 +27,7 @@ static inline unsigned long long get_clock (void)
{
unsigned long long clk;
- __asm__("stck 0(%1)" : "=m" (clk) : "a" (&clk) : "cc");
+ __asm__ __volatile__ ("stck 0(%1)" : "=m" (clk) : "a" (&clk) : "cc");
return clk;
}
diff --git a/include/asm-sparc/libata-portmap.h b/include/asm-sparc/libata-portmap.h
new file mode 100644
index 00000000000..75484ef0c74
--- /dev/null
+++ b/include/asm-sparc/libata-portmap.h
@@ -0,0 +1 @@
+#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-sparc/oplib.h b/include/asm-sparc/oplib.h
index f283f8aaf6a..91691e52c05 100644
--- a/include/asm-sparc/oplib.h
+++ b/include/asm-sparc/oplib.h
@@ -267,11 +267,6 @@ extern void prom_getstring(int node, char *prop, char *buf, int bufsize);
/* Does the passed node have the given "name"? YES=1 NO=0 */
extern int prom_nodematch(int thisnode, char *name);
-/* Puts in buffer a prom name in the form name@x,y or name (x for which_io
- * and y for first regs phys address
- */
-extern int prom_getname(int node, char *buf, int buflen);
-
/* Search all siblings starting at the passed node for "name" matching
* the given string. Returns the node on success, zero on failure.
*/
diff --git a/include/asm-sparc/signal.h b/include/asm-sparc/signal.h
index 0ae5084c427..d03a21c97ab 100644
--- a/include/asm-sparc/signal.h
+++ b/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 <asm-generic/signal.h>
diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
index 15065af566c..c9f5c34d318 100644
--- a/include/asm-sparc64/kprobes.h
+++ b/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/include/asm-sparc64/libata-portmap.h b/include/asm-sparc64/libata-portmap.h
new file mode 100644
index 00000000000..75484ef0c74
--- /dev/null
+++ b/include/asm-sparc64/libata-portmap.h
@@ -0,0 +1 @@
+#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-sparc64/openprom.h b/include/asm-sparc64/openprom.h
index b4959d2b0d9..e01b80559c9 100644
--- a/include/asm-sparc64/openprom.h
+++ b/include/asm-sparc64/openprom.h
@@ -175,7 +175,7 @@ struct linux_nodeops {
};
/* More fun PROM structures for device probing. */
-#define PROMREG_MAX 16
+#define PROMREG_MAX 24
#define PROMVADDR_MAX 16
#define PROMINTR_MAX 15
diff --git a/include/asm-sparc64/oplib.h b/include/asm-sparc64/oplib.h
index a68b0bb0595..6a0da3b1695 100644
--- a/include/asm-sparc64/oplib.h
+++ b/include/asm-sparc64/oplib.h
@@ -287,11 +287,6 @@ extern void prom_getstring(int node, const char *prop, char *buf, int bufsize);
/* Does the passed node have the given "name"? YES=1 NO=0 */
extern int prom_nodematch(int thisnode, const char *name);
-/* Puts in buffer a prom name in the form name@x,y or name (x for which_io
- * and y for first regs phys address
- */
-extern int prom_getname(int node, char *buf, int buflen);
-
/* Search all siblings starting at the passed node for "name" matching
* the given string. Returns the node on success, zero on failure.
*/
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index 03f5bc9b6be..1ba19eb34ce 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/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/include/asm-sparc64/sfp-machine.h b/include/asm-sparc64/sfp-machine.h
index 5015bb8d6c3..89d42431efb 100644
--- a/include/asm-sparc64/sfp-machine.h
+++ b/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/include/asm-x86_64/calgary.h b/include/asm-x86_64/calgary.h
index fbfb50136ed..4e391952424 100644
--- a/include/asm-x86_64/calgary.h
+++ b/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/include/asm-x86_64/kprobes.h b/include/asm-x86_64/kprobes.h
index d36febd9bb1..cf5317898fb 100644
--- a/include/asm-x86_64/kprobes.h
+++ b/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/include/asm-x86_64/libata-portmap.h b/include/asm-x86_64/libata-portmap.h
new file mode 100644
index 00000000000..75484ef0c74
--- /dev/null
+++ b/include/asm-x86_64/libata-portmap.h
@@ -0,0 +1 @@
+#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index f7bf875aae4..10f346165ca 100644
--- a/include/asm-x86_64/page.h
+++ b/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/include/asm-x86_64/swiotlb.h b/include/asm-x86_64/swiotlb.h
index 5f9a0180582..ba94ab3d267 100644
--- a/include/asm-x86_64/swiotlb.h
+++ b/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/include/linux/audit.h b/include/linux/audit.h
index b27d7debc5a..64f9f9e56ac 100644
--- a/include/linux/audit.h
+++ b/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/include/linux/cn_proc.h b/include/linux/cn_proc.h
index dbb7769009b..1c86d65bc4b 100644
--- a/include/linux/cn_proc.h
+++ b/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/include/linux/cpu.h b/include/linux/cpu.h
index 44a11f1ccaf..8fb344a9abd 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -48,7 +48,6 @@ static inline void unregister_cpu_notifier(struct notifier_block *nb)
{
}
#endif
-extern int current_in_cpu_hotplug(void);
int cpu_up(unsigned int cpu);
@@ -61,10 +60,6 @@ static inline int register_cpu_notifier(struct notifier_block *nb)
static inline void unregister_cpu_notifier(struct notifier_block *nb)
{
}
-static inline int current_in_cpu_hotplug(void)
-{
- return 0;
-}
#endif /* CONFIG_SMP */
extern struct sysdev_class cpu_sysdev_class;
@@ -73,7 +68,6 @@ extern struct sysdev_class cpu_sysdev_class;
/* Stop CPUs going up and down. */
extern void lock_cpu_hotplug(void);
extern void unlock_cpu_hotplug(void);
-extern int lock_cpu_hotplug_interruptible(void);
#define hotcpu_notifier(fn, pri) { \
static struct notifier_block fn##_nb = \
{ .notifier_call = fn, .priority = pri }; \
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 35e137636b0..4ea39fee99c 100644
--- a/include/linux/cpufreq.h
+++ b/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/include/linux/debug_locks.h b/include/linux/debug_locks.h
index 6a7047851e4..88dafa246d8 100644
--- a/include/linux/debug_locks.h
+++ b/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/include/linux/delayacct.h b/include/linux/delayacct.h
index 7e8b6011b8f..11487b6e712 100644
--- a/include/linux/delayacct.h
+++ b/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/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 5607e6457a6..9f9cce7bd86 100644
--- a/include/linux/ext3_fs.h
+++ b/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/include/linux/fb.h b/include/linux/fb.h
index 405f44e44e5..4ad0673b199 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -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/include/linux/fsnotify.h b/include/linux/fsnotify.h
index cc5dec70c32..d4f219ffaa5 100644
--- a/include/linux/fsnotify.h
+++ b/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/include/linux/futex.h b/include/linux/futex.h
index 34c3a215f2c..d097b5b72bc 100644
--- a/include/linux/futex.h
+++ b/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/include/linux/ide.h b/include/linux/ide.h
index dc7abef1096..99620451d95 100644
--- a/include/linux/ide.h
+++ b/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/include/linux/input.h b/include/linux/input.h
index 56f1e0e1e59..b3253ab72ff 100644
--- a/include/linux/input.h
+++ b/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/include/linux/irq.h b/include/linux/irq.h
index b48eae32dc6..fbf6d901e9c 100644
--- a/include/linux/irq.h
+++ b/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/include/linux/jiffies.h b/include/linux/jiffies.h
index 043376920f5..329ebcffa10 100644
--- a/include/linux/jiffies.h
+++ b/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/include/linux/kobject.h b/include/linux/kobject.h
index 0503b2ed8ba..2d229327959 100644
--- a/include/linux/kobject.h
+++ b/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/include/linux/libata.h b/include/linux/libata.h
index 6cc497a2b6d..ed749f77869 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -36,6 +36,8 @@
#include <linux/workqueue.h>
#include <scsi/scsi_host.h>
+#include <asm/libata-portmap.h>
+
/*
* compile-time options: to be removed as soon as all the drivers are
* converted to the new debugging mechanism
@@ -265,12 +267,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,
@@ -348,12 +352,12 @@ struct ata_probe_ent {
struct scsi_host_template *sht;
struct ata_ioports port[ATA_MAX_PORTS];
unsigned int n_ports;
- unsigned int hard_port_no;
+ unsigned int dummy_port_mask;
unsigned int pio_mask;
unsigned int mwdma_mask;
unsigned int udma_mask;
- unsigned int legacy_mode;
unsigned long irq;
+ unsigned long irq2;
unsigned int irq_flags;
unsigned long host_flags;
unsigned long host_set_flags;
@@ -365,6 +369,7 @@ struct ata_host_set {
spinlock_t lock;
struct device *dev;
unsigned long irq;
+ unsigned long irq2;
void __iomem *mmio_base;
unsigned int n_ports;
void *private_data;
@@ -372,7 +377,6 @@ struct ata_host_set {
unsigned long flags;
int simplex_claimed; /* Keep seperate in case we
ever need to do this locked */
- struct ata_host_set *next; /* for legacy mode */
struct ata_port *ports[0];
};
@@ -503,7 +507,6 @@ struct ata_port {
unsigned int pflags; /* ATA_PFLAG_xxx */
unsigned int id; /* unique id req'd by scsi midlyr */
unsigned int port_no; /* unique port #; from zero */
- unsigned int hard_port_no; /* hardware port #; from zero */
struct ata_prd *prd; /* our SG list */
dma_addr_t prd_dma; /* and its DMA mapping */
@@ -647,6 +650,8 @@ extern const unsigned long sata_deb_timing_normal[];
extern const unsigned long sata_deb_timing_hotplug[];
extern const unsigned long sata_deb_timing_long[];
+extern const struct ata_port_operations ata_dummy_port_ops;
+
static inline const unsigned long *
sata_ehc_deb_timing(struct ata_eh_context *ehc)
{
@@ -656,6 +661,11 @@ sata_ehc_deb_timing(struct ata_eh_context *ehc)
return sata_deb_timing_normal;
}
+static inline int ata_port_is_dummy(struct ata_port *ap)
+{
+ return ap->ops == &ata_dummy_port_ops;
+}
+
extern void ata_port_probe(struct ata_port *);
extern void __sata_phy_reset(struct ata_port *ap);
extern void sata_phy_reset(struct ata_port *ap);
@@ -674,19 +684,30 @@ extern void ata_std_ports(struct ata_ioports *ioaddr);
extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
unsigned int n_ports);
extern void ata_pci_remove_one (struct pci_dev *pdev);
-extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t state);
+extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg);
extern void ata_pci_device_do_resume(struct pci_dev *pdev);
-extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state);
+extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
extern int ata_pci_device_resume(struct pci_dev *pdev);
extern int ata_pci_clear_simplex(struct pci_dev *pdev);
#endif /* CONFIG_PCI */
extern int ata_device_add(const struct ata_probe_ent *ent);
extern void ata_port_detach(struct ata_port *ap);
+extern void ata_host_set_init(struct ata_host_set *, struct device *,
+ unsigned long, const struct ata_port_operations *);
extern void ata_host_set_remove(struct ata_host_set *host_set);
extern int ata_scsi_detect(struct scsi_host_template *sht);
extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
extern int ata_scsi_release(struct Scsi_Host *host);
+extern void ata_sas_port_destroy(struct ata_port *);
+extern struct ata_port *ata_sas_port_alloc(struct ata_host_set *,
+ struct ata_port_info *, struct Scsi_Host *);
+extern int ata_sas_port_init(struct ata_port *);
+extern int ata_sas_port_start(struct ata_port *ap);
+extern void ata_sas_port_stop(struct ata_port *ap);
+extern int ata_sas_slave_configure(struct scsi_device *, struct ata_port *);
+extern int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
+ struct ata_port *ap);
extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
extern int sata_scr_valid(struct ata_port *ap);
extern int sata_scr_read(struct ata_port *ap, int reg, u32 *val);
@@ -695,7 +716,7 @@ extern int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val);
extern int ata_port_online(struct ata_port *ap);
extern int ata_port_offline(struct ata_port *ap);
extern int ata_scsi_device_resume(struct scsi_device *);
-extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state);
+extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t mesg);
extern int ata_host_set_suspend(struct ata_host_set *host_set,
pm_message_t mesg);
extern void ata_host_set_resume(struct ata_host_set *host_set);
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index aa4fe905bb4..0d92c468d55 100644
--- a/include/linux/lockd/lockd.h
+++ b/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/include/linux/netdevice.h b/include/linux/netdevice.h
index 76cc099c858..75f02d8c6ed 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -924,10 +924,10 @@ static inline void netif_tx_lock_bh(struct net_device *dev)
static inline int netif_tx_trylock(struct net_device *dev)
{
- int err = spin_trylock(&dev->_xmit_lock);
- if (!err)
+ int ok = spin_trylock(&dev->_xmit_lock);
+ if (likely(ok))
dev->xmit_lock_owner = smp_processor_id();
- return err;
+ return ok;
}
static inline void netif_tx_unlock(struct net_device *dev)
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index 87764022cc6..10c13dc4665 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -6,7 +6,6 @@
#include <linux/netfilter.h>
#if defined(__KERNEL__) && defined(CONFIG_BRIDGE_NETFILTER)
-#include <asm/atomic.h>
#include <linux/if_ether.h>
#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/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 55ea853d57b..247434553ae 100644
--- a/include/linux/nfs_fs.h
+++ b/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/include/linux/pci_ids.h b/include/linux/pci_ids.h
index c09396d2c77..4eae06b08cf 100644
--- a/include/linux/pci_ids.h
+++ b/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/include/linux/pmu.h b/include/linux/pmu.h
index 2ed807ddc08..783177387ac 100644
--- a/include/linux/pmu.h
+++ b/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/include/linux/sched.h b/include/linux/sched.h
index 6afa72e080c..6674fc1e51b 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1558,6 +1558,14 @@ static inline void freeze(struct task_struct *p)
}
/*
+ * 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
*/
static inline int thaw_process(struct task_struct *p)
diff --git a/include/linux/security.h b/include/linux/security.h
index f75303831d0..6bc2aad494f 100644
--- a/include/linux/security.h
+++ b/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/include/linux/skbuff.h b/include/linux/skbuff.h
index 0bf31b83578..19c96d498e2 100644
--- a/include/linux/skbuff.h
+++ b/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;
}
@@ -1066,9 +1071,8 @@ static inline void __skb_queue_purge(struct sk_buff_head *list)
kfree_skb(skb);
}
-#ifndef CONFIG_HAVE_ARCH_DEV_ALLOC_SKB
/**
- * __dev_alloc_skb - allocate an skbuff for sending
+ * __dev_alloc_skb - allocate an skbuff for receiving
* @length: length to allocate
* @gfp_mask: get_free_pages mask, passed to alloc_skb
*
@@ -1087,12 +1091,9 @@ static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
skb_reserve(skb, NET_SKB_PAD);
return skb;
}
-#else
-extern struct sk_buff *__dev_alloc_skb(unsigned int length, int gfp_mask);
-#endif
/**
- * dev_alloc_skb - allocate an skbuff for sending
+ * dev_alloc_skb - allocate an skbuff for receiving
* @length: length to allocate
*
* Allocate a new &sk_buff and assign it a usage count of one. The
@@ -1108,6 +1109,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/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index e8bbe8118de..840e47a4ccc 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/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/include/linux/usb.h b/include/linux/usb.h
index c944e8f06a4..d2bd0c8e015 100644
--- a/include/linux/usb.h
+++ b/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/include/linux/usb_usual.h b/include/linux/usb_usual.h
index f38f43f20fa..e7fc5fed5b9 100644
--- a/include/linux/usb_usual.h
+++ b/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/include/linux/videodev.h b/include/linux/videodev.h
index 41bc7e9603c..518c7a32175 100644
--- a/include/linux/videodev.h
+++ b/include/linux/videodev.h
@@ -12,10 +12,11 @@
#ifndef __LINUX_VIDEODEV_H
#define __LINUX_VIDEODEV_H
-#define HAVE_V4L1 1
-
#include <linux/videodev2.h>
+#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/include/linux/videodev2.h b/include/linux/videodev2.h
index a62673dad76..b7146956a92 100644
--- a/include/linux/videodev2.h
+++ b/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/include/linux/vmstat.h b/include/linux/vmstat.h
index 1ab806c4751..2d9b1b60798 100644
--- a/include/linux/vmstat.h
+++ b/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/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index 62dae1a8c44..f8665326ed9 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -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/include/net/af_unix.h b/include/net/af_unix.h
index 2fec827c880..c0398f5a8cb 100644
--- a/include/net/af_unix.h
+++ b/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/include/net/ip6_route.h b/include/net/ip6_route.h
index ab29dafb1a6..96b0e66406e 100644
--- a/include/net/ip6_route.h
+++ b/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/include/net/ipv6.h b/include/net/ipv6.h
index a8fdf7970b3..ece7e8a84ff 100644
--- a/include/net/ipv6.h
+++ b/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/include/net/netdma.h b/include/net/netdma.h
index 19760eb131a..7f53cd1d8b1 100644
--- a/include/net/netdma.h
+++ b/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();
@@ -37,7 +37,7 @@ static inline struct dma_chan *get_softnet_dma(void)
}
int dma_skb_copy_datagram_iovec(struct dma_chan* chan,
- const struct sk_buff *skb, int offset, struct iovec *to,
+ struct sk_buff *skb, int offset, struct iovec *to,
size_t len, struct dma_pinned_list *pinned_list);
#endif /* CONFIG_NET_DMA */
diff --git a/include/net/netevent.h b/include/net/netevent.h
new file mode 100644
index 00000000000..e5d21624142
--- /dev/null
+++ b/include/net/netevent.h
@@ -0,0 +1,33 @@
+#ifndef _NET_EVENT_H
+#define _NET_EVENT_H
+
+/*
+ * Generic netevent notifiers
+ *
+ * Authors:
+ * Tom Tucker <tom@opengridcomputing.com>
+ * Steve Wise <swise@opengridcomputing.com>
+ *
+ * Changes:
+ */
+#ifdef __KERNEL__
+
+#include <net/dst.h>
+
+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/include/net/pkt_sched.h b/include/net/pkt_sched.h
index 1925c65e617..f6afee73235 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -169,23 +169,17 @@ psched_tod_diff(int delta_sec, int bound)
#define PSCHED_TADD2(tv, delta, tv_res) \
({ \
- int __delta = (delta); \
- (tv_res) = (tv); \
- while(__delta >= USEC_PER_SEC){ \
- (tv_res).tv_sec++; \
- __delta -= USEC_PER_SEC; \
- } \
+ int __delta = (tv).tv_usec + (delta); \
+ (tv_res).tv_sec = (tv).tv_sec; \
+ while (__delta >= USEC_PER_SEC) { (tv_res).tv_sec++; __delta -= USEC_PER_SEC; } \
(tv_res).tv_usec = __delta; \
})
#define PSCHED_TADD(tv, delta) \
({ \
- int __delta = (delta); \
- while(__delta >= USEC_PER_SEC){ \
- (tv).tv_sec++; \
- __delta -= USEC_PER_SEC; \
- } \
- (tv).tv_usec = __delta; \
+ (tv).tv_usec += (delta); \
+ while ((tv).tv_usec >= USEC_PER_SEC) { (tv).tv_sec++; \
+ (tv).tv_usec -= USEC_PER_SEC; } \
})
/* Set/check that time is in the "past perfect";
diff --git a/include/net/red.h b/include/net/red.h
index 5ccdbb3d472..a4eb37946f2 100644
--- a/include/net/red.h
+++ b/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/include/net/scm.h b/include/net/scm.h
index 02daa097cdc..5637d5e22d5 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -3,6 +3,7 @@
#include <linux/limits.h>
#include <linux/net.h>
+#include <linux/security.h>
/* 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/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 5f69158c100..e5aa7ff1f5b 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -445,6 +445,7 @@ typedef struct sctp_sender_hb_info {
struct sctp_paramhdr param_hdr;
union sctp_addr daddr;
unsigned long sent_at;
+ __u64 hb_nonce;
} __attribute__((packed)) sctp_sender_hb_info_t;
/*
@@ -730,13 +731,10 @@ void sctp_init_addrs(struct sctp_chunk *, union sctp_addr *,
const union sctp_addr *sctp_source(const struct sctp_chunk *chunk);
/* This is a structure for holding either an IPv6 or an IPv4 address. */
-/* sin_family -- AF_INET or AF_INET6
- * sin_port -- ordinary port number
- * sin_addr -- cast to either (struct in_addr) or (struct in6_addr)
- */
struct sctp_sockaddr_entry {
struct list_head list;
union sctp_addr a;
+ __u8 use_as_src;
};
typedef struct sctp_chunk *(sctp_packet_phandler_t)(struct sctp_association *);
@@ -984,6 +982,9 @@ struct sctp_transport {
*/
char cacc_saw_newack;
} cacc;
+
+ /* 64-bit random number sent with heartbeat. */
+ __u64 hb_nonce;
};
struct sctp_transport *sctp_transport_new(const union sctp_addr *,
@@ -1138,7 +1139,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
sctp_scope_t scope, gfp_t gfp,
int flags);
int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
- gfp_t gfp);
+ __u8 use_as_src, gfp_t gfp);
int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
struct sctp_sock *);
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
index 8a6bef6f91e..1b7aae6cdd8 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -560,9 +560,18 @@ struct sctp_paddrinfo {
} __attribute__((packed, aligned(4)));
/* Peer addresses's state. */
+/* UNKNOWN: Peer address passed by the upper layer in sendmsg or connect[x]
+ * calls.
+ * UNCONFIRMED: Peer address received in INIT/INIT-ACK address parameters.
+ * Not yet confirmed by a heartbeat and not available for data
+ * transfers.
+ * ACTIVE : Peer address confirmed, active and available for data transfers.
+ * INACTIVE: Peer address inactive and not available for data transfers.
+ */
enum sctp_spinfo_state {
SCTP_INACTIVE,
SCTP_ACTIVE,
+ SCTP_UNCONFIRMED,
SCTP_UNKNOWN = 0xffff /* Value used for transport state unknown */
};
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 0720bddff1e..7a093d0aa0f 100644
--- a/include/net/tcp.h
+++ b/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/include/rdma/ib_mad.h b/include/rdma/ib_mad.h
index 5ff77558013..585d28e960d 100644
--- a/include/rdma/ib_mad.h
+++ b/include/rdma/ib_mad.h
@@ -75,6 +75,7 @@
#define IB_MGMT_METHOD_TRAP_REPRESS 0x07
#define IB_MGMT_METHOD_RESP 0x80
+#define IB_BM_ATTR_MOD_RESP cpu_to_be32(1)
#define IB_MGMT_MAX_METHODS 128
@@ -247,6 +248,12 @@ struct ib_mad_send_buf {
};
/**
+ * ib_response_mad - Returns if the specified MAD has been generated in
+ * response to a sent request or trap.
+ */
+int ib_response_mad(struct ib_mad *mad);
+
+/**
* ib_get_rmpp_resptime - Returns the RMPP response time.
* @rmpp_hdr: An RMPP header.
*/
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 371f70d9aa9..58e6444eebe 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -58,9 +58,7 @@ struct scsi_cmnd {
int timeout_per_command;
unsigned char cmd_len;
- unsigned char old_cmd_len;
enum dma_data_direction sc_data_direction;
- enum dma_data_direction sc_old_data_direction;
/* These elements define the operation we are about to perform */
#define MAX_COMMAND_SIZE 16
@@ -71,18 +69,11 @@ struct scsi_cmnd {
void *request_buffer; /* Actual requested buffer */
/* These elements define the operation we ultimately want to perform */
- unsigned char data_cmnd[MAX_COMMAND_SIZE];
- unsigned short old_use_sg; /* We save use_sg here when requesting
- * sense info */
unsigned short use_sg; /* Number of pieces of scatter-gather */
unsigned short sglist_len; /* size of malloc'd scatter-gather list */
- unsigned bufflen; /* Size of data buffer */
- void *buffer; /* Data buffer */
unsigned underflow; /* Return error if less than
this amount is transferred */
- unsigned old_underflow; /* save underflow here when reusing the
- * command for error handling */
unsigned transfersize; /* How much we are guaranteed to
transfer with each SCSI transfer
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h
index e3c503cd175..6cc2314098c 100644
--- a/include/scsi/scsi_transport_sas.h
+++ b/include/scsi/scsi_transport_sas.h
@@ -106,6 +106,7 @@ struct sas_end_device {
struct sas_expander_device {
int level;
+ int next_port_id;
#define SAS_EXPANDER_VENDOR_ID_LEN 8
char vendor_id[SAS_EXPANDER_VENDOR_ID_LEN+1];
@@ -127,8 +128,10 @@ struct sas_expander_device {
struct sas_port {
struct device dev;
- u8 port_identifier;
+ int port_identifier;
int num_phys;
+ /* port flags */
+ unsigned int is_backlink:1;
/* the other end of the link */
struct sas_rphy *rphy;
@@ -168,11 +171,13 @@ extern void sas_rphy_delete(struct sas_rphy *);
extern int scsi_is_sas_rphy(const struct device *);
struct sas_port *sas_port_alloc(struct device *, int);
+struct sas_port *sas_port_alloc_num(struct device *);
int sas_port_add(struct sas_port *);
void sas_port_free(struct sas_port *);
void sas_port_delete(struct sas_port *);
void sas_port_add_phy(struct sas_port *, struct sas_phy *);
void sas_port_delete_phy(struct sas_port *, struct sas_phy *);
+void sas_port_mark_backlink(struct sas_port *);
int scsi_is_sas_port(const struct device *);
extern struct scsi_transport_template *
diff --git a/ipc/msg.c b/ipc/msg.c
index cd92d342953..2b4fccf8ea5 100644
--- a/ipc/msg.c
+++ b/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 @@ out_unlock:
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 @@ out_unlock:
}
}
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/kernel/audit.c b/kernel/audit.c
index d417ca1db79..0a36091ed71 100644
--- a/kernel/audit.c
+++ b/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/kernel/auditfilter.c b/kernel/auditfilter.c
index 5b4e16276ca..6a9a5c5a4e7 100644
--- a/kernel/auditfilter.c
+++ b/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/kernel/auditsc.c b/kernel/auditsc.c
index ae40ac8c39e..efc1b74bebf 100644
--- a/kernel/auditsc.c
+++ b/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 @@ update_context:
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/kernel/cpu.c b/kernel/cpu.c
index 70fbf2e8376..f230f9ae01c 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -16,56 +16,48 @@
#include <linux/mutex.h>
/* This protects CPUs going up and down... */
-static DEFINE_MUTEX(cpucontrol);
+static DEFINE_MUTEX(cpu_add_remove_lock);
+static DEFINE_MUTEX(cpu_bitmask_lock);
static __cpuinitdata BLOCKING_NOTIFIER_HEAD(cpu_chain);
#ifdef CONFIG_HOTPLUG_CPU
-static struct task_struct *lock_cpu_hotplug_owner;
-static int lock_cpu_hotplug_depth;
-static int __lock_cpu_hotplug(int interruptible)
-{
- int ret = 0;
-
- if (lock_cpu_hotplug_owner != current) {
- if (interruptible)
- ret = mutex_lock_interruptible(&cpucontrol);
- else
- mutex_lock(&cpucontrol);
- }
-
- /*
- * Set only if we succeed in locking
- */
- if (!ret) {
- lock_cpu_hotplug_depth++;
- lock_cpu_hotplug_owner = current;
- }
-
- return ret;
-}
+/* Crappy recursive lock-takers in cpufreq! Complain loudly about idiots */
+static struct task_struct *recursive;
+static int recursive_depth;
void lock_cpu_hotplug(void)
{
- __lock_cpu_hotplug(0);
+ struct task_struct *tsk = current;
+
+ if (tsk == recursive) {
+ static int warnings = 10;
+ if (warnings) {
+ printk(KERN_ERR "Lukewarm IQ detected in hotplug locking\n");
+ WARN_ON(1);
+ warnings--;
+ }
+ recursive_depth++;
+ return;
+ }
+ mutex_lock(&cpu_bitmask_lock);
+ recursive = tsk;
}
EXPORT_SYMBOL_GPL(lock_cpu_hotplug);
void unlock_cpu_hotplug(void)
{
- if (--lock_cpu_hotplug_depth == 0) {
- lock_cpu_hotplug_owner = NULL;
- mutex_unlock(&cpucontrol);
+ WARN_ON(recursive != current);
+ if (recursive_depth) {
+ recursive_depth--;
+ return;
}
+ mutex_unlock(&cpu_bitmask_lock);
+ recursive = NULL;
}
EXPORT_SYMBOL_GPL(unlock_cpu_hotplug);
-int lock_cpu_hotplug_interruptible(void)
-{
- return __lock_cpu_hotplug(1);
-}
-EXPORT_SYMBOL_GPL(lock_cpu_hotplug_interruptible);
#endif /* CONFIG_HOTPLUG_CPU */
/* Need to know about CPUs going up/down? */
@@ -122,9 +114,7 @@ int cpu_down(unsigned int cpu)
struct task_struct *p;
cpumask_t old_allowed, tmp;
- if ((err = lock_cpu_hotplug_interruptible()) != 0)
- return err;
-
+ mutex_lock(&cpu_add_remove_lock);
if (num_online_cpus() == 1) {
err = -EBUSY;
goto out;
@@ -150,7 +140,10 @@ int cpu_down(unsigned int cpu)
cpu_clear(cpu, tmp);
set_cpus_allowed(current, tmp);
+ mutex_lock(&cpu_bitmask_lock);
p = __stop_machine_run(take_cpu_down, NULL, cpu);
+ mutex_unlock(&cpu_bitmask_lock);
+
if (IS_ERR(p)) {
/* CPU didn't die: tell everyone. Can't complain. */
if (blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED,
@@ -187,7 +180,7 @@ out_thread:
out_allowed:
set_cpus_allowed(current, old_allowed);
out:
- unlock_cpu_hotplug();
+ mutex_unlock(&cpu_add_remove_lock);
return err;
}
#endif /*CONFIG_HOTPLUG_CPU*/
@@ -197,9 +190,7 @@ int __devinit cpu_up(unsigned int cpu)
int ret;
void *hcpu = (void *)(long)cpu;
- if ((ret = lock_cpu_hotplug_interruptible()) != 0)
- return ret;
-
+ mutex_lock(&cpu_add_remove_lock);
if (cpu_online(cpu) || !cpu_present(cpu)) {
ret = -EINVAL;
goto out;
@@ -214,7 +205,9 @@ int __devinit cpu_up(unsigned int cpu)
}
/* Arch-specific enabling code. */
+ mutex_lock(&cpu_bitmask_lock);
ret = __cpu_up(cpu);
+ mutex_unlock(&cpu_bitmask_lock);
if (ret != 0)
goto out_notify;
BUG_ON(!cpu_online(cpu));
@@ -227,6 +220,6 @@ out_notify:
blocking_notifier_call_chain(&cpu_chain,
CPU_UP_CANCELED, hcpu);
out:
- unlock_cpu_hotplug();
+ mutex_unlock(&cpu_add_remove_lock);
return ret;
}
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index c232dc07743..1a649f2bb9b 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -762,6 +762,8 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
*
* Call with manage_mutex held. May nest a call to the
* lock_cpu_hotplug()/unlock_cpu_hotplug() pair.
+ * Must not be called holding callback_mutex, because we must
+ * not call lock_cpu_hotplug() while holding callback_mutex.
*/
static void update_cpu_domains(struct cpuset *cur)
@@ -781,7 +783,7 @@ static void update_cpu_domains(struct cpuset *cur)
if (is_cpu_exclusive(c))
cpus_andnot(pspan, pspan, c->cpus_allowed);
}
- if (is_removed(cur) || !is_cpu_exclusive(cur)) {
+ if (!is_cpu_exclusive(cur)) {
cpus_or(pspan, pspan, cur->cpus_allowed);
if (cpus_equal(pspan, cur->cpus_allowed))
return;
@@ -1917,6 +1919,17 @@ static int cpuset_mkdir(struct inode *dir, struct dentry *dentry, int mode)
return cpuset_create(c_parent, dentry->d_name.name, mode | S_IFDIR);
}
+/*
+ * Locking note on the strange update_flag() call below:
+ *
+ * If the cpuset being removed is marked cpu_exclusive, then simulate
+ * turning cpu_exclusive off, which will call update_cpu_domains().
+ * The lock_cpu_hotplug() call in update_cpu_domains() must not be
+ * made while holding callback_mutex. Elsewhere the kernel nests
+ * callback_mutex inside lock_cpu_hotplug() calls. So the reverse
+ * nesting would risk an ABBA deadlock.
+ */
+
static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
{
struct cpuset *cs = dentry->d_fsdata;
@@ -1936,11 +1949,16 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
mutex_unlock(&manage_mutex);
return -EBUSY;
}
+ if (is_cpu_exclusive(cs)) {
+ int retval = update_flag(CS_CPU_EXCLUSIVE, cs, "0");
+ if (retval < 0) {
+ mutex_unlock(&manage_mutex);
+ return retval;
+ }
+ }
parent = cs->parent;
mutex_lock(&callback_mutex);
set_bit(CS_REMOVED, &cs->flags);
- if (is_cpu_exclusive(cs))
- update_cpu_domains(cs);
list_del(&cs->sibling); /* delete my sibling from parent->children */
spin_lock(&cs->dentry->d_lock);
d = dget(cs->dentry);
diff --git a/kernel/delayacct.c b/kernel/delayacct.c
index f05392d6426..57ca3730205 100644
--- a/kernel/delayacct.c
+++ b/kernel/delayacct.c
@@ -19,15 +19,15 @@
#include <linux/sysctl.h>
#include <linux/delayacct.h>
-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/kernel/fork.c b/kernel/fork.c
index 1b0f7b1e088..aa36c43783c 100644
--- a/kernel/fork.c
+++ b/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/kernel/futex.c b/kernel/futex.c
index cf0c8e21d1a..c2b2e0b83ab 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -415,15 +415,15 @@ out_unlock:
*/
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;
@@ -930,6 +948,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 +1255,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 +1264,7 @@ static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock,
q.pi_state->owner = current;
spin_lock_irq(&current->pi_lock);
+ WARN_ON(!list_empty(&q.pi_state->list));
list_add(&q.pi_state->list, &current->pi_state_list);
spin_unlock_irq(&current->pi_lock);
@@ -1427,9 +1448,11 @@ retry_locked:
* 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 +1485,11 @@ retry_locked:
/*
* 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);
@@ -1683,9 +1708,9 @@ err_unlock:
* 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,21 +1727,45 @@ retry:
* 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 +1775,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 +1793,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 +1806,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/kernel/futex_compat.c b/kernel/futex_compat.c
index d1d92b441fb..c5cca3f65cb 100644
--- a/kernel/futex_compat.c
+++ b/kernel/futex_compat.c
@@ -12,6 +12,23 @@
#include <asm/uaccess.h>
+
+/*
+ * 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/kernel/hrtimer.c b/kernel/hrtimer.c
index d17766d40da..be989efc785 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -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/kernel/irq/manage.c b/kernel/irq/manage.c
index 4e461438e48..92be519eff2 100644
--- a/kernel/irq/manage.c
+++ b/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/kernel/kprobes.c b/kernel/kprobes.c
index 64aab081153..3f57dfdc8f9 100644
--- a/kernel/kprobes.c
+++ b/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/kernel/power/process.c b/kernel/power/process.c
index b2a5f671d6c..72e72d2c61e 100644
--- a/kernel/power/process.c
+++ b/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/kernel/printk.c b/kernel/printk.c
index 65ca0688f86..1149365e989 100644
--- a/kernel/printk.c
+++ b/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/kernel/rcupdate.c b/kernel/rcupdate.c
index 759805c9859..436ab35f6fa 100644
--- a/kernel/rcupdate.c
+++ b/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/kernel/resource.c b/kernel/resource.c
index 0dd3a857579..46286434af8 100644
--- a/kernel/resource.c
+++ b/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/kernel/rtmutex.c b/kernel/rtmutex.c
index d2ef13b485e..3e13a1e5856 100644
--- a/kernel/rtmutex.c
+++ b/kernel/rtmutex.c
@@ -7,6 +7,8 @@
* Copyright (C) 2005-2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
* Copyright (C) 2005 Kihon Technologies Inc., Steven Rostedt
* Copyright (C) 2006 Esben Nielsen
+ *
+ * See Documentation/rt-mutex-design.txt for details.
*/
#include <linux/spinlock.h>
#include <linux/module.h>
diff --git a/kernel/sched.c b/kernel/sched.c
index b44b9a43b0f..a2be2d05529 100644
--- a/kernel/sched.c
+++ b/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/kernel/signal.c b/kernel/signal.c
index 7fe874d12fa..bfdb5686fa3 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -791,22 +791,31 @@ out:
/*
* 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/kernel/softirq.c b/kernel/softirq.c
index 0f08a84ae30..3789ca98197 100644
--- a/kernel/softirq.c
+++ b/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/kernel/softlockup.c b/kernel/softlockup.c
index 6b76caa2298..03e6a2b0b78 100644
--- a/kernel/softlockup.c
+++ b/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/kernel/taskstats.c b/kernel/taskstats.c
index f45179ce028..e7818765733 100644
--- a/kernel/taskstats.c
+++ b/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/kernel/timer.c b/kernel/timer.c
index 05809c2e2fd..b650f04888e 100644
--- a/kernel/timer.c
+++ b/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)
{
@@ -1688,7 +1688,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 +1708,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/kernel/workqueue.c b/kernel/workqueue.c
index eebb1d83923..448e8f7b342 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -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.
@@ -400,6 +421,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;
@@ -425,18 +452,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)
{
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 2b1530fc573..7f20e7b857c 100644
--- a/lib/kobject_uevent.c
+++ b/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/lib/spinlock_debug.c b/lib/spinlock_debug.c
index 3d9c4dc965e..58c577dd82e 100644
--- a/lib/spinlock_debug.c
+++ b/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/lib/zlib_inflate/inflate.c b/lib/zlib_inflate/inflate.c
index 7f922dccf1a..fceb97c3aff 100644
--- a/lib/zlib_inflate/inflate.c
+++ b/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/mm/fadvise.c b/mm/fadvise.c
index 60a5d55e51d..168c78a121b 100644
--- a/mm/fadvise.c
+++ b/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/mm/filemap.c b/mm/filemap.c
index d087fc3d328..b9a60c43b61 100644
--- a/mm/filemap.c
+++ b/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/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 01c9fb97c61..c37319542b7 100644
--- a/mm/memory_hotplug.c
+++ b/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/mm/slab.c b/mm/slab.c
index 0f20843beff..21ba0603570 100644
--- a/mm/slab.c
+++ b/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/net/8021q/vlan.c b/net/8021q/vlan.c
index 458031bfff5..18fcb9fa518 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -67,10 +67,6 @@ static struct packet_type vlan_packet_type = {
.func = vlan_skb_recv, /* VLAN receive method */
};
-/* Bits of netdev state that are propagated from real device to virtual */
-#define VLAN_LINK_STATE_MASK \
- ((1<<__LINK_STATE_PRESENT)|(1<<__LINK_STATE_NOCARRIER)|(1<<__LINK_STATE_DORMANT))
-
/* End of global variables definitions. */
/*
@@ -479,7 +475,9 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
new_dev->flags = real_dev->flags;
new_dev->flags &= ~IFF_UP;
- new_dev->state = real_dev->state & ~(1<<__LINK_STATE_START);
+ new_dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
+ (1<<__LINK_STATE_DORMANT))) |
+ (1<<__LINK_STATE_PRESENT);
/* need 4 bytes for extra VLAN header info,
* hope the underlying device can handle it.
@@ -542,12 +540,11 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
* so it cannot "appear" on us.
*/
if (!grp) { /* need to add a new group */
- grp = kmalloc(sizeof(struct vlan_group), GFP_KERNEL);
+ grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
if (!grp)
goto out_free_unregister;
/* printk(KERN_ALERT "VLAN REGISTER: Allocated new group.\n"); */
- memset(grp, 0, sizeof(struct vlan_group));
grp->real_dev_ifindex = real_dev->ifindex;
hlist_add_head_rcu(&grp->hlist,
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 5ee96d4b40e..96dc6bb52d1 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -227,12 +227,11 @@ static void atif_drop_device(struct net_device *dev)
static struct atalk_iface *atif_add_device(struct net_device *dev,
struct atalk_addr *sa)
{
- struct atalk_iface *iface = kmalloc(sizeof(*iface), GFP_KERNEL);
+ struct atalk_iface *iface = kzalloc(sizeof(*iface), GFP_KERNEL);
if (!iface)
goto out;
- memset(iface, 0, sizeof(*iface));
dev_hold(dev);
iface->dev = dev;
dev->atalk_ptr = iface;
@@ -559,12 +558,11 @@ static int atrtr_create(struct rtentry *r, struct net_device *devhint)
}
if (!rt) {
- rt = kmalloc(sizeof(*rt), GFP_ATOMIC);
+ rt = kzalloc(sizeof(*rt), GFP_ATOMIC);
retval = -ENOBUFS;
if (!rt)
goto out_unlock;
- memset(rt, 0, sizeof(*rt));
rt->next = atalk_routes;
atalk_routes = rt;
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index a487233dc46..d00cca97eb3 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -508,10 +508,9 @@ Note: we do not have explicit unassign, but look at _push()
if (copy_from_user(&be, arg, sizeof be))
return -EFAULT;
- brvcc = kmalloc(sizeof(struct br2684_vcc), GFP_KERNEL);
+ brvcc = kzalloc(sizeof(struct br2684_vcc), GFP_KERNEL);
if (!brvcc)
return -ENOMEM;
- memset(brvcc, 0, sizeof(struct br2684_vcc));
write_lock_irq(&devs_lock);
net_dev = br2684_find_dev(&be.ifspec);
if (net_dev == NULL) {
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 2e62105d91b..7ce7bfe3fba 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -929,12 +929,11 @@ static int arp_seq_open(struct inode *inode, struct file *file)
struct seq_file *seq;
int rc = -EAGAIN;
- state = kmalloc(sizeof(*state), GFP_KERNEL);
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
if (!state) {
rc = -ENOMEM;
goto out_kfree;
}
- memset(state, 0, sizeof(*state));
state->ns.neigh_sub_iter = clip_seq_sub_iter;
rc = seq_open(file, &arp_seq_ops);
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 4b68a18171c..b4aa489849d 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -1811,12 +1811,11 @@ make_entry(struct lec_priv *priv, unsigned char *mac_addr)
{
struct lec_arp_table *to_return;
- to_return = kmalloc(sizeof(struct lec_arp_table), GFP_ATOMIC);
+ to_return = kzalloc(sizeof(struct lec_arp_table), GFP_ATOMIC);
if (!to_return) {
printk("LEC: Arp entry kmalloc failed\n");
return NULL;
}
- memset(to_return, 0, sizeof(struct lec_arp_table));
memcpy(to_return->mac_addr, mac_addr, ETH_ALEN);
init_timer(&to_return->timer);
to_return->timer.function = lec_arp_expire_arp;
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index 9aafe1e2f04..00704661e83 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -258,10 +258,9 @@ static struct mpoa_client *alloc_mpc(void)
{
struct mpoa_client *mpc;
- mpc = kmalloc(sizeof (struct mpoa_client), GFP_KERNEL);
+ mpc = kzalloc(sizeof (struct mpoa_client), GFP_KERNEL);
if (mpc == NULL)
return NULL;
- memset(mpc, 0, sizeof(struct mpoa_client));
rwlock_init(&mpc->ingress_lock);
rwlock_init(&mpc->egress_lock);
mpc->next = mpcs;
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index 76a7d8ff6c0..19d5dfc0702 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -287,10 +287,9 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
if (be.encaps != PPPOATM_ENCAPS_AUTODETECT &&
be.encaps != PPPOATM_ENCAPS_VC && be.encaps != PPPOATM_ENCAPS_LLC)
return -EINVAL;
- pvcc = kmalloc(sizeof(*pvcc), GFP_KERNEL);
+ pvcc = kzalloc(sizeof(*pvcc), GFP_KERNEL);
if (pvcc == NULL)
return -ENOMEM;
- memset(pvcc, 0, sizeof(*pvcc));
pvcc->atmvcc = atmvcc;
pvcc->old_push = atmvcc->push;
pvcc->old_pop = atmvcc->pop;
diff --git a/net/atm/resources.c b/net/atm/resources.c
index de25c6408b0..529f7e64aa2 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -33,10 +33,9 @@ static struct atm_dev *__alloc_atm_dev(const char *type)
{
struct atm_dev *dev;
- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return NULL;
- memset(dev, 0, sizeof(*dev));
dev->type = type;
dev->signal = ATM_PHY_SIG_UNKNOWN;
dev->link_rate = ATM_OC3_PCR;
diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c
index 369a75b160f..867d4253797 100644
--- a/net/ax25/sysctl_net_ax25.c
+++ b/net/ax25/sysctl_net_ax25.c
@@ -203,13 +203,11 @@ void ax25_register_sysctl(void)
for (ax25_table_size = sizeof(ctl_table), ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
ax25_table_size += sizeof(ctl_table);
- if ((ax25_table = kmalloc(ax25_table_size, GFP_ATOMIC)) == NULL) {
+ if ((ax25_table = kzalloc(ax25_table_size, GFP_ATOMIC)) == NULL) {
spin_unlock_bh(&ax25_dev_lock);
return;
}
- memset(ax25_table, 0x00, ax25_table_size);
-
for (n = 0, ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next) {
ctl_table *child = kmalloc(sizeof(ax25_param_table), GFP_ATOMIC);
if (!child) {
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 77eab8f4c7f..332dd8f436e 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -55,6 +55,7 @@
#define VERSION "1.8"
static int disable_cfc = 0;
+static int channel_mtu = -1;
static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU;
static struct task_struct *rfcomm_thread;
@@ -812,7 +813,10 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d
pn->credits = 0;
}
- pn->mtu = htobs(d->mtu);
+ if (cr && channel_mtu >= 0)
+ pn->mtu = htobs(channel_mtu);
+ else
+ pn->mtu = htobs(d->mtu);
*ptr = __fcs(buf); ptr++;
@@ -1243,7 +1247,10 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
d->priority = pn->priority;
- d->mtu = s->mtu = btohs(pn->mtu);
+ d->mtu = btohs(pn->mtu);
+
+ if (cr && d->mtu > s->mtu)
+ d->mtu = s->mtu;
return 0;
}
@@ -1770,6 +1777,11 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s)
s = rfcomm_session_add(nsock, BT_OPEN);
if (s) {
rfcomm_session_hold(s);
+
+ /* We should adjust MTU on incoming sessions.
+ * L2CAP MTU minus UIH header and FCS. */
+ s->mtu = min(l2cap_pi(nsock->sk)->omtu, l2cap_pi(nsock->sk)->imtu) - 5;
+
rfcomm_schedule(RFCOMM_SCHED_RX);
} else
sock_release(nsock);
@@ -2087,6 +2099,9 @@ module_exit(rfcomm_exit);
module_param(disable_cfc, bool, 0644);
MODULE_PARM_DESC(disable_cfc, "Disable credit based flow control");
+module_param(channel_mtu, int, 0644);
+MODULE_PARM_DESC(channel_mtu, "Default MTU for the RFCOMM channel");
+
module_param(l2cap_mtu, uint, 0644);
MODULE_PARM_DESC(l2cap_mtu, "Default MTU for the L2CAP connection");
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 159fb840982..4e4119a1213 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -162,12 +162,10 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if (num > BR_MAX_PORTS)
num = BR_MAX_PORTS;
- indices = kmalloc(num*sizeof(int), GFP_KERNEL);
+ indices = kcalloc(num, sizeof(int), GFP_KERNEL);
if (indices == NULL)
return -ENOMEM;
- memset(indices, 0, num*sizeof(int));
-
get_port_ifindices(br, indices, num);
if (copy_to_user((void __user *)args[1], indices, num*sizeof(int)))
num = -EFAULT;
@@ -327,11 +325,10 @@ static int old_deviceless(void __user *uarg)
if (args[2] >= 2048)
return -ENOMEM;
- indices = kmalloc(args[2]*sizeof(int), GFP_KERNEL);
+ indices = kcalloc(args[2], sizeof(int), GFP_KERNEL);
if (indices == NULL)
return -ENOMEM;
- memset(indices, 0, args[2]*sizeof(int));
args[2] = get_bridge_ifindices(indices, args[2]);
ret = copy_to_user((void __user *)args[1], indices, args[2]*sizeof(int))
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index cbc8a389a0a..05b3de88824 100644
--- a/net/bridge/br_netfilter.c
+++ b/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/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 06abb6634f5..53086fb7508 100644
--- a/net/bridge/br_netlink.c
+++ b/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/net/core/Makefile b/net/core/Makefile
index e9bd2467d5a..2645ba428d4 100644
--- a/net/core/Makefile
+++ b/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/net/core/dev.c b/net/core/dev.c
index 4d2b5167d7f..d95e2626d94 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1166,11 +1166,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 +1215,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);
@@ -3429,12 +3419,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 +3434,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/net/core/ethtool.c b/net/core/ethtool.c
index 27ce1683caf..2797e281541 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -437,7 +437,7 @@ static int ethtool_set_pauseparam(struct net_device *dev, void __user *useraddr)
{
struct ethtool_pauseparam pauseparam;
- if (!dev->ethtool_ops->get_pauseparam)
+ if (!dev->ethtool_ops->set_pauseparam)
return -EOPNOTSUPP;
if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam)))
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 7ad681f5e71..5130d2efdbb 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -29,6 +29,7 @@
#include <net/neighbour.h>
#include <net/dst.h>
#include <net/sock.h>
+#include <net/netevent.h>
#include <linux/rtnetlink.h>
#include <linux/random.h>
#include <linux/string.h>
@@ -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 @@ out:
(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/net/core/netevent.c b/net/core/netevent.c
new file mode 100644
index 00000000000..35d02c38554
--- /dev/null
+++ b/net/core/netevent.c
@@ -0,0 +1,69 @@
+/*
+ * Network event notifiers
+ *
+ * Authors:
+ * Tom Tucker <tom@opengridcomputing.com>
+ * Steve Wise <swise@opengridcomputing.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Fixes:
+ */
+
+#include <linux/rtnetlink.h>
+#include <linux/notifier.h>
+
+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/net/core/skbuff.c b/net/core/skbuff.c
index 476aa397850..022d8894c11 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -71,13 +71,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
* reliable.
@@ -256,6 +249,29 @@ nodata:
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);
+ return skb;
+}
static void skb_drop_list(struct sk_buff **listp)
{
@@ -846,7 +862,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 +874,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 +884,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 +899,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 +918,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 +2064,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/net/core/user_dma.c b/net/core/user_dma.c
index b7c98dbcdb8..248a6b666af 100644
--- a/net/core/user_dma.c
+++ b/net/core/user_dma.c
@@ -29,6 +29,7 @@
#include <linux/socket.h>
#include <linux/rtnetlink.h> /* for BUG_TRAP */
#include <net/tcp.h>
+#include <net/netdma.h>
#define NET_DMA_DEFAULT_COPYBREAK 4096
diff --git a/net/dccp/feat.h b/net/dccp/feat.h
index 6048373c718..b44c45504fb 100644
--- a/net/dccp/feat.h
+++ b/net/dccp/feat.h
@@ -26,4 +26,6 @@ extern void dccp_feat_clean(struct dccp_minisock *dmsk);
extern int dccp_feat_clone(struct sock *oldsk, struct sock *newsk);
extern int dccp_feat_init(struct dccp_minisock *dmsk);
+extern int dccp_feat_default_sequence_window;
+
#endif /* _DCCP_FEAT_H */
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index c3073e7e81d..7f56f7e8f57 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -504,8 +504,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
ireq = inet_rsk(req);
ireq->loc_addr = daddr;
ireq->rmt_addr = saddr;
- req->rcv_wnd = 100; /* Fake, option parsing will get the
- right value */
+ req->rcv_wnd = dccp_feat_default_sequence_window;
ireq->opt = NULL;
/*
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index ff42bc43263..610c722ac27 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -31,6 +31,7 @@
#include "dccp.h"
#include "ipv6.h"
+#include "feat.h"
/* Socket used for sending RSTs and ACKs */
static struct socket *dccp_v6_ctl_socket;
@@ -229,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)
@@ -707,8 +708,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
ireq = inet_rsk(req);
ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr);
ipv6_addr_copy(&ireq6->loc_addr, &skb->nh.ipv6h->daddr);
- req->rcv_wnd = 100; /* Fake, option parsing will get the
- right value */
+ req->rcv_wnd = dccp_feat_default_sequence_window;
ireq6->pktopts = NULL;
if (ipv6_opt_accepted(sk, skb) ||
@@ -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/net/dccp/options.c b/net/dccp/options.c
index c3cda1e39aa..daf72bb671f 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -29,6 +29,8 @@ int dccp_feat_default_ack_ratio = DCCPF_INITIAL_ACK_RATIO;
int dccp_feat_default_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR;
int dccp_feat_default_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT;
+EXPORT_SYMBOL_GPL(dccp_feat_default_sequence_window);
+
void dccp_minisock_init(struct dccp_minisock *dmsk)
{
dmsk->dccpms_sequence_window = dccp_feat_default_sequence_window;
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 98a25208440..476455fbdb0 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -413,11 +413,7 @@ static struct dn_ifaddr *dn_dev_alloc_ifa(void)
{
struct dn_ifaddr *ifa;
- ifa = kmalloc(sizeof(*ifa), GFP_KERNEL);
-
- if (ifa) {
- memset(ifa, 0, sizeof(*ifa));
- }
+ ifa = kzalloc(sizeof(*ifa), GFP_KERNEL);
return ifa;
}
@@ -1105,10 +1101,9 @@ struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
return NULL;
*err = -ENOBUFS;
- if ((dn_db = kmalloc(sizeof(struct dn_dev), GFP_ATOMIC)) == NULL)
+ if ((dn_db = kzalloc(sizeof(struct dn_dev), GFP_ATOMIC)) == NULL)
return NULL;
- memset(dn_db, 0, sizeof(struct dn_dev));
memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms));
smp_wmb();
dev->dn_ptr = dn_db;
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index 0375077391b..fa20e2efcfc 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -283,11 +283,10 @@ struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct dn_kern_rta
goto err_inval;
}
- fi = kmalloc(sizeof(*fi)+nhs*sizeof(struct dn_fib_nh), GFP_KERNEL);
+ fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct dn_fib_nh), GFP_KERNEL);
err = -ENOBUFS;
if (fi == NULL)
goto failure;
- memset(fi, 0, sizeof(*fi)+nhs*sizeof(struct dn_fib_nh));
fi->fib_protocol = r->rtm_protocol;
fi->fib_nhs = nhs;
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 5ce9c9e0565..ff0ebe99137 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -580,12 +580,11 @@ static int dn_neigh_seq_open(struct inode *inode, struct file *file)
{
struct seq_file *seq;
int rc = -ENOMEM;
- struct neigh_seq_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ struct neigh_seq_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s)
goto out;
- memset(s, 0, sizeof(*s));
rc = seq_open(file, &dn_neigh_seq_ops);
if (rc)
goto out_kfree;
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 1355614ec11..743e9fcf7c5 100644
--- a/net/decnet/dn_route.c
+++ b/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/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 22f321d9bf9..6986be754ef 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -151,10 +151,9 @@ int dn_fib_rtm_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
}
}
- new_r = kmalloc(sizeof(*new_r), GFP_KERNEL);
+ new_r = kzalloc(sizeof(*new_r), GFP_KERNEL);
if (!new_r)
return -ENOMEM;
- memset(new_r, 0, sizeof(*new_r));
if (rta[RTA_SRC-1])
memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 2);
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index 37d9d0a1ac8..e926c952e36 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -158,12 +158,10 @@ static void dn_rehash_zone(struct dn_zone *dz)
break;
}
- ht = kmalloc(new_divisor*sizeof(struct dn_fib_node*), GFP_KERNEL);
-
+ ht = kcalloc(new_divisor, sizeof(struct dn_fib_node*), GFP_KERNEL);
if (ht == NULL)
return;
- memset(ht, 0, new_divisor*sizeof(struct dn_fib_node *));
write_lock_bh(&dn_fib_tables_lock);
old_ht = dz->dz_hash;
dz->dz_hash = ht;
@@ -184,11 +182,10 @@ static void dn_free_node(struct dn_fib_node *f)
static struct dn_zone *dn_new_zone(struct dn_hash *table, int z)
{
int i;
- struct dn_zone *dz = kmalloc(sizeof(struct dn_zone), GFP_KERNEL);
+ struct dn_zone *dz = kzalloc(sizeof(struct dn_zone), GFP_KERNEL);
if (!dz)
return NULL;
- memset(dz, 0, sizeof(struct dn_zone));
if (z) {
dz->dz_divisor = 16;
dz->dz_hashmask = 0x0F;
@@ -197,14 +194,12 @@ static struct dn_zone *dn_new_zone(struct dn_hash *table, int z)
dz->dz_hashmask = 0;
}
- dz->dz_hash = kmalloc(dz->dz_divisor*sizeof(struct dn_fib_node *), GFP_KERNEL);
-
+ dz->dz_hash = kcalloc(dz->dz_divisor, sizeof(struct dn_fib_node *), GFP_KERNEL);
if (!dz->dz_hash) {
kfree(dz);
return NULL;
}
- memset(dz->dz_hash, 0, dz->dz_divisor*sizeof(struct dn_fib_node*));
dz->dz_order = z;
dz->dz_mask = dnet_make_mask(z);
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index 309ae4c6549..4d66aac1348 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -673,12 +673,11 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
edev = dev->ec_ptr;
if (edev == NULL) {
/* Magic up a new one. */
- edev = kmalloc(sizeof(struct ec_device), GFP_KERNEL);
+ edev = kzalloc(sizeof(struct ec_device), GFP_KERNEL);
if (edev == NULL) {
err = -ENOMEM;
break;
}
- memset(edev, 0, sizeof(struct ec_device));
dev->ec_ptr = edev;
} else
net2dev_map[edev->net] = NULL;
diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig
index dbb08528ddf..f7e84e9d13a 100644
--- a/net/ieee80211/Kconfig
+++ b/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/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c
index cb71d794a7d..5ed0a98b2d7 100644
--- a/net/ieee80211/ieee80211_crypt.c
+++ b/net/ieee80211/ieee80211_crypt.c
@@ -110,11 +110,10 @@ int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
unsigned long flags;
struct ieee80211_crypto_alg *alg;
- alg = kmalloc(sizeof(*alg), GFP_KERNEL);
+ alg = kzalloc(sizeof(*alg), GFP_KERNEL);
if (alg == NULL)
return -ENOMEM;
- memset(alg, 0, sizeof(*alg));
alg->ops = ops;
spin_lock_irqsave(&ieee80211_crypto_lock, flags);
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index 492647382ad..ed90a8af144 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -76,10 +76,9 @@ static void *ieee80211_ccmp_init(int key_idx)
{
struct ieee80211_ccmp_data *priv;
- priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
+ priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
if (priv == NULL)
goto fail;
- memset(priv, 0, sizeof(*priv));
priv->key_idx = key_idx;
priv->tfm = crypto_alloc_tfm("aes", 0);
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index c5a87724aab..0ebf235f693 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -39,10 +39,9 @@ static void *prism2_wep_init(int keyidx)
{
struct prism2_wep_data *priv;
- priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
+ priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
if (priv == NULL)
goto fail;
- memset(priv, 0, sizeof(*priv));
priv->key_idx = keyidx;
priv->tfm = crypto_alloc_tfm("arc4", 0);
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index a78c4f845f6..5cb9cfd3539 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -369,11 +369,10 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
struct ieee80211_crypt_data *new_crypt;
/* take WEP into use */
- new_crypt = kmalloc(sizeof(struct ieee80211_crypt_data),
+ new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
GFP_KERNEL);
if (new_crypt == NULL)
return -ENOMEM;
- memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
new_crypt->ops = ieee80211_get_crypto_ops("WEP");
if (!new_crypt->ops) {
request_module("ieee80211_crypt_wep");
@@ -616,13 +615,11 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
ieee80211_crypt_delayed_deinit(ieee, crypt);
- new_crypt = (struct ieee80211_crypt_data *)
- kmalloc(sizeof(*new_crypt), GFP_KERNEL);
+ new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
if (new_crypt == NULL) {
ret = -ENOMEM;
goto done;
}
- memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
new_crypt->ops = ops;
if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
new_crypt->priv = new_crypt->ops->init(idx);
diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c
index ebc33ca6e69..4cef39e171d 100644
--- a/net/ieee80211/softmac/ieee80211softmac_auth.c
+++ b/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/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index 8cc8b20f5cd..6ae5a1dc795 100644
--- a/net/ieee80211/softmac/ieee80211softmac_io.c
+++ b/net/ieee80211/softmac/ieee80211softmac_io.c
@@ -96,8 +96,7 @@ ieee80211softmac_alloc_mgt(u32 size)
if(size > IEEE80211_DATA_LEN)
return NULL;
/* Allocate the frame */
- data = kmalloc(size, GFP_ATOMIC);
- memset(data, 0, size);
+ data = kzalloc(size, GFP_ATOMIC);
return data;
}
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 8e748be36c5..1366bc6ce6a 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -215,12 +215,10 @@ static int ah_init_state(struct xfrm_state *x)
if (x->encap)
goto error;
- ahp = kmalloc(sizeof(*ahp), GFP_KERNEL);
+ ahp = kzalloc(sizeof(*ahp), GFP_KERNEL);
if (ahp == NULL)
return -ENOMEM;
- memset(ahp, 0, sizeof(*ahp));
-
ahp->key = x->aalg->alg_key;
ahp->key_len = (x->aalg->alg_key_len+7)/8;
ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 7b51b3bdb54..c8a3723bc00 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -1372,12 +1372,11 @@ static int arp_seq_open(struct inode *inode, struct file *file)
{
struct seq_file *seq;
int rc = -ENOMEM;
- struct neigh_seq_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ struct neigh_seq_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s)
goto out;
- memset(s, 0, sizeof(*s));
rc = seq_open(file, &arp_seq_ops);
if (rc)
goto out_kfree;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index a7c65e9e5ec..a6cc31d911e 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -93,10 +93,9 @@ static void devinet_sysctl_unregister(struct ipv4_devconf *p);
static struct in_ifaddr *inet_alloc_ifa(void)
{
- struct in_ifaddr *ifa = kmalloc(sizeof(*ifa), GFP_KERNEL);
+ struct in_ifaddr *ifa = kzalloc(sizeof(*ifa), GFP_KERNEL);
if (ifa) {
- memset(ifa, 0, sizeof(*ifa));
INIT_RCU_HEAD(&ifa->rcu_head);
}
@@ -140,10 +139,9 @@ struct in_device *inetdev_init(struct net_device *dev)
ASSERT_RTNL();
- in_dev = kmalloc(sizeof(*in_dev), GFP_KERNEL);
+ in_dev = kzalloc(sizeof(*in_dev), GFP_KERNEL);
if (!in_dev)
goto out;
- memset(in_dev, 0, sizeof(*in_dev));
INIT_RCU_HEAD(&in_dev->rcu_head);
memcpy(&in_dev->cnf, &ipv4_devconf_dflt, sizeof(in_dev->cnf));
in_dev->cnf.sysctl = NULL;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 4e112738b3f..fc2f8ce441d 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -316,12 +316,10 @@ static int esp_init_state(struct xfrm_state *x)
if (x->ealg == NULL)
goto error;
- esp = kmalloc(sizeof(*esp), GFP_KERNEL);
+ esp = kzalloc(sizeof(*esp), GFP_KERNEL);
if (esp == NULL)
return -ENOMEM;
- memset(esp, 0, sizeof(*esp));
-
if (x->aalg) {
struct xfrm_algo_desc *aalg_desc;
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index 3c1d32ad35f..72c633b357c 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -204,11 +204,10 @@ static struct fn_zone *
fn_new_zone(struct fn_hash *table, int z)
{
int i;
- struct fn_zone *fz = kmalloc(sizeof(struct fn_zone), GFP_KERNEL);
+ struct fn_zone *fz = kzalloc(sizeof(struct fn_zone), GFP_KERNEL);
if (!fz)
return NULL;
- memset(fz, 0, sizeof(struct fn_zone));
if (z) {
fz->fz_divisor = 16;
} else {
@@ -1046,7 +1045,7 @@ static int fib_seq_open(struct inode *inode, struct file *file)
{
struct seq_file *seq;
int rc = -ENOMEM;
- struct fib_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ struct fib_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s)
goto out;
@@ -1057,7 +1056,6 @@ static int fib_seq_open(struct inode *inode, struct file *file)
seq = file->private_data;
seq->private = s;
- memset(s, 0, sizeof(*s));
out:
return rc;
out_kfree:
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 773b12ba4e3..79b04718bdf 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -196,10 +196,9 @@ int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
}
}
- new_r = kmalloc(sizeof(*new_r), GFP_KERNEL);
+ new_r = kzalloc(sizeof(*new_r), GFP_KERNEL);
if (!new_r)
return -ENOMEM;
- memset(new_r, 0, sizeof(*new_r));
if (rta[RTA_SRC-1])
memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 4);
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 5f87533684d..9be53a8e72c 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -709,11 +709,10 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
goto failure;
}
- fi = kmalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
+ fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
if (fi == NULL)
goto failure;
fib_info_cnt++;
- memset(fi, 0, sizeof(*fi)+nhs*sizeof(struct fib_nh));
fi->fib_protocol = r->rtm_protocol;
@@ -962,10 +961,6 @@ fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
rtm->rtm_protocol = fi->fib_protocol;
if (fi->fib_priority)
RTA_PUT(skb, RTA_PRIORITY, 4, &fi->fib_priority);
-#ifdef CONFIG_NET_CLS_ROUTE
- if (fi->fib_nh[0].nh_tclassid)
- RTA_PUT(skb, RTA_FLOW, 4, &fi->fib_nh[0].nh_tclassid);
-#endif
if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0)
goto rtattr_failure;
if (fi->fib_prefsrc)
@@ -975,6 +970,10 @@ fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
RTA_PUT(skb, RTA_GATEWAY, 4, &fi->fib_nh->nh_gw);
if (fi->fib_nh->nh_oif)
RTA_PUT(skb, RTA_OIF, sizeof(int), &fi->fib_nh->nh_oif);
+#ifdef CONFIG_NET_CLS_ROUTE
+ if (fi->fib_nh[0].nh_tclassid)
+ RTA_PUT(skb, RTA_FLOW, 4, &fi->fib_nh[0].nh_tclassid);
+#endif
}
#ifdef CONFIG_IP_ROUTE_MULTIPATH
if (fi->fib_nhs > 1) {
@@ -993,6 +992,10 @@ fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
nhp->rtnh_ifindex = nh->nh_oif;
if (nh->nh_gw)
RTA_PUT(skb, RTA_GATEWAY, 4, &nh->nh_gw);
+#ifdef CONFIG_NET_CLS_ROUTE
+ if (nh->nh_tclassid)
+ RTA_PUT(skb, RTA_FLOW, 4, &nh->nh_tclassid);
+#endif
nhp->rtnh_len = skb->tail - (unsigned char*)nhp;
} endfor_nexthops(fi);
mp_head->rta_type = RTA_MULTIPATH;
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index d299c8e547d..9f4b752f5a3 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1028,10 +1028,9 @@ static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im)
* for deleted items allows change reports to use common code with
* non-deleted or query-response MCA's.
*/
- pmc = kmalloc(sizeof(*pmc), GFP_KERNEL);
+ pmc = kzalloc(sizeof(*pmc), GFP_KERNEL);
if (!pmc)
return;
- memset(pmc, 0, sizeof(*pmc));
spin_lock_bh(&im->lock);
pmc->interface = im->interface;
in_dev_hold(in_dev);
@@ -1529,10 +1528,9 @@ static int ip_mc_add1_src(struct ip_mc_list *pmc, int sfmode,
psf_prev = psf;
}
if (!psf) {
- psf = kmalloc(sizeof(*psf), GFP_ATOMIC);
+ psf = kzalloc(sizeof(*psf), GFP_ATOMIC);
if (!psf)
return -ENOBUFS;
- memset(psf, 0, sizeof(*psf));
psf->sf_inaddr = *psfsrc;
if (psf_prev) {
psf_prev->sf_next = psf;
@@ -2380,7 +2378,7 @@ static int igmp_mc_seq_open(struct inode *inode, struct file *file)
{
struct seq_file *seq;
int rc = -ENOMEM;
- struct igmp_mc_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ struct igmp_mc_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s)
goto out;
@@ -2390,7 +2388,6 @@ static int igmp_mc_seq_open(struct inode *inode, struct file *file)
seq = file->private_data;
seq->private = s;
- memset(s, 0, sizeof(*s));
out:
return rc;
out_kfree:
@@ -2555,7 +2552,7 @@ static int igmp_mcf_seq_open(struct inode *inode, struct file *file)
{
struct seq_file *seq;
int rc = -ENOMEM;
- struct igmp_mcf_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ struct igmp_mcf_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s)
goto out;
@@ -2565,7 +2562,6 @@ static int igmp_mcf_seq_open(struct inode *inode, struct file *file)
seq = file->private_data;
seq->private = s;
- memset(s, 0, sizeof(*s));
out:
return rc;
out_kfree:
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 8e7e41b66c7..492858e6faf 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -909,11 +909,10 @@ static int __init inet_diag_init(void)
sizeof(struct inet_diag_handler *));
int err = -ENOMEM;
- inet_diag_table = kmalloc(inet_diag_table_size, GFP_KERNEL);
+ inet_diag_table = kzalloc(inet_diag_table_size, GFP_KERNEL);
if (!inet_diag_table)
goto out;
- memset(inet_diag_table, 0, inet_diag_table_size);
idiagnl = netlink_kernel_create(NETLINK_INET_DIAG, 0, inet_diag_rcv,
THIS_MODULE);
if (idiagnl == NULL)
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 6ff9b10d956..0f9b3a31997 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -617,7 +617,6 @@ static int ipgre_rcv(struct sk_buff *skb)
skb->mac.raw = skb->nh.raw;
skb->nh.raw = __pskb_pull(skb, offset);
skb_postpull_rcsum(skb, skb->h.raw, offset);
- memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
skb->pkt_type = PACKET_HOST;
#ifdef CONFIG_NET_IPGRE_BROADCAST
if (MULTICAST(iph->daddr)) {
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 184c78ca79e..212734ca238 100644
--- a/net/ipv4/ip_input.c
+++ b/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/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index cbcae654462..406056edc02 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -256,7 +256,6 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
if (!opt) {
opt = &(IPCB(skb)->opt);
- memset(opt, 0, sizeof(struct ip_options));
iph = skb->nh.raw;
opt->optlen = ((struct iphdr *)iph)->ihl*4 - sizeof(struct iphdr);
optptr = iph + sizeof(struct iphdr);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 7c9f9a6421b..9bf307a2978 100644
--- a/net/ipv4/ip_output.c
+++ b/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 @@ slow_path:
/*
* 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 @@ slow_path:
err = output(skb2);
if (err)
goto fail;
+
+ IP_INC_STATS(IPSTATS_MIB_FRAGCREATES);
}
kfree_skb(skb);
IP_INC_STATS(IPSTATS_MIB_FRAGOKS);
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 84f43a3c909..2d05c4133d3 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/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/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 8a8b5cf2f7f..a0c28b2b756 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -410,11 +410,10 @@ static int ipcomp_init_state(struct xfrm_state *x)
goto out;
err = -ENOMEM;
- ipcd = kmalloc(sizeof(*ipcd), GFP_KERNEL);
+ ipcd = kzalloc(sizeof(*ipcd), GFP_KERNEL);
if (!ipcd)
goto out;
- memset(ipcd, 0, sizeof(*ipcd));
x->props.header_len = 0;
if (x->props.mode)
x->props.header_len += sizeof(struct iphdr);
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 3291d5192aa..76ab50b0d6e 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -487,7 +487,6 @@ static int ipip_rcv(struct sk_buff *skb)
skb->mac.raw = skb->nh.raw;
skb->nh.raw = skb->data;
- memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
skb->protocol = htons(ETH_P_IP);
skb->pkt_type = PACKET_HOST;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index ba33f8621c6..85893eef6b1 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1461,7 +1461,6 @@ int pim_rcv_v1(struct sk_buff * skb)
skb_pull(skb, (u8*)encap - skb->data);
skb->nh.iph = (struct iphdr *)skb->data;
skb->dev = reg_dev;
- memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
skb->protocol = htons(ETH_P_IP);
skb->ip_summed = 0;
skb->pkt_type = PACKET_HOST;
@@ -1517,7 +1516,6 @@ static int pim_rcv(struct sk_buff * skb)
skb_pull(skb, (u8*)encap - skb->data);
skb->nh.iph = (struct iphdr *)skb->data;
skb->dev = reg_dev;
- memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
skb->protocol = htons(ETH_P_IP);
skb->ip_summed = 0;
skb->pkt_type = PACKET_HOST;
@@ -1580,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;
@@ -1593,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/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index f28ec688216..6a28fafe910 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -735,12 +735,11 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest,
if (atype != RTN_LOCAL && atype != RTN_UNICAST)
return -EINVAL;
- dest = kmalloc(sizeof(struct ip_vs_dest), GFP_ATOMIC);
+ dest = kzalloc(sizeof(struct ip_vs_dest), GFP_ATOMIC);
if (dest == NULL) {
IP_VS_ERR("ip_vs_new_dest: kmalloc failed.\n");
return -ENOMEM;
}
- memset(dest, 0, sizeof(struct ip_vs_dest));
dest->protocol = svc->protocol;
dest->vaddr = svc->addr;
@@ -1050,14 +1049,12 @@ ip_vs_add_service(struct ip_vs_service_user *u, struct ip_vs_service **svc_p)
goto out_mod_dec;
}
- svc = (struct ip_vs_service *)
- kmalloc(sizeof(struct ip_vs_service), GFP_ATOMIC);
+ svc = kzalloc(sizeof(struct ip_vs_service), GFP_ATOMIC);
if (svc == NULL) {
IP_VS_DBG(1, "ip_vs_add_service: kmalloc failed.\n");
ret = -ENOMEM;
goto out_err;
}
- memset(svc, 0, sizeof(struct ip_vs_service));
/* I'm the first user of the service */
atomic_set(&svc->usecnt, 1);
@@ -1797,7 +1794,7 @@ static int ip_vs_info_open(struct inode *inode, struct file *file)
{
struct seq_file *seq;
int rc = -ENOMEM;
- struct ip_vs_iter *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ struct ip_vs_iter *s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s)
goto out;
@@ -1808,7 +1805,6 @@ static int ip_vs_info_open(struct inode *inode, struct file *file)
seq = file->private_data;
seq->private = s;
- memset(s, 0, sizeof(*s));
out:
return rc;
out_kfree:
diff --git a/net/ipv4/ipvs/ip_vs_est.c b/net/ipv4/ipvs/ip_vs_est.c
index 4c1940381ba..7d68b80c4c1 100644
--- a/net/ipv4/ipvs/ip_vs_est.c
+++ b/net/ipv4/ipvs/ip_vs_est.c
@@ -123,11 +123,10 @@ int ip_vs_new_estimator(struct ip_vs_stats *stats)
{
struct ip_vs_estimator *est;
- est = kmalloc(sizeof(*est), GFP_KERNEL);
+ est = kzalloc(sizeof(*est), GFP_KERNEL);
if (est == NULL)
return -ENOMEM;
- memset(est, 0, sizeof(*est));
est->stats = stats;
est->last_conns = stats->conns;
est->cps = stats->cps<<10;
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
index af35235672d..9a39e296971 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c
+++ b/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/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
index fc87ce0da40..4f222d6be00 100644
--- a/net/ipv4/netfilter/ip_conntrack_sip.c
+++ b/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/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 7bd3c22003a..7a9fa04a467 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/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/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
index 0b1b416759c..18b7fbdccb6 100644
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ b/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/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index cbffeae3f56..d994c5f5744 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -172,11 +172,10 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip,
struct clusterip_config *c;
char buffer[16];
- c = kmalloc(sizeof(*c), GFP_ATOMIC);
+ c = kzalloc(sizeof(*c), GFP_ATOMIC);
if (!c)
return NULL;
- memset(c, 0, sizeof(*c));
c->dev = dev;
c->clusterip = ip;
memcpy(&c->clustermac, &i->clustermac, ETH_ALEN);
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index 92980ab8ce4..6b662449e82 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -508,6 +508,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/net/ipv4/raw.c b/net/ipv4/raw.c
index bd221ec3f81..62b2762a242 100644
--- a/net/ipv4/raw.c
+++ b/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/net/ipv4/route.c b/net/ipv4/route.c
index 2dc6dbb2846..19bd49d69d9 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -104,6 +104,7 @@
#include <net/icmp.h>
#include <net/xfrm.h>
#include <net/ip_mp_alg.h>
+#include <net/netevent.h>
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
#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);
}
}
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index f6a2d9223d0..934396bb137 100644
--- a/net/ipv4/tcp.c
+++ b/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 @@ adjudge_to_death:
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/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 738dad9f7d4..104af5d5bcb 100644
--- a/net/ipv4/tcp_input.c
+++ b/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/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index a891133f00e..4b04c3edd4a 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/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;
}
@@ -1640,10 +1638,9 @@ static int tcp_seq_open(struct inode *inode, struct file *file)
if (unlikely(afinfo == NULL))
return -EINVAL;
- s = kmalloc(sizeof(*s), GFP_KERNEL);
+ s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s)
return -ENOMEM;
- memset(s, 0, sizeof(*s));
s->family = afinfo->family;
s->seq_ops.start = tcp_seq_start;
s->seq_ops.next = tcp_seq_next;
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 0ccb7cb22b1..624e2b2c7f5 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/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/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index d7d517a3a23..b3435324b57 100644
--- a/net/ipv4/tcp_probe.c
+++ b/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)
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 9bfcddad695..f136cec96d9 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1468,11 +1468,10 @@ static int udp_seq_open(struct inode *inode, struct file *file)
struct udp_seq_afinfo *afinfo = PDE(inode)->data;
struct seq_file *seq;
int rc = -ENOMEM;
- struct udp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ struct udp_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s)
goto out;
- memset(s, 0, sizeof(*s));
s->family = afinfo->family;
s->seq_ops.start = udp_seq_start;
s->seq_ops.next = udp_seq_next;
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index f8d880beb12..13cafbe56ce 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -92,7 +92,6 @@ static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
skb->mac.raw = memmove(skb->data - skb->mac_len,
skb->mac.raw, skb->mac_len);
skb->nh.raw = skb->data;
- memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
err = 0;
out:
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 2316a4315a1..8ea1e36bf8e 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1869,15 +1869,21 @@ err_exit:
/*
* 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(&ifp->lock);
+ ifp->valid_lft = valid_lft;
+ ifp->prefered_lft = prefered_lft;
+ ifp->tstamp = jiffies;
+ spin_unlock(&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 @@ restart:
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]);
}
@@ -2864,11 +2895,61 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
}
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/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 5a0ba58b86c..ac85e9c532c 100644
--- a/net/ipv6/af_inet6.c
+++ b/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/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 5c950cc79d8..bf491077b82 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/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/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index df8f051c0fc..25c2a9e0389 100644
--- a/net/ipv6/ip6_input.c
+++ b/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/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 3bc74ce7880..69451af6abe 100644
--- a/net/ipv6/ip6_output.c
+++ b/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 @@ slow_path:
/*
* 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 @@ fail:
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 @@ out_err_release:
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),
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index bc77c0e1a94..84d7ebdb9d2 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -567,10 +567,9 @@ static inline struct ipv6_txoptions *create_tel(__u8 encap_limit)
int opt_len = sizeof(*opt) + 8;
- if (!(opt = kmalloc(opt_len, GFP_ATOMIC))) {
+ if (!(opt = kzalloc(opt_len, GFP_ATOMIC))) {
return NULL;
}
- memset(opt, 0, opt_len);
opt->tot_len = opt_len;
opt->dst0opt = (struct ipv6_opt_hdr *) (opt + 1);
opt->opt_nflen = 8;
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index fa1ce0ae123..d57e61ce4a7 100644
--- a/net/ipv6/raw.c
+++ b/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/net/ipv6/route.c b/net/ipv6/route.c
index 87c39c978cd..4b163711f3a 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -53,6 +53,7 @@
#include <linux/rtnetlink.h>
#include <net/dst.h>
#include <net/xfrm.h>
+#include <net/netevent.h>
#include <asm/uaccess.h>
@@ -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 @@ restart:
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/net/ipv6/sit.c b/net/ipv6/sit.c
index c56aeece2bf..836eecd7e62 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -380,7 +380,6 @@ static int ipip6_rcv(struct sk_buff *skb)
secpath_reset(skb);
skb->mac.raw = skb->nh.raw;
skb->nh.raw = skb->data;
- memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
IPCB(skb)->flags = 0;
skb->protocol = htons(ETH_P_IPV6);
skb->pkt_type = PACKET_HOST;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 923989d0520..b843a650be7 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/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 @@ drop:
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/net/ipv6/udp.c b/net/ipv6/udp.c
index ccc57f434cd..3d54f246411 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -782,7 +782,7 @@ do_udp_sendmsg:
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/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 0eea60ea9eb..c8c8b44a0f5 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/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/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 6b44fe8516c..c8f9369c2a8 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -31,27 +31,6 @@
#include <linux/icmpv6.h>
#include <linux/mutex.h>
-#ifdef CONFIG_IPV6_XFRM6_TUNNEL_DEBUG
-# define X6TDEBUG 3
-#else
-# define X6TDEBUG 1
-#endif
-
-#define X6TPRINTK(fmt, args...) printk(fmt, ## args)
-#define X6TNOPRINTK(fmt, args...) do { ; } while(0)
-
-#if X6TDEBUG >= 1
-# define X6TPRINTK1 X6TPRINTK
-#else
-# define X6TPRINTK1 X6TNOPRINTK
-#endif
-
-#if X6TDEBUG >= 3
-# define X6TPRINTK3 X6TPRINTK
-#else
-# define X6TPRINTK3 X6TNOPRINTK
-#endif
-
/*
* xfrm_tunnel_spi things are for allocating unique id ("spi")
* per xfrm_address_t.
@@ -62,15 +41,8 @@ struct xfrm6_tunnel_spi {
xfrm_address_t addr;
u32 spi;
atomic_t refcnt;
-#ifdef XFRM6_TUNNEL_SPI_MAGIC
- u32 magic;
-#endif
};
-#ifdef CONFIG_IPV6_XFRM6_TUNNEL_DEBUG
-# define XFRM6_TUNNEL_SPI_MAGIC 0xdeadbeef
-#endif
-
static DEFINE_RWLOCK(xfrm6_tunnel_spi_lock);
static u32 xfrm6_tunnel_spi;
@@ -86,43 +58,15 @@ static kmem_cache_t *xfrm6_tunnel_spi_kmem __read_mostly;
static struct hlist_head xfrm6_tunnel_spi_byaddr[XFRM6_TUNNEL_SPI_BYADDR_HSIZE];
static struct hlist_head xfrm6_tunnel_spi_byspi[XFRM6_TUNNEL_SPI_BYSPI_HSIZE];
-#ifdef XFRM6_TUNNEL_SPI_MAGIC
-static int x6spi_check_magic(const struct xfrm6_tunnel_spi *x6spi,
- const char *name)
-{
- if (unlikely(x6spi->magic != XFRM6_TUNNEL_SPI_MAGIC)) {
- X6TPRINTK3(KERN_DEBUG "%s(): x6spi object "
- "at %p has corrupted magic %08x "
- "(should be %08x)\n",
- name, x6spi, x6spi->magic, XFRM6_TUNNEL_SPI_MAGIC);
- return -1;
- }
- return 0;
-}
-#else
-static int inline x6spi_check_magic(const struct xfrm6_tunnel_spi *x6spi,
- const char *name)
-{
- return 0;
-}
-#endif
-
-#define X6SPI_CHECK_MAGIC(x6spi) x6spi_check_magic((x6spi), __FUNCTION__)
-
-
static unsigned inline xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr)
{
unsigned h;
- X6TPRINTK3(KERN_DEBUG "%s(addr=%p)\n", __FUNCTION__, addr);
-
h = addr->a6[0] ^ addr->a6[1] ^ addr->a6[2] ^ addr->a6[3];
h ^= h >> 16;
h ^= h >> 8;
h &= XFRM6_TUNNEL_SPI_BYADDR_HSIZE - 1;
- X6TPRINTK3(KERN_DEBUG "%s() = %u\n", __FUNCTION__, h);
-
return h;
}
@@ -136,19 +80,13 @@ static int xfrm6_tunnel_spi_init(void)
{
int i;
- X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
-
xfrm6_tunnel_spi = 0;
xfrm6_tunnel_spi_kmem = kmem_cache_create("xfrm6_tunnel_spi",
sizeof(struct xfrm6_tunnel_spi),
0, SLAB_HWCACHE_ALIGN,
NULL, NULL);
- if (!xfrm6_tunnel_spi_kmem) {
- X6TPRINTK1(KERN_ERR
- "%s(): failed to allocate xfrm6_tunnel_spi_kmem\n",
- __FUNCTION__);
+ if (!xfrm6_tunnel_spi_kmem)
return -ENOMEM;
- }
for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++)
INIT_HLIST_HEAD(&xfrm6_tunnel_spi_byaddr[i]);
@@ -161,22 +99,16 @@ static void xfrm6_tunnel_spi_fini(void)
{
int i;
- X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
-
for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++) {
if (!hlist_empty(&xfrm6_tunnel_spi_byaddr[i]))
- goto err;
+ return;
}
for (i = 0; i < XFRM6_TUNNEL_SPI_BYSPI_HSIZE; i++) {
if (!hlist_empty(&xfrm6_tunnel_spi_byspi[i]))
- goto err;
+ return;
}
kmem_cache_destroy(xfrm6_tunnel_spi_kmem);
xfrm6_tunnel_spi_kmem = NULL;
- return;
-err:
- X6TPRINTK1(KERN_ERR "%s(): table is not empty\n", __FUNCTION__);
- return;
}
static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
@@ -184,19 +116,13 @@ static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
struct xfrm6_tunnel_spi *x6spi;
struct hlist_node *pos;
- X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr);
-
hlist_for_each_entry(x6spi, pos,
&xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)],
list_byaddr) {
- if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) {
- X6SPI_CHECK_MAGIC(x6spi);
- X6TPRINTK3(KERN_DEBUG "%s() = %p(%u)\n", __FUNCTION__, x6spi, x6spi->spi);
+ if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0)
return x6spi;
- }
}
- X6TPRINTK3(KERN_DEBUG "%s() = NULL(0)\n", __FUNCTION__);
return NULL;
}
@@ -205,8 +131,6 @@ u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
struct xfrm6_tunnel_spi *x6spi;
u32 spi;
- X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr);
-
read_lock_bh(&xfrm6_tunnel_spi_lock);
x6spi = __xfrm6_tunnel_spi_lookup(saddr);
spi = x6spi ? x6spi->spi : 0;
@@ -223,8 +147,6 @@ static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
struct hlist_node *pos;
unsigned index;
- X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr);
-
if (xfrm6_tunnel_spi < XFRM6_TUNNEL_SPI_MIN ||
xfrm6_tunnel_spi >= XFRM6_TUNNEL_SPI_MAX)
xfrm6_tunnel_spi = XFRM6_TUNNEL_SPI_MIN;
@@ -258,18 +180,10 @@ try_next_2:;
spi = 0;
goto out;
alloc_spi:
- X6TPRINTK3(KERN_DEBUG "%s(): allocate new spi for " NIP6_FMT "\n",
- __FUNCTION__,
- NIP6(*(struct in6_addr *)saddr));
x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, SLAB_ATOMIC);
- if (!x6spi) {
- X6TPRINTK1(KERN_ERR "%s(): kmem_cache_alloc() failed\n",
- __FUNCTION__);
+ if (!x6spi)
goto out;
- }
-#ifdef XFRM6_TUNNEL_SPI_MAGIC
- x6spi->magic = XFRM6_TUNNEL_SPI_MAGIC;
-#endif
+
memcpy(&x6spi->addr, saddr, sizeof(x6spi->addr));
x6spi->spi = spi;
atomic_set(&x6spi->refcnt, 1);
@@ -278,9 +192,7 @@ alloc_spi:
index = xfrm6_tunnel_spi_hash_byaddr(saddr);
hlist_add_head(&x6spi->list_byaddr, &xfrm6_tunnel_spi_byaddr[index]);
- X6SPI_CHECK_MAGIC(x6spi);
out:
- X6TPRINTK3(KERN_DEBUG "%s() = %u\n", __FUNCTION__, spi);
return spi;
}
@@ -289,8 +201,6 @@ u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
struct xfrm6_tunnel_spi *x6spi;
u32 spi;
- X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr);
-
write_lock_bh(&xfrm6_tunnel_spi_lock);
x6spi = __xfrm6_tunnel_spi_lookup(saddr);
if (x6spi) {
@@ -300,8 +210,6 @@ u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
spi = __xfrm6_tunnel_alloc_spi(saddr);
write_unlock_bh(&xfrm6_tunnel_spi_lock);
- X6TPRINTK3(KERN_DEBUG "%s() = %u\n", __FUNCTION__, spi);
-
return spi;
}
@@ -312,8 +220,6 @@ void xfrm6_tunnel_free_spi(xfrm_address_t *saddr)
struct xfrm6_tunnel_spi *x6spi;
struct hlist_node *pos, *n;
- X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr);
-
write_lock_bh(&xfrm6_tunnel_spi_lock);
hlist_for_each_entry_safe(x6spi, pos, n,
@@ -321,12 +227,6 @@ void xfrm6_tunnel_free_spi(xfrm_address_t *saddr)
list_byaddr)
{
if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) {
- X6TPRINTK3(KERN_DEBUG "%s(): x6spi object for " NIP6_FMT
- " found at %p\n",
- __FUNCTION__,
- NIP6(*(struct in6_addr *)saddr),
- x6spi);
- X6SPI_CHECK_MAGIC(x6spi);
if (atomic_dec_and_test(&x6spi->refcnt)) {
hlist_del(&x6spi->list_byaddr);
hlist_del(&x6spi->list_byspi);
@@ -377,20 +277,14 @@ static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
case ICMPV6_ADDR_UNREACH:
case ICMPV6_PORT_UNREACH:
default:
- X6TPRINTK3(KERN_DEBUG
- "xfrm6_tunnel: Destination Unreach.\n");
break;
}
break;
case ICMPV6_PKT_TOOBIG:
- X6TPRINTK3(KERN_DEBUG
- "xfrm6_tunnel: Packet Too Big.\n");
break;
case ICMPV6_TIME_EXCEED:
switch (code) {
case ICMPV6_EXC_HOPLIMIT:
- X6TPRINTK3(KERN_DEBUG
- "xfrm6_tunnel: Too small Hoplimit.\n");
break;
case ICMPV6_EXC_FRAGTIME:
default:
@@ -447,22 +341,14 @@ static struct xfrm6_tunnel xfrm6_tunnel_handler = {
static int __init xfrm6_tunnel_init(void)
{
- X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
-
- if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0) {
- X6TPRINTK1(KERN_ERR
- "xfrm6_tunnel init: can't add xfrm type\n");
+ if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0)
return -EAGAIN;
- }
+
if (xfrm6_tunnel_register(&xfrm6_tunnel_handler)) {
- X6TPRINTK1(KERN_ERR
- "xfrm6_tunnel init(): can't add handler\n");
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
return -EAGAIN;
}
if (xfrm6_tunnel_spi_init() < 0) {
- X6TPRINTK1(KERN_ERR
- "xfrm6_tunnel init: failed to initialize spi\n");
xfrm6_tunnel_deregister(&xfrm6_tunnel_handler);
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
return -EAGAIN;
@@ -472,15 +358,9 @@ static int __init xfrm6_tunnel_init(void)
static void __exit xfrm6_tunnel_fini(void)
{
- X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
-
xfrm6_tunnel_spi_fini();
- if (xfrm6_tunnel_deregister(&xfrm6_tunnel_handler))
- X6TPRINTK1(KERN_ERR
- "xfrm6_tunnel close: can't remove handler\n");
- if (xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6) < 0)
- X6TPRINTK1(KERN_ERR
- "xfrm6_tunnel close: can't remove xfrm type\n");
+ xfrm6_tunnel_deregister(&xfrm6_tunnel_handler);
+ xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
}
module_init(xfrm6_tunnel_init);
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 7fae48a53bf..17699eeb64d 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -308,7 +308,7 @@ static void irda_connect_response(struct irda_sock *self)
IRDA_ASSERT(self != NULL, return;);
- skb = dev_alloc_skb(64);
+ skb = alloc_skb(64, GFP_ATOMIC);
if (skb == NULL) {
IRDA_DEBUG(0, "%s() Unable to allocate sk_buff!\n",
__FUNCTION__);
diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c
index 9c4a902a9db..ad6b6af3dd9 100644
--- a/net/irda/ircomm/ircomm_core.c
+++ b/net/irda/ircomm/ircomm_core.c
@@ -115,12 +115,10 @@ struct ircomm_cb *ircomm_open(notify_t *notify, __u8 service_type, int line)
IRDA_ASSERT(ircomm != NULL, return NULL;);
- self = kmalloc(sizeof(struct ircomm_cb), GFP_ATOMIC);
+ self = kzalloc(sizeof(struct ircomm_cb), GFP_ATOMIC);
if (self == NULL)
return NULL;
- memset(self, 0, sizeof(struct ircomm_cb));
-
self->notify = *notify;
self->magic = IRCOMM_MAGIC;
diff --git a/net/irda/ircomm/ircomm_lmp.c b/net/irda/ircomm/ircomm_lmp.c
index d9097207aed..959874b6451 100644
--- a/net/irda/ircomm/ircomm_lmp.c
+++ b/net/irda/ircomm/ircomm_lmp.c
@@ -81,7 +81,7 @@ static int ircomm_lmp_connect_response(struct ircomm_cb *self,
/* Any userdata supplied? */
if (userdata == NULL) {
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(64, GFP_ATOMIC);
if (!tx_skb)
return -ENOMEM;
@@ -115,7 +115,7 @@ static int ircomm_lmp_disconnect_request(struct ircomm_cb *self,
IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
if (!userdata) {
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(64, GFP_ATOMIC);
if (!tx_skb)
return -ENOMEM;
diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c
index 6009bab0509..a39f5735a90 100644
--- a/net/irda/ircomm/ircomm_param.c
+++ b/net/irda/ircomm/ircomm_param.c
@@ -121,7 +121,7 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
skb = self->ctrl_skb;
if (!skb) {
- skb = dev_alloc_skb(256);
+ skb = alloc_skb(256, GFP_ATOMIC);
if (!skb) {
spin_unlock_irqrestore(&self->spinlock, flags);
return -ENOMEM;
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index b400f27851f..3bcdb467efc 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -379,12 +379,11 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
self = hashbin_lock_find(ircomm_tty, line, NULL);
if (!self) {
/* No, so make new instance */
- self = kmalloc(sizeof(struct ircomm_tty_cb), GFP_KERNEL);
+ self = kzalloc(sizeof(struct ircomm_tty_cb), GFP_KERNEL);
if (self == NULL) {
IRDA_ERROR("%s(), kmalloc failed!\n", __FUNCTION__);
return -ENOMEM;
}
- memset(self, 0, sizeof(struct ircomm_tty_cb));
self->magic = IRCOMM_TTY_MAGIC;
self->flow = FLOW_STOP;
@@ -759,8 +758,9 @@ static int ircomm_tty_write(struct tty_struct *tty,
}
} else {
/* Prepare a full sized frame */
- skb = dev_alloc_skb(self->max_data_size+
- self->max_header_size);
+ skb = alloc_skb(self->max_data_size+
+ self->max_header_size,
+ GFP_ATOMIC);
if (!skb) {
spin_unlock_irqrestore(&self->spinlock, flags);
return -ENOBUFS;
diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c
index ba40e5495f5..7e7a31798d8 100644
--- a/net/irda/irda_device.c
+++ b/net/irda/irda_device.c
@@ -401,12 +401,10 @@ dongle_t *irda_device_dongle_init(struct net_device *dev, int type)
}
/* Allocate dongle info for this instance */
- dongle = kmalloc(sizeof(dongle_t), GFP_KERNEL);
+ dongle = kzalloc(sizeof(dongle_t), GFP_KERNEL);
if (!dongle)
goto out;
- memset(dongle, 0, sizeof(dongle_t));
-
/* Bind the registration info to this particular instance */
dongle->issue = reg;
dongle->dev = dev;
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index a0472652a44..61128aa05b4 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -345,7 +345,7 @@ static void iriap_disconnect_request(struct iriap_cb *self)
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(64, GFP_ATOMIC);
if (tx_skb == NULL) {
IRDA_DEBUG(0, "%s(), Could not allocate an sk_buff of length %d\n",
__FUNCTION__, 64);
@@ -396,7 +396,7 @@ int iriap_getvaluebyclass_request(struct iriap_cb *self,
attr_len = strlen(attr); /* Up to IAS_MAX_ATTRIBNAME = 60 */
skb_len = self->max_header_size+2+name_len+1+attr_len+4;
- tx_skb = dev_alloc_skb(skb_len);
+ tx_skb = alloc_skb(skb_len, GFP_ATOMIC);
if (!tx_skb)
return -ENOMEM;
@@ -562,7 +562,8 @@ static void iriap_getvaluebyclass_response(struct iriap_cb *self,
* value. We add 32 bytes because of the 6 bytes for the frame and
* max 5 bytes for the value coding.
*/
- tx_skb = dev_alloc_skb(value->len + self->max_header_size + 32);
+ tx_skb = alloc_skb(value->len + self->max_header_size + 32,
+ GFP_ATOMIC);
if (!tx_skb)
return;
@@ -700,7 +701,7 @@ void iriap_send_ack(struct iriap_cb *self)
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(64, GFP_ATOMIC);
if (!tx_skb)
return;
diff --git a/net/irda/iriap_event.c b/net/irda/iriap_event.c
index a73607450de..da17395df05 100644
--- a/net/irda/iriap_event.c
+++ b/net/irda/iriap_event.c
@@ -365,7 +365,7 @@ static void state_r_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
switch (event) {
case IAP_LM_CONNECT_INDICATION:
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(64, GFP_ATOMIC);
if (tx_skb == NULL) {
IRDA_WARNING("%s: unable to malloc!\n", __FUNCTION__);
return;
diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c
index 82e665c7999..a154b1d71c0 100644
--- a/net/irda/irias_object.c
+++ b/net/irda/irias_object.c
@@ -82,13 +82,12 @@ struct ias_object *irias_new_object( char *name, int id)
IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
- obj = kmalloc(sizeof(struct ias_object), GFP_ATOMIC);
+ obj = kzalloc(sizeof(struct ias_object), GFP_ATOMIC);
if (obj == NULL) {
IRDA_WARNING("%s(), Unable to allocate object!\n",
__FUNCTION__);
return NULL;
}
- memset(obj, 0, sizeof( struct ias_object));
obj->magic = IAS_OBJECT_MAGIC;
obj->name = strndup(name, IAS_MAX_CLASSNAME);
@@ -346,13 +345,12 @@ void irias_add_integer_attrib(struct ias_object *obj, char *name, int value,
IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
IRDA_ASSERT(name != NULL, return;);
- attrib = kmalloc(sizeof(struct ias_attrib), GFP_ATOMIC);
+ attrib = kzalloc(sizeof(struct ias_attrib), GFP_ATOMIC);
if (attrib == NULL) {
IRDA_WARNING("%s: Unable to allocate attribute!\n",
__FUNCTION__);
return;
}
- memset(attrib, 0, sizeof( struct ias_attrib));
attrib->magic = IAS_ATTRIB_MAGIC;
attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);
@@ -382,13 +380,12 @@ void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets,
IRDA_ASSERT(name != NULL, return;);
IRDA_ASSERT(octets != NULL, return;);
- attrib = kmalloc(sizeof(struct ias_attrib), GFP_ATOMIC);
+ attrib = kzalloc(sizeof(struct ias_attrib), GFP_ATOMIC);
if (attrib == NULL) {
IRDA_WARNING("%s: Unable to allocate attribute!\n",
__FUNCTION__);
return;
}
- memset(attrib, 0, sizeof( struct ias_attrib));
attrib->magic = IAS_ATTRIB_MAGIC;
attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);
@@ -416,13 +413,12 @@ void irias_add_string_attrib(struct ias_object *obj, char *name, char *value,
IRDA_ASSERT(name != NULL, return;);
IRDA_ASSERT(value != NULL, return;);
- attrib = kmalloc(sizeof( struct ias_attrib), GFP_ATOMIC);
+ attrib = kzalloc(sizeof( struct ias_attrib), GFP_ATOMIC);
if (attrib == NULL) {
IRDA_WARNING("%s: Unable to allocate attribute!\n",
__FUNCTION__);
return;
}
- memset(attrib, 0, sizeof( struct ias_attrib));
attrib->magic = IAS_ATTRIB_MAGIC;
attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);
@@ -443,12 +439,11 @@ struct ias_value *irias_new_integer_value(int integer)
{
struct ias_value *value;
- value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
+ value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC);
if (value == NULL) {
IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
return NULL;
}
- memset(value, 0, sizeof(struct ias_value));
value->type = IAS_INTEGER;
value->len = 4;
@@ -469,12 +464,11 @@ struct ias_value *irias_new_string_value(char *string)
{
struct ias_value *value;
- value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
+ value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC);
if (value == NULL) {
IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
return NULL;
}
- memset( value, 0, sizeof( struct ias_value));
value->type = IAS_STRING;
value->charset = CS_ASCII;
@@ -495,12 +489,11 @@ struct ias_value *irias_new_octseq_value(__u8 *octseq , int len)
{
struct ias_value *value;
- value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
+ value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC);
if (value == NULL) {
IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
return NULL;
}
- memset(value, 0, sizeof(struct ias_value));
value->type = IAS_OCT_SEQ;
/* Check length */
@@ -522,12 +515,11 @@ struct ias_value *irias_new_missing_value(void)
{
struct ias_value *value;
- value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
+ value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC);
if (value == NULL) {
IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
return NULL;
}
- memset(value, 0, sizeof(struct ias_value));
value->type = IAS_MISSING;
value->len = 0;
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
index bd659dd545a..7dd0a2fe1d2 100644
--- a/net/irda/irlan/irlan_common.c
+++ b/net/irda/irlan/irlan_common.c
@@ -636,7 +636,7 @@ void irlan_get_provider_info(struct irlan_cb *self)
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
- skb = dev_alloc_skb(64);
+ skb = alloc_skb(64, GFP_ATOMIC);
if (!skb)
return;
@@ -668,7 +668,7 @@ void irlan_open_data_channel(struct irlan_cb *self)
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
- skb = dev_alloc_skb(64);
+ skb = alloc_skb(64, GFP_ATOMIC);
if (!skb)
return;
@@ -704,7 +704,7 @@ void irlan_close_data_channel(struct irlan_cb *self)
if (self->client.tsap_ctrl == NULL)
return;
- skb = dev_alloc_skb(64);
+ skb = alloc_skb(64, GFP_ATOMIC);
if (!skb)
return;
@@ -739,7 +739,7 @@ static void irlan_open_unicast_addr(struct irlan_cb *self)
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
- skb = dev_alloc_skb(128);
+ skb = alloc_skb(128, GFP_ATOMIC);
if (!skb)
return;
@@ -777,7 +777,7 @@ void irlan_set_broadcast_filter(struct irlan_cb *self, int status)
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
- skb = dev_alloc_skb(128);
+ skb = alloc_skb(128, GFP_ATOMIC);
if (!skb)
return;
@@ -816,7 +816,7 @@ void irlan_set_multicast_filter(struct irlan_cb *self, int status)
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
- skb = dev_alloc_skb(128);
+ skb = alloc_skb(128, GFP_ATOMIC);
if (!skb)
return;
@@ -856,7 +856,7 @@ static void irlan_get_unicast_addr(struct irlan_cb *self)
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
- skb = dev_alloc_skb(128);
+ skb = alloc_skb(128, GFP_ATOMIC);
if (!skb)
return;
@@ -891,7 +891,7 @@ void irlan_get_media_char(struct irlan_cb *self)
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
- skb = dev_alloc_skb(64);
+ skb = alloc_skb(64, GFP_ATOMIC);
if (!skb)
return;
diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c
index 39c202d1c37..9c0df86044d 100644
--- a/net/irda/irlan/irlan_provider.c
+++ b/net/irda/irlan/irlan_provider.c
@@ -296,7 +296,7 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command,
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
- skb = dev_alloc_skb(128);
+ skb = alloc_skb(128, GFP_ATOMIC);
if (!skb)
return;
diff --git a/net/irda/irlap.c b/net/irda/irlap.c
index cade355ac8a..e7852a07495 100644
--- a/net/irda/irlap.c
+++ b/net/irda/irlap.c
@@ -116,11 +116,10 @@ struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
/* Initialize the irlap structure. */
- self = kmalloc(sizeof(struct irlap_cb), GFP_KERNEL);
+ self = kzalloc(sizeof(struct irlap_cb), GFP_KERNEL);
if (self == NULL)
return NULL;
- memset(self, 0, sizeof(struct irlap_cb));
self->magic = LAP_MAGIC;
/* Make a binding between the layers */
@@ -882,7 +881,7 @@ static void irlap_change_speed(struct irlap_cb *self, __u32 speed, int now)
/* Change speed now, or just piggyback speed on frames */
if (now) {
/* Send down empty frame to trigger speed change */
- skb = dev_alloc_skb(0);
+ skb = alloc_skb(0, GFP_ATOMIC);
if (skb)
irlap_queue_xmit(self, skb);
}
@@ -1222,7 +1221,7 @@ static int irlap_seq_open(struct inode *inode, struct file *file)
{
struct seq_file *seq;
int rc = -ENOMEM;
- struct irlap_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ struct irlap_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s)
goto out;
@@ -1238,7 +1237,6 @@ static int irlap_seq_open(struct inode *inode, struct file *file)
seq = file->private_data;
seq->private = s;
- memset(s, 0, sizeof(*s));
out:
return rc;
out_kfree:
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c
index 3e9a06abbdd..ccb983bf0f4 100644
--- a/net/irda/irlap_frame.c
+++ b/net/irda/irlap_frame.c
@@ -117,7 +117,7 @@ void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos)
IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
/* Allocate frame */
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(64, GFP_ATOMIC);
if (!tx_skb)
return;
@@ -210,7 +210,7 @@ void irlap_send_ua_response_frame(struct irlap_cb *self, struct qos_info *qos)
IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
/* Allocate frame */
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(64, GFP_ATOMIC);
if (!tx_skb)
return;
@@ -250,7 +250,7 @@ void irlap_send_dm_frame( struct irlap_cb *self)
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
- tx_skb = dev_alloc_skb(32);
+ tx_skb = alloc_skb(32, GFP_ATOMIC);
if (!tx_skb)
return;
@@ -282,7 +282,7 @@ void irlap_send_disc_frame(struct irlap_cb *self)
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
- tx_skb = dev_alloc_skb(16);
+ tx_skb = alloc_skb(16, GFP_ATOMIC);
if (!tx_skb)
return;
@@ -315,7 +315,7 @@ void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
IRDA_ASSERT(discovery != NULL, return;);
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(64, GFP_ATOMIC);
if (!tx_skb)
return;
@@ -422,11 +422,10 @@ static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
return;
}
- if ((discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC)) == NULL) {
+ if ((discovery = kzalloc(sizeof(discovery_t), GFP_ATOMIC)) == NULL) {
IRDA_WARNING("%s: kmalloc failed!\n", __FUNCTION__);
return;
}
- memset(discovery, 0, sizeof(discovery_t));
discovery->data.daddr = info->daddr;
discovery->data.saddr = self->saddr;
@@ -576,7 +575,7 @@ void irlap_send_rr_frame(struct irlap_cb *self, int command)
struct sk_buff *tx_skb;
__u8 *frame;
- tx_skb = dev_alloc_skb(16);
+ tx_skb = alloc_skb(16, GFP_ATOMIC);
if (!tx_skb)
return;
@@ -601,7 +600,7 @@ void irlap_send_rd_frame(struct irlap_cb *self)
struct sk_buff *tx_skb;
__u8 *frame;
- tx_skb = dev_alloc_skb(16);
+ tx_skb = alloc_skb(16, GFP_ATOMIC);
if (!tx_skb)
return;
@@ -1215,7 +1214,7 @@ void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr,
struct test_frame *frame;
__u8 *info;
- tx_skb = dev_alloc_skb(cmd->len+sizeof(struct test_frame));
+ tx_skb = alloc_skb(cmd->len+sizeof(struct test_frame), GFP_ATOMIC);
if (!tx_skb)
return;
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index 129ad64c15b..c440913dee1 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -78,10 +78,9 @@ int __init irlmp_init(void)
{
IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
/* Initialize the irlmp structure. */
- irlmp = kmalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
+ irlmp = kzalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
if (irlmp == NULL)
return -ENOMEM;
- memset(irlmp, 0, sizeof(struct irlmp_cb));
irlmp->magic = LMP_MAGIC;
@@ -160,12 +159,11 @@ struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, notify_t *notify, __u8 pid)
return NULL;
/* Allocate new instance of a LSAP connection */
- self = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
+ self = kzalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
if (self == NULL) {
IRDA_ERROR("%s: can't allocate memory\n", __FUNCTION__);
return NULL;
}
- memset(self, 0, sizeof(struct lsap_cb));
self->magic = LMP_LSAP_MAGIC;
self->slsap_sel = slsap_sel;
@@ -288,12 +286,11 @@ void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, notify_t *notify)
/*
* Allocate new instance of a LSAP connection
*/
- lap = kmalloc(sizeof(struct lap_cb), GFP_KERNEL);
+ lap = kzalloc(sizeof(struct lap_cb), GFP_KERNEL);
if (lap == NULL) {
IRDA_ERROR("%s: unable to kmalloc\n", __FUNCTION__);
return;
}
- memset(lap, 0, sizeof(struct lap_cb));
lap->irlap = irlap;
lap->magic = LMP_LAP_MAGIC;
@@ -395,7 +392,7 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
/* Any userdata? */
if (tx_skb == NULL) {
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(64, GFP_ATOMIC);
if (!tx_skb)
return -ENOMEM;
diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c
index e53bf9e0053..a1e502ff907 100644
--- a/net/irda/irnet/irnet_ppp.c
+++ b/net/irda/irnet/irnet_ppp.c
@@ -476,11 +476,10 @@ dev_irnet_open(struct inode * inode,
#endif /* SECURE_DEVIRNET */
/* Allocate a private structure for this IrNET instance */
- ap = kmalloc(sizeof(*ap), GFP_KERNEL);
+ ap = kzalloc(sizeof(*ap), GFP_KERNEL);
DABORT(ap == NULL, -ENOMEM, FS_ERROR, "Can't allocate struct irnet...\n");
/* initialize the irnet structure */
- memset(ap, 0, sizeof(*ap));
ap->file = file;
/* PPP channel setup */
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index 49c51c5f1a8..42acf1cde73 100644
--- a/net/irda/irttp.c
+++ b/net/irda/irttp.c
@@ -85,10 +85,9 @@ static pi_param_info_t param_info = { pi_major_call_table, 1, 0x0f, 4 };
*/
int __init irttp_init(void)
{
- irttp = kmalloc(sizeof(struct irttp_cb), GFP_KERNEL);
+ irttp = kzalloc(sizeof(struct irttp_cb), GFP_KERNEL);
if (irttp == NULL)
return -ENOMEM;
- memset(irttp, 0, sizeof(struct irttp_cb));
irttp->magic = TTP_MAGIC;
@@ -306,7 +305,8 @@ static inline void irttp_fragment_skb(struct tsap_cb *self,
IRDA_DEBUG(2, "%s(), fragmenting ...\n", __FUNCTION__);
/* Make new segment */
- frag = dev_alloc_skb(self->max_seg_size+self->max_header_size);
+ frag = alloc_skb(self->max_seg_size+self->max_header_size,
+ GFP_ATOMIC);
if (!frag)
return;
@@ -389,12 +389,11 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
return NULL;
}
- self = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
+ self = kzalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
if (self == NULL) {
IRDA_DEBUG(0, "%s(), unable to kmalloc!\n", __FUNCTION__);
return NULL;
}
- memset(self, 0, sizeof(struct tsap_cb));
spin_lock_init(&self->lock);
/* Initialise todo timer */
@@ -805,7 +804,7 @@ static inline void irttp_give_credit(struct tsap_cb *self)
self->send_credit, self->avail_credit, self->remote_credit);
/* Give credit to peer */
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(64, GFP_ATOMIC);
if (!tx_skb)
return;
@@ -1094,7 +1093,7 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
/* Any userdata supplied? */
if (userdata == NULL) {
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(64, GFP_ATOMIC);
if (!tx_skb)
return -ENOMEM;
@@ -1342,7 +1341,7 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
/* Any userdata supplied? */
if (userdata == NULL) {
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(64, GFP_ATOMIC);
if (!tx_skb)
return -ENOMEM;
@@ -1541,7 +1540,7 @@ int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
if (!userdata) {
struct sk_buff *tx_skb;
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(64, GFP_ATOMIC);
if (!tx_skb)
return -ENOMEM;
@@ -1876,7 +1875,7 @@ static int irttp_seq_open(struct inode *inode, struct file *file)
int rc = -ENOMEM;
struct irttp_iter_state *s;
- s = kmalloc(sizeof(*s), GFP_KERNEL);
+ s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s)
goto out;
@@ -1886,7 +1885,6 @@ static int irttp_seq_open(struct inode *inode, struct file *file)
seq = file->private_data;
seq->private = s;
- memset(s, 0, sizeof(*s));
out:
return rc;
out_kfree:
diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c
index aea6616cea3..7e6bc41eeb2 100644
--- a/net/lapb/lapb_iface.c
+++ b/net/lapb/lapb_iface.c
@@ -115,14 +115,12 @@ static struct lapb_cb *lapb_devtostruct(struct net_device *dev)
*/
static struct lapb_cb *lapb_create_cb(void)
{
- struct lapb_cb *lapb = kmalloc(sizeof(*lapb), GFP_ATOMIC);
+ struct lapb_cb *lapb = kzalloc(sizeof(*lapb), GFP_ATOMIC);
if (!lapb)
goto out;
- memset(lapb, 0x00, sizeof(*lapb));
-
skb_queue_head_init(&lapb->write_queue);
skb_queue_head_init(&lapb->ack_queue);
@@ -240,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/net/llc/af_llc.c b/net/llc/af_llc.c
index d6cfe84d521..2652ead96c6 100644
--- a/net/llc/af_llc.c
+++ b/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/net/llc/llc_core.c b/net/llc/llc_core.c
index bd242a49514..d12413cff5b 100644
--- a/net/llc/llc_core.c
+++ b/net/llc/llc_core.c
@@ -33,10 +33,9 @@ unsigned char llc_station_mac_sa[ETH_ALEN];
*/
static struct llc_sap *llc_sap_alloc(void)
{
- struct llc_sap *sap = kmalloc(sizeof(*sap), GFP_ATOMIC);
+ struct llc_sap *sap = kzalloc(sizeof(*sap), GFP_ATOMIC);
if (sap) {
- memset(sap, 0, sizeof(*sap));
sap->state = LLC_SAP_STATE_ACTIVE;
memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN);
rwlock_init(&sap->sk_list.lock);
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c
index 20c4eb5c1ac..42eb0c3a978 100644
--- a/net/llc/llc_sap.c
+++ b/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;
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 42a178aa30f..a9894ddfd72 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -386,8 +386,8 @@ config NETFILTER_XT_MATCH_REALM
<file:Documentation/modules.txt>. 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/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 5fcab2ef231..4ef83669996 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/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/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index bb6fcee452c..662a869593b 100644
--- a/net/netfilter/nf_queue.c
+++ b/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/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index c2ce9c4011c..de9537ad9a7 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/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/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index 5fe4c9df17f..a9f4f6f3c62 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -113,6 +113,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/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c
index 3ac703b5cb8..d2f5320a80b 100644
--- a/net/netfilter/xt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -9,6 +9,8 @@
#include <linux/skbuff.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
+#include <linux/in.h>
+#include <linux/ip.h>
#include <linux/netfilter/xt_pkttype.h>
#include <linux/netfilter/x_tables.h>
@@ -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/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index 0ebb6ac2c8c..d8e3891b5f8 100644
--- a/net/netfilter/xt_string.c
+++ b/net/netfilter/xt_string.c
@@ -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/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 55c0adc8f11..b85c1f9f128 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -562,10 +562,9 @@ static int netlink_alloc_groups(struct sock *sk)
if (err)
return err;
- nlk->groups = kmalloc(NLGRPSZ(groups), GFP_KERNEL);
+ nlk->groups = kzalloc(NLGRPSZ(groups), GFP_KERNEL);
if (nlk->groups == NULL)
return -ENOMEM;
- memset(nlk->groups, 0, NLGRPSZ(groups));
nlk->ngroups = groups;
return 0;
}
@@ -1393,11 +1392,10 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
struct sock *sk;
struct netlink_sock *nlk;
- cb = kmalloc(sizeof(*cb), GFP_KERNEL);
+ cb = kzalloc(sizeof(*cb), GFP_KERNEL);
if (cb == NULL)
return -ENOBUFS;
- memset(cb, 0, sizeof(*cb));
cb->dump = dump;
cb->done = done;
cb->nlh = nlh;
@@ -1668,7 +1666,7 @@ static int netlink_seq_open(struct inode *inode, struct file *file)
struct nl_seq_iter *iter;
int err;
- iter = kmalloc(sizeof(*iter), GFP_KERNEL);
+ iter = kzalloc(sizeof(*iter), GFP_KERNEL);
if (!iter)
return -ENOMEM;
@@ -1678,7 +1676,6 @@ static int netlink_seq_open(struct inode *inode, struct file *file)
return err;
}
- memset(iter, 0, sizeof(*iter));
seq = file->private_data;
seq->private = iter;
return 0;
@@ -1747,15 +1744,13 @@ static int __init netlink_proto_init(void)
if (sizeof(struct netlink_skb_parms) > sizeof(dummy_skb->cb))
netlink_skb_parms_too_large();
- nl_table = kmalloc(sizeof(*nl_table) * MAX_LINKS, GFP_KERNEL);
+ nl_table = kcalloc(MAX_LINKS, sizeof(*nl_table), GFP_KERNEL);
if (!nl_table) {
enomem:
printk(KERN_CRIT "netlink_init: Cannot allocate nl_table\n");
return -ENOMEM;
}
- memset(nl_table, 0, sizeof(*nl_table) * MAX_LINKS);
-
if (num_physpages >= (128 * 1024))
max = num_physpages >> (21 - PAGE_SHIFT);
else
diff --git a/net/rxrpc/connection.c b/net/rxrpc/connection.c
index 573b572f8f9..93d2c55ad2d 100644
--- a/net/rxrpc/connection.c
+++ b/net/rxrpc/connection.c
@@ -58,13 +58,12 @@ static inline int __rxrpc_create_connection(struct rxrpc_peer *peer,
_enter("%p",peer);
/* allocate and initialise a connection record */
- conn = kmalloc(sizeof(struct rxrpc_connection), GFP_KERNEL);
+ conn = kzalloc(sizeof(struct rxrpc_connection), GFP_KERNEL);
if (!conn) {
_leave(" = -ENOMEM");
return -ENOMEM;
}
- memset(conn, 0, sizeof(struct rxrpc_connection));
atomic_set(&conn->usage, 1);
INIT_LIST_HEAD(&conn->link);
@@ -535,13 +534,12 @@ int rxrpc_conn_newmsg(struct rxrpc_connection *conn,
return -EINVAL;
}
- msg = kmalloc(sizeof(struct rxrpc_message), alloc_flags);
+ msg = kzalloc(sizeof(struct rxrpc_message), alloc_flags);
if (!msg) {
_leave(" = -ENOMEM");
return -ENOMEM;
}
- memset(msg, 0, sizeof(*msg));
atomic_set(&msg->usage, 1);
INIT_LIST_HEAD(&msg->link);
diff --git a/net/rxrpc/peer.c b/net/rxrpc/peer.c
index ed38f5b17c1..8a275157a3b 100644
--- a/net/rxrpc/peer.c
+++ b/net/rxrpc/peer.c
@@ -58,13 +58,12 @@ static int __rxrpc_create_peer(struct rxrpc_transport *trans, __be32 addr,
_enter("%p,%08x", trans, ntohl(addr));
/* allocate and initialise a peer record */
- peer = kmalloc(sizeof(struct rxrpc_peer), GFP_KERNEL);
+ peer = kzalloc(sizeof(struct rxrpc_peer), GFP_KERNEL);
if (!peer) {
_leave(" = -ENOMEM");
return -ENOMEM;
}
- memset(peer, 0, sizeof(struct rxrpc_peer));
atomic_set(&peer->usage, 1);
INIT_LIST_HEAD(&peer->link);
diff --git a/net/rxrpc/transport.c b/net/rxrpc/transport.c
index dbe6105e83a..465efc86fcc 100644
--- a/net/rxrpc/transport.c
+++ b/net/rxrpc/transport.c
@@ -68,11 +68,10 @@ int rxrpc_create_transport(unsigned short port,
_enter("%hu", port);
- trans = kmalloc(sizeof(struct rxrpc_transport), GFP_KERNEL);
+ trans = kzalloc(sizeof(struct rxrpc_transport), GFP_KERNEL);
if (!trans)
return -ENOMEM;
- memset(trans, 0, sizeof(struct rxrpc_transport));
atomic_set(&trans->usage, 1);
INIT_LIST_HEAD(&trans->services);
INIT_LIST_HEAD(&trans->link);
@@ -312,13 +311,12 @@ static int rxrpc_incoming_msg(struct rxrpc_transport *trans,
_enter("");
- msg = kmalloc(sizeof(struct rxrpc_message), GFP_KERNEL);
+ msg = kzalloc(sizeof(struct rxrpc_message), GFP_KERNEL);
if (!msg) {
_leave(" = -ENOMEM");
return -ENOMEM;
}
- memset(msg, 0, sizeof(*msg));
atomic_set(&msg->usage, 1);
list_add_tail(&msg->link,msgq);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 9affeeedf10..a2587b52e53 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -312,10 +312,9 @@ struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est,
}
*err = -ENOMEM;
- a = kmalloc(sizeof(*a), GFP_KERNEL);
+ a = kzalloc(sizeof(*a), GFP_KERNEL);
if (a == NULL)
goto err_mod;
- memset(a, 0, sizeof(*a));
/* backward compatibility for policer */
if (name == NULL)
@@ -492,10 +491,9 @@ tcf_action_get_1(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int *err)
index = *(int *)RTA_DATA(tb[TCA_ACT_INDEX - 1]);
*err = -ENOMEM;
- a = kmalloc(sizeof(struct tc_action), GFP_KERNEL);
+ a = kzalloc(sizeof(struct tc_action), GFP_KERNEL);
if (a == NULL)
return NULL;
- memset(a, 0, sizeof(struct tc_action));
*err = -EINVAL;
a->ops = tc_lookup_action(tb[TCA_ACT_KIND - 1]);
@@ -531,12 +529,11 @@ static struct tc_action *create_a(int i)
{
struct tc_action *act;
- act = kmalloc(sizeof(*act), GFP_KERNEL);
+ act = kzalloc(sizeof(*act), GFP_KERNEL);
if (act == NULL) {
printk("create_a: failed to alloc!\n");
return NULL;
}
- memset(act, 0, sizeof(*act));
act->order = i;
return act;
}
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 58b3a865204..f257475e0e0 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -209,10 +209,9 @@ tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref)
s = sizeof(*opt) + p->nkeys * sizeof(struct tc_pedit_key);
/* netlink spinlocks held above us - must use ATOMIC */
- opt = kmalloc(s, GFP_ATOMIC);
+ opt = kzalloc(s, GFP_ATOMIC);
if (opt == NULL)
return -ENOBUFS;
- memset(opt, 0, s);
memcpy(opt->keys, p->keys, p->nkeys * sizeof(struct tc_pedit_key));
opt->index = p->index;
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 47e00bd9625..da905d7b4b4 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -196,10 +196,9 @@ static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,
return ret;
}
- p = kmalloc(sizeof(*p), GFP_KERNEL);
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL)
return -ENOMEM;
- memset(p, 0, sizeof(*p));
ret = ACT_P_CREATED;
p->refcnt = 1;
@@ -429,11 +428,10 @@ struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est)
return p;
}
- p = kmalloc(sizeof(*p), GFP_KERNEL);
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL)
return NULL;
- memset(p, 0, sizeof(*p));
p->refcnt = 1;
spin_lock_init(&p->lock);
p->stats_lock = &p->lock;
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 61507f006b1..86cac49a053 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -178,19 +178,17 @@ static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
err = -ENOBUFS;
if (head == NULL) {
- head = kmalloc(sizeof(*head), GFP_KERNEL);
+ head = kzalloc(sizeof(*head), GFP_KERNEL);
if (head == NULL)
goto errout;
- memset(head, 0, sizeof(*head));
INIT_LIST_HEAD(&head->flist);
tp->root = head;
}
- f = kmalloc(sizeof(*f), GFP_KERNEL);
+ f = kzalloc(sizeof(*f), GFP_KERNEL);
if (f == NULL)
goto errout;
- memset(f, 0, sizeof(*f));
err = -EINVAL;
if (handle)
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index d41de91fc4f..e6973d9b686 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -267,20 +267,18 @@ static int fw_change(struct tcf_proto *tp, unsigned long base,
return -EINVAL;
if (head == NULL) {
- head = kmalloc(sizeof(struct fw_head), GFP_KERNEL);
+ head = kzalloc(sizeof(struct fw_head), GFP_KERNEL);
if (head == NULL)
return -ENOBUFS;
- memset(head, 0, sizeof(*head));
tcf_tree_lock(tp);
tp->root = head;
tcf_tree_unlock(tp);
}
- f = kmalloc(sizeof(struct fw_filter), GFP_KERNEL);
+ f = kzalloc(sizeof(struct fw_filter), GFP_KERNEL);
if (f == NULL)
return -ENOBUFS;
- memset(f, 0, sizeof(*f));
f->id = handle;
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index c2e71900f7b..d3aea730d4c 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -396,10 +396,9 @@ static int route4_set_parms(struct tcf_proto *tp, unsigned long base,
h1 = to_hash(nhandle);
if ((b = head->table[h1]) == NULL) {
err = -ENOBUFS;
- b = kmalloc(sizeof(struct route4_bucket), GFP_KERNEL);
+ b = kzalloc(sizeof(struct route4_bucket), GFP_KERNEL);
if (b == NULL)
goto errout;
- memset(b, 0, sizeof(*b));
tcf_tree_lock(tp);
head->table[h1] = b;
@@ -475,20 +474,18 @@ static int route4_change(struct tcf_proto *tp, unsigned long base,
err = -ENOBUFS;
if (head == NULL) {
- head = kmalloc(sizeof(struct route4_head), GFP_KERNEL);
+ head = kzalloc(sizeof(struct route4_head), GFP_KERNEL);
if (head == NULL)
goto errout;
- memset(head, 0, sizeof(struct route4_head));
tcf_tree_lock(tp);
tp->root = head;
tcf_tree_unlock(tp);
}
- f = kmalloc(sizeof(struct route4_filter), GFP_KERNEL);
+ f = kzalloc(sizeof(struct route4_filter), GFP_KERNEL);
if (f == NULL)
goto errout;
- memset(f, 0, sizeof(*f));
err = route4_set_parms(tp, base, f, handle, head, tb,
tca[TCA_RATE-1], 1);
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index ba874197162..6e230ecfba0 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -240,9 +240,8 @@ static int rsvp_init(struct tcf_proto *tp)
{
struct rsvp_head *data;
- data = kmalloc(sizeof(struct rsvp_head), GFP_KERNEL);
+ data = kzalloc(sizeof(struct rsvp_head), GFP_KERNEL);
if (data) {
- memset(data, 0, sizeof(struct rsvp_head));
tp->root = data;
return 0;
}
@@ -446,11 +445,10 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
goto errout2;
err = -ENOBUFS;
- f = kmalloc(sizeof(struct rsvp_filter), GFP_KERNEL);
+ f = kzalloc(sizeof(struct rsvp_filter), GFP_KERNEL);
if (f == NULL)
goto errout2;
- memset(f, 0, sizeof(*f));
h2 = 16;
if (tb[TCA_RSVP_SRC-1]) {
err = -EINVAL;
@@ -532,10 +530,9 @@ insert:
/* No session found. Create new one. */
err = -ENOBUFS;
- s = kmalloc(sizeof(struct rsvp_session), GFP_KERNEL);
+ s = kzalloc(sizeof(struct rsvp_session), GFP_KERNEL);
if (s == NULL)
goto errout;
- memset(s, 0, sizeof(*s));
memcpy(s->dst, dst, sizeof(s->dst));
if (pinfo) {
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 7870e7bb0ba..5af8a59e150 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -148,11 +148,10 @@ static int tcindex_init(struct tcf_proto *tp)
struct tcindex_data *p;
DPRINTK("tcindex_init(tp %p)\n",tp);
- p = kmalloc(sizeof(struct tcindex_data),GFP_KERNEL);
+ p = kzalloc(sizeof(struct tcindex_data),GFP_KERNEL);
if (!p)
return -ENOMEM;
- memset(p, 0, sizeof(*p));
p->mask = 0xffff;
p->hash = DEFAULT_HASH_SIZE;
p->fall_through = 1;
@@ -296,16 +295,14 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
err = -ENOMEM;
if (!cp.perfect && !cp.h) {
if (valid_perfect_hash(&cp)) {
- cp.perfect = kmalloc(cp.hash * sizeof(*r), GFP_KERNEL);
+ cp.perfect = kcalloc(cp.hash, sizeof(*r), GFP_KERNEL);
if (!cp.perfect)
goto errout;
- memset(cp.perfect, 0, cp.hash * sizeof(*r));
balloc = 1;
} else {
- cp.h = kmalloc(cp.hash * sizeof(f), GFP_KERNEL);
+ cp.h = kcalloc(cp.hash, sizeof(f), GFP_KERNEL);
if (!cp.h)
goto errout;
- memset(cp.h, 0, cp.hash * sizeof(f));
balloc = 2;
}
}
@@ -316,10 +313,9 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
r = tcindex_lookup(&cp, handle) ? : &new_filter_result;
if (r == &new_filter_result) {
- f = kmalloc(sizeof(*f), GFP_KERNEL);
+ f = kzalloc(sizeof(*f), GFP_KERNEL);
if (!f)
goto errout_alloc;
- memset(f, 0, sizeof(*f));
}
if (tb[TCA_TCINDEX_CLASSID-1]) {
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index d712edcd1bc..eea36696674 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -307,23 +307,21 @@ static int u32_init(struct tcf_proto *tp)
if (tp_c->q == tp->q)
break;
- root_ht = kmalloc(sizeof(*root_ht), GFP_KERNEL);
+ root_ht = kzalloc(sizeof(*root_ht), GFP_KERNEL);
if (root_ht == NULL)
return -ENOBUFS;
- memset(root_ht, 0, sizeof(*root_ht));
root_ht->divisor = 0;
root_ht->refcnt++;
root_ht->handle = tp_c ? gen_new_htid(tp_c) : 0x80000000;
root_ht->prio = tp->prio;
if (tp_c == NULL) {
- tp_c = kmalloc(sizeof(*tp_c), GFP_KERNEL);
+ tp_c = kzalloc(sizeof(*tp_c), GFP_KERNEL);
if (tp_c == NULL) {
kfree(root_ht);
return -ENOBUFS;
}
- memset(tp_c, 0, sizeof(*tp_c));
tp_c->q = tp->q;
tp_c->next = u32_list;
u32_list = tp_c;
@@ -571,10 +569,9 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
if (handle == 0)
return -ENOMEM;
}
- ht = kmalloc(sizeof(*ht) + divisor*sizeof(void*), GFP_KERNEL);
+ ht = kzalloc(sizeof(*ht) + divisor*sizeof(void*), GFP_KERNEL);
if (ht == NULL)
return -ENOBUFS;
- memset(ht, 0, sizeof(*ht) + divisor*sizeof(void*));
ht->tp_c = tp_c;
ht->refcnt = 0;
ht->divisor = divisor;
@@ -617,18 +614,16 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
s = RTA_DATA(tb[TCA_U32_SEL-1]);
- n = kmalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key), GFP_KERNEL);
+ n = kzalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key), GFP_KERNEL);
if (n == NULL)
return -ENOBUFS;
- memset(n, 0, sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key));
#ifdef CONFIG_CLS_U32_PERF
- n->pf = kmalloc(sizeof(struct tc_u32_pcnt) + s->nkeys*sizeof(u64), GFP_KERNEL);
+ n->pf = kzalloc(sizeof(struct tc_u32_pcnt) + s->nkeys*sizeof(u64), GFP_KERNEL);
if (n->pf == NULL) {
kfree(n);
return -ENOBUFS;
}
- memset(n->pf, 0, sizeof(struct tc_u32_pcnt) + s->nkeys*sizeof(u64));
#endif
memcpy(&n->sel, s, sizeof(*s) + s->nkeys*sizeof(struct tc_u32_key));
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index 698372954f4..61e3b740ab1 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -773,10 +773,9 @@ static int em_meta_change(struct tcf_proto *tp, void *data, int len,
TCF_META_ID(hdr->right.kind) > TCF_META_ID_MAX)
goto errout;
- meta = kmalloc(sizeof(*meta), GFP_KERNEL);
+ meta = kzalloc(sizeof(*meta), GFP_KERNEL);
if (meta == NULL)
goto errout;
- memset(meta, 0, sizeof(*meta));
memcpy(&meta->lvalue.hdr, &hdr->left, sizeof(hdr->left));
memcpy(&meta->rvalue.hdr, &hdr->right, sizeof(hdr->right));
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index 2405a86093a..0fd0768a17c 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -321,10 +321,9 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct rtattr *rta,
list_len = RTA_PAYLOAD(rt_list);
matches_len = tree_hdr->nmatches * sizeof(*em);
- tree->matches = kmalloc(matches_len, GFP_KERNEL);
+ tree->matches = kzalloc(matches_len, GFP_KERNEL);
if (tree->matches == NULL)
goto errout;
- memset(tree->matches, 0, matches_len);
/* We do not use rtattr_parse_nested here because the maximum
* number of attributes is unknown. This saves us the allocation
diff --git a/net/sched/estimator.c b/net/sched/estimator.c
index 5d3ae03e22a..0ebc98e9be2 100644
--- a/net/sched/estimator.c
+++ b/net/sched/estimator.c
@@ -139,11 +139,10 @@ int qdisc_new_estimator(struct tc_stats *stats, spinlock_t *stats_lock, struct r
if (parm->interval < -2 || parm->interval > 3)
return -EINVAL;
- est = kmalloc(sizeof(*est), GFP_KERNEL);
+ est = kzalloc(sizeof(*est), GFP_KERNEL);
if (est == NULL)
return -ENOBUFS;
- memset(est, 0, sizeof(*est));
est->interval = parm->interval + 2;
est->stats = stats;
est->stats_lock = stats_lock;
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index c7844bacbbc..a19eff12cf7 100644
--- a/net/sched/sch_api.c
+++ b/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/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 80b7f6a8d00..bac881bfe36 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1926,10 +1926,9 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
}
err = -ENOBUFS;
- cl = kmalloc(sizeof(*cl), GFP_KERNEL);
+ cl = kzalloc(sizeof(*cl), GFP_KERNEL);
if (cl == NULL)
goto failure;
- memset(cl, 0, sizeof(*cl));
cl->R_tab = rtab;
rtab = NULL;
cl->refcnt = 1;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index d735f51686a..0834c2ee917 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -432,10 +432,9 @@ struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops)
size = QDISC_ALIGN(sizeof(*sch));
size += ops->priv_size + (QDISC_ALIGNTO - 1);
- p = kmalloc(size, GFP_KERNEL);
+ p = kzalloc(size, GFP_KERNEL);
if (!p)
goto errout;
- memset(p, 0, size);
sch = (struct Qdisc *) QDISC_ALIGN((unsigned long) p);
sch->padded = (char *) sch - (char *) p;
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index 0cafdd5feb1..18e81a8ffb0 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -406,10 +406,9 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp,
struct gred_sched_data *q;
if (table->tab[dp] == NULL) {
- table->tab[dp] = kmalloc(sizeof(*q), GFP_KERNEL);
+ table->tab[dp] = kzalloc(sizeof(*q), GFP_KERNEL);
if (table->tab[dp] == NULL)
return -ENOMEM;
- memset(table->tab[dp], 0, sizeof(*q));
}
q = table->tab[dp];
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 6b1b4a981e8..6a6735a2ed3 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -1123,10 +1123,9 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
if (rsc == NULL && fsc == NULL)
return -EINVAL;
- cl = kmalloc(sizeof(struct hfsc_class), GFP_KERNEL);
+ cl = kzalloc(sizeof(struct hfsc_class), GFP_KERNEL);
if (cl == NULL)
return -ENOBUFS;
- memset(cl, 0, sizeof(struct hfsc_class));
if (rsc != NULL)
hfsc_change_rsc(cl, rsc, 0);
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index cc5f339e6f9..880a3394a51 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1559,10 +1559,9 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
goto failure;
}
err = -ENOBUFS;
- if ((cl = kmalloc(sizeof(*cl), GFP_KERNEL)) == NULL)
+ if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL)
goto failure;
- memset(cl, 0, sizeof(*cl));
cl->refcnt = 1;
INIT_LIST_HEAD(&cl->sibling);
INIT_LIST_HEAD(&cl->hlist);
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index c5bd8064e6d..a08ec4c7c55 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -148,7 +148,8 @@ static long tabledist(unsigned long mu, long sigma,
static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
struct netem_sched_data *q = qdisc_priv(sch);
- struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb;
+ /* We don't fill cb now as skb_unshare() may invalidate it */
+ struct netem_skb_cb *cb;
struct sk_buff *skb2;
int ret;
int count = 1;
@@ -200,6 +201,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
skb->data[net_random() % skb_headlen(skb)] ^= 1<<(net_random() % 8);
}
+ cb = (struct netem_skb_cb *)skb->cb;
if (q->gap == 0 /* not doing reordering */
|| q->counter < q->gap /* inside last reordering gap */
|| q->reorder < get_crandom(&q->reorder_cor)) {
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 9d05e13e92f..27329ce9c31 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -441,7 +441,8 @@ void sctp_assoc_set_primary(struct sctp_association *asoc,
/* If the primary path is changing, assume that the
* user wants to use this new path.
*/
- if (transport->state != SCTP_INACTIVE)
+ if ((transport->state == SCTP_ACTIVE) ||
+ (transport->state == SCTP_UNKNOWN))
asoc->peer.active_path = transport;
/*
@@ -532,11 +533,11 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
port = addr->v4.sin_port;
SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ",
- " port: %d state:%s\n",
+ " port: %d state:%d\n",
asoc,
addr,
addr->v4.sin_port,
- peer_state == SCTP_UNKNOWN?"UNKNOWN":"ACTIVE");
+ peer_state);
/* Set the port if it has not been set yet. */
if (0 == asoc->peer.port)
@@ -545,9 +546,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
/* Check to see if this is a duplicate. */
peer = sctp_assoc_lookup_paddr(asoc, addr);
if (peer) {
- if (peer_state == SCTP_ACTIVE &&
- peer->state == SCTP_UNKNOWN)
- peer->state = SCTP_ACTIVE;
+ if (peer->state == SCTP_UNKNOWN) {
+ if (peer_state == SCTP_ACTIVE)
+ peer->state = SCTP_ACTIVE;
+ if (peer_state == SCTP_UNCONFIRMED)
+ peer->state = SCTP_UNCONFIRMED;
+ }
return peer;
}
@@ -739,7 +743,8 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
list_for_each(pos, &asoc->peer.transport_addr_list) {
t = list_entry(pos, struct sctp_transport, transports);
- if (t->state == SCTP_INACTIVE)
+ if ((t->state == SCTP_INACTIVE) ||
+ (t->state == SCTP_UNCONFIRMED))
continue;
if (!first || t->last_time_heard > first->last_time_heard) {
second = first;
@@ -759,7 +764,8 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
* [If the primary is active but not most recent, bump the most
* recently used transport.]
*/
- if (asoc->peer.primary_path->state != SCTP_INACTIVE &&
+ if (((asoc->peer.primary_path->state == SCTP_ACTIVE) ||
+ (asoc->peer.primary_path->state == SCTP_UNKNOWN)) &&
first != asoc->peer.primary_path) {
second = first;
first = asoc->peer.primary_path;
@@ -1054,7 +1060,7 @@ void sctp_assoc_update(struct sctp_association *asoc,
transports);
if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr))
sctp_assoc_add_peer(asoc, &trans->ipaddr,
- GFP_ATOMIC, SCTP_ACTIVE);
+ GFP_ATOMIC, trans->state);
}
asoc->ctsn_ack_point = asoc->next_tsn - 1;
@@ -1094,7 +1100,8 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
/* Try to find an active transport. */
- if (t->state != SCTP_INACTIVE) {
+ if ((t->state == SCTP_ACTIVE) ||
+ (t->state == SCTP_UNKNOWN)) {
break;
} else {
/* Keep track of the next transport in case
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index 2b962627f63..2b9c12a170e 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -146,7 +146,7 @@ void sctp_bind_addr_free(struct sctp_bind_addr *bp)
/* Add an address to the bind address list in the SCTP_bind_addr structure. */
int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
- gfp_t gfp)
+ __u8 use_as_src, gfp_t gfp)
{
struct sctp_sockaddr_entry *addr;
@@ -163,6 +163,8 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
if (!addr->a.v4.sin_port)
addr->a.v4.sin_port = bp->port;
+ addr->use_as_src = use_as_src;
+
INIT_LIST_HEAD(&addr->list);
list_add_tail(&addr->list, &bp->address_list);
SCTP_DBG_OBJCNT_INC(addr);
@@ -274,7 +276,7 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
}
af->from_addr_param(&addr, rawaddr, port, 0);
- retval = sctp_add_bind_addr(bp, &addr, gfp);
+ retval = sctp_add_bind_addr(bp, &addr, 1, gfp);
if (retval) {
/* Can't finish building the list, clean up. */
sctp_bind_addr_clean(bp);
@@ -367,7 +369,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
(((AF_INET6 == addr->sa.sa_family) &&
(flags & SCTP_ADDR6_ALLOWED) &&
(flags & SCTP_ADDR6_PEERSUPP))))
- error = sctp_add_bind_addr(dest, addr, gfp);
+ error = sctp_add_bind_addr(dest, addr, 1, gfp);
}
return error;
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 67bd53070ee..ffda1d68052 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -158,6 +158,12 @@ void sctp_endpoint_add_asoc(struct sctp_endpoint *ep,
void sctp_endpoint_free(struct sctp_endpoint *ep)
{
ep->base.dead = 1;
+
+ ep->base.sk->sk_state = SCTP_SS_CLOSED;
+
+ /* Unlink this endpoint, so we can't find it again! */
+ sctp_unhash_endpoint(ep);
+
sctp_endpoint_put(ep);
}
@@ -166,11 +172,6 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
{
SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return);
- ep->base.sk->sk_state = SCTP_SS_CLOSED;
-
- /* Unlink this endpoint, so we can't find it again! */
- sctp_unhash_endpoint(ep);
-
/* Free up the HMAC transform. */
sctp_crypto_free_tfm(sctp_sk(ep->base.sk)->hmac);
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 8ef08070c8b..99c0cefc04e 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -290,7 +290,8 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc,
sctp_read_lock(addr_lock);
list_for_each(pos, &bp->address_list) {
laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
- if ((laddr->a.sa.sa_family == AF_INET6) &&
+ if ((laddr->use_as_src) &&
+ (laddr->a.sa.sa_family == AF_INET6) &&
(scope <= sctp_scope(&laddr->a))) {
bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
if (!baddr || (matchlen < bmatchlen)) {
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index e5faa351aaa..30b710c54e6 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -691,7 +691,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
if (!new_transport) {
new_transport = asoc->peer.active_path;
- } else if (new_transport->state == SCTP_INACTIVE) {
+ } else if ((new_transport->state == SCTP_INACTIVE) ||
+ (new_transport->state == SCTP_UNCONFIRMED)) {
/* If the chunk is Heartbeat or Heartbeat Ack,
* send it to chunk->transport, even if it's
* inactive.
@@ -848,7 +849,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
*/
new_transport = chunk->transport;
if (!new_transport ||
- new_transport->state == SCTP_INACTIVE)
+ ((new_transport->state == SCTP_INACTIVE) ||
+ (new_transport->state == SCTP_UNCONFIRMED)))
new_transport = asoc->peer.active_path;
/* Change packets if necessary. */
@@ -1464,7 +1466,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
/* Mark the destination transport address as
* active if it is not so marked.
*/
- if (transport->state == SCTP_INACTIVE) {
+ if ((transport->state == SCTP_INACTIVE) ||
+ (transport->state == SCTP_UNCONFIRMED)) {
sctp_assoc_control_transport(
transport->asoc,
transport,
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 816c033d788..1ab03a27a76 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -240,7 +240,7 @@ int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope,
(((AF_INET6 == addr->a.sa.sa_family) &&
(copy_flags & SCTP_ADDR6_ALLOWED) &&
(copy_flags & SCTP_ADDR6_PEERSUPP)))) {
- error = sctp_add_bind_addr(bp, &addr->a,
+ error = sctp_add_bind_addr(bp, &addr->a, 1,
GFP_ATOMIC);
if (error)
goto end_copy;
@@ -486,6 +486,8 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
list_for_each(pos, &bp->address_list) {
laddr = list_entry(pos, struct sctp_sockaddr_entry,
list);
+ if (!laddr->use_as_src)
+ continue;
sctp_v4_dst_saddr(&dst_saddr, dst, bp->port);
if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a))
goto out_unlock;
@@ -506,7 +508,8 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
list_for_each(pos, &bp->address_list) {
laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
- if (AF_INET == laddr->a.sa.sa_family) {
+ if ((laddr->use_as_src) &&
+ (AF_INET == laddr->a.sa.sa_family)) {
fl.fl4_src = laddr->a.v4.sin_addr.s_addr;
if (!ip_route_output_key(&rt, &fl)) {
dst = &rt->u.dst;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 2a877369169..4f11f585820 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1493,7 +1493,7 @@ no_hmac:
/* Also, add the destination address. */
if (list_empty(&retval->base.bind_addr.address_list)) {
- sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest,
+ sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest, 1,
GFP_ATOMIC);
}
@@ -2017,7 +2017,7 @@ static int sctp_process_param(struct sctp_association *asoc,
af->from_addr_param(&addr, param.addr, asoc->peer.port, 0);
scope = sctp_scope(peer_addr);
if (sctp_in_scope(&addr, scope))
- if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_ACTIVE))
+ if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED))
return 0;
break;
@@ -2418,7 +2418,7 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc,
* Due to Resource Shortage'.
*/
- peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_ACTIVE);
+ peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_UNCONFIRMED);
if (!peer)
return SCTP_ERROR_RSRC_LOW;
@@ -2565,6 +2565,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
union sctp_addr_param *addr_param;
struct list_head *pos;
struct sctp_transport *transport;
+ struct sctp_sockaddr_entry *saddr;
int retval = 0;
addr_param = (union sctp_addr_param *)
@@ -2578,7 +2579,11 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
case SCTP_PARAM_ADD_IP:
sctp_local_bh_disable();
sctp_write_lock(&asoc->base.addr_lock);
- retval = sctp_add_bind_addr(bp, &addr, GFP_ATOMIC);
+ list_for_each(pos, &bp->address_list) {
+ saddr = list_entry(pos, struct sctp_sockaddr_entry, list);
+ if (sctp_cmp_addr_exact(&saddr->a, &addr))
+ saddr->use_as_src = 1;
+ }
sctp_write_unlock(&asoc->base.addr_lock);
sctp_local_bh_enable();
break;
@@ -2591,6 +2596,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
list_for_each(pos, &asoc->peer.transport_addr_list) {
transport = list_entry(pos, struct sctp_transport,
transports);
+ dst_release(transport->dst);
sctp_transport_route(transport, NULL,
sctp_sk(asoc->base.sk));
}
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index c5beb2ad7ef..9c10bdec1af 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -430,7 +430,11 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
/* The check for association's overall error counter exceeding the
* threshold is done in the state function.
*/
- asoc->overall_error_count++;
+ /* When probing UNCONFIRMED addresses, the association overall
+ * error count is NOT incremented
+ */
+ if (transport->state != SCTP_UNCONFIRMED)
+ asoc->overall_error_count++;
if (transport->state != SCTP_INACTIVE &&
(transport->error_count++ >= transport->pathmaxrxt)) {
@@ -610,7 +614,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
/* Mark the destination transport address as active if it is not so
* marked.
*/
- if (t->state == SCTP_INACTIVE)
+ if ((t->state == SCTP_INACTIVE) || (t->state == SCTP_UNCONFIRMED))
sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP,
SCTP_HEARTBEAT_SUCCESS);
@@ -620,6 +624,10 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
*/
hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data;
sctp_transport_update_rto(t, (jiffies - hbinfo->sent_at));
+
+ /* Update the heartbeat timer. */
+ if (!mod_timer(&t->hb_timer, sctp_transport_timeout(t)))
+ sctp_transport_hold(t);
}
/* Helper function to do a transport reset at the expiry of the hearbeat
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 9e58144f485..ead3f1b0ea3 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -846,6 +846,7 @@ static sctp_disposition_t sctp_sf_heartbeat(const struct sctp_endpoint *ep,
hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t));
hbinfo.daddr = transport->ipaddr;
hbinfo.sent_at = jiffies;
+ hbinfo.hb_nonce = transport->hb_nonce;
/* Send a heartbeat to our peer. */
paylen = sizeof(sctp_sender_hb_info_t);
@@ -1048,6 +1049,10 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
return SCTP_DISPOSITION_DISCARD;
}
+ /* Validate the 64-bit random nonce. */
+ if (hbinfo->hb_nonce != link->hb_nonce)
+ return SCTP_DISPOSITION_DISCARD;
+
max_interval = link->hbinterval + link->rto;
/* Check if the timestamp looks valid. */
@@ -5278,7 +5283,6 @@ static int sctp_eat_data(const struct sctp_association *asoc,
datalen -= sizeof(sctp_data_chunk_t);
deliver = SCTP_CMD_CHUNK_ULP;
- chunk->data_accepted = 1;
/* Think about partial delivery. */
if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) {
@@ -5357,6 +5361,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
if (SCTP_CMD_CHUNK_ULP == deliver)
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn));
+ chunk->data_accepted = 1;
+
/* Note: Some chunks may get overcounted (if we drop) or overcounted
* if we renege and the chunk arrives again.
*/
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 0a2c71d0d8a..54722e622e6 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -369,7 +369,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
/* Use GFP_ATOMIC since BHs are disabled. */
addr->v4.sin_port = ntohs(addr->v4.sin_port);
- ret = sctp_add_bind_addr(bp, addr, GFP_ATOMIC);
+ ret = sctp_add_bind_addr(bp, addr, 1, GFP_ATOMIC);
addr->v4.sin_port = htons(addr->v4.sin_port);
sctp_write_unlock(&ep->base.addr_lock);
sctp_local_bh_enable();
@@ -491,6 +491,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
struct sctp_chunk *chunk;
struct sctp_sockaddr_entry *laddr;
union sctp_addr *addr;
+ union sctp_addr saveaddr;
void *addr_buf;
struct sctp_af *af;
struct list_head *pos;
@@ -558,14 +559,26 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
}
retval = sctp_send_asconf(asoc, chunk);
+ if (retval)
+ goto out;
- /* FIXME: After sending the add address ASCONF chunk, we
- * cannot append the address to the association's binding
- * address list, because the new address may be used as the
- * source of a message sent to the peer before the ASCONF
- * chunk is received by the peer. So we should wait until
- * ASCONF_ACK is received.
+ /* Add the new addresses to the bind address list with
+ * use_as_src set to 0.
*/
+ sctp_local_bh_disable();
+ sctp_write_lock(&asoc->base.addr_lock);
+ addr_buf = addrs;
+ for (i = 0; i < addrcnt; i++) {
+ addr = (union sctp_addr *)addr_buf;
+ af = sctp_get_af_specific(addr->v4.sin_family);
+ memcpy(&saveaddr, addr, af->sockaddr_len);
+ saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port);
+ retval = sctp_add_bind_addr(bp, &saveaddr, 0,
+ GFP_ATOMIC);
+ addr_buf += af->sockaddr_len;
+ }
+ sctp_write_unlock(&asoc->base.addr_lock);
+ sctp_local_bh_enable();
}
out:
@@ -676,12 +689,15 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
struct sctp_sock *sp;
struct sctp_endpoint *ep;
struct sctp_association *asoc;
+ struct sctp_transport *transport;
struct sctp_bind_addr *bp;
struct sctp_chunk *chunk;
union sctp_addr *laddr;
+ union sctp_addr saveaddr;
void *addr_buf;
struct sctp_af *af;
- struct list_head *pos;
+ struct list_head *pos, *pos1;
+ struct sctp_sockaddr_entry *saddr;
int i;
int retval = 0;
@@ -748,14 +764,42 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
goto out;
}
- retval = sctp_send_asconf(asoc, chunk);
+ /* Reset use_as_src flag for the addresses in the bind address
+ * list that are to be deleted.
+ */
+ sctp_local_bh_disable();
+ sctp_write_lock(&asoc->base.addr_lock);
+ addr_buf = addrs;
+ for (i = 0; i < addrcnt; i++) {
+ laddr = (union sctp_addr *)addr_buf;
+ af = sctp_get_af_specific(laddr->v4.sin_family);
+ memcpy(&saveaddr, laddr, af->sockaddr_len);
+ saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port);
+ list_for_each(pos1, &bp->address_list) {
+ saddr = list_entry(pos1,
+ struct sctp_sockaddr_entry,
+ list);
+ if (sctp_cmp_addr_exact(&saddr->a, &saveaddr))
+ saddr->use_as_src = 0;
+ }
+ addr_buf += af->sockaddr_len;
+ }
+ sctp_write_unlock(&asoc->base.addr_lock);
+ sctp_local_bh_enable();
- /* FIXME: After sending the delete address ASCONF chunk, we
- * cannot remove the addresses from the association's bind
- * address list, because there maybe some packet send to
- * the delete addresses, so we should wait until ASCONF_ACK
- * packet is received.
+ /* Update the route and saddr entries for all the transports
+ * as some of the addresses in the bind address list are
+ * about to be deleted and cannot be used as source addresses.
*/
+ list_for_each(pos1, &asoc->peer.transport_addr_list) {
+ transport = list_entry(pos1, struct sctp_transport,
+ transports);
+ dst_release(transport->dst);
+ sctp_transport_route(transport, NULL,
+ sctp_sk(asoc->base.sk));
+ }
+
+ retval = sctp_send_asconf(asoc, chunk);
}
out:
return retval;
@@ -4977,7 +5021,7 @@ static struct sctp_bind_bucket *sctp_bucket_create(
/* Caller must hold hashbucket lock for this tb with local BH disabled */
static void sctp_bucket_destroy(struct sctp_bind_bucket *pp)
{
- if (hlist_empty(&pp->owner)) {
+ if (pp && hlist_empty(&pp->owner)) {
if (pp->next)
pp->next->pprev = pp->pprev;
*(pp->pprev) = pp->next;
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 160f62ad1cc..2763aa93de1 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -49,6 +49,7 @@
*/
#include <linux/types.h>
+#include <linux/random.h>
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
@@ -85,7 +86,6 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
peer->init_sent_count = 0;
- peer->state = SCTP_ACTIVE;
peer->param_flags = SPP_HB_DISABLE |
SPP_PMTUD_ENABLE |
SPP_SACKDELAY_ENABLE;
@@ -109,6 +109,9 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
peer->hb_timer.function = sctp_generate_heartbeat_event;
peer->hb_timer.data = (unsigned long)peer;
+ /* Initialize the 64-bit random nonce sent with heartbeat. */
+ get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce));
+
atomic_set(&peer->refcnt, 1);
peer->dead = 0;
@@ -517,7 +520,9 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
unsigned long sctp_transport_timeout(struct sctp_transport *t)
{
unsigned long timeout;
- timeout = t->hbinterval + t->rto + sctp_jitter(t->rto);
+ timeout = t->rto + sctp_jitter(t->rto);
+ if (t->state != SCTP_UNCONFIRMED)
+ timeout += t->hbinterval;
timeout += jiffies;
return timeout;
}
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 519ebc17c02..4a9aa9393b9 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -225,9 +225,8 @@ gss_alloc_context(void)
{
struct gss_cl_ctx *ctx;
- ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (ctx != NULL) {
- memset(ctx, 0, sizeof(*ctx));
ctx->gc_proc = RPC_GSS_PROC_DATA;
ctx->gc_seq = 1; /* NetApp 6.4R1 doesn't accept seq. no. 0 */
spin_lock_init(&ctx->gc_seq_lock);
@@ -391,9 +390,8 @@ gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
{
struct gss_upcall_msg *gss_msg;
- gss_msg = kmalloc(sizeof(*gss_msg), GFP_KERNEL);
+ gss_msg = kzalloc(sizeof(*gss_msg), GFP_KERNEL);
if (gss_msg != NULL) {
- memset(gss_msg, 0, sizeof(*gss_msg));
INIT_LIST_HEAD(&gss_msg->list);
rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
init_waitqueue_head(&gss_msg->waitqueue);
@@ -776,10 +774,9 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
dprintk("RPC: gss_create_cred for uid %d, flavor %d\n",
acred->uid, auth->au_flavor);
- if (!(cred = kmalloc(sizeof(*cred), GFP_KERNEL)))
+ if (!(cred = kzalloc(sizeof(*cred), GFP_KERNEL)))
goto out_err;
- memset(cred, 0, sizeof(*cred));
atomic_set(&cred->gc_count, 1);
cred->gc_uid = acred->uid;
/*
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index b8714a87b34..70e1e53a632 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -129,9 +129,8 @@ gss_import_sec_context_kerberos(const void *p,
const void *end = (const void *)((const char *)p + len);
struct krb5_ctx *ctx;
- if (!(ctx = kmalloc(sizeof(*ctx), GFP_KERNEL)))
+ if (!(ctx = kzalloc(sizeof(*ctx), GFP_KERNEL)))
goto out_err;
- memset(ctx, 0, sizeof(*ctx));
p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));
if (IS_ERR(p))
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index d88468d21c3..3db745379d0 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -237,9 +237,8 @@ gss_import_sec_context(const void *input_token, size_t bufsize,
struct gss_api_mech *mech,
struct gss_ctx **ctx_id)
{
- if (!(*ctx_id = kmalloc(sizeof(**ctx_id), GFP_KERNEL)))
+ if (!(*ctx_id = kzalloc(sizeof(**ctx_id), GFP_KERNEL)))
return GSS_S_FAILURE;
- memset(*ctx_id, 0, sizeof(**ctx_id));
(*ctx_id)->mech_type = gss_mech_get(mech);
return mech->gm_ops
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index 3d0432aa45c..88dcb52d171 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -152,9 +152,8 @@ gss_import_sec_context_spkm3(const void *p, size_t len,
const void *end = (const void *)((const char *)p + len);
struct spkm3_ctx *ctx;
- if (!(ctx = kmalloc(sizeof(*ctx), GFP_KERNEL)))
+ if (!(ctx = kzalloc(sizeof(*ctx), GFP_KERNEL)))
goto out_err;
- memset(ctx, 0, sizeof(*ctx));
p = simple_get_netobj(p, end, &ctx->ctx_id);
if (IS_ERR(p))
diff --git a/net/sunrpc/auth_gss/gss_spkm3_token.c b/net/sunrpc/auth_gss/gss_spkm3_token.c
index af0d7ce7468..854a983ccf2 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_token.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_token.c
@@ -90,10 +90,9 @@ asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits)
int
decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen, int explen)
{
- if (!(out->data = kmalloc(explen,GFP_KERNEL)))
+ if (!(out->data = kzalloc(explen,GFP_KERNEL)))
return 0;
out->len = explen;
- memset(out->data, 0, explen);
memcpy(out->data, in, enclen);
return 1;
}
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 7026b0866b7..00cb388ece0 100644
--- a/net/sunrpc/cache.c
+++ b/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/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index aa8965e9d30..d6409e75721 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -125,10 +125,9 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname,
goto out_err;
err = -ENOMEM;
- clnt = kmalloc(sizeof(*clnt), GFP_KERNEL);
+ clnt = kzalloc(sizeof(*clnt), GFP_KERNEL);
if (!clnt)
goto out_err;
- memset(clnt, 0, sizeof(*clnt));
atomic_set(&clnt->cl_users, 0);
atomic_set(&clnt->cl_count, 1);
clnt->cl_parent = clnt;
@@ -922,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);
}
@@ -993,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/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index dc6cb93c883..a3bd2db2e02 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/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/net/sunrpc/stats.c b/net/sunrpc/stats.c
index 15c2db26767..bd98124c3a6 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -114,13 +114,8 @@ void svc_seq_show(struct seq_file *seq, const struct svc_stat *statp) {
*/
struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt)
{
- unsigned int ops = clnt->cl_maxproc;
- size_t size = ops * sizeof(struct rpc_iostats);
struct rpc_iostats *new;
-
- new = kmalloc(size, GFP_KERNEL);
- if (new)
- memset(new, 0 , size);
+ new = kcalloc(clnt->cl_maxproc, sizeof(struct rpc_iostats), GFP_KERNEL);
return new;
}
EXPORT_SYMBOL(rpc_alloc_iostats);
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 01ba60a4957..b76a227dd3a 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -32,9 +32,8 @@ svc_create(struct svc_program *prog, unsigned int bufsize)
int vers;
unsigned int xdrsize;
- if (!(serv = kmalloc(sizeof(*serv), GFP_KERNEL)))
+ if (!(serv = kzalloc(sizeof(*serv), GFP_KERNEL)))
return NULL;
- memset(serv, 0, sizeof(*serv));
serv->sv_name = prog->pg_name;
serv->sv_program = prog;
serv->sv_nrthreads = 1;
@@ -159,11 +158,10 @@ svc_create_thread(svc_thread_fn func, struct svc_serv *serv)
struct svc_rqst *rqstp;
int error = -ENOMEM;
- rqstp = kmalloc(sizeof(*rqstp), GFP_KERNEL);
+ rqstp = kzalloc(sizeof(*rqstp), GFP_KERNEL);
if (!rqstp)
goto out;
- memset(rqstp, 0, sizeof(*rqstp));
init_waitqueue_head(&rqstp->rq_wait);
if (!(rqstp->rq_argp = kmalloc(serv->sv_xdrsize, GFP_KERNEL))
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index a27905a0ad2..d9a95732df4 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1322,11 +1322,10 @@ svc_setup_socket(struct svc_serv *serv, struct socket *sock,
struct sock *inet;
dprintk("svc: svc_setup_socket %p\n", sock);
- if (!(svsk = kmalloc(sizeof(*svsk), GFP_KERNEL))) {
+ if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) {
*errp = -ENOMEM;
return NULL;
}
- memset(svsk, 0, sizeof(*svsk));
inet = sock->sk;
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 02060d0e7be..e8c2bc4977f 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -707,12 +707,9 @@ out_unlock:
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)
@@ -908,9 +893,8 @@ static struct rpc_xprt *xprt_setup(int proto, struct sockaddr_in *ap, struct rpc
struct rpc_xprt *xprt;
struct rpc_rqst *req;
- if ((xprt = kmalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL)
+ if ((xprt = kzalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL)
return ERR_PTR(-ENOMEM);
- memset(xprt, 0, sizeof(*xprt)); /* Nnnngh! */
xprt->addr = *ap;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 21006b10910..441bd53f5ec 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -414,6 +414,33 @@ static int xs_tcp_send_request(struct rpc_task *task)
}
/**
+ * 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,
@@ -1276,10 +1303,9 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
xprt->max_reqs = xprt_udp_slot_table_entries;
slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
- xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
+ xprt->slot = kzalloc(slot_table_size, GFP_KERNEL);
if (xprt->slot == NULL)
return -ENOMEM;
- memset(xprt->slot, 0, slot_table_size);
xprt->prot = IPPROTO_UDP;
xprt->port = xs_get_random_port();
@@ -1318,10 +1344,9 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
xprt->max_reqs = xprt_tcp_slot_table_entries;
slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]);
- xprt->slot = kmalloc(slot_table_size, GFP_KERNEL);
+ xprt->slot = kzalloc(slot_table_size, GFP_KERNEL);
if (xprt->slot == NULL)
return -ENOMEM;
- memset(xprt->slot, 0, slot_table_size);
xprt->prot = IPPROTO_TCP;
xprt->port = xs_get_random_port();
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 7ef17a449cf..75a5968c213 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -665,11 +665,9 @@ int tipc_bearer_init(void)
int res;
write_lock_bh(&tipc_net_lock);
- tipc_bearers = kmalloc(MAX_BEARERS * sizeof(struct bearer), GFP_ATOMIC);
- media_list = kmalloc(MAX_MEDIA * sizeof(struct media), GFP_ATOMIC);
+ tipc_bearers = kcalloc(MAX_BEARERS, sizeof(struct bearer), GFP_ATOMIC);
+ media_list = kcalloc(MAX_MEDIA, sizeof(struct media), GFP_ATOMIC);
if (tipc_bearers && media_list) {
- memset(tipc_bearers, 0, MAX_BEARERS * sizeof(struct bearer));
- memset(media_list, 0, MAX_MEDIA * sizeof(struct media));
res = TIPC_OK;
} else {
kfree(tipc_bearers);
diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c
index 1dcb6940e33..b46b5188a9f 100644
--- a/net/tipc/cluster.c
+++ b/net/tipc/cluster.c
@@ -57,29 +57,25 @@ struct cluster *tipc_cltr_create(u32 addr)
struct _zone *z_ptr;
struct cluster *c_ptr;
int max_nodes;
- int alloc;
- c_ptr = (struct cluster *)kmalloc(sizeof(*c_ptr), GFP_ATOMIC);
+ c_ptr = kzalloc(sizeof(*c_ptr), GFP_ATOMIC);
if (c_ptr == NULL) {
warn("Cluster creation failure, no memory\n");
return NULL;
}
- memset(c_ptr, 0, sizeof(*c_ptr));
c_ptr->addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
if (in_own_cluster(addr))
max_nodes = LOWEST_SLAVE + tipc_max_slaves;
else
max_nodes = tipc_max_nodes + 1;
- alloc = sizeof(void *) * (max_nodes + 1);
- c_ptr->nodes = (struct node **)kmalloc(alloc, GFP_ATOMIC);
+ c_ptr->nodes = kcalloc(max_nodes + 1, sizeof(void*), GFP_ATOMIC);
if (c_ptr->nodes == NULL) {
warn("Cluster creation failure, no memory for node area\n");
kfree(c_ptr);
return NULL;
}
- memset(c_ptr->nodes, 0, alloc);
if (in_own_cluster(addr))
tipc_local_nodes = c_ptr->nodes;
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index 2b844120312..ee94de92ae9 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -295,7 +295,7 @@ struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr,
{
struct link_req *req;
- req = (struct link_req *)kmalloc(sizeof(*req), GFP_ATOMIC);
+ req = kmalloc(sizeof(*req), GFP_ATOMIC);
if (!req)
return NULL;
diff --git a/net/tipc/link.c b/net/tipc/link.c
index c10e18a49b9..693f02eca6d 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -417,12 +417,11 @@ struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer,
struct tipc_msg *msg;
char *if_name;
- l_ptr = (struct link *)kmalloc(sizeof(*l_ptr), GFP_ATOMIC);
+ l_ptr = kzalloc(sizeof(*l_ptr), GFP_ATOMIC);
if (!l_ptr) {
warn("Link creation failed, no memory\n");
return NULL;
}
- memset(l_ptr, 0, sizeof(*l_ptr));
l_ptr->addr = peer;
if_name = strchr(b_ptr->publ.name, ':') + 1;
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index a6926ff07bc..049242ea5c3 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -117,14 +117,12 @@ static struct publication *publ_create(u32 type, u32 lower, u32 upper,
u32 scope, u32 node, u32 port_ref,
u32 key)
{
- struct publication *publ =
- (struct publication *)kmalloc(sizeof(*publ), GFP_ATOMIC);
+ struct publication *publ = kzalloc(sizeof(*publ), GFP_ATOMIC);
if (publ == NULL) {
warn("Publication creation failure, no memory\n");
return NULL;
}
- memset(publ, 0, sizeof(*publ));
publ->type = type;
publ->lower = lower;
publ->upper = upper;
@@ -144,11 +142,7 @@ static struct publication *publ_create(u32 type, u32 lower, u32 upper,
static struct sub_seq *tipc_subseq_alloc(u32 cnt)
{
- u32 sz = cnt * sizeof(struct sub_seq);
- struct sub_seq *sseq = (struct sub_seq *)kmalloc(sz, GFP_ATOMIC);
-
- if (sseq)
- memset(sseq, 0, sz);
+ struct sub_seq *sseq = kcalloc(cnt, sizeof(struct sub_seq), GFP_ATOMIC);
return sseq;
}
@@ -160,8 +154,7 @@ static struct sub_seq *tipc_subseq_alloc(u32 cnt)
static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_head)
{
- struct name_seq *nseq =
- (struct name_seq *)kmalloc(sizeof(*nseq), GFP_ATOMIC);
+ struct name_seq *nseq = kzalloc(sizeof(*nseq), GFP_ATOMIC);
struct sub_seq *sseq = tipc_subseq_alloc(1);
if (!nseq || !sseq) {
@@ -171,7 +164,6 @@ static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_hea
return NULL;
}
- memset(nseq, 0, sizeof(*nseq));
spin_lock_init(&nseq->lock);
nseq->type = type;
nseq->sseqs = sseq;
@@ -1060,7 +1052,7 @@ int tipc_nametbl_init(void)
{
int array_size = sizeof(struct hlist_head) * tipc_nametbl_size;
- table.types = (struct hlist_head *)kmalloc(array_size, GFP_ATOMIC);
+ table.types = kmalloc(array_size, GFP_ATOMIC);
if (!table.types)
return -ENOMEM;
diff --git a/net/tipc/net.c b/net/tipc/net.c
index e5a359ab493..a991bf8a7f7 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -160,14 +160,11 @@ void tipc_net_send_external_routes(u32 dest)
static int net_init(void)
{
- u32 sz = sizeof(struct _zone *) * (tipc_max_zones + 1);
-
memset(&tipc_net, 0, sizeof(tipc_net));
- tipc_net.zones = (struct _zone **)kmalloc(sz, GFP_ATOMIC);
+ tipc_net.zones = kcalloc(tipc_max_zones + 1, sizeof(struct _zone *), GFP_ATOMIC);
if (!tipc_net.zones) {
return -ENOMEM;
}
- memset(tipc_net.zones, 0, sz);
return TIPC_OK;
}
diff --git a/net/tipc/port.c b/net/tipc/port.c
index 3251c8d8e53..b9c8c6b9e94 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -226,12 +226,11 @@ u32 tipc_createport_raw(void *usr_handle,
struct tipc_msg *msg;
u32 ref;
- p_ptr = kmalloc(sizeof(*p_ptr), GFP_ATOMIC);
+ p_ptr = kzalloc(sizeof(*p_ptr), GFP_ATOMIC);
if (!p_ptr) {
warn("Port creation failed, no memory\n");
return 0;
}
- memset(p_ptr, 0, sizeof(*p_ptr));
ref = tipc_ref_acquire(p_ptr, &p_ptr->publ.lock);
if (!ref) {
warn("Port creation failed, reference table exhausted\n");
@@ -1058,7 +1057,7 @@ int tipc_createport(u32 user_ref,
struct port *p_ptr;
u32 ref;
- up_ptr = (struct user_port *)kmalloc(sizeof(*up_ptr), GFP_ATOMIC);
+ up_ptr = kmalloc(sizeof(*up_ptr), GFP_ATOMIC);
if (!up_ptr) {
warn("Port creation failed, no memory\n");
return -ENOMEM;
diff --git a/net/tipc/ref.c b/net/tipc/ref.c
index 596d3c8ff75..e6d6ae22ea4 100644
--- a/net/tipc/ref.c
+++ b/net/tipc/ref.c
@@ -79,7 +79,7 @@ int tipc_ref_table_init(u32 requested_size, u32 start)
while (sz < requested_size) {
sz <<= 1;
}
- table = (struct reference *)vmalloc(sz * sizeof(struct reference));
+ table = vmalloc(sz * sizeof(*table));
if (table == NULL)
return -ENOMEM;
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index e19b4bcd67e..c51600ba5f4 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -393,12 +393,11 @@ static void subscr_named_msg_event(void *usr_handle,
/* Create subscriber object */
- subscriber = kmalloc(sizeof(struct subscriber), GFP_ATOMIC);
+ subscriber = kzalloc(sizeof(struct subscriber), GFP_ATOMIC);
if (subscriber == NULL) {
warn("Subscriber rejected, no memory\n");
return;
}
- memset(subscriber, 0, sizeof(struct subscriber));
INIT_LIST_HEAD(&subscriber->subscription_list);
INIT_LIST_HEAD(&subscriber->subscriber_list);
subscriber->ref = tipc_ref_acquire(subscriber, &subscriber->lock);
diff --git a/net/tipc/user_reg.c b/net/tipc/user_reg.c
index 1e3ae57c722..04d1b9be9c5 100644
--- a/net/tipc/user_reg.c
+++ b/net/tipc/user_reg.c
@@ -82,9 +82,8 @@ static int reg_init(void)
spin_lock_bh(&reg_lock);
if (!users) {
- users = (struct tipc_user *)kmalloc(USER_LIST_SIZE, GFP_ATOMIC);
+ users = kzalloc(USER_LIST_SIZE, GFP_ATOMIC);
if (users) {
- memset(users, 0, USER_LIST_SIZE);
for (i = 1; i <= MAX_USERID; i++) {
users[i].next = i - 1;
}
diff --git a/net/tipc/zone.c b/net/tipc/zone.c
index 316c4872ff5..f5b00ea2d5a 100644
--- a/net/tipc/zone.c
+++ b/net/tipc/zone.c
@@ -52,13 +52,12 @@ struct _zone *tipc_zone_create(u32 addr)
return NULL;
}
- z_ptr = (struct _zone *)kmalloc(sizeof(*z_ptr), GFP_ATOMIC);
+ z_ptr = kzalloc(sizeof(*z_ptr), GFP_ATOMIC);
if (!z_ptr) {
warn("Zone creation failed, insufficient memory\n");
return NULL;
}
- memset(z_ptr, 0, sizeof(*z_ptr));
z_num = tipc_zone(addr);
z_ptr->addr = tipc_addr(z_num, 0, 0);
tipc_net.zones[z_num] = z_ptr;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index f70475bfb62..de6ec519272 100644
--- a/net/unix/af_unix.c
+++ b/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)
@@ -663,11 +657,10 @@ static int unix_autobind(struct socket *sock)
goto out;
err = -ENOMEM;
- addr = kmalloc(sizeof(*addr) + sizeof(short) + 16, GFP_KERNEL);
+ addr = kzalloc(sizeof(*addr) + sizeof(short) + 16, GFP_KERNEL);
if (!addr)
goto out;
- memset(addr, 0, sizeof(*addr) + sizeof(short) + 16);
addr->name->sun_family = AF_UNIX;
atomic_set(&addr->refcnt, 1);
@@ -1323,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/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
index a690cf773b6..6f39faa1583 100644
--- a/net/wanrouter/af_wanpipe.c
+++ b/net/wanrouter/af_wanpipe.c
@@ -370,12 +370,11 @@ static int wanpipe_listen_rcv (struct sk_buff *skb, struct sock *sk)
* used by the ioctl call to read call information
* and to execute commands.
*/
- if ((mbox_ptr = kmalloc(sizeof(mbox_cmd_t), GFP_ATOMIC)) == NULL) {
+ if ((mbox_ptr = kzalloc(sizeof(mbox_cmd_t), GFP_ATOMIC)) == NULL) {
wanpipe_kill_sock_irq (newsk);
release_device(dev);
return -ENOMEM;
}
- memset(mbox_ptr, 0, sizeof(mbox_cmd_t));
memcpy(mbox_ptr,skb->data,skb->len);
/* Register the lcn on which incoming call came
@@ -507,11 +506,10 @@ static struct sock *wanpipe_alloc_socket(void)
if ((sk = sk_alloc(PF_WANPIPE, GFP_ATOMIC, &wanpipe_proto, 1)) == NULL)
return NULL;
- if ((wan_opt = kmalloc(sizeof(struct wanpipe_opt), GFP_ATOMIC)) == NULL) {
+ if ((wan_opt = kzalloc(sizeof(struct wanpipe_opt), GFP_ATOMIC)) == NULL) {
sk_free(sk);
return NULL;
}
- memset(wan_opt, 0x00, sizeof(struct wanpipe_opt));
wp_sk(sk) = wan_opt;
@@ -2011,10 +2009,9 @@ static int set_ioctl_cmd (struct sock *sk, void *arg)
dev_put(dev);
- if ((mbox_ptr = kmalloc(sizeof(mbox_cmd_t), GFP_ATOMIC)) == NULL)
+ if ((mbox_ptr = kzalloc(sizeof(mbox_cmd_t), GFP_ATOMIC)) == NULL)
return -ENOMEM;
- memset(mbox_ptr, 0, sizeof(mbox_cmd_t));
wp_sk(sk)->mbox = mbox_ptr;
wanpipe_link_driver(dev,sk);
diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
index ad8e8a79779..9479659277a 100644
--- a/net/wanrouter/wanmain.c
+++ b/net/wanrouter/wanmain.c
@@ -642,18 +642,16 @@ static int wanrouter_device_new_if(struct wan_device *wandev,
if (cnf->config_id == WANCONFIG_MPPP) {
#ifdef CONFIG_WANPIPE_MULTPPP
- pppdev = kmalloc(sizeof(struct ppp_device), GFP_KERNEL);
+ pppdev = kzalloc(sizeof(struct ppp_device), GFP_KERNEL);
err = -ENOBUFS;
if (pppdev == NULL)
goto out;
- memset(pppdev, 0, sizeof(struct ppp_device));
- pppdev->dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
+ pppdev->dev = kzalloc(sizeof(struct net_device), GFP_KERNEL);
if (pppdev->dev == NULL) {
kfree(pppdev);
err = -ENOBUFS;
goto out;
}
- memset(pppdev->dev, 0, sizeof(struct net_device));
err = wandev->new_if(wandev, (struct net_device *)pppdev, cnf);
dev = pppdev->dev;
#else
@@ -663,11 +661,10 @@ static int wanrouter_device_new_if(struct wan_device *wandev,
goto out;
#endif
} else {
- dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
+ dev = kzalloc(sizeof(struct net_device), GFP_KERNEL);
err = -ENOBUFS;
if (dev == NULL)
goto out;
- memset(dev, 0, sizeof(struct net_device));
err = wandev->new_if(wandev, dev, cnf);
}
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 405b741dff4..f35bc676128 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -307,10 +307,9 @@ struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp)
{
struct xfrm_policy *policy;
- policy = kmalloc(sizeof(struct xfrm_policy), gfp);
+ policy = kzalloc(sizeof(struct xfrm_policy), gfp);
if (policy) {
- memset(policy, 0, sizeof(struct xfrm_policy));
atomic_set(&policy->refcnt, 1);
rwlock_init(&policy->lock);
init_timer(&policy->timer);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 43f00fc28a3..0021aad5db4 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -194,10 +194,9 @@ struct xfrm_state *xfrm_state_alloc(void)
{
struct xfrm_state *x;
- x = kmalloc(sizeof(struct xfrm_state), GFP_ATOMIC);
+ x = kzalloc(sizeof(struct xfrm_state), GFP_ATOMIC);
if (x) {
- memset(x, 0, sizeof(struct xfrm_state));
atomic_set(&x->refcnt, 1);
atomic_set(&x->tunnel_users, 0);
INIT_LIST_HEAD(&x->bydst);
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 2180c88cfe8..bb19c1561f1 100644
--- a/scripts/Kbuild.include
+++ b/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/scripts/Makefile.modpost b/scripts/Makefile.modpost
index a49550205dc..0a64688c2b5 100644
--- a/scripts/Makefile.modpost
+++ b/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/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 2ee48c377b6..a69d8acbf27 100644
--- a/scripts/kconfig/confdata.c
+++ b/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/scripts/kernel-doc b/scripts/kernel-doc
index f9460a6218d..c9ca0c23bd9 100755
--- a/scripts/kernel-doc
+++ b/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/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 37f67c23e11..44312926b84 100644
--- a/scripts/mod/file2alias.c
+++ b/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;
@@ -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/security/dummy.c b/security/dummy.c
index bbbfda70e13..58c6d399c84 100644
--- a/security/dummy.c
+++ b/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/security/selinux/hooks.c b/security/selinux/hooks.c
index a91c961ba38..5d1b8c73319 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3524,25 +3524,21 @@ out:
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/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 0111990ba83..f03960e697c 100644
--- a/security/selinux/ss/policydb.c
+++ b/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/security/selinux/ss/services.c b/security/selinux/ss/services.c
index d2e80e62ff0..85e42988439 100644
--- a/security/selinux/ss/services.c
+++ b/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/sound/aoa/codecs/snd-aoa-codec-toonie.c b/sound/aoa/codecs/snd-aoa-codec-toonie.c
index bcc555647e7..3c7d1d8a9a6 100644
--- a/sound/aoa/codecs/snd-aoa-codec-toonie.c
+++ b/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/sound/aoa/core/snd-aoa-gpio-feature.c b/sound/aoa/core/snd-aoa-gpio-feature.c
index 7ae0c0bdfad..f69d33357a2 100644
--- a/sound/aoa/core/snd-aoa-gpio-feature.c
+++ b/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(&notif->mutex);
diff --git a/sound/aoa/core/snd-aoa-gpio-pmf.c b/sound/aoa/core/snd-aoa-gpio-pmf.c
index 3d57fd1aec4..2836c321839 100644
--- a/sound/aoa/core/snd-aoa-gpio-pmf.c
+++ b/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<<bit); \
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 71b5080fa66..75a9505c744 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -988,13 +988,12 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, struct snd_mix
if (ptr->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/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index f5ff4f4a16e..472fce0ee0e 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/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/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 4260de90f36..102ff548ce6 100644
--- a/sound/core/seq/seq_device.c
+++ b/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/sound/core/sgbuf.c b/sound/core/sgbuf.c
index 6e4d4ab3463..c30669f14ac 100644
--- a/sound/core/sgbuf.c
+++ b/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/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
index c4af84995d0..7e65a103fbb 100644
--- a/sound/drivers/vx/vx_pcm.c
+++ b/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/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 27a8dbe6f6a..c3dafa29054 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/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/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index f9b5c3dc3b3..79f24cdf5fb 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/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/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c
index a8b31286b6d..1076af4c366 100644
--- a/sound/pci/emu10k1/irq.c
+++ b/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/sound/ppc/awacs.c b/sound/ppc/awacs.c
index 82d791be749..05dabe45465 100644
--- a/sound/ppc/awacs.c
+++ b/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/sound/ppc/daca.c b/sound/ppc/daca.c
index 46eebf5610e..57202b0f033 100644
--- a/sound/ppc/daca.c
+++ b/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/sound/ppc/keywest.c b/sound/ppc/keywest.c
index fb05938dcbd..59482a4cd44 100644
--- a/sound/ppc/keywest.c
+++ b/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/sound/ppc/powermac.c b/sound/ppc/powermac.c
index fa9a44ab487..2264574fa06 100644
--- a/sound/ppc/powermac.c
+++ b/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/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 692c6117767..84f6b19c07c 100644
--- a/sound/ppc/tumbler.c
+++ b/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/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index d32d83d970c..1b7f499c549 100644
--- a/sound/usb/usbaudio.c
+++ b/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;