summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CREDITS8
-rw-r--r--Documentation/00-INDEX2
-rw-r--r--Documentation/ABI/testing/sysfs-dev20
-rw-r--r--Documentation/ABI/testing/sysfs-devices-memory24
-rw-r--r--Documentation/ABI/testing/sysfs-kernel-mm6
-rw-r--r--Documentation/ABI/testing/sysfs-kernel-mm-hugepages15
-rw-r--r--Documentation/CodingStyle42
-rw-r--r--Documentation/DMA-attributes.txt9
-rw-r--r--Documentation/DocBook/kernel-locking.tmpl57
-rw-r--r--Documentation/DocBook/procfs-guide.tmpl4
-rw-r--r--Documentation/DocBook/uio-howto.tmpl63
-rw-r--r--Documentation/HOWTO2
-rw-r--r--Documentation/accounting/delay-accounting.txt11
-rw-r--r--Documentation/accounting/getdelays.c8
-rw-r--r--Documentation/accounting/taskstats-struct.txt7
-rw-r--r--Documentation/bt8xxgpio.txt67
-rw-r--r--Documentation/controllers/memory.txt3
-rw-r--r--Documentation/edac.txt151
-rw-r--r--Documentation/fb/sh7760fb.txt131
-rw-r--r--Documentation/fb/tridentfb.txt46
-rw-r--r--Documentation/feature-removal-schedule.txt26
-rw-r--r--Documentation/filesystems/Locking7
-rw-r--r--Documentation/filesystems/bfs.txt10
-rw-r--r--Documentation/filesystems/proc.txt44
-rw-r--r--Documentation/filesystems/sysfs.txt6
-rw-r--r--Documentation/filesystems/vfat.txt8
-rw-r--r--Documentation/gpio.txt135
-rw-r--r--Documentation/kernel-parameters.txt49
-rw-r--r--Documentation/laptops/thinkpad-acpi.txt26
-rw-r--r--Documentation/moxa-smartio392
-rw-r--r--Documentation/networking/e1000.txt14
-rw-r--r--Documentation/networking/udplite.txt2
-rw-r--r--Documentation/power/00-INDEX4
-rw-r--r--Documentation/power/apm-acpi.txt32
-rw-r--r--Documentation/power/pm.txt257
-rw-r--r--Documentation/powerpc/booting-without-of.txt246
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt38
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/usb.txt53
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/mcu-mpc8349emitx.txt17
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/pmc.txt63
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/tsec.txt31
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/upm-nand.txt28
-rw-r--r--Documentation/powerpc/dts-bindings/gpio/led.txt15
-rw-r--r--Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl2
-rw-r--r--Documentation/specialix.txt8
-rw-r--r--Documentation/sysfs-rules.txt5
-rw-r--r--Documentation/telephony/ixj.txt13
-rw-r--r--Documentation/unaligned-memory-access.txt32
-rw-r--r--Documentation/video4linux/w9968cf.txt3
-rw-r--r--Documentation/vm/hugetlbpage.txt23
-rw-r--r--MAINTAINERS60
-rw-r--r--Makefile4
-rw-r--r--arch/Kconfig29
-rw-r--r--arch/alpha/Kconfig5
-rw-r--r--arch/alpha/boot/misc.c39
-rw-r--r--arch/alpha/mm/numa.c10
-rw-r--r--arch/arm/Kconfig22
-rw-r--r--arch/arm/boot/compressed/misc.c59
-rw-r--r--arch/arm/common/dmabounce.c22
-rw-r--r--arch/arm/common/locomo.c2
-rw-r--r--arch/arm/common/sa1111.c12
-rw-r--r--arch/arm/common/scoop.c2
-rw-r--r--arch/arm/configs/ezx_defconfig1614
-rw-r--r--arch/arm/kernel/Makefile1
-rw-r--r--arch/arm/kernel/ecard.c5
-rw-r--r--arch/arm/kernel/kgdb.c201
-rw-r--r--arch/arm/kernel/kprobes.c6
-rw-r--r--arch/arm/kernel/module.c1
-rw-r--r--arch/arm/kernel/process.c2
-rw-r--r--arch/arm/kernel/setup.c2
-rw-r--r--arch/arm/kernel/time.c4
-rw-r--r--arch/arm/kernel/traps.c5
-rw-r--r--arch/arm/mach-integrator/impd1.c7
-rw-r--r--arch/arm/mach-integrator/lm.c6
-rw-r--r--arch/arm/mach-iop32x/n2100.c52
-rw-r--r--arch/arm/mach-ns9xxx/clock.c2
-rw-r--r--arch/arm/mach-pxa/Kconfig219
-rw-r--r--arch/arm/mach-pxa/Makefile15
-rw-r--r--arch/arm/mach-pxa/clock.c30
-rw-r--r--arch/arm/mach-pxa/clock.h33
-rw-r--r--arch/arm/mach-pxa/cm-x270-pci.c27
-rw-r--r--arch/arm/mach-pxa/cm-x270-pci.h14
-rw-r--r--arch/arm/mach-pxa/cm-x270.c403
-rw-r--r--arch/arm/mach-pxa/corgi.c1
-rw-r--r--arch/arm/mach-pxa/devices.c61
-rw-r--r--arch/arm/mach-pxa/devices.h2
-rw-r--r--arch/arm/mach-pxa/e400_lcd.c56
-rw-r--r--arch/arm/mach-pxa/e740_lcd.c123
-rw-r--r--arch/arm/mach-pxa/e750_lcd.c109
-rw-r--r--arch/arm/mach-pxa/e800_lcd.c159
-rw-r--r--arch/arm/mach-pxa/em-x270.c371
-rw-r--r--arch/arm/mach-pxa/eseries.c15
-rw-r--r--arch/arm/mach-pxa/eseries_udc.c57
-rw-r--r--arch/arm/mach-pxa/ezx.c220
-rw-r--r--arch/arm/mach-pxa/littleton.c70
-rw-r--r--arch/arm/mach-pxa/lubbock.c19
-rw-r--r--arch/arm/mach-pxa/magician.c49
-rw-r--r--arch/arm/mach-pxa/mainstone.c18
-rw-r--r--arch/arm/mach-pxa/mfp-pxa2xx.c71
-rw-r--r--arch/arm/mach-pxa/palmtx.c416
-rw-r--r--arch/arm/mach-pxa/pcm027.c31
-rw-r--r--arch/arm/mach-pxa/pcm990-baseboard.c74
-rw-r--r--arch/arm/mach-pxa/poodle.c1
-rw-r--r--arch/arm/mach-pxa/pxa25x.c59
-rw-r--r--arch/arm/mach-pxa/pxa300.c19
-rw-r--r--arch/arm/mach-pxa/pxa320.c21
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c25
-rw-r--r--arch/arm/mach-pxa/pxa930.c190
-rw-r--r--arch/arm/mach-pxa/reset.c96
-rw-r--r--arch/arm/mach-pxa/saar.c84
-rw-r--r--arch/arm/mach-pxa/spitz.c10
-rw-r--r--arch/arm/mach-pxa/ssp.c13
-rw-r--r--arch/arm/mach-pxa/tavorevb.c84
-rw-r--r--arch/arm/mach-pxa/tosa-bt.c150
-rw-r--r--arch/arm/mach-pxa/tosa.c382
-rw-r--r--arch/arm/mach-pxa/trizeps4.c1
-rw-r--r--arch/arm/mach-pxa/zylonite.c103
-rw-r--r--arch/arm/mach-pxa/zylonite_pxa300.c46
-rw-r--r--arch/arm/mach-pxa/zylonite_pxa320.c6
-rw-r--r--arch/arm/mach-sa1100/clock.c2
-rw-r--r--arch/arm/mm/Makefile2
-rw-r--r--arch/arm/mm/discontig.c34
-rw-r--r--arch/arm/mm/init.c2
-rw-r--r--arch/arm/plat-omap/fb.c5
-rw-r--r--arch/arm/plat-omap/gpio.c3
-rw-r--r--arch/arm/plat-omap/mailbox.c2
-rw-r--r--arch/arm/tools/mach-types10
-rw-r--r--arch/avr32/Kconfig3
-rw-r--r--arch/avr32/kernel/cpu.c38
-rw-r--r--arch/avr32/kernel/process.c2
-rw-r--r--arch/avr32/kernel/stacktrace.c1
-rw-r--r--arch/avr32/mach-at32ap/at32ap700x.c27
-rw-r--r--arch/avr32/mach-at32ap/pio.c2
-rw-r--r--arch/avr32/mm/init.c5
-rw-r--r--arch/avr32/mm/ioremap.c1
-rw-r--r--arch/blackfin/Kconfig4
-rw-r--r--arch/blackfin/kernel/process.c2
-rw-r--r--arch/cris/arch-v10/boot/compressed/misc.c36
-rw-r--r--arch/cris/arch-v10/mm/init.c2
-rw-r--r--arch/cris/arch-v32/boot/compressed/misc.c39
-rw-r--r--arch/cris/arch-v32/mm/init.c2
-rw-r--r--arch/cris/kernel/profile.c17
-rw-r--r--arch/frv/kernel/pm.c1
-rw-r--r--arch/h8300/Kconfig14
-rw-r--r--arch/h8300/boot/compressed/misc.c38
-rw-r--r--arch/h8300/kernel/setup.c1
-rw-r--r--arch/ia64/ia32/sys_ia32.c2
-rw-r--r--arch/ia64/kernel/entry.S6
-rw-r--r--arch/ia64/kernel/err_inject.c22
-rw-r--r--arch/ia64/kernel/kprobes.c6
-rw-r--r--arch/ia64/kernel/sys_ia64.c2
-rw-r--r--arch/ia64/mm/discontig.c30
-rw-r--r--arch/ia64/mm/hugetlbpage.c15
-rw-r--r--arch/m32r/boot/compressed/misc.c37
-rw-r--r--arch/m32r/mm/discontig.c10
-rw-r--r--arch/m32r/mm/init.c6
-rw-r--r--arch/m68k/amiga/chipram.c1
-rw-r--r--arch/m68k/mm/init.c4
-rw-r--r--arch/m68k/mm/motorola.c2
-rw-r--r--arch/m68k/mm/sun3mmu.c2
-rw-r--r--arch/m68knommu/Kconfig15
-rw-r--r--arch/m68knommu/Makefile11
-rw-r--r--arch/m68knommu/configs/m5208evb_defconfig610
-rw-r--r--arch/m68knommu/configs/m5249evb_defconfig497
-rw-r--r--arch/m68knommu/configs/m5275evb_defconfig627
-rw-r--r--arch/m68knommu/configs/m5307c3_defconfig580
-rw-r--r--arch/m68knommu/configs/m5407c3_defconfig641
-rw-r--r--arch/m68knommu/kernel/setup.c1
-rw-r--r--arch/m68knommu/kernel/time.c40
-rw-r--r--arch/m68knommu/kernel/traps.c38
-rw-r--r--arch/m68knommu/kernel/vmlinux.lds.S1
-rw-r--r--arch/m68knommu/platform/coldfire/Makefile2
-rw-r--r--arch/m68knommu/platform/coldfire/dma_timer.c84
-rw-r--r--arch/m68knommu/platform/coldfire/head.S3
-rw-r--r--arch/m68knommu/platform/coldfire/pit.c91
-rw-r--r--arch/mips/Kconfig2
-rw-r--r--arch/mips/au1000/common/power.c1
-rw-r--r--arch/mips/kernel/linux32.c1
-rw-r--r--arch/mips/kernel/module.c1
-rw-r--r--arch/mips/kernel/process.c2
-rw-r--r--arch/mips/kernel/rtlx.c4
-rw-r--r--arch/mips/kernel/stacktrace.c1
-rw-r--r--arch/mips/kernel/syscall.c2
-rw-r--r--arch/mips/sgi-ip27/ip27-klnuma.c1
-rw-r--r--arch/mips/sgi-ip27/ip27-memory.c4
-rw-r--r--arch/mips/sibyte/common/sb_tbprof.c3
-rw-r--r--arch/mn10300/boot/compressed/misc.c37
-rw-r--r--arch/mn10300/mm/init.c6
-rw-r--r--arch/parisc/hpux/sys_hpux.c2
-rw-r--r--arch/parisc/mm/init.c5
-rw-r--r--arch/powerpc/Kconfig19
-rw-r--r--arch/powerpc/Kconfig.debug50
-rw-r--r--arch/powerpc/boot/Makefile4
-rw-r--r--arch/powerpc/boot/dts/mpc7448hpc2.dts24
-rw-r--r--arch/powerpc/boot/dts/mpc8313erdb.dts241
-rw-r--r--arch/powerpc/boot/dts/mpc8610_hpcd.dts14
-rw-r--r--arch/powerpc/configs/85xx/mpc8544_ds_defconfig8
-rw-r--r--arch/powerpc/configs/85xx/mpc8572_ds_defconfig8
-rw-r--r--arch/powerpc/configs/mpc85xx_defconfig8
-rw-r--r--arch/powerpc/configs/mpc8610_hpcd_defconfig121
-rw-r--r--arch/powerpc/configs/mpc8641_hpcn_defconfig8
-rw-r--r--arch/powerpc/configs/ppc6xx_defconfig3304
-rw-r--r--arch/powerpc/configs/ps3_defconfig196
-rw-r--r--arch/powerpc/kernel/Makefile1
-rw-r--r--arch/powerpc/kernel/cputable.c31
-rw-r--r--arch/powerpc/kernel/entry_32.S6
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S187
-rw-r--r--arch/powerpc/kernel/idle.c2
-rw-r--r--arch/powerpc/kernel/iommu.c35
-rw-r--r--arch/powerpc/kernel/kgdb.c410
-rw-r--r--arch/powerpc/kernel/kprobes.c6
-rw-r--r--arch/powerpc/kernel/lparcfg.c386
-rw-r--r--arch/powerpc/kernel/pci-common.c1
-rw-r--r--arch/powerpc/kernel/process.c46
-rw-r--r--arch/powerpc/kernel/prom_init.c9
-rw-r--r--arch/powerpc/kernel/prom_parse.c44
-rw-r--r--arch/powerpc/kernel/ptrace.c72
-rw-r--r--arch/powerpc/kernel/setup_32.c16
-rw-r--r--arch/powerpc/kernel/signal.c6
-rw-r--r--arch/powerpc/kernel/stacktrace.c2
-rw-r--r--arch/powerpc/kernel/suspend.c1
-rw-r--r--arch/powerpc/kernel/sysfs.c18
-rw-r--r--arch/powerpc/kernel/traps.c16
-rw-r--r--arch/powerpc/kernel/vio.c1033
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S31
-rw-r--r--arch/powerpc/lib/code-patching.c1
-rw-r--r--arch/powerpc/lib/feature-fixups.c2
-rw-r--r--arch/powerpc/lib/string.S18
-rw-r--r--arch/powerpc/mm/fault.c25
-rw-r--r--arch/powerpc/mm/hash_utils_64.c51
-rw-r--r--arch/powerpc/mm/hugetlbpage.c341
-rw-r--r--arch/powerpc/mm/init_64.c8
-rw-r--r--arch/powerpc/mm/numa.c3
-rw-r--r--arch/powerpc/mm/pgtable_32.c22
-rw-r--r--arch/powerpc/mm/pgtable_64.c16
-rw-r--r--arch/powerpc/mm/tlb_64.c2
-rw-r--r--arch/powerpc/platforms/52xx/Kconfig5
-rw-r--r--arch/powerpc/platforms/82xx/Kconfig1
-rw-r--r--arch/powerpc/platforms/82xx/ep8248e.c4
-rw-r--r--arch/powerpc/platforms/83xx/Kconfig3
-rw-r--r--arch/powerpc/platforms/83xx/Makefile2
-rw-r--r--arch/powerpc/platforms/83xx/mpc831x_rdb.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_mds.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_rdb.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_itx.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_mds.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc836x_mds.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc836x_rdk.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc837x_mds.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc837x_rdb.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc83xx.h5
-rw-r--r--arch/powerpc/platforms/83xx/pci.c91
-rw-r--r--arch/powerpc/platforms/83xx/sbc834x.c1
-rw-r--r--arch/powerpc/platforms/83xx/suspend-asm.S533
-rw-r--r--arch/powerpc/platforms/83xx/suspend.c388
-rw-r--r--arch/powerpc/platforms/83xx/usb.c24
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig3
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ds.c2
-rw-r--r--arch/powerpc/platforms/86xx/Kconfig3
-rw-r--r--arch/powerpc/platforms/86xx/mpc8610_hpcd.c87
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_hpcn.c2
-rw-r--r--arch/powerpc/platforms/Kconfig6
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype5
-rw-r--r--arch/powerpc/platforms/cell/Kconfig25
-rw-r--r--arch/powerpc/platforms/cell/Makefile3
-rw-r--r--arch/powerpc/platforms/cell/cbe_powerbutton.c117
-rw-r--r--arch/powerpc/platforms/cell/cbe_thermal.c45
-rw-r--r--arch/powerpc/platforms/cell/cpufreq_spudemand.c184
-rw-r--r--arch/powerpc/platforms/cell/iommu.c132
-rw-r--r--arch/powerpc/platforms/cell/pervasive.c27
-rw-r--r--arch/powerpc/platforms/cell/pervasive.h9
-rw-r--r--arch/powerpc/platforms/cell/ras.c46
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c3
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c23
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c35
-rw-r--r--arch/powerpc/platforms/cell/spufs/sputrace.c3
-rw-r--r--arch/powerpc/platforms/chrp/pci.c2
-rw-r--r--arch/powerpc/platforms/fsl_uli1575.c117
-rw-r--r--arch/powerpc/platforms/iseries/Kconfig1
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c6
-rw-r--r--arch/powerpc/platforms/iseries/setup.c4
-rw-r--r--arch/powerpc/platforms/pasemi/iommu.c6
-rw-r--r--arch/powerpc/platforms/powermac/setup.c6
-rw-r--r--arch/powerpc/platforms/ps3/Kconfig1
-rw-r--r--arch/powerpc/platforms/ps3/device-init.c1
-rw-r--r--arch/powerpc/platforms/ps3/system-bus.c21
-rw-r--r--arch/powerpc/platforms/pseries/Kconfig24
-rw-r--r--arch/powerpc/platforms/pseries/Makefile1
-rw-r--r--arch/powerpc/platforms/pseries/cmm.c468
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c26
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c52
-rw-r--r--arch/powerpc/platforms/pseries/plpar_wrappers.h10
-rw-r--r--arch/powerpc/platforms/pseries/setup.c71
-rw-r--r--arch/powerpc/sysdev/axonram.c28
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c6
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c61
-rw-r--r--arch/powerpc/sysdev/fsl_pci.h1
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c90
-rw-r--r--arch/powerpc/sysdev/fsl_soc.h1
-rw-r--r--arch/powerpc/sysdev/ipic.c71
-rw-r--r--arch/powerpc/sysdev/qe_lib/Kconfig2
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe.c6
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc.c6
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc_fast.c16
-rw-r--r--arch/s390/Kconfig1
-rw-r--r--arch/s390/kernel/kprobes.c6
-rw-r--r--arch/s390/kernel/process.c2
-rw-r--r--arch/s390/kernel/setup.c4
-rw-r--r--arch/s390/kernel/smp.c36
-rw-r--r--arch/s390/kernel/time.c35
-rw-r--r--arch/s390/kernel/topology.c14
-rw-r--r--arch/s390/mm/hugetlbpage.c8
-rw-r--r--arch/sh/Kconfig1
-rw-r--r--arch/sh/boards/renesas/migor/setup.c3
-rw-r--r--arch/sh/boot/compressed/misc_32.c38
-rw-r--r--arch/sh/boot/compressed/misc_64.c40
-rw-r--r--arch/sh/drivers/dma/dma-sysfs.c15
-rw-r--r--arch/sh/kernel/process_32.c2
-rw-r--r--arch/sh/kernel/stacktrace.c1
-rw-r--r--arch/sh/kernel/sys_sh32.c2
-rw-r--r--arch/sh/mm/hugetlbpage.c8
-rw-r--r--arch/sh/mm/init.c2
-rw-r--r--arch/sh/mm/numa.c5
-rw-r--r--arch/sparc/Kconfig14
-rw-r--r--arch/sparc/Makefile1
-rw-r--r--arch/sparc/kernel/sys_sparc.c2
-rw-r--r--arch/sparc/kernel/systbls.S3
-rw-r--r--arch/sparc/mm/srmmu.c3
-rw-r--r--arch/sparc/mm/sun4c.c3
-rw-r--r--arch/sparc64/kernel/ebus.c4
-rw-r--r--arch/sparc64/kernel/iommu_common.h2
-rw-r--r--arch/sparc64/kernel/irq.c10
-rw-r--r--arch/sparc64/kernel/kprobes.c11
-rw-r--r--arch/sparc64/kernel/ldc.c38
-rw-r--r--arch/sparc64/kernel/of_device.c4
-rw-r--r--arch/sparc64/kernel/pci.c2
-rw-r--r--arch/sparc64/kernel/process.c8
-rw-r--r--arch/sparc64/kernel/sys_sparc.c2
-rw-r--r--arch/sparc64/kernel/sysfs.c16
-rw-r--r--arch/sparc64/kernel/systbls.S6
-rw-r--r--arch/sparc64/kernel/time.c15
-rw-r--r--arch/sparc64/kernel/traps.c3
-rw-r--r--arch/sparc64/kernel/vio.c18
-rw-r--r--arch/sparc64/mm/hugetlbpage.c10
-rw-r--r--arch/sparc64/mm/init.c3
-rw-r--r--arch/um/include/init.h8
-rw-r--r--arch/um/include/irq_kern.h2
-rw-r--r--arch/um/include/irq_user.h2
-rw-r--r--arch/um/include/skas/skas.h1
-rw-r--r--arch/um/include/um_uaccess.h1
-rw-r--r--arch/um/kernel/irq.c35
-rw-r--r--arch/um/kernel/ksyms.c1
-rw-r--r--arch/um/kernel/mem.c33
-rw-r--r--arch/um/kernel/physmem.c2
-rw-r--r--arch/um/kernel/process.c2
-rw-r--r--arch/um/kernel/ptrace.c2
-rw-r--r--arch/um/kernel/time.c8
-rw-r--r--arch/um/kernel/uaccess.c2
-rw-r--r--arch/um/os-Linux/sigio.c2
-rw-r--r--arch/um/os-Linux/signal.c2
-rw-r--r--arch/um/os-Linux/skas/process.c2
-rw-r--r--arch/um/os-Linux/umid.c2
-rw-r--r--arch/um/sys-i386/bugs.c2
-rw-r--r--arch/um/sys-i386/checksum.S5
-rw-r--r--arch/um/sys-i386/ldt.c4
-rw-r--r--arch/v850/Kconfig353
-rw-r--r--arch/v850/Kconfig.debug10
-rw-r--r--arch/v850/Makefile54
-rw-r--r--arch/v850/README44
-rw-r--r--arch/v850/configs/rte-ma1-cb_defconfig617
-rw-r--r--arch/v850/configs/rte-me2-cb_defconfig462
-rw-r--r--arch/v850/configs/sim_defconfig451
-rw-r--r--arch/v850/kernel/Makefile40
-rw-r--r--arch/v850/kernel/anna-rom.ld16
-rw-r--r--arch/v850/kernel/anna.c202
-rw-r--r--arch/v850/kernel/anna.ld20
-rw-r--r--arch/v850/kernel/as85ep1-rom.ld21
-rw-r--r--arch/v850/kernel/as85ep1.c234
-rw-r--r--arch/v850/kernel/as85ep1.ld49
-rw-r--r--arch/v850/kernel/asm-offsets.c58
-rw-r--r--arch/v850/kernel/bug.c142
-rw-r--r--arch/v850/kernel/entry.S1121
-rw-r--r--arch/v850/kernel/fpga85e2c.c167
-rw-r--r--arch/v850/kernel/fpga85e2c.ld62
-rw-r--r--arch/v850/kernel/gbus_int.c271
-rw-r--r--arch/v850/kernel/head.S128
-rw-r--r--arch/v850/kernel/highres_timer.c132
-rw-r--r--arch/v850/kernel/init_task.c48
-rw-r--r--arch/v850/kernel/intv.S87
-rw-r--r--arch/v850/kernel/irq.c123
-rw-r--r--arch/v850/kernel/ma.c69
-rw-r--r--arch/v850/kernel/mach.c17
-rw-r--r--arch/v850/kernel/mach.h56
-rw-r--r--arch/v850/kernel/me2.c73
-rw-r--r--arch/v850/kernel/memcons.c135
-rw-r--r--arch/v850/kernel/module.c237
-rw-r--r--arch/v850/kernel/process.c217
-rw-r--r--arch/v850/kernel/procfs.c67
-rw-r--r--arch/v850/kernel/ptrace.c235
-rw-r--r--arch/v850/kernel/rte_cb.c193
-rw-r--r--arch/v850/kernel/rte_cb_leds.c137
-rw-r--r--arch/v850/kernel/rte_cb_multi.c121
-rw-r--r--arch/v850/kernel/rte_ma1_cb-rom.ld14
-rw-r--r--arch/v850/kernel/rte_ma1_cb.c107
-rw-r--r--arch/v850/kernel/rte_ma1_cb.ld57
-rw-r--r--arch/v850/kernel/rte_mb_a_pci.c819
-rw-r--r--arch/v850/kernel/rte_me2_cb.c298
-rw-r--r--arch/v850/kernel/rte_me2_cb.ld30
-rw-r--r--arch/v850/kernel/rte_nb85e_cb-multi.ld57
-rw-r--r--arch/v850/kernel/rte_nb85e_cb.c81
-rw-r--r--arch/v850/kernel/rte_nb85e_cb.ld22
-rw-r--r--arch/v850/kernel/setup.c330
-rw-r--r--arch/v850/kernel/signal.c523
-rw-r--r--arch/v850/kernel/sim.c172
-rw-r--r--arch/v850/kernel/sim.ld13
-rw-r--r--arch/v850/kernel/sim85e2.c195
-rw-r--r--arch/v850/kernel/sim85e2.ld36
-rw-r--r--arch/v850/kernel/simcons.c161
-rw-r--r--arch/v850/kernel/syscalls.c196
-rw-r--r--arch/v850/kernel/teg.c62
-rw-r--r--arch/v850/kernel/time.c106
-rw-r--r--arch/v850/kernel/v850_ksyms.c51
-rw-r--r--arch/v850/kernel/v850e2_cache.c127
-rw-r--r--arch/v850/kernel/v850e_cache.c174
-rw-r--r--arch/v850/kernel/v850e_intc.c104
-rw-r--r--arch/v850/kernel/v850e_timer_d.c54
-rw-r--r--arch/v850/kernel/v850e_utils.c62
-rw-r--r--arch/v850/kernel/vmlinux.lds.S306
-rw-r--r--arch/v850/lib/Makefile6
-rw-r--r--arch/v850/lib/ashldi3.c62
-rw-r--r--arch/v850/lib/ashrdi3.c63
-rw-r--r--arch/v850/lib/checksum.c155
-rw-r--r--arch/v850/lib/lshrdi3.c62
-rw-r--r--arch/v850/lib/memcpy.c92
-rw-r--r--arch/v850/lib/memset.c68
-rw-r--r--arch/v850/lib/muldi3.c61
-rw-r--r--arch/v850/lib/negdi2.c25
-rw-r--r--arch/x86/Kconfig3
-rw-r--r--arch/x86/Kconfig.cpu2
-rw-r--r--arch/x86/boot/compressed/misc.c39
-rw-r--r--arch/x86/ia32/ia32entry.S97
-rw-r--r--arch/x86/ia32/sys_ia32.c2
-rw-r--r--arch/x86/kernel/acpi/cstate.c3
-rw-r--r--arch/x86/kernel/acpi/sleep.c4
-rw-r--r--arch/x86/kernel/apm_32.c1
-rw-r--r--arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c16
-rw-r--r--arch/x86/kernel/cpu/cpufreq/p4-clockmod.c6
-rw-r--r--arch/x86/kernel/cpu/cpufreq/powernow-k8.c23
-rw-r--r--arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c157
-rw-r--r--arch/x86/kernel/cpu/cpufreq/speedstep-ich.c7
-rw-r--r--arch/x86/kernel/cpu/intel_cacheinfo.c5
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_64.c20
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd_64.c4
-rw-r--r--arch/x86/kernel/cpu/mcheck/therm_throt.c1
-rw-r--r--arch/x86/kernel/cpu/proc.c2
-rw-r--r--arch/x86/kernel/cpuid.c4
-rw-r--r--arch/x86/kernel/entry_32.S55
-rw-r--r--arch/x86/kernel/entry_64.S55
-rw-r--r--arch/x86/kernel/genapic_flat_64.c2
-rw-r--r--arch/x86/kernel/genx2apic_uv_x.c4
-rw-r--r--arch/x86/kernel/hpet.c10
-rw-r--r--arch/x86/kernel/io_apic_64.c12
-rw-r--r--arch/x86/kernel/irqinit_64.c5
-rw-r--r--arch/x86/kernel/kprobes.c6
-rw-r--r--arch/x86/kernel/ldt.c6
-rw-r--r--arch/x86/kernel/microcode.c23
-rw-r--r--arch/x86/kernel/module_64.c1
-rw-r--r--arch/x86/kernel/msr.c4
-rw-r--r--arch/x86/kernel/paravirt.c2
-rw-r--r--arch/x86/kernel/pci-calgary_64.c85
-rw-r--r--arch/x86/kernel/pci-dma.c6
-rw-r--r--arch/x86/kernel/pci-gart_64.c4
-rw-r--r--arch/x86/kernel/process_32.c2
-rw-r--r--arch/x86/kernel/process_64.c2
-rw-r--r--arch/x86/kernel/reboot.c14
-rw-r--r--arch/x86/kernel/setup.c7
-rw-r--r--arch/x86/kernel/signal_32.c3
-rw-r--r--arch/x86/kernel/signal_64.c56
-rw-r--r--arch/x86/kernel/smpboot.c8
-rw-r--r--arch/x86/kernel/syscall_table_32.S6
-rw-r--r--arch/x86/mach-es7000/es7000plat.c8
-rw-r--r--arch/x86/mm/discontig_32.c3
-rw-r--r--arch/x86/mm/dump_pagetables.c10
-rw-r--r--arch/x86/mm/hugetlbpage.c78
-rw-r--r--arch/x86/mm/ioremap.c8
-rw-r--r--arch/x86/mm/numa_64.c4
-rw-r--r--arch/x86/oprofile/nmi_int.c36
-rw-r--r--arch/x86/pci/i386.c1
-rw-r--r--arch/x86/xen/enlighten.c2
-rw-r--r--arch/x86/xen/mmu.c8
-rw-r--r--arch/x86/xen/smp.c4
-rw-r--r--arch/x86/xen/xen-asm_64.S2
-rw-r--r--arch/xtensa/Kconfig4
-rw-r--r--arch/xtensa/kernel/setup.c1
-rw-r--r--arch/xtensa/kernel/syscall.c2
-rw-r--r--block/bsg.c3
-rw-r--r--block/genhd.c205
-rw-r--r--block/ioctl.c5
-rw-r--r--crypto/async_tx/async_memcpy.c12
-rw-r--r--crypto/async_tx/async_memset.c12
-rw-r--r--crypto/async_tx/async_tx.c33
-rw-r--r--crypto/async_tx/async_xor.c262
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/acpi/fan.c10
-rw-r--r--drivers/acpi/glue.c6
-rw-r--r--drivers/acpi/namespace/nsnames.c8
-rw-r--r--drivers/acpi/pci_link.c31
-rw-r--r--drivers/acpi/pci_slot.c5
-rw-r--r--drivers/acpi/processor_core.c5
-rw-r--r--drivers/acpi/processor_throttling.c17
-rw-r--r--drivers/acpi/scan.c2
-rw-r--r--drivers/acpi/sleep/main.c42
-rw-r--r--drivers/acpi/system.c1
-rw-r--r--drivers/acpi/tables/tbfadt.c17
-rw-r--r--drivers/acpi/thermal.c47
-rw-r--r--drivers/acpi/utilities/utalloc.c4
-rw-r--r--drivers/acpi/video.c19
-rw-r--r--drivers/ata/ahci.c2
-rw-r--r--drivers/atm/fore200e.c15
-rw-r--r--drivers/auxdisplay/cfag12864b.c13
-rw-r--r--drivers/base/Kconfig3
-rw-r--r--drivers/base/base.h27
-rw-r--r--drivers/base/class.c153
-rw-r--r--drivers/base/core.c196
-rw-r--r--drivers/base/cpu.c14
-rw-r--r--drivers/base/firmware_class.c12
-rw-r--r--drivers/base/memory.c31
-rw-r--r--drivers/base/node.c15
-rw-r--r--drivers/base/power/trace.c2
-rw-r--r--drivers/base/sys.c64
-rw-r--r--drivers/base/topology.c17
-rw-r--r--drivers/block/aoe/aoechr.c14
-rw-r--r--drivers/block/paride/pg.c5
-rw-r--r--drivers/block/paride/pt.c10
-rw-r--r--drivers/block/pktcdvd.c4
-rw-r--r--drivers/block/virtio_blk.c10
-rw-r--r--drivers/char/Kconfig36
-rw-r--r--drivers/char/Makefile9
-rw-r--r--drivers/char/amiserial.c3
-rw-r--r--drivers/char/cyclades.c8
-rw-r--r--drivers/char/ds1302.c17
-rw-r--r--drivers/char/dsp56k.c23
-rw-r--r--drivers/char/efirtc.c35
-rw-r--r--drivers/char/epca.c58
-rw-r--r--drivers/char/esp.c5
-rw-r--r--drivers/char/hpet.c2
-rw-r--r--drivers/char/hvc_console.c85
-rw-r--r--drivers/char/hvc_console.h35
-rw-r--r--drivers/char/hvc_irq.c44
-rw-r--r--drivers/char/hvc_iseries.c2
-rw-r--r--drivers/char/hvc_vio.c2
-rw-r--r--drivers/char/hvc_xen.c2
-rw-r--r--drivers/char/ip2/ip2main.c25
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c2
-rw-r--r--drivers/char/isicom.c30
-rw-r--r--drivers/char/istallion.c19
-rw-r--r--drivers/char/lcd.c516
-rw-r--r--drivers/char/lcd.h154
-rw-r--r--drivers/char/lp.c3
-rw-r--r--drivers/char/mem.c11
-rw-r--r--drivers/char/misc.c4
-rw-r--r--drivers/char/moxa.c3
-rw-r--r--drivers/char/mspec.c23
-rw-r--r--drivers/char/mwave/mwavedd.c39
-rw-r--r--drivers/char/mwave/mwavedd.h2
-rw-r--r--drivers/char/mwave/tp3780i.c2
-rw-r--r--drivers/char/mxser.c386
-rw-r--r--drivers/char/n_hdlc.c4
-rw-r--r--drivers/char/nvram.c1
-rw-r--r--drivers/char/nwflash.c31
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c2
-rw-r--r--drivers/char/pcmcia/cm4040_cs.c3
-rw-r--r--drivers/char/pcmcia/synclink_cs.c5
-rw-r--r--drivers/char/ppdev.c23
-rw-r--r--drivers/char/random.c1
-rw-r--r--drivers/char/raw.c7
-rw-r--r--drivers/char/rio/rio_linux.c8
-rw-r--r--drivers/char/riscom8.c27
-rw-r--r--drivers/char/rocket.c5
-rw-r--r--drivers/char/rtc.c19
-rw-r--r--drivers/char/snsc.c3
-rw-r--r--drivers/char/specialix.c803
-rw-r--r--drivers/char/stallion.c21
-rw-r--r--drivers/char/sx.c76
-rw-r--r--drivers/char/synclink.c7
-rw-r--r--drivers/char/synclink_gt.c154
-rw-r--r--drivers/char/synclinkmp.c9
-rw-r--r--drivers/char/tty_io.c735
-rw-r--r--drivers/char/tty_ldisc.c714
-rw-r--r--drivers/char/vc_screen.c12
-rw-r--r--drivers/char/viotape.c8
-rw-r--r--drivers/char/virtio_console.c40
-rw-r--r--drivers/char/vme_scc.c5
-rw-r--r--drivers/char/vt.c22
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c6
-rw-r--r--drivers/cpufreq/cpufreq.c14
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c2
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c4
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c79
-rw-r--r--drivers/cpuidle/sysfs.c10
-rw-r--r--drivers/dca/dca-core.c131
-rw-r--r--drivers/dca/dca-sysfs.c9
-rw-r--r--drivers/dma/Kconfig37
-rw-r--r--drivers/dma/Makefile3
-rw-r--r--drivers/dma/dmaengine.c35
-rw-r--r--drivers/dma/dmatest.c444
-rw-r--r--drivers/dma/dw_dmac.c1122
-rw-r--r--drivers/dma/dw_dmac_regs.h225
-rw-r--r--drivers/dma/fsldma.c38
-rw-r--r--drivers/dma/ioat.c15
-rw-r--r--drivers/dma/ioat_dca.c244
-rw-r--r--drivers/dma/ioat_dma.c402
-rw-r--r--drivers/dma/ioatdma.h28
-rw-r--r--drivers/dma/ioatdma_hw.h1
-rw-r--r--drivers/dma/ioatdma_registers.h20
-rw-r--r--drivers/dma/iop-adma.c53
-rw-r--r--drivers/dma/mv_xor.c1375
-rw-r--r--drivers/dma/mv_xor.h183
-rw-r--r--drivers/edac/Kconfig7
-rw-r--r--drivers/edac/Makefile1
-rw-r--r--drivers/edac/cell_edac.c5
-rw-r--r--drivers/edac/e752x_edac.c59
-rw-r--r--drivers/edac/edac_mc_sysfs.c158
-rw-r--r--drivers/edac/edac_pci_sysfs.c30
-rw-r--r--drivers/edac/i5100_edac.c981
-rw-r--r--drivers/edac/mpc85xx_edac.c67
-rw-r--r--drivers/edac/mv64x60_edac.c37
-rw-r--r--drivers/eisa/Makefile2
-rw-r--r--drivers/eisa/eisa-bus.c4
-rw-r--r--drivers/firmware/dcdbas.c16
-rw-r--r--drivers/firmware/dell_rbu.c28
-rw-r--r--drivers/gpio/Kconfig96
-rw-r--r--drivers/gpio/Makefile5
-rw-r--r--drivers/gpio/bt8xxgpio.c348
-rw-r--r--drivers/gpio/gpiolib.c536
-rw-r--r--drivers/gpio/max7301.c339
-rw-r--r--drivers/gpio/max732x.c385
-rw-r--r--drivers/gpio/mcp23s08.c134
-rw-r--r--drivers/gpio/pca953x.c1
-rw-r--r--drivers/gpio/pcf857x.c34
-rw-r--r--drivers/hid/hid-core.c10
-rw-r--r--drivers/hid/hid-input-quirks.c40
-rw-r--r--drivers/hid/hid-input.c3
-rw-r--r--drivers/hid/hidraw.c53
-rw-r--r--drivers/hid/usbhid/hid-quirks.c22
-rw-r--r--drivers/hid/usbhid/hiddev.c14
-rw-r--r--drivers/hid/usbhid/usbkbd.c10
-rw-r--r--drivers/hid/usbhid/usbmouse.c8
-rw-r--r--drivers/hwmon/hwmon.c3
-rw-r--r--drivers/i2c/chips/Kconfig2
-rw-r--r--drivers/i2c/chips/tps65010.c2
-rw-r--r--drivers/i2c/i2c-core.c6
-rw-r--r--drivers/i2c/i2c-dev.c6
-rw-r--r--drivers/ide/Kconfig4
-rw-r--r--drivers/ide/Makefile9
-rw-r--r--drivers/ide/arm/icside.c77
-rw-r--r--drivers/ide/arm/ide_arm.c14
-rw-r--r--drivers/ide/arm/palm_bk3710.c39
-rw-r--r--drivers/ide/arm/rapide.c30
-rw-r--r--drivers/ide/h8300/ide-h8300.c48
-rw-r--r--drivers/ide/ide-atapi.c58
-rw-r--r--drivers/ide/ide-cd.c196
-rw-r--r--drivers/ide/ide-cd.h38
-rw-r--r--drivers/ide/ide-cd_ioctl.c35
-rw-r--r--drivers/ide/ide-disk.c14
-rw-r--r--drivers/ide/ide-dma.c105
-rw-r--r--drivers/ide/ide-floppy.c102
-rw-r--r--drivers/ide/ide-generic.c107
-rw-r--r--drivers/ide/ide-io.c42
-rw-r--r--drivers/ide/ide-iops.c236
-rw-r--r--drivers/ide/ide-lib.c17
-rw-r--r--drivers/ide/ide-pnp.c29
-rw-r--r--drivers/ide/ide-probe.c437
-rw-r--r--drivers/ide/ide-proc.c8
-rw-r--r--drivers/ide/ide-tape.c169
-rw-r--r--drivers/ide/ide-taskfile.c46
-rw-r--r--drivers/ide/ide.c96
-rw-r--r--drivers/ide/legacy/buddha.c24
-rw-r--r--drivers/ide/legacy/falconide.c56
-rw-r--r--drivers/ide/legacy/gayle.c43
-rw-r--r--drivers/ide/legacy/ht6560b.c24
-rw-r--r--drivers/ide/legacy/ide-4drives.c20
-rw-r--r--drivers/ide/legacy/ide-cs.c54
-rw-r--r--drivers/ide/legacy/ide_platform.c32
-rw-r--r--drivers/ide/legacy/macide.c15
-rw-r--r--drivers/ide/legacy/q40ide.c47
-rw-r--r--drivers/ide/mips/au1xxx-ide.c56
-rw-r--r--drivers/ide/mips/swarm.c24
-rw-r--r--drivers/ide/pci/aec62xx.c81
-rw-r--r--drivers/ide/pci/alim15x3.c30
-rw-r--r--drivers/ide/pci/amd74xx.c156
-rw-r--r--drivers/ide/pci/atiixp.c20
-rw-r--r--drivers/ide/pci/cmd640.c29
-rw-r--r--drivers/ide/pci/cmd64x.c62
-rw-r--r--drivers/ide/pci/cs5520.c63
-rw-r--r--drivers/ide/pci/cs5530.c20
-rw-r--r--drivers/ide/pci/cs5535.c16
-rw-r--r--drivers/ide/pci/cy82c693.c35
-rw-r--r--drivers/ide/pci/delkin_cb.c25
-rw-r--r--drivers/ide/pci/generic.c78
-rw-r--r--drivers/ide/pci/hpt34x.c22
-rw-r--r--drivers/ide/pci/hpt366.c206
-rw-r--r--drivers/ide/pci/it8213.c35
-rw-r--r--drivers/ide/pci/it821x.c74
-rw-r--r--drivers/ide/pci/jmicron.c13
-rw-r--r--drivers/ide/pci/ns87415.c126
-rw-r--r--drivers/ide/pci/opti621.c13
-rw-r--r--drivers/ide/pci/pdc202xx_new.c78
-rw-r--r--drivers/ide/pci/pdc202xx_old.c52
-rw-r--r--drivers/ide/pci/piix.c122
-rw-r--r--drivers/ide/pci/rz1000.c13
-rw-r--r--drivers/ide/pci/sc1200.c50
-rw-r--r--drivers/ide/pci/scc_pata.c139
-rw-r--r--drivers/ide/pci/serverworks.c44
-rw-r--r--drivers/ide/pci/sgiioc4.c65
-rw-r--r--drivers/ide/pci/siimage.c167
-rw-r--r--drivers/ide/pci/sis5513.c39
-rw-r--r--drivers/ide/pci/sl82c105.c21
-rw-r--r--drivers/ide/pci/slc90e66.c13
-rw-r--r--drivers/ide/pci/tc86c001.c73
-rw-r--r--drivers/ide/pci/triflex.c13
-rw-r--r--drivers/ide/pci/trm290.c17
-rw-r--r--drivers/ide/pci/via82cxxx.c140
-rw-r--r--drivers/ide/ppc/pmac.c222
-rw-r--r--drivers/ide/setup-pci.c331
-rw-r--r--drivers/ieee1394/dv1394.c7
-rw-r--r--drivers/ieee1394/iso.c1
-rw-r--r--drivers/ieee1394/nodemgr.c23
-rw-r--r--drivers/ieee1394/raw1394.c4
-rw-r--r--drivers/ieee1394/video1394.c6
-rw-r--r--drivers/infiniband/core/cm.c72
-rw-r--r--drivers/infiniband/core/cma.c99
-rw-r--r--drivers/infiniband/core/iwcm.c3
-rw-r--r--drivers/infiniband/core/sa_query.c3
-rw-r--r--drivers/infiniband/hw/ehca/ehca_classes.h1
-rw-r--r--drivers/infiniband/hw/ehca/ehca_hca.c4
-rw-r--r--drivers/infiniband/hw/ehca/ehca_irq.c8
-rw-r--r--drivers/infiniband/hw/ehca/ehca_qp.c2
-rw-r--r--drivers/infiniband/hw/ehca/ipz_pt_fn.c1
-rw-r--r--drivers/infiniband/hw/ipath/ipath_file_ops.c2
-rw-r--r--drivers/infiniband/hw/mlx4/cq.c12
-rw-r--r--drivers/infiniband/hw/mlx4/main.c11
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h15
-rw-r--r--drivers/infiniband/hw/mlx4/mr.c70
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c74
-rw-r--r--drivers/infiniband/hw/mthca/mthca_dev.h1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mr.c26
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c2
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c1
-rw-r--r--drivers/input/keyboard/hil_kbd.c1
-rw-r--r--drivers/input/keyboard/tosakbd.c2
-rw-r--r--drivers/input/misc/hp_sdc_rtc.c1
-rw-r--r--drivers/input/serio/hp_sdc.c2
-rw-r--r--drivers/isdn/capi/capi.c6
-rw-r--r--drivers/isdn/gigaset/asyncdata.c3
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c12
-rw-r--r--drivers/isdn/gigaset/common.c2
-rw-r--r--drivers/isdn/gigaset/gigaset.h3
-rw-r--r--drivers/isdn/gigaset/i4l.c56
-rw-r--r--drivers/isdn/gigaset/interface.c25
-rw-r--r--drivers/isdn/gigaset/usb-gigaset.c7
-rw-r--r--drivers/isdn/hisax/st5481.h4
-rw-r--r--drivers/isdn/hisax/st5481_b.c4
-rw-r--r--drivers/isdn/hisax/st5481_d.c6
-rw-r--r--drivers/isdn/hisax/st5481_usb.c18
-rw-r--r--drivers/leds/Kconfig16
-rw-r--r--drivers/leds/Makefile2
-rw-r--r--drivers/leds/led-triggers.c3
-rw-r--r--drivers/leds/leds-atmel-pwm.c2
-rw-r--r--drivers/leds/leds-h1940.c9
-rw-r--r--drivers/leds/leds-pca9532.c337
-rw-r--r--drivers/leds/leds-pca955x.c384
-rw-r--r--drivers/lguest/lguest_device.c14
-rw-r--r--drivers/macintosh/adb.c3
-rw-r--r--drivers/mca/mca-bus.c2
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c4
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-dvb.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-ioread.c1
-rw-r--r--drivers/media/video/uvc/uvc_queue.c1
-rw-r--r--drivers/media/video/videobuf-core.c1
-rw-r--r--drivers/memstick/host/jmb38x_ms.c4
-rw-r--r--drivers/message/fusion/mptbase.c3
-rw-r--r--drivers/message/fusion/mptbase.h4
-rw-r--r--drivers/message/fusion/mptfc.c4
-rw-r--r--drivers/message/i2o/device.c54
-rw-r--r--drivers/mfd/Kconfig21
-rw-r--r--drivers/mfd/Makefile4
-rw-r--r--drivers/mfd/htc-egpio.c2
-rw-r--r--drivers/mfd/htc-pasic3.c2
-rw-r--r--drivers/mfd/mcp-sa11x0.c2
-rw-r--r--drivers/mfd/mfd-core.c114
-rw-r--r--drivers/mfd/sm501.c439
-rw-r--r--drivers/mfd/tc6393xb.c600
-rw-r--r--drivers/misc/Kconfig32
-rw-r--r--drivers/misc/Makefile2
-rw-r--r--drivers/misc/atmel_pwm.c3
-rw-r--r--drivers/misc/hp-wmi.c494
-rw-r--r--drivers/misc/hpilo.c768
-rw-r--r--drivers/misc/hpilo.h189
-rw-r--r--drivers/misc/phantom.c7
-rw-r--r--drivers/misc/sgi-xp/xpc_main.c3
-rw-r--r--drivers/misc/thinkpad_acpi.c475
-rw-r--r--drivers/mmc/card/mmc_test.c225
-rw-r--r--drivers/mmc/card/queue.c97
-rw-r--r--drivers/mmc/host/au1xmmc.c54
-rw-r--r--drivers/mmc/host/pxamci.c2
-rw-r--r--drivers/mmc/host/s3cmci.c50
-rw-r--r--drivers/mmc/host/sdhci.c167
-rw-r--r--drivers/mmc/host/sdhci.h7
-rw-r--r--drivers/mtd/devices/block2mtd.c8
-rw-r--r--drivers/mtd/maps/uclinux.c1
-rw-r--r--drivers/mtd/mtdchar.c9
-rw-r--r--drivers/mtd/nand/cmx270_nand.c79
-rw-r--r--drivers/mtd/ubi/build.c99
-rw-r--r--drivers/mtd/ubi/cdev.c234
-rw-r--r--drivers/mtd/ubi/debug.c158
-rw-r--r--drivers/mtd/ubi/debug.h74
-rw-r--r--drivers/mtd/ubi/eba.c77
-rw-r--r--drivers/mtd/ubi/gluebi.c16
-rw-r--r--drivers/mtd/ubi/io.c48
-rw-r--r--drivers/mtd/ubi/kapi.c50
-rw-r--r--drivers/mtd/ubi/misc.c2
-rw-r--r--drivers/mtd/ubi/scan.c136
-rw-r--r--drivers/mtd/ubi/scan.h21
-rw-r--r--drivers/mtd/ubi/ubi-media.h38
-rw-r--r--drivers/mtd/ubi/ubi.h75
-rw-r--r--drivers/mtd/ubi/upd.c32
-rw-r--r--drivers/mtd/ubi/vmt.c148
-rw-r--r--drivers/mtd/ubi/vtbl.c127
-rw-r--r--drivers/mtd/ubi/wl.c208
-rw-r--r--drivers/net/3c59x.c2
-rw-r--r--drivers/net/8139too.c138
-rw-r--r--drivers/net/Kconfig25
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/arm/at91_ether.c41
-rw-r--r--drivers/net/arm/at91_ether.h1
-rw-r--r--drivers/net/arm/ep93xx_eth.c2
-rw-r--r--drivers/net/arm/etherh.c6
-rw-r--r--drivers/net/atl1e/Makefile2
-rw-r--r--drivers/net/atl1e/atl1e.h503
-rw-r--r--drivers/net/atl1e/atl1e_ethtool.c405
-rw-r--r--drivers/net/atl1e/atl1e_hw.c664
-rw-r--r--drivers/net/atl1e/atl1e_hw.h793
-rw-r--r--drivers/net/atl1e/atl1e_main.c2599
-rw-r--r--drivers/net/atl1e/atl1e_param.c263
-rw-r--r--drivers/net/au1000_eth.c5
-rw-r--r--drivers/net/bfin_mac.c1
-rw-r--r--drivers/net/bonding/bond_main.c3
-rw-r--r--drivers/net/cpmac.c2
-rw-r--r--drivers/net/dm9000.c15
-rw-r--r--drivers/net/e1000/e1000.h71
-rw-r--r--drivers/net/e1000/e1000_ethtool.c558
-rw-r--r--drivers/net/e1000/e1000_hw.c1373
-rw-r--r--drivers/net/e1000/e1000_main.c1490
-rw-r--r--drivers/net/e1000/e1000_osdep.h14
-rw-r--r--drivers/net/e1000/e1000_param.c16
-rw-r--r--drivers/net/e1000e/netdev.c2
-rw-r--r--drivers/net/fec.c54
-rw-r--r--drivers/net/fec_mpc52xx.c5
-rw-r--r--drivers/net/fs_enet/Makefile5
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c319
-rw-r--r--drivers/net/fs_enet/fs_enet.h4
-rw-r--r--drivers/net/fs_enet/mac-fcc.c67
-rw-r--r--drivers/net/fs_enet/mac-fec.c23
-rw-r--r--drivers/net/fs_enet/mac-scc.c37
-rw-r--r--drivers/net/fs_enet/mii-bitbang.c107
-rw-r--r--drivers/net/fs_enet/mii-fec.c144
-rw-r--r--drivers/net/gianfar.c122
-rw-r--r--drivers/net/gianfar.h12
-rw-r--r--drivers/net/gianfar_ethtool.c41
-rw-r--r--drivers/net/hamradio/bpqether.c2
-rw-r--r--drivers/net/hp-plus.c2
-rw-r--r--drivers/net/hp.c2
-rw-r--r--drivers/net/ibmveth.c189
-rw-r--r--drivers/net/ibmveth.h5
-rw-r--r--drivers/net/igb/igb_main.c2
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c2
-rw-r--r--drivers/net/macb.c4
-rw-r--r--drivers/net/macvlan.c3
-rw-r--r--drivers/net/meth.c2
-rw-r--r--drivers/net/mlx4/cmd.c3
-rw-r--r--drivers/net/mlx4/eq.c1
-rw-r--r--drivers/net/mlx4/fw.c18
-rw-r--r--drivers/net/mlx4/fw.h2
-rw-r--r--drivers/net/mlx4/main.c2
-rw-r--r--drivers/net/mlx4/mlx4.h1
-rw-r--r--drivers/net/mlx4/mr.c49
-rw-r--r--drivers/net/mlx4/pd.c7
-rw-r--r--drivers/net/mv643xx_eth.c2
-rw-r--r--drivers/net/myri10ge/myri10ge.c62
-rw-r--r--drivers/net/ne.c2
-rw-r--r--drivers/net/ne2.c2
-rw-r--r--drivers/net/netxen/Makefile2
-rw-r--r--drivers/net/netxen/netxen_nic.h575
-rw-r--r--drivers/net/netxen/netxen_nic_ctx.c710
-rw-r--r--drivers/net/netxen/netxen_nic_ethtool.c168
-rw-r--r--drivers/net/netxen/netxen_nic_hdr.h251
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c2196
-rw-r--r--drivers/net/netxen/netxen_nic_hw.h60
-rw-r--r--drivers/net/netxen/netxen_nic_init.c806
-rw-r--r--drivers/net/netxen/netxen_nic_isr.c220
-rw-r--r--drivers/net/netxen/netxen_nic_main.c1169
-rw-r--r--drivers/net/netxen/netxen_nic_niu.c114
-rw-r--r--drivers/net/netxen/netxen_nic_phan_reg.h31
-rw-r--r--drivers/net/phy/marvell.c7
-rw-r--r--drivers/net/ppp_generic.c3
-rw-r--r--drivers/net/r6040.c445
-rw-r--r--drivers/net/r8169.c14
-rw-r--r--drivers/net/sfc/efx.c39
-rw-r--r--drivers/net/sfc/falcon.c12
-rw-r--r--drivers/net/sfc/net_driver.h5
-rw-r--r--drivers/net/sh_eth.c5
-rw-r--r--drivers/net/sky2.c5
-rw-r--r--drivers/net/smc91x.c94
-rw-r--r--drivers/net/smc91x.h76
-rw-r--r--drivers/net/tc35815.c1
-rw-r--r--drivers/net/tulip/de4x5.c16
-rw-r--r--drivers/net/tulip/de4x5.h3
-rw-r--r--drivers/net/tun.c2
-rw-r--r--drivers/net/usb/cdc_ether.c11
-rw-r--r--drivers/net/usb/rndis_host.c4
-rw-r--r--drivers/net/virtio_net.c114
-rw-r--r--drivers/net/wan/cosa.c6
-rw-r--r--drivers/net/wireless/hostap/hostap_hw.c3
-rw-r--r--drivers/net/wireless/ipw2200.c33
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c18
-rw-r--r--drivers/of/Kconfig2
-rw-r--r--drivers/of/of_i2c.c2
-rw-r--r--drivers/parport/parport_ax88796.c2
-rw-r--r--drivers/pci/dmar.c4
-rw-r--r--drivers/pci/hotplug/acpiphp.h4
-rw-r--r--drivers/pci/pci.c34
-rw-r--r--drivers/pci/proc.c18
-rw-r--r--drivers/pcmcia/Kconfig3
-rw-r--r--drivers/pcmcia/Makefile1
-rw-r--r--drivers/pcmcia/electra_cf.c1
-rw-r--r--drivers/pcmcia/pxa2xx_cm_x270.c93
-rw-r--r--drivers/pcmcia/pxa2xx_palmtx.c118
-rw-r--r--drivers/power/Kconfig6
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/apm_power.c2
-rw-r--r--drivers/power/ds2760_battery.c2
-rw-r--r--drivers/power/palmtx_battery.c198
-rw-r--r--drivers/power/pda_power.c2
-rw-r--r--drivers/power/power_supply_core.c4
-rw-r--r--drivers/rtc/Kconfig19
-rw-r--r--drivers/rtc/Makefile2
-rw-r--r--drivers/rtc/interface.c2
-rw-r--r--drivers/rtc/rtc-at91rm9200.c16
-rw-r--r--drivers/rtc/rtc-cmos.c294
-rw-r--r--drivers/rtc/rtc-dev.c58
-rw-r--r--drivers/rtc/rtc-ds1305.c847
-rw-r--r--drivers/rtc/rtc-m41t80.c20
-rw-r--r--drivers/rtc/rtc-m41t94.c173
-rw-r--r--drivers/rtc/rtc-omap.c21
-rw-r--r--drivers/rtc/rtc-pcf8583.c129
-rw-r--r--drivers/rtc/rtc-s3c.c89
-rw-r--r--drivers/rtc/rtc-vr41xx.c65
-rw-r--r--drivers/s390/char/raw3270.c14
-rw-r--r--drivers/s390/char/tape_class.c7
-rw-r--r--drivers/s390/char/vmur.c5
-rw-r--r--drivers/s390/kvm/kvm_virtio.c34
-rw-r--r--drivers/s390/net/claw.c2141
-rw-r--r--drivers/s390/net/ctcm_dbug.c29
-rw-r--r--drivers/s390/net/ctcm_dbug.h39
-rw-r--r--drivers/s390/net/ctcm_fsms.c402
-rw-r--r--drivers/s390/net/ctcm_main.c514
-rw-r--r--drivers/s390/net/ctcm_main.h31
-rw-r--r--drivers/s390/net/ctcm_mpc.c1110
-rw-r--r--drivers/s390/net/ctcm_mpc.h2
-rw-r--r--drivers/s390/net/qeth_l3_main.c2
-rw-r--r--drivers/sbus/sbus.c6
-rw-r--r--drivers/scsi/dpt_i2o.c4
-rw-r--r--drivers/scsi/hosts.c7
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c15
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c45
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.h2
-rw-r--r--drivers/scsi/ide-scsi.c65
-rw-r--r--drivers/scsi/scsi_transport_fc.c9
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c8
-rw-r--r--drivers/scsi/sun_esp.c1
-rw-r--r--drivers/serial/8250.c25
-rw-r--r--drivers/serial/8250_gsc.c2
-rw-r--r--drivers/serial/8250_pci.c17
-rw-r--r--drivers/serial/Kconfig16
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c118
-rw-r--r--drivers/serial/dz.c24
-rw-r--r--drivers/serial/icom.c2
-rw-r--r--drivers/serial/mpsc.c148
-rw-r--r--drivers/serial/samsung.c2
-rw-r--r--drivers/serial/serial_core.c3
-rw-r--r--drivers/serial/serial_txx9.c2
-rw-r--r--drivers/serial/zs.c21
-rw-r--r--drivers/spi/Kconfig45
-rw-r--r--drivers/spi/au1550_spi.c207
-rw-r--r--drivers/spi/spi.c6
-rw-r--r--drivers/spi/spi_mpc83xx.c29
-rw-r--r--drivers/spi/spidev.c23
-rw-r--r--drivers/spi/xilinx_spi.c5
-rw-r--r--drivers/telephony/ixj.c17
-rw-r--r--drivers/uio/Kconfig10
-rw-r--r--drivers/uio/Makefile1
-rw-r--r--drivers/uio/uio.c26
-rw-r--r--drivers/uio/uio_pdrv.c118
-rw-r--r--drivers/usb/class/cdc-acm.c9
-rw-r--r--drivers/usb/core/devio.c11
-rw-r--r--drivers/usb/core/file.c5
-rw-r--r--drivers/usb/gadget/at91_udc.h2
-rw-r--r--drivers/usb/gadget/cdc2.c2
-rw-r--r--drivers/usb/gadget/ether.c2
-rw-r--r--drivers/usb/gadget/file_storage.c14
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.c2
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.h2
-rw-r--r--drivers/usb/gadget/gmidi.c2
-rw-r--r--drivers/usb/gadget/goku_udc.c2
-rw-r--r--drivers/usb/gadget/goku_udc.h2
-rw-r--r--drivers/usb/gadget/inode.c2
-rw-r--r--drivers/usb/gadget/net2280.c2
-rw-r--r--drivers/usb/gadget/net2280.h2
-rw-r--r--drivers/usb/gadget/omap_udc.c6
-rw-r--r--drivers/usb/gadget/omap_udc.h2
-rw-r--r--drivers/usb/gadget/printer.c6
-rw-r--r--drivers/usb/gadget/pxa25x_udc.c12
-rw-r--r--drivers/usb/gadget/pxa25x_udc.h2
-rw-r--r--drivers/usb/gadget/u_ether.c3
-rw-r--r--drivers/usb/host/isp116x-hcd.c2
-rw-r--r--drivers/usb/host/isp116x.h2
-rw-r--r--drivers/usb/host/sl811-hcd.c2
-rw-r--r--drivers/usb/host/sl811.h2
-rw-r--r--drivers/usb/misc/usbtest.c4
-rw-r--r--drivers/usb/mon/mon_bin.c5
-rw-r--r--drivers/usb/serial/aircable.c19
-rw-r--r--drivers/usb/serial/ark3116.c32
-rw-r--r--drivers/usb/serial/belkin_sa.c201
-rw-r--r--drivers/usb/serial/belkin_sa.h15
-rw-r--r--drivers/usb/serial/bus.c20
-rw-r--r--drivers/usb/serial/ch341.c10
-rw-r--r--drivers/usb/serial/console.c136
-rw-r--r--drivers/usb/serial/cp2101.c379
-rw-r--r--drivers/usb/serial/cyberjack.c176
-rw-r--r--drivers/usb/serial/cypress_m8.c703
-rw-r--r--drivers/usb/serial/cypress_m8.h2
-rw-r--r--drivers/usb/serial/digi_acceleport.c457
-rw-r--r--drivers/usb/serial/empeg.c257
-rw-r--r--drivers/usb/serial/ezusb.c22
-rw-r--r--drivers/usb/serial/ftdi_sio.c1247
-rw-r--r--drivers/usb/serial/ftdi_sio.h126
-rw-r--r--drivers/usb/serial/funsoft.c2
-rw-r--r--drivers/usb/serial/garmin_gps.c400
-rw-r--r--drivers/usb/serial/generic.c122
-rw-r--r--drivers/usb/serial/hp4x.c3
-rw-r--r--drivers/usb/serial/io_edgeport.c1964
-rw-r--r--drivers/usb/serial/io_tables.h6
-rw-r--r--drivers/usb/serial/io_ti.c109
-rw-r--r--drivers/usb/serial/ipaq.c143
-rw-r--r--drivers/usb/serial/ipw.c294
-rw-r--r--drivers/usb/serial/ir-usb.c81
-rw-r--r--drivers/usb/serial/iuu_phoenix.c58
-rw-r--r--drivers/usb/serial/keyspan.c955
-rw-r--r--drivers/usb/serial/keyspan.h39
-rw-r--r--drivers/usb/serial/keyspan_pda.c231
-rw-r--r--drivers/usb/serial/kl5kusb105.c415
-rw-r--r--drivers/usb/serial/kobil_sct.c617
-rw-r--r--drivers/usb/serial/mct_u232.c364
-rw-r--r--drivers/usb/serial/mos7720.c308
-rw-r--r--drivers/usb/serial/mos7840.c557
-rw-r--r--drivers/usb/serial/navman.c10
-rw-r--r--drivers/usb/serial/omninet.c171
-rw-r--r--drivers/usb/serial/option.c166
-rw-r--r--drivers/usb/serial/oti6858.c255
-rw-r--r--drivers/usb/serial/pl2303.c140
-rw-r--r--drivers/usb/serial/safe_serial.c298
-rw-r--r--drivers/usb/serial/sierra.c95
-rw-r--r--drivers/usb/serial/spcp8x5.c73
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c449
-rw-r--r--drivers/usb/serial/usb-serial.c387
-rw-r--r--drivers/usb/serial/usb_debug.c5
-rw-r--r--drivers/usb/serial/visor.c384
-rw-r--r--drivers/usb/serial/whiteheat.c441
-rw-r--r--drivers/usb/serial/whiteheat.h78
-rw-r--r--drivers/video/Kconfig53
-rw-r--r--drivers/video/Makefile5
-rw-r--r--drivers/video/acornfb.c1
-rw-r--r--drivers/video/amifb.c24
-rw-r--r--drivers/video/atafb.c7
-rw-r--r--drivers/video/atmel_lcdfb.c92
-rw-r--r--drivers/video/aty/aty128fb.c8
-rw-r--r--drivers/video/aty/atyfb_base.c100
-rw-r--r--drivers/video/aty/radeon_base.c20
-rw-r--r--drivers/video/aty/radeonfb.h2
-rw-r--r--drivers/video/backlight/Kconfig45
-rw-r--r--drivers/video/backlight/Makefile8
-rw-r--r--drivers/video/backlight/atmel-pwm-bl.c244
-rw-r--r--drivers/video/backlight/backlight.c1
-rw-r--r--drivers/video/backlight/ili9320.c330
-rw-r--r--drivers/video/backlight/ili9320.h80
-rw-r--r--drivers/video/backlight/lcd.c2
-rw-r--r--drivers/video/backlight/mbp_nvidia_bl.c116
-rw-r--r--drivers/video/backlight/platform_lcd.c172
-rw-r--r--drivers/video/backlight/vgg2432a4.c284
-rw-r--r--drivers/video/bf54x-lq043fb.c2
-rw-r--r--drivers/video/bfin-t350mcqb-fb.c2
-rw-r--r--drivers/video/carminefb.c790
-rw-r--r--drivers/video/carminefb.h64
-rw-r--r--drivers/video/carminefb_regs.h159
-rw-r--r--drivers/video/cobalt_lcdfb.c371
-rw-r--r--drivers/video/console/fbcon.c8
-rw-r--r--drivers/video/console/fbcon.h8
-rw-r--r--drivers/video/console/mdacon.c4
-rw-r--r--drivers/video/fbmem.c15
-rw-r--r--drivers/video/fbmon.c2
-rw-r--r--drivers/video/fsl-diu-fb.c60
-rw-r--r--drivers/video/geode/lxfb.h2
-rw-r--r--drivers/video/geode/lxfb_ops.c28
-rw-r--r--drivers/video/hgafb.c36
-rw-r--r--drivers/video/imxfb.c1
-rw-r--r--drivers/video/neofb.c215
-rw-r--r--drivers/video/offb.c192
-rw-r--r--drivers/video/omap/dispc.c1
-rw-r--r--drivers/video/omap/omapfb_main.c1
-rw-r--r--drivers/video/ps3fb.c1
-rw-r--r--drivers/video/pxafb.c72
-rw-r--r--drivers/video/pxafb.h2
-rw-r--r--drivers/video/sa1100fb.c8
-rw-r--r--drivers/video/sa1100fb.h2
-rw-r--r--drivers/video/sh7760fb.c658
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c725
-rw-r--r--drivers/video/sis/init.h1
-rw-r--r--drivers/video/sis/init301.h1
-rw-r--r--drivers/video/sis/initextlfb.c1
-rw-r--r--drivers/video/sis/osdef.h1
-rw-r--r--drivers/video/sis/sis.h22
-rw-r--r--drivers/video/sis/sis_accel.c1
-rw-r--r--drivers/video/sis/sis_main.c44
-rw-r--r--drivers/video/sis/sis_main.h4
-rw-r--r--drivers/video/sis/vgatypes.h4
-rw-r--r--drivers/video/skeletonfb.c37
-rw-r--r--drivers/video/sm501fb.c329
-rw-r--r--drivers/video/tdfxfb.c8
-rw-r--r--drivers/video/tridentfb.c1350
-rw-r--r--drivers/video/uvesafb.c4
-rw-r--r--drivers/video/vfb.c14
-rw-r--r--drivers/video/vga16fb.c122
-rw-r--r--drivers/virtio/virtio.c26
-rw-r--r--drivers/virtio/virtio_pci.c13
-rw-r--r--drivers/virtio/virtio_ring.c23
-rw-r--r--drivers/watchdog/Kconfig2
-rw-r--r--drivers/watchdog/Makefile2
-rw-r--r--drivers/xen/balloon.c1
-rw-r--r--drivers/zorro/zorro-sysfs.c1
-rw-r--r--fs/Kconfig74
-rw-r--r--fs/aio.c2
-rw-r--r--fs/anon_inodes.c11
-rw-r--r--fs/autofs4/autofs_i.h28
-rw-r--r--fs/autofs4/expire.c91
-rw-r--r--fs/autofs4/inode.c33
-rw-r--r--fs/autofs4/root.c589
-rw-r--r--fs/autofs4/waitq.c267
-rw-r--r--fs/binfmt_elf.c100
-rw-r--r--fs/binfmt_elf_fdpic.c26
-rw-r--r--fs/binfmt_misc.c20
-rw-r--r--fs/coda/coda_linux.c6
-rw-r--r--fs/coda/psdev.c9
-rw-r--r--fs/coda/upcall.c15
-rw-r--r--fs/compat.c22
-rw-r--r--fs/compat_ioctl.c3
-rw-r--r--fs/dcache.c335
-rw-r--r--fs/debugfs/inode.c114
-rw-r--r--fs/dlm/plock.c2
-rw-r--r--fs/dquot.c129
-rw-r--r--fs/ecryptfs/Makefile2
-rw-r--r--fs/ecryptfs/crypto.c37
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h23
-rw-r--r--fs/ecryptfs/file.c17
-rw-r--r--fs/ecryptfs/inode.c31
-rw-r--r--fs/ecryptfs/keystore.c9
-rw-r--r--fs/ecryptfs/kthread.c203
-rw-r--r--fs/ecryptfs/main.c79
-rw-r--r--fs/ecryptfs/miscdev.c59
-rw-r--r--fs/ecryptfs/mmap.c11
-rw-r--r--fs/eventfd.c17
-rw-r--r--fs/eventpoll.c30
-rw-r--r--fs/exec.c143
-rw-r--r--fs/ext2/super.c1
-rw-r--r--fs/ext2/xattr_security.c2
-rw-r--r--fs/ext2/xattr_trusted.c4
-rw-r--r--fs/ext2/xattr_user.c4
-rw-r--r--fs/ext3/dir.c14
-rw-r--r--fs/ext3/ialloc.c9
-rw-r--r--fs/ext3/inode.c46
-rw-r--r--fs/ext3/namei.c26
-rw-r--r--fs/ext3/super.c78
-rw-r--r--fs/ext3/xattr_security.c2
-rw-r--r--fs/ext3/xattr_trusted.c4
-rw-r--r--fs/ext3/xattr_user.c4
-rw-r--r--fs/fat/dir.c229
-rw-r--r--fs/fat/inode.c34
-rw-r--r--fs/fat/misc.c10
-rw-r--r--fs/fcntl.c15
-rw-r--r--fs/fuse/dir.c139
-rw-r--r--fs/fuse/file.c11
-rw-r--r--fs/fuse/fuse_i.h10
-rw-r--r--fs/fuse/inode.c177
-rw-r--r--fs/hfs/bitmap.c8
-rw-r--r--fs/hfs/btree.c2
-rw-r--r--fs/hfs/extent.c14
-rw-r--r--fs/hfs/hfs_fs.h5
-rw-r--r--fs/hfs/inode.c4
-rw-r--r--fs/hfs/super.c2
-rw-r--r--fs/hfsplus/extents.c14
-rw-r--r--fs/hfsplus/hfsplus_fs.h3
-rw-r--r--fs/hfsplus/inode.c4
-rw-r--r--fs/hfsplus/super.c2
-rw-r--r--fs/hugetlbfs/inode.c101
-rw-r--r--fs/inotify_user.c18
-rw-r--r--fs/isofs/rock.c22
-rw-r--r--fs/jbd/commit.c64
-rw-r--r--fs/jbd/journal.c8
-rw-r--r--fs/jbd/revoke.c163
-rw-r--r--fs/jbd/transaction.c57
-rw-r--r--fs/jfs/super.c1
-rw-r--r--fs/lockd/clntproc.c10
-rw-r--r--fs/lockd/svclock.c13
-rw-r--r--fs/locks.c90
-rw-r--r--fs/minix/inode.c3
-rw-r--r--fs/minix/minix.h6
-rw-r--r--fs/minix/namei.c24
-rw-r--r--fs/msdos/namei.c21
-rw-r--r--fs/nfs/nfsroot.c2
-rw-r--r--fs/nfsd/lockd.c13
-rw-r--r--fs/open.c3
-rw-r--r--fs/partitions/check.c40
-rw-r--r--fs/partitions/efi.c42
-rw-r--r--fs/partitions/ldm.c70
-rw-r--r--fs/partitions/ldm.h5
-rw-r--r--fs/pipe.c35
-rw-r--r--fs/proc/Kconfig59
-rw-r--r--fs/proc/base.c86
-rw-r--r--fs/proc/generic.c14
-rw-r--r--fs/proc/inode.c81
-rw-r--r--fs/proc/internal.h8
-rw-r--r--fs/proc/kcore.c10
-rw-r--r--fs/proc/kmsg.c2
-rw-r--r--fs/proc/proc_misc.c19
-rw-r--r--fs/proc/proc_net.c11
-rw-r--r--fs/proc/task_mmu.c2
-rw-r--r--fs/quota.c18
-rw-r--r--fs/quota_v1.c1
-rw-r--r--fs/quota_v2.c1
-rw-r--r--fs/reiserfs/journal.c42
-rw-r--r--fs/reiserfs/super.c124
-rw-r--r--fs/reiserfs/xattr_security.c2
-rw-r--r--fs/reiserfs/xattr_trusted.c2
-rw-r--r--fs/reiserfs/xattr_user.c2
-rw-r--r--fs/signalfd.c19
-rw-r--r--fs/smbfs/cache.c1
-rw-r--r--fs/smbfs/proc.c1
-rw-r--r--fs/super.c1
-rw-r--r--fs/sync.c3
-rw-r--r--fs/sysfs/dir.c37
-rw-r--r--fs/sysfs/file.c5
-rw-r--r--fs/sysfs/symlink.c41
-rw-r--r--fs/sysfs/sysfs.h1
-rw-r--r--fs/timerfd.c9
-rw-r--r--fs/ufs/super.c3
-rw-r--r--fs/vfat/namei.c2
-rw-r--r--include/asm-alpha/ide.h44
-rw-r--r--include/asm-alpha/kvm.h6
-rw-r--r--include/asm-alpha/page.h3
-rw-r--r--include/asm-alpha/semaphore.h1
-rw-r--r--include/asm-alpha/socket.h5
-rw-r--r--include/asm-alpha/thread_info.h4
-rw-r--r--include/asm-arm/arch-iop13xx/adma.h18
-rw-r--r--include/asm-arm/arch-pxa/cm-x270.h50
-rw-r--r--include/asm-arm/arch-pxa/eseries-gpio.h50
-rw-r--r--include/asm-arm/arch-pxa/eseries-irq.h27
-rw-r--r--include/asm-arm/arch-pxa/hardware.h33
-rw-r--r--include/asm-arm/arch-pxa/irqs.h3
-rw-r--r--include/asm-arm/arch-pxa/mfp-pxa2xx.h1
-rw-r--r--include/asm-arm/arch-pxa/mfp-pxa930.h491
-rw-r--r--include/asm-arm/arch-pxa/mfp.h8
-rw-r--r--include/asm-arm/arch-pxa/palmtx.h106
-rw-r--r--include/asm-arm/arch-pxa/pxa27x-udc.h2
-rw-r--r--include/asm-arm/arch-pxa/pxa2xx_spi.h2
-rw-r--r--include/asm-arm/arch-pxa/pxa3xx_nand.h2
-rw-r--r--include/asm-arm/arch-pxa/pxafb.h3
-rw-r--r--include/asm-arm/arch-pxa/regs-lcd.h6
-rw-r--r--include/asm-arm/arch-pxa/regs-ssp.h16
-rw-r--r--include/asm-arm/arch-pxa/system.h17
-rw-r--r--include/asm-arm/arch-pxa/tosa.h50
-rw-r--r--include/asm-arm/arch-pxa/tosa_bt.h22
-rw-r--r--include/asm-arm/arch-pxa/uncompress.h13
-rw-r--r--include/asm-arm/arch-pxa/zylonite.h2
-rw-r--r--include/asm-arm/arch-sa1100/h3600.h5
-rw-r--r--include/asm-arm/hardware/iop3xx-adma.h4
-rw-r--r--include/asm-arm/ide.h4
-rw-r--r--include/asm-arm/kgdb.h104
-rw-r--r--include/asm-arm/kvm.h6
-rw-r--r--include/asm-arm/mach/udc_pxa2xx.h1
-rw-r--r--include/asm-arm/page-nommu.h4
-rw-r--r--include/asm-arm/page.h3
-rw-r--r--include/asm-arm/plat-orion/mv_xor.h28
-rw-r--r--include/asm-arm/ptrace.h6
-rw-r--r--include/asm-arm/semaphore.h1
-rw-r--r--include/asm-arm/thread_info.h13
-rw-r--r--include/asm-arm/traps.h2
-rw-r--r--include/asm-avr32/arch-at32ap/at32ap700x.h16
-rw-r--r--include/asm-avr32/kvm.h6
-rw-r--r--include/asm-avr32/page.h3
-rw-r--r--include/asm-avr32/semaphore.h1
-rw-r--r--include/asm-avr32/thread_info.h4
-rw-r--r--include/asm-blackfin/ide.h27
-rw-r--r--include/asm-blackfin/kvm.h6
-rw-r--r--include/asm-blackfin/page.h3
-rw-r--r--include/asm-blackfin/ptrace.h6
-rw-r--r--include/asm-blackfin/semaphore.h1
-rw-r--r--include/asm-blackfin/thread_info.h5
-rw-r--r--include/asm-cris/arch-v10/Kbuild1
-rw-r--r--include/asm-cris/arch-v10/ide.h91
-rw-r--r--include/asm-cris/arch-v10/ptrace.h4
-rw-r--r--include/asm-cris/arch-v32/Kbuild1
-rw-r--r--include/asm-cris/arch-v32/ide.h56
-rw-r--r--include/asm-cris/arch-v32/ptrace.h4
-rw-r--r--include/asm-cris/cacheflush.h1
-rw-r--r--include/asm-cris/ide.h1
-rw-r--r--include/asm-cris/kvm.h6
-rw-r--r--include/asm-cris/page.h3
-rw-r--r--include/asm-cris/ptrace.h4
-rw-r--r--include/asm-cris/semaphore.h1
-rw-r--r--include/asm-cris/thread_info.h2
-rw-r--r--include/asm-frv/Kbuild1
-rw-r--r--include/asm-frv/ide.h4
-rw-r--r--include/asm-frv/kvm.h6
-rw-r--r--include/asm-frv/page.h3
-rw-r--r--include/asm-frv/semaphore.h1
-rw-r--r--include/asm-frv/thread_info.h2
-rw-r--r--include/asm-generic/Kbuild.asm2
-rw-r--r--include/asm-generic/bug.h25
-rw-r--r--include/asm-generic/gpio.h35
-rw-r--r--include/asm-generic/int-ll64.h2
-rw-r--r--include/asm-h8300/elf.h4
-rw-r--r--include/asm-h8300/ide.h26
-rw-r--r--include/asm-h8300/keyboard.h24
-rw-r--r--include/asm-h8300/kvm.h6
-rw-r--r--include/asm-h8300/page.h3
-rw-r--r--include/asm-h8300/semaphore.h1
-rw-r--r--include/asm-h8300/thread_info.h5
-rw-r--r--include/asm-ia64/hugetlb.h5
-rw-r--r--include/asm-ia64/ide.h51
-rw-r--r--include/asm-ia64/page.h1
-rw-r--r--include/asm-ia64/semaphore.h1
-rw-r--r--include/asm-ia64/thread_info.h2
-rw-r--r--include/asm-ia64/unistd.h8
-rw-r--r--include/asm-m32r/ide.h70
-rw-r--r--include/asm-m32r/kvm.h6
-rw-r--r--include/asm-m32r/page.h3
-rw-r--r--include/asm-m32r/semaphore.h1
-rw-r--r--include/asm-m32r/thread_info.h2
-rw-r--r--include/asm-m68k/dvma.h2
-rw-r--r--include/asm-m68k/ide.h4
-rw-r--r--include/asm-m68k/kvm.h6
-rw-r--r--include/asm-m68k/page.h3
-rw-r--r--include/asm-m68k/semaphore.h1
-rw-r--r--include/asm-m68k/thread_info.h8
-rw-r--r--include/asm-m68knommu/bitops.h30
-rw-r--r--include/asm-m68knommu/byteorder.h16
-rw-r--r--include/asm-m68knommu/commproc.h19
-rw-r--r--include/asm-m68knommu/kvm.h6
-rw-r--r--include/asm-m68knommu/page.h3
-rw-r--r--include/asm-m68knommu/ptrace.h2
-rw-r--r--include/asm-m68knommu/semaphore.h1
-rw-r--r--include/asm-m68knommu/system.h11
-rw-r--r--include/asm-m68knommu/thread_info.h4
-rw-r--r--include/asm-mips/kvm.h6
-rw-r--r--include/asm-mips/mach-au1x00/au1550_spi.h1
-rw-r--r--include/asm-mips/mach-generic/gpio.h2
-rw-r--r--include/asm-mips/mach-generic/ide.h48
-rw-r--r--include/asm-mips/page.h3
-rw-r--r--include/asm-mips/processor.h2
-rw-r--r--include/asm-mips/semaphore.h1
-rw-r--r--include/asm-mips/socket.h7
-rw-r--r--include/asm-mips/thread_info.h2
-rw-r--r--include/asm-mn10300/ide.h4
-rw-r--r--include/asm-mn10300/kvm.h6
-rw-r--r--include/asm-mn10300/page.h3
-rw-r--r--include/asm-mn10300/pci.h9
-rw-r--r--include/asm-mn10300/ptrace.h8
-rw-r--r--include/asm-mn10300/scatterlist.h9
-rw-r--r--include/asm-mn10300/semaphore.h1
-rw-r--r--include/asm-mn10300/thread_info.h2
-rw-r--r--include/asm-parisc/ide.h4
-rw-r--r--include/asm-parisc/kvm.h6
-rw-r--r--include/asm-parisc/page.h4
-rw-r--r--include/asm-parisc/ptrace.h4
-rw-r--r--include/asm-parisc/semaphore.h1
-rw-r--r--include/asm-parisc/socket.h5
-rw-r--r--include/asm-parisc/thread_info.h10
-rw-r--r--include/asm-powerpc/Kbuild1
-rw-r--r--include/asm-powerpc/asm-compat.h2
-rw-r--r--include/asm-powerpc/cputable.h2
-rw-r--r--include/asm-powerpc/elf.h8
-rw-r--r--include/asm-powerpc/firmware.h3
-rw-r--r--include/asm-powerpc/gpio.h4
-rw-r--r--include/asm-powerpc/hugetlb.h10
-rw-r--r--include/asm-powerpc/hvcall.h23
-rw-r--r--include/asm-powerpc/ide.h26
-rw-r--r--include/asm-powerpc/io.h5
-rw-r--r--include/asm-powerpc/kgdb.h92
-rw-r--r--include/asm-powerpc/lppaca.h5
-rw-r--r--include/asm-powerpc/machdep.h5
-rw-r--r--include/asm-powerpc/mmu-hash64.h6
-rw-r--r--include/asm-powerpc/mpc52xx_psc.h40
-rw-r--r--include/asm-powerpc/page.h3
-rw-r--r--include/asm-powerpc/page_64.h1
-rw-r--r--include/asm-powerpc/pgalloc-64.h4
-rw-r--r--include/asm-powerpc/pgtable-4k.h3
-rw-r--r--include/asm-powerpc/pgtable-64k.h2
-rw-r--r--include/asm-powerpc/pgtable-ppc32.h31
-rw-r--r--include/asm-powerpc/pgtable-ppc64.h8
-rw-r--r--include/asm-powerpc/pgtable.h13
-rw-r--r--include/asm-powerpc/pmi.h1
-rw-r--r--include/asm-powerpc/ps3.h7
-rw-r--r--include/asm-powerpc/reg.h4
-rw-r--r--include/asm-powerpc/semaphore.h1
-rw-r--r--include/asm-powerpc/syscalls.h1
-rw-r--r--include/asm-powerpc/systbl.h6
-rw-r--r--include/asm-powerpc/system.h2
-rw-r--r--include/asm-powerpc/thread_info.h14
-rw-r--r--include/asm-powerpc/tlbflush.h11
-rw-r--r--include/asm-powerpc/uaccess.h21
-rw-r--r--include/asm-powerpc/ucc_fast.h8
-rw-r--r--include/asm-powerpc/unistd.h8
-rw-r--r--include/asm-powerpc/vio.h27
-rw-r--r--include/asm-s390/Kbuild1
-rw-r--r--include/asm-s390/hugetlb.h3
-rw-r--r--include/asm-s390/kvm_virtio.h10
-rw-r--r--include/asm-s390/page.h3
-rw-r--r--include/asm-s390/semaphore.h1
-rw-r--r--include/asm-s390/thread_info.h5
-rw-r--r--include/asm-sh/hugetlb.h5
-rw-r--r--include/asm-sh/ide.h21
-rw-r--r--include/asm-sh/kvm.h6
-rw-r--r--include/asm-sh/page.h3
-rw-r--r--include/asm-sh/ptrace.h2
-rw-r--r--include/asm-sh/semaphore.h1
-rw-r--r--include/asm-sh/sh7760fb.h197
-rw-r--r--include/asm-sh/sh_mobile_lcdc.h66
-rw-r--r--include/asm-sh/thread_info.h2
-rw-r--r--include/asm-sparc/hugetlb.h5
-rw-r--r--include/asm-sparc/ide.h99
-rw-r--r--include/asm-sparc/ide_32.h95
-rw-r--r--include/asm-sparc/ide_64.h118
-rw-r--r--include/asm-sparc/io_32.h1
-rw-r--r--include/asm-sparc/io_64.h2
-rw-r--r--include/asm-sparc/kvm.h6
-rw-r--r--include/asm-sparc/page_32.h3
-rw-r--r--include/asm-sparc/page_64.h3
-rw-r--r--include/asm-sparc/semaphore.h1
-rw-r--r--include/asm-sparc/thread_info_32.h2
-rw-r--r--include/asm-sparc/thread_info_64.h2
-rw-r--r--include/asm-sparc/unistd_32.h8
-rw-r--r--include/asm-sparc/unistd_64.h8
-rw-r--r--include/asm-sparc64/kvm.h1
-rw-r--r--include/asm-sparc64/semaphore.h1
-rw-r--r--include/asm-um/kvm.h6
-rw-r--r--include/asm-um/page.h6
-rw-r--r--include/asm-um/ptrace-generic.h3
-rw-r--r--include/asm-um/semaphore.h1
-rw-r--r--include/asm-um/thread_info.h16
-rw-r--r--include/asm-v850/Kbuild1
-rw-r--r--include/asm-v850/a.out.h21
-rw-r--r--include/asm-v850/anna.h137
-rw-r--r--include/asm-v850/as85ep1.h152
-rw-r--r--include/asm-v850/asm.h32
-rw-r--r--include/asm-v850/atomic.h131
-rw-r--r--include/asm-v850/auxvec.h4
-rw-r--r--include/asm-v850/bitops.h161
-rw-r--r--include/asm-v850/bug.h25
-rw-r--r--include/asm-v850/bugs.h16
-rw-r--r--include/asm-v850/byteorder.h48
-rw-r--r--include/asm-v850/cache.h26
-rw-r--r--include/asm-v850/cacheflush.h70
-rw-r--r--include/asm-v850/checksum.h112
-rw-r--r--include/asm-v850/clinkage.h26
-rw-r--r--include/asm-v850/cputime.h6
-rw-r--r--include/asm-v850/current.h47
-rw-r--r--include/asm-v850/delay.h47
-rw-r--r--include/asm-v850/device.h7
-rw-r--r--include/asm-v850/div64.h1
-rw-r--r--include/asm-v850/dma-mapping.h11
-rw-r--r--include/asm-v850/dma.h18
-rw-r--r--include/asm-v850/elf.h99
-rw-r--r--include/asm-v850/emergency-restart.h6
-rw-r--r--include/asm-v850/entry.h113
-rw-r--r--include/asm-v850/errno.h6
-rw-r--r--include/asm-v850/fb.h12
-rw-r--r--include/asm-v850/fcntl.h11
-rw-r--r--include/asm-v850/flat.h133
-rw-r--r--include/asm-v850/fpga85e2c.h82
-rw-r--r--include/asm-v850/futex.h6
-rw-r--r--include/asm-v850/gbus_int.h97
-rw-r--r--include/asm-v850/hardirq.h28
-rw-r--r--include/asm-v850/highres_timer.h44
-rw-r--r--include/asm-v850/hw_irq.h4
-rw-r--r--include/asm-v850/io.h142
-rw-r--r--include/asm-v850/ioctl.h1
-rw-r--r--include/asm-v850/ioctls.h84
-rw-r--r--include/asm-v850/ipcbuf.h29
-rw-r--r--include/asm-v850/irq.h55
-rw-r--r--include/asm-v850/irq_regs.h1
-rw-r--r--include/asm-v850/kdebug.h1
-rw-r--r--include/asm-v850/kmap_types.h19
-rw-r--r--include/asm-v850/kvm.h6
-rw-r--r--include/asm-v850/linkage.h8
-rw-r--r--include/asm-v850/local.h6
-rw-r--r--include/asm-v850/ma.h101
-rw-r--r--include/asm-v850/ma1.h50
-rw-r--r--include/asm-v850/machdep.h60
-rw-r--r--include/asm-v850/macrology.h17
-rw-r--r--include/asm-v850/me2.h182
-rw-r--r--include/asm-v850/mman.h15
-rw-r--r--include/asm-v850/mmu.h11
-rw-r--r--include/asm-v850/mmu_context.h13
-rw-r--r--include/asm-v850/module.h62
-rw-r--r--include/asm-v850/msgbuf.h31
-rw-r--r--include/asm-v850/mutex.h9
-rw-r--r--include/asm-v850/page.h128
-rw-r--r--include/asm-v850/param.h33
-rw-r--r--include/asm-v850/pci.h119
-rw-r--r--include/asm-v850/percpu.h14
-rw-r--r--include/asm-v850/pgalloc.h22
-rw-r--r--include/asm-v850/pgtable.h59
-rw-r--r--include/asm-v850/poll.h9
-rw-r--r--include/asm-v850/posix_types.h72
-rw-r--r--include/asm-v850/processor.h120
-rw-r--r--include/asm-v850/ptrace.h121
-rw-r--r--include/asm-v850/resource.h6
-rw-r--r--include/asm-v850/rte_cb.h78
-rw-r--r--include/asm-v850/rte_ma1_cb.h128
-rw-r--r--include/asm-v850/rte_mb_a_pci.h56
-rw-r--r--include/asm-v850/rte_me2_cb.h202
-rw-r--r--include/asm-v850/rte_nb85e_cb.h111
-rw-r--r--include/asm-v850/scatterlist.h31
-rw-r--r--include/asm-v850/sections.h6
-rw-r--r--include/asm-v850/segment.h36
-rw-r--r--include/asm-v850/semaphore.h1
-rw-r--r--include/asm-v850/sembuf.h25
-rw-r--r--include/asm-v850/serial.h56
-rw-r--r--include/asm-v850/setup.h6
-rw-r--r--include/asm-v850/shmbuf.h42
-rw-r--r--include/asm-v850/shmparam.h6
-rw-r--r--include/asm-v850/sigcontext.h25
-rw-r--r--include/asm-v850/siginfo.h6
-rw-r--r--include/asm-v850/signal.h168
-rw-r--r--include/asm-v850/sim.h47
-rw-r--r--include/asm-v850/sim85e2.h69
-rw-r--r--include/asm-v850/sim85e2c.h26
-rw-r--r--include/asm-v850/sim85e2s.h28
-rw-r--r--include/asm-v850/simsyscall.h99
-rw-r--r--include/asm-v850/socket.h57
-rw-r--r--include/asm-v850/sockios.h13
-rw-r--r--include/asm-v850/stat.h73
-rw-r--r--include/asm-v850/statfs.h6
-rw-r--r--include/asm-v850/string.h25
-rw-r--r--include/asm-v850/system.h123
-rw-r--r--include/asm-v850/teg.h101
-rw-r--r--include/asm-v850/termbits.h200
-rw-r--r--include/asm-v850/termios.h90
-rw-r--r--include/asm-v850/thread_info.h129
-rw-r--r--include/asm-v850/timex.h18
-rw-r--r--include/asm-v850/tlb.h21
-rw-r--r--include/asm-v850/tlbflush.h64
-rw-r--r--include/asm-v850/topology.h6
-rw-r--r--include/asm-v850/types.h36
-rw-r--r--include/asm-v850/uaccess.h159
-rw-r--r--include/asm-v850/ucontext.h14
-rw-r--r--include/asm-v850/unaligned.h22
-rw-r--r--include/asm-v850/unistd.h244
-rw-r--r--include/asm-v850/user.h52
-rw-r--r--include/asm-v850/v850e.h21
-rw-r--r--include/asm-v850/v850e2.h69
-rw-r--r--include/asm-v850/v850e2_cache.h75
-rw-r--r--include/asm-v850/v850e_cache.h48
-rw-r--r--include/asm-v850/v850e_intc.h133
-rw-r--r--include/asm-v850/v850e_timer_c.h48
-rw-r--r--include/asm-v850/v850e_timer_d.h62
-rw-r--r--include/asm-v850/v850e_uart.h76
-rw-r--r--include/asm-v850/v850e_uarta.h278
-rw-r--r--include/asm-v850/v850e_uartb.h262
-rw-r--r--include/asm-v850/v850e_utils.h35
-rw-r--r--include/asm-x86/Kbuild2
-rw-r--r--include/asm-x86/gpio.h60
-rw-r--r--include/asm-x86/hugetlb.h10
-rw-r--r--include/asm-x86/i387.h54
-rw-r--r--include/asm-x86/ide.h65
-rw-r--r--include/asm-x86/io_32.h2
-rw-r--r--include/asm-x86/io_64.h2
-rw-r--r--include/asm-x86/ipi.h2
-rw-r--r--include/asm-x86/page.h17
-rw-r--r--include/asm-x86/paravirt.h3
-rw-r--r--include/asm-x86/pgtable-3level.h8
-rw-r--r--include/asm-x86/pgtable.h4
-rw-r--r--include/asm-x86/pgtable_32.h4
-rw-r--r--include/asm-x86/pgtable_64.h10
-rw-r--r--include/asm-x86/processor-flags.h2
-rw-r--r--include/asm-x86/processor.h2
-rw-r--r--include/asm-x86/semaphore.h1
-rw-r--r--include/asm-x86/thread_info.h6
-rw-r--r--include/asm-x86/unistd_32.h6
-rw-r--r--include/asm-x86/unistd_64.h14
-rw-r--r--include/asm-x86/xen/page.h2
-rw-r--r--include/asm-xtensa/ide.h35
-rw-r--r--include/asm-xtensa/kvm.h6
-rw-r--r--include/asm-xtensa/page.h2
-rw-r--r--include/asm-xtensa/ptrace.h10
-rw-r--r--include/asm-xtensa/semaphore.h1
-rw-r--r--include/asm-xtensa/thread_info.h5
-rw-r--r--include/linux/Kbuild3
-rw-r--r--include/linux/acct.h3
-rw-r--r--include/linux/acpi.h1
-rw-r--r--include/linux/anon_inodes.h2
-rw-r--r--include/linux/async_tx.h11
-rw-r--r--include/linux/atmel-pwm-bl.h43
-rw-r--r--include/linux/audit.h1
-rw-r--r--include/linux/auto_fs4.h2
-rw-r--r--include/linux/auxvec.h8
-rw-r--r--include/linux/bcd.h9
-rw-r--r--include/linux/binfmts.h2
-rw-r--r--include/linux/bootmem.h104
-rw-r--r--include/linux/byteorder/big_endian.h12
-rw-r--r--include/linux/byteorder/little_endian.h12
-rw-r--r--include/linux/cgroup.h51
-rw-r--r--include/linux/coda.h43
-rw-r--r--include/linux/consolemap.h14
-rw-r--r--include/linux/cpu.h15
-rw-r--r--include/linux/cpumask.h172
-rw-r--r--include/linux/cpuset.h7
-rw-r--r--include/linux/crash_dump.h8
-rw-r--r--include/linux/dca.h7
-rw-r--r--include/linux/debugfs.h4
-rw-r--r--include/linux/delayacct.h19
-rw-r--r--include/linux/device.h58
-rw-r--r--include/linux/dirent.h20
-rw-r--r--include/linux/dma-attrs.h1
-rw-r--r--include/linux/dmaengine.h69
-rw-r--r--include/linux/dw_dmac.h62
-rw-r--r--include/linux/eisa.h2
-rw-r--r--include/linux/eventfd.h7
-rw-r--r--include/linux/eventpoll.h4
-rw-r--r--include/linux/ext2_fs.h4
-rw-r--r--include/linux/ext3_fs.h1
-rw-r--r--include/linux/fb.h5
-rw-r--r--include/linux/fd1772.h80
-rw-r--r--include/linux/fs.h17
-rw-r--r--include/linux/fs_enet_pd.h8
-rw-r--r--include/linux/fsl_devices.h7
-rw-r--r--include/linux/fuse.h3
-rw-r--r--include/linux/genhd.h2
-rw-r--r--include/linux/gfp.h24
-rw-r--r--include/linux/gpio.h13
-rw-r--r--include/linux/hid.h2
-rw-r--r--include/linux/hugetlb.h143
-rw-r--r--include/linux/i2c/max732x.h19
-rw-r--r--include/linux/ide.h223
-rw-r--r--include/linux/idr.h24
-rw-r--r--include/linux/init.h8
-rw-r--r--include/linux/init_task.h2
-rw-r--r--include/linux/inotify.h6
-rw-r--r--include/linux/ipc_namespace.h3
-rw-r--r--include/linux/ipv6.h2
-rw-r--r--include/linux/irqflags.h54
-rw-r--r--include/linux/kallsyms.h19
-rw-r--r--include/linux/kernel.h29
-rw-r--r--include/linux/kmod.h16
-rw-r--r--include/linux/kobject.h5
-rw-r--r--include/linux/kprobes.h7
-rw-r--r--include/linux/kthread.h3
-rw-r--r--include/linux/lcd.h2
-rw-r--r--include/linux/leds-pca9532.h45
-rw-r--r--include/linux/leds.h16
-rw-r--r--include/linux/list.h4
-rw-r--r--include/linux/major.h2
-rw-r--r--include/linux/memcontrol.h24
-rw-r--r--include/linux/memory_hotplug.h20
-rw-r--r--include/linux/mempolicy.h19
-rw-r--r--include/linux/mfd/core.h55
-rw-r--r--include/linux/mfd/tc6393xb.h49
-rw-r--r--include/linux/mfd/tmio.h17
-rw-r--r--include/linux/migrate.h21
-rw-r--r--include/linux/mlx4/device.h10
-rw-r--r--include/linux/mlx4/qp.h18
-rw-r--r--include/linux/mm.h30
-rw-r--r--include/linux/mm_types.h15
-rw-r--r--include/linux/module.h52
-rw-r--r--include/linux/msdos_fs.h56
-rw-r--r--include/linux/mtd/map.h2
-rw-r--r--include/linux/mtd/mtd.h2
-rw-r--r--include/linux/mtd/ubi.h5
-rw-r--r--include/linux/net.h18
-rw-r--r--include/linux/netdevice.h60
-rw-r--r--include/linux/nfsd/nfsd.h1
-rw-r--r--include/linux/notifier.h2
-rw-r--r--include/linux/nsproxy.h7
-rw-r--r--include/linux/of_gpio.h2
-rw-r--r--include/linux/page-flags.h29
-rw-r--r--include/linux/pagemap.h2
-rw-r--r--include/linux/parser.h2
-rw-r--r--include/linux/pci.h2
-rw-r--r--include/linux/pci_ids.h11
-rw-r--r--include/linux/pid.h8
-rw-r--r--include/linux/pid_namespace.h8
-rw-r--r--include/linux/pm.h109
-rw-r--r--include/linux/pm_legacy.h35
-rw-r--r--include/linux/proc_fs.h4
-rw-r--r--include/linux/profile.h58
-rw-r--r--include/linux/quota.h33
-rw-r--r--include/linux/quotaops.h281
-rw-r--r--include/linux/ratelimit.h27
-rw-r--r--include/linux/rcupreempt.h9
-rw-r--r--include/linux/reiserfs_fs.h4
-rw-r--r--include/linux/reiserfs_fs_sb.h6
-rw-r--r--include/linux/res_counter.h33
-rw-r--r--include/linux/rtc.h17
-rw-r--r--include/linux/scatterlist.h38
-rw-r--r--include/linux/sched.h45
-rw-r--r--include/linux/security.h2
-rw-r--r--include/linux/sem.h30
-rw-r--r--include/linux/semaphore.h6
-rw-r--r--include/linux/serial_core.h3
-rw-r--r--include/linux/signalfd.h6
-rw-r--r--include/linux/slab.h2
-rw-r--r--include/linux/sm501.h39
-rw-r--r--include/linux/smb_fs.h19
-rw-r--r--include/linux/smc91x.h12
-rw-r--r--include/linux/spi/ds1305.h35
-rw-r--r--include/linux/spi/max7301.h9
-rw-r--r--include/linux/spi/mcp23s08.h25
-rw-r--r--include/linux/spi/spi.h4
-rw-r--r--include/linux/spinlock.h72
-rw-r--r--include/linux/string.h3
-rw-r--r--include/linux/synclink.h1
-rw-r--r--include/linux/syscalls.h9
-rw-r--r--include/linux/sysdev.h39
-rw-r--r--include/linux/sysfs.h10
-rw-r--r--include/linux/taskstats.h6
-rw-r--r--include/linux/tick.h5
-rw-r--r--include/linux/timerfd.h6
-rw-r--r--include/linux/tty.h11
-rw-r--r--include/linux/tty_driver.h14
-rw-r--r--include/linux/typecheck.h24
-rw-r--r--include/linux/uio_driver.h8
-rw-r--r--include/linux/usb/composite.h2
-rw-r--r--include/linux/usb/serial.h56
-rw-r--r--include/linux/virtio_9p.h2
-rw-r--r--include/linux/virtio_balloon.h2
-rw-r--r--include/linux/virtio_blk.h5
-rw-r--r--include/linux/virtio_config.h16
-rw-r--r--include/linux/virtio_console.h2
-rw-r--r--include/linux/virtio_net.h2
-rw-r--r--include/linux/virtio_pci.h5
-rw-r--r--include/linux/virtio_ring.h2
-rw-r--r--include/linux/virtio_rng.h2
-rw-r--r--include/linux/vmstat.h6
-rw-r--r--include/linux/vt_kern.h19
-rw-r--r--include/linux/workqueue.h5
-rw-r--r--include/mtd/ubi-user.h76
-rw-r--r--include/net/ieee80211_radiotap.h2
-rw-r--r--include/net/if_inet6.h2
-rw-r--r--include/net/ip6_route.h2
-rw-r--r--include/net/ipcomp.h6
-rw-r--r--include/net/netns/ipv6.h2
-rw-r--r--include/net/sctp/structs.h1
-rw-r--r--include/rdma/rdma_cm.h4
-rw-r--r--include/scsi/scsi_host.h2
-rw-r--r--include/scsi/scsi_transport_fc.h4
-rw-r--r--include/scsi/scsi_transport_iscsi.h2
-rw-r--r--include/video/atmel_lcdc.h1
-rw-r--r--include/video/ili9320.h201
-rw-r--r--include/video/neomagic.h17
-rw-r--r--include/video/platform_lcd.h21
-rw-r--r--include/video/trident.h77
-rw-r--r--init/Kconfig15
-rw-r--r--init/do_mounts.c1
-rw-r--r--init/do_mounts_rd.c37
-rw-r--r--init/initramfs.c22
-rw-r--r--init/main.c9
-rw-r--r--init/version.c3
-rw-r--r--ipc/ipc_sysctl.c72
-rw-r--r--ipc/ipcns_notifier.c20
-rw-r--r--ipc/mqueue.c25
-rw-r--r--ipc/sem.c316
-rw-r--r--ipc/shm.c24
-rw-r--r--ipc/util.c61
-rw-r--r--ipc/util.h6
-rw-r--r--kernel/Kconfig.hz2
-rw-r--r--kernel/Makefile5
-rw-r--r--kernel/acct.c222
-rw-r--r--kernel/auditsc.c3
-rw-r--r--kernel/capability.c338
-rw-r--r--kernel/cgroup.c309
-rw-r--r--kernel/cpu.c47
-rw-r--r--kernel/cpuset.c363
-rw-r--r--kernel/delayacct.c16
-rw-r--r--kernel/exec_domain.c2
-rw-r--r--kernel/exit.c61
-rw-r--r--kernel/fork.c44
-rw-r--r--kernel/irq/manage.c107
-rw-r--r--kernel/kallsyms.c2
-rw-r--r--kernel/kmod.c15
-rw-r--r--kernel/kprobes.c132
-rw-r--r--kernel/kthread.c4
-rw-r--r--kernel/marker.c25
-rw-r--r--kernel/module.c336
-rw-r--r--kernel/ns_cgroup.c8
-rw-r--r--kernel/nsproxy.c8
-rw-r--r--kernel/panic.c22
-rw-r--r--kernel/pid.c10
-rw-r--r--kernel/pid_namespace.c10
-rw-r--r--kernel/posix-timers.c21
-rw-r--r--kernel/power/Kconfig11
-rw-r--r--kernel/power/main.c194
-rw-r--r--kernel/power/poweroff.c4
-rw-r--r--kernel/power/process.c2
-rw-r--r--kernel/power/snapshot.c88
-rw-r--r--kernel/printk.c19
-rw-r--r--kernel/profile.c4
-rw-r--r--kernel/rcuclassic.c2
-rw-r--r--kernel/rcupreempt.c10
-rw-r--r--kernel/res_counter.c48
-rw-r--r--kernel/rtmutex-tester.c7
-rw-r--r--kernel/sched.c359
-rw-r--r--kernel/sched_fair.c10
-rw-r--r--kernel/sched_rt.c83
-rw-r--r--kernel/signal.c80
-rw-r--r--kernel/softirq.c2
-rw-r--r--kernel/softlockup.c45
-rw-r--r--kernel/stop_machine.c3
-rw-r--r--kernel/sys.c4
-rw-r--r--kernel/sys_ni.c7
-rw-r--r--kernel/sysctl.c38
-rw-r--r--kernel/sysctl_check.c2
-rw-r--r--kernel/taskstats.c6
-rw-r--r--kernel/time/clocksource.c12
-rw-r--r--kernel/time/tick-broadcast.c3
-rw-r--r--kernel/time/tick-common.c14
-rw-r--r--kernel/time/tick-sched.c16
-rw-r--r--kernel/trace/trace_sysprof.c6
-rw-r--r--kernel/tsacct.c25
-rw-r--r--kernel/workqueue.c149
-rw-r--r--lib/Kconfig.debug41
-rw-r--r--lib/Kconfig.kgdb3
-rw-r--r--lib/Makefile2
-rw-r--r--lib/bcd.c14
-rw-r--r--lib/cmdline.c16
-rw-r--r--lib/cpumask.c9
-rw-r--r--lib/debugobjects.c4
-rw-r--r--lib/idr.c140
-rw-r--r--lib/inflate.c52
-rw-r--r--lib/kobject.c19
-rw-r--r--lib/kobject_uevent.c3
-rw-r--r--lib/list_debug.c50
-rw-r--r--lib/lzo/lzo1x_decompress.c6
-rw-r--r--lib/ratelimit.c55
-rw-r--r--lib/scatterlist.c176
-rw-r--r--lib/smp_processor_id.c6
-rw-r--r--lib/textsearch.c2
-rw-r--r--mm/Kconfig2
-rw-r--r--mm/Makefile2
-rw-r--r--mm/allocpercpu.c4
-rw-r--r--mm/bootmem.c935
-rw-r--r--mm/filemap.c168
-rw-r--r--mm/hugetlb.c1612
-rw-r--r--mm/internal.h61
-rw-r--r--mm/memcontrol.c364
-rw-r--r--mm/memory.c243
-rw-r--r--mm/memory_hotplug.c80
-rw-r--r--mm/mempolicy.c9
-rw-r--r--mm/migrate.c24
-rw-r--r--mm/mm_init.c152
-rw-r--r--mm/mmap.c12
-rw-r--r--mm/mprotect.c6
-rw-r--r--mm/page_alloc.c152
-rw-r--r--mm/pdflush.c4
-rw-r--r--mm/rmap.c14
-rw-r--r--mm/shmem.c91
-rw-r--r--mm/slob.c12
-rw-r--r--mm/slub.c65
-rw-r--r--mm/sparse.c115
-rw-r--r--mm/swap.c8
-rw-r--r--mm/swapfile.c49
-rw-r--r--mm/vmalloc.c20
-rw-r--r--mm/vmscan.c5
-rw-r--r--mm/vmstat.c3
-rw-r--r--net/802/psnap.c4
-rw-r--r--net/8021q/vlan_dev.c4
-rw-r--r--net/9p/trans_fd.c2
-rw-r--r--net/bluetooth/hci_sysfs.c7
-rw-r--r--net/compat.c52
-rw-r--r--net/core/dev.c109
-rw-r--r--net/core/sock.c2
-rw-r--r--net/core/sysctl_net_core.c4
-rw-r--r--net/core/user_dma.c1
-rw-r--r--net/core/utils.c5
-rw-r--r--net/ipv4/Kconfig4
-rw-r--r--net/ipv4/af_inet.c9
-rw-r--r--net/ipv4/ipcomp.c315
-rw-r--r--net/ipv4/netfilter/Kconfig2
-rw-r--r--net/ipv4/tcp_input.c3
-rw-r--r--net/ipv4/tcp_output.c2
-rw-r--r--net/ipv4/udp.c4
-rw-r--r--net/ipv6/Kconfig4
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/af_inet6.c9
-rw-r--r--net/ipv6/ip6_fib.c60
-rw-r--r--net/ipv6/ipcomp6.c298
-rw-r--r--net/ipv6/netfilter/Kconfig2
-rw-r--r--net/ipv6/route.c10
-rw-r--r--net/iucv/iucv.c2
-rw-r--r--net/netrom/af_netrom.c2
-rw-r--r--net/rose/af_rose.c2
-rw-r--r--net/sched/sch_api.c2
-rw-r--r--net/sched/sch_generic.c10
-rw-r--r--net/sched/sch_sfq.c9
-rw-r--r--net/sctp/outqueue.c4
-rw-r--r--net/sctp/proc.c5
-rw-r--r--net/sctp/socket.c2
-rw-r--r--net/socket.c142
-rw-r--r--net/sunrpc/svc.c3
-rw-r--r--net/sysctl_net.c14
-rw-r--r--net/xfrm/Kconfig6
-rw-r--r--net/xfrm/Makefile1
-rw-r--r--net/xfrm/xfrm_ipcomp.c385
-rw-r--r--samples/firmware_class/firmware_sample_firmware_class.c2
-rw-r--r--samples/kobject/kset-example.c2
-rw-r--r--scripts/Makefile.fwinst10
-rw-r--r--scripts/Makefile.modpost1
-rwxr-xr-xscripts/checkpatch.pl310
-rwxr-xr-xscripts/checkstack.pl27
-rw-r--r--scripts/genksyms/genksyms.c3
-rw-r--r--scripts/mod/file2alias.c26
-rw-r--r--scripts/mod/mk_elfconfig.c2
-rw-r--r--scripts/mod/modpost.c3
-rw-r--r--security/Kconfig3
-rw-r--r--security/commoncap.c108
-rw-r--r--security/device_cgroup.c158
-rw-r--r--sound/core/info.c1
-rw-r--r--sound/core/init.c5
-rw-r--r--sound/oss/Kconfig41
-rw-r--r--sound/oss/Makefile3
-rw-r--r--sound/oss/soundcard.c14
-rw-r--r--sound/oss/trident.c4654
-rw-r--r--sound/oss/trident.h358
-rw-r--r--sound/soc/pxa/Kconfig1
-rw-r--r--sound/soc/pxa/tosa.c29
-rw-r--r--sound/sound_core.c5
-rw-r--r--virt/kvm/kvm_main.c4
1956 files changed, 81971 insertions, 59088 deletions
diff --git a/CREDITS b/CREDITS
index 077b147388b..c62dcb3b7e2 100644
--- a/CREDITS
+++ b/CREDITS
@@ -317,6 +317,14 @@ S: 2322 37th Ave SW
S: Seattle, Washington 98126-2010
S: USA
+N: Muli Ben-Yehuda
+E: mulix@mulix.org
+E: muli@il.ibm.com
+W: http://www.mulix.org
+D: trident OSS sound driver, x86-64 dma-ops and Calgary IOMMU,
+D: KVM and Xen bits and other misc. hackery.
+S: Haifa, Israel
+
N: Johannes Berg
E: johannes@sipsolutions.net
W: http://johannes.sipsolutions.net/
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index 1977fab3865..6de71308a90 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -361,8 +361,6 @@ telephony/
- directory with info on telephony (e.g. voice over IP) support.
time_interpolators.txt
- info on time interpolators.
-tipar.txt
- - information about Parallel link cable for Texas Instruments handhelds.
tty.txt
- guide to the locking policies of the tty layer.
uml/
diff --git a/Documentation/ABI/testing/sysfs-dev b/Documentation/ABI/testing/sysfs-dev
new file mode 100644
index 00000000000..a9f2b8b0530
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-dev
@@ -0,0 +1,20 @@
+What: /sys/dev
+Date: April 2008
+KernelVersion: 2.6.26
+Contact: Dan Williams <dan.j.williams@intel.com>
+Description: The /sys/dev tree provides a method to look up the sysfs
+ path for a device using the information returned from
+ stat(2). There are two directories, 'block' and 'char',
+ beneath /sys/dev containing symbolic links with names of
+ the form "<major>:<minor>". These links point to the
+ corresponding sysfs path for the given device.
+
+ Example:
+ $ readlink /sys/dev/block/8:32
+ ../../block/sdc
+
+ Entries in /sys/dev/char and /sys/dev/block will be
+ dynamically created and destroyed as devices enter and
+ leave the system.
+
+Users: mdadm <linux-raid@vger.kernel.org>
diff --git a/Documentation/ABI/testing/sysfs-devices-memory b/Documentation/ABI/testing/sysfs-devices-memory
new file mode 100644
index 00000000000..7a16fe1e227
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-memory
@@ -0,0 +1,24 @@
+What: /sys/devices/system/memory
+Date: June 2008
+Contact: Badari Pulavarty <pbadari@us.ibm.com>
+Description:
+ The /sys/devices/system/memory contains a snapshot of the
+ internal state of the kernel memory blocks. Files could be
+ added or removed dynamically to represent hot-add/remove
+ operations.
+
+Users: hotplug memory add/remove tools
+ https://w3.opensource.ibm.com/projects/powerpc-utils/
+
+What: /sys/devices/system/memory/memoryX/removable
+Date: June 2008
+Contact: Badari Pulavarty <pbadari@us.ibm.com>
+Description:
+ The file /sys/devices/system/memory/memoryX/removable
+ indicates whether this memory block is removable or not.
+ This is useful for a user-level agent to determine
+ identify removable sections of the memory before attempting
+ potentially expensive hot-remove memory operation
+
+Users: hotplug memory remove tools
+ https://w3.opensource.ibm.com/projects/powerpc-utils/
diff --git a/Documentation/ABI/testing/sysfs-kernel-mm b/Documentation/ABI/testing/sysfs-kernel-mm
new file mode 100644
index 00000000000..190d523ac15
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-kernel-mm
@@ -0,0 +1,6 @@
+What: /sys/kernel/mm
+Date: July 2008
+Contact: Nishanth Aravamudan <nacc@us.ibm.com>, VM maintainers
+Description:
+ /sys/kernel/mm/ should contain any and all VM
+ related information in /sys/kernel/.
diff --git a/Documentation/ABI/testing/sysfs-kernel-mm-hugepages b/Documentation/ABI/testing/sysfs-kernel-mm-hugepages
new file mode 100644
index 00000000000..e21c00571cf
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-kernel-mm-hugepages
@@ -0,0 +1,15 @@
+What: /sys/kernel/mm/hugepages/
+Date: June 2008
+Contact: Nishanth Aravamudan <nacc@us.ibm.com>, hugetlb maintainers
+Description:
+ /sys/kernel/mm/hugepages/ contains a number of subdirectories
+ of the form hugepages-<size>kB, where <size> is the page size
+ of the hugepages supported by the kernel/CPU combination.
+
+ Under these directories are a number of files:
+ nr_hugepages
+ nr_overcommit_hugepages
+ free_hugepages
+ surplus_hugepages
+ resv_hugepages
+ See Documentation/vm/hugetlbpage.txt for details.
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index 6caa1461557..1875e502f87 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -474,25 +474,29 @@ make a good program).
So, you can either get rid of GNU emacs, or change it to use saner
values. To do the latter, you can stick the following in your .emacs file:
-(defun linux-c-mode ()
- "C mode with adjusted defaults for use with the Linux kernel."
- (interactive)
- (c-mode)
- (c-set-style "K&R")
- (setq tab-width 8)
- (setq indent-tabs-mode t)
- (setq c-basic-offset 8))
-
-This will define the M-x linux-c-mode command. When hacking on a
-module, if you put the string -*- linux-c -*- somewhere on the first
-two lines, this mode will be automatically invoked. Also, you may want
-to add
-
-(setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . linux-c-mode)
- auto-mode-alist))
-
-to your .emacs file if you want to have linux-c-mode switched on
-automagically when you edit source files under /usr/src/linux.
+(defun c-lineup-arglist-tabs-only (ignored)
+ "Line up argument lists by tabs, not spaces"
+ (let* ((anchor (c-langelem-pos c-syntactic-element))
+ (column (c-langelem-2nd-pos c-syntactic-element))
+ (offset (- (1+ column) anchor))
+ (steps (floor offset c-basic-offset)))
+ (* (max steps 1)
+ c-basic-offset)))
+
+(add-hook 'c-mode-hook
+ (lambda ()
+ (let ((filename (buffer-file-name)))
+ ;; Enable kernel mode for the appropriate files
+ (when (and filename
+ (string-match "~/src/linux-trees" filename))
+ (setq indent-tabs-mode t)
+ (c-set-style "linux")
+ (c-set-offset 'arglist-cont-nonempty
+ '(c-lineup-gcc-asm-reg
+ c-lineup-arglist-tabs-only))))))
+
+This will make emacs go better with the kernel coding style for C
+files below ~/src/linux-trees.
But even if you fail in getting emacs to do sane formatting, not
everything is lost: use "indent".
diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt
index 6d772f84b47..b768cc0e402 100644
--- a/Documentation/DMA-attributes.txt
+++ b/Documentation/DMA-attributes.txt
@@ -22,3 +22,12 @@ ready and available in memory. The DMA of the "completion indication"
could race with data DMA. Mapping the memory used for completion
indications with DMA_ATTR_WRITE_BARRIER would prevent the race.
+DMA_ATTR_WEAK_ORDERING
+----------------------
+
+DMA_ATTR_WEAK_ORDERING specifies that reads and writes to the mapping
+may be weakly ordered, that is that reads and writes may pass each other.
+
+Since it is optional for platforms to implement DMA_ATTR_WEAK_ORDERING,
+those that do not will simply ignore the attribute and exhibit default
+behavior.
diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl
index 2510763295d..084f6ad7b7a 100644
--- a/Documentation/DocBook/kernel-locking.tmpl
+++ b/Documentation/DocBook/kernel-locking.tmpl
@@ -219,10 +219,10 @@
</para>
<sect1 id="lock-intro">
- <title>Three Main Types of Kernel Locks: Spinlocks, Mutexes and Semaphores</title>
+ <title>Two Main Types of Kernel Locks: Spinlocks and Mutexes</title>
<para>
- There are three main types of kernel locks. The fundamental type
+ There are two main types of kernel locks. The fundamental type
is the spinlock
(<filename class="headerfile">include/asm/spinlock.h</filename>),
which is a very simple single-holder lock: if you can't get the
@@ -240,14 +240,6 @@
use a spinlock instead.
</para>
<para>
- The third type is a semaphore
- (<filename class="headerfile">include/linux/semaphore.h</filename>): it
- can have more than one holder at any time (the number decided at
- initialization time), although it is most commonly used as a
- single-holder lock (a mutex). If you can't get a semaphore, your
- task will be suspended and later on woken up - just like for mutexes.
- </para>
- <para>
Neither type of lock is recursive: see
<xref linkend="deadlock"/>.
</para>
@@ -278,7 +270,7 @@
</para>
<para>
- Semaphores still exist, because they are required for
+ Mutexes still exist, because they are required for
synchronization between <firstterm linkend="gloss-usercontext">user
contexts</firstterm>, as we will see below.
</para>
@@ -289,18 +281,17 @@
<para>
If you have a data structure which is only ever accessed from
- user context, then you can use a simple semaphore
- (<filename>linux/linux/semaphore.h</filename>) to protect it. This
- is the most trivial case: you initialize the semaphore to the number
- of resources available (usually 1), and call
- <function>down_interruptible()</function> to grab the semaphore, and
- <function>up()</function> to release it. There is also a
- <function>down()</function>, which should be avoided, because it
+ user context, then you can use a simple mutex
+ (<filename>include/linux/mutex.h</filename>) to protect it. This
+ is the most trivial case: you initialize the mutex. Then you can
+ call <function>mutex_lock_interruptible()</function> to grab the mutex,
+ and <function>mutex_unlock()</function> to release it. There is also a
+ <function>mutex_lock()</function>, which should be avoided, because it
will not return if a signal is received.
</para>
<para>
- Example: <filename>linux/net/core/netfilter.c</filename> allows
+ Example: <filename>net/netfilter/nf_sockopt.c</filename> allows
registration of new <function>setsockopt()</function> and
<function>getsockopt()</function> calls, with
<function>nf_register_sockopt()</function>. Registration and
@@ -515,7 +506,7 @@
<listitem>
<para>
If you are in a process context (any syscall) and want to
- lock other process out, use a semaphore. You can take a semaphore
+ lock other process out, use a mutex. You can take a mutex
and sleep (<function>copy_from_user*(</function> or
<function>kmalloc(x,GFP_KERNEL)</function>).
</para>
@@ -662,7 +653,7 @@
<entry>SLBH</entry>
<entry>SLBH</entry>
<entry>SLBH</entry>
-<entry>DI</entry>
+<entry>MLI</entry>
<entry>None</entry>
</row>
@@ -692,8 +683,8 @@
<entry>spin_lock_bh</entry>
</row>
<row>
-<entry>DI</entry>
-<entry>down_interruptible</entry>
+<entry>MLI</entry>
+<entry>mutex_lock_interruptible</entry>
</row>
</tbody>
@@ -1310,7 +1301,7 @@ as Alan Cox says, <quote>Lock data, not code</quote>.
<para>
There is a coding bug where a piece of code tries to grab a
spinlock twice: it will spin forever, waiting for the lock to
- be released (spinlocks, rwlocks and semaphores are not
+ be released (spinlocks, rwlocks and mutexes are not
recursive in Linux). This is trivial to diagnose: not a
stay-up-five-nights-talk-to-fluffy-code-bunnies kind of
problem.
@@ -1335,7 +1326,7 @@ as Alan Cox says, <quote>Lock data, not code</quote>.
<para>
This complete lockup is easy to diagnose: on SMP boxes the
- watchdog timer or compiling with <symbol>DEBUG_SPINLOCKS</symbol> set
+ watchdog timer or compiling with <symbol>DEBUG_SPINLOCK</symbol> set
(<filename>include/linux/spinlock.h</filename>) will show this up
immediately when it happens.
</para>
@@ -1558,7 +1549,7 @@ the amount of locking which needs to be done.
<title>Read/Write Lock Variants</title>
<para>
- Both spinlocks and semaphores have read/write variants:
+ Both spinlocks and mutexes have read/write variants:
<type>rwlock_t</type> and <structname>struct rw_semaphore</structname>.
These divide users into two classes: the readers and the writers. If
you are only reading the data, you can get a read lock, but to write to
@@ -1681,7 +1672,7 @@ the amount of locking which needs to be done.
#include &lt;linux/slab.h&gt;
#include &lt;linux/string.h&gt;
+#include &lt;linux/rcupdate.h&gt;
- #include &lt;linux/semaphore.h&gt;
+ #include &lt;linux/mutex.h&gt;
#include &lt;asm/errno.h&gt;
struct object
@@ -1913,7 +1904,7 @@ machines due to caching.
</listitem>
<listitem>
<para>
- <function> put_user()</function>
+ <function>put_user()</function>
</para>
</listitem>
</itemizedlist>
@@ -1927,13 +1918,13 @@ machines due to caching.
<listitem>
<para>
- <function>down_interruptible()</function> and
- <function>down()</function>
+ <function>mutex_lock_interruptible()</function> and
+ <function>mutex_lock()</function>
</para>
<para>
- There is a <function>down_trylock()</function> which can be
+ There is a <function>mutex_trylock()</function> which can be
used inside interrupt context, as it will not sleep.
- <function>up()</function> will also never sleep.
+ <function>mutex_unlock()</function> will also never sleep.
</para>
</listitem>
</itemizedlist>
@@ -2023,7 +2014,7 @@ machines due to caching.
<para>
Prior to 2.5, or when <symbol>CONFIG_PREEMPT</symbol> is
unset, processes in user context inside the kernel would not
- preempt each other (ie. you had that CPU until you have it up,
+ preempt each other (ie. you had that CPU until you gave it up,
except for interrupts). With the addition of
<symbol>CONFIG_PREEMPT</symbol> in 2.5.4, this changed: when
in user context, higher priority tasks can "cut in": spinlocks
diff --git a/Documentation/DocBook/procfs-guide.tmpl b/Documentation/DocBook/procfs-guide.tmpl
index 1fd6a1ec759..8a5dc6e021f 100644
--- a/Documentation/DocBook/procfs-guide.tmpl
+++ b/Documentation/DocBook/procfs-guide.tmpl
@@ -29,12 +29,12 @@
<revhistory>
<revision>
- <revnumber>1.0&nbsp;</revnumber>
+ <revnumber>1.0</revnumber>
<date>May 30, 2001</date>
<revremark>Initial revision posted to linux-kernel</revremark>
</revision>
<revision>
- <revnumber>1.1&nbsp;</revnumber>
+ <revnumber>1.1</revnumber>
<date>June 3, 2001</date>
<revremark>Revised after comments from linux-kernel</revremark>
</revision>
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl
index fdd7f4f887b..df87d1b9360 100644
--- a/Documentation/DocBook/uio-howto.tmpl
+++ b/Documentation/DocBook/uio-howto.tmpl
@@ -21,6 +21,18 @@
</affiliation>
</author>
+<copyright>
+ <year>2006-2008</year>
+ <holder>Hans-Jürgen Koch.</holder>
+</copyright>
+
+<legalnotice>
+<para>
+This documentation is Free Software licensed under the terms of the
+GPL version 2.
+</para>
+</legalnotice>
+
<pubdate>2006-12-11</pubdate>
<abstract>
@@ -30,6 +42,12 @@
<revhistory>
<revision>
+ <revnumber>0.5</revnumber>
+ <date>2008-05-22</date>
+ <authorinitials>hjk</authorinitials>
+ <revremark>Added description of write() function.</revremark>
+ </revision>
+ <revision>
<revnumber>0.4</revnumber>
<date>2007-11-26</date>
<authorinitials>hjk</authorinitials>
@@ -57,20 +75,9 @@
</bookinfo>
<chapter id="aboutthisdoc">
-<?dbhtml filename="about.html"?>
+<?dbhtml filename="aboutthis.html"?>
<title>About this document</title>
-<sect1 id="copyright">
-<?dbhtml filename="copyright.html"?>
-<title>Copyright and License</title>
-<para>
- Copyright (c) 2006 by Hans-Jürgen Koch.</para>
-<para>
-This documentation is Free Software licensed under the terms of the
-GPL version 2.
-</para>
-</sect1>
-
<sect1 id="translations">
<?dbhtml filename="translations.html"?>
<title>Translations</title>
@@ -189,6 +196,30 @@ interested in translating it, please email me
represents the total interrupt count. You can use this number
to figure out if you missed some interrupts.
</para>
+ <para>
+ For some hardware that has more than one interrupt source internally,
+ but not separate IRQ mask and status registers, there might be
+ situations where userspace cannot determine what the interrupt source
+ was if the kernel handler disables them by writing to the chip's IRQ
+ register. In such a case, the kernel has to disable the IRQ completely
+ to leave the chip's register untouched. Now the userspace part can
+ determine the cause of the interrupt, but it cannot re-enable
+ interrupts. Another cornercase is chips where re-enabling interrupts
+ is a read-modify-write operation to a combined IRQ status/acknowledge
+ register. This would be racy if a new interrupt occurred
+ simultaneously.
+ </para>
+ <para>
+ To address these problems, UIO also implements a write() function. It
+ is normally not used and can be ignored for hardware that has only a
+ single interrupt source or has separate IRQ mask and status registers.
+ If you need it, however, a write to <filename>/dev/uioX</filename>
+ will call the <function>irqcontrol()</function> function implemented
+ by the driver. You have to write a 32-bit value that is usually either
+ 0 or 1 to disable or enable interrupts. If a driver does not implement
+ <function>irqcontrol()</function>, <function>write()</function> will
+ return with <varname>-ENOSYS</varname>.
+ </para>
<para>
To handle interrupts properly, your custom kernel module can
@@ -362,6 +393,14 @@ device is actually used.
<function>open()</function>, you will probably also want a custom
<function>release()</function> function.
</para></listitem>
+
+<listitem><para>
+<varname>int (*irqcontrol)(struct uio_info *info, s32 irq_on)
+</varname>: Optional. If you need to be able to enable or disable
+interrupts from userspace by writing to <filename>/dev/uioX</filename>,
+you can implement this function. The parameter <varname>irq_on</varname>
+will be 0 to disable interrupts and 1 to enable them.
+</para></listitem>
</itemizedlist>
<para>
diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index 619e8caf30d..c2371c5a98f 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -358,7 +358,7 @@ Here is a list of some of the different kernel trees available:
- pcmcia, Dominik Brodowski <linux@dominikbrodowski.net>
git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
- - SCSI, James Bottomley <James.Bottomley@SteelEye.com>
+ - SCSI, James Bottomley <James.Bottomley@hansenpartnership.com>
git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
- x86, Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/accounting/delay-accounting.txt b/Documentation/accounting/delay-accounting.txt
index 1443cd71d26..8a12f0730c9 100644
--- a/Documentation/accounting/delay-accounting.txt
+++ b/Documentation/accounting/delay-accounting.txt
@@ -11,6 +11,7 @@ the delays experienced by a task while
a) waiting for a CPU (while being runnable)
b) completion of synchronous block I/O initiated by the task
c) swapping in pages
+d) memory reclaim
and makes these statistics available to userspace through
the taskstats interface.
@@ -41,7 +42,7 @@ this structure. See
include/linux/taskstats.h
for a description of the fields pertaining to delay accounting.
It will generally be in the form of counters returning the cumulative
-delay seen for cpu, sync block I/O, swapin etc.
+delay seen for cpu, sync block I/O, swapin, memory reclaim etc.
Taking the difference of two successive readings of a given
counter (say cpu_delay_total) for a task will give the delay
@@ -94,7 +95,9 @@ CPU count real total virtual total delay total
7876 92005750 100000000 24001500
IO count delay total
0 0
-MEM count delay total
+SWAP count delay total
+ 0 0
+RECLAIM count delay total
0 0
Get delays seen in executing a given simple command
@@ -108,5 +111,7 @@ CPU count real total virtual total delay total
6 4000250 4000000 0
IO count delay total
0 0
-MEM count delay total
+SWAP count delay total
+ 0 0
+RECLAIM count delay total
0 0
diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c
index 40121b5cca1..3f7755f3963 100644
--- a/Documentation/accounting/getdelays.c
+++ b/Documentation/accounting/getdelays.c
@@ -196,14 +196,18 @@ void print_delayacct(struct taskstats *t)
" %15llu%15llu%15llu%15llu\n"
"IO %15s%15s\n"
" %15llu%15llu\n"
- "MEM %15s%15s\n"
+ "SWAP %15s%15s\n"
+ " %15llu%15llu\n"
+ "RECLAIM %12s%15s\n"
" %15llu%15llu\n",
"count", "real total", "virtual total", "delay total",
t->cpu_count, t->cpu_run_real_total, t->cpu_run_virtual_total,
t->cpu_delay_total,
"count", "delay total",
t->blkio_count, t->blkio_delay_total,
- "count", "delay total", t->swapin_count, t->swapin_delay_total);
+ "count", "delay total", t->swapin_count, t->swapin_delay_total,
+ "count", "delay total",
+ t->freepages_count, t->freepages_delay_total);
}
void task_context_switch_counts(struct taskstats *t)
diff --git a/Documentation/accounting/taskstats-struct.txt b/Documentation/accounting/taskstats-struct.txt
index cd784f46bf8..b988d110db5 100644
--- a/Documentation/accounting/taskstats-struct.txt
+++ b/Documentation/accounting/taskstats-struct.txt
@@ -26,6 +26,8 @@ There are three different groups of fields in the struct taskstats:
5) Time accounting for SMT machines
+6) Extended delay accounting fields for memory reclaim
+
Future extension should add fields to the end of the taskstats struct, and
should not change the relative position of each field within the struct.
@@ -170,4 +172,9 @@ struct taskstats {
__u64 ac_utimescaled; /* utime scaled on frequency etc */
__u64 ac_stimescaled; /* stime scaled on frequency etc */
__u64 cpu_scaled_run_real_total; /* scaled cpu_run_real_total */
+
+6) Extended delay accounting fields for memory reclaim
+ /* Delay waiting for memory reclaim */
+ __u64 freepages_count;
+ __u64 freepages_delay_total;
}
diff --git a/Documentation/bt8xxgpio.txt b/Documentation/bt8xxgpio.txt
new file mode 100644
index 00000000000..d8297e4ebd2
--- /dev/null
+++ b/Documentation/bt8xxgpio.txt
@@ -0,0 +1,67 @@
+===============================================================
+== BT8XXGPIO driver ==
+== ==
+== A driver for a selfmade cheap BT8xx based PCI GPIO-card ==
+== ==
+== For advanced documentation, see ==
+== http://www.bu3sch.de/btgpio.php ==
+===============================================================
+
+
+A generic digital 24-port PCI GPIO card can be built out of an ordinary
+Brooktree bt848, bt849, bt878 or bt879 based analog TV tuner card. The
+Brooktree chip is used in old analog Hauppauge WinTV PCI cards. You can easily
+find them used for low prices on the net.
+
+The bt8xx chip does have 24 digital GPIO ports.
+These ports are accessible via 24 pins on the SMD chip package.
+
+
+==============================================
+== How to physically access the GPIO pins ==
+==============================================
+
+The are several ways to access these pins. One might unsolder the whole chip
+and put it on a custom PCI board, or one might only unsolder each individual
+GPIO pin and solder that to some tiny wire. As the chip package really is tiny
+there are some advanced soldering skills needed in any case.
+
+The physical pinouts are drawn in the following ASCII art.
+The GPIO pins are marked with G00-G23
+
+ G G G G G G G G G G G G G G G G G G
+ 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+ ---------------------------------------------------------------------------
+ --| ^ ^ |--
+ --| pin 86 pin 67 |--
+ --| |--
+ --| pin 61 > |-- G18
+ --| |-- G19
+ --| |-- G20
+ --| |-- G21
+ --| |-- G22
+ --| pin 56 > |-- G23
+ --| |--
+ --| Brooktree 878/879 |--
+ --| |--
+ --| |--
+ --| |--
+ --| |--
+ --| |--
+ --| |--
+ --| |--
+ --| |--
+ --| |--
+ --| |--
+ --| |--
+ --| |--
+ --| |--
+ --| O |--
+ --| |--
+ ---------------------------------------------------------------------------
+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+ ^
+ This is pin 1
+
diff --git a/Documentation/controllers/memory.txt b/Documentation/controllers/memory.txt
index 866b9cd9a95..9b53d582736 100644
--- a/Documentation/controllers/memory.txt
+++ b/Documentation/controllers/memory.txt
@@ -242,8 +242,7 @@ rmdir() if there are no tasks.
1. Add support for accounting huge pages (as a separate controller)
2. Make per-cgroup scanner reclaim not-shared pages first
3. Teach controller to account for shared-pages
-4. Start reclamation when the limit is lowered
-5. Start reclamation in the background when the limit is
+4. Start reclamation in the background when the limit is
not yet hit but the usage is getting closer
Summary
diff --git a/Documentation/edac.txt b/Documentation/edac.txt
index a5c36842ece..ced52738800 100644
--- a/Documentation/edac.txt
+++ b/Documentation/edac.txt
@@ -222,74 +222,9 @@ both csrow2 and csrow3 are populated, this indicates a dual ranked
set of DIMMs for channels 0 and 1.
-Within each of the 'mc','mcX' and 'csrowX' directories are several
+Within each of the 'mcX' and 'csrowX' directories are several
EDAC control and attribute files.
-
-============================================================================
-DIRECTORY 'mc'
-
-In directory 'mc' are EDAC system overall control and attribute files:
-
-
-Panic on UE control file:
-
- 'edac_mc_panic_on_ue'
-
- An uncorrectable error will cause a machine panic. This is usually
- desirable. It is a bad idea to continue when an uncorrectable error
- occurs - it is indeterminate what was uncorrected and the operating
- system context might be so mangled that continuing will lead to further
- corruption. If the kernel has MCE configured, then EDAC will never
- notice the UE.
-
- LOAD TIME: module/kernel parameter: panic_on_ue=[0|1]
-
- RUN TIME: echo "1" >/sys/devices/system/edac/mc/edac_mc_panic_on_ue
-
-
-Log UE control file:
-
- 'edac_mc_log_ue'
-
- Generate kernel messages describing uncorrectable errors. These errors
- are reported through the system message log system. UE statistics
- will be accumulated even when UE logging is disabled.
-
- LOAD TIME: module/kernel parameter: log_ue=[0|1]
-
- RUN TIME: echo "1" >/sys/devices/system/edac/mc/edac_mc_log_ue
-
-
-Log CE control file:
-
- 'edac_mc_log_ce'
-
- Generate kernel messages describing correctable errors. These
- errors are reported through the system message log system.
- CE statistics will be accumulated even when CE logging is disabled.
-
- LOAD TIME: module/kernel parameter: log_ce=[0|1]
-
- RUN TIME: echo "1" >/sys/devices/system/edac/mc/edac_mc_log_ce
-
-
-Polling period control file:
-
- 'edac_mc_poll_msec'
-
- The time period, in milliseconds, for polling for error information.
- Too small a value wastes resources. Too large a value might delay
- necessary handling of errors and might loose valuable information for
- locating the error. 1000 milliseconds (once each second) is the current
- default. Systems which require all the bandwidth they can get, may
- increase this.
-
- LOAD TIME: module/kernel parameter: poll_msec=[0|1]
-
- RUN TIME: echo "1000" >/sys/devices/system/edac/mc/edac_mc_poll_msec
-
-
============================================================================
'mcX' DIRECTORIES
@@ -537,7 +472,6 @@ Channel 1 DIMM Label control file:
motherboard specific and determination of this information
must occur in userland at this time.
-
============================================================================
SYSTEM LOGGING
@@ -570,7 +504,6 @@ error type, a notice of "no info" and then an optional,
driver-specific error message.
-
============================================================================
PCI Bus Parity Detection
@@ -604,6 +537,74 @@ Enable/Disable PCI Parity checking control file:
echo "0" >/sys/devices/system/edac/pci/check_pci_parity
+Parity Count:
+
+ 'pci_parity_count'
+
+ This attribute file will display the number of parity errors that
+ have been detected.
+
+
+============================================================================
+MODULE PARAMETERS
+
+Panic on UE control file:
+
+ 'edac_mc_panic_on_ue'
+
+ An uncorrectable error will cause a machine panic. This is usually
+ desirable. It is a bad idea to continue when an uncorrectable error
+ occurs - it is indeterminate what was uncorrected and the operating
+ system context might be so mangled that continuing will lead to further
+ corruption. If the kernel has MCE configured, then EDAC will never
+ notice the UE.
+
+ LOAD TIME: module/kernel parameter: edac_mc_panic_on_ue=[0|1]
+
+ RUN TIME: echo "1" > /sys/module/edac_core/parameters/edac_mc_panic_on_ue
+
+
+Log UE control file:
+
+ 'edac_mc_log_ue'
+
+ Generate kernel messages describing uncorrectable errors. These errors
+ are reported through the system message log system. UE statistics
+ will be accumulated even when UE logging is disabled.
+
+ LOAD TIME: module/kernel parameter: edac_mc_log_ue=[0|1]
+
+ RUN TIME: echo "1" > /sys/module/edac_core/parameters/edac_mc_log_ue
+
+
+Log CE control file:
+
+ 'edac_mc_log_ce'
+
+ Generate kernel messages describing correctable errors. These
+ errors are reported through the system message log system.
+ CE statistics will be accumulated even when CE logging is disabled.
+
+ LOAD TIME: module/kernel parameter: edac_mc_log_ce=[0|1]
+
+ RUN TIME: echo "1" > /sys/module/edac_core/parameters/edac_mc_log_ce
+
+
+Polling period control file:
+
+ 'edac_mc_poll_msec'
+
+ The time period, in milliseconds, for polling for error information.
+ Too small a value wastes resources. Too large a value might delay
+ necessary handling of errors and might loose valuable information for
+ locating the error. 1000 milliseconds (once each second) is the current
+ default. Systems which require all the bandwidth they can get, may
+ increase this.
+
+ LOAD TIME: module/kernel parameter: edac_mc_poll_msec=[0|1]
+
+ RUN TIME: echo "1000" > /sys/module/edac_core/parameters/edac_mc_poll_msec
+
Panic on PCI PARITY Error:
@@ -614,21 +615,13 @@ Panic on PCI PARITY Error:
error has been detected.
- module/kernel parameter: panic_on_pci_parity=[0|1]
+ module/kernel parameter: edac_panic_on_pci_pe=[0|1]
Enable:
- echo "1" >/sys/devices/system/edac/pci/panic_on_pci_parity
+ echo "1" > /sys/module/edac_core/parameters/edac_panic_on_pci_pe
Disable:
- echo "0" >/sys/devices/system/edac/pci/panic_on_pci_parity
-
-
-Parity Count:
-
- 'pci_parity_count'
-
- This attribute file will display the number of parity errors that
- have been detected.
+ echo "0" > /sys/module/edac_core/parameters/edac_panic_on_pci_pe
diff --git a/Documentation/fb/sh7760fb.txt b/Documentation/fb/sh7760fb.txt
new file mode 100644
index 00000000000..c87bfe5c630
--- /dev/null
+++ b/Documentation/fb/sh7760fb.txt
@@ -0,0 +1,131 @@
+SH7760/SH7763 integrated LCDC Framebuffer driver
+================================================
+
+0. Overwiew
+-----------
+The SH7760/SH7763 have an integrated LCD Display controller (LCDC) which
+supports (in theory) resolutions ranging from 1x1 to 1024x1024,
+with color depths ranging from 1 to 16 bits, on STN, DSTN and TFT Panels.
+
+Caveats:
+* Framebuffer memory must be a large chunk allocated at the top
+ of Area3 (HW requirement). Because of this requirement you should NOT
+ make the driver a module since at runtime it may become impossible to
+ get a large enough contiguous chunk of memory.
+
+* The driver does not support changing resolution while loaded
+ (displays aren't hotpluggable anyway)
+
+* Heavy flickering may be observed
+ a) if you're using 15/16bit color modes at >= 640x480 px resolutions,
+ b) during PCMCIA (or any other slow bus) activity.
+
+* Rotation works only 90degress clockwise, and only if horizontal
+ resolution is <= 320 pixels.
+
+files: drivers/video/sh7760fb.c
+ include/asm-sh/sh7760fb.h
+ Documentation/fb/sh7760fb.txt
+
+1. Platform setup
+-----------------
+SH7760:
+ Video data is fetched via the DMABRG DMA engine, so you have to
+ configure the SH DMAC for DMABRG mode (write 0x94808080 to the
+ DMARSRA register somewhere at boot).
+
+ PFC registers PCCR and PCDR must be set to peripheral mode.
+ (write zeros to both).
+
+The driver does NOT do the above for you since board setup is, well, job
+of the board setup code.
+
+2. Panel definitions
+--------------------
+The LCDC must explicitly be told about the type of LCD panel
+attached. Data must be wrapped in a "struct sh7760fb_platdata" and
+passed to the driver as platform_data.
+
+Suggest you take a closer look at the SH7760 Manual, Section 30.
+(http://documentation.renesas.com/eng/products/mpumcu/e602291_sh7760.pdf)
+
+The following code illustrates what needs to be done to
+get the framebuffer working on a 640x480 TFT:
+
+====================== cut here ======================================
+
+#include <linux/fb.h>
+#include <asm/sh7760fb.h>
+
+/*
+ * NEC NL6440bc26-01 640x480 TFT
+ * dotclock 25175 kHz
+ * Xres 640 Yres 480
+ * Htotal 800 Vtotal 525
+ * HsynStart 656 VsynStart 490
+ * HsynLenn 30 VsynLenn 2
+ *
+ * The linux framebuffer layer does not use the syncstart/synclen
+ * values but right/left/upper/lower margin values. The comments
+ * for the x_margin explain how to calculate those from given
+ * panel sync timings.
+ */
+static struct fb_videomode nl6448bc26 = {
+ .name = "NL6448BC26",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = 39683, /* in picoseconds! */
+ .hsync_len = 30,
+ .vsync_len = 2,
+ .left_margin = 114, /* HTOT - (HSYNSLEN + HSYNSTART) */
+ .right_margin = 16, /* HSYNSTART - XRES */
+ .upper_margin = 33, /* VTOT - (VSYNLEN + VSYNSTART) */
+ .lower_margin = 10, /* VSYNSTART - YRES */
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct sh7760fb_platdata sh7760fb_nl6448 = {
+ .def_mode = &nl6448bc26,
+ .ldmtr = LDMTR_TFT_COLOR_16, /* 16bit TFT panel */
+ .lddfr = LDDFR_8BPP, /* we want 8bit output */
+ .ldpmmr = 0x0070,
+ .ldpspr = 0x0500,
+ .ldaclnr = 0,
+ .ldickr = LDICKR_CLKSRC(LCDC_CLKSRC_EXTERNAL) |
+ LDICKR_CLKDIV(1),
+ .rotate = 0,
+ .novsync = 1,
+ .blank = NULL,
+};
+
+/* SH7760:
+ * 0xFE300800: 256 * 4byte xRGB palette ram
+ * 0xFE300C00: 42 bytes ctrl registers
+ */
+static struct resource sh7760_lcdc_res[] = {
+ [0] = {
+ .start = 0xFE300800,
+ .end = 0xFE300CFF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 65,
+ .end = 65,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sh7760_lcdc_dev = {
+ .dev = {
+ .platform_data = &sh7760fb_nl6448,
+ },
+ .name = "sh7760-lcdc",
+ .id = -1,
+ .resource = sh7760_lcdc_res,
+ .num_resources = ARRAY_SIZE(sh7760_lcdc_res),
+};
+
+====================== cut here ======================================
diff --git a/Documentation/fb/tridentfb.txt b/Documentation/fb/tridentfb.txt
index 8a6c8a43e6a..45d9de5b13a 100644
--- a/Documentation/fb/tridentfb.txt
+++ b/Documentation/fb/tridentfb.txt
@@ -3,11 +3,25 @@ Tridentfb is a framebuffer driver for some Trident chip based cards.
The following list of chips is thought to be supported although not all are
tested:
-those from the Image series with Cyber in their names - accelerated
-those with Blade in their names (Blade3D,CyberBlade...) - accelerated
-the newer CyberBladeXP family - nonaccelerated
-
-Only PCI/AGP based cards are supported, none of the older Tridents.
+those from the TGUI series 9440/96XX and with Cyber in their names
+those from the Image series and with Cyber in their names
+those with Blade in their names (Blade3D,CyberBlade...)
+the newer CyberBladeXP family
+
+All families are accelerated. Only PCI/AGP based cards are supported,
+none of the older Tridents.
+The driver supports 8, 16 and 32 bits per pixel depths.
+The TGUI family requires a line length to be power of 2 if acceleration
+is enabled. This means that range of possible resolutions and bpp is
+limited comparing to the range if acceleration is disabled (see list
+of parameters below).
+
+Known bugs:
+1. The driver randomly locks up on 3DImage975 chip with acceleration
+ enabled. The same happens in X11 (Xorg).
+2. The ramdac speeds require some more fine tuning. It is possible to
+ switch resolution which the chip does not support at some depths for
+ older chips.
How to use it?
==============
@@ -17,12 +31,11 @@ video=tridentfb
The parameters for tridentfb are concatenated with a ':' as in this example.
-video=tridentfb:800x600,bpp=16,noaccel
+video=tridentfb:800x600-16@75,noaccel
The second level parameters that tridentfb understands are:
noaccel - turns off acceleration (when it doesn't work for your card)
-accel - force text acceleration (for boards which by default are noacceled)
fp - use flat panel related stuff
crt - assume monitor is present instead of fp
@@ -31,21 +44,24 @@ center - for flat panels and resolutions smaller than native size center the
image, otherwise use
stretch
-memsize - integer value in Kb, use if your card's memory size is misdetected.
+memsize - integer value in KB, use if your card's memory size is misdetected.
look at the driver output to see what it says when initializing.
-memdiff - integer value in Kb,should be nonzero if your card reports
- more memory than it actually has.For instance mine is 192K less than
+
+memdiff - integer value in KB, should be nonzero if your card reports
+ more memory than it actually has. For instance mine is 192K less than
detection says in all three BIOS selectable situations 2M, 4M, 8M.
Only use if your video memory is taken from main memory hence of
- configurable size.Otherwise use memsize.
- If in some modes which barely fit the memory you see garbage at the bottom
- this might help by not letting change to that mode anymore.
+ configurable size. Otherwise use memsize.
+ If in some modes which barely fit the memory you see garbage
+ at the bottom this might help by not letting change to that mode
+ anymore.
nativex - the width in pixels of the flat panel.If you know it (usually 1024
800 or 1280) and it is not what the driver seems to detect use it.
-bpp - bits per pixel (8,16 or 32)
-mode - a mode name like 800x600 (as described in Documentation/fb/modedb.txt)
+bpp - bits per pixel (8,16 or 32)
+mode - a mode name like 800x600-8@75 as described in
+ Documentation/fb/modedb.txt
Using insane values for the above parameters will probably result in driver
misbehaviour so take care(for instance memsize=12345678 or memdiff=23784 or
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 9f73587219e..721c71b86e0 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -138,24 +138,6 @@ Who: Kay Sievers <kay.sievers@suse.de>
---------------------------
-What: find_task_by_pid
-When: 2.6.26
-Why: With pid namespaces, calling this funciton will return the
- wrong task when called from inside a namespace.
-
- The best way to save a task pid and find a task by this
- pid later, is to find this task's struct pid pointer (or get
- it directly from the task) and call pid_task() later.
-
- If someone really needs to get a task by its pid_t, then
- he most likely needs the find_task_by_vpid() to get the
- task from the same namespace as the current task is in, but
- this may be not so in general.
-
-Who: Pavel Emelyanov <xemul@openvz.org>
-
----------------------------
-
What: ACPI procfs interface
When: July 2008
Why: ACPI sysfs conversion should be finished by January 2008.
@@ -300,14 +282,6 @@ Who: ocfs2-devel@oss.oracle.com
---------------------------
-What: asm/semaphore.h
-When: 2.6.26
-Why: Implementation became generic; users should now include
- linux/semaphore.h instead.
-Who: Matthew Wilcox <willy@linux.intel.com>
-
----------------------------
-
What: SCTP_GET_PEER_ADDRS_NUM_OLD, SCTP_GET_PEER_ADDRS_OLD,
SCTP_GET_LOCAL_ADDRS_NUM_OLD, SCTP_GET_LOCAL_ADDRS_OLD
When: June 2009
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 8b22d7d8b99..680fb566b92 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -510,6 +510,7 @@ prototypes:
void (*close)(struct vm_area_struct*);
int (*fault)(struct vm_area_struct*, struct vm_fault *);
int (*page_mkwrite)(struct vm_area_struct *, struct page *);
+ int (*access)(struct vm_area_struct *, unsigned long, void*, int, int);
locking rules:
BKL mmap_sem PageLocked(page)
@@ -517,6 +518,7 @@ open: no yes
close: no yes
fault: no yes
page_mkwrite: no yes no
+access: no yes
->page_mkwrite() is called when a previously read-only page is
about to become writeable. The file system is responsible for
@@ -525,6 +527,11 @@ taking to lock out truncate, the page range should be verified to be
within i_size. The page mapping should also be checked that it is not
NULL.
+ ->access() is called when get_user_pages() fails in
+acces_process_vm(), typically used to debug a process through
+/proc/pid/mem or ptrace. This function is needed only for
+VM_IO | VM_PFNMAP VMAs.
+
================================================================================
Dubious stuff
diff --git a/Documentation/filesystems/bfs.txt b/Documentation/filesystems/bfs.txt
index ea825e178e7..78043d5a8fc 100644
--- a/Documentation/filesystems/bfs.txt
+++ b/Documentation/filesystems/bfs.txt
@@ -26,11 +26,11 @@ You can simplify mounting by just typing:
this will allocate the first available loopback device (and load loop.o
kernel module if necessary) automatically. If the loopback driver is not
-loaded automatically, make sure that your kernel is compiled with kmod
-support (CONFIG_KMOD) enabled. Beware that umount will not
-deallocate /dev/loopN device if /etc/mtab file on your system is a
-symbolic link to /proc/mounts. You will need to do it manually using
-"-d" switch of losetup(8). Read losetup(8) manpage for more info.
+loaded automatically, make sure that you have compiled the module and
+that modprobe is functioning. Beware that umount will not deallocate
+/dev/loopN device if /etc/mtab file on your system is a symbolic link to
+/proc/mounts. You will need to do it manually using "-d" switch of
+losetup(8). Read losetup(8) manpage for more info.
To create the BFS image under UnixWare you need to find out first which
slice contains it. The command prtvtoc(1M) is your friend:
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 7f268f327d7..8c6384bdfed 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -296,6 +296,7 @@ Table 1-4: Kernel info in /proc
uptime System uptime
version Kernel version
video bttv info of video resources (2.4)
+ vmallocinfo Show vmalloced areas
..............................................................................
You can, for example, check which interrupts are currently in use and what
@@ -557,6 +558,49 @@ VmallocTotal: total size of vmalloc memory area
VmallocUsed: amount of vmalloc area which is used
VmallocChunk: largest contigious block of vmalloc area which is free
+..............................................................................
+
+vmallocinfo:
+
+Provides information about vmalloced/vmaped areas. One line per area,
+containing the virtual address range of the area, size in bytes,
+caller information of the creator, and optional information depending
+on the kind of area :
+
+ pages=nr number of pages
+ phys=addr if a physical address was specified
+ ioremap I/O mapping (ioremap() and friends)
+ vmalloc vmalloc() area
+ vmap vmap()ed pages
+ user VM_USERMAP area
+ vpages buffer for pages pointers was vmalloced (huge area)
+ N<node>=nr (Only on NUMA kernels)
+ Number of pages allocated on memory node <node>
+
+> cat /proc/vmallocinfo
+0xffffc20000000000-0xffffc20000201000 2101248 alloc_large_system_hash+0x204 ...
+ /0x2c0 pages=512 vmalloc N0=128 N1=128 N2=128 N3=128
+0xffffc20000201000-0xffffc20000302000 1052672 alloc_large_system_hash+0x204 ...
+ /0x2c0 pages=256 vmalloc N0=64 N1=64 N2=64 N3=64
+0xffffc20000302000-0xffffc20000304000 8192 acpi_tb_verify_table+0x21/0x4f...
+ phys=7fee8000 ioremap
+0xffffc20000304000-0xffffc20000307000 12288 acpi_tb_verify_table+0x21/0x4f...
+ phys=7fee7000 ioremap
+0xffffc2000031d000-0xffffc2000031f000 8192 init_vdso_vars+0x112/0x210
+0xffffc2000031f000-0xffffc2000032b000 49152 cramfs_uncompress_init+0x2e ...
+ /0x80 pages=11 vmalloc N0=3 N1=3 N2=2 N3=3
+0xffffc2000033a000-0xffffc2000033d000 12288 sys_swapon+0x640/0xac0 ...
+ pages=2 vmalloc N1=2
+0xffffc20000347000-0xffffc2000034c000 20480 xt_alloc_table_info+0xfe ...
+ /0x130 [x_tables] pages=4 vmalloc N0=4
+0xffffffffa0000000-0xffffffffa000f000 61440 sys_init_module+0xc27/0x1d00 ...
+ pages=14 vmalloc N2=14
+0xffffffffa000f000-0xffffffffa0014000 20480 sys_init_module+0xc27/0x1d00 ...
+ pages=4 vmalloc N1=4
+0xffffffffa0014000-0xffffffffa0017000 12288 sys_init_module+0xc27/0x1d00 ...
+ pages=2 vmalloc N1=2
+0xffffffffa0017000-0xffffffffa0022000 45056 sys_init_module+0xc27/0x1d00 ...
+ pages=10 vmalloc N0=10
1.3 IDE devices in /proc/ide
----------------------------
diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
index 7f27b8f840d..9e9c348275a 100644
--- a/Documentation/filesystems/sysfs.txt
+++ b/Documentation/filesystems/sysfs.txt
@@ -248,6 +248,7 @@ The top level sysfs directory looks like:
block/
bus/
class/
+dev/
devices/
firmware/
net/
@@ -274,6 +275,11 @@ fs/ contains a directory for some filesystems. Currently each
filesystem wanting to export attributes must create its own hierarchy
below fs/ (see ./fuse.txt for an example).
+dev/ contains two directories char/ and block/. Inside these two
+directories there are symlinks named <major>:<minor>. These symlinks
+point to the sysfs directory for the given device. /sys/dev provides a
+quick way to lookup the sysfs interface for a device from the result of
+a stat(2) operation.
More information can driver-model specific features can be found in
Documentation/driver-model/.
diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt
index 2d5e1e582e1..bbac4f1d905 100644
--- a/Documentation/filesystems/vfat.txt
+++ b/Documentation/filesystems/vfat.txt
@@ -96,6 +96,14 @@ shortname=lower|win95|winnt|mixed
emulate the Windows 95 rule for create.
Default setting is `lower'.
+tz=UTC -- Interpret timestamps as UTC rather than local time.
+ This option disables the conversion of timestamps
+ between local time (as used by Windows on FAT) and UTC
+ (which Linux uses internally). This is particuluarly
+ useful when mounting devices (like digital cameras)
+ that are set to UTC in order to avoid the pitfalls of
+ local time.
+
<bool>: 0,1,yes,no,true,false
TODO
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
index c35ca9e40d4..18022e249c5 100644
--- a/Documentation/gpio.txt
+++ b/Documentation/gpio.txt
@@ -347,15 +347,12 @@ necessarily be nonportable.
Dynamic definition of GPIOs is not currently standard; for example, as
a side effect of configuring an add-on board with some GPIO expanders.
-These calls are purely for kernel space, but a userspace API could be built
-on top of them.
-
GPIO implementor's framework (OPTIONAL)
=======================================
As noted earlier, there is an optional implementation framework making it
easier for platforms to support different kinds of GPIO controller using
-the same programming interface.
+the same programming interface. This framework is called "gpiolib".
As a debugging aid, if debugfs is available a /sys/kernel/debug/gpio file
will be found there. That will list all the controllers registered through
@@ -392,11 +389,21 @@ either NULL or the label associated with that GPIO when it was requested.
Platform Support
----------------
-To support this framework, a platform's Kconfig will "select HAVE_GPIO_LIB"
+To support this framework, a platform's Kconfig will "select" either
+ARCH_REQUIRE_GPIOLIB or ARCH_WANT_OPTIONAL_GPIOLIB
and arrange that its <asm/gpio.h> includes <asm-generic/gpio.h> and defines
three functions: gpio_get_value(), gpio_set_value(), and gpio_cansleep().
They may also want to provide a custom value for ARCH_NR_GPIOS.
+ARCH_REQUIRE_GPIOLIB means that the gpio-lib code will always get compiled
+into the kernel on that architecture.
+
+ARCH_WANT_OPTIONAL_GPIOLIB means the gpio-lib code defaults to off and the user
+can enable it and build it into the kernel optionally.
+
+If neither of these options are selected, the platform does not support
+GPIOs through GPIO-lib and the code cannot be enabled by the user.
+
Trivial implementations of those functions can directly use framework
code, which always dispatches through the gpio_chip:
@@ -439,4 +446,120 @@ becomes available. That may mean the device should not be registered until
calls for that GPIO can work. One way to address such dependencies is for
such gpio_chip controllers to provide setup() and teardown() callbacks to
board specific code; those board specific callbacks would register devices
-once all the necessary resources are available.
+once all the necessary resources are available, and remove them later when
+the GPIO controller device becomes unavailable.
+
+
+Sysfs Interface for Userspace (OPTIONAL)
+========================================
+Platforms which use the "gpiolib" implementors framework may choose to
+configure a sysfs user interface to GPIOs. This is different from the
+debugfs interface, since it provides control over GPIO direction and
+value instead of just showing a gpio state summary. Plus, it could be
+present on production systems without debugging support.
+
+Given approprate hardware documentation for the system, userspace could
+know for example that GPIO #23 controls the write protect line used to
+protect boot loader segments in flash memory. System upgrade procedures
+may need to temporarily remove that protection, first importing a GPIO,
+then changing its output state, then updating the code before re-enabling
+the write protection. In normal use, GPIO #23 would never be touched,
+and the kernel would have no need to know about it.
+
+Again depending on appropriate hardware documentation, on some systems
+userspace GPIO can be used to determine system configuration data that
+standard kernels won't know about. And for some tasks, simple userspace
+GPIO drivers could be all that the system really needs.
+
+Note that standard kernel drivers exist for common "LEDs and Buttons"
+GPIO tasks: "leds-gpio" and "gpio_keys", respectively. Use those
+instead of talking directly to the GPIOs; they integrate with kernel
+frameworks better than your userspace code could.
+
+
+Paths in Sysfs
+--------------
+There are three kinds of entry in /sys/class/gpio:
+
+ - Control interfaces used to get userspace control over GPIOs;
+
+ - GPIOs themselves; and
+
+ - GPIO controllers ("gpio_chip" instances).
+
+That's in addition to standard files including the "device" symlink.
+
+The control interfaces are write-only:
+
+ /sys/class/gpio/
+
+ "export" ... Userspace may ask the kernel to export control of
+ a GPIO to userspace by writing its number to this file.
+
+ Example: "echo 19 > export" will create a "gpio19" node
+ for GPIO #19, if that's not requested by kernel code.
+
+ "unexport" ... Reverses the effect of exporting to userspace.
+
+ Example: "echo 19 > unexport" will remove a "gpio19"
+ node exported using the "export" file.
+
+GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
+and have the following read/write attributes:
+
+ /sys/class/gpio/gpioN/
+
+ "direction" ... reads as either "in" or "out". This value may
+ normally be written. Writing as "out" defaults to
+ initializing the value as low. To ensure glitch free
+ operation, values "low" and "high" may be written to
+ configure the GPIO as an output with that initial value.
+
+ Note that this attribute *will not exist* if the kernel
+ doesn't support changing the direction of a GPIO, or
+ it was exported by kernel code that didn't explicitly
+ allow userspace to reconfigure this GPIO's direction.
+
+ "value" ... reads as either 0 (low) or 1 (high). If the GPIO
+ is configured as an output, this value may be written;
+ any nonzero value is treated as high.
+
+GPIO controllers have paths like /sys/class/gpio/chipchip42/ (for the
+controller implementing GPIOs starting at #42) and have the following
+read-only attributes:
+
+ /sys/class/gpio/gpiochipN/
+
+ "base" ... same as N, the first GPIO managed by this chip
+
+ "label" ... provided for diagnostics (not always unique)
+
+ "ngpio" ... how many GPIOs this manges (N to N + ngpio - 1)
+
+Board documentation should in most cases cover what GPIOs are used for
+what purposes. However, those numbers are not always stable; GPIOs on
+a daughtercard might be different depending on the base board being used,
+or other cards in the stack. In such cases, you may need to use the
+gpiochip nodes (possibly in conjunction with schematics) to determine
+the correct GPIO number to use for a given signal.
+
+
+Exporting from Kernel code
+--------------------------
+Kernel code can explicitly manage exports of GPIOs which have already been
+requested using gpio_request():
+
+ /* export the GPIO to userspace */
+ int gpio_export(unsigned gpio, bool direction_may_change);
+
+ /* reverse gpio_export() */
+ void gpio_unexport();
+
+After a kernel driver requests a GPIO, it may only be made available in
+the sysfs interface by gpio_export(). The driver can control whether the
+signal direction may change. This helps drivers prevent userspace code
+from accidentally clobbering important system state.
+
+This explicit exporting can help with debugging (by making some kinds
+of experiments easier), or can provide an always-there interface that's
+suitable for documenting as part of a board support package.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 30d44b78171..e7bea3e8530 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -87,7 +87,8 @@ parameter is applicable:
SH SuperH architecture is enabled.
SMP The kernel is an SMP kernel.
SPARC Sparc architecture is enabled.
- SWSUSP Software suspend is enabled.
+ SWSUSP Software suspend (hibernation) is enabled.
+ SUSPEND System suspend states are enabled.
TS Appropriate touchscreen support is enabled.
USB USB support is enabled.
USBHID USB Human Interface Device support is enabled.
@@ -147,10 +148,12 @@ and is between 256 and 4096 characters. It is defined in the file
default: 0
acpi_sleep= [HW,ACPI] Sleep options
- Format: { s3_bios, s3_mode, s3_beep, old_ordering }
+ Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig, old_ordering }
See Documentation/power/video.txt for s3_bios and s3_mode.
s3_beep is for debugging; it makes the PC's speaker beep
as soon as the kernel's real-mode entry point is called.
+ s4_nohwsig prevents ACPI hardware signature from being
+ used during resume from hibernation.
old_ordering causes the ACPI 1.0 ordering of the _PTS
control method, wrt putting devices into low power
states, to be enforced (the ACPI 2.0 ordering of _PTS is
@@ -774,8 +777,22 @@ and is between 256 and 4096 characters. It is defined in the file
hisax= [HW,ISDN]
See Documentation/isdn/README.HiSax.
- hugepages= [HW,X86-32,IA-64] Maximal number of HugeTLB pages.
- hugepagesz= [HW,IA-64,PPC] The size of the HugeTLB pages.
+ hugepages= [HW,X86-32,IA-64] HugeTLB pages to allocate at boot.
+ hugepagesz= [HW,IA-64,PPC,X86-64] The size of the HugeTLB pages.
+ On x86-64 and powerpc, this option can be specified
+ multiple times interleaved with hugepages= to reserve
+ huge pages of different sizes. Valid pages sizes on
+ x86-64 are 2M (when the CPU supports "pse") and 1G
+ (when the CPU supports the "pdpe1gb" cpuinfo flag)
+ Note that 1GB pages can only be allocated at boot time
+ using hugepages= and not freed afterwards.
+ default_hugepagesz=
+ [same as hugepagesz=] The size of the default
+ HugeTLB page size. This is the size represented by
+ the legacy /proc/ hugepages APIs, used for SHM, and
+ default size when mounting hugetlbfs filesystems.
+ Defaults to the default architecture's huge page size
+ if not specified.
i8042.direct [HW] Put keyboard port into non-translated mode
i8042.dumbkbd [HW] Pretend that controller can only read data from
@@ -1225,6 +1242,14 @@ and is between 256 and 4096 characters. It is defined in the file
mga= [HW,DRM]
+ mminit_loglevel=
+ [KNL] When CONFIG_DEBUG_MEMORY_INIT is set, this
+ parameter allows control of the logging verbosity for
+ the additional memory initialisation checks. A value
+ of 0 disables mminit logging and a level of 4 will
+ log everything. Information is printed at KERN_DEBUG
+ so loglevel=8 may also need to be specified.
+
mousedev.tap_time=
[MOUSE] Maximum time between finger touching and
leaving touchpad surface for touch to be considered
@@ -2034,6 +2059,9 @@ and is between 256 and 4096 characters. It is defined in the file
snd-ymfpci= [HW,ALSA]
+ softlockup_panic=
+ [KNL] Should the soft-lockup detector generate panics.
+
sonypi.*= [HW] Sony Programmable I/O Control Device driver
See Documentation/sonypi.txt
@@ -2098,6 +2126,12 @@ and is between 256 and 4096 characters. It is defined in the file
tdfx= [HW,DRM]
+ test_suspend= [SUSPEND]
+ Specify "mem" (for Suspend-to-RAM) or "standby" (for
+ standby suspend) as the system sleep state to briefly
+ enter during system startup. The system is woken from
+ this state using a wakeup-capable RTC alarm.
+
thash_entries= [KNL,NET]
Set number of hash buckets for TCP connection
@@ -2125,13 +2159,6 @@ and is between 256 and 4096 characters. It is defined in the file
<deci-seconds>: poll all this frequency
0: no polling (default)
- tipar.timeout= [HW,PPT]
- Set communications timeout in tenths of a second
- (default 15).
-
- tipar.delay= [HW,PPT]
- Set inter-bit delay in microseconds (default 10).
-
tmscsim= [HW,SCSI]
See comment before function dc390_setup() in
drivers/scsi/tmscsim.c.
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
index 64b3f146e4b..02dc748b76c 100644
--- a/Documentation/laptops/thinkpad-acpi.txt
+++ b/Documentation/laptops/thinkpad-acpi.txt
@@ -1,7 +1,7 @@
ThinkPad ACPI Extras Driver
- Version 0.20
- April 09th, 2008
+ Version 0.21
+ May 29th, 2008
Borislav Deianov <borislav@users.sf.net>
Henrique de Moraes Holschuh <hmh@hmh.eng.br>
@@ -621,7 +621,8 @@ Bluetooth
---------
procfs: /proc/acpi/ibm/bluetooth
-sysfs device attribute: bluetooth_enable
+sysfs device attribute: bluetooth_enable (deprecated)
+sysfs rfkill class: switch "tpacpi_bluetooth_sw"
This feature shows the presence and current state of a ThinkPad
Bluetooth device in the internal ThinkPad CDC slot.
@@ -643,8 +644,12 @@ Sysfs notes:
0: disables Bluetooth / Bluetooth is disabled
1: enables Bluetooth / Bluetooth is enabled.
- Note: this interface will be probably be superseded by the
- generic rfkill class, so it is NOT to be considered stable yet.
+ Note: this interface has been superseded by the generic rfkill
+ class. It has been deprecated, and it will be removed in year
+ 2010.
+
+ rfkill controller switch "tpacpi_bluetooth_sw": refer to
+ Documentation/rfkill.txt for details.
Video output control -- /proc/acpi/ibm/video
--------------------------------------------
@@ -1374,7 +1379,8 @@ EXPERIMENTAL: WAN
-----------------
procfs: /proc/acpi/ibm/wan
-sysfs device attribute: wwan_enable
+sysfs device attribute: wwan_enable (deprecated)
+sysfs rfkill class: switch "tpacpi_wwan_sw"
This feature is marked EXPERIMENTAL because the implementation
directly accesses hardware registers and may not work as expected. USE
@@ -1404,8 +1410,12 @@ Sysfs notes:
0: disables WWAN card / WWAN card is disabled
1: enables WWAN card / WWAN card is enabled.
- Note: this interface will be probably be superseded by the
- generic rfkill class, so it is NOT to be considered stable yet.
+ Note: this interface has been superseded by the generic rfkill
+ class. It has been deprecated, and it will be removed in year
+ 2010.
+
+ rfkill controller switch "tpacpi_wwan_sw": refer to
+ Documentation/rfkill.txt for details.
Multiple Commands, Module Parameters
------------------------------------
diff --git a/Documentation/moxa-smartio b/Documentation/moxa-smartio
index fe24ecc6372..5337e80a5b9 100644
--- a/Documentation/moxa-smartio
+++ b/Documentation/moxa-smartio
@@ -1,14 +1,22 @@
=============================================================================
-
- MOXA Smartio Family Device Driver Ver 1.1 Installation Guide
- for Linux Kernel 2.2.x and 2.0.3x
- Copyright (C) 1999, Moxa Technologies Co, Ltd.
+ MOXA Smartio/Industio Family Device Driver Installation Guide
+ for Linux Kernel 2.4.x, 2.6.x
+ Copyright (C) 2008, Moxa Inc.
=============================================================================
+Date: 01/21/2008
+
Content
1. Introduction
2. System Requirement
3. Installation
+ 3.1 Hardware installation
+ 3.2 Driver files
+ 3.3 Device naming convention
+ 3.4 Module driver configuration
+ 3.5 Static driver configuration for Linux kernel 2.4.x and 2.6.x.
+ 3.6 Custom configuration
+ 3.7 Verify driver installation
4. Utilities
5. Setserial
6. Troubleshooting
@@ -16,27 +24,48 @@ Content
-----------------------------------------------------------------------------
1. Introduction
- The Smartio family Linux driver, Ver. 1.1, supports following multiport
+ The Smartio/Industio/UPCI family Linux driver supports following multiport
boards.
- -C104P/H/HS, C104H/PCI, C104HS/PCI, CI-104J 4 port multiport board.
- -C168P/H/HS, C168H/PCI 8 port multiport board.
-
- This driver has been modified a little and cleaned up from the Moxa
- contributed driver code and merged into Linux 2.2.14pre. In particular
- official major/minor numbers have been assigned which are different to
- those the original Moxa supplied driver used.
+ - 2 ports multiport board
+ CP-102U, CP-102UL, CP-102UF
+ CP-132U-I, CP-132UL,
+ CP-132, CP-132I, CP132S, CP-132IS,
+ CI-132, CI-132I, CI-132IS,
+ (C102H, C102HI, C102HIS, C102P, CP-102, CP-102S)
+
+ - 4 ports multiport board
+ CP-104EL,
+ CP-104UL, CP-104JU,
+ CP-134U, CP-134U-I,
+ C104H/PCI, C104HS/PCI,
+ CP-114, CP-114I, CP-114S, CP-114IS, CP-114UL,
+ C104H, C104HS,
+ CI-104J, CI-104JS,
+ CI-134, CI-134I, CI-134IS,
+ (C114HI, CT-114I, C104P)
+ POS-104UL,
+ CB-114,
+ CB-134I
+
+ - 8 ports multiport board
+ CP-118EL, CP-168EL,
+ CP-118U, CP-168U,
+ C168H/PCI,
+ C168H, C168HS,
+ (C168P),
+ CB-108
This driver and installation procedure have been developed upon Linux Kernel
- 2.2.5 and backward compatible to 2.0.3x. This driver supports Intel x86 and
- Alpha hardware platform. In order to maintain compatibility, this version
- has also been properly tested with RedHat, OpenLinux, TurboLinux and
- S.u.S.E Linux. However, if compatibility problem occurs, please contact
- Moxa at support@moxa.com.tw.
+ 2.4.x and 2.6.x. This driver supports Intel x86 hardware platform. In order
+ to maintain compatibility, this version has also been properly tested with
+ RedHat, Mandrake, Fedora and S.u.S.E Linux. However, if compatibility problem
+ occurs, please contact Moxa at support@moxa.com.tw.
In addition to device driver, useful utilities are also provided in this
version. They are
- - msdiag Diagnostic program for detecting installed Moxa Smartio boards.
+ - msdiag Diagnostic program for displaying installed Moxa
+ Smartio/Industio boards.
- msmon Monitor program to observe data count and line status signals.
- msterm A simple terminal program which is useful in testing serial
ports.
@@ -47,8 +76,7 @@ Content
GNU General Public License in this version. Please refer to GNU General
Public License announcement in each source code file for more detail.
- In Moxa's ftp sites, you may always find latest driver at
- ftp://ftp.moxa.com or ftp://ftp.moxa.com.tw.
+ In Moxa's Web sites, you may always find latest driver at http://web.moxa.com.
This version of driver can be installed as Loadable Module (Module driver)
or built-in into kernel (Static driver). You may refer to following
@@ -61,8 +89,8 @@ Content
-----------------------------------------------------------------------------
2. System Requirement
- - Hardware platform: Intel x86 or Alpha machine
- - Kernel version: 2.0.3x or 2.2.x
+ - Hardware platform: Intel x86 machine
+ - Kernel version: 2.4.x or 2.6.x
- gcc version 2.72 or later
- Maximum 4 boards can be installed in combination
@@ -70,9 +98,18 @@ Content
3. Installation
3.1 Hardware installation
+ 3.2 Driver files
+ 3.3 Device naming convention
+ 3.4 Module driver configuration
+ 3.5 Static driver configuration for Linux kernel 2.4.x, 2.6.x.
+ 3.6 Custom configuration
+ 3.7 Verify driver installation
+
+
+ 3.1 Hardware installation
- There are two types of buses, ISA and PCI, for Smartio family multiport
- board.
+ There are two types of buses, ISA and PCI, for Smartio/Industio
+ family multiport board.
ISA board
---------
@@ -81,47 +118,57 @@ Content
installation procedure in User's Manual before proceed any further.
Please make sure the JP1 is open after the ISA board is set properly.
- PCI board
- ---------
+ PCI/UPCI board
+ --------------
You may need to adjust IRQ usage in BIOS to avoid from IRQ conflict
with other ISA devices. Please refer to hardware installation
procedure in User's Manual in advance.
- IRQ Sharing
+ PCI IRQ Sharing
-----------
Each port within the same multiport board shares the same IRQ. Up to
- 4 Moxa Smartio Family multiport boards can be installed together on
- one system and they can share the same IRQ.
+ 4 Moxa Smartio/Industio PCI Family multiport boards can be installed
+ together on one system and they can share the same IRQ.
+
- 3.2 Driver files and device naming convention
+ 3.2 Driver files
The driver file may be obtained from ftp, CD-ROM or floppy disk. The
first step, anyway, is to copy driver file "mxser.tgz" into specified
directory. e.g. /moxa. The execute commands as below.
+ # cd /
+ # mkdir moxa
# cd /moxa
- # tar xvf /dev/fd0
+ # tar xvf /dev/fd0
+
or
+
+ # cd /
+ # mkdir moxa
# cd /moxa
# cp /mnt/cdrom/<driver directory>/mxser.tgz .
# tar xvfz mxser.tgz
+
+ 3.3 Device naming convention
+
You may find all the driver and utilities files in /moxa/mxser.
Following installation procedure depends on the model you'd like to
- run the driver. If you prefer module driver, please refer to 3.3.
- If static driver is required, please refer to 3.4.
+ run the driver. If you prefer module driver, please refer to 3.4.
+ If static driver is required, please refer to 3.5.
Dialin and callout port
-----------------------
- This driver remains traditional serial device properties. There're
+ This driver remains traditional serial device properties. There are
two special file name for each serial port. One is dial-in port
which is named "ttyMxx". For callout port, the naming convention
is "cumxx".
Device naming when more than 2 boards installed
-----------------------------------------------
- Naming convention for each Smartio multiport board is pre-defined
- as below.
+ Naming convention for each Smartio/Industio multiport board is
+ pre-defined as below.
Board Num. Dial-in Port Callout port
1st board ttyM0 - ttyM7 cum0 - cum7
@@ -129,6 +176,12 @@ Content
3rd board ttyM16 - ttyM23 cum16 - cum23
4th board ttyM24 - ttym31 cum24 - cum31
+
+ !!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ Under Kernel 2.6 the cum Device is Obsolete. So use ttyM*
+ device instead.
+ !!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
Board sequence
--------------
This driver will activate ISA boards according to the parameter set
@@ -138,69 +191,131 @@ Content
For PCI boards, their sequence will be after ISA boards and C168H/PCI
has higher priority than C104H/PCI boards.
- 3.3 Module driver configuration
+ 3.4 Module driver configuration
Module driver is easiest way to install. If you prefer static driver
installation, please skip this paragraph.
- 1. Find "Makefile" in /moxa/mxser, then run
- # make install
+
+ ------------- Prepare to use the MOXA driver--------------------
+ 3.4.1 Create tty device with correct major number
+ Before using MOXA driver, your system must have the tty devices
+ which are created with driver's major number. We offer one shell
+ script "msmknod" to simplify the procedure.
+ This step is only needed to be executed once. But you still
+ need to do this procedure when:
+ a. You change the driver's major number. Please refer the "3.7"
+ section.
+ b. Your total installed MOXA boards number is changed. Maybe you
+ add/delete one MOXA board.
+ c. You want to change the tty name. This needs to modify the
+ shell script "msmknod"
+
+ The procedure is:
+ # cd /moxa/mxser/driver
+ # ./msmknod
+
+ This shell script will require the major number for dial-in
+ device and callout device to create tty device. You also need
+ to specify the total installed MOXA board number. Default major
+ numbers for dial-in device and callout device are 30, 35. If
+ you need to change to other number, please refer section "3.7"
+ for more detailed procedure.
+ Msmknod will delete any special files occupying the same device
+ naming.
+
+ 3.4.2 Build the MOXA driver and utilities
+ Before using the MOXA driver and utilities, you need compile the
+ all the source code. This step is only need to be executed once.
+ But you still re-compile the source code if you modify the source
+ code. For example, if you change the driver's major number (see
+ "3.7" section), then you need to do this step again.
+
+ Find "Makefile" in /moxa/mxser, then run
+
+ # make clean; make install
+
+ !!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!
+ For Red Hat 9, Red Hat Enterprise Linux AS3/ES3/WS3 & Fedora Core1:
+ # make clean; make installsp1
+
+ For Red Hat Enterprise Linux AS4/ES4/WS4:
+ # make clean; make installsp2
+ !!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!
The driver files "mxser.o" and utilities will be properly compiled
- and copied to system directories respectively.Then run
+ and copied to system directories respectively.
- # insmod mxser
+ ------------- Load MOXA driver--------------------
+ 3.4.3 Load the MOXA driver
- to activate the modular driver. You may run "lsmod" to check
- if "mxser.o" is activated.
+ # modprobe mxser <argument>
- 2. Create special files by executing "msmknod".
- # cd /moxa/mxser/driver
- # ./msmknod
+ will activate the module driver. You may run "lsmod" to check
+ if "mxser" is activated. If the MOXA board is ISA board, the
+ <argument> is needed. Please refer to section "3.4.5" for more
+ information.
+
+
+ ------------- Load MOXA driver on boot --------------------
+ 3.4.4 For the above description, you may manually execute
+ "modprobe mxser" to activate this driver and run
+ "rmmod mxser" to remove it.
+ However, it's better to have a boot time configuration to
+ eliminate manual operation. Boot time configuration can be
+ achieved by rc file. We offer one "rc.mxser" file to simplify
+ the procedure under "moxa/mxser/driver".
- Default major numbers for dial-in device and callout device are
- 174, 175. Msmknod will delete any special files occupying the same
- device naming.
+ But if you use ISA board, please modify the "modprobe ..." command
+ to add the argument (see "3.4.5" section). After modifying the
+ rc.mxser, please try to execute "/moxa/mxser/driver/rc.mxser"
+ manually to make sure the modification is ok. If any error
+ encountered, please try to modify again. If the modification is
+ completed, follow the below step.
- 3. Up to now, you may manually execute "insmod mxser" to activate
- this driver and run "rmmod mxser" to remove it. However, it's
- better to have a boot time configuration to eliminate manual
- operation.
- Boot time configuration can be achieved by rc file. Run following
- command for setting rc files.
+ Run following command for setting rc files.
# cd /moxa/mxser/driver
# cp ./rc.mxser /etc/rc.d
# cd /etc/rc.d
- You may have to modify part of the content in rc.mxser to specify
- parameters for ISA board. Please refer to rc.mxser for more detail.
- Find "rc.serial". If "rc.serial" doesn't exist, create it by vi.
- Add "rc.mxser" in last line. Next, open rc.local by vi
- and append following content.
+ Check "rc.serial" is existed or not. If "rc.serial" doesn't exist,
+ create it by vi, run "chmod 755 rc.serial" to change the permission.
+ Add "/etc/rc.d/rc.mxser" in last line,
- if [ -f /etc/rc.d/rc.serial ]; then
- sh /etc/rc.d/rc.serial
- fi
+ Reboot and check if moxa.o activated by "lsmod" command.
- 4. Reboot and check if mxser.o activated by "lsmod" command.
- 5. If you'd like to drive Smartio ISA boards in the system, you'll
- have to add parameter to specify CAP address of given board while
- activating "mxser.o". The format for parameters are as follows.
+ 3.4.5. If you'd like to drive Smartio/Industio ISA boards in the system,
+ you'll have to add parameter to specify CAP address of given
+ board while activating "mxser.o". The format for parameters are
+ as follows.
- insmod mxser ioaddr=0x???,0x???,0x???,0x???
+ modprobe mxser ioaddr=0x???,0x???,0x???,0x???
| | | |
| | | +- 4th ISA board
| | +------ 3rd ISA board
| +------------ 2nd ISA board
+------------------- 1st ISA board
- 3.4 Static driver configuration
+ 3.5 Static driver configuration for Linux kernel 2.4.x and 2.6.x
+
+ Note: To use static driver, you must install the linux kernel
+ source package.
+
+ 3.5.1 Backup the built-in driver in the kernel.
+ # cd /usr/src/linux/drivers/char
+ # mv mxser.c mxser.c.old
+
+ For Red Hat 7.x user, you need to create link:
+ # cd /usr/src
+ # ln -s linux-2.4 linux
- 1. Create link
+ 3.5.2 Create link
# cd /usr/src/linux/drivers/char
# ln -s /moxa/mxser/driver/mxser.c mxser.c
- 2. Add CAP address list for ISA boards
+ 3.5.3 Add CAP address list for ISA boards. For PCI boards user,
+ please skip this step.
+
In module mode, the CAP address for ISA board is given by
parameter. In static driver configuration, you'll have to
assign it within driver's source code. If you will not
@@ -222,73 +337,55 @@ Content
static int mxserBoardCAP[]
= {0x280, 0x180, 0x00, 0x00};
- 3. Modify tty_io.c
- # cd /usr/src/linux/drivers/char/
- # vi tty_io.c
- Find pty_init(), insert "mxser_init()" as
+ 3.5.4 Setup kernel configuration
- pty_init();
- mxser_init();
+ Configure the kernel:
- 4. Modify tty.h
- # cd /usr/src/linux/include/linux
- # vi tty.h
- Find extern int tty_init(void), insert "mxser_init()" as
+ # cd /usr/src/linux
+ # make menuconfig
- extern int tty_init(void);
- extern int mxser_init(void);
-
- 5. Modify Makefile
- # cd /usr/src/linux/drivers/char
- # vi Makefile
- Find L_OBJS := tty_io.o ...... random.o, add
- "mxser.o" at last of this line as
- L_OBJS := tty_io.o ....... mxser.o
+ You will go into a menu-driven system. Please select [Character
+ devices][Non-standard serial port support], enable the [Moxa
+ SmartIO support] driver with "[*]" for built-in (not "[M]"), then
+ select [Exit] to exit this program.
- 6. Rebuild kernel
- The following are for Linux kernel rebuilding,for your reference only.
+ 3.5.5 Rebuild kernel
+ The following are for Linux kernel rebuilding, for your
+ reference only.
For appropriate details, please refer to the Linux document.
- If 'lilo' utility is installed, please use 'make zlilo' to rebuild
- kernel. If 'lilo' is not installed, please follow the following steps.
-
a. cd /usr/src/linux
- b. make clean /* take a few minutes */
- c. make bzImage /* take probably 10-20 minutes */
- d. Backup original boot kernel. /* optional step */
- e. cp /usr/src/linux/arch/i386/boot/bzImage /boot/vmlinuz
+ b. make clean /* take a few minutes */
+ c. make dep /* take a few minutes */
+ d. make bzImage /* take probably 10-20 minutes */
+ e. make install /* copy boot image to correct position */
f. Please make sure the boot kernel (vmlinuz) is in the
- correct position. If you use 'lilo' utility, you should
- check /etc/lilo.conf 'image' item specified the path
- which is the 'vmlinuz' path, or you will load wrong
- (or old) boot kernel image (vmlinuz).
- g. chmod 400 /vmlinuz
- h. lilo
- i. rdev -R /vmlinuz 1
- j. sync
-
- Note that if the result of "make zImage" is ERROR, then you have to
- go back to Linux configuration Setup. Type "make config" in directory
- /usr/src/linux or "setup".
-
- Since system include file, /usr/src/linux/include/linux/interrupt.h,
- is modified each time the MOXA driver is installed, kernel rebuilding
- is inevitable. And it takes about 10 to 20 minutes depends on the
- machine.
-
- 7. Make utility
- # cd /moxa/mxser/utility
- # make install
-
- 8. Make special file
+ correct position.
+ g. If you use 'lilo' utility, you should check /etc/lilo.conf
+ 'image' item specified the path which is the 'vmlinuz' path,
+ or you will load wrong (or old) boot kernel image (vmlinuz).
+ After checking /etc/lilo.conf, please run "lilo".
+
+ Note that if the result of "make bzImage" is ERROR, then you have to
+ go back to Linux configuration Setup. Type "make menuconfig" in
+ directory /usr/src/linux.
+
+
+ 3.5.6 Make tty device and special file
# cd /moxa/mxser/driver
# ./msmknod
- 9. Reboot
+ 3.5.7 Make utility
+ # cd /moxa/mxser/utility
+ # make clean; make install
+
+ 3.5.8 Reboot
- 3.5 Custom configuration
+
+
+ 3.6 Custom configuration
Although this driver already provides you default configuration, you
- still can change the device name and major number.The instruction to
+ still can change the device name and major number. The instruction to
change these parameters are shown as below.
Change Device name
@@ -306,33 +403,37 @@ Content
2 free major numbers for this driver. There are 3 steps to change
major numbers.
- 1. Find free major numbers
+ 3.6.1 Find free major numbers
In /proc/devices, you may find all the major numbers occupied
in the system. Please select 2 major numbers that are available.
e.g. 40, 45.
- 2. Create special files
+ 3.6.2 Create special files
Run /moxa/mxser/driver/msmknod to create special files with
specified major numbers.
- 3. Modify driver with new major number
+ 3.6.3 Modify driver with new major number
Run vi to open /moxa/mxser/driver/mxser.c. Locate the line
contains "MXSERMAJOR". Change the content as below.
#define MXSERMAJOR 40
#define MXSERCUMAJOR 45
- 4. Run # make install in /moxa/mxser/driver.
+ 3.6.4 Run "make clean; make install" in /moxa/mxser/driver.
- 3.6 Verify driver installation
+ 3.7 Verify driver installation
You may refer to /var/log/messages to check the latest status
log reported by this driver whenever it's activated.
+
-----------------------------------------------------------------------------
4. Utilities
There are 3 utilities contained in this driver. They are msdiag, msmon and
msterm. These 3 utilities are released in form of source code. They should
be compiled into executable file and copied into /usr/bin.
+ Before using these utilities, please load driver (refer 3.4 & 3.5) and
+ make sure you had run the "msmknod" utility.
+
msdiag - Diagnostic
--------------------
- This utility provides the function to detect what Moxa Smartio multiport
- board exists in the system.
+ This utility provides the function to display what Moxa Smartio/Industio
+ board found by driver in the system.
msmon - Port Monitoring
-----------------------
@@ -353,12 +454,13 @@ Content
application, for example, sending AT command to a modem connected to the
port or used as a terminal for login purpose. Note that this is only a
dumb terminal emulation without handling full screen operation.
+
-----------------------------------------------------------------------------
5. Setserial
Supported Setserial parameters are listed as below.
- uart set UART type(16450-->disable FIFO, 16550A-->enable FIFO)
+ uart set UART type(16450-->disable FIFO, 16550A-->enable FIFO)
close_delay set the amount of time(in 1/100 of a second) that DTR
should be kept low while being closed.
closing_wait set the amount of time(in 1/100 of a second) that the
@@ -366,7 +468,13 @@ Content
being closed, before the receiver is disable.
spd_hi Use 57.6kb when the application requests 38.4kb.
spd_vhi Use 115.2kb when the application requests 38.4kb.
+ spd_shi Use 230.4kb when the application requests 38.4kb.
+ spd_warp Use 460.8kb when the application requests 38.4kb.
spd_normal Use 38.4kb when the application requests 38.4kb.
+ spd_cust Use the custom divisor to set the speed when the
+ application requests 38.4kb.
+ divisor This option set the custom divison.
+ baud_base This option set the base baud rate.
-----------------------------------------------------------------------------
6. Troubleshooting
@@ -375,8 +483,9 @@ Content
possible. If all the possible solutions fail, please contact our technical
support team to get more help.
- Error msg: More than 4 Moxa Smartio family boards found. Fifth board and
- after are ignored.
+
+ Error msg: More than 4 Moxa Smartio/Industio family boards found. Fifth board
+ and after are ignored.
Solution:
To avoid this problem, please unplug fifth and after board, because Moxa
driver supports up to 4 boards.
@@ -384,7 +493,7 @@ Content
Error msg: Request_irq fail, IRQ(?) may be conflict with another device.
Solution:
Other PCI or ISA devices occupy the assigned IRQ. If you are not sure
- which device causes the situation,please check /proc/interrupts to find
+ which device causes the situation, please check /proc/interrupts to find
free IRQ and simply change another free IRQ for Moxa board.
Error msg: Board #: C1xx Series(CAP=xxx) interrupt number invalid.
@@ -397,15 +506,18 @@ Content
Moxa ISA board needs an interrupt vector.Please refer to user's manual
"Hardware Installation" chapter to set interrupt vector.
- Error msg: Couldn't install MOXA Smartio family driver!
+ Error msg: Couldn't install MOXA Smartio/Industio family driver!
Solution:
Load Moxa driver fail, the major number may conflict with other devices.
- Please refer to previous section 3.5 to change a free major number for
+ Please refer to previous section 3.7 to change a free major number for
Moxa driver.
- Error msg: Couldn't install MOXA Smartio family callout driver!
+ Error msg: Couldn't install MOXA Smartio/Industio family callout driver!
Solution:
Load Moxa callout driver fail, the callout device major number may
- conflict with other devices. Please refer to previous section 3.5 to
+ conflict with other devices. Please refer to previous section 3.7 to
change a free callout device major number for Moxa driver.
+
+
-----------------------------------------------------------------------------
+
diff --git a/Documentation/networking/e1000.txt b/Documentation/networking/e1000.txt
index 61b171cf531..2df71861e57 100644
--- a/Documentation/networking/e1000.txt
+++ b/Documentation/networking/e1000.txt
@@ -513,21 +513,11 @@ Additional Configurations
Intel(R) PRO/1000 PT Dual Port Server Connection
Intel(R) PRO/1000 PT Dual Port Server Adapter
Intel(R) PRO/1000 PF Dual Port Server Adapter
- Intel(R) PRO/1000 PT Quad Port Server Adapter
+ Intel(R) PRO/1000 PT Quad Port Server Adapter
NAPI
----
- NAPI (Rx polling mode) is supported in the e1000 driver. NAPI is enabled
- or disabled based on the configuration of the kernel. To override
- the default, use the following compile-time flags.
-
- To enable NAPI, compile the driver module, passing in a configuration option:
-
- make CFLAGS_EXTRA=-DE1000_NAPI install
-
- To disable NAPI, compile the driver module, passing in a configuration option:
-
- make CFLAGS_EXTRA=-DE1000_NO_NAPI install
+ NAPI (Rx polling mode) is enabled in the e1000 driver.
See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI.
diff --git a/Documentation/networking/udplite.txt b/Documentation/networking/udplite.txt
index 3870f280280..855d8da57a2 100644
--- a/Documentation/networking/udplite.txt
+++ b/Documentation/networking/udplite.txt
@@ -148,7 +148,7 @@
getsockopt(sockfd, SOL_SOCKET, SO_NO_CHECK, &value, ...);
is meaningless (as in TCP). Packets with a zero checksum field are
- illegal (cf. RFC 3828, sec. 3.1) will be silently discarded.
+ illegal (cf. RFC 3828, sec. 3.1) and will be silently discarded.
4) Fragmentation
diff --git a/Documentation/power/00-INDEX b/Documentation/power/00-INDEX
index a55d7f1c836..fb742c213c9 100644
--- a/Documentation/power/00-INDEX
+++ b/Documentation/power/00-INDEX
@@ -1,5 +1,7 @@
00-INDEX
- This file
+apm-acpi.txt
+ - basic info about the APM and ACPI support.
basic-pm-debugging.txt
- Debugging suspend and resume
devices.txt
@@ -14,8 +16,6 @@ notifiers.txt
- Registering suspend notifiers in device drivers
pci.txt
- How the PCI Subsystem Does Power Management
-pm.txt
- - info on Linux power management support.
pm_qos_interface.txt
- info on Linux PM Quality of Service interface
power_supply_class.txt
diff --git a/Documentation/power/apm-acpi.txt b/Documentation/power/apm-acpi.txt
new file mode 100644
index 00000000000..1bd799dc17e
--- /dev/null
+++ b/Documentation/power/apm-acpi.txt
@@ -0,0 +1,32 @@
+APM or ACPI?
+------------
+If you have a relatively recent x86 mobile, desktop, or server system,
+odds are it supports either Advanced Power Management (APM) or
+Advanced Configuration and Power Interface (ACPI). ACPI is the newer
+of the two technologies and puts power management in the hands of the
+operating system, allowing for more intelligent power management than
+is possible with BIOS controlled APM.
+
+The best way to determine which, if either, your system supports is to
+build a kernel with both ACPI and APM enabled (as of 2.3.x ACPI is
+enabled by default). If a working ACPI implementation is found, the
+ACPI driver will override and disable APM, otherwise the APM driver
+will be used.
+
+No, sorry, you cannot have both ACPI and APM enabled and running at
+once. Some people with broken ACPI or broken APM implementations
+would like to use both to get a full set of working features, but you
+simply cannot mix and match the two. Only one power management
+interface can be in control of the machine at once. Think about it..
+
+User-space Daemons
+------------------
+Both APM and ACPI rely on user-space daemons, apmd and acpid
+respectively, to be completely functional. Obtain both of these
+daemons from your Linux distribution or from the Internet (see below)
+and be sure that they are started sometime in the system boot process.
+Go ahead and start both. If ACPI or APM is not available on your
+system the associated daemon will exit gracefully.
+
+ apmd: http://worldvisions.ca/~apenwarr/apmd/
+ acpid: http://acpid.sf.net/
diff --git a/Documentation/power/pm.txt b/Documentation/power/pm.txt
deleted file mode 100644
index be841507e43..00000000000
--- a/Documentation/power/pm.txt
+++ /dev/null
@@ -1,257 +0,0 @@
- Linux Power Management Support
-
-This document briefly describes how to use power management with your
-Linux system and how to add power management support to Linux drivers.
-
-APM or ACPI?
-------------
-If you have a relatively recent x86 mobile, desktop, or server system,
-odds are it supports either Advanced Power Management (APM) or
-Advanced Configuration and Power Interface (ACPI). ACPI is the newer
-of the two technologies and puts power management in the hands of the
-operating system, allowing for more intelligent power management than
-is possible with BIOS controlled APM.
-
-The best way to determine which, if either, your system supports is to
-build a kernel with both ACPI and APM enabled (as of 2.3.x ACPI is
-enabled by default). If a working ACPI implementation is found, the
-ACPI driver will override and disable APM, otherwise the APM driver
-will be used.
-
-No, sorry, you cannot have both ACPI and APM enabled and running at
-once. Some people with broken ACPI or broken APM implementations
-would like to use both to get a full set of working features, but you
-simply cannot mix and match the two. Only one power management
-interface can be in control of the machine at once. Think about it..
-
-User-space Daemons
-------------------
-Both APM and ACPI rely on user-space daemons, apmd and acpid
-respectively, to be completely functional. Obtain both of these
-daemons from your Linux distribution or from the Internet (see below)
-and be sure that they are started sometime in the system boot process.
-Go ahead and start both. If ACPI or APM is not available on your
-system the associated daemon will exit gracefully.
-
- apmd: http://worldvisions.ca/~apenwarr/apmd/
- acpid: http://acpid.sf.net/
-
-Driver Interface -- OBSOLETE, DO NOT USE!
-----------------*************************
-
-Note: pm_register(), pm_access(), pm_dev_idle() and friends are
-obsolete. Please do not use them. Instead you should properly hook
-your driver into the driver model, and use its suspend()/resume()
-callbacks to do this kind of stuff.
-
-If you are writing a new driver or maintaining an old driver, it
-should include power management support. Without power management
-support, a single driver may prevent a system with power management
-capabilities from ever being able to suspend (safely).
-
-Overview:
-1) Register each instance of a device with "pm_register"
-2) Call "pm_access" before accessing the hardware.
- (this will ensure that the hardware is awake and ready)
-3) Your "pm_callback" is called before going into a
- suspend state (ACPI D1-D3) or after resuming (ACPI D0)
- from a suspend.
-4) Call "pm_dev_idle" when the device is not being used
- (optional but will improve device idle detection)
-5) When unloaded, unregister the device with "pm_unregister"
-
-/*
- * Description: Register a device with the power-management subsystem
- *
- * Parameters:
- * type - device type (PCI device, system device, ...)
- * id - instance number or unique identifier
- * cback - request handler callback (suspend, resume, ...)
- *
- * Returns: Registered PM device or NULL on error
- *
- * Examples:
- * dev = pm_register(PM_SYS_DEV, PM_SYS_VGA, vga_callback);
- *
- * struct pci_dev *pci_dev = pci_find_dev(...);
- * dev = pm_register(PM_PCI_DEV, PM_PCI_ID(pci_dev), callback);
- */
-struct pm_dev *pm_register(pm_dev_t type, unsigned long id, pm_callback cback);
-
-/*
- * Description: Unregister a device with the power management subsystem
- *
- * Parameters:
- * dev - PM device previously returned from pm_register
- */
-void pm_unregister(struct pm_dev *dev);
-
-/*
- * Description: Unregister all devices with a matching callback function
- *
- * Parameters:
- * cback - previously registered request callback
- *
- * Notes: Provided for easier porting from old APM interface
- */
-void pm_unregister_all(pm_callback cback);
-
-/*
- * Power management request callback
- *
- * Parameters:
- * dev - PM device previously returned from pm_register
- * rqst - request type
- * data - data, if any, associated with the request
- *
- * Returns: 0 if the request is successful
- * EINVAL if the request is not supported
- * EBUSY if the device is now busy and cannot handle the request
- * ENOMEM if the device was unable to handle the request due to memory
- *
- * Details: The device request callback will be called before the
- * device/system enters a suspend state (ACPI D1-D3) or
- * or after the device/system resumes from suspend (ACPI D0).
- * For PM_SUSPEND, the ACPI D-state being entered is passed
- * as the "data" argument to the callback. The device
- * driver should save (PM_SUSPEND) or restore (PM_RESUME)
- * device context when the request callback is called.
- *
- * Once a driver returns 0 (success) from a suspend
- * request, it should not process any further requests or
- * access the device hardware until a call to "pm_access" is made.
- */
-typedef int (*pm_callback)(struct pm_dev *dev, pm_request_t rqst, void *data);
-
-Driver Details
---------------
-This is just a quick Q&A as a stopgap until a real driver writers'
-power management guide is available.
-
-Q: When is a device suspended?
-
-Devices can be suspended based on direct user request (eg. laptop lid
-closes), system power policy (eg. sleep after 30 minutes of console
-inactivity), or device power policy (eg. power down device after 5
-minutes of inactivity)
-
-Q: Must a driver honor a suspend request?
-
-No, a driver can return -EBUSY from a suspend request and this
-will stop the system from suspending. When a suspend request
-fails, all suspended devices are resumed and the system continues
-to run. Suspend can be retried at a later time.
-
-Q: Can the driver block suspend/resume requests?
-
-Yes, a driver can delay its return from a suspend or resume
-request until the device is ready to handle requests. It
-is advantageous to return as quickly as possible from a
-request as suspend/resume are done serially.
-
-Q: What context is a suspend/resume initiated from?
-
-A suspend or resume is initiated from a kernel thread context.
-It is safe to block, allocate memory, initiate requests
-or anything else you can do within the kernel.
-
-Q: Will requests continue to arrive after a suspend?
-
-Possibly. It is the driver's responsibility to queue(*),
-fail, or drop any requests that arrive after returning
-success to a suspend request. It is important that the
-driver not access its device until after it receives
-a resume request as the device's bus may no longer
-be active.
-
-(*) If a driver queues requests for processing after
- resume be aware that the device, network, etc.
- might be in a different state than at suspend time.
- It's probably better to drop requests unless
- the driver is a storage device.
-
-Q: Do I have to manage bus-specific power management registers
-
-No. It is the responsibility of the bus driver to manage
-PCI, USB, etc. power management registers. The bus driver
-or the power management subsystem will also enable any
-wake-on functionality that the device has.
-
-Q: So, really, what do I need to do to support suspend/resume?
-
-You need to save any device context that would
-be lost if the device was powered off and then restore
-it at resume time. When ACPI is active, there are
-three levels of device suspend states; D1, D2, and D3.
-(The suspend state is passed as the "data" argument
-to the device callback.) With D3, the device is powered
-off and loses all context, D1 and D2 are shallower power
-states and require less device context to be saved. To
-play it safe, just save everything at suspend and restore
-everything at resume.
-
-Q: Where do I store device context for suspend?
-
-Anywhere in memory, kmalloc a buffer or store it
-in the device descriptor. You are guaranteed that the
-contents of memory will be restored and accessible
-before resume, even when the system suspends to disk.
-
-Q: What do I need to do for ACPI vs. APM vs. etc?
-
-Drivers need not be aware of the specific power management
-technology that is active. They just need to be aware
-of when the overlying power management system requests
-that they suspend or resume.
-
-Q: What about device dependencies?
-
-When a driver registers a device, the power management
-subsystem uses the information provided to build a
-tree of device dependencies (eg. USB device X is on
-USB controller Y which is on PCI bus Z) When power
-management wants to suspend a device, it first sends
-a suspend request to its driver, then the bus driver,
-and so on up to the system bus. Device resumes
-proceed in the opposite direction.
-
-Q: Who do I contact for additional information about
- enabling power management for my specific driver/device?
-
-ACPI Development mailing list: linux-acpi@vger.kernel.org
-
-System Interface -- OBSOLETE, DO NOT USE!
-----------------*************************
-If you are providing new power management support to Linux (ie.
-adding support for something like APM or ACPI), you should
-communicate with drivers through the existing generic power
-management interface.
-
-/*
- * Send a request to all devices
- *
- * Parameters:
- * rqst - request type
- * data - data, if any, associated with the request
- *
- * Returns: 0 if the request is successful
- * See "pm_callback" return for errors
- *
- * Details: Walk list of registered devices and call pm_send
- * for each until complete or an error is encountered.
- * If an error is encountered for a suspend request,
- * return all devices to the state they were in before
- * the suspend request.
- */
-int pm_send_all(pm_request_t rqst, void *data);
-
-/*
- * Find a matching device
- *
- * Parameters:
- * type - device type (PCI device, system device, or 0 to match all devices)
- * from - previous match or NULL to start from the beginning
- *
- * Returns: Matching device or NULL if none found
- */
-struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from);
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index aee243a846a..99514ced82c 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -59,6 +59,7 @@ Table of Contents
p) Freescale Synchronous Serial Interface
q) USB EHCI controllers
r) MDIO on GPIOs
+ s) SPI busses
VII - Marvell Discovery mv64[345]6x System Controller chips
1) The /system-controller node
@@ -89,10 +90,12 @@ Table of Contents
3) OpenPIC Interrupt Controllers
4) ISA Interrupt Controllers
- VIII - Specifying GPIO information for devices
+ IX - Specifying GPIO information for devices
1) gpios property
2) gpio-controller nodes
+ X - Specifying device power management information (sleep property)
+
Appendix A - Sample SOC node for MPC8540
@@ -1881,6 +1884,62 @@ platforms are moved over to use the flattened-device-tree model.
&qe_pio_c 6>;
};
+ s) SPI (Serial Peripheral Interface) busses
+
+ SPI busses can be described with a node for the SPI master device
+ and a set of child nodes for each SPI slave on the bus. For this
+ discussion, it is assumed that the system's SPI controller is in
+ SPI master mode. This binding does not describe SPI controllers
+ in slave mode.
+
+ The SPI master node requires the following properties:
+ - #address-cells - number of cells required to define a chip select
+ address on the SPI bus.
+ - #size-cells - should be zero.
+ - compatible - name of SPI bus controller following generic names
+ recommended practice.
+ No other properties are required in the SPI bus node. It is assumed
+ that a driver for an SPI bus device will understand that it is an SPI bus.
+ However, the binding does not attempt to define the specific method for
+ assigning chip select numbers. Since SPI chip select configuration is
+ flexible and non-standardized, it is left out of this binding with the
+ assumption that board specific platform code will be used to manage
+ chip selects. Individual drivers can define additional properties to
+ support describing the chip select layout.
+
+ SPI slave nodes must be children of the SPI master node and can
+ contain the following properties.
+ - reg - (required) chip select address of device.
+ - compatible - (required) name of SPI device following generic names
+ recommended practice
+ - spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz
+ - spi-cpol - (optional) Empty property indicating device requires
+ inverse clock polarity (CPOL) mode
+ - spi-cpha - (optional) Empty property indicating device requires
+ shifted clock phase (CPHA) mode
+
+ SPI example for an MPC5200 SPI bus:
+ spi@f00 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
+ reg = <0xf00 0x20>;
+ interrupts = <2 13 0 2 14 0>;
+ interrupt-parent = <&mpc5200_pic>;
+
+ ethernet-switch@0 {
+ compatible = "micrel,ks8995m";
+ spi-max-frequency = <1000000>;
+ reg = <0>;
+ };
+
+ codec@1 {
+ compatible = "ti,tlv320aic26";
+ spi-max-frequency = <100000>;
+ reg = <1>;
+ };
+ };
+
VII - Marvell Discovery mv64[345]6x System Controller chips
===========================================================
@@ -2488,8 +2547,8 @@ encodings listed below:
2 = high to low edge sensitive type enabled
3 = low to high edge sensitive type enabled
-VIII - Specifying GPIO information for devices
-==============================================
+IX - Specifying GPIO information for devices
+============================================
1) gpios property
-----------------
@@ -2537,116 +2596,151 @@ Example of two SOC GPIO banks defined as gpio-controller nodes:
gpio-controller;
};
+X - Specifying Device Power Management Information (sleep property)
+===================================================================
+
+Devices on SOCs often have mechanisms for placing devices into low-power
+states that are decoupled from the devices' own register blocks. Sometimes,
+this information is more complicated than a cell-index property can
+reasonably describe. Thus, each device controlled in such a manner
+may contain a "sleep" property which describes these connections.
+
+The sleep property consists of one or more sleep resources, each of
+which consists of a phandle to a sleep controller, followed by a
+controller-specific sleep specifier of zero or more cells.
+
+The semantics of what type of low power modes are possible are defined
+by the sleep controller. Some examples of the types of low power modes
+that may be supported are:
+
+ - Dynamic: The device may be disabled or enabled at any time.
+ - System Suspend: The device may request to be disabled or remain
+ awake during system suspend, but will not be disabled until then.
+ - Permanent: The device is disabled permanently (until the next hard
+ reset).
+
+Some devices may share a clock domain with each other, such that they should
+only be suspended when none of the devices are in use. Where reasonable,
+such nodes should be placed on a virtual bus, where the bus has the sleep
+property. If the clock domain is shared among devices that cannot be
+reasonably grouped in this manner, then create a virtual sleep controller
+(similar to an interrupt nexus, except that defining a standardized
+sleep-map should wait until its necessity is demonstrated).
+
Appendix A - Sample SOC node for MPC8540
========================================
-Note that the #address-cells and #size-cells for the SoC node
-in this example have been explicitly listed; these are likely
-not necessary as they are usually the same as the root node.
-
- soc8540@e0000000 {
+ soc@e0000000 {
#address-cells = <1>;
#size-cells = <1>;
- #interrupt-cells = <2>;
+ compatible = "fsl,mpc8540-ccsr", "simple-bus";
device_type = "soc";
- ranges = <00000000 e0000000 00100000>
- reg = <e0000000 00003000>;
+ ranges = <0x00000000 0xe0000000 0x00100000>
bus-frequency = <0>;
-
- mdio@24520 {
- reg = <24520 20>;
- device_type = "mdio";
- compatible = "gianfar";
-
- ethernet-phy@0 {
- linux,phandle = <2452000>
- interrupt-parent = <40000>;
- interrupts = <35 1>;
- reg = <0>;
- device_type = "ethernet-phy";
- };
-
- ethernet-phy@1 {
- linux,phandle = <2452001>
- interrupt-parent = <40000>;
- interrupts = <35 1>;
- reg = <1>;
- device_type = "ethernet-phy";
- };
-
- ethernet-phy@3 {
- linux,phandle = <2452002>
- interrupt-parent = <40000>;
- interrupts = <35 1>;
- reg = <3>;
- device_type = "ethernet-phy";
- };
-
- };
+ interrupt-parent = <&pic>;
ethernet@24000 {
- #size-cells = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
device_type = "network";
model = "TSEC";
- compatible = "gianfar";
- reg = <24000 1000>;
- mac-address = [ 00 E0 0C 00 73 00 ];
- interrupts = <d 3 e 3 12 3>;
- interrupt-parent = <40000>;
- phy-handle = <2452000>;
+ compatible = "gianfar", "simple-bus";
+ reg = <0x24000 0x1000>;
+ local-mac-address = [ 00 E0 0C 00 73 00 ];
+ interrupts = <29 2 30 2 34 2>;
+ phy-handle = <&phy0>;
+ sleep = <&pmc 00000080>;
+ ranges;
+
+ mdio@24520 {
+ reg = <0x24520 0x20>;
+ compatible = "fsl,gianfar-mdio";
+
+ phy0: ethernet-phy@0 {
+ interrupts = <5 1>;
+ reg = <0>;
+ device_type = "ethernet-phy";
+ };
+
+ phy1: ethernet-phy@1 {
+ interrupts = <5 1>;
+ reg = <1>;
+ device_type = "ethernet-phy";
+ };
+
+ phy3: ethernet-phy@3 {
+ interrupts = <7 1>;
+ reg = <3>;
+ device_type = "ethernet-phy";
+ };
+ };
};
ethernet@25000 {
- #address-cells = <1>;
- #size-cells = <0>;
device_type = "network";
model = "TSEC";
compatible = "gianfar";
- reg = <25000 1000>;
- mac-address = [ 00 E0 0C 00 73 01 ];
- interrupts = <13 3 14 3 18 3>;
- interrupt-parent = <40000>;
- phy-handle = <2452001>;
+ reg = <0x25000 0x1000>;
+ local-mac-address = [ 00 E0 0C 00 73 01 ];
+ interrupts = <13 2 14 2 18 2>;
+ phy-handle = <&phy1>;
+ sleep = <&pmc 00000040>;
};
ethernet@26000 {
- #address-cells = <1>;
- #size-cells = <0>;
device_type = "network";
model = "FEC";
compatible = "gianfar";
- reg = <26000 1000>;
- mac-address = [ 00 E0 0C 00 73 02 ];
- interrupts = <19 3>;
- interrupt-parent = <40000>;
- phy-handle = <2452002>;
+ reg = <0x26000 0x1000>;
+ local-mac-address = [ 00 E0 0C 00 73 02 ];
+ interrupts = <41 2>;
+ phy-handle = <&phy3>;
+ sleep = <&pmc 00000020>;
};
serial@4500 {
- device_type = "serial";
- compatible = "ns16550";
- reg = <4500 100>;
- clock-frequency = <0>;
- interrupts = <1a 3>;
- interrupt-parent = <40000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8540-duart", "simple-bus";
+ sleep = <&pmc 00000002>;
+ ranges;
+
+ serial@4500 {
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <42 2>;
+ };
+
+ serial@4600 {
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x4600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <42 2>;
+ };
};
- pic@40000 {
- linux,phandle = <40000>;
+ pic: pic@40000 {
interrupt-controller;
#address-cells = <0>;
- reg = <40000 40000>;
+ #interrupt-cells = <2>;
+ reg = <0x40000 0x40000>;
compatible = "chrp,open-pic";
device_type = "open-pic";
};
i2c@3000 {
- interrupt-parent = <40000>;
- interrupts = <1b 3>;
- reg = <3000 18>;
- device_type = "i2c";
+ interrupts = <43 2>;
+ reg = <0x3000 0x100>;
compatible = "fsl-i2c";
dfsrr;
+ sleep = <&pmc 00000004>;
};
+ pmc: power@e0070 {
+ compatible = "fsl,mpc8540-pmc", "fsl,mpc8548-pmc";
+ reg = <0xe0070 0x20>;
+ };
};
diff --git a/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt b/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt
new file mode 100644
index 00000000000..1815dfede1b
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt
@@ -0,0 +1,38 @@
+Every GPIO controller node must have #gpio-cells property defined,
+this information will be used to translate gpio-specifiers.
+
+On CPM1 devices, all ports are using slightly different register layouts.
+Ports A, C and D are 16bit ports and Ports B and E are 32bit ports.
+
+On CPM2 devices, all ports are 32bit ports and use a common register layout.
+
+Required properties:
+- compatible : "fsl,cpm1-pario-bank-a", "fsl,cpm1-pario-bank-b",
+ "fsl,cpm1-pario-bank-c", "fsl,cpm1-pario-bank-d",
+ "fsl,cpm1-pario-bank-e", "fsl,cpm2-pario-bank"
+- #gpio-cells : Should be two. The first cell is the pin number and the
+ second cell is used to specify optional paramters (currently unused).
+- gpio-controller : Marks the port as GPIO controller.
+
+Example of three SOC GPIO banks defined as gpio-controller nodes:
+
+ CPM1_PIO_A: gpio-controller@950 {
+ #gpio-cells = <2>;
+ compatible = "fsl,cpm1-pario-bank-a";
+ reg = <0x950 0x10>;
+ gpio-controller;
+ };
+
+ CPM1_PIO_B: gpio-controller@ab8 {
+ #gpio-cells = <2>;
+ compatible = "fsl,cpm1-pario-bank-b";
+ reg = <0xab8 0x10>;
+ gpio-controller;
+ };
+
+ CPM1_PIO_E: gpio-controller@ac8 {
+ #gpio-cells = <2>;
+ compatible = "fsl,cpm1-pario-bank-e";
+ reg = <0xac8 0x18>;
+ gpio-controller;
+ };
diff --git a/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/usb.txt b/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/usb.txt
index c8f44d6bcbc..9ccd5f30405 100644
--- a/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/usb.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/usb.txt
@@ -1,22 +1,37 @@
-* USB (Universal Serial Bus Controller)
+Freescale QUICC Engine USB Controller
Required properties:
-- compatible : could be "qe_udc" or "fhci-hcd".
-- mode : the could be "host" or "slave".
-- reg : Offset and length of the register set for the device
-- interrupts : <a b> where a is the interrupt number and b is a
- field that represents an encoding of the sense and level
- information for the interrupt. This should be encoded based on
- the information in section 2) depending on the type of interrupt
- controller you have.
-- interrupt-parent : the phandle for the interrupt controller that
- services interrupts for this device.
+- compatible : should be "fsl,<chip>-qe-usb", "fsl,mpc8323-qe-usb".
+- reg : the first two cells should contain usb registers location and
+ length, the next two two cells should contain PRAM location and
+ length.
+- interrupts : should contain USB interrupt.
+- interrupt-parent : interrupt source phandle.
+- fsl,fullspeed-clock : specifies the full speed USB clock source:
+ "none": clock source is disabled
+ "brg1" through "brg16": clock source is BRG1-BRG16, respectively
+ "clk1" through "clk24": clock source is CLK1-CLK24, respectively
+- fsl,lowspeed-clock : specifies the low speed USB clock source:
+ "none": clock source is disabled
+ "brg1" through "brg16": clock source is BRG1-BRG16, respectively
+ "clk1" through "clk24": clock source is CLK1-CLK24, respectively
+- hub-power-budget : USB power budget for the root hub, in mA.
+- gpios : should specify GPIOs in this order: USBOE, USBTP, USBTN, USBRP,
+ USBRN, SPEED (optional), and POWER (optional).
-Example(slave):
- usb@6c0 {
- compatible = "qe_udc";
- reg = <6c0 40>;
- interrupts = <8b 0>;
- interrupt-parent = <700>;
- mode = "slave";
- };
+Example:
+
+usb@6c0 {
+ compatible = "fsl,mpc8360-qe-usb", "fsl,mpc8323-qe-usb";
+ reg = <0x6c0 0x40 0x8b00 0x100>;
+ interrupts = <11>;
+ interrupt-parent = <&qeic>;
+ fsl,fullspeed-clock = "clk21";
+ gpios = <&qe_pio_b 2 0 /* USBOE */
+ &qe_pio_b 3 0 /* USBTP */
+ &qe_pio_b 8 0 /* USBTN */
+ &qe_pio_b 9 0 /* USBRP */
+ &qe_pio_b 11 0 /* USBRN */
+ &qe_pio_e 20 0 /* SPEED */
+ &qe_pio_e 21 0 /* POWER */>;
+};
diff --git a/Documentation/powerpc/dts-bindings/fsl/mcu-mpc8349emitx.txt b/Documentation/powerpc/dts-bindings/fsl/mcu-mpc8349emitx.txt
new file mode 100644
index 00000000000..0f766333b6e
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/fsl/mcu-mpc8349emitx.txt
@@ -0,0 +1,17 @@
+Freescale MPC8349E-mITX-compatible Power Management Micro Controller Unit (MCU)
+
+Required properties:
+- compatible : "fsl,<mcu-chip>-<board>", "fsl,mcu-mpc8349emitx".
+- reg : should specify I2C address (0x0a).
+- #gpio-cells : should be 2.
+- gpio-controller : should be present.
+
+Example:
+
+mcu@0a {
+ #gpio-cells = <2>;
+ compatible = "fsl,mc9s08qg8-mpc8349emitx",
+ "fsl,mcu-mpc8349emitx";
+ reg = <0x0a>;
+ gpio-controller;
+};
diff --git a/Documentation/powerpc/dts-bindings/fsl/pmc.txt b/Documentation/powerpc/dts-bindings/fsl/pmc.txt
new file mode 100644
index 00000000000..02f6f43ee1b
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/fsl/pmc.txt
@@ -0,0 +1,63 @@
+* Power Management Controller
+
+Properties:
+- compatible: "fsl,<chip>-pmc".
+
+ "fsl,mpc8349-pmc" should be listed for any chip whose PMC is
+ compatible. "fsl,mpc8313-pmc" should also be listed for any chip
+ whose PMC is compatible, and implies deep-sleep capability.
+
+ "fsl,mpc8548-pmc" should be listed for any chip whose PMC is
+ compatible. "fsl,mpc8536-pmc" should also be listed for any chip
+ whose PMC is compatible, and implies deep-sleep capability.
+
+ "fsl,mpc8641d-pmc" should be listed for any chip whose PMC is
+ compatible; all statements below that apply to "fsl,mpc8548-pmc" also
+ apply to "fsl,mpc8641d-pmc".
+
+ Compatibility does not include bit assigments in SCCR/PMCDR/DEVDISR; these
+ bit assigments are indicated via the sleep specifier in each device's
+ sleep property.
+
+- reg: For devices compatible with "fsl,mpc8349-pmc", the first resource
+ is the PMC block, and the second resource is the Clock Configuration
+ block.
+
+ For devices compatible with "fsl,mpc8548-pmc", the first resource
+ is a 32-byte block beginning with DEVDISR.
+
+- interrupts: For "fsl,mpc8349-pmc"-compatible devices, the first
+ resource is the PMC block interrupt.
+
+- fsl,mpc8313-wakeup-timer: For "fsl,mpc8313-pmc"-compatible devices,
+ this is a phandle to an "fsl,gtm" node on which timer 4 can be used as
+ a wakeup source from deep sleep.
+
+Sleep specifiers:
+
+ fsl,mpc8349-pmc: Sleep specifiers consist of one cell. For each bit
+ that is set in the cell, the corresponding bit in SCCR will be saved
+ and cleared on suspend, and restored on resume. This sleep controller
+ supports disabling and resuming devices at any time.
+
+ fsl,mpc8536-pmc: Sleep specifiers consist of three cells, the third of
+ which will be ORed into PMCDR upon suspend, and cleared from PMCDR
+ upon resume. The first two cells are as described for fsl,mpc8578-pmc.
+ This sleep controller only supports disabling devices during system
+ sleep, or permanently.
+
+ fsl,mpc8548-pmc: Sleep specifiers consist of one or two cells, the
+ first of which will be ORed into DEVDISR (and the second into
+ DEVDISR2, if present -- this cell should be zero or absent if the
+ hardware does not have DEVDISR2) upon a request for permanent device
+ disabling. This sleep controller does not support configuring devices
+ to disable during system sleep (unless supported by another compatible
+ match), or dynamically.
+
+Example:
+
+ power@b00 {
+ compatible = "fsl,mpc8313-pmc", "fsl,mpc8349-pmc";
+ reg = <0xb00 0x100 0xa00 0x100>;
+ interrupts = <80 8>;
+ };
diff --git a/Documentation/powerpc/dts-bindings/fsl/tsec.txt b/Documentation/powerpc/dts-bindings/fsl/tsec.txt
index 583ef6b56c4..cf55fa4112d 100644
--- a/Documentation/powerpc/dts-bindings/fsl/tsec.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/tsec.txt
@@ -24,46 +24,39 @@ Example:
* Gianfar-compatible ethernet nodes
-Required properties:
+Properties:
- device_type : Should be "network"
- model : Model of the device. Can be "TSEC", "eTSEC", or "FEC"
- compatible : Should be "gianfar"
- reg : Offset and length of the register set for the device
- - mac-address : List of bytes representing the ethernet address of
+ - local-mac-address : List of bytes representing the ethernet address of
this controller
- - interrupts : <a b> where a is the interrupt number and b is a
- field that represents an encoding of the sense and level
- information for the interrupt. This should be encoded based on
- the information in section 2) depending on the type of interrupt
- controller you have.
- - interrupt-parent : the phandle for the interrupt controller that
- services interrupts for this device.
+ - interrupts : For FEC devices, the first interrupt is the device's
+ interrupt. For TSEC and eTSEC devices, the first interrupt is
+ transmit, the second is receive, and the third is error.
- phy-handle : The phandle for the PHY connected to this ethernet
controller.
- fixed-link : <a b c d e> where a is emulated phy id - choose any,
but unique to the all specified fixed-links, b is duplex - 0 half,
1 full, c is link speed - d#10/d#100/d#1000, d is pause - 0 no
pause, 1 pause, e is asym_pause - 0 no asym_pause, 1 asym_pause.
-
-Recommended properties:
-
- phy-connection-type : a string naming the controller/PHY interface type,
i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id", "sgmii",
"tbi", or "rtbi". This property is only really needed if the connection
is of type "rgmii-id", as all other connection types are detected by
hardware.
-
+ - fsl,magic-packet : If present, indicates that the hardware supports
+ waking up via magic packet.
Example:
ethernet@24000 {
- #size-cells = <0>;
device_type = "network";
model = "TSEC";
compatible = "gianfar";
- reg = <24000 1000>;
- mac-address = [ 00 E0 0C 00 73 00 ];
- interrupts = <d 3 e 3 12 3>;
- interrupt-parent = <40000>;
- phy-handle = <2452000>
+ reg = <0x24000 0x1000>;
+ local-mac-address = [ 00 E0 0C 00 73 00 ];
+ interrupts = <29 2 30 2 34 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>
};
diff --git a/Documentation/powerpc/dts-bindings/fsl/upm-nand.txt b/Documentation/powerpc/dts-bindings/fsl/upm-nand.txt
new file mode 100644
index 00000000000..84a04d5eb8e
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/fsl/upm-nand.txt
@@ -0,0 +1,28 @@
+Freescale Localbus UPM programmed to work with NAND flash
+
+Required properties:
+- compatible : "fsl,upm-nand".
+- reg : should specify localbus chip select and size used for the chip.
+- fsl,upm-addr-offset : UPM pattern offset for the address latch.
+- fsl,upm-cmd-offset : UPM pattern offset for the command latch.
+- gpios : may specify optional GPIO connected to the Ready-Not-Busy pin.
+
+Example:
+
+upm@1,0 {
+ compatible = "fsl,upm-nand";
+ reg = <1 0 1>;
+ fsl,upm-addr-offset = <16>;
+ fsl,upm-cmd-offset = <8>;
+ gpios = <&qe_pio_e 18 0>;
+
+ flash {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "...";
+
+ partition@0 {
+ ...
+ };
+ };
+};
diff --git a/Documentation/powerpc/dts-bindings/gpio/led.txt b/Documentation/powerpc/dts-bindings/gpio/led.txt
new file mode 100644
index 00000000000..ff51f4c0fa9
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/gpio/led.txt
@@ -0,0 +1,15 @@
+LED connected to GPIO
+
+Required properties:
+- compatible : should be "gpio-led".
+- label : (optional) the label for this LED. If omitted, the label is
+ taken from the node name (excluding the unit address).
+- gpios : should specify LED GPIO.
+
+Example:
+
+led@0 {
+ compatible = "gpio-led";
+ label = "hdd";
+ gpios = <&mcu_pio 0 1>;
+};
diff --git a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
index c4d2e3507af..9d644f7e241 100644
--- a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
+++ b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
@@ -42,7 +42,7 @@
<sect1><title>Device Components</title>
!Esound/core/device.c
</sect1>
- <sect1><title>KMOD and Device File Entries</title>
+ <sect1><title>Module requests and Device File Entries</title>
!Esound/core/sound.c
</sect1>
<sect1><title>Memory Management Helpers</title>
diff --git a/Documentation/specialix.txt b/Documentation/specialix.txt
index 4a4b428ce8f..6eb6f3a3331 100644
--- a/Documentation/specialix.txt
+++ b/Documentation/specialix.txt
@@ -270,8 +270,8 @@ The pinout of the connectors on the IO8+ is:
Hardware handshaking issues.
============================
-The driver can be compiled in two different ways. The default
-("Specialix DTR/RTS pin is RTS" is off) the pin behaves as DTR when
+The driver can be told to operate in two different ways. The default
+behaviour is specialix.sx_rtscts = 0 where the pin behaves as DTR when
hardware handshaking is off. It behaves as the RTS hardware
handshaking signal when hardware handshaking is selected.
@@ -280,7 +280,7 @@ cable will either be compatible with hardware handshaking or with
software handshaking. So switching on the fly is not really an
option.
-I actually prefer to use the "Specialix DTR/RTS pin is RTS" option.
+I actually prefer to use the "specialix.sx_rtscts=1" option.
This makes the DTR/RTS pin always an RTS pin, and ioctls to
change DTR are always ignored. I have a cable that is configured
for this.
@@ -379,7 +379,5 @@ it doesn't fit in your computer, bring back the card.
You have to WRITE to the address register to even
read-probe a CD186x register. Disable autodetection?
-- Specialix: any suggestions?
- - Arbitrary baud rates are not implemented yet.
- If you need this, bug me about it.
diff --git a/Documentation/sysfs-rules.txt b/Documentation/sysfs-rules.txt
index 80ef562160b..6049a2a84dd 100644
--- a/Documentation/sysfs-rules.txt
+++ b/Documentation/sysfs-rules.txt
@@ -3,9 +3,8 @@ Rules on how to access information in the Linux kernel sysfs
The kernel-exported sysfs exports internal kernel implementation details
and depends on internal kernel structures and layout. It is agreed upon
by the kernel developers that the Linux kernel does not provide a stable
-internal API. As sysfs is a direct export of kernel internal
-structures, the sysfs interface cannot provide a stable interface either;
-it may always change along with internal kernel changes.
+internal API. Therefore, there are aspects of the sysfs interface that
+may not be stable across kernel releases.
To minimize the risk of breaking users of sysfs, which are in most cases
low-level userspace applications, with a new kernel release, the users
diff --git a/Documentation/telephony/ixj.txt b/Documentation/telephony/ixj.txt
index 621024fd3a1..44d124005ba 100644
--- a/Documentation/telephony/ixj.txt
+++ b/Documentation/telephony/ixj.txt
@@ -305,21 +305,14 @@ driver, like this:
which will result in the needed drivers getting loaded automatically.
- g. if you are planning on using kerneld to automatically load the
-module for you, then you need to edit /etc/conf.modules and add the
+ g. if you are planning on having the kernel automatically request
+the module for you, then you need to edit /etc/conf.modules and add the
following lines:
options ixj dspio=0x340 xio=0x330 ixjdebug=0
If you do this, then when you execute an application that uses the
-module kerneld will load the module for you. Note that to do this,
-you need to have your kernel set to support kerneld. You can check
-for this by looking at /usr/src/linux/.config and you should see this:
-
- # Loadable module support
- #
- <snip>
- CONFIG_KMOD=y
+module the kernel will request that it is loaded.
h. if you want non-root users to be able to read and write to the
ixj devices (this is a good idea!) you should do the following:
diff --git a/Documentation/unaligned-memory-access.txt b/Documentation/unaligned-memory-access.txt
index b0472ac5226..f866c72291b 100644
--- a/Documentation/unaligned-memory-access.txt
+++ b/Documentation/unaligned-memory-access.txt
@@ -218,9 +218,35 @@ If use of such macros is not convenient, another option is to use memcpy(),
where the source or destination (or both) are of type u8* or unsigned char*.
Due to the byte-wise nature of this operation, unaligned accesses are avoided.
+
+Alignment vs. Networking
+========================
+
+On architectures that require aligned loads, networking requires that the IP
+header is aligned on a four-byte boundary to optimise the IP stack. For
+regular ethernet hardware, the constant NET_IP_ALIGN is used. On most
+architectures this constant has the value 2 because the normal ethernet
+header is 14 bytes long, so in order to get proper alignment one needs to
+DMA to an address which can be expressed as 4*n + 2. One notable exception
+here is powerpc which defines NET_IP_ALIGN to 0 because DMA to unaligned
+addresses can be very expensive and dwarf the cost of unaligned loads.
+
+For some ethernet hardware that cannot DMA to unaligned addresses like
+4*n+2 or non-ethernet hardware, this can be a problem, and it is then
+required to copy the incoming frame into an aligned buffer. Because this is
+unnecessary on architectures that can do unaligned accesses, the code can be
+made dependent on CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS like so:
+
+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+ skb = original skb
+#else
+ skb = copy skb
+#endif
+
--
-Author: Daniel Drake <dsd@gentoo.org>
+Authors: Daniel Drake <dsd@gentoo.org>,
+ Johannes Berg <johannes@sipsolutions.net>
With help from: Alan Cox, Avuton Olrich, Heikki Orsila, Jan Engelhardt,
-Johannes Berg, Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock,
-Uli Kunitz, Vadim Lobanov
+Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock, Uli Kunitz,
+Vadim Lobanov
diff --git a/Documentation/video4linux/w9968cf.txt b/Documentation/video4linux/w9968cf.txt
index e0bba8393c7..05138e8aea0 100644
--- a/Documentation/video4linux/w9968cf.txt
+++ b/Documentation/video4linux/w9968cf.txt
@@ -193,9 +193,6 @@ Description: Automatic 'ovcamchip' module loading: 0 disabled, 1 enabled.
loads that module automatically. This action is performed as
once soon as the 'w9968cf' module is loaded into memory.
Default: 1
-Note: The kernel must be compiled with the CONFIG_KMOD option
- enabled for the 'ovcamchip' module to be loaded and for
- this parameter to be present.
-------------------------------------------------------------------------------
Name: simcams
Type: int
diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
index 3102b81bef8..8a5b5763f0f 100644
--- a/Documentation/vm/hugetlbpage.txt
+++ b/Documentation/vm/hugetlbpage.txt
@@ -95,6 +95,29 @@ this condition holds, however, no more surplus huge pages will be
allowed on the system until one of the two sysctls are increased
sufficiently, or the surplus huge pages go out of use and are freed.
+With support for multiple hugepage pools at run-time available, much of
+the hugepage userspace interface has been duplicated in sysfs. The above
+information applies to the default hugepage size (which will be
+controlled by the proc interfaces for backwards compatibility). The root
+hugepage control directory is
+
+ /sys/kernel/mm/hugepages
+
+For each hugepage size supported by the running kernel, a subdirectory
+will exist, of the form
+
+ hugepages-${size}kB
+
+Inside each of these directories, the same set of files will exist:
+
+ nr_hugepages
+ nr_overcommit_hugepages
+ free_hugepages
+ resv_hugepages
+ surplus_hugepages
+
+which function as described above for the default hugepage-sized case.
+
If the user applications are going to request hugepages using mmap system
call, then it is required that system administrator mount a file system of
type hugetlbfs:
diff --git a/MAINTAINERS b/MAINTAINERS
index df3fa0e42f2..4cbf6016a9b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -441,10 +441,7 @@ M: spyro@f2s.com
S: Maintained
ARM PRIMECELL MMCI PL180/1 DRIVER
-P: Russell King
-M: rmk@arm.linux.org.uk
-L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
-S: Maintained
+S: Orphan
ARM/ADI ROADRUNNER MACHINE SUPPORT
P: Lennert Buytenhek
@@ -483,11 +480,28 @@ M: kernel@wantstofly.org
L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
S: Maintained
+ARM/COMPULAB CM-X270/EM-X270 MACHINE SUPPORT
+P: Mike Rapoport
+M: mike@compulab.co.il
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S: Maintained
+
ARM/CORGI MACHINE SUPPORT
P: Richard Purdie
M: rpurdie@rpsys.net
S: Maintained
+ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6)
+P: Daniel Ribeiro
+M: drwyrm@gmail.com
+P: Stefan Schmidt
+M: stefan@openezx.org
+P: Harald Welte
+M: laforge@openezx.org
+L: openezx-devel@lists.openezx.org (subscribers-only)
+W: http://www.openezx.org/
+S: Maintained
+
ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
P: Lennert Buytenhek
M: kernel@wantstofly.org
@@ -575,10 +589,18 @@ L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
S: Maintained
ARM/TOSA MACHINE SUPPORT
+P: Dmitry Baryshkov
+M: dbaryshkov@gmail.com
P: Dirk Opfer
M: dirk@opfer-online.de
S: Maintained
+ARM/PALMTX SUPPORT
+P: Marek Vasut
+M: marek.vasut@gmail.com
+W: http://hackndev.com
+S: Maintained
+
ARM/PLEB SUPPORT
P: Peter Chubb
M: pleb@gelato.unsw.edu.au
@@ -1021,6 +1043,12 @@ M: fujita.tomonori@lab.ntt.co.jp
L: linux-scsi@vger.kernel.org
S: Supported
+BT8XXGPIO DRIVER
+P: Michael Buesch
+M: mb@bu3sch.de
+W: http://bu3sch.de/btgpio.php
+S: Maintained
+
BTTV VIDEO4LINUX DRIVER
P: Mauro Carvalho Chehab
M: mchehab@infradead.org
@@ -1962,7 +1990,7 @@ P: Carlos Corbacho
M: carlos@strangeworlds.co.uk
S: Odd Fixes
-HPET: High Precision Event Timers driver (hpet.c)
+HPET: High Precision Event Timers driver (drivers/char/hpet.c)
P: Clemens Ladisch
M: clemens@ladisch.de
S: Maintained
@@ -2915,8 +2943,6 @@ P: Faisal Latif
M: flatif@neteffect.com
P: Chien Tung
M: ctung@neteffect.com
-P: Glenn Streiff
-M: gstreiff@neteffect.com
L: general@lists.openfabrics.org
W: http://www.neteffect.com
S: Supported
@@ -3533,7 +3559,7 @@ S: Supported
S390 NETWORK DRIVERS
P: Ursula Braun
-M: ubraun@linux.vnet.ibm.com
+M: ursula.braun@de.ibm.com
P: Frank Blaschka
M: blaschka@linux.vnet.ibm.com
M: linux390@de.ibm.com
@@ -3553,7 +3579,7 @@ S: Supported
S390 IUCV NETWORK LAYER
P: Ursula Braun
-M: ubraun@linux.vnet.ibm.com
+M: ursula.braun@de.ibm.com
M: linux390@de.ibm.com
L: linux-s390@vger.kernel.org
W: http://www.ibm.com/developerworks/linux/linux390/
@@ -4047,9 +4073,10 @@ W: http://www.buzzard.org.uk/toshiba/
S: Maintained
TPM DEVICE DRIVER
-P: Debora Velarde
-P: Rajiv Andrade
-M: tpmdd-devel@lists.sourceforge.net
+P: Debora Velarde
+M: debora@linux.vnet.ibm.com
+P: Rajiv Andrade
+M: srajiv@linux.vnet.ibm.com
W: http://tpmdd.sourceforge.net
P: Marcel Selhorst
M: tpm@selhorst.net
@@ -4057,12 +4084,6 @@ W: http://www.prosec.rub.de/tpm/
L: tpmdd-devel@lists.sourceforge.net
S: Maintained
-TRIDENT 4DWAVE/SIS 7018 PCI AUDIO CORE
-P: Muli Ben-Yehuda
-M: mulix@mulix.org
-L: linux-kernel@vger.kernel.org
-S: Maintained
-
TRIVIAL PATCHES
P: Jesper Juhl
M: trivial@kernel.org
@@ -4108,9 +4129,6 @@ W: http://www.uclinux.org/
L: uclinux-dev@uclinux.org (subscribers-only)
S: Maintained
-UCLINUX FOR NEC V850
-P: Miles Bader
-
UCLINUX FOR RENESAS H8/300
P: Yoshinori Sato
M: ysato@users.sourceforge.jp
diff --git a/Makefile b/Makefile
index 6192922de9c..3cad7db5eba 100644
--- a/Makefile
+++ b/Makefile
@@ -1061,6 +1061,7 @@ modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
$(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
@echo ' Building modules, stage 2.';
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
+ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modbuild
# Target to prepare building external modules
@@ -1148,7 +1149,8 @@ clean: archclean $(clean-dirs)
@find . $(RCS_FIND_IGNORE) \
\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
- -o -name '*.symtypes' -o -name 'modules.order' \) \
+ -o -name '*.symtypes' -o -name 'modules.order' \
+ -o -name 'Module.markers' \) \
-type f -print | xargs rm -f
# mrproper - Delete all generated files, including .config
diff --git a/arch/Kconfig b/arch/Kconfig
index ad89a33d8c6..b0fabfa864f 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -27,10 +27,32 @@ config KPROBES
for kernel debugging, non-intrusive instrumentation and testing.
If in doubt, say "N".
+config HAVE_EFFICIENT_UNALIGNED_ACCESS
+ def_bool n
+ help
+ Some architectures are unable to perform unaligned accesses
+ without the use of get_unaligned/put_unaligned. Others are
+ unable to perform such accesses efficiently (e.g. trap on
+ unaligned access and require fixing it up in the exception
+ handler.)
+
+ This symbol should be selected by an architecture if it can
+ perform unaligned accesses efficiently to allow different
+ code paths to be selected for these cases. Some network
+ drivers, for example, could opt to not fix up alignment
+ problems with received packets if doing so would not help
+ much.
+
+ See Documentation/unaligned-memory-access.txt for more
+ information on the topic of unaligned memory accesses.
+
config KRETPROBES
def_bool y
depends on KPROBES && HAVE_KRETPROBES
+config HAVE_IOREMAP_PROT
+ def_bool n
+
config HAVE_KPROBES
def_bool n
@@ -42,3 +64,10 @@ config HAVE_DMA_ATTRS
config USE_GENERIC_SMP_HELPERS
def_bool n
+
+config HAVE_CLK
+ def_bool n
+ help
+ The <linux/clk.h> calls support software clock gating and
+ thus are a key power management tool on many systems.
+
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index dbe8c280fea..1bec55d63ef 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -333,11 +333,6 @@ config PCI_SYSCALL
config IOMMU_HELPER
def_bool PCI
-config ALPHA_CORE_AGP
- bool
- depends on ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL
- default y
-
config ALPHA_NONAME
bool
depends on ALPHA_BOOK1 || ALPHA_NONAME_CH
diff --git a/arch/alpha/boot/misc.c b/arch/alpha/boot/misc.c
index c00646b25f6..3047a1b3a51 100644
--- a/arch/alpha/boot/misc.c
+++ b/arch/alpha/boot/misc.c
@@ -78,8 +78,6 @@ static unsigned outcnt; /* bytes in output buffer */
static int fill_inbuf(void);
static void flush_window(void);
static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
static char *input_data;
static int input_data_size;
@@ -88,51 +86,18 @@ static uch *output_data;
static ulg output_ptr;
static ulg bytes_out;
-static void *malloc(int size);
-static void free(void *where);
static void error(char *m);
static void gzip_mark(void **);
static void gzip_release(void **);
extern int end;
static ulg free_mem_ptr;
-static ulg free_mem_ptr_end;
+static ulg free_mem_end_ptr;
#define HEAP_SIZE 0x3000
#include "../../../lib/inflate.c"
-static void *malloc(int size)
-{
- void *p;
-
- if (size <0) error("Malloc error");
- if (free_mem_ptr <= 0) error("Memory error");
-
- free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
- p = (void *)free_mem_ptr;
- free_mem_ptr += size;
-
- if (free_mem_ptr >= free_mem_ptr_end)
- error("Out of memory");
- return p;
-}
-
-static void free(void *where)
-{ /* gzip_mark & gzip_release do the free */
-}
-
-static void gzip_mark(void **ptr)
-{
- *ptr = (void *) free_mem_ptr;
-}
-
-static void gzip_release(void **ptr)
-{
- free_mem_ptr = (long) *ptr;
-}
-
/* ===========================================================================
* Fill the input buffer. This is called only when the buffer is empty
* and at least one byte is really needed.
@@ -193,7 +158,7 @@ decompress_kernel(void *output_start,
/* FIXME FIXME FIXME */
free_mem_ptr = (ulg)output_start + ksize;
- free_mem_ptr_end = (ulg)output_start + ksize + 0x200000;
+ free_mem_end_ptr = (ulg)output_start + ksize + 0x200000;
/* FIXME FIXME FIXME */
/* put in temp area to reduce initial footprint */
diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
index 10ab7833e83..d8c4ceaf00b 100644
--- a/arch/alpha/mm/numa.c
+++ b/arch/alpha/mm/numa.c
@@ -19,7 +19,6 @@
#include <asm/pgalloc.h>
pg_data_t node_data[MAX_NUMNODES];
-bootmem_data_t node_bdata[MAX_NUMNODES];
EXPORT_SYMBOL(node_data);
#undef DEBUG_DISCONTIG
@@ -141,7 +140,7 @@ setup_memory_node(int nid, void *kernel_end)
printk(" not enough mem to reserve NODE_DATA");
return;
}
- NODE_DATA(nid)->bdata = &node_bdata[nid];
+ NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
printk(" Detected node memory: start %8lu, end %8lu\n",
node_min_pfn, node_max_pfn);
@@ -304,8 +303,9 @@ void __init paging_init(void)
dma_local_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
for_each_online_node(nid) {
- unsigned long start_pfn = node_bdata[nid].node_boot_start >> PAGE_SHIFT;
- unsigned long end_pfn = node_bdata[nid].node_low_pfn;
+ bootmem_data_t *bdata = &bootmem_node_data[nid];
+ unsigned long start_pfn = bdata->node_min_pfn;
+ unsigned long end_pfn = bdata->node_low_pfn;
if (dma_local_pfn >= end_pfn - start_pfn)
zones_size[ZONE_DMA] = end_pfn - start_pfn;
@@ -313,7 +313,7 @@ void __init paging_init(void)
zones_size[ZONE_DMA] = dma_local_pfn;
zones_size[ZONE_NORMAL] = (end_pfn - start_pfn) - dma_local_pfn;
}
- free_area_init_node(nid, NODE_DATA(nid), zones_size, start_pfn, NULL);
+ free_area_init_node(nid, zones_size, start_pfn, NULL);
}
/* Initialize the kernel's ZERO_PGE. */
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c7ad324ddf2..dabb015aa40 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -12,6 +12,7 @@ config ARM
select RTC_LIB
select SYS_SUPPORTS_APM_EMULATION
select HAVE_OPROFILE
+ select HAVE_ARCH_KGDB
select HAVE_KPROBES if (!XIP_KERNEL)
select HAVE_KRETPROBES if (HAVE_KPROBES)
select HAVE_FTRACE if (!XIP_KERNEL)
@@ -197,12 +198,14 @@ choice
config ARCH_AAEC2000
bool "Agilent AAEC-2000 based"
select ARM_AMBA
+ select HAVE_CLK
help
This enables support for systems based on the Agilent AAEC-2000
config ARCH_INTEGRATOR
bool "ARM Ltd. Integrator family"
select ARM_AMBA
+ select HAVE_CLK
select ICST525
help
Support for ARM's Integrator platform.
@@ -210,6 +213,7 @@ config ARCH_INTEGRATOR
config ARCH_REALVIEW
bool "ARM Ltd. RealView family"
select ARM_AMBA
+ select HAVE_CLK
select ICST307
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
@@ -220,6 +224,7 @@ config ARCH_VERSATILE
bool "ARM Ltd. Versatile family"
select ARM_AMBA
select ARM_VIC
+ select HAVE_CLK
select ICST307
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
@@ -261,7 +266,9 @@ config ARCH_EP93XX
select ARM_AMBA
select ARM_VIC
select GENERIC_GPIO
- select HAVE_GPIO_LIB
+ select HAVE_CLK
+ select HAVE_CLK
+ select ARCH_REQUIRE_GPIOLIB
help
This enables support for the Cirrus EP93xx series of CPUs.
@@ -380,6 +387,7 @@ config ARCH_NS9XXX
select GENERIC_GPIO
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
+ select HAVE_CLK
help
Say Y here if you intend to run this kernel on a NetSilicon NS9xxx
System.
@@ -429,6 +437,7 @@ config ARCH_ORION5X
config ARCH_PNX4008
bool "Philips Nexperia PNX4008 Mobile"
+ select HAVE_CLK
help
This enables support for Philips PNX4008 mobile platform.
@@ -437,7 +446,8 @@ config ARCH_PXA
depends on MMU
select ARCH_MTD_XIP
select GENERIC_GPIO
- select HAVE_GPIO_LIB
+ select HAVE_CLK
+ select ARCH_REQUIRE_GPIOLIB
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
select TICK_ONESHOT
@@ -467,14 +477,16 @@ config ARCH_SA1100
select GENERIC_GPIO
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
+ select HAVE_CLK
select TICK_ONESHOT
- select HAVE_GPIO_LIB
+ select ARCH_REQUIRE_GPIOLIB
help
Support for StrongARM 11x0 based boards.
config ARCH_S3C2410
bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
select GENERIC_GPIO
+ select HAVE_CLK
help
Samsung S3C2410X CPU based systems, such as the Simtec Electronics
BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
@@ -502,13 +514,15 @@ config ARCH_DAVINCI
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
select GENERIC_GPIO
+ select HAVE_CLK
help
Support for TI's DaVinci platform.
config ARCH_OMAP
bool "TI OMAP"
select GENERIC_GPIO
- select HAVE_GPIO_LIB
+ select HAVE_CLK
+ select ARCH_REQUIRE_GPIOLIB
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
help
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index 9b444022cb9..7145cc7c04f 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -217,8 +217,6 @@ static unsigned outcnt; /* bytes in output buffer */
static int fill_inbuf(void);
static void flush_window(void);
static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
extern char input_data[];
extern char input_data_end[];
@@ -227,64 +225,21 @@ static uch *output_data;
static ulg output_ptr;
static ulg bytes_out;
-static void *malloc(int size);
-static void free(void *where);
static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
static void putstr(const char *);
extern int end;
static ulg free_mem_ptr;
-static ulg free_mem_ptr_end;
+static ulg free_mem_end_ptr;
-#define HEAP_SIZE 0x3000
-
-#include "../../../../lib/inflate.c"
-
-#ifndef STANDALONE_DEBUG
-static void *malloc(int size)
-{
- void *p;
-
- if (size <0) error("Malloc error");
- if (free_mem_ptr <= 0) error("Memory error");
-
- free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
- p = (void *)free_mem_ptr;
- free_mem_ptr += size;
-
- if (free_mem_ptr >= free_mem_ptr_end)
- error("Out of memory");
- return p;
-}
-
-static void free(void *where)
-{ /* gzip_mark & gzip_release do the free */
-}
-
-static void gzip_mark(void **ptr)
-{
- arch_decomp_wdog();
- *ptr = (void *) free_mem_ptr;
-}
+#ifdef STANDALONE_DEBUG
+#define NO_INFLATE_MALLOC
+#endif
-static void gzip_release(void **ptr)
-{
- arch_decomp_wdog();
- free_mem_ptr = (long) *ptr;
-}
-#else
-static void gzip_mark(void **ptr)
-{
-}
+#define ARCH_HAS_DECOMP_WDOG
-static void gzip_release(void **ptr)
-{
-}
-#endif
+#include "../../../../lib/inflate.c"
/* ===========================================================================
* Fill the input buffer. This is called only when the buffer is empty
@@ -348,7 +303,7 @@ decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
{
output_data = (uch *)output_start; /* Points to kernel start */
free_mem_ptr = free_mem_ptr_p;
- free_mem_ptr_end = free_mem_ptr_end_p;
+ free_mem_end_ptr = free_mem_ptr_end_p;
__machine_arch_type = arch_id;
arch_decomp_setup();
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 2744673314b..dd294734260 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -554,9 +554,8 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
if (!device_info) {
- printk(KERN_ERR
- "Could not allocated dmabounce_device_info for %s",
- dev->bus_id);
+ dev_err(dev,
+ "Could not allocated dmabounce_device_info\n");
return -ENOMEM;
}
@@ -594,8 +593,7 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
dev->archdata.dmabounce = device_info;
- printk(KERN_INFO "dmabounce: registered device %s on %s bus\n",
- dev->bus_id, dev->bus->name);
+ dev_info(dev, "dmabounce: registered device\n");
return 0;
@@ -614,16 +612,15 @@ dmabounce_unregister_dev(struct device *dev)
dev->archdata.dmabounce = NULL;
if (!device_info) {
- printk(KERN_WARNING
- "%s: Never registered with dmabounce but attempting" \
- "to unregister!\n", dev->bus_id);
+ dev_warn(dev,
+ "Never registered with dmabounce but attempting"
+ "to unregister!\n");
return;
}
if (!list_empty(&device_info->safe_buffers)) {
- printk(KERN_ERR
- "%s: Removing from dmabounce with pending buffers!\n",
- dev->bus_id);
+ dev_err(dev,
+ "Removing from dmabounce with pending buffers!\n");
BUG();
}
@@ -639,8 +636,7 @@ dmabounce_unregister_dev(struct device *dev)
kfree(device_info);
- printk(KERN_INFO "dmabounce: device %s on %s bus unregistered\n",
- dev->bus_id, dev->bus->name);
+ dev_info(dev, "dmabounce: device unregistered\n");
}
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index d973c986f72..c3c3a333904 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -543,7 +543,6 @@ locomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info)
goto out;
}
- strncpy(dev->dev.bus_id, info->name, sizeof(dev->dev.bus_id));
/*
* If the parent device has a DMA mask associated with it,
* propagate it down to the children.
@@ -553,6 +552,7 @@ locomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info)
dev->dev.dma_mask = &dev->dma_mask;
}
+ dev_set_name(&dev->dev, "%s", info->name);
dev->devid = info->devid;
dev->dev.parent = lchip->dev;
dev->dev.bus = &locomo_bus_type;
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index eb06d0b2cb7..0a8e1ff2af8 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -550,9 +550,7 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
goto out;
}
- snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
- "%4.4lx", info->offset);
-
+ dev_set_name(&dev->dev, "%4.4lx", info->offset);
dev->devid = info->devid;
dev->dev.parent = sachip->dev;
dev->dev.bus = &sa1111_bus_type;
@@ -560,7 +558,7 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
dev->dev.coherent_dma_mask = sachip->dev->coherent_dma_mask;
dev->res.start = sachip->phys + info->offset;
dev->res.end = dev->res.start + 511;
- dev->res.name = dev->dev.bus_id;
+ dev->res.name = dev_name(&dev->dev);
dev->res.flags = IORESOURCE_MEM;
dev->mapbase = sachip->base + info->offset;
dev->skpcr_mask = info->skpcr_mask;
@@ -570,6 +568,7 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
if (ret) {
printk("SA1111: failed to allocate resource for %s\n",
dev->res.name);
+ dev_set_name(&dev->dev, NULL);
kfree(dev);
goto out;
}
@@ -593,7 +592,8 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
if (dev->dma_mask != 0xffffffffUL) {
ret = dmabounce_register_dev(&dev->dev, 1024, 4096);
if (ret) {
- printk("SA1111: Failed to register %s with dmabounce", dev->dev.bus_id);
+ dev_err(&dev->dev, "SA1111: Failed to register"
+ " with dmabounce\n");
device_unregister(&dev->dev);
}
}
@@ -627,7 +627,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
if (!sachip)
return -ENOMEM;
- sachip->clk = clk_get(me, "GPIO27_CLK");
+ sachip->clk = clk_get(me, "SA1111_CLK");
if (!sachip->clk) {
ret = PTR_ERR(sachip->clk);
goto err_free;
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index bc299b07a6f..ae39553589d 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -247,7 +247,7 @@ static int __devinit scoop_probe(struct platform_device *pdev)
devptr->gpio.base = -1;
if (inf->gpio_base != 0) {
- devptr->gpio.label = pdev->dev.bus_id;
+ devptr->gpio.label = dev_name(&pdev->dev);
devptr->gpio.base = inf->gpio_base;
devptr->gpio.ngpio = 12; /* PA11 = 0, PA12 = 1, etc. up to PA22 = 11 */
devptr->gpio.set = scoop_gpio_set;
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
new file mode 100644
index 00000000000..2a84d557adc
--- /dev/null
+++ b/arch/arm/configs/ezx_defconfig
@@ -0,0 +1,1614 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc3
+# Mon Jul 7 17:52:21 2008
+#
+CONFIG_ARM=y
+CONFIG_HAVE_PWM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_ZONE_DMA=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION="-ezxdev"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_CLASSIC_RCU=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM7X00A is not set
+
+#
+# Intel PXA2xx/PXA3xx Implementations
+#
+# CONFIG_ARCH_GUMSTIX is not set
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_LOGICPD_PXA270 is not set
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_PXA_SHARPSL is not set
+# CONFIG_ARCH_PXA_ESERIES is not set
+# CONFIG_MACH_TRIZEPS4 is not set
+# CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_COLIBRI is not set
+# CONFIG_MACH_ZYLONITE is not set
+# CONFIG_MACH_LITTLETON is not set
+# CONFIG_MACH_ARMCORE is not set
+# CONFIG_MACH_MAGICIAN is not set
+# CONFIG_MACH_PCM027 is not set
+CONFIG_PXA_EZX=y
+CONFIG_MACH_EZX_A780=y
+CONFIG_MACH_EZX_E680=y
+CONFIG_MACH_EZX_A1200=y
+CONFIG_MACH_EZX_A910=y
+CONFIG_MACH_EZX_E6=y
+CONFIG_MACH_EZX_E2=y
+CONFIG_PXA27x=y
+CONFIG_PXA_SSP=y
+CONFIG_PXA_PWM=y
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_IWMMXT=y
+CONFIG_XSCALE_PMU=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=tty1 root=/dev/mmcblk0p2 rootfstype=ext2 rootdelay=1 ip=192.168.0.202:192.168.0.200:192.168.0.200:255.255.255.0 debug"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_APM_EMULATION=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CT_PROTO_DCCP is not set
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+# CONFIG_NETFILTER_XT_MATCH_RATEEST 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=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# Bridge: Netfilter Configuration
+#
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_SCH_FIFO=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIUSB is not set
+# CONFIG_BT_HCIBTUSB is not set
+# CONFIG_BT_HCIBTSDIO is not set
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+# CONFIG_BT_HCIUART_BCSP is not set
+# CONFIG_BT_HCIUART_LL is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+
+#
+# Wireless
+#
+CONFIG_CFG80211=m
+CONFIG_NL80211=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_MAC80211=m
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_NONE is not set
+
+#
+# Selecting 'y' for an algorithm will
+#
+
+#
+# build the algorithm into mac80211.
+#
+CONFIG_MAC80211_RC_DEFAULT="pid"
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT is not set
+# CONFIG_MAC80211_DEBUG is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLKDEVS is not set
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+# CONFIG_MTD_CFI_I2 is not set
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+CONFIG_MTD_XIP=y
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x0
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PXA2XX is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_SHARP_SL is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_NET_ETHERNET is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_APMPOWER is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_PXA27x=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+CONFIG_TOUCHSCREEN_PCAP=y
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+CONFIG_INPUT_UINPUT=y
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=8
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_PXA2XX=m
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_HAVE_GPIO_LIB=y
+
+#
+# GPIO Support
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TC6393XB is not set
+CONFIG_EZX_PCAP=y
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_V4L_USB_DRIVERS is not set
+# CONFIG_SOC_CAMERA is not set
+# CONFIG_VIDEO_PXA27x is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_SMARTPANEL is not set
+CONFIG_FB_PXA_PARAMETERS=y
+# CONFIG_FB_MBX is not set
+# CONFIG_FB_AM200EPD is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_CORGI is not set
+CONFIG_BACKLIGHT_PWM=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+CONFIG_FONT_MINI_4x6=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+# CONFIG_SND_PXA2XX_AC97 is not set
+
+#
+# SPI devices
+#
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+CONFIG_SND_SOC=y
+CONFIG_SND_PXA2XX_SOC=y
+
+#
+# ALSA SoC audio for Freescale SOCs
+#
+
+#
+# SoC Audio for the Texas Instruments OMAP
+#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_M66592 is not set
+CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=y
+# CONFIG_USB_ETH_RNDIS is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+
+#
+# MMC/SD Host Controller Drivers
+#
+CONFIG_MMC_PXA=y
+# CONFIG_MMC_SPI is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_GPIO is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SA1100=m
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=m
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+# CONFIG_NFS_V4 is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_ROOT_NFS is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+# CONFIG_CIFS_STATS2 is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_SAMPLES is not set
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+# CONFIG_CRYPTO_CAMELLIA is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index eb9092ca800..1d296fc8494 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o
obj-$(CONFIG_ATAGS_PROC) += atags.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
obj-$(CONFIG_ARM_THUMBEE) += thumbee.o
+obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index 8bfd299bfe7..f5cfdabcb87 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -783,7 +783,7 @@ static void ecard_proc_init(void)
#define ec_set_resource(ec,nr,st,sz) \
do { \
- (ec)->resource[nr].name = ec->dev.bus_id; \
+ (ec)->resource[nr].name = dev_name(&ec->dev); \
(ec)->resource[nr].start = st; \
(ec)->resource[nr].end = (st) + (sz) - 1; \
(ec)->resource[nr].flags = IORESOURCE_MEM; \
@@ -853,8 +853,7 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot)
for (i = 0; i < ECARD_NUM_RESOURCES; i++) {
if (ec->resource[i].flags &&
request_resource(&iomem_resource, &ec->resource[i])) {
- printk(KERN_ERR "%s: resource(s) not available\n",
- ec->dev.bus_id);
+ dev_err(&ec->dev, "resource(s) not available\n");
ec->resource[i].end -= ec->resource[i].start;
ec->resource[i].start = 0;
ec->resource[i].flags = 0;
diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c
new file mode 100644
index 00000000000..aaffaecffcd
--- /dev/null
+++ b/arch/arm/kernel/kgdb.c
@@ -0,0 +1,201 @@
+/*
+ * arch/arm/kernel/kgdb.c
+ *
+ * ARM KGDB support
+ *
+ * Copyright (c) 2002-2004 MontaVista Software, Inc
+ * Copyright (c) 2008 Wind River Systems, Inc.
+ *
+ * Authors: George Davis <davis_g@mvista.com>
+ * Deepak Saxena <dsaxena@plexity.net>
+ */
+#include <linux/kgdb.h>
+#include <asm/traps.h>
+
+/* Make a local copy of the registers passed into the handler (bletch) */
+void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
+{
+ int regno;
+
+ /* Initialize all to zero. */
+ for (regno = 0; regno < GDB_MAX_REGS; regno++)
+ gdb_regs[regno] = 0;
+
+ gdb_regs[_R0] = kernel_regs->ARM_r0;
+ gdb_regs[_R1] = kernel_regs->ARM_r1;
+ gdb_regs[_R2] = kernel_regs->ARM_r2;
+ gdb_regs[_R3] = kernel_regs->ARM_r3;
+ gdb_regs[_R4] = kernel_regs->ARM_r4;
+ gdb_regs[_R5] = kernel_regs->ARM_r5;
+ gdb_regs[_R6] = kernel_regs->ARM_r6;
+ gdb_regs[_R7] = kernel_regs->ARM_r7;
+ gdb_regs[_R8] = kernel_regs->ARM_r8;
+ gdb_regs[_R9] = kernel_regs->ARM_r9;
+ gdb_regs[_R10] = kernel_regs->ARM_r10;
+ gdb_regs[_FP] = kernel_regs->ARM_fp;
+ gdb_regs[_IP] = kernel_regs->ARM_ip;
+ gdb_regs[_SPT] = kernel_regs->ARM_sp;
+ gdb_regs[_LR] = kernel_regs->ARM_lr;
+ gdb_regs[_PC] = kernel_regs->ARM_pc;
+ gdb_regs[_CPSR] = kernel_regs->ARM_cpsr;
+}
+
+/* Copy local gdb registers back to kgdb regs, for later copy to kernel */
+void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
+{
+ kernel_regs->ARM_r0 = gdb_regs[_R0];
+ kernel_regs->ARM_r1 = gdb_regs[_R1];
+ kernel_regs->ARM_r2 = gdb_regs[_R2];
+ kernel_regs->ARM_r3 = gdb_regs[_R3];
+ kernel_regs->ARM_r4 = gdb_regs[_R4];
+ kernel_regs->ARM_r5 = gdb_regs[_R5];
+ kernel_regs->ARM_r6 = gdb_regs[_R6];
+ kernel_regs->ARM_r7 = gdb_regs[_R7];
+ kernel_regs->ARM_r8 = gdb_regs[_R8];
+ kernel_regs->ARM_r9 = gdb_regs[_R9];
+ kernel_regs->ARM_r10 = gdb_regs[_R10];
+ kernel_regs->ARM_fp = gdb_regs[_FP];
+ kernel_regs->ARM_ip = gdb_regs[_IP];
+ kernel_regs->ARM_sp = gdb_regs[_SPT];
+ kernel_regs->ARM_lr = gdb_regs[_LR];
+ kernel_regs->ARM_pc = gdb_regs[_PC];
+ kernel_regs->ARM_cpsr = gdb_regs[_CPSR];
+}
+
+void
+sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
+{
+ struct pt_regs *thread_regs;
+ int regno;
+
+ /* Just making sure... */
+ if (task == NULL)
+ return;
+
+ /* Initialize to zero */
+ for (regno = 0; regno < GDB_MAX_REGS; regno++)
+ gdb_regs[regno] = 0;
+
+ /* Otherwise, we have only some registers from switch_to() */
+ thread_regs = task_pt_regs(task);
+ gdb_regs[_R0] = thread_regs->ARM_r0;
+ gdb_regs[_R1] = thread_regs->ARM_r1;
+ gdb_regs[_R2] = thread_regs->ARM_r2;
+ gdb_regs[_R3] = thread_regs->ARM_r3;
+ gdb_regs[_R4] = thread_regs->ARM_r4;
+ gdb_regs[_R5] = thread_regs->ARM_r5;
+ gdb_regs[_R6] = thread_regs->ARM_r6;
+ gdb_regs[_R7] = thread_regs->ARM_r7;
+ gdb_regs[_R8] = thread_regs->ARM_r8;
+ gdb_regs[_R9] = thread_regs->ARM_r9;
+ gdb_regs[_R10] = thread_regs->ARM_r10;
+ gdb_regs[_FP] = thread_regs->ARM_fp;
+ gdb_regs[_IP] = thread_regs->ARM_ip;
+ gdb_regs[_SPT] = thread_regs->ARM_sp;
+ gdb_regs[_LR] = thread_regs->ARM_lr;
+ gdb_regs[_PC] = thread_regs->ARM_pc;
+ gdb_regs[_CPSR] = thread_regs->ARM_cpsr;
+}
+
+static int compiled_break;
+
+int kgdb_arch_handle_exception(int exception_vector, int signo,
+ int err_code, char *remcom_in_buffer,
+ char *remcom_out_buffer,
+ struct pt_regs *linux_regs)
+{
+ unsigned long addr;
+ char *ptr;
+
+ switch (remcom_in_buffer[0]) {
+ case 'D':
+ case 'k':
+ case 'c':
+ kgdb_contthread = NULL;
+
+ /*
+ * Try to read optional parameter, pc unchanged if no parm.
+ * If this was a compiled breakpoint, we need to move
+ * to the next instruction or we will just breakpoint
+ * over and over again.
+ */
+ ptr = &remcom_in_buffer[1];
+ if (kgdb_hex2long(&ptr, &addr))
+ linux_regs->ARM_pc = addr;
+ else if (compiled_break == 1)
+ linux_regs->ARM_pc += 4;
+
+ compiled_break = 0;
+
+ return 0;
+ }
+
+ return -1;
+}
+
+static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr)
+{
+ kgdb_handle_exception(1, SIGTRAP, 0, regs);
+
+ return 0;
+}
+
+static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr)
+{
+ compiled_break = 1;
+ kgdb_handle_exception(1, SIGTRAP, 0, regs);
+
+ return 0;
+}
+
+static struct undef_hook kgdb_brkpt_hook = {
+ .instr_mask = 0xffffffff,
+ .instr_val = KGDB_BREAKINST,
+ .fn = kgdb_brk_fn
+};
+
+static struct undef_hook kgdb_compiled_brkpt_hook = {
+ .instr_mask = 0xffffffff,
+ .instr_val = KGDB_COMPILED_BREAK,
+ .fn = kgdb_compiled_brk_fn
+};
+
+/**
+ * kgdb_arch_init - Perform any architecture specific initalization.
+ *
+ * This function will handle the initalization of any architecture
+ * specific callbacks.
+ */
+int kgdb_arch_init(void)
+{
+ register_undef_hook(&kgdb_brkpt_hook);
+ register_undef_hook(&kgdb_compiled_brkpt_hook);
+
+ return 0;
+}
+
+/**
+ * kgdb_arch_exit - Perform any architecture specific uninitalization.
+ *
+ * This function will handle the uninitalization of any architecture
+ * specific callbacks, for dynamic registration and unregistration.
+ */
+void kgdb_arch_exit(void)
+{
+ unregister_undef_hook(&kgdb_brkpt_hook);
+ unregister_undef_hook(&kgdb_compiled_brkpt_hook);
+}
+
+/*
+ * Register our undef instruction hooks with ARM undef core.
+ * We regsiter a hook specifically looking for the KGB break inst
+ * and we handle the normal undef case within the do_undefinstr
+ * handler.
+ */
+struct kgdb_arch arch_kgdb_ops = {
+#ifndef __ARMEB__
+ .gdb_bpt_instr = {0xfe, 0xde, 0xff, 0xe7}
+#else /* ! __ARMEB__ */
+ .gdb_bpt_instr = {0xe7, 0xff, 0xde, 0xfe}
+#endif
+};
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 5ee39e10c8d..d28513f14d0 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -296,8 +296,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
INIT_HLIST_HEAD(&empty_rp);
- spin_lock_irqsave(&kretprobe_lock, flags);
- head = kretprobe_inst_table_head(current);
+ kretprobe_hash_lock(current, &head, &flags);
/*
* It is possible to have multiple instances associated with a given
@@ -337,7 +336,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
}
kretprobe_assert(ri, orig_ret_address, trampoline_address);
- spin_unlock_irqrestore(&kretprobe_lock, flags);
+ kretprobe_hash_unlock(current, &flags);
hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
hlist_del(&ri->hlist);
@@ -347,7 +346,6 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
return (void *)orig_ret_address;
}
-/* Called with kretprobe_lock held. */
void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
struct pt_regs *regs)
{
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 79b7e5cf541..a68259a0ccc 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/moduleloader.h>
#include <linux/kernel.h>
+#include <linux/mm.h>
#include <linux/elf.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 199b3680118..89bfded70a1 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -162,7 +162,7 @@ void cpu_idle(void)
if (!idle)
idle = default_idle;
leds_event(led_idle_start);
- tick_nohz_stop_sched_tick();
+ tick_nohz_stop_sched_tick(1);
while (!need_resched())
idle();
leds_event(led_idle_end);
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index b7b0720bc1b..38f0e7940a1 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -36,6 +36,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
+#include <asm/traps.h>
#include "compat.h"
#include "atags.h"
@@ -853,6 +854,7 @@ void __init setup_arch(char **cmdline_p)
conswitchp = &dummy_con;
#endif
#endif
+ early_trap_init();
}
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index cc5145b28e7..368d171754c 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -130,7 +130,9 @@ static const struct leds_evt_name evt_names[] = {
{ "red", led_red_on, led_red_off },
};
-static ssize_t leds_store(struct sys_device *dev, const char *buf, size_t size)
+static ssize_t leds_store(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ const char *buf, size_t size)
{
int ret = -EINVAL, len = strcspn(buf, " ");
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 5595fdd75e8..7277aef8309 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -708,6 +708,11 @@ EXPORT_SYMBOL(abort);
void __init trap_init(void)
{
+ return;
+}
+
+void __init early_trap_init(void)
+{
unsigned long vectors = CONFIG_VECTORS_BASE;
extern char __stubs_start[], __stubs_end[];
extern char __vectors_start[], __vectors_end[];
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index 62e653a3ea1..5a1588cf824 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -393,9 +393,7 @@ static int impd1_probe(struct lm_device *dev)
if (!d)
continue;
- snprintf(d->dev.bus_id, sizeof(d->dev.bus_id),
- "lm%x:%5.5lx", dev->id, idev->offset >> 12);
-
+ dev_set_name(&d->dev, "lm%x:%5.5lx", dev->id, idev->offset >> 12);
d->dev.parent = &dev->dev;
d->res.start = dev->resource.start + idev->offset;
d->res.end = d->res.start + SZ_4K - 1;
@@ -407,8 +405,7 @@ static int impd1_probe(struct lm_device *dev)
ret = amba_device_register(d, &dev->resource);
if (ret) {
- printk("unable to register device %s: %d\n",
- d->dev.bus_id, ret);
+ dev_err(&d->dev, "unable to register device: %d\n");
kfree(d);
}
}
diff --git a/arch/arm/mach-integrator/lm.c b/arch/arm/mach-integrator/lm.c
index 622cdc4212d..f939c509140 100644
--- a/arch/arm/mach-integrator/lm.c
+++ b/arch/arm/mach-integrator/lm.c
@@ -81,8 +81,10 @@ int lm_device_register(struct lm_device *dev)
dev->dev.release = lm_device_release;
dev->dev.bus = &lm_bustype;
- snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), "lm%d", dev->id);
- dev->resource.name = dev->dev.bus_id;
+ ret = dev_set_name(&dev->dev, "lm%d", dev->id);
+ if (ret)
+ return ret;
+ dev->resource.name = dev_name(&dev->dev);
ret = request_resource(&iomem_resource, &dev->resource);
if (ret == 0) {
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index 2741063bf36..28f164ea472 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -17,6 +17,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/f75375s.h>
+#include <linux/leds-pca9532.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/pci.h>
@@ -206,6 +207,53 @@ static struct f75375s_platform_data n2100_f75375s = {
.pwm_enable = { 0, 0 },
};
+static struct pca9532_platform_data n2100_leds = {
+ .leds = {
+ { .name = "n2100:red:satafail0",
+ .state = PCA9532_OFF,
+ .type = PCA9532_TYPE_LED,
+ },
+ { .name = "n2100:red:satafail1",
+ .state = PCA9532_OFF,
+ .type = PCA9532_TYPE_LED,
+ },
+ { .name = "n2100:blue:usb",
+ .state = PCA9532_OFF,
+ .type = PCA9532_TYPE_LED,
+ },
+ { .type = PCA9532_TYPE_NONE },
+
+ { .type = PCA9532_TYPE_NONE },
+ { .type = PCA9532_TYPE_NONE },
+ { .type = PCA9532_TYPE_NONE },
+ { .name = "n2100:red:usb",
+ .state = PCA9532_OFF,
+ .type = PCA9532_TYPE_LED,
+ },
+
+ { .type = PCA9532_TYPE_NONE }, /* power OFF gpio */
+ { .type = PCA9532_TYPE_NONE }, /* reset gpio */
+ { .type = PCA9532_TYPE_NONE },
+ { .type = PCA9532_TYPE_NONE },
+
+ { .type = PCA9532_TYPE_NONE },
+ { .name = "n2100:orange:system",
+ .state = PCA9532_OFF,
+ .type = PCA9532_TYPE_LED,
+ },
+ { .name = "n2100:red:system",
+ .state = PCA9532_OFF,
+ .type = PCA9532_TYPE_LED,
+ },
+ { .name = "N2100 beeper" ,
+ .state = PCA9532_OFF,
+ .type = PCA9532_TYPE_N2100_BEEP,
+ },
+ },
+ .psc = { 0, 0 },
+ .pwm = { 0, 0 },
+};
+
static struct i2c_board_info __initdata n2100_i2c_devices[] = {
{
I2C_BOARD_INFO("rs5c372b", 0x32),
@@ -214,6 +262,10 @@ static struct i2c_board_info __initdata n2100_i2c_devices[] = {
I2C_BOARD_INFO("f75375", 0x2e),
.platform_data = &n2100_f75375s,
},
+ {
+ I2C_BOARD_INFO("pca9532", 0x60),
+ .platform_data = &n2100_leds,
+ },
};
/*
diff --git a/arch/arm/mach-ns9xxx/clock.c b/arch/arm/mach-ns9xxx/clock.c
index f8639161068..44ed20d4a38 100644
--- a/arch/arm/mach-ns9xxx/clock.c
+++ b/arch/arm/mach-ns9xxx/clock.c
@@ -14,8 +14,8 @@
#include <linux/clk.h>
#include <linux/string.h>
#include <linux/platform_device.h>
+#include <linux/semaphore.h>
-#include <asm/semaphore.h>
#include "clock.h"
static LIST_HEAD(clocks);
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 914bb33dab9..e8ee7ec9ff6 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -16,18 +16,24 @@ config CPU_PXA310
config CPU_PXA320
bool "PXA320 (codename Monahans-P)"
+config CPU_PXA930
+ bool "PXA930 (codename Tavor-P)"
+
endmenu
endif
-menu "Select target boards"
-
config ARCH_GUMSTIX
bool "Gumstix XScale boards"
help
Say Y here if you intend to run this kernel on a
Gumstix Full Function Minature Computer.
+config MACH_GUMSTIX_F
+ bool "Basix, Connex, ws-200ax, ws-400ax systems"
+ depends on ARCH_GUMSTIX
+ select PXA25x
+
config ARCH_LUBBOCK
bool "Intel DBPXA250 Development Platform"
select PXA25x
@@ -58,6 +64,57 @@ config PXA_SHARPSL
SL-C3000 (Spitz), SL-C3100 (Borzoi) or SL-C6000x (Tosa)
handheld computer.
+config MACH_POODLE
+ bool "Enable Sharp SL-5600 (Poodle) Support"
+ depends on PXA_SHARPSL
+ select PXA25x
+ select SHARP_LOCOMO
+ select PXA_SSP
+
+config MACH_CORGI
+ bool "Enable Sharp SL-C700 (Corgi) Support"
+ depends on PXA_SHARPSL
+ select PXA25x
+ select PXA_SHARP_C7xx
+
+config MACH_SHEPHERD
+ bool "Enable Sharp SL-C750 (Shepherd) Support"
+ depends on PXA_SHARPSL
+ select PXA25x
+ select PXA_SHARP_C7xx
+
+config MACH_HUSKY
+ bool "Enable Sharp SL-C760 (Husky) Support"
+ depends on PXA_SHARPSL
+ select PXA25x
+ select PXA_SHARP_C7xx
+
+config MACH_AKITA
+ bool "Enable Sharp SL-1000 (Akita) Support"
+ depends on PXA_SHARPSL
+ select PXA27x
+ select PXA_SHARP_Cxx00
+ select MACH_SPITZ
+ select I2C
+ select I2C_PXA
+
+config MACH_SPITZ
+ bool "Enable Sharp Zaurus SL-3000 (Spitz) Support"
+ depends on PXA_SHARPSL
+ select PXA27x
+ select PXA_SHARP_Cxx00
+
+config MACH_BORZOI
+ bool "Enable Sharp Zaurus SL-3100 (Borzoi) Support"
+ depends on PXA_SHARPSL
+ select PXA27x
+ select PXA_SHARP_Cxx00
+
+config MACH_TOSA
+ bool "Enable Sharp SL-6000x (Tosa) Support"
+ depends on PXA_SHARPSL
+ select PXA25x
+
config ARCH_PXA_ESERIES
bool "PXA based Toshiba e-series PDAs"
select PXA25x
@@ -70,10 +127,19 @@ config MACH_E330
Say Y here if you intend to run this kernel on a Toshiba
e330 family PDA.
+config MACH_E350
+ bool "Toshiba e350"
+ default y
+ depends on ARCH_PXA_ESERIES
+ help
+ Say Y here if you intend to run this kernel on a Toshiba
+ e350 family PDA.
+
config MACH_E740
bool "Toshiba e740"
default y
depends on ARCH_PXA_ESERIES
+ select FB_W100
help
Say Y here if you intend to run this kernel on a Toshiba
e740 family PDA.
@@ -82,6 +148,7 @@ config MACH_E750
bool "Toshiba e750"
default y
depends on ARCH_PXA_ESERIES
+ select FB_W100
help
Say Y here if you intend to run this kernel on a Toshiba
e750 family PDA.
@@ -98,6 +165,7 @@ config MACH_E800
bool "Toshiba e800"
default y
depends on ARCH_PXA_ESERIES
+ select FB_W100
help
Say Y here if you intend to run this kernel on a Toshiba
e800 family PDA.
@@ -106,6 +174,10 @@ config MACH_TRIZEPS4
bool "Keith und Koep Trizeps4 DIMM-Module"
select PXA27x
+config MACH_TRIZEPS4_CONXS
+ bool "ConXS Eval Board"
+ depends on MACH_TRIZEPS4
+
config MACH_EM_X270
bool "CompuLab EM-x270 platform"
select PXA27x
@@ -115,7 +187,7 @@ config MACH_COLIBRI
select PXA27x
config MACH_ZYLONITE
- bool "PXA3xx Development Platform"
+ bool "PXA3xx Development Platform (aka Zylonite)"
select PXA3xx
select HAVE_PWM
@@ -124,6 +196,16 @@ config MACH_LITTLETON
select PXA3xx
select PXA_SSP
+config MACH_TAVOREVB
+ bool "PXA930 Evaluation Board (aka TavorEVB)"
+ select PXA3xx
+ select PXA930
+
+config MACH_SAAR
+ bool "PXA930 Handheld Platform (aka SAAR)"
+ select PXA3xx
+ select PXA930
+
config MACH_ARMCORE
bool "CompuLab CM-X270 modules"
select PXA27x
@@ -131,7 +213,6 @@ config MACH_ARMCORE
config MACH_MAGICIAN
bool "Enable HTC Magician Support"
- depends on ARCH_PXA
select PXA27x
select IWMMXT
@@ -139,18 +220,26 @@ config MACH_PCM027
bool "Phytec phyCORE-PXA270 CPU module (PCM-027)"
select PXA27x
select IWMMXT
+ select PXA_SSP
-endmenu
+config ARCH_PXA_PALM
+ bool "PXA based Palm PDAs"
+ select HAVE_PWM
-choice
- prompt "Used baseboard"
- depends on MACH_PCM027
+config MACH_PALMTX
+ bool "Palm T|X"
+ default y
+ depends on ARCH_PXA_PALM
+ select PXA27x
+ select IWMMXT
+ help
+ Say Y here if you intend to run this kernel on a Palm T|X
+ handheld computer.
config MACH_PCM990_BASEBOARD
bool "PHYTEC PCM-990 development board"
select HAVE_PWM
-
-endchoice
+ depends on MACH_PCM027
choice
prompt "display on pcm990"
@@ -167,88 +256,45 @@ config PCM990_DISPLAY_NONE
endchoice
-if ARCH_GUMSTIX
-
-choice
- prompt "Select target Gumstix board"
-
-config MACH_GUMSTIX_F
- bool "Basix, Connex, ws-200ax, ws-400ax systems"
- select PXA25x
-
-endchoice
-
-endif
+config PXA_EZX
+ bool "Motorola EZX Platform"
+ select PXA27x
+ select IWMMXT
+ select HAVE_PWM
-if MACH_TRIZEPS4
+config MACH_EZX_A780
+ bool "Motorola EZX A780"
+ default y
+ depends on PXA_EZX
-choice
- prompt "Select base board for Trizeps 4 module"
+config MACH_EZX_E680
+ bool "Motorola EZX E680"
+ default y
+ depends on PXA_EZX
-config MACH_TRIZEPS4_CONXS
- bool "ConXS Eval Board"
+config MACH_EZX_A1200
+ bool "Motorola EZX A1200"
+ default y
+ depends on PXA_EZX
-config MACH_TRIZEPS4_ANY
- bool "another Board"
+config MACH_EZX_A910
+ bool "Motorola EZX A910"
+ default y
+ depends on PXA_EZX
-endchoice
+config MACH_EZX_E6
+ bool "Motorola EZX E6"
+ default y
+ depends on PXA_EZX
-endif
+config MACH_EZX_E2
+ bool "Motorola EZX E2"
+ default y
+ depends on PXA_EZX
endmenu
-config MACH_POODLE
- bool "Enable Sharp SL-5600 (Poodle) Support"
- depends on PXA_SHARPSL
- select PXA25x
- select SHARP_LOCOMO
- select PXA_SSP
-
-config MACH_CORGI
- bool "Enable Sharp SL-C700 (Corgi) Support"
- depends on PXA_SHARPSL
- select PXA25x
- select PXA_SHARP_C7xx
-
-config MACH_SHEPHERD
- bool "Enable Sharp SL-C750 (Shepherd) Support"
- depends on PXA_SHARPSL
- select PXA25x
- select PXA_SHARP_C7xx
-
-config MACH_HUSKY
- bool "Enable Sharp SL-C760 (Husky) Support"
- depends on PXA_SHARPSL
- select PXA25x
- select PXA_SHARP_C7xx
-
-config MACH_AKITA
- bool "Enable Sharp SL-1000 (Akita) Support"
- depends on PXA_SHARPSL
- select PXA27x
- select PXA_SHARP_Cxx00
- select MACH_SPITZ
- select I2C
- select I2C_PXA
-
-config MACH_SPITZ
- bool "Enable Sharp Zaurus SL-3000 (Spitz) Support"
- depends on PXA_SHARPSL
- select PXA27x
- select PXA_SHARP_Cxx00
-
-config MACH_BORZOI
- bool "Enable Sharp Zaurus SL-3100 (Borzoi) Support"
- depends on PXA_SHARPSL
- select PXA27x
- select PXA_SHARP_Cxx00
-
-config MACH_TOSA
- bool "Enable Sharp SL-6000x (Tosa) Support"
- depends on PXA_SHARPSL
- select PXA25x
-
config PXA25x
bool
help
@@ -288,4 +334,13 @@ config PXA_PWM
default BACKLIGHT_PWM
help
Enable support for PXA2xx/PXA3xx PWM controllers
+
+config TOSA_BT
+ tristate "Control the state of built-in bluetooth chip on Sharp SL-6000"
+ depends on MACH_TOSA
+ select RFKILL
+ help
+ This is a simple driver that is able to control
+ the state of built in bluetooth chip on tosa.
+
endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index c4dfbe87fc4..99ecbe7f850 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -4,7 +4,7 @@
# Common support (must be linked before board specific support)
obj-y += clock.o devices.o generic.o irq.o dma.o \
- time.o gpio.o
+ time.o gpio.o reset.o
obj-$(CONFIG_PM) += pm.o sleep.o standby.o
obj-$(CONFIG_CPU_FREQ) += cpu-pxa.o
@@ -18,6 +18,7 @@ obj-$(CONFIG_PXA27x) += mfp-pxa2xx.o pxa2xx.o pxa27x.o
obj-$(CONFIG_PXA3xx) += mfp-pxa3xx.o pxa3xx.o smemc.o
obj-$(CONFIG_CPU_PXA300) += pxa300.o
obj-$(CONFIG_CPU_PXA320) += pxa320.o
+obj-$(CONFIG_CPU_PXA930) += pxa930.o
# Specific board support
obj-$(CONFIG_ARCH_GUMSTIX) += gumstix.o
@@ -36,7 +37,12 @@ obj-$(CONFIG_MACH_PCM990_BASEBOARD) += pcm990-baseboard.o
obj-$(CONFIG_MACH_TOSA) += tosa.o
obj-$(CONFIG_MACH_EM_X270) += em-x270.o
obj-$(CONFIG_MACH_MAGICIAN) += magician.o
-obj-$(CONFIG_ARCH_PXA_ESERIES) += eseries.o
+obj-$(CONFIG_ARCH_PXA_ESERIES) += eseries.o eseries_udc.o
+obj-$(CONFIG_MACH_E740) += e740_lcd.o
+obj-$(CONFIG_MACH_E750) += e750_lcd.o
+obj-$(CONFIG_MACH_E400) += e400_lcd.o
+obj-$(CONFIG_MACH_E800) += e800_lcd.o
+obj-$(CONFIG_MACH_PALMTX) += palmtx.o
ifeq ($(CONFIG_MACH_ZYLONITE),y)
obj-y += zylonite.o
@@ -44,8 +50,11 @@ ifeq ($(CONFIG_MACH_ZYLONITE),y)
obj-$(CONFIG_CPU_PXA320) += zylonite_pxa320.o
endif
obj-$(CONFIG_MACH_LITTLETON) += littleton.o
+obj-$(CONFIG_MACH_TAVOREVB) += tavorevb.o
+obj-$(CONFIG_MACH_SAAR) += saar.o
obj-$(CONFIG_MACH_ARMCORE) += cm-x270.o
+obj-$(CONFIG_PXA_EZX) += ezx.o
# Support for blinky lights
led-y := leds.o
@@ -59,3 +68,5 @@ obj-$(CONFIG_LEDS) += $(led-y)
ifeq ($(CONFIG_PCI),y)
obj-$(CONFIG_MACH_ARMCORE) += cm-x270-pci.o
endif
+
+obj-$(CONFIG_TOSA_BT) += tosa-bt.o
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index b4d04955dcb..630063ffa6f 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -101,21 +101,6 @@ unsigned long clk_get_rate(struct clk *clk)
EXPORT_SYMBOL(clk_get_rate);
-static void clk_gpio27_enable(struct clk *clk)
-{
- pxa_gpio_mode(GPIO11_3_6MHz_MD);
-}
-
-static void clk_gpio27_disable(struct clk *clk)
-{
-}
-
-static const struct clkops clk_gpio27_ops = {
- .enable = clk_gpio27_enable,
- .disable = clk_gpio27_disable,
-};
-
-
void clk_cken_enable(struct clk *clk)
{
CKEN |= 1 << clk->cken;
@@ -131,14 +116,6 @@ const struct clkops clk_cken_ops = {
.disable = clk_cken_disable,
};
-static struct clk common_clks[] = {
- {
- .name = "GPIO27_CLK",
- .ops = &clk_gpio27_ops,
- .rate = 3686400,
- },
-};
-
void clks_register(struct clk *clks, size_t num)
{
int i;
@@ -148,10 +125,3 @@ void clks_register(struct clk *clks, size_t num)
list_add(&clks[i].node, &clocks);
mutex_unlock(&clocks_mutex);
}
-
-static int __init clk_init(void)
-{
- clks_register(common_clks, ARRAY_SIZE(common_clks));
- return 0;
-}
-arch_initcall(clk_init);
diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h
index 83cbfaba485..1ec8f9178aa 100644
--- a/arch/arm/mach-pxa/clock.h
+++ b/arch/arm/mach-pxa/clock.h
@@ -47,9 +47,42 @@ struct clk {
.other = _other, \
}
+#define INIT_CLK(_name, _ops, _rate, _delay, _dev) \
+ { \
+ .name = _name, \
+ .dev = _dev, \
+ .ops = _ops, \
+ .rate = _rate, \
+ .delay = _delay, \
+ }
+
extern const struct clkops clk_cken_ops;
void clk_cken_enable(struct clk *clk);
void clk_cken_disable(struct clk *clk);
+#ifdef CONFIG_PXA3xx
+#define PXA3xx_CKEN(_name, _cken, _rate, _delay, _dev) \
+ { \
+ .name = _name, \
+ .dev = _dev, \
+ .ops = &clk_pxa3xx_cken_ops, \
+ .rate = _rate, \
+ .cken = CKEN_##_cken, \
+ .delay = _delay, \
+ }
+
+#define PXA3xx_CK(_name, _cken, _ops, _dev) \
+ { \
+ .name = _name, \
+ .dev = _dev, \
+ .ops = _ops, \
+ .cken = CKEN_##_cken, \
+ }
+
+extern const struct clkops clk_pxa3xx_cken_ops;
+extern void clk_pxa3xx_cken_enable(struct clk *);
+extern void clk_pxa3xx_cken_disable(struct clk *);
+#endif
+
void clks_register(struct clk *clks, size_t num);
diff --git a/arch/arm/mach-pxa/cm-x270-pci.c b/arch/arm/mach-pxa/cm-x270-pci.c
index 319c9ff3ab9..bcf0cde6ccc 100644
--- a/arch/arm/mach-pxa/cm-x270-pci.c
+++ b/arch/arm/mach-pxa/cm-x270-pci.c
@@ -5,7 +5,7 @@
*
* Bits taken from various places.
*
- * Copyright (C) 2007 Compulab, Ltd.
+ * Copyright (C) 2007, 2008 Compulab, Ltd.
* Mike Rapoport <mike@compulab.co.il>
*
* This program is free software; you can redistribute it and/or modify
@@ -19,16 +19,16 @@
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
+#include <linux/gpio.h>
#include <asm/mach/pci.h>
-#include <asm/arch/cm-x270.h>
#include <asm/arch/pxa-regs.h>
-#include <asm/arch/pxa2xx-gpio.h>
#include <asm/mach-types.h>
#include <asm/hardware/it8152.h>
-unsigned long it8152_base_address = CMX270_IT8152_VIRT;
+unsigned long it8152_base_address;
+static int cmx270_it8152_irq_gpio;
/*
* Only first 64MB of memory can be accessed via PCI.
@@ -42,7 +42,7 @@ void __init cmx270_pci_adjust_zones(int node, unsigned long *zone_size,
unsigned int sz = SZ_64M >> PAGE_SHIFT;
if (machine_is_armcore()) {
- pr_info("Adjusting zones for CM-x270\n");
+ pr_info("Adjusting zones for CM-X270\n");
/*
* Only adjust if > 64M on current system
@@ -60,19 +60,20 @@ void __init cmx270_pci_adjust_zones(int node, unsigned long *zone_size,
static void cmx270_it8152_irq_demux(unsigned int irq, struct irq_desc *desc)
{
/* clear our parent irq */
- GEDR(GPIO_IT8152_IRQ) = GPIO_bit(GPIO_IT8152_IRQ);
+ GEDR(cmx270_it8152_irq_gpio) = GPIO_bit(cmx270_it8152_irq_gpio);
it8152_irq_demux(irq, desc);
}
-void __cmx270_pci_init_irq(void)
+void __cmx270_pci_init_irq(int irq_gpio)
{
it8152_init_irq();
- pxa_gpio_mode(IRQ_TO_GPIO(GPIO_IT8152_IRQ));
- set_irq_type(IRQ_GPIO(GPIO_IT8152_IRQ), IRQT_RISING);
- set_irq_chained_handler(IRQ_GPIO(GPIO_IT8152_IRQ),
- cmx270_it8152_irq_demux);
+ cmx270_it8152_irq_gpio = irq_gpio;
+
+ set_irq_type(gpio_to_irq(irq_gpio), IRQT_RISING);
+
+ set_irq_chained_handler(gpio_to_irq(irq_gpio), cmx270_it8152_irq_demux);
}
#ifdef CONFIG_PM
@@ -115,8 +116,8 @@ static int __init cmx270_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
/*
Here comes the ugly part. The routing is baseboard specific,
- but defining a platform for each possible base of CM-x270 is
- unrealistic. Here we keep mapping for ATXBase and SB-x270.
+ but defining a platform for each possible base of CM-X270 is
+ unrealistic. Here we keep mapping for ATXBase and SB-X270.
*/
/* ATXBASE PCI slot */
if (slot == 7)
diff --git a/arch/arm/mach-pxa/cm-x270-pci.h b/arch/arm/mach-pxa/cm-x270-pci.h
index ffe37b66f9a..48f532f4cb5 100644
--- a/arch/arm/mach-pxa/cm-x270-pci.h
+++ b/arch/arm/mach-pxa/cm-x270-pci.h
@@ -1,13 +1,13 @@
-extern void __cmx270_pci_init_irq(void);
+extern void __cmx270_pci_init_irq(int irq_gpio);
extern void __cmx270_pci_suspend(void);
extern void __cmx270_pci_resume(void);
#ifdef CONFIG_PCI
-#define cmx270_pci_init_irq __cmx270_pci_init_irq
-#define cmx270_pci_suspend __cmx270_pci_suspend
-#define cmx270_pci_resume __cmx270_pci_resume
+#define cmx270_pci_init_irq(x) __cmx270_pci_init_irq(x)
+#define cmx270_pci_suspend(x) __cmx270_pci_suspend(x)
+#define cmx270_pci_resume(x) __cmx270_pci_resume(x)
#else
-#define cmx270_pci_init_irq() do {} while (0)
-#define cmx270_pci_suspend() do {} while (0)
-#define cmx270_pci_resume() do {} while (0)
+#define cmx270_pci_init_irq(x) do {} while (0)
+#define cmx270_pci_suspend(x) do {} while (0)
+#define cmx270_pci_resume(x) do {} while (0)
#endif
diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
index 01b9964acec..402e807eae5 100644
--- a/arch/arm/mach-pxa/cm-x270.c
+++ b/arch/arm/mach-pxa/cm-x270.c
@@ -1,7 +1,7 @@
/*
* linux/arch/arm/mach-pxa/cm-x270.c
*
- * Copyright (C) 2007 CompuLab, Ltd.
+ * Copyright (C) 2007, 2008 CompuLab, Ltd.
* Mike Rapoport <mike@compulab.co.il>
*
* This program is free software; you can redistribute it and/or modify
@@ -9,44 +9,156 @@
* published by the Free Software Foundation.
*/
-#include <linux/types.h>
-#include <linux/pm.h>
-#include <linux/fb.h>
#include <linux/platform_device.h>
-#include <linux/irq.h>
#include <linux/sysdev.h>
-#include <linux/io.h>
-#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
#include <linux/dm9000.h>
#include <linux/rtc-v3020.h>
-#include <linux/serial_8250.h>
-
#include <video/mbxfb.h>
+#include <linux/leds.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
#include <asm/mach/map.h>
-#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-regs.h>
-#include <asm/arch/pxa2xx-gpio.h>
+#include <asm/arch/mfp-pxa27x.h>
+#include <asm/arch/pxa-regs.h>
#include <asm/arch/audio.h>
#include <asm/arch/pxafb.h>
#include <asm/arch/ohci.h>
#include <asm/arch/mmc.h>
#include <asm/arch/bitfield.h>
-#include <asm/arch/cm-x270.h>
#include <asm/hardware/it8152.h>
#include "generic.h"
#include "cm-x270-pci.h"
+/* virtual addresses for statically mapped regions */
+#define CMX270_VIRT_BASE (0xe8000000)
+#define CMX270_IT8152_VIRT (CMX270_VIRT_BASE)
+
#define RTC_PHYS_BASE (PXA_CS1_PHYS + (5 << 22))
#define DM9000_PHYS_BASE (PXA_CS1_PHYS + (6 << 22))
-static struct resource cmx270_dm9k_resource[] = {
+/* GPIO IRQ usage */
+#define GPIO10_ETHIRQ (10)
+#define GPIO22_IT8152_IRQ (22)
+#define GPIO83_MMC_IRQ (83)
+#define GPIO95_GFXIRQ (95)
+
+#define CMX270_ETHIRQ IRQ_GPIO(GPIO10_ETHIRQ)
+#define CMX270_IT8152_IRQ IRQ_GPIO(GPIO22_IT8152_IRQ)
+#define CMX270_MMC_IRQ IRQ_GPIO(GPIO83_MMC_IRQ)
+#define CMX270_GFXIRQ IRQ_GPIO(GPIO95_GFXIRQ)
+
+/* MMC power enable */
+#define GPIO105_MMC_POWER (105)
+
+static unsigned long cmx270_pin_config[] = {
+ /* AC'97 */
+ GPIO28_AC97_BITCLK,
+ GPIO29_AC97_SDATA_IN_0,
+ GPIO30_AC97_SDATA_OUT,
+ GPIO31_AC97_SYNC,
+ GPIO98_AC97_SYSCLK,
+ GPIO113_AC97_nRESET,
+
+ /* BTUART */
+ GPIO42_BTUART_RXD,
+ GPIO43_BTUART_TXD,
+ GPIO44_BTUART_CTS,
+ GPIO45_BTUART_RTS,
+
+ /* STUART */
+ GPIO46_STUART_RXD,
+ GPIO47_STUART_TXD,
+
+ /* MCI controller */
+ GPIO32_MMC_CLK,
+ GPIO112_MMC_CMD,
+ GPIO92_MMC_DAT_0,
+ GPIO109_MMC_DAT_1,
+ GPIO110_MMC_DAT_2,
+ GPIO111_MMC_DAT_3,
+
+ /* LCD */
+ GPIO58_LCD_LDD_0,
+ GPIO59_LCD_LDD_1,
+ GPIO60_LCD_LDD_2,
+ GPIO61_LCD_LDD_3,
+ GPIO62_LCD_LDD_4,
+ GPIO63_LCD_LDD_5,
+ GPIO64_LCD_LDD_6,
+ GPIO65_LCD_LDD_7,
+ GPIO66_LCD_LDD_8,
+ GPIO67_LCD_LDD_9,
+ GPIO68_LCD_LDD_10,
+ GPIO69_LCD_LDD_11,
+ GPIO70_LCD_LDD_12,
+ GPIO71_LCD_LDD_13,
+ GPIO72_LCD_LDD_14,
+ GPIO73_LCD_LDD_15,
+ GPIO74_LCD_FCLK,
+ GPIO75_LCD_LCLK,
+ GPIO76_LCD_PCLK,
+ GPIO77_LCD_BIAS,
+
+ /* I2C */
+ GPIO117_I2C_SCL,
+ GPIO118_I2C_SDA,
+
+ /* SSP1 */
+ GPIO23_SSP1_SCLK,
+ GPIO24_SSP1_SFRM,
+ GPIO25_SSP1_TXD,
+ GPIO26_SSP1_RXD,
+
+ /* SSP2 */
+ GPIO19_SSP2_SCLK,
+ GPIO14_SSP2_SFRM,
+ GPIO87_SSP2_TXD,
+ GPIO88_SSP2_RXD,
+
+ /* PC Card */
+ GPIO48_nPOE,
+ GPIO49_nPWE,
+ GPIO50_nPIOR,
+ GPIO51_nPIOW,
+ GPIO85_nPCE_1,
+ GPIO54_nPCE_2,
+ GPIO55_nPREG,
+ GPIO56_nPWAIT,
+ GPIO57_nIOIS16,
+
+ /* SDRAM and local bus */
+ GPIO15_nCS_1,
+ GPIO78_nCS_2,
+ GPIO79_nCS_3,
+ GPIO80_nCS_4,
+ GPIO33_nCS_5,
+ GPIO49_nPWE,
+ GPIO18_RDY,
+
+ /* GPIO */
+ GPIO0_GPIO | WAKEUP_ON_EDGE_BOTH,
+ GPIO105_GPIO | MFP_LPM_DRIVE_HIGH, /* MMC/SD power */
+ GPIO53_GPIO, /* PC card reset */
+
+ /* NAND controls */
+ GPIO11_GPIO | MFP_LPM_DRIVE_HIGH, /* NAND CE# */
+ GPIO89_GPIO, /* NAND Ready/Busy */
+
+ /* interrupts */
+ GPIO10_GPIO, /* DM9000 interrupt */
+ GPIO83_GPIO, /* MMC card detect */
+};
+
+#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+static struct resource cmx270_dm9000_resource[] = {
[0] = {
.start = DM9000_PHYS_BASE,
.end = DM9000_PHYS_BASE + 4,
@@ -64,31 +176,45 @@ static struct resource cmx270_dm9k_resource[] = {
}
};
-/* for the moment we limit ourselves to 32bit IO until some
- * better IO routines can be written and tested
- */
-static struct dm9000_plat_data cmx270_dm9k_platdata = {
+static struct dm9000_plat_data cmx270_dm9000_platdata = {
.flags = DM9000_PLATF_32BITONLY,
};
-/* Ethernet device */
-static struct platform_device cmx270_device_dm9k = {
+static struct platform_device cmx270_dm9000_device = {
.name = "dm9000",
.id = 0,
- .num_resources = ARRAY_SIZE(cmx270_dm9k_resource),
- .resource = cmx270_dm9k_resource,
+ .num_resources = ARRAY_SIZE(cmx270_dm9000_resource),
+ .resource = cmx270_dm9000_resource,
.dev = {
- .platform_data = &cmx270_dm9k_platdata,
+ .platform_data = &cmx270_dm9000_platdata,
}
};
-/* touchscreen controller */
+static void __init cmx270_init_dm9000(void)
+{
+ platform_device_register(&cmx270_dm9000_device);
+}
+#else
+static inline void cmx270_init_dm9000(void) {}
+#endif
+
+/* UCB1400 touchscreen controller */
+#if defined(CONFIG_TOUCHSCREEN_UCB1400) || defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE)
static struct platform_device cmx270_ts_device = {
.name = "ucb1400_ts",
.id = -1,
};
-/* RTC */
+static void __init cmx270_init_touchscreen(void)
+{
+ platform_device_register(&cmx270_ts_device);
+}
+#else
+static inline void cmx270_init_touchscreen(void) {}
+#endif
+
+/* V3020 RTC */
+#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE)
static struct resource cmx270_v3020_resource[] = {
[0] = {
.start = RTC_PHYS_BASE,
@@ -111,28 +237,67 @@ static struct platform_device cmx270_rtc_device = {
}
};
-/*
- * CM-X270 LEDs
- */
+static void __init cmx270_init_rtc(void)
+{
+ platform_device_register(&cmx270_rtc_device);
+}
+#else
+static inline void cmx270_init_rtc(void) {}
+#endif
+
+/* CM-X270 LEDs */
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+static struct gpio_led cmx270_leds[] = {
+ [0] = {
+ .name = "cm-x270:red",
+ .default_trigger = "nand-disk",
+ .gpio = 93,
+ .active_low = 1,
+ },
+ [1] = {
+ .name = "cm-x270:green",
+ .default_trigger = "heartbeat",
+ .gpio = 94,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led_platform_data cmx270_gpio_led_pdata = {
+ .num_leds = ARRAY_SIZE(cmx270_leds),
+ .leds = cmx270_leds,
+};
+
static struct platform_device cmx270_led_device = {
- .name = "cm-x270-led",
+ .name = "leds-gpio",
.id = -1,
+ .dev = {
+ .platform_data = &cmx270_gpio_led_pdata,
+ },
};
+static void __init cmx270_init_leds(void)
+{
+ platform_device_register(&cmx270_led_device);
+}
+#else
+static inline void cmx270_init_leds(void) {}
+#endif
+
/* 2700G graphics */
+#if defined(CONFIG_FB_MBX) || defined(CONFIG_FB_MBX_MODULE)
static u64 fb_dma_mask = ~(u64)0;
static struct resource cmx270_2700G_resource[] = {
/* frame buffer memory including ODFB and External SDRAM */
[0] = {
- .start = MARATHON_PHYS,
- .end = MARATHON_PHYS + 0x02000000,
+ .start = PXA_CS2_PHYS,
+ .end = PXA_CS2_PHYS + 0x01ffffff,
.flags = IORESOURCE_MEM,
},
/* Marathon registers */
[1] = {
- .start = MARATHON_PHYS + 0x03fe0000,
- .end = MARATHON_PHYS + 0x03ffffff,
+ .start = PXA_CS2_PHYS + 0x03fe0000,
+ .end = PXA_CS2_PHYS + 0x03ffffff,
.flags = IORESOURCE_MEM,
},
};
@@ -200,43 +365,15 @@ static struct platform_device cmx270_2700G = {
.id = -1,
};
-static u64 ata_dma_mask = ~(u64)0;
-
-static struct platform_device cmx270_ata = {
- .name = "pata_cm_x270",
- .id = -1,
- .dev = {
- .dma_mask = &ata_dma_mask,
- .coherent_dma_mask = 0xffffffff,
- },
-};
-
-/* platform devices */
-static struct platform_device *platform_devices[] __initdata = {
- &cmx270_device_dm9k,
- &cmx270_rtc_device,
- &cmx270_2700G,
- &cmx270_led_device,
- &cmx270_ts_device,
- &cmx270_ata,
-};
-
-/* Map PCI companion and IDE/General Purpose CS statically */
-static struct map_desc cmx270_io_desc[] __initdata = {
- [0] = { /* IDE/general purpose space */
- .virtual = CMX270_IDE104_VIRT,
- .pfn = __phys_to_pfn(CMX270_IDE104_PHYS),
- .length = SZ_64M - SZ_8M,
- .type = MT_DEVICE
- },
- [1] = { /* PCI bridge */
- .virtual = CMX270_IT8152_VIRT,
- .pfn = __phys_to_pfn(CMX270_IT8152_PHYS),
- .length = SZ_64M,
- .type = MT_DEVICE
- },
-};
+static void __init cmx270_init_2700G(void)
+{
+ platform_device_register(&cmx270_2700G);
+}
+#else
+static inline void cmx270_init_2700G(void) {}
+#endif
+#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
/*
Display definitions
keep these for backwards compatibility, although symbolic names (as
@@ -446,7 +583,16 @@ static int __init cmx270_set_display(char *str)
*/
__setup("monitor=", cmx270_set_display);
+static void __init cmx270_init_display(void)
+{
+ set_pxa_fb_info(cmx270_display);
+}
+#else
+static inline void cmx270_init_display(void) {}
+#endif
+
/* PXA27x OHCI controller setup */
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
static int cmx270_ohci_init(struct device *dev)
{
/* Set the Power Control Polarity Low */
@@ -461,35 +607,37 @@ static struct pxaohci_platform_data cmx270_ohci_platform_data = {
.init = cmx270_ohci_init,
};
+static void __init cmx270_init_ohci(void)
+{
+ pxa_set_ohci_info(&cmx270_ohci_platform_data);
+}
+#else
+static inline void cmx270_init_ohci(void) {}
+#endif
+#if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE)
static int cmx270_mci_init(struct device *dev,
irq_handler_t cmx270_detect_int,
void *data)
{
int err;
- /*
- * setup GPIO for PXA27x MMC controller
- */
- pxa_gpio_mode(GPIO32_MMCCLK_MD);
- pxa_gpio_mode(GPIO112_MMCCMD_MD);
- pxa_gpio_mode(GPIO92_MMCDAT0_MD);
- pxa_gpio_mode(GPIO109_MMCDAT1_MD);
- pxa_gpio_mode(GPIO110_MMCDAT2_MD);
- pxa_gpio_mode(GPIO111_MMCDAT3_MD);
-
- /* SB-X270 uses GPIO105 as SD power enable */
- pxa_gpio_mode(105 | GPIO_OUT);
+ err = gpio_request(GPIO105_MMC_POWER, "MMC/SD power");
+ if (err) {
+ dev_warn(dev, "power gpio unavailable\n");
+ return err;
+ }
- /* card detect IRQ on GPIO 83 */
- pxa_gpio_mode(IRQ_TO_GPIO(CMX270_MMC_IRQ));
+ gpio_direction_output(GPIO105_MMC_POWER, 0);
err = request_irq(CMX270_MMC_IRQ, cmx270_detect_int,
IRQF_DISABLED | IRQF_TRIGGER_FALLING,
"MMC card detect", data);
- if (err)
- printk(KERN_ERR "cmx270_mci_init: MMC/SD: can't"
- " request MMC card detect IRQ\n");
+ if (err) {
+ gpio_free(GPIO105_MMC_POWER);
+ dev_err(dev, "cmx270_mci_init: MMC/SD: can't"
+ " request MMC card detect IRQ\n");
+ }
return err;
}
@@ -499,17 +647,18 @@ static void cmx270_mci_setpower(struct device *dev, unsigned int vdd)
struct pxamci_platform_data *p_d = dev->platform_data;
if ((1 << vdd) & p_d->ocr_mask) {
- printk(KERN_DEBUG "%s: on\n", __func__);
- GPCR(105) = GPIO_bit(105);
+ dev_dbg(dev, "power on\n");
+ gpio_set_value(GPIO105_MMC_POWER, 0);
} else {
- GPSR(105) = GPIO_bit(105);
- printk(KERN_DEBUG "%s: off\n", __func__);
+ gpio_set_value(GPIO105_MMC_POWER, 1);
+ dev_dbg(dev, "power off\n");
}
}
static void cmx270_mci_exit(struct device *dev, void *data)
{
free_irq(CMX270_MMC_IRQ, data);
+ gpio_free(GPIO105_MMC_POWER);
}
static struct pxamci_platform_data cmx270_mci_platform_data = {
@@ -519,6 +668,14 @@ static struct pxamci_platform_data cmx270_mci_platform_data = {
.exit = cmx270_mci_exit,
};
+static void __init cmx270_init_mmc(void)
+{
+ pxa_set_mci_info(&cmx270_mci_platform_data);
+}
+#else
+static inline void cmx270_init_mmc(void) {}
+#endif
+
#ifdef CONFIG_PM
static unsigned long sleep_save_msc[10];
@@ -580,53 +737,63 @@ static int __init cmx270_pm_init(void)
static int __init cmx270_pm_init(void) { return 0; }
#endif
-static void __init cmx270_init(void)
+#if defined(CONFIG_SND_PXA2XX_AC97) || defined(CONFIG_SND_PXA2XX_AC97_MODULE)
+static void __init cmx270_init_ac97(void)
{
- cmx270_pm_init();
-
- set_pxa_fb_info(cmx270_display);
-
- /* register CM-X270 platform devices */
- platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
pxa_set_ac97_info(NULL);
+}
+#else
+static inline void cmx270_init_ac97(void) {}
+#endif
- /* set MCI and OHCI platform parameters */
- pxa_set_mci_info(&cmx270_mci_platform_data);
- pxa_set_ohci_info(&cmx270_ohci_platform_data);
-
- /* This enables the STUART */
- pxa_gpio_mode(GPIO46_STRXD_MD);
- pxa_gpio_mode(GPIO47_STTXD_MD);
+static void __init cmx270_init(void)
+{
+ cmx270_pm_init();
- /* This enables the BTUART */
- pxa_gpio_mode(GPIO42_BTRXD_MD);
- pxa_gpio_mode(GPIO43_BTTXD_MD);
- pxa_gpio_mode(GPIO44_BTCTS_MD);
- pxa_gpio_mode(GPIO45_BTRTS_MD);
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(cmx270_pin_config));
+
+ cmx270_init_dm9000();
+ cmx270_init_rtc();
+ cmx270_init_display();
+ cmx270_init_mmc();
+ cmx270_init_ohci();
+ cmx270_init_ac97();
+ cmx270_init_touchscreen();
+ cmx270_init_leds();
+ cmx270_init_2700G();
}
static void __init cmx270_init_irq(void)
{
pxa27x_init_irq();
+ cmx270_pci_init_irq(GPIO22_IT8152_IRQ);
+}
- cmx270_pci_init_irq();
+#ifdef CONFIG_PCI
+/* Map PCI companion statically */
+static struct map_desc cmx270_io_desc[] __initdata = {
+ [0] = { /* PCI bridge */
+ .virtual = CMX270_IT8152_VIRT,
+ .pfn = __phys_to_pfn(PXA_CS4_PHYS),
+ .length = SZ_64M,
+ .type = MT_DEVICE
+ },
+};
- /* Setup interrupt for dm9000 */
- pxa_gpio_mode(IRQ_TO_GPIO(CMX270_ETHIRQ));
- set_irq_type(CMX270_ETHIRQ, IRQT_RISING);
+static void __init cmx270_map_io(void)
+{
+ pxa_map_io();
+ iotable_init(cmx270_io_desc, ARRAY_SIZE(cmx270_io_desc));
- /* Setup interrupt for 2700G */
- pxa_gpio_mode(IRQ_TO_GPIO(CMX270_GFXIRQ));
- set_irq_type(CMX270_GFXIRQ, IRQT_FALLING);
+ it8152_base_address = CMX270_IT8152_VIRT;
}
-
+#else
static void __init cmx270_map_io(void)
{
pxa_map_io();
- iotable_init(cmx270_io_desc, ARRAY_SIZE(cmx270_io_desc));
}
-
+#endif
MACHINE_START(ARMCORE, "Compulab CM-x270")
.boot_params = 0xa0000100,
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index b37671b7188..e58504edb14 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -465,6 +465,7 @@ static void corgi_irda_transceiver_mode(struct device *dev, int mode)
GPSR(CORGI_GPIO_IR_ON) = GPIO_bit(CORGI_GPIO_IR_ON);
else
GPCR(CORGI_GPIO_IR_ON) = GPIO_bit(CORGI_GPIO_IR_ON);
+ pxa2xx_transceiver_mode(dev, mode);
}
static struct pxaficp_platform_data corgi_ficp_platform_data = {
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index a6f2390ce66..84489dc51d8 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -13,8 +13,10 @@
#include <asm/arch/mfp-pxa27x.h>
#include <asm/arch/ohci.h>
#include <asm/arch/pxa27x_keypad.h>
+#include <asm/arch/pxa2xx_spi.h>
#include <asm/arch/camera.h>
#include <asm/arch/audio.h>
+#include <asm/arch/pxa3xx_nand.h>
#include "devices.h"
#include "generic.h"
@@ -830,4 +832,63 @@ void __init pxa3xx_set_mci3_info(struct pxamci_platform_data *info)
pxa_register_device(&pxa3xx_device_mci3, info);
}
+static struct resource pxa3xx_resources_nand[] = {
+ [0] = {
+ .start = 0x43100000,
+ .end = 0x43100053,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_NAND,
+ .end = IRQ_NAND,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ /* DRCMR for Data DMA */
+ .start = 97,
+ .end = 97,
+ .flags = IORESOURCE_DMA,
+ },
+ [3] = {
+ /* DRCMR for Command DMA */
+ .start = 99,
+ .end = 99,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static u64 pxa3xx_nand_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device pxa3xx_device_nand = {
+ .name = "pxa3xx-nand",
+ .id = -1,
+ .dev = {
+ .dma_mask = &pxa3xx_nand_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(pxa3xx_resources_nand),
+ .resource = pxa3xx_resources_nand,
+};
+
+void __init pxa3xx_set_nand_info(struct pxa3xx_nand_platform_data *info)
+{
+ pxa_register_device(&pxa3xx_device_nand, info);
+}
#endif /* CONFIG_PXA3xx */
+
+/* pxa2xx-spi platform-device ID equals respective SSP platform-device ID + 1.
+ * See comment in arch/arm/mach-pxa/ssp.c::ssp_probe() */
+void __init pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info)
+{
+ struct platform_device *pd;
+
+ pd = platform_device_alloc("pxa2xx-spi", id);
+ if (pd == NULL) {
+ printk(KERN_ERR "pxa2xx-spi: failed to allocate device id %d\n",
+ id);
+ return;
+ }
+
+ pd->dev.platform_data = info;
+ platform_device_add(pd);
+}
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
index b852eb18daa..887c738f591 100644
--- a/arch/arm/mach-pxa/devices.h
+++ b/arch/arm/mach-pxa/devices.h
@@ -31,4 +31,6 @@ extern struct platform_device pxa25x_device_pwm1;
extern struct platform_device pxa27x_device_pwm0;
extern struct platform_device pxa27x_device_pwm1;
+extern struct platform_device pxa3xx_device_nand;
+
void __init pxa_register_device(struct platform_device *dev, void *data);
diff --git a/arch/arm/mach-pxa/e400_lcd.c b/arch/arm/mach-pxa/e400_lcd.c
new file mode 100644
index 00000000000..16c02363062
--- /dev/null
+++ b/arch/arm/mach-pxa/e400_lcd.c
@@ -0,0 +1,56 @@
+/*
+ * e400_lcd.c
+ *
+ * (c) 2005 Ian Molton <spyro@f2s.com>
+ *
+ * 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/module.h>
+
+#include <asm/mach-types.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxafb.h>
+
+static struct pxafb_mode_info e400_pxafb_mode_info = {
+ .pixclock = 140703,
+ .xres = 240,
+ .yres = 320,
+ .bpp = 16,
+ .hsync_len = 4,
+ .left_margin = 28,
+ .right_margin = 8,
+ .vsync_len = 3,
+ .upper_margin = 5,
+ .lower_margin = 6,
+ .sync = 0,
+};
+
+static struct pxafb_mach_info e400_pxafb_mach_info = {
+ .modes = &e400_pxafb_mode_info,
+ .num_modes = 1,
+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+ .lccr3 = 0,
+ .pxafb_backlight_power = NULL,
+};
+
+static int __init e400_lcd_init(void)
+{
+ if (!machine_is_e400())
+ return -ENODEV;
+
+ set_pxa_fb_info(&e400_pxafb_mach_info);
+ return 0;
+}
+
+module_init(e400_lcd_init);
+
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
+MODULE_DESCRIPTION("e400 lcd driver");
+MODULE_LICENSE("GPLv2");
+
diff --git a/arch/arm/mach-pxa/e740_lcd.c b/arch/arm/mach-pxa/e740_lcd.c
new file mode 100644
index 00000000000..26bd599af17
--- /dev/null
+++ b/arch/arm/mach-pxa/e740_lcd.c
@@ -0,0 +1,123 @@
+/* e740_lcd.c
+ *
+ * This file contains the definitions for the LCD timings and functions
+ * to control the LCD power / frontlighting via the w100fb driver.
+ *
+ * (c) 2005 Ian Molton <spyro@f2s.com>
+ *
+ * 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/module.h>
+#include <linux/device.h>
+#include <linux/fb.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+
+#include <video/w100fb.h>
+
+/*
+**potential** shutdown routine - to be investigated
+devmem2 0x0c010528 w 0xff3fff00
+devmem2 0x0c010190 w 0x7FFF8000
+devmem2 0x0c0101b0 w 0x00FF0000
+devmem2 0x0c01008c w 0x00000000
+devmem2 0x0c010080 w 0x000000bf
+devmem2 0x0c010098 w 0x00000015
+devmem2 0x0c010088 w 0x4b000204
+devmem2 0x0c010098 w 0x0000001d
+*/
+
+static struct w100_gen_regs e740_lcd_regs = {
+ .lcd_format = 0x00008023,
+ .lcdd_cntl1 = 0x0f000000,
+ .lcdd_cntl2 = 0x0003ffff,
+ .genlcd_cntl1 = 0x00ffff03,
+ .genlcd_cntl2 = 0x003c0f03,
+ .genlcd_cntl3 = 0x000143aa,
+};
+
+static struct w100_mode e740_lcd_mode = {
+ .xres = 240,
+ .yres = 320,
+ .left_margin = 20,
+ .right_margin = 28,
+ .upper_margin = 9,
+ .lower_margin = 8,
+ .crtc_ss = 0x80140013,
+ .crtc_ls = 0x81150110,
+ .crtc_gs = 0x80050005,
+ .crtc_vpos_gs = 0x000a0009,
+ .crtc_rev = 0x0040010a,
+ .crtc_dclk = 0xa906000a,
+ .crtc_gclk = 0x80050108,
+ .crtc_goe = 0x80050108,
+ .pll_freq = 57,
+ .pixclk_divider = 4,
+ .pixclk_divider_rotated = 4,
+ .pixclk_src = CLK_SRC_XTAL,
+ .sysclk_divider = 1,
+ .sysclk_src = CLK_SRC_PLL,
+ .crtc_ps1_active = 0x41060010,
+};
+
+
+static struct w100_gpio_regs e740_w100_gpio_info = {
+ .init_data1 = 0x21002103,
+ .gpio_dir1 = 0xffffdeff,
+ .gpio_oe1 = 0x03c00643,
+ .init_data2 = 0x003f003f,
+ .gpio_dir2 = 0xffffffff,
+ .gpio_oe2 = 0x000000ff,
+};
+
+static struct w100fb_mach_info e740_fb_info = {
+ .modelist = &e740_lcd_mode,
+ .num_modes = 1,
+ .regs = &e740_lcd_regs,
+ .gpio = &e740_w100_gpio_info,
+ .xtal_freq = 14318000,
+ .xtal_dbl = 1,
+};
+
+static struct resource e740_fb_resources[] = {
+ [0] = {
+ .start = 0x0c000000,
+ .end = 0x0cffffff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+/* ----------------------- device declarations -------------------------- */
+
+
+static struct platform_device e740_fb_device = {
+ .name = "w100fb",
+ .id = -1,
+ .dev = {
+ .platform_data = &e740_fb_info,
+ },
+ .num_resources = ARRAY_SIZE(e740_fb_resources),
+ .resource = e740_fb_resources,
+};
+
+static int e740_lcd_init(void)
+{
+ int ret;
+
+ if (!machine_is_e740())
+ return -ENODEV;
+
+ return platform_device_register(&e740_fb_device);
+}
+
+module_init(e740_lcd_init);
+
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
+MODULE_DESCRIPTION("e740 lcd driver");
+MODULE_LICENSE("GPLv2");
diff --git a/arch/arm/mach-pxa/e750_lcd.c b/arch/arm/mach-pxa/e750_lcd.c
new file mode 100644
index 00000000000..75edc3b5390
--- /dev/null
+++ b/arch/arm/mach-pxa/e750_lcd.c
@@ -0,0 +1,109 @@
+/* e750_lcd.c
+ *
+ * This file contains the definitions for the LCD timings and functions
+ * to control the LCD power / frontlighting via the w100fb driver.
+ *
+ * (c) 2005 Ian Molton <spyro@f2s.com>
+ *
+ * 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/module.h>
+#include <linux/device.h>
+#include <linux/fb.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+
+#include <video/w100fb.h>
+
+static struct w100_gen_regs e750_lcd_regs = {
+ .lcd_format = 0x00008003,
+ .lcdd_cntl1 = 0x00000000,
+ .lcdd_cntl2 = 0x0003ffff,
+ .genlcd_cntl1 = 0x00fff003,
+ .genlcd_cntl2 = 0x003c0f03,
+ .genlcd_cntl3 = 0x000143aa,
+};
+
+static struct w100_mode e750_lcd_mode = {
+ .xres = 240,
+ .yres = 320,
+ .left_margin = 21,
+ .right_margin = 22,
+ .upper_margin = 5,
+ .lower_margin = 4,
+ .crtc_ss = 0x80150014,
+ .crtc_ls = 0x8014000d,
+ .crtc_gs = 0xc1000005,
+ .crtc_vpos_gs = 0x00020147,
+ .crtc_rev = 0x0040010a,
+ .crtc_dclk = 0xa1700030,
+ .crtc_gclk = 0x80cc0015,
+ .crtc_goe = 0x80cc0015,
+ .crtc_ps1_active = 0x61060017,
+ .pll_freq = 57,
+ .pixclk_divider = 4,
+ .pixclk_divider_rotated = 4,
+ .pixclk_src = CLK_SRC_XTAL,
+ .sysclk_divider = 1,
+ .sysclk_src = CLK_SRC_PLL,
+};
+
+
+static struct w100_gpio_regs e750_w100_gpio_info = {
+ .init_data1 = 0x01192f1b,
+ .gpio_dir1 = 0xd5ffdeff,
+ .gpio_oe1 = 0x000020bf,
+ .init_data2 = 0x010f010f,
+ .gpio_dir2 = 0xffffffff,
+ .gpio_oe2 = 0x000001cf,
+};
+
+static struct w100fb_mach_info e750_fb_info = {
+ .modelist = &e750_lcd_mode,
+ .num_modes = 1,
+ .regs = &e750_lcd_regs,
+ .gpio = &e750_w100_gpio_info,
+ .xtal_freq = 14318000,
+ .xtal_dbl = 1,
+};
+
+static struct resource e750_fb_resources[] = {
+ [0] = {
+ .start = 0x0c000000,
+ .end = 0x0cffffff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+/* ----------------------- device declarations -------------------------- */
+
+
+static struct platform_device e750_fb_device = {
+ .name = "w100fb",
+ .id = -1,
+ .dev = {
+ .platform_data = &e750_fb_info,
+ },
+ .num_resources = ARRAY_SIZE(e750_fb_resources),
+ .resource = e750_fb_resources,
+};
+
+static int e750_lcd_init(void)
+{
+ if (!machine_is_e750())
+ return -ENODEV;
+
+ return platform_device_register(&e750_fb_device);
+}
+
+module_init(e750_lcd_init);
+
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
+MODULE_DESCRIPTION("e750 lcd driver");
+MODULE_LICENSE("GPLv2");
diff --git a/arch/arm/mach-pxa/e800_lcd.c b/arch/arm/mach-pxa/e800_lcd.c
new file mode 100644
index 00000000000..e6aeab0ebc2
--- /dev/null
+++ b/arch/arm/mach-pxa/e800_lcd.c
@@ -0,0 +1,159 @@
+/* e800_lcd.c
+ *
+ * This file contains the definitions for the LCD timings and functions
+ * to control the LCD power / frontlighting via the w100fb driver.
+ *
+ * (c) 2005 Ian Molton <spyro@f2s.com>
+ *
+ * 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/module.h>
+#include <linux/device.h>
+#include <linux/fb.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+
+#include <video/w100fb.h>
+
+static struct w100_gen_regs e800_lcd_regs = {
+ .lcd_format = 0x00008003,
+ .lcdd_cntl1 = 0x02a00000,
+ .lcdd_cntl2 = 0x0003ffff,
+ .genlcd_cntl1 = 0x000ff2a3,
+ .genlcd_cntl2 = 0x000002a3,
+ .genlcd_cntl3 = 0x000102aa,
+};
+
+static struct w100_mode e800_lcd_mode[2] = {
+ [0] = {
+ .xres = 480,
+ .yres = 640,
+ .left_margin = 52,
+ .right_margin = 148,
+ .upper_margin = 2,
+ .lower_margin = 6,
+ .crtc_ss = 0x80350034,
+ .crtc_ls = 0x802b0026,
+ .crtc_gs = 0x80160016,
+ .crtc_vpos_gs = 0x00020003,
+ .crtc_rev = 0x0040001d,
+ .crtc_dclk = 0xe0000000,
+ .crtc_gclk = 0x82a50049,
+ .crtc_goe = 0x80ee001c,
+ .crtc_ps1_active = 0x00000000,
+ .pll_freq = 128,
+ .pixclk_divider = 4,
+ .pixclk_divider_rotated = 6,
+ .pixclk_src = CLK_SRC_PLL,
+ .sysclk_divider = 0,
+ .sysclk_src = CLK_SRC_PLL,
+ },
+ [1] = {
+ .xres = 240,
+ .yres = 320,
+ .left_margin = 15,
+ .right_margin = 88,
+ .upper_margin = 0,
+ .lower_margin = 7,
+ .crtc_ss = 0xd010000f,
+ .crtc_ls = 0x80070003,
+ .crtc_gs = 0x80000000,
+ .crtc_vpos_gs = 0x01460147,
+ .crtc_rev = 0x00400003,
+ .crtc_dclk = 0xa1700030,
+ .crtc_gclk = 0x814b0008,
+ .crtc_goe = 0x80cc0015,
+ .crtc_ps1_active = 0x00000000,
+ .pll_freq = 100,
+ .pixclk_divider = 6, /* Wince uses 14 which gives a 7MHz pclk. */
+ .pixclk_divider_rotated = 6, /* we want a 14MHz one (much nicer to look at) */
+ .pixclk_src = CLK_SRC_PLL,
+ .sysclk_divider = 0,
+ .sysclk_src = CLK_SRC_PLL,
+ }
+};
+
+
+static struct w100_gpio_regs e800_w100_gpio_info = {
+ .init_data1 = 0xc13fc019,
+ .gpio_dir1 = 0x3e40df7f,
+ .gpio_oe1 = 0x003c3000,
+ .init_data2 = 0x00000000,
+ .gpio_dir2 = 0x00000000,
+ .gpio_oe2 = 0x00000000,
+};
+
+static struct w100_mem_info e800_w100_mem_info = {
+ .ext_cntl = 0x09640011,
+ .sdram_mode_reg = 0x00600021,
+ .ext_timing_cntl = 0x10001545,
+ .io_cntl = 0x7ddd7333,
+ .size = 0x1fffff,
+};
+
+static void e800_tg_change(struct w100fb_par *par)
+{
+ unsigned long tmp;
+
+ tmp = w100fb_gpio_read(W100_GPIO_PORT_A);
+ if (par->mode->xres == 480)
+ tmp |= 0x100;
+ else
+ tmp &= ~0x100;
+ w100fb_gpio_write(W100_GPIO_PORT_A, tmp);
+}
+
+static struct w100_tg_info e800_tg_info = {
+ .change = e800_tg_change,
+};
+
+static struct w100fb_mach_info e800_fb_info = {
+ .modelist = e800_lcd_mode,
+ .num_modes = 2,
+ .regs = &e800_lcd_regs,
+ .gpio = &e800_w100_gpio_info,
+ .mem = &e800_w100_mem_info,
+ .tg = &e800_tg_info,
+ .xtal_freq = 16000000,
+};
+
+static struct resource e800_fb_resources[] = {
+ [0] = {
+ .start = 0x0c000000,
+ .end = 0x0cffffff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+/* ----------------------- device declarations -------------------------- */
+
+
+static struct platform_device e800_fb_device = {
+ .name = "w100fb",
+ .id = -1,
+ .dev = {
+ .platform_data = &e800_fb_info,
+ },
+ .num_resources = ARRAY_SIZE(e800_fb_resources),
+ .resource = e800_fb_resources,
+};
+
+static int e800_lcd_init(void)
+{
+ if (!machine_is_e800())
+ return -ENODEV;
+
+ return platform_device_register(&e800_fb_device);
+}
+
+module_init(e800_lcd_init);
+
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
+MODULE_DESCRIPTION("e800 lcd driver");
+MODULE_LICENSE("GPLv2");
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 1bf68074992..e5cc6ca63c7 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -1,7 +1,7 @@
/*
- * Support for CompuLab EM-x270 platform
+ * Support for CompuLab EM-X270 platform
*
- * Copyright (C) 2007 CompuLab, Ltd.
+ * Copyright (C) 2007, 2008 CompuLab, Ltd.
* Author: Mike Rapoport <mike@compulab.co.il>
*
* This program is free software; you can redistribute it and/or modify
@@ -14,31 +14,159 @@
#include <linux/dm9000.h>
#include <linux/rtc-v3020.h>
-
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio.h>
#include <asm/mach-types.h>
-
#include <asm/mach/arch.h>
+#include <asm/arch/mfp-pxa27x.h>
#include <asm/arch/pxa-regs.h>
-#include <asm/arch/pxa2xx-gpio.h>
#include <asm/arch/pxa27x-udc.h>
#include <asm/arch/audio.h>
#include <asm/arch/pxafb.h>
#include <asm/arch/ohci.h>
#include <asm/arch/mmc.h>
-#include <asm/arch/bitfield.h>
+#include <asm/arch/pxa27x_keypad.h>
#include "generic.h"
/* GPIO IRQ usage */
-#define EM_X270_MMC_PD (105)
-#define EM_X270_ETHIRQ IRQ_GPIO(41)
-#define EM_X270_MMC_IRQ IRQ_GPIO(13)
+#define GPIO41_ETHIRQ (41)
+#define GPIO13_MMC_CD (13)
+#define EM_X270_ETHIRQ IRQ_GPIO(GPIO41_ETHIRQ)
+#define EM_X270_MMC_CD IRQ_GPIO(GPIO13_MMC_CD)
+
+/* NAND control GPIOs */
+#define GPIO11_NAND_CS (11)
+#define GPIO56_NAND_RB (56)
+
+static unsigned long em_x270_pin_config[] = {
+ /* AC'97 */
+ GPIO28_AC97_BITCLK,
+ GPIO29_AC97_SDATA_IN_0,
+ GPIO30_AC97_SDATA_OUT,
+ GPIO31_AC97_SYNC,
+ GPIO98_AC97_SYSCLK,
+ GPIO113_AC97_nRESET,
+
+ /* BTUART */
+ GPIO42_BTUART_RXD,
+ GPIO43_BTUART_TXD,
+ GPIO44_BTUART_CTS,
+ GPIO45_BTUART_RTS,
+
+ /* STUART */
+ GPIO46_STUART_RXD,
+ GPIO47_STUART_TXD,
+
+ /* MCI controller */
+ GPIO32_MMC_CLK,
+ GPIO112_MMC_CMD,
+ GPIO92_MMC_DAT_0,
+ GPIO109_MMC_DAT_1,
+ GPIO110_MMC_DAT_2,
+ GPIO111_MMC_DAT_3,
+
+ /* LCD */
+ GPIO58_LCD_LDD_0,
+ GPIO59_LCD_LDD_1,
+ GPIO60_LCD_LDD_2,
+ GPIO61_LCD_LDD_3,
+ GPIO62_LCD_LDD_4,
+ GPIO63_LCD_LDD_5,
+ GPIO64_LCD_LDD_6,
+ GPIO65_LCD_LDD_7,
+ GPIO66_LCD_LDD_8,
+ GPIO67_LCD_LDD_9,
+ GPIO68_LCD_LDD_10,
+ GPIO69_LCD_LDD_11,
+ GPIO70_LCD_LDD_12,
+ GPIO71_LCD_LDD_13,
+ GPIO72_LCD_LDD_14,
+ GPIO73_LCD_LDD_15,
+ GPIO74_LCD_FCLK,
+ GPIO75_LCD_LCLK,
+ GPIO76_LCD_PCLK,
+ GPIO77_LCD_BIAS,
+
+ /* QCI */
+ GPIO84_CIF_FV,
+ GPIO25_CIF_LV,
+ GPIO53_CIF_MCLK,
+ GPIO54_CIF_PCLK,
+ GPIO81_CIF_DD_0,
+ GPIO55_CIF_DD_1,
+ GPIO51_CIF_DD_2,
+ GPIO50_CIF_DD_3,
+ GPIO52_CIF_DD_4,
+ GPIO48_CIF_DD_5,
+ GPIO17_CIF_DD_6,
+ GPIO12_CIF_DD_7,
+
+ /* I2C */
+ GPIO117_I2C_SCL,
+ GPIO118_I2C_SDA,
+
+ /* Keypad */
+ GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH,
+ GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH,
+ GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH,
+ GPIO34_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH,
+ GPIO39_KP_MKIN_4 | WAKEUP_ON_LEVEL_HIGH,
+ GPIO99_KP_MKIN_5 | WAKEUP_ON_LEVEL_HIGH,
+ GPIO91_KP_MKIN_6 | WAKEUP_ON_LEVEL_HIGH,
+ GPIO36_KP_MKIN_7 | WAKEUP_ON_LEVEL_HIGH,
+ GPIO103_KP_MKOUT_0,
+ GPIO104_KP_MKOUT_1,
+ GPIO105_KP_MKOUT_2,
+ GPIO106_KP_MKOUT_3,
+ GPIO107_KP_MKOUT_4,
+ GPIO108_KP_MKOUT_5,
+ GPIO96_KP_MKOUT_6,
+ GPIO22_KP_MKOUT_7,
+
+ /* SSP1 */
+ GPIO26_SSP1_RXD,
+ GPIO23_SSP1_SCLK,
+ GPIO24_SSP1_SFRM,
+ GPIO57_SSP1_TXD,
+
+ /* SSP2 */
+ GPIO19_SSP2_SCLK,
+ GPIO14_SSP2_SFRM,
+ GPIO89_SSP2_TXD,
+ GPIO88_SSP2_RXD,
+
+ /* SDRAM and local bus */
+ GPIO15_nCS_1,
+ GPIO78_nCS_2,
+ GPIO79_nCS_3,
+ GPIO80_nCS_4,
+ GPIO49_nPWE,
+ GPIO18_RDY,
+
+ /* GPIO */
+ GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH,
+
+ /* power controls */
+ GPIO20_GPIO | MFP_LPM_DRIVE_LOW, /* GPRS_PWEN */
+ GPIO115_GPIO | MFP_LPM_DRIVE_LOW, /* WLAN_PWEN */
+
+ /* NAND controls */
+ GPIO11_GPIO | MFP_LPM_DRIVE_HIGH, /* NAND CE# */
+ GPIO56_GPIO, /* NAND Ready/Busy */
+
+ /* interrupts */
+ GPIO13_GPIO, /* MMC card detect */
+ GPIO41_GPIO, /* DM9000 interrupt */
+};
-static struct resource em_x270_dm9k_resource[] = {
+#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+static struct resource em_x270_dm9000_resource[] = {
[0] = {
.start = PXA_CS2_PHYS,
.end = PXA_CS2_PHYS + 3,
@@ -56,32 +184,30 @@ static struct resource em_x270_dm9k_resource[] = {
}
};
-/* for the moment we limit ourselves to 32bit IO until some
- * better IO routines can be written and tested
- */
-static struct dm9000_plat_data em_x270_dm9k_platdata = {
+static struct dm9000_plat_data em_x270_dm9000_platdata = {
.flags = DM9000_PLATF_32BITONLY,
};
-/* Ethernet device */
-static struct platform_device em_x270_dm9k = {
+static struct platform_device em_x270_dm9000 = {
.name = "dm9000",
.id = 0,
- .num_resources = ARRAY_SIZE(em_x270_dm9k_resource),
- .resource = em_x270_dm9k_resource,
+ .num_resources = ARRAY_SIZE(em_x270_dm9000_resource),
+ .resource = em_x270_dm9000_resource,
.dev = {
- .platform_data = &em_x270_dm9k_platdata,
+ .platform_data = &em_x270_dm9000_platdata,
}
};
-/* WM9712 touchscreen controller. Hopefully the driver will make it to
- * the mainstream sometime */
-static struct platform_device em_x270_ts = {
- .name = "wm97xx-ts",
- .id = -1,
-};
+static void __init em_x270_init_dm9000(void)
+{
+ platform_device_register(&em_x270_dm9000);
+}
+#else
+static inline void em_x270_init_dm9000(void) {}
+#endif
-/* RTC */
+/* V3020 RTC */
+#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE)
static struct resource em_x270_v3020_resource[] = {
[0] = {
.start = PXA_CS4_PHYS,
@@ -104,20 +230,26 @@ static struct platform_device em_x270_rtc = {
}
};
-/* NAND flash */
-#define GPIO_NAND_CS (11)
-#define GPIO_NAND_RB (56)
+static void __init em_x270_init_rtc(void)
+{
+ platform_device_register(&em_x270_rtc);
+}
+#else
+static inline void em_x270_init_rtc(void) {}
+#endif
+/* NAND flash */
+#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
static inline void nand_cs_on(void)
{
- GPCR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
+ gpio_set_value(GPIO11_NAND_CS, 0);
}
static void nand_cs_off(void)
{
dsb();
- GPSR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
+ gpio_set_value(GPIO11_NAND_CS, 1);
}
/* hardware specific access to control-lines */
@@ -157,7 +289,7 @@ static int em_x270_nand_device_ready(struct mtd_info *mtd)
{
dsb();
- return GPLR(GPIO_NAND_RB) & GPIO_bit(GPIO_NAND_RB);
+ return gpio_get_value(GPIO56_NAND_RB);
}
static struct mtd_partition em_x270_partition_info[] = {
@@ -210,16 +342,35 @@ static struct platform_device em_x270_nand = {
}
};
-/* platform devices */
-static struct platform_device *platform_devices[] __initdata = {
- &em_x270_dm9k,
- &em_x270_ts,
- &em_x270_rtc,
- &em_x270_nand,
-};
+static void __init em_x270_init_nand(void)
+{
+ int err;
+ err = gpio_request(GPIO11_NAND_CS, "NAND CS");
+ if (err) {
+ pr_warning("EM-X270: failed to request NAND CS gpio\n");
+ return;
+ }
+
+ gpio_direction_output(GPIO11_NAND_CS, 1);
+
+ err = gpio_request(GPIO56_NAND_RB, "NAND R/B");
+ if (err) {
+ pr_warning("EM-X270: failed to request NAND R/B gpio\n");
+ gpio_free(GPIO11_NAND_CS);
+ return;
+ }
+
+ gpio_direction_input(GPIO56_NAND_RB);
+
+ platform_device_register(&em_x270_nand);
+}
+#else
+static inline void em_x270_init_nand(void) {}
+#endif
/* PXA27x OHCI controller setup */
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
static int em_x270_ohci_init(struct device *dev)
{
/* Set the Power Control Polarity Low */
@@ -237,27 +388,23 @@ static struct pxaohci_platform_data em_x270_ohci_platform_data = {
.init = em_x270_ohci_init,
};
+static void __init em_x270_init_ohci(void)
+{
+ pxa_set_ohci_info(&em_x270_ohci_platform_data);
+}
+#else
+static inline void em_x270_init_ohci(void) {}
+#endif
+/* MCI controller setup */
+#if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE)
static int em_x270_mci_init(struct device *dev,
irq_handler_t em_x270_detect_int,
void *data)
{
- int err;
-
- /* setup GPIO for PXA27x MMC controller */
- pxa_gpio_mode(GPIO32_MMCCLK_MD);
- pxa_gpio_mode(GPIO112_MMCCMD_MD);
- pxa_gpio_mode(GPIO92_MMCDAT0_MD);
- pxa_gpio_mode(GPIO109_MMCDAT1_MD);
- pxa_gpio_mode(GPIO110_MMCDAT2_MD);
- pxa_gpio_mode(GPIO111_MMCDAT3_MD);
-
- /* EM-X270 uses GPIO13 as SD power enable */
- pxa_gpio_mode(EM_X270_MMC_PD | GPIO_OUT);
-
- err = request_irq(EM_X270_MMC_IRQ, em_x270_detect_int,
- IRQF_DISABLED | IRQF_TRIGGER_FALLING,
- "MMC card detect", data);
+ int err = request_irq(EM_X270_MMC_CD, em_x270_detect_int,
+ IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+ "MMC card detect", data);
if (err) {
printk(KERN_ERR "%s: can't request MMC card detect IRQ: %d\n",
__func__, err);
@@ -279,7 +426,8 @@ static void em_x270_mci_setpower(struct device *dev, unsigned int vdd)
static void em_x270_mci_exit(struct device *dev, void *data)
{
- free_irq(EM_X270_MMC_IRQ, data);
+ int irq = gpio_to_irq(GPIO13_MMC_CD);
+ free_irq(irq, data);
}
static struct pxamci_platform_data em_x270_mci_platform_data = {
@@ -289,7 +437,16 @@ static struct pxamci_platform_data em_x270_mci_platform_data = {
.exit = em_x270_mci_exit,
};
+static void __init em_x270_init_mmc(void)
+{
+ pxa_set_mci_info(&em_x270_mci_platform_data);
+}
+#else
+static inline void em_x270_init_mmc(void) {}
+#endif
+
/* LCD 480x640 */
+#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
static struct pxafb_mode_info em_x270_lcd_mode = {
.pixclock = 50000,
.bpp = 16,
@@ -307,40 +464,96 @@ static struct pxafb_mode_info em_x270_lcd_mode = {
static struct pxafb_mach_info em_x270_lcd = {
.modes = &em_x270_lcd_mode,
.num_modes = 1,
- .cmap_inverse = 0,
- .cmap_static = 0,
- .lccr0 = LCCR0_PAS,
- .lccr3 = LCCR3_PixClkDiv(0x01) | LCCR3_Acb(0xff),
+ .lcd_conn = LCD_COLOR_TFT_16BPP,
};
-
-static void __init em_x270_init(void)
+static void __init em_x270_init_lcd(void)
{
- /* setup LCD */
set_pxa_fb_info(&em_x270_lcd);
+}
+#else
+static inline void em_x270_init_lcd(void) {}
+#endif
- /* register EM-X270 platform devices */
- platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+#if defined(CONFIG_SND_PXA2XX_AC97) || defined(CONFIG_SND_PXA2XX_AC97_MODULE)
+static void __init em_x270_init_ac97(void)
+{
pxa_set_ac97_info(NULL);
+}
+#else
+static inline void em_x270_init_ac97(void) {}
+#endif
+
+#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
+static unsigned int em_x270_matrix_keys[] = {
+ KEY(0, 0, KEY_A), KEY(1, 0, KEY_UP), KEY(2, 1, KEY_B),
+ KEY(0, 2, KEY_LEFT), KEY(1, 1, KEY_ENTER), KEY(2, 0, KEY_RIGHT),
+ KEY(0, 1, KEY_C), KEY(1, 2, KEY_DOWN), KEY(2, 2, KEY_D),
+};
- /* set MCI and OHCI platform parameters */
- pxa_set_mci_info(&em_x270_mci_platform_data);
- pxa_set_ohci_info(&em_x270_ohci_platform_data);
+struct pxa27x_keypad_platform_data em_x270_keypad_info = {
+ /* code map for the matrix keys */
+ .matrix_key_rows = 3,
+ .matrix_key_cols = 3,
+ .matrix_key_map = em_x270_matrix_keys,
+ .matrix_key_map_size = ARRAY_SIZE(em_x270_matrix_keys),
+};
+
+static void __init em_x270_init_keypad(void)
+{
+ pxa_set_keypad_info(&em_x270_keypad_info);
+}
+#else
+static inline void em_x270_init_keypad(void) {}
+#endif
- /* setup STUART GPIOs */
- pxa_gpio_mode(GPIO46_STRXD_MD);
- pxa_gpio_mode(GPIO47_STTXD_MD);
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+static struct gpio_keys_button gpio_keys_button[] = {
+ [0] = {
+ .desc = "sleep/wakeup",
+ .code = KEY_SUSPEND,
+ .type = EV_PWR,
+ .gpio = 1,
+ .wakeup = 1,
+ },
+};
- /* setup BTUART GPIOs */
- pxa_gpio_mode(GPIO42_BTRXD_MD);
- pxa_gpio_mode(GPIO43_BTTXD_MD);
- pxa_gpio_mode(GPIO44_BTCTS_MD);
- pxa_gpio_mode(GPIO45_BTRTS_MD);
+static struct gpio_keys_platform_data em_x270_gpio_keys_data = {
+ .buttons = gpio_keys_button,
+ .nbuttons = 1,
+};
- /* Setup interrupt for dm9000 */
- set_irq_type(EM_X270_ETHIRQ, IRQT_RISING);
+static struct platform_device em_x270_gpio_keys = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &em_x270_gpio_keys_data,
+ },
+};
+
+static void __init em_x270_init_gpio_keys(void)
+{
+ platform_device_register(&em_x270_gpio_keys);
+}
+#else
+static inline void em_x270_init_gpio_keys(void) {}
+#endif
+
+static void __init em_x270_init(void)
+{
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(em_x270_pin_config));
+
+ em_x270_init_dm9000();
+ em_x270_init_rtc();
+ em_x270_init_nand();
+ em_x270_init_lcd();
+ em_x270_init_mmc();
+ em_x270_init_ohci();
+ em_x270_init_keypad();
+ em_x270_init_gpio_keys();
+ em_x270_init_ac97();
}
-MACHINE_START(EM_X270, "Compulab EM-x270")
+MACHINE_START(EM_X270, "Compulab EM-X270")
.boot_params = 0xa0000100,
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c
index ee0ae93c876..c29b7b21c11 100644
--- a/arch/arm/mach-pxa/eseries.c
+++ b/arch/arm/mach-pxa/eseries.c
@@ -17,7 +17,7 @@
#include <asm/arch/hardware.h>
#include <asm/mach-types.h>
-#include <generic.h>
+#include "generic.h"
/* Only e800 has 128MB RAM */
static void __init eseries_fixup(struct machine_desc *desc,
@@ -47,6 +47,19 @@ MACHINE_START(E330, "Toshiba e330")
MACHINE_END
#endif
+#ifdef CONFIG_MACH_E350
+MACHINE_START(E350, "Toshiba e350")
+ /* Maintainer: Ian Molton (spyro@f2s.com) */
+ .phys_io = 0x40000000,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .boot_params = 0xa0000100,
+ .map_io = pxa_map_io,
+ .init_irq = pxa25x_init_irq,
+ .fixup = eseries_fixup,
+ .timer = &pxa_timer,
+MACHINE_END
+#endif
+
#ifdef CONFIG_MACH_E740
MACHINE_START(E740, "Toshiba e740")
/* Maintainer: Ian Molton (spyro@f2s.com) */
diff --git a/arch/arm/mach-pxa/eseries_udc.c b/arch/arm/mach-pxa/eseries_udc.c
new file mode 100644
index 00000000000..362847a1099
--- /dev/null
+++ b/arch/arm/mach-pxa/eseries_udc.c
@@ -0,0 +1,57 @@
+/*
+ * UDC functions for the Toshiba e-series PDAs
+ *
+ * Copyright (c) Ian Molton 2003
+ *
+ * This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/arch/udc.h>
+#include <asm/arch/eseries-gpio.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+#include <asm/domain.h>
+
+/* local PXA generic code */
+#include "generic.h"
+
+static struct pxa2xx_udc_mach_info e7xx_udc_mach_info = {
+ .gpio_vbus = GPIO_E7XX_USB_DISC,
+ .gpio_pullup = GPIO_E7XX_USB_PULLUP,
+ .gpio_pullup_inverted = 1
+};
+
+static struct pxa2xx_udc_mach_info e800_udc_mach_info = {
+ .gpio_vbus = GPIO_E800_USB_DISC,
+ .gpio_pullup = GPIO_E800_USB_PULLUP,
+ .gpio_pullup_inverted = 1
+};
+
+static int __init eseries_udc_init(void)
+{
+ if (machine_is_e330() || machine_is_e350() ||
+ machine_is_e740() || machine_is_e750() ||
+ machine_is_e400())
+ pxa_set_udc_info(&e7xx_udc_mach_info);
+ else if (machine_is_e800())
+ pxa_set_udc_info(&e800_udc_mach_info);
+
+ return 0;
+}
+
+module_init(eseries_udc_init);
+
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
+MODULE_DESCRIPTION("eseries UDC support");
+MODULE_LICENSE("GPLv2");
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
new file mode 100644
index 00000000000..0143eed6539
--- /dev/null
+++ b/arch/arm/mach-pxa/ezx.c
@@ -0,0 +1,220 @@
+/*
+ * ezx.c - Common code for the EZX platform.
+ *
+ * Copyright (C) 2005-2006 Harald Welte <laforge@openezx.org>,
+ * 2007-2008 Daniel Ribeiro <drwyrm@gmail.com>,
+ * 2007-2008 Stefan Schmidt <stefan@datenfreihafen.org>
+ *
+ * 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/platform_device.h>
+#include <linux/delay.h>
+#include <linux/pwm_backlight.h>
+
+#include <asm/setup.h>
+#include <asm/arch/pxafb.h>
+#include <asm/arch/ohci.h>
+#include <asm/arch/i2c.h>
+
+#include <asm/arch/mfp-pxa27x.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-regs.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "devices.h"
+#include "generic.h"
+
+static struct platform_pwm_backlight_data ezx_backlight_data = {
+ .pwm_id = 0,
+ .max_brightness = 1023,
+ .dft_brightness = 1023,
+ .pwm_period_ns = 78770,
+};
+
+static struct platform_device ezx_backlight_device = {
+ .name = "pwm-backlight",
+ .dev = {
+ .parent = &pxa27x_device_pwm0.dev,
+ .platform_data = &ezx_backlight_data,
+ },
+};
+
+static struct pxafb_mode_info mode_ezx_old = {
+ .pixclock = 150000,
+ .xres = 240,
+ .yres = 320,
+ .bpp = 16,
+ .hsync_len = 10,
+ .left_margin = 20,
+ .right_margin = 10,
+ .vsync_len = 2,
+ .upper_margin = 3,
+ .lower_margin = 2,
+ .sync = 0,
+};
+
+static struct pxafb_mach_info ezx_fb_info_1 = {
+ .modes = &mode_ezx_old,
+ .num_modes = 1,
+ .lcd_conn = LCD_COLOR_TFT_16BPP,
+};
+
+static struct pxafb_mode_info mode_72r89803y01 = {
+ .pixclock = 192308,
+ .xres = 240,
+ .yres = 320,
+ .bpp = 32,
+ .depth = 18,
+ .hsync_len = 10,
+ .left_margin = 20,
+ .right_margin = 10,
+ .vsync_len = 2,
+ .upper_margin = 3,
+ .lower_margin = 2,
+ .sync = 0,
+};
+
+static struct pxafb_mach_info ezx_fb_info_2 = {
+ .modes = &mode_72r89803y01,
+ .num_modes = 1,
+ .lcd_conn = LCD_COLOR_TFT_18BPP,
+};
+
+static struct platform_device *devices[] __initdata = {
+ &ezx_backlight_device,
+};
+
+static unsigned long ezx_pin_config[] __initdata = {
+ /* PWM backlight */
+ GPIO16_PWM0_OUT,
+
+ /* BTUART */
+ GPIO42_BTUART_RXD,
+ GPIO43_BTUART_TXD,
+ GPIO44_BTUART_CTS,
+ GPIO45_BTUART_RTS,
+
+ /* STUART */
+ GPIO46_STUART_RXD,
+ GPIO47_STUART_TXD,
+
+ /* For A780 support (connected with Neptune GSM chip) */
+ GPIO30_USB_P3_2, /* ICL_TXENB */
+ GPIO31_USB_P3_6, /* ICL_VPOUT */
+ GPIO90_USB_P3_5, /* ICL_VPIN */
+ GPIO91_USB_P3_1, /* ICL_XRXD */
+ GPIO56_USB_P3_4, /* ICL_VMOUT */
+ GPIO113_USB_P3_3, /* /ICL_VMIN */
+};
+
+static void __init ezx_init(void)
+{
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config));
+ pxa_set_i2c_info(NULL);
+ if (machine_is_ezx_a780() || machine_is_ezx_e680())
+ set_pxa_fb_info(&ezx_fb_info_1);
+ else
+ set_pxa_fb_info(&ezx_fb_info_2);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+static void __init ezx_fixup(struct machine_desc *desc, struct tag *tags,
+ char **cmdline, struct meminfo *mi)
+{
+ /* We have two ram chips. First one with 32MB at 0xA0000000 and a second
+ * 16MB one at 0xAC000000
+ */
+ mi->nr_banks = 2;
+ mi->bank[0].start = 0xa0000000;
+ mi->bank[0].node = 0;
+ mi->bank[0].size = (32*1024*1024);
+ mi->bank[1].start = 0xac000000;
+ mi->bank[1].node = 1;
+ mi->bank[1].size = (16*1024*1024);
+}
+
+#ifdef CONFIG_MACH_EZX_A780
+MACHINE_START(EZX_A780, "Motorola EZX A780")
+ .phys_io = 0x40000000,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .fixup = ezx_fixup,
+ .boot_params = 0xa0000100,
+ .map_io = pxa_map_io,
+ .init_irq = pxa27x_init_irq,
+ .timer = &pxa_timer,
+ .init_machine = &ezx_init,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EZX_E680
+MACHINE_START(EZX_E680, "Motorola EZX E680")
+ .phys_io = 0x40000000,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .fixup = ezx_fixup,
+ .boot_params = 0xa0000100,
+ .map_io = pxa_map_io,
+ .init_irq = pxa27x_init_irq,
+ .timer = &pxa_timer,
+ .init_machine = &ezx_init,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EZX_A1200
+MACHINE_START(EZX_A1200, "Motorola EZX A1200")
+ .phys_io = 0x40000000,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .fixup = ezx_fixup,
+ .boot_params = 0xa0000100,
+ .map_io = pxa_map_io,
+ .init_irq = pxa27x_init_irq,
+ .timer = &pxa_timer,
+ .init_machine = &ezx_init,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EZX_A910
+MACHINE_START(EZX_A910, "Motorola EZX A910")
+ .phys_io = 0x40000000,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .fixup = ezx_fixup,
+ .boot_params = 0xa0000100,
+ .map_io = pxa_map_io,
+ .init_irq = pxa27x_init_irq,
+ .timer = &pxa_timer,
+ .init_machine = &ezx_init,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EZX_E6
+MACHINE_START(EZX_E6, "Motorola EZX E6")
+ .phys_io = 0x40000000,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .fixup = ezx_fixup,
+ .boot_params = 0xa0000100,
+ .map_io = pxa_map_io,
+ .init_irq = pxa27x_init_irq,
+ .timer = &pxa_timer,
+ .init_machine = &ezx_init,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EZX_E2
+MACHINE_START(EZX_E2, "Motorola EZX E2")
+ .phys_io = 0x40000000,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .fixup = ezx_fixup,
+ .boot_params = 0xa0000100,
+ .map_io = pxa_map_io,
+ .init_irq = pxa27x_init_irq,
+ .timer = &pxa_timer,
+ .init_machine = &ezx_init,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index 530654474bb..dd759d03a9f 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -20,6 +20,7 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/smc91x.h>
#include <asm/types.h>
#include <asm/setup.h>
@@ -38,6 +39,7 @@
#include <asm/arch/pxafb.h>
#include <asm/arch/ssp.h>
#include <asm/arch/pxa27x_keypad.h>
+#include <asm/arch/pxa3xx_nand.h>
#include <asm/arch/littleton.h>
#include "generic.h"
@@ -101,18 +103,26 @@ static struct resource smc91x_resources[] = {
[1] = {
.start = IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO90)),
.end = IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO90)),
- .flags = IORESOURCE_IRQ | IRQF_TRIGGER_FALLING,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
}
};
+static struct smc91x_platdata littleton_smc91x_info = {
+ .flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT |
+ SMC91X_NOWAIT | SMC91X_USE_DMA,
+};
+
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = 0,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
+ .dev = {
+ .platform_data = &littleton_smc91x_info,
+ },
};
-#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULES)
+#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
/* use bit 30, 31 as the indicator of command parameter number */
#define CMD0(x) ((0x00000000) | ((x) << 9))
#define CMD1(x, x1) ((0x40000000) | ((x) << 9) | 0x100 | (x1))
@@ -311,9 +321,9 @@ static void littleton_init_lcd(void)
}
#else
static inline void littleton_init_lcd(void) {};
-#endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULES */
+#endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULE */
-#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
+#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
static unsigned int littleton_matrix_key_map[] = {
/* KEY(row, col, key_code) */
KEY(1, 3, KEY_0), KEY(0, 0, KEY_1), KEY(1, 0, KEY_2), KEY(2, 0, KEY_3),
@@ -361,6 +371,57 @@ static void __init littleton_init_keypad(void)
static inline void littleton_init_keypad(void) {}
#endif
+#if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE)
+static struct mtd_partition littleton_nand_partitions[] = {
+ [0] = {
+ .name = "Bootloader",
+ .offset = 0,
+ .size = 0x060000,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ [1] = {
+ .name = "Kernel",
+ .offset = 0x060000,
+ .size = 0x200000,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ [2] = {
+ .name = "Filesystem",
+ .offset = 0x0260000,
+ .size = 0x3000000, /* 48M - rootfs */
+ },
+ [3] = {
+ .name = "MassStorage",
+ .offset = 0x3260000,
+ .size = 0x3d40000,
+ },
+ [4] = {
+ .name = "BBT",
+ .offset = 0x6FA0000,
+ .size = 0x80000,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* NOTE: we reserve some blocks at the end of the NAND flash for
+ * bad block management, and the max number of relocation blocks
+ * differs on different platforms. Please take care with it when
+ * defining the partition table.
+ */
+};
+
+static struct pxa3xx_nand_platform_data littleton_nand_info = {
+ .enable_arbiter = 1,
+ .parts = littleton_nand_partitions,
+ .nr_parts = ARRAY_SIZE(littleton_nand_partitions),
+};
+
+static void __init littleton_init_nand(void)
+{
+ pxa3xx_set_nand_info(&littleton_nand_info);
+}
+#else
+static inline void littleton_init_nand(void) {}
+#endif /* CONFIG_MTD_NAND_PXA3xx || CONFIG_MTD_NAND_PXA3xx_MODULE */
+
static void __init littleton_init(void)
{
/* initialize MFP configurations */
@@ -374,6 +435,7 @@ static void __init littleton_init(void)
littleton_init_lcd();
littleton_init_keypad();
+ littleton_init_nand();
}
MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleton)")
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index a3fae413920..ac26423cd20 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -21,6 +21,7 @@
#include <linux/interrupt.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/smc91x.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
@@ -226,14 +227,6 @@ static struct pxa2xx_spi_master pxa_ssp_master_info = {
.num_chipselect = 0,
};
-static struct platform_device pxa_ssp = {
- .name = "pxa2xx-spi",
- .id = 1,
- .dev = {
- .platform_data = &pxa_ssp_master_info,
- },
-};
-
static int lubbock_ads7846_pendown_state(void)
{
/* TS_BUSY is bit 8 in LUB_MISC_RD, but pendown is irq-only */
@@ -292,11 +285,18 @@ static struct resource smc91x_resources[] = {
},
};
+static struct smc91x_platdata lubbock_smc91x_info = {
+ .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_IO_SHIFT_2,
+};
+
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = -1,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
+ .dev = {
+ .platform_data = &lubbock_smc91x_info,
+ },
};
static struct resource flash_resources[] = {
@@ -367,7 +367,6 @@ static struct platform_device *devices[] __initdata = {
&smc91x_device,
&lubbock_flash_device[0],
&lubbock_flash_device[1],
- &pxa_ssp,
};
static struct pxafb_mode_info sharp_lm8v31_mode = {
@@ -471,6 +470,7 @@ static void lubbock_irda_transceiver_mode(struct device *dev, int mode)
} else if (mode & IR_FIRMODE) {
LUB_MISC_WR |= 1 << 4;
}
+ pxa2xx_transceiver_mode(dev, mode);
local_irq_restore(flags);
}
@@ -501,6 +501,7 @@ static void __init lubbock_init(void)
lubbock_flash_data[flashboot].name = "boot-rom";
(void) platform_add_devices(devices, ARRAY_SIZE(devices));
+ pxa2xx_set_spi_info(1, &pxa_ssp_master_info);
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
}
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index 01b2fa79021..c9d274f0048 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -17,17 +17,15 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
+#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/mfd/htc-egpio.h>
#include <linux/mfd/htc-pasic3.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
#include <linux/mtd/physmap.h>
#include <linux/pda_power.h>
#include <linux/pwm_backlight.h>
-#include <asm/gpio.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -44,7 +42,7 @@
#include "devices.h"
#include "generic.h"
-static unsigned long magician_pin_config[] = {
+static unsigned long magician_pin_config[] __initdata = {
/* SDRAM and Static Memory I/O Signals */
GPIO20_nSDCS_2,
@@ -134,6 +132,7 @@ static unsigned long magician_pin_config[] = {
static void magician_irda_transceiver_mode(struct device *dev, int mode)
{
gpio_set_value(GPIO83_MAGICIAN_nIR_EN, mode & IR_OFF);
+ pxa2xx_transceiver_mode(dev, mode);
}
static struct pxaficp_platform_data magician_ficp_info = {
@@ -399,6 +398,7 @@ static struct platform_pwm_backlight_data backlight_data = {
static struct platform_device backlight = {
.name = "pwm-backlight",
+ .id = -1,
.dev = {
.parent = &pxa27x_device_pwm0.dev,
.platform_data = &backlight_data,
@@ -511,6 +511,37 @@ static struct platform_device pasic3 = {
* External power
*/
+static int power_supply_init(struct device *dev)
+{
+ int ret;
+
+ ret = gpio_request(EGPIO_MAGICIAN_CABLE_STATE_AC, "CABLE_STATE_AC");
+ if (ret)
+ goto err_cs_ac;
+ ret = gpio_request(EGPIO_MAGICIAN_CABLE_STATE_USB, "CABLE_STATE_USB");
+ if (ret)
+ goto err_cs_usb;
+ ret = gpio_request(EGPIO_MAGICIAN_CHARGE_EN, "CHARGE_EN");
+ if (ret)
+ goto err_chg_en;
+ ret = gpio_request(GPIO30_MAGICIAN_nCHARGE_EN, "nCHARGE_EN");
+ if (!ret)
+ ret = gpio_direction_output(GPIO30_MAGICIAN_nCHARGE_EN, 0);
+ if (ret)
+ goto err_nchg_en;
+
+ return 0;
+
+err_nchg_en:
+ gpio_free(EGPIO_MAGICIAN_CHARGE_EN);
+err_chg_en:
+ gpio_free(EGPIO_MAGICIAN_CABLE_STATE_USB);
+err_cs_usb:
+ gpio_free(EGPIO_MAGICIAN_CABLE_STATE_AC);
+err_cs_ac:
+ return ret;
+}
+
static int magician_is_ac_online(void)
{
return gpio_get_value(EGPIO_MAGICIAN_CABLE_STATE_AC);
@@ -527,14 +558,24 @@ static void magician_set_charge(int flags)
gpio_set_value(EGPIO_MAGICIAN_CHARGE_EN, flags);
}
+static void power_supply_exit(struct device *dev)
+{
+ gpio_free(GPIO30_MAGICIAN_nCHARGE_EN);
+ gpio_free(EGPIO_MAGICIAN_CHARGE_EN);
+ gpio_free(EGPIO_MAGICIAN_CABLE_STATE_USB);
+ gpio_free(EGPIO_MAGICIAN_CABLE_STATE_AC);
+}
+
static char *magician_supplicants[] = {
"ds2760-battery.0", "backup-battery"
};
static struct pda_power_pdata power_supply_info = {
+ .init = power_supply_init,
.is_ac_online = magician_is_ac_online,
.is_usb_online = magician_is_usb_online,
.set_charge = magician_set_charge,
+ .exit = power_supply_exit,
.supplied_to = magician_supplicants,
.num_supplicants = ARRAY_SIZE(magician_supplicants),
};
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index f2e9e7c4da8..851ec2d9b69 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -26,6 +26,7 @@
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/pwm_backlight.h>
+#include <linux/smc91x.h>
#include <asm/types.h>
#include <asm/setup.h>
@@ -110,9 +111,9 @@ static unsigned long mainstone_pin_config[] = {
GPIO45_AC97_SYSCLK,
/* Keypad */
- GPIO93_KP_DKIN_0 | WAKEUP_ON_LEVEL_HIGH,
- GPIO94_KP_DKIN_1 | WAKEUP_ON_LEVEL_HIGH,
- GPIO95_KP_DKIN_2 | WAKEUP_ON_LEVEL_HIGH,
+ GPIO93_KP_DKIN_0,
+ GPIO94_KP_DKIN_1,
+ GPIO95_KP_DKIN_2,
GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH,
GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH,
GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH,
@@ -240,11 +241,19 @@ static struct resource smc91x_resources[] = {
}
};
+static struct smc91x_platdata mainstone_smc91x_info = {
+ .flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
+ SMC91X_NOWAIT | SMC91X_USE_DMA,
+};
+
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = 0,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
+ .dev = {
+ .platform_data = &mainstone_smc91x_info,
+ },
};
static int mst_audio_startup(struct snd_pcm_substream *substream, void *priv)
@@ -455,6 +464,7 @@ static void mainstone_irda_transceiver_mode(struct device *dev, int mode)
} else if (mode & IR_FIRMODE) {
MST_MSCWR1 |= MST_MSCWR1_IRDA_FIR;
}
+ pxa2xx_transceiver_mode(dev, mode);
if (mode & IR_OFF) {
MST_MSCWR1 = (MST_MSCWR1 & ~MST_MSCWR1_IRDA_MASK) | MST_MSCWR1_IRDA_OFF;
} else {
@@ -513,7 +523,7 @@ static struct pxaohci_platform_data mainstone_ohci_platform_data = {
.init = mainstone_ohci_init,
};
-#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
+#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
static unsigned int mainstone_matrix_keys[] = {
KEY(0, 0, KEY_A), KEY(1, 0, KEY_B), KEY(2, 0, KEY_C),
KEY(3, 0, KEY_D), KEY(4, 0, KEY_E), KEY(5, 0, KEY_F),
diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c
index d1cdb4ecb0b..fd4545eab80 100644
--- a/arch/arm/mach-pxa/mfp-pxa2xx.c
+++ b/arch/arm/mach-pxa/mfp-pxa2xx.c
@@ -39,6 +39,28 @@ struct gpio_desc {
static struct gpio_desc gpio_desc[MFP_PIN_GPIO127 + 1];
+static int __mfp_config_lpm(unsigned gpio, unsigned long lpm)
+{
+ unsigned mask = GPIO_bit(gpio);
+
+ /* low power state */
+ switch (lpm) {
+ case MFP_LPM_DRIVE_HIGH:
+ PGSR(gpio) |= mask;
+ break;
+ case MFP_LPM_DRIVE_LOW:
+ PGSR(gpio) &= ~mask;
+ break;
+ case MFP_LPM_INPUT:
+ break;
+ default:
+ pr_warning("%s: invalid low power state for GPIO%d\n",
+ __func__, gpio);
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int __mfp_config_gpio(unsigned gpio, unsigned long c)
{
unsigned long gafr, mask = GPIO_bit(gpio);
@@ -57,21 +79,8 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c)
else
GPDR(gpio) &= ~mask;
- /* low power state */
- switch (c & MFP_LPM_STATE_MASK) {
- case MFP_LPM_DRIVE_HIGH:
- PGSR(gpio) |= mask;
- break;
- case MFP_LPM_DRIVE_LOW:
- PGSR(gpio) &= ~mask;
- break;
- case MFP_LPM_INPUT:
- break;
- default:
- pr_warning("%s: invalid low power state for GPIO%d\n",
- __func__, gpio);
+ if (__mfp_config_lpm(gpio, c & MFP_LPM_STATE_MASK))
return -EINVAL;
- }
/* give early warning if MFP_LPM_CAN_WAKEUP is set on the
* configurations of those pins not able to wakeup
@@ -91,6 +100,18 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c)
return 0;
}
+static inline int __mfp_validate(int mfp)
+{
+ int gpio = mfp_to_gpio(mfp);
+
+ if ((mfp > MFP_PIN_GPIO127) || !gpio_desc[gpio].valid) {
+ pr_warning("%s: GPIO%d is invalid pin\n", __func__, gpio);
+ return -1;
+ }
+
+ return gpio;
+}
+
void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num)
{
unsigned long flags;
@@ -99,13 +120,9 @@ void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num)
for (i = 0, c = mfp_cfgs; i < num; i++, c++) {
- gpio = mfp_to_gpio(MFP_PIN(*c));
-
- if (!gpio_desc[gpio].valid) {
- pr_warning("%s: GPIO%d is invalid pin\n",
- __func__, gpio);
+ gpio = __mfp_validate(MFP_PIN(*c));
+ if (gpio < 0)
continue;
- }
local_irq_save(flags);
@@ -116,6 +133,20 @@ void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num)
}
}
+void pxa2xx_mfp_set_lpm(int mfp, unsigned long lpm)
+{
+ unsigned long flags;
+ int gpio;
+
+ gpio = __mfp_validate(mfp);
+ if (gpio < 0)
+ return;
+
+ local_irq_save(flags);
+ __mfp_config_lpm(gpio, lpm);
+ local_irq_restore(flags);
+}
+
int gpio_set_wake(unsigned int gpio, unsigned int on)
{
struct gpio_desc *d;
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
new file mode 100644
index 00000000000..408657a24f8
--- /dev/null
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -0,0 +1,416 @@
+/*
+ * Hardware definitions for PalmTX
+ *
+ * Author: Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on work of:
+ * Alex Osborne <ato@meshy.org>
+ * Cristiano P. <cristianop@users.sourceforge.net>
+ * Jan Herman <2hp@seznam.cz>
+ * Michal Hrusecky
+ *
+ * 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.
+ *
+ * (find more info at www.hackndev.com)
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/pda_power.h>
+#include <linux/pwm_backlight.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/audio.h>
+#include <asm/arch/palmtx.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/pxafb.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/mfp-pxa27x.h>
+#include <asm/arch/irda.h>
+#include <asm/arch/pxa27x_keypad.h>
+#include <asm/arch/udc.h>
+
+#include "generic.h"
+#include "devices.h"
+
+/******************************************************************************
+ * Pin configuration
+ ******************************************************************************/
+static unsigned long palmtx_pin_config[] __initdata = {
+ /* MMC */
+ GPIO32_MMC_CLK,
+ GPIO92_MMC_DAT_0,
+ GPIO109_MMC_DAT_1,
+ GPIO110_MMC_DAT_2,
+ GPIO111_MMC_DAT_3,
+ GPIO112_MMC_CMD,
+
+ /* AC97 */
+ GPIO28_AC97_BITCLK,
+ GPIO29_AC97_SDATA_IN_0,
+ GPIO30_AC97_SDATA_OUT,
+ GPIO31_AC97_SYNC,
+
+ /* IrDA */
+ GPIO46_FICP_RXD,
+ GPIO47_FICP_TXD,
+
+ /* PWM */
+ GPIO16_PWM0_OUT,
+
+ /* USB */
+ GPIO13_GPIO,
+
+ /* PCMCIA */
+ GPIO48_nPOE,
+ GPIO49_nPWE,
+ GPIO50_nPIOR,
+ GPIO51_nPIOW,
+ GPIO85_nPCE_1,
+ GPIO54_nPCE_2,
+ GPIO79_PSKTSEL,
+ GPIO55_nPREG,
+ GPIO56_nPWAIT,
+ GPIO57_nIOIS16,
+};
+
+/******************************************************************************
+ * SD/MMC card controller
+ ******************************************************************************/
+static int palmtx_mci_init(struct device *dev, irq_handler_t palmtx_detect_int,
+ void *data)
+{
+ int err = 0;
+
+ /* Setup an interrupt for detecting card insert/remove events */
+ err = request_irq(IRQ_GPIO_PALMTX_SD_DETECT_N, palmtx_detect_int,
+ IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ "SD/MMC card detect", data);
+ if (err) {
+ printk(KERN_ERR "%s: cannot request SD/MMC card detect IRQ\n",
+ __func__);
+ return err;
+ }
+
+ err = gpio_request(GPIO_NR_PALMTX_SD_POWER, "SD_POWER");
+ if (err)
+ goto pwr_err;
+
+ err = gpio_request(GPIO_NR_PALMTX_SD_READONLY, "SD_READONLY");
+ if (err)
+ goto ro_err;
+
+ printk(KERN_DEBUG "%s: irq registered\n", __func__);
+
+ return 0;
+
+ro_err:
+ gpio_free(GPIO_NR_PALMTX_SD_POWER);
+pwr_err:
+ free_irq(IRQ_GPIO_PALMTX_SD_DETECT_N, data);
+ return err;
+}
+
+static void palmtx_mci_exit(struct device *dev, void *data)
+{
+ gpio_free(GPIO_NR_PALMTX_SD_READONLY);
+ gpio_free(GPIO_NR_PALMTX_SD_POWER);
+ free_irq(IRQ_GPIO_PALMTX_SD_DETECT_N, data);
+}
+
+static void palmtx_mci_power(struct device *dev, unsigned int vdd)
+{
+ struct pxamci_platform_data *p_d = dev->platform_data;
+ gpio_set_value(GPIO_NR_PALMTX_SD_POWER, p_d->ocr_mask & (1 << vdd));
+}
+
+static int palmtx_mci_get_ro(struct device *dev)
+{
+ return gpio_get_value(GPIO_NR_PALMTX_SD_READONLY);
+}
+
+static struct pxamci_platform_data palmtx_mci_platform_data = {
+ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
+ .setpower = palmtx_mci_power,
+ .get_ro = palmtx_mci_get_ro,
+ .init = palmtx_mci_init,
+ .exit = palmtx_mci_exit,
+};
+
+/******************************************************************************
+ * GPIO keyboard
+ ******************************************************************************/
+static unsigned int palmtx_matrix_keys[] = {
+ KEY(0, 0, KEY_POWER),
+ KEY(0, 1, KEY_F1),
+ KEY(0, 2, KEY_ENTER),
+
+ KEY(1, 0, KEY_F2),
+ KEY(1, 1, KEY_F3),
+ KEY(1, 2, KEY_F4),
+
+ KEY(2, 0, KEY_UP),
+ KEY(2, 2, KEY_DOWN),
+
+ KEY(3, 0, KEY_RIGHT),
+ KEY(3, 2, KEY_LEFT),
+
+};
+
+static struct pxa27x_keypad_platform_data palmtx_keypad_platform_data = {
+ .matrix_key_rows = 4,
+ .matrix_key_cols = 3,
+ .matrix_key_map = palmtx_matrix_keys,
+ .matrix_key_map_size = ARRAY_SIZE(palmtx_matrix_keys),
+
+ .debounce_interval = 30,
+};
+
+/******************************************************************************
+ * GPIO keys
+ ******************************************************************************/
+static struct gpio_keys_button palmtx_pxa_buttons[] = {
+ {KEY_F8, GPIO_NR_PALMTX_HOTSYNC_BUTTON_N, 1, "HotSync Button" },
+};
+
+static struct gpio_keys_platform_data palmtx_pxa_keys_data = {
+ .buttons = palmtx_pxa_buttons,
+ .nbuttons = ARRAY_SIZE(palmtx_pxa_buttons),
+};
+
+static struct platform_device palmtx_pxa_keys = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmtx_pxa_keys_data,
+ },
+};
+
+/******************************************************************************
+ * Backlight
+ ******************************************************************************/
+static int palmtx_backlight_init(struct device *dev)
+{
+ int ret;
+
+ ret = gpio_request(GPIO_NR_PALMTX_BL_POWER, "BL POWER");
+ if (ret)
+ goto err;
+ ret = gpio_request(GPIO_NR_PALMTX_LCD_POWER, "LCD POWER");
+ if (ret)
+ goto err2;
+
+ return 0;
+err2:
+ gpio_free(GPIO_NR_PALMTX_BL_POWER);
+err:
+ return ret;
+}
+
+static int palmtx_backlight_notify(int brightness)
+{
+ gpio_set_value(GPIO_NR_PALMTX_BL_POWER, brightness);
+ gpio_set_value(GPIO_NR_PALMTX_LCD_POWER, brightness);
+ return brightness;
+}
+
+static void palmtx_backlight_exit(struct device *dev)
+{
+ gpio_free(GPIO_NR_PALMTX_BL_POWER);
+ gpio_free(GPIO_NR_PALMTX_LCD_POWER);
+}
+
+static struct platform_pwm_backlight_data palmtx_backlight_data = {
+ .pwm_id = 0,
+ .max_brightness = PALMTX_MAX_INTENSITY,
+ .dft_brightness = PALMTX_MAX_INTENSITY,
+ .pwm_period_ns = PALMTX_PERIOD_NS,
+ .init = palmtx_backlight_init,
+ .notify = palmtx_backlight_notify,
+ .exit = palmtx_backlight_exit,
+};
+
+static struct platform_device palmtx_backlight = {
+ .name = "pwm-backlight",
+ .dev = {
+ .parent = &pxa27x_device_pwm0.dev,
+ .platform_data = &palmtx_backlight_data,
+ },
+};
+
+/******************************************************************************
+ * IrDA
+ ******************************************************************************/
+static void palmtx_irda_transceiver_mode(struct device *dev, int mode)
+{
+ gpio_set_value(GPIO_NR_PALMTX_IR_DISABLE, mode & IR_OFF);
+ pxa2xx_transceiver_mode(dev, mode);
+}
+
+static struct pxaficp_platform_data palmtx_ficp_platform_data = {
+ .transceiver_cap = IR_SIRMODE | IR_FIRMODE | IR_OFF,
+ .transceiver_mode = palmtx_irda_transceiver_mode,
+};
+
+/******************************************************************************
+ * UDC
+ ******************************************************************************/
+static void palmtx_udc_command(int cmd)
+{
+ gpio_set_value(GPIO_NR_PALMTX_USB_POWER, !cmd);
+ udelay(50);
+ gpio_set_value(GPIO_NR_PALMTX_USB_PULLUP, !cmd);
+}
+
+static struct pxa2xx_udc_mach_info palmtx_udc_info __initdata = {
+ .gpio_vbus = GPIO_NR_PALMTX_USB_DETECT_N,
+ .gpio_vbus_inverted = 1,
+ .udc_command = palmtx_udc_command,
+};
+
+/******************************************************************************
+ * Power supply
+ ******************************************************************************/
+static int power_supply_init(struct device *dev)
+{
+ int ret;
+
+ ret = gpio_request(GPIO_NR_PALMTX_POWER_DETECT, "CABLE_STATE_AC");
+ if (ret)
+ goto err_cs_ac;
+
+ ret = gpio_request(GPIO_NR_PALMTX_USB_DETECT_N, "CABLE_STATE_USB");
+ if (ret)
+ goto err_cs_usb;
+
+ return 0;
+
+err_cs_usb:
+ gpio_free(GPIO_NR_PALMTX_POWER_DETECT);
+err_cs_ac:
+ return ret;
+}
+
+static int palmtx_is_ac_online(void)
+{
+ return gpio_get_value(GPIO_NR_PALMTX_POWER_DETECT);
+}
+
+static int palmtx_is_usb_online(void)
+{
+ return !gpio_get_value(GPIO_NR_PALMTX_USB_DETECT_N);
+}
+
+static void power_supply_exit(struct device *dev)
+{
+ gpio_free(GPIO_NR_PALMTX_USB_DETECT_N);
+ gpio_free(GPIO_NR_PALMTX_POWER_DETECT);
+}
+
+static char *palmtx_supplicants[] = {
+ "main-battery",
+};
+
+static struct pda_power_pdata power_supply_info = {
+ .init = power_supply_init,
+ .is_ac_online = palmtx_is_ac_online,
+ .is_usb_online = palmtx_is_usb_online,
+ .exit = power_supply_exit,
+ .supplied_to = palmtx_supplicants,
+ .num_supplicants = ARRAY_SIZE(palmtx_supplicants),
+};
+
+static struct platform_device power_supply = {
+ .name = "pda-power",
+ .id = -1,
+ .dev = {
+ .platform_data = &power_supply_info,
+ },
+};
+
+/******************************************************************************
+ * Framebuffer
+ ******************************************************************************/
+static struct pxafb_mode_info palmtx_lcd_modes[] = {
+{
+ .pixclock = 57692,
+ .xres = 320,
+ .yres = 480,
+ .bpp = 16,
+
+ .left_margin = 32,
+ .right_margin = 1,
+ .upper_margin = 7,
+ .lower_margin = 1,
+
+ .hsync_len = 4,
+ .vsync_len = 1,
+},
+};
+
+static struct pxafb_mach_info palmtx_lcd_screen = {
+ .modes = palmtx_lcd_modes,
+ .num_modes = ARRAY_SIZE(palmtx_lcd_modes),
+ .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
+};
+
+/******************************************************************************
+ * Machine init
+ ******************************************************************************/
+static struct platform_device *devices[] __initdata = {
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+ &palmtx_pxa_keys,
+#endif
+ &palmtx_backlight,
+ &power_supply,
+};
+
+static struct map_desc palmtx_io_desc[] __initdata = {
+{
+ .virtual = PALMTX_PCMCIA_VIRT,
+ .pfn = __phys_to_pfn(PALMTX_PCMCIA_PHYS),
+ .length = PALMTX_PCMCIA_SIZE,
+ .type = MT_DEVICE
+},
+};
+
+static void __init palmtx_map_io(void)
+{
+ pxa_map_io();
+ iotable_init(palmtx_io_desc, ARRAY_SIZE(palmtx_io_desc));
+}
+
+static void __init palmtx_init(void)
+{
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(palmtx_pin_config));
+
+ set_pxa_fb_info(&palmtx_lcd_screen);
+ pxa_set_mci_info(&palmtx_mci_platform_data);
+ pxa_set_udc_info(&palmtx_udc_info);
+ pxa_set_ac97_info(NULL);
+ pxa_set_ficp_info(&palmtx_ficp_platform_data);
+ pxa_set_keypad_info(&palmtx_keypad_platform_data);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(PALMTX, "Palm T|X")
+ .phys_io = PALMTX_PHYS_IO_START,
+ .io_pg_offst = io_p2v(0x40000000),
+ .boot_params = 0xa0000100,
+ .map_io = palmtx_map_io,
+ .init_irq = pxa27x_init_irq,
+ .timer = &pxa_timer,
+ .init_machine = palmtx_init
+MACHINE_END
diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c
index 3b945eb0aee..377f3be8ce5 100644
--- a/arch/arm/mach-pxa/pcm027.c
+++ b/arch/arm/mach-pxa/pcm027.c
@@ -24,7 +24,9 @@
#include <linux/platform_device.h>
#include <linux/mtd/physmap.h>
#include <linux/spi/spi.h>
+#include <linux/spi/max7301.h>
#include <linux/leds.h>
+
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/arch/hardware.h>
@@ -108,6 +110,32 @@ static struct platform_device smc91x_device = {
.resource = smc91x_resources,
};
+/*
+ * SPI host and devices
+ */
+static struct pxa2xx_spi_master pxa_ssp_master_info = {
+ .num_chipselect = 1,
+};
+
+static struct max7301_platform_data max7301_info = {
+ .base = -1,
+};
+
+/* bus_num must match id in pxa2xx_set_spi_info() call */
+static struct spi_board_info spi_board_info[] __initdata = {
+ {
+ .modalias = "max7301",
+ .platform_data = &max7301_info,
+ .max_speed_hz = 13000000,
+ .bus_num = 1,
+ .chip_select = 0,
+ .mode = SPI_MODE_0,
+ },
+};
+
+/*
+ * NOR flash
+ */
static struct physmap_flash_data pcm027_flash_data = {
.width = 4,
};
@@ -190,6 +218,9 @@ static void __init pcm027_init(void)
#ifdef CONFIG_MACH_PCM990_BASEBOARD
pcm990_baseboard_init();
#endif
+
+ pxa2xx_set_spi_info(1, &pxa_ssp_master_info);
+ spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
}
static void __init pcm027_map_io(void)
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 5d87c7c866e..30023b00e47 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -33,14 +33,30 @@
#include <asm/arch/camera.h>
#include <asm/mach/map.h>
#include <asm/arch/pxa-regs.h>
-#include <asm/arch/pxa2xx-gpio.h>
#include <asm/arch/audio.h>
#include <asm/arch/mmc.h>
#include <asm/arch/ohci.h>
#include <asm/arch/pcm990_baseboard.h>
#include <asm/arch/pxafb.h>
+#include <asm/arch/mfp-pxa27x.h>
#include "devices.h"
+#include "generic.h"
+
+static unsigned long pcm990_pin_config[] __initdata = {
+ /* MMC */
+ GPIO32_MMC_CLK,
+ GPIO112_MMC_CMD,
+ GPIO92_MMC_DAT_0,
+ GPIO109_MMC_DAT_1,
+ GPIO110_MMC_DAT_2,
+ GPIO111_MMC_DAT_3,
+ /* USB */
+ GPIO88_USBH1_PWR,
+ GPIO89_USBH1_PEN,
+ /* PWM0 */
+ GPIO16_PWM0_OUT,
+};
/*
* pcm990_lcd_power - control power supply to the LCD
@@ -277,16 +293,6 @@ static int pcm990_mci_init(struct device *dev, irq_handler_t mci_detect_int,
{
int err;
- /*
- * enable GPIO for PXA27x MMC controller
- */
- pxa_gpio_mode(GPIO32_MMCCLK_MD);
- pxa_gpio_mode(GPIO112_MMCCMD_MD);
- pxa_gpio_mode(GPIO92_MMCDAT0_MD);
- pxa_gpio_mode(GPIO109_MMCDAT1_MD);
- pxa_gpio_mode(GPIO110_MMCDAT2_MD);
- pxa_gpio_mode(GPIO111_MMCDAT3_MD);
-
err = request_irq(PCM027_MMCDET_IRQ, mci_detect_int, IRQF_DISABLED,
"MMC card detect", data);
if (err)
@@ -333,8 +339,6 @@ static struct pxamci_platform_data pcm990_mci_platform_data = {
*/
static int pcm990_ohci_init(struct device *dev)
{
- pxa_gpio_mode(PCM990_USB_OVERCURRENT);
- pxa_gpio_mode(PCM990_USB_PWR_EN);
/*
* disable USB port 2 and 3
* power sense is active low
@@ -361,23 +365,27 @@ static struct pxaohci_platform_data pcm990_ohci_platform_data = {
* PXA27x Camera specific stuff
*/
#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE)
+static unsigned long pcm990_camera_pin_config[] = {
+ /* CIF */
+ GPIO98_CIF_DD_0,
+ GPIO105_CIF_DD_1,
+ GPIO104_CIF_DD_2,
+ GPIO103_CIF_DD_3,
+ GPIO95_CIF_DD_4,
+ GPIO94_CIF_DD_5,
+ GPIO93_CIF_DD_6,
+ GPIO108_CIF_DD_7,
+ GPIO107_CIF_DD_8,
+ GPIO106_CIF_DD_9,
+ GPIO42_CIF_MCLK,
+ GPIO45_CIF_PCLK,
+ GPIO43_CIF_FV,
+ GPIO44_CIF_LV,
+};
+
static int pcm990_pxacamera_init(struct device *dev)
{
- pxa_gpio_mode(GPIO98_CIF_DD_0_MD);
- pxa_gpio_mode(GPIO105_CIF_DD_1_MD);
- pxa_gpio_mode(GPIO104_CIF_DD_2_MD);
- pxa_gpio_mode(GPIO103_CIF_DD_3_MD);
- pxa_gpio_mode(GPIO95_CIF_DD_4_MD);
- pxa_gpio_mode(GPIO94_CIF_DD_5_MD);
- pxa_gpio_mode(GPIO93_CIF_DD_6_MD);
- pxa_gpio_mode(GPIO108_CIF_DD_7_MD);
- pxa_gpio_mode(GPIO107_CIF_DD_8_MD);
- pxa_gpio_mode(GPIO106_CIF_DD_9_MD);
- pxa_gpio_mode(GPIO42_CIF_MCLK_MD);
- pxa_gpio_mode(GPIO45_CIF_PCLK_MD);
- pxa_gpio_mode(GPIO43_CIF_FV_MD);
- pxa_gpio_mode(GPIO44_CIF_LV_MD);
-
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(pcm990_camera_pin_config));
return 0;
}
@@ -449,8 +457,10 @@ static struct map_desc pcm990_io_desc[] __initdata = {
*/
void __init pcm990_baseboard_init(void)
{
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(pcm990_pin_config));
+
/* register CPLD access */
- iotable_init(pcm990_io_desc, ARRAY_SIZE(pcm990_io_desc));
+ iotable_init(ARRAY_AND_SIZE(pcm990_io_desc));
/* register CPLD's IRQ controller */
pcm990_init_irq();
@@ -458,7 +468,6 @@ void __init pcm990_baseboard_init(void)
#ifndef CONFIG_PCM990_DISPLAY_NONE
set_pxa_fb_info(&pcm990_fbinfo);
#endif
- pxa_gpio_mode(GPIO16_PWM0_MD);
platform_device_register(&pcm990_backlight_device);
/* MMC */
@@ -473,9 +482,8 @@ void __init pcm990_baseboard_init(void)
#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE)
pxa_set_camera_info(&pcm990_pxacamera_platform_data);
- i2c_register_board_info(0, pcm990_i2c_devices,
- ARRAY_SIZE(pcm990_i2c_devices));
+ i2c_register_board_info(0, ARRAY_AND_SIZE(pcm990_i2c_devices));
#endif
- printk(KERN_INFO"PCM-990 Evaluation baseboard initialized\n");
+ printk(KERN_INFO "PCM-990 Evaluation baseboard initialized\n");
}
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index f81c10cafd4..39612cfa0b4 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -267,6 +267,7 @@ static void poodle_irda_transceiver_mode(struct device *dev, int mode)
} else {
GPCR(POODLE_GPIO_IR_ON) = GPIO_bit(POODLE_GPIO_IR_ON);
}
+ pxa2xx_transceiver_mode(dev, mode);
}
static struct pxaficp_platform_data poodle_ficp_platform_data = {
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 4cd50e3005e..c5b845b935b 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -109,6 +109,52 @@ static const struct clkops clk_pxa25x_lcd_ops = {
.getrate = clk_pxa25x_lcd_getrate,
};
+static unsigned long gpio12_config_32k[] = {
+ GPIO12_32KHz,
+};
+
+static unsigned long gpio12_config_gpio[] = {
+ GPIO12_GPIO,
+};
+
+static void clk_gpio12_enable(struct clk *clk)
+{
+ pxa2xx_mfp_config(gpio12_config_32k, 1);
+}
+
+static void clk_gpio12_disable(struct clk *clk)
+{
+ pxa2xx_mfp_config(gpio12_config_gpio, 1);
+}
+
+static const struct clkops clk_pxa25x_gpio12_ops = {
+ .enable = clk_gpio12_enable,
+ .disable = clk_gpio12_disable,
+};
+
+static unsigned long gpio11_config_3m6[] = {
+ GPIO11_3_6MHz,
+};
+
+static unsigned long gpio11_config_gpio[] = {
+ GPIO11_GPIO,
+};
+
+static void clk_gpio11_enable(struct clk *clk)
+{
+ pxa2xx_mfp_config(gpio11_config_3m6, 1);
+}
+
+static void clk_gpio11_disable(struct clk *clk)
+{
+ pxa2xx_mfp_config(gpio11_config_gpio, 1);
+}
+
+static const struct clkops clk_pxa25x_gpio11_ops = {
+ .enable = clk_gpio11_enable,
+ .disable = clk_gpio11_disable,
+};
+
/*
* 3.6864MHz -> OST, GPIO, SSP, PWM, PLLs (95.842MHz, 147.456MHz)
* 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz
@@ -128,6 +174,8 @@ static struct clk pxa25x_clks[] = {
INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev),
INIT_CKEN("UARTCLK", STUART, 14745600, 1, NULL),
INIT_CKEN("UDCCLK", USB, 47923000, 5, &pxa25x_device_udc.dev),
+ INIT_CLK("GPIO11_CLK", &clk_pxa25x_gpio11_ops, 3686400, 0, NULL),
+ INIT_CLK("GPIO12_CLK", &clk_pxa25x_gpio12_ops, 32768, 0, NULL),
INIT_CKEN("MMCCLK", MMC, 19169000, 0, &pxa_device_mci.dev),
INIT_CKEN("I2CCLK", I2C, 31949000, 0, &pxa_device_i2c.dev),
@@ -145,7 +193,10 @@ static struct clk pxa25x_clks[] = {
INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL),
};
-static struct clk gpio7_clk = INIT_CKOTHER("GPIO7_CK", &pxa25x_clks[4], NULL);
+static struct clk pxa2xx_clk_aliases[] = {
+ INIT_CKOTHER("GPIO7_CLK", &pxa25x_clks[4], NULL),
+ INIT_CKOTHER("SA1111_CLK", &pxa25x_clks[5], NULL),
+};
#ifdef CONFIG_PM
@@ -293,7 +344,7 @@ static int __init pxa25x_init(void)
int i, ret = 0;
/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
- if (cpu_is_pxa25x())
+ if (cpu_is_pxa255())
clks_register(&pxa25x_hwuart_clk, 1);
if (cpu_is_pxa21x() || cpu_is_pxa25x()) {
@@ -317,10 +368,10 @@ static int __init pxa25x_init(void)
}
/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
- if (cpu_is_pxa25x())
+ if (cpu_is_pxa255())
ret = platform_device_register(&pxa_device_hwuart);
- clks_register(&gpio7_clk, 1);
+ clks_register(pxa2xx_clk_aliases, ARRAY_SIZE(pxa2xx_clk_aliases));
return ret;
}
diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c
index 0a0d3877f21..da92e973388 100644
--- a/arch/arm/mach-pxa/pxa300.c
+++ b/arch/arm/mach-pxa/pxa300.c
@@ -15,10 +15,16 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/platform_device.h>
#include <asm/hardware.h>
+#include <asm/arch/pxa3xx-regs.h>
#include <asm/arch/mfp-pxa300.h>
+#include "generic.h"
+#include "devices.h"
+#include "clock.h"
+
static struct pxa3xx_mfp_addr_map pxa300_mfp_addr_map[] __initdata = {
MFP_ADDR_X(GPIO0, GPIO2, 0x00b4),
@@ -79,15 +85,26 @@ static struct pxa3xx_mfp_addr_map pxa310_mfp_addr_map[] __initdata = {
MFP_ADDR_END,
};
+static struct clk common_clks[] = {
+ PXA3xx_CKEN("NANDCLK", NAND, 156000000, 0, &pxa3xx_device_nand.dev),
+};
+
+static struct clk pxa310_clks[] = {
+ PXA3xx_CKEN("MMCCLK", MMC3, 19500000, 0, &pxa3xx_device_mci3.dev),
+};
+
static int __init pxa300_init(void)
{
if (cpu_is_pxa300() || cpu_is_pxa310()) {
pxa3xx_init_mfp();
pxa3xx_mfp_init_addr(pxa300_mfp_addr_map);
+ clks_register(ARRAY_AND_SIZE(common_clks));
}
- if (cpu_is_pxa310())
+ if (cpu_is_pxa310()) {
pxa3xx_mfp_init_addr(pxa310_mfp_addr_map);
+ clks_register(ARRAY_AND_SIZE(pxa310_clks));
+ }
return 0;
}
diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c
index 74128eb8f8d..c557c23a1ef 100644
--- a/arch/arm/mach-pxa/pxa320.c
+++ b/arch/arm/mach-pxa/pxa320.c
@@ -15,11 +15,17 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/platform_device.h>
#include <asm/hardware.h>
#include <asm/arch/mfp.h>
+#include <asm/arch/pxa3xx-regs.h>
#include <asm/arch/mfp-pxa320.h>
+#include "generic.h"
+#include "devices.h"
+#include "clock.h"
+
static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = {
MFP_ADDR_X(GPIO0, GPIO4, 0x0124),
@@ -74,16 +80,17 @@ static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = {
MFP_ADDR_END,
};
-static void __init pxa320_init_mfp(void)
-{
- pxa3xx_init_mfp();
- pxa3xx_mfp_init_addr(pxa320_mfp_addr_map);
-}
+static struct clk pxa320_clks[] = {
+ PXA3xx_CKEN("NANDCLK", NAND, 104000000, 0, &pxa3xx_device_nand.dev),
+};
static int __init pxa320_init(void)
{
- if (cpu_is_pxa320())
- pxa320_init_mfp();
+ if (cpu_is_pxa320()) {
+ pxa3xx_init_mfp();
+ pxa3xx_mfp_init_addr(pxa320_mfp_addr_map);
+ clks_register(ARRAY_AND_SIZE(pxa320_clks));
+ }
return 0;
}
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 15685d2b8f8..f491025a0c8 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -144,7 +144,7 @@ static unsigned long clk_pxa3xx_hsio_getrate(struct clk *clk)
return hsio_clk;
}
-static void clk_pxa3xx_cken_enable(struct clk *clk)
+void clk_pxa3xx_cken_enable(struct clk *clk)
{
unsigned long mask = 1ul << (clk->cken & 0x1f);
@@ -154,7 +154,7 @@ static void clk_pxa3xx_cken_enable(struct clk *clk)
CKENB |= mask;
}
-static void clk_pxa3xx_cken_disable(struct clk *clk)
+void clk_pxa3xx_cken_disable(struct clk *clk)
{
unsigned long mask = 1ul << (clk->cken & 0x1f);
@@ -164,7 +164,7 @@ static void clk_pxa3xx_cken_disable(struct clk *clk)
CKENB &= ~mask;
}
-static const struct clkops clk_pxa3xx_cken_ops = {
+const struct clkops clk_pxa3xx_cken_ops = {
.enable = clk_pxa3xx_cken_enable,
.disable = clk_pxa3xx_cken_disable,
};
@@ -196,24 +196,6 @@ static const struct clkops clk_pout_ops = {
.disable = clk_pout_disable,
};
-#define PXA3xx_CKEN(_name, _cken, _rate, _delay, _dev) \
- { \
- .name = _name, \
- .dev = _dev, \
- .ops = &clk_pxa3xx_cken_ops, \
- .rate = _rate, \
- .cken = CKEN_##_cken, \
- .delay = _delay, \
- }
-
-#define PXA3xx_CK(_name, _cken, _ops, _dev) \
- { \
- .name = _name, \
- .dev = _dev, \
- .ops = _ops, \
- .cken = CKEN_##_cken, \
- }
-
static struct clk pxa3xx_clks[] = {
{
.name = "CLK_POUT",
@@ -244,7 +226,6 @@ static struct clk pxa3xx_clks[] = {
PXA3xx_CKEN("MMCCLK", MMC1, 19500000, 0, &pxa_device_mci.dev),
PXA3xx_CKEN("MMCCLK", MMC2, 19500000, 0, &pxa3xx_device_mci2.dev),
- PXA3xx_CKEN("MMCCLK", MMC3, 19500000, 0, &pxa3xx_device_mci3.dev),
};
#ifdef CONFIG_PM
diff --git a/arch/arm/mach-pxa/pxa930.c b/arch/arm/mach-pxa/pxa930.c
new file mode 100644
index 00000000000..9503897d049
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa930.c
@@ -0,0 +1,190 @@
+/*
+ * linux/arch/arm/mach-pxa/pxa930.c
+ *
+ * Code specific to PXA930
+ *
+ * Copyright (C) 2007-2008 Marvell Internation Ltd.
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/mfp-pxa930.h>
+
+static struct pxa3xx_mfp_addr_map pxa930_mfp_addr_map[] __initdata = {
+
+ MFP_ADDR(GPIO0, 0x02e0),
+ MFP_ADDR(GPIO1, 0x02dc),
+ MFP_ADDR(GPIO2, 0x02e8),
+ MFP_ADDR(GPIO3, 0x02d8),
+ MFP_ADDR(GPIO4, 0x02e4),
+ MFP_ADDR(GPIO5, 0x02ec),
+ MFP_ADDR(GPIO6, 0x02f8),
+ MFP_ADDR(GPIO7, 0x02fc),
+ MFP_ADDR(GPIO8, 0x0300),
+ MFP_ADDR(GPIO9, 0x02d4),
+ MFP_ADDR(GPIO10, 0x02f4),
+ MFP_ADDR(GPIO11, 0x02f0),
+ MFP_ADDR(GPIO12, 0x0304),
+ MFP_ADDR(GPIO13, 0x0310),
+ MFP_ADDR(GPIO14, 0x0308),
+ MFP_ADDR(GPIO15, 0x030c),
+ MFP_ADDR(GPIO16, 0x04e8),
+ MFP_ADDR(GPIO17, 0x04f4),
+ MFP_ADDR(GPIO18, 0x04f8),
+ MFP_ADDR(GPIO19, 0x04fc),
+ MFP_ADDR(GPIO20, 0x0518),
+ MFP_ADDR(GPIO21, 0x051c),
+ MFP_ADDR(GPIO22, 0x04ec),
+ MFP_ADDR(GPIO23, 0x0500),
+ MFP_ADDR(GPIO24, 0x04f0),
+ MFP_ADDR(GPIO25, 0x0504),
+ MFP_ADDR(GPIO26, 0x0510),
+ MFP_ADDR(GPIO27, 0x0514),
+ MFP_ADDR(GPIO28, 0x0520),
+ MFP_ADDR(GPIO29, 0x0600),
+ MFP_ADDR(GPIO30, 0x0618),
+ MFP_ADDR(GPIO31, 0x0610),
+ MFP_ADDR(GPIO32, 0x060c),
+ MFP_ADDR(GPIO33, 0x061c),
+ MFP_ADDR(GPIO34, 0x0620),
+ MFP_ADDR(GPIO35, 0x0628),
+ MFP_ADDR(GPIO36, 0x062c),
+ MFP_ADDR(GPIO37, 0x0630),
+ MFP_ADDR(GPIO38, 0x0634),
+ MFP_ADDR(GPIO39, 0x0638),
+ MFP_ADDR(GPIO40, 0x063c),
+ MFP_ADDR(GPIO41, 0x0614),
+ MFP_ADDR(GPIO42, 0x0624),
+ MFP_ADDR(GPIO43, 0x0608),
+ MFP_ADDR(GPIO44, 0x0604),
+ MFP_ADDR(GPIO45, 0x050c),
+ MFP_ADDR(GPIO46, 0x0508),
+ MFP_ADDR(GPIO47, 0x02bc),
+ MFP_ADDR(GPIO48, 0x02b4),
+ MFP_ADDR(GPIO49, 0x02b8),
+ MFP_ADDR(GPIO50, 0x02c8),
+ MFP_ADDR(GPIO51, 0x02c0),
+ MFP_ADDR(GPIO52, 0x02c4),
+ MFP_ADDR(GPIO53, 0x02d0),
+ MFP_ADDR(GPIO54, 0x02cc),
+ MFP_ADDR(GPIO55, 0x029c),
+ MFP_ADDR(GPIO56, 0x02a0),
+ MFP_ADDR(GPIO57, 0x0294),
+ MFP_ADDR(GPIO58, 0x0298),
+ MFP_ADDR(GPIO59, 0x02a4),
+ MFP_ADDR(GPIO60, 0x02a8),
+ MFP_ADDR(GPIO61, 0x02b0),
+ MFP_ADDR(GPIO62, 0x02ac),
+ MFP_ADDR(GPIO63, 0x0640),
+ MFP_ADDR(GPIO64, 0x065c),
+ MFP_ADDR(GPIO65, 0x0648),
+ MFP_ADDR(GPIO66, 0x0644),
+ MFP_ADDR(GPIO67, 0x0674),
+ MFP_ADDR(GPIO68, 0x0658),
+ MFP_ADDR(GPIO69, 0x0654),
+ MFP_ADDR(GPIO70, 0x0660),
+ MFP_ADDR(GPIO71, 0x0668),
+ MFP_ADDR(GPIO72, 0x0664),
+ MFP_ADDR(GPIO73, 0x0650),
+ MFP_ADDR(GPIO74, 0x066c),
+ MFP_ADDR(GPIO75, 0x064c),
+ MFP_ADDR(GPIO76, 0x0670),
+ MFP_ADDR(GPIO77, 0x0678),
+ MFP_ADDR(GPIO78, 0x067c),
+ MFP_ADDR(GPIO79, 0x0694),
+ MFP_ADDR(GPIO80, 0x069c),
+ MFP_ADDR(GPIO81, 0x06a0),
+ MFP_ADDR(GPIO82, 0x06a4),
+ MFP_ADDR(GPIO83, 0x0698),
+ MFP_ADDR(GPIO84, 0x06bc),
+ MFP_ADDR(GPIO85, 0x06b4),
+ MFP_ADDR(GPIO86, 0x06b0),
+ MFP_ADDR(GPIO87, 0x06c0),
+ MFP_ADDR(GPIO88, 0x06c4),
+ MFP_ADDR(GPIO89, 0x06ac),
+ MFP_ADDR(GPIO90, 0x0680),
+ MFP_ADDR(GPIO91, 0x0684),
+ MFP_ADDR(GPIO92, 0x0688),
+ MFP_ADDR(GPIO93, 0x0690),
+ MFP_ADDR(GPIO94, 0x068c),
+ MFP_ADDR(GPIO95, 0x06a8),
+ MFP_ADDR(GPIO96, 0x06b8),
+ MFP_ADDR(GPIO97, 0x0410),
+ MFP_ADDR(GPIO98, 0x0418),
+ MFP_ADDR(GPIO99, 0x041c),
+ MFP_ADDR(GPIO100, 0x0414),
+ MFP_ADDR(GPIO101, 0x0408),
+ MFP_ADDR(GPIO102, 0x0324),
+ MFP_ADDR(GPIO103, 0x040c),
+ MFP_ADDR(GPIO104, 0x0400),
+ MFP_ADDR(GPIO105, 0x0328),
+ MFP_ADDR(GPIO106, 0x0404),
+
+ MFP_ADDR(nXCVREN, 0x0204),
+ MFP_ADDR(DF_CLE_nOE, 0x020c),
+ MFP_ADDR(DF_nADV1_ALE, 0x0218),
+ MFP_ADDR(DF_SCLK_E, 0x0214),
+ MFP_ADDR(DF_SCLK_S, 0x0210),
+ MFP_ADDR(nBE0, 0x021c),
+ MFP_ADDR(nBE1, 0x0220),
+ MFP_ADDR(DF_nADV2_ALE, 0x0224),
+ MFP_ADDR(DF_INT_RnB, 0x0228),
+ MFP_ADDR(DF_nCS0, 0x022c),
+ MFP_ADDR(DF_nCS1, 0x0230),
+ MFP_ADDR(nLUA, 0x0254),
+ MFP_ADDR(nLLA, 0x0258),
+ MFP_ADDR(DF_nWE, 0x0234),
+ MFP_ADDR(DF_nRE_nOE, 0x0238),
+ MFP_ADDR(DF_ADDR0, 0x024c),
+ MFP_ADDR(DF_ADDR1, 0x0250),
+ MFP_ADDR(DF_ADDR2, 0x025c),
+ MFP_ADDR(DF_ADDR3, 0x0260),
+ MFP_ADDR(DF_IO0, 0x023c),
+ MFP_ADDR(DF_IO1, 0x0240),
+ MFP_ADDR(DF_IO2, 0x0244),
+ MFP_ADDR(DF_IO3, 0x0248),
+ MFP_ADDR(DF_IO4, 0x0264),
+ MFP_ADDR(DF_IO5, 0x0268),
+ MFP_ADDR(DF_IO6, 0x026c),
+ MFP_ADDR(DF_IO7, 0x0270),
+ MFP_ADDR(DF_IO8, 0x0274),
+ MFP_ADDR(DF_IO9, 0x0278),
+ MFP_ADDR(DF_IO10, 0x027c),
+ MFP_ADDR(DF_IO11, 0x0280),
+ MFP_ADDR(DF_IO12, 0x0284),
+ MFP_ADDR(DF_IO13, 0x0288),
+ MFP_ADDR(DF_IO14, 0x028c),
+ MFP_ADDR(DF_IO15, 0x0290),
+
+ MFP_ADDR(GSIM_UIO, 0x0314),
+ MFP_ADDR(GSIM_UCLK, 0x0318),
+ MFP_ADDR(GSIM_UDET, 0x031c),
+ MFP_ADDR(GSIM_nURST, 0x0320),
+
+ MFP_ADDR(PMIC_INT, 0x06c8),
+
+ MFP_ADDR(RDY, 0x0200),
+
+ MFP_ADDR_END,
+};
+
+static int __init pxa930_init(void)
+{
+ if (cpu_is_pxa930()) {
+ pxa3xx_init_mfp();
+ pxa3xx_mfp_init_addr(pxa930_mfp_addr_map);
+ }
+
+ return 0;
+}
+
+core_initcall(pxa930_init);
diff --git a/arch/arm/mach-pxa/reset.c b/arch/arm/mach-pxa/reset.c
new file mode 100644
index 00000000000..9d39dea57ce
--- /dev/null
+++ b/arch/arm/mach-pxa/reset.c
@@ -0,0 +1,96 @@
+/*
+ * 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/module.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <asm/io.h>
+#include <asm/proc-fns.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-regs.h>
+
+static void do_hw_reset(void);
+
+static int reset_gpio = -1;
+
+int init_gpio_reset(int gpio)
+{
+ int rc;
+
+ rc = gpio_request(gpio, "reset generator");
+ if (rc) {
+ printk(KERN_ERR "Can't request reset_gpio\n");
+ goto out;
+ }
+
+ rc = gpio_direction_input(gpio);
+ if (rc) {
+ printk(KERN_ERR "Can't configure reset_gpio for input\n");
+ gpio_free(gpio);
+ goto out;
+ }
+
+out:
+ if (!rc)
+ reset_gpio = gpio;
+
+ return rc;
+}
+
+/*
+ * Trigger GPIO reset.
+ * This covers various types of logic connecting gpio pin
+ * to RESET pins (nRESET or GPIO_RESET):
+ */
+static void do_gpio_reset(void)
+{
+ BUG_ON(reset_gpio == -1);
+
+ /* drive it low */
+ gpio_direction_output(reset_gpio, 0);
+ mdelay(2);
+ /* rising edge or drive high */
+ gpio_set_value(reset_gpio, 1);
+ mdelay(2);
+ /* falling edge */
+ gpio_set_value(reset_gpio, 0);
+
+ /* give it some time */
+ mdelay(10);
+
+ WARN_ON(1);
+ /* fallback */
+ do_hw_reset();
+}
+
+static void do_hw_reset(void)
+{
+ /* Initialize the watchdog and let it fire */
+ OWER = OWER_WME;
+ OSSR = OSSR_M3;
+ OSMR3 = OSCR + 368640; /* ... in 100 ms */
+}
+
+void arch_reset(char mode)
+{
+ if (cpu_is_pxa2xx())
+ RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+
+ switch (mode) {
+ case 's':
+ /* Jump into ROM at address 0 */
+ cpu_reset(0);
+ break;
+ case 'h':
+ do_hw_reset();
+ break;
+ case 'g':
+ do_gpio_reset();
+ break;
+ }
+}
+
diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c
new file mode 100644
index 00000000000..d02bc6f8bb9
--- /dev/null
+++ b/arch/arm/mach-pxa/saar.c
@@ -0,0 +1,84 @@
+/*
+ * linux/arch/arm/mach-pxa/saar.c
+ *
+ * Support for the Marvell PXA930 Handheld Platform (aka SAAR)
+ *
+ * Copyright (C) 2007-2008 Marvell International Ltd.
+ *
+ * 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
+ * publishhed by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/smc91x.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware.h>
+#include <asm/arch/pxa3xx-regs.h>
+#include <asm/arch/mfp-pxa930.h>
+
+#include "devices.h"
+#include "generic.h"
+
+/* SAAR MFP configurations */
+static mfp_cfg_t saar_mfp_cfg[] __initdata = {
+ /* Ethernet */
+ DF_nCS1_nCS3,
+ GPIO97_GPIO,
+};
+
+#define SAAR_ETH_PHYS (0x14000000)
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = (SAAR_ETH_PHYS + 0x300),
+ .end = (SAAR_ETH_PHYS + 0xfffff),
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO97)),
+ .end = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO97)),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+ }
+};
+
+static struct smc91x_platdata saar_smc91x_info = {
+ .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_USE_DMA,
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+ .dev = {
+ .platform_data = &saar_smc91x_info,
+ },
+};
+
+static void __init saar_init(void)
+{
+ /* initialize MFP configurations */
+ pxa3xx_mfp_config(ARRAY_AND_SIZE(saar_mfp_cfg));
+
+ platform_device_register(&smc91x_device);
+}
+
+MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
+ /* Maintainer: Eric Miao <eric.miao@marvell.com> */
+ .phys_io = 0x40000000,
+ .boot_params = 0xa0000100,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .map_io = pxa_map_io,
+ .init_irq = pxa3xx_init_irq,
+ .timer = &pxa_timer,
+ .init_machine = saar_init,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index e7d0fcd9b43..762249c03de 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -38,6 +38,7 @@
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-regs.h>
#include <asm/arch/pxa2xx-gpio.h>
+#include <asm/arch/pxa27x-udc.h>
#include <asm/arch/irda.h>
#include <asm/arch/mmc.h>
#include <asm/arch/ohci.h>
@@ -450,6 +451,7 @@ static void spitz_irda_transceiver_mode(struct device *dev, int mode)
set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_IR_ON);
else
reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_IR_ON);
+ pxa2xx_transceiver_mode(dev, mode);
}
#ifdef CONFIG_MACH_AKITA
@@ -459,6 +461,7 @@ static void akita_irda_transceiver_mode(struct device *dev, int mode)
akita_set_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_IR_ON);
else
akita_reset_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_IR_ON);
+ pxa2xx_transceiver_mode(dev, mode);
}
#endif
@@ -529,11 +532,7 @@ static struct platform_device *devices[] __initdata = {
static void spitz_poweroff(void)
{
- pxa_gpio_mode(SPITZ_GPIO_ON_RESET | GPIO_OUT);
- GPSR(SPITZ_GPIO_ON_RESET) = GPIO_bit(SPITZ_GPIO_ON_RESET);
-
- mdelay(1000);
- arm_machine_restart('h');
+ arm_machine_restart('g');
}
static void spitz_restart(char mode)
@@ -547,6 +546,7 @@ static void spitz_restart(char mode)
static void __init common_init(void)
{
+ init_gpio_reset(SPITZ_GPIO_ON_RESET);
pm_power_off = spitz_poweroff;
arm_pm_restart = spitz_restart;
diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c
index 0bb31982fb6..89f38683787 100644
--- a/arch/arm/mach-pxa/ssp.c
+++ b/arch/arm/mach-pxa/ssp.c
@@ -14,13 +14,6 @@
* IO-based SSP applications and allows easy port setup for DMA access.
*
* Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
- *
- * Revision history:
- * 22nd Aug 2003 Initial version.
- * 20th Dec 2004 Added ssp_config for changing port config without
- * closing the port.
- * 4th Aug 2005 Added option to disable irq handler registration and
- * cleaned up irq and clock detection.
*/
#include <linux/module.h>
@@ -285,7 +278,7 @@ int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags)
goto out_region;
dev->irq = ssp->irq;
} else
- dev->irq = 0;
+ dev->irq = NO_IRQ;
/* turn on SSP port clock */
clk_enable(ssp->clk);
@@ -306,7 +299,8 @@ void ssp_exit(struct ssp_dev *dev)
struct ssp_device *ssp = dev->ssp;
ssp_disable(dev);
- free_irq(dev->irq, dev);
+ if (dev->irq != NO_IRQ)
+ free_irq(dev->irq, dev);
clk_disable(ssp->clk);
ssp_free(ssp);
}
@@ -360,6 +354,7 @@ static int __devinit ssp_probe(struct platform_device *pdev, int type)
dev_err(&pdev->dev, "failed to allocate memory");
return -ENOMEM;
}
+ ssp->pdev = pdev;
ssp->clk = clk_get(&pdev->dev, "SSPCLK");
if (IS_ERR(ssp->clk)) {
diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c
new file mode 100644
index 00000000000..ac283507e42
--- /dev/null
+++ b/arch/arm/mach-pxa/tavorevb.c
@@ -0,0 +1,84 @@
+/*
+ * linux/arch/arm/mach-pxa/tavorevb.c
+ *
+ * Support for the Marvell PXA930 Evaluation Board
+ *
+ * Copyright (C) 2007-2008 Marvell International Ltd.
+ *
+ * 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
+ * publishhed by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/smc91x.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware.h>
+#include <asm/arch/pxa3xx-regs.h>
+#include <asm/arch/mfp-pxa930.h>
+
+#include "devices.h"
+#include "generic.h"
+
+/* Tavor EVB MFP configurations */
+static mfp_cfg_t tavorevb_mfp_cfg[] __initdata = {
+ /* Ethernet */
+ DF_nCS1_nCS3,
+ GPIO47_GPIO,
+};
+
+#define TAVOREVB_ETH_PHYS (0x14000000)
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = (TAVOREVB_ETH_PHYS + 0x300),
+ .end = (TAVOREVB_ETH_PHYS + 0xfffff),
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO47)),
+ .end = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO47)),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+ }
+};
+
+static struct smc91x_platdata tavorevb_smc91x_info = {
+ .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_USE_DMA,
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+ .dev = {
+ .platform_data = &tavorevb_smc91x_info,
+ },
+};
+
+static void __init tavorevb_init(void)
+{
+ /* initialize MFP configurations */
+ pxa3xx_mfp_config(ARRAY_AND_SIZE(tavorevb_mfp_cfg));
+
+ platform_device_register(&smc91x_device);
+}
+
+MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
+ /* Maintainer: Eric Miao <eric.miao@marvell.com> */
+ .phys_io = 0x40000000,
+ .boot_params = 0xa0000100,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .map_io = pxa_map_io,
+ .init_irq = pxa3xx_init_irq,
+ .timer = &pxa_timer,
+ .init_machine = tavorevb_init,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/tosa-bt.c b/arch/arm/mach-pxa/tosa-bt.c
new file mode 100644
index 00000000000..7d8505466e5
--- /dev/null
+++ b/arch/arm/mach-pxa/tosa-bt.c
@@ -0,0 +1,150 @@
+/*
+ * Bluetooth built-in chip control
+ *
+ * Copyright (c) 2008 Dmitry Baryshkov
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/rfkill.h>
+
+#include <asm/arch/tosa_bt.h>
+
+static void tosa_bt_on(struct tosa_bt_data *data)
+{
+ gpio_set_value(data->gpio_reset, 0);
+ gpio_set_value(data->gpio_pwr, 1);
+ gpio_set_value(data->gpio_reset, 1);
+ mdelay(20);
+ gpio_set_value(data->gpio_reset, 0);
+}
+
+static void tosa_bt_off(struct tosa_bt_data *data)
+{
+ gpio_set_value(data->gpio_reset, 1);
+ mdelay(10);
+ gpio_set_value(data->gpio_pwr, 0);
+ gpio_set_value(data->gpio_reset, 0);
+}
+
+static int tosa_bt_toggle_radio(void *data, enum rfkill_state state)
+{
+ pr_info("BT_RADIO going: %s\n",
+ state == RFKILL_STATE_ON ? "on" : "off");
+
+ if (state == RFKILL_STATE_ON) {
+ pr_info("TOSA_BT: going ON\n");
+ tosa_bt_on(data);
+ } else {
+ pr_info("TOSA_BT: going OFF\n");
+ tosa_bt_off(data);
+ }
+ return 0;
+}
+
+static int tosa_bt_probe(struct platform_device *dev)
+{
+ int rc;
+ struct rfkill *rfk;
+
+ struct tosa_bt_data *data = dev->dev.platform_data;
+
+ rc = gpio_request(data->gpio_reset, "Bluetooth reset");
+ if (rc)
+ goto err_reset;
+ rc = gpio_direction_output(data->gpio_reset, 0);
+ if (rc)
+ goto err_reset_dir;
+ rc = gpio_request(data->gpio_pwr, "Bluetooth power");
+ if (rc)
+ goto err_pwr;
+ rc = gpio_direction_output(data->gpio_pwr, 0);
+ if (rc)
+ goto err_pwr_dir;
+
+ rfk = rfkill_allocate(&dev->dev, RFKILL_TYPE_BLUETOOTH);
+ if (!rfk) {
+ rc = -ENOMEM;
+ goto err_rfk_alloc;
+ }
+
+ rfk->name = "tosa-bt";
+ rfk->toggle_radio = tosa_bt_toggle_radio;
+ rfk->data = data;
+#ifdef CONFIG_RFKILL_LEDS
+ rfk->led_trigger.name = "tosa-bt";
+#endif
+
+ rc = rfkill_register(rfk);
+ if (rc)
+ goto err_rfkill;
+
+ platform_set_drvdata(dev, rfk);
+
+ return 0;
+
+err_rfkill:
+ if (rfk)
+ rfkill_free(rfk);
+ rfk = NULL;
+err_rfk_alloc:
+ tosa_bt_off(data);
+err_pwr_dir:
+ gpio_free(data->gpio_pwr);
+err_pwr:
+err_reset_dir:
+ gpio_free(data->gpio_reset);
+err_reset:
+ return rc;
+}
+
+static int __devexit tosa_bt_remove(struct platform_device *dev)
+{
+ struct tosa_bt_data *data = dev->dev.platform_data;
+ struct rfkill *rfk = platform_get_drvdata(dev);
+
+ platform_set_drvdata(dev, NULL);
+
+ if (rfk)
+ rfkill_unregister(rfk);
+ rfk = NULL;
+
+ tosa_bt_off(data);
+
+ gpio_free(data->gpio_pwr);
+ gpio_free(data->gpio_reset);
+
+ return 0;
+}
+
+static struct platform_driver tosa_bt_driver = {
+ .probe = tosa_bt_probe,
+ .remove = __devexit_p(tosa_bt_remove),
+
+ .driver = {
+ .name = "tosa-bt",
+ .owner = THIS_MODULE,
+ },
+};
+
+
+static int __init tosa_bt_init(void)
+{
+ return platform_driver_register(&tosa_bt_driver);
+}
+
+static void __exit tosa_bt_exit(void)
+{
+ platform_driver_unregister(&tosa_bt_driver);
+}
+
+module_init(tosa_bt_init);
+module_exit(tosa_bt_exit);
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index ab4a9f57991..fea17ce6b55 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -18,30 +18,31 @@
#include <linux/major.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
#include <linux/mmc/host.h>
+#include <linux/mfd/tc6393xb.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
#include <linux/pm.h>
-#include <linux/delay.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/gpio.h>
+#include <linux/pda_power.h>
+#include <linux/rfkill.h>
#include <asm/setup.h>
-#include <asm/memory.h>
#include <asm/mach-types.h>
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-regs.h>
#include <asm/arch/mfp-pxa25x.h>
#include <asm/arch/irda.h>
#include <asm/arch/i2c.h>
#include <asm/arch/mmc.h>
#include <asm/arch/udc.h>
+#include <asm/arch/tosa_bt.h>
#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
#include <asm/arch/tosa.h>
#include <asm/hardware/scoop.h>
@@ -86,7 +87,7 @@ static unsigned long tosa_pin_config[] = {
GPIO6_MMC_CLK,
GPIO8_MMC_CS0,
GPIO9_GPIO, /* Detect */
- // GPIO10 nSD_INT
+ GPIO10_GPIO, /* nSD_INT */
/* CF */
GPIO13_GPIO, /* CD_IRQ */
@@ -124,34 +125,34 @@ static unsigned long tosa_pin_config[] = {
GPIO44_BTUART_CTS,
GPIO45_BTUART_RTS,
- /* IrDA */
- GPIO46_STUART_RXD,
- GPIO47_STUART_TXD,
-
/* Keybd */
- GPIO58_GPIO,
- GPIO59_GPIO,
- GPIO60_GPIO,
- GPIO61_GPIO,
- GPIO62_GPIO,
- GPIO63_GPIO,
- GPIO64_GPIO,
- GPIO65_GPIO,
- GPIO66_GPIO,
- GPIO67_GPIO,
- GPIO68_GPIO,
- GPIO69_GPIO,
- GPIO70_GPIO,
- GPIO71_GPIO,
- GPIO72_GPIO,
- GPIO73_GPIO,
- GPIO74_GPIO,
- GPIO75_GPIO,
+ GPIO58_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO59_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO60_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO61_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO62_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO63_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO64_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO65_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO66_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO67_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO68_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO69_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO70_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO71_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO72_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO73_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO74_GPIO | MFP_LPM_DRIVE_LOW,
+ GPIO75_GPIO | MFP_LPM_DRIVE_LOW,
/* SPI */
GPIO81_SSP2_CLK_OUT,
GPIO82_SSP2_FRM_OUT,
GPIO83_SSP2_TXD,
+
+ /* IrDA is managed in other way */
+ GPIO46_GPIO,
+ GPIO47_GPIO,
};
/*
@@ -249,6 +250,15 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
tosa_mci_platform_data.detect_delay = msecs_to_jiffies(250);
+ err = gpio_request(TOSA_GPIO_nSD_DETECT, "MMC/SD card detect");
+ if (err) {
+ printk(KERN_ERR "tosa_mci_init: can't request nSD_DETECT gpio\n");
+ goto err_gpio_detect;
+ }
+ err = gpio_direction_input(TOSA_GPIO_nSD_DETECT);
+ if (err)
+ goto err_gpio_detect_dir;
+
err = request_irq(TOSA_IRQ_GPIO_nSD_DETECT, tosa_detect_int,
IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"MMC/SD card detect", data);
@@ -257,7 +267,7 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
goto err_irq;
}
- err = gpio_request(TOSA_GPIO_SD_WP, "sd_wp");
+ err = gpio_request(TOSA_GPIO_SD_WP, "SD Write Protect");
if (err) {
printk(KERN_ERR "tosa_mci_init: can't request SD_WP gpio\n");
goto err_gpio_wp;
@@ -266,7 +276,7 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
if (err)
goto err_gpio_wp_dir;
- err = gpio_request(TOSA_GPIO_PWR_ON, "sd_pwr");
+ err = gpio_request(TOSA_GPIO_PWR_ON, "SD Power");
if (err) {
printk(KERN_ERR "tosa_mci_init: can't request SD_PWR gpio\n");
goto err_gpio_pwr;
@@ -275,8 +285,20 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
if (err)
goto err_gpio_pwr_dir;
+ err = gpio_request(TOSA_GPIO_nSD_INT, "SD Int");
+ if (err) {
+ printk(KERN_ERR "tosa_mci_init: can't request SD_PWR gpio\n");
+ goto err_gpio_int;
+ }
+ err = gpio_direction_input(TOSA_GPIO_nSD_INT);
+ if (err)
+ goto err_gpio_int_dir;
+
return 0;
+err_gpio_int_dir:
+ gpio_free(TOSA_GPIO_nSD_INT);
+err_gpio_int:
err_gpio_pwr_dir:
gpio_free(TOSA_GPIO_PWR_ON);
err_gpio_pwr:
@@ -285,6 +307,9 @@ err_gpio_wp_dir:
err_gpio_wp:
free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data);
err_irq:
+err_gpio_detect_dir:
+ gpio_free(TOSA_GPIO_nSD_DETECT);
+err_gpio_detect:
return err;
}
@@ -306,9 +331,11 @@ static int tosa_mci_get_ro(struct device *dev)
static void tosa_mci_exit(struct device *dev, void *data)
{
+ gpio_free(TOSA_GPIO_nSD_INT);
gpio_free(TOSA_GPIO_PWR_ON);
gpio_free(TOSA_GPIO_SD_WP);
free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data);
+ gpio_free(TOSA_GPIO_nSD_DETECT);
}
static struct pxamci_platform_data tosa_mci_platform_data = {
@@ -322,29 +349,55 @@ static struct pxamci_platform_data tosa_mci_platform_data = {
/*
* Irda
*/
+static void tosa_irda_transceiver_mode(struct device *dev, int mode)
+{
+ if (mode & IR_OFF) {
+ gpio_set_value(TOSA_GPIO_IR_POWERDWN, 0);
+ pxa2xx_transceiver_mode(dev, mode);
+ gpio_direction_output(TOSA_GPIO_IRDA_TX, 0);
+ } else {
+ pxa2xx_transceiver_mode(dev, mode);
+ gpio_set_value(TOSA_GPIO_IR_POWERDWN, 1);
+ }
+}
+
static int tosa_irda_startup(struct device *dev)
{
int ret;
+ ret = gpio_request(TOSA_GPIO_IRDA_TX, "IrDA TX");
+ if (ret)
+ goto err_tx;
+ ret = gpio_direction_output(TOSA_GPIO_IRDA_TX, 0);
+ if (ret)
+ goto err_tx_dir;
+
ret = gpio_request(TOSA_GPIO_IR_POWERDWN, "IrDA powerdown");
if (ret)
- return ret;
+ goto err_pwr;
ret = gpio_direction_output(TOSA_GPIO_IR_POWERDWN, 0);
if (ret)
- gpio_free(TOSA_GPIO_IR_POWERDWN);
+ goto err_pwr_dir;
- return ret;
- }
+ tosa_irda_transceiver_mode(dev, IR_SIRMODE | IR_OFF);
-static void tosa_irda_shutdown(struct device *dev)
-{
+ return 0;
+
+err_pwr_dir:
gpio_free(TOSA_GPIO_IR_POWERDWN);
+err_pwr:
+err_tx_dir:
+ gpio_free(TOSA_GPIO_IRDA_TX);
+err_tx:
+ return ret;
}
-static void tosa_irda_transceiver_mode(struct device *dev, int mode)
+static void tosa_irda_shutdown(struct device *dev)
{
- gpio_set_value(TOSA_GPIO_IR_POWERDWN, !(mode & IR_OFF));
+ tosa_irda_transceiver_mode(dev, IR_SIRMODE | IR_OFF);
+ gpio_free(TOSA_GPIO_IR_POWERDWN);
+ gpio_free(TOSA_GPIO_IRDA_TX);
}
static struct pxaficp_platform_data tosa_ficp_platform_data = {
@@ -355,6 +408,70 @@ static struct pxaficp_platform_data tosa_ficp_platform_data = {
};
/*
+ * Tosa AC IN
+ */
+static int tosa_power_init(struct device *dev)
+{
+ int ret = gpio_request(TOSA_GPIO_AC_IN, "ac in");
+ if (ret)
+ goto err_gpio_req;
+
+ ret = gpio_direction_input(TOSA_GPIO_AC_IN);
+ if (ret)
+ goto err_gpio_in;
+
+ return 0;
+
+err_gpio_in:
+ gpio_free(TOSA_GPIO_AC_IN);
+err_gpio_req:
+ return ret;
+}
+
+static void tosa_power_exit(struct device *dev)
+{
+ gpio_free(TOSA_GPIO_AC_IN);
+}
+
+static int tosa_power_ac_online(void)
+{
+ return gpio_get_value(TOSA_GPIO_AC_IN) == 0;
+}
+
+static char *tosa_ac_supplied_to[] = {
+ "main-battery",
+ "backup-battery",
+ "jacket-battery",
+};
+
+static struct pda_power_pdata tosa_power_data = {
+ .init = tosa_power_init,
+ .is_ac_online = tosa_power_ac_online,
+ .exit = tosa_power_exit,
+ .supplied_to = tosa_ac_supplied_to,
+ .num_supplicants = ARRAY_SIZE(tosa_ac_supplied_to),
+};
+
+static struct resource tosa_power_resource[] = {
+ {
+ .name = "ac",
+ .start = gpio_to_irq(TOSA_GPIO_AC_IN),
+ .end = gpio_to_irq(TOSA_GPIO_AC_IN),
+ .flags = IORESOURCE_IRQ |
+ IORESOURCE_IRQ_HIGHEDGE |
+ IORESOURCE_IRQ_LOWEDGE,
+ },
+};
+
+static struct platform_device tosa_power_device = {
+ .name = "pda-power",
+ .id = -1,
+ .dev.platform_data = &tosa_power_data,
+ .resource = tosa_power_resource,
+ .num_resources = ARRAY_SIZE(tosa_power_resource),
+};
+
+/*
* Tosa Keyboard
*/
static struct platform_device tosakbd_device = {
@@ -439,7 +556,7 @@ static struct gpio_led tosa_gpio_leds[] = {
},
{
.name = "tosa:blue:bluetooth",
- .default_trigger = "none",
+ .default_trigger = "tosa-bt",
.gpio = TOSA_GPIO_BT_LED,
},
};
@@ -457,21 +574,184 @@ static struct platform_device tosaled_device = {
},
};
+/*
+ * Toshiba Mobile IO Controller
+ */
+static struct resource tc6393xb_resources[] = {
+ [0] = {
+ .start = TOSA_LCDC_PHYS,
+ .end = TOSA_LCDC_PHYS + 0x3ffffff,
+ .flags = IORESOURCE_MEM,
+ },
+
+ [1] = {
+ .start = TOSA_IRQ_GPIO_TC6393XB_INT,
+ .end = TOSA_IRQ_GPIO_TC6393XB_INT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+
+static int tosa_tc6393xb_enable(struct platform_device *dev)
+{
+ int rc;
+
+ rc = gpio_request(TOSA_GPIO_TC6393XB_REST_IN, "tc6393xb #pclr");
+ if (rc)
+ goto err_req_pclr;
+ rc = gpio_request(TOSA_GPIO_TC6393XB_SUSPEND, "tc6393xb #suspend");
+ if (rc)
+ goto err_req_suspend;
+ rc = gpio_request(TOSA_GPIO_TC6393XB_L3V_ON, "l3v");
+ if (rc)
+ goto err_req_l3v;
+ rc = gpio_direction_output(TOSA_GPIO_TC6393XB_L3V_ON, 0);
+ if (rc)
+ goto err_dir_l3v;
+ rc = gpio_direction_output(TOSA_GPIO_TC6393XB_SUSPEND, 0);
+ if (rc)
+ goto err_dir_suspend;
+ rc = gpio_direction_output(TOSA_GPIO_TC6393XB_REST_IN, 0);
+ if (rc)
+ goto err_dir_pclr;
+
+ mdelay(1);
+
+ gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 1);
+
+ mdelay(10);
+
+ gpio_set_value(TOSA_GPIO_TC6393XB_REST_IN, 1);
+ gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 1);
+
+ return 0;
+err_dir_pclr:
+err_dir_suspend:
+err_dir_l3v:
+ gpio_free(TOSA_GPIO_TC6393XB_L3V_ON);
+err_req_l3v:
+ gpio_free(TOSA_GPIO_TC6393XB_SUSPEND);
+err_req_suspend:
+ gpio_free(TOSA_GPIO_TC6393XB_REST_IN);
+err_req_pclr:
+ return rc;
+}
+
+static int tosa_tc6393xb_disable(struct platform_device *dev)
+{
+ gpio_free(TOSA_GPIO_TC6393XB_L3V_ON);
+ gpio_free(TOSA_GPIO_TC6393XB_SUSPEND);
+ gpio_free(TOSA_GPIO_TC6393XB_REST_IN);
+
+ return 0;
+}
+
+static int tosa_tc6393xb_resume(struct platform_device *dev)
+{
+ gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 1);
+ mdelay(10);
+ gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 1);
+ mdelay(10);
+
+ return 0;
+}
+
+static int tosa_tc6393xb_suspend(struct platform_device *dev)
+{
+ gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 0);
+ gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 0);
+ return 0;
+}
+
+static struct mtd_partition tosa_nand_partition[] = {
+ {
+ .name = "smf",
+ .offset = 0,
+ .size = 7 * 1024 * 1024,
+ },
+ {
+ .name = "root",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 28 * 1024 * 1024,
+ },
+ {
+ .name = "home",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
+
+static struct nand_bbt_descr tosa_tc6393xb_nand_bbt = {
+ .options = 0,
+ .offs = 4,
+ .len = 2,
+ .pattern = scan_ff_pattern
+};
+
+static struct tmio_nand_data tosa_tc6393xb_nand_config = {
+ .num_partitions = ARRAY_SIZE(tosa_nand_partition),
+ .partition = tosa_nand_partition,
+ .badblock_pattern = &tosa_tc6393xb_nand_bbt,
+};
+
+static struct tc6393xb_platform_data tosa_tc6393xb_setup = {
+ .scr_pll2cr = 0x0cc1,
+ .scr_gper = 0x3300,
+ .scr_gpo_dsr =
+ TOSA_TC6393XB_GPIO_BIT(TOSA_GPIO_CARD_VCC_ON),
+ .scr_gpo_doecr =
+ TOSA_TC6393XB_GPIO_BIT(TOSA_GPIO_CARD_VCC_ON),
+
+ .irq_base = IRQ_BOARD_START,
+ .gpio_base = TOSA_TC6393XB_GPIO_BASE,
+
+ .enable = tosa_tc6393xb_enable,
+ .disable = tosa_tc6393xb_disable,
+ .suspend = tosa_tc6393xb_suspend,
+ .resume = tosa_tc6393xb_resume,
+
+ .nand_data = &tosa_tc6393xb_nand_config,
+};
+
+
+static struct platform_device tc6393xb_device = {
+ .name = "tc6393xb",
+ .id = -1,
+ .dev = {
+ .platform_data = &tosa_tc6393xb_setup,
+ },
+ .num_resources = ARRAY_SIZE(tc6393xb_resources),
+ .resource = tc6393xb_resources,
+};
+
+static struct tosa_bt_data tosa_bt_data = {
+ .gpio_pwr = TOSA_GPIO_BT_PWR_EN,
+ .gpio_reset = TOSA_GPIO_BT_RESET,
+};
+
+static struct platform_device tosa_bt_device = {
+ .name = "tosa-bt",
+ .id = -1,
+ .dev.platform_data = &tosa_bt_data,
+};
+
+
static struct platform_device *devices[] __initdata = {
&tosascoop_device,
&tosascoop_jc_device,
+ &tc6393xb_device,
+ &tosa_power_device,
&tosakbd_device,
&tosa_gpio_keys_device,
&tosaled_device,
+ &tosa_bt_device,
};
static void tosa_poweroff(void)
{
- gpio_direction_output(TOSA_GPIO_ON_RESET, 0);
- gpio_set_value(TOSA_GPIO_ON_RESET, 1);
-
- mdelay(1000);
- arm_machine_restart('h');
+ arm_machine_restart('g');
}
static void tosa_restart(char mode)
@@ -485,10 +765,14 @@ static void tosa_restart(char mode)
static void __init tosa_init(void)
{
+ int dummy;
+
pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_config));
gpio_set_wake(MFP_PIN_GPIO1, 1);
/* We can't pass to gpio-keys since it will drop the Reset altfunc */
+ init_gpio_reset(TOSA_GPIO_ON_RESET);
+
pm_power_off = tosa_poweroff;
arm_pm_restart = tosa_restart;
@@ -497,6 +781,10 @@ static void __init tosa_init(void)
/* enable batt_fault */
PMCR = 0x01;
+ dummy = gpiochip_reserve(TOSA_SCOOP_GPIO_BASE, 12);
+ dummy = gpiochip_reserve(TOSA_SCOOP_JC_GPIO_BASE, 12);
+ dummy = gpiochip_reserve(TOSA_TC6393XB_GPIO_BASE, 16);
+
pxa_set_mci_info(&tosa_mci_platform_data);
pxa_set_udc_info(&udc_info);
pxa_set_ficp_info(&tosa_ficp_platform_data);
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 61e24402308..dee7bf36f01 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -254,6 +254,7 @@ static void board_irda_mode(struct device *dev, int mode)
/* Fast mode */
trizeps_conxs_ircr |= ConXS_IRCR_MODE;
}
+ pxa2xx_transceiver_mode(dev, mode);
if (mode & IR_OFF) {
trizeps_conxs_ircr |= ConXS_IRCR_SD;
} else {
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index 66b446ca273..8fca6d890b7 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/pwm_backlight.h>
+#include <linux/smc91x.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -29,6 +30,7 @@
#include <asm/arch/zylonite.h>
#include <asm/arch/mmc.h>
#include <asm/arch/pxa27x_keypad.h>
+#include <asm/arch/pxa3xx_nand.h>
#include "devices.h"
#include "generic.h"
@@ -37,6 +39,8 @@
struct platform_mmc_slot zylonite_mmc_slot[MAX_SLOTS];
int gpio_eth_irq;
+int gpio_debug_led1;
+int gpio_debug_led2;
int wm9713_irq;
@@ -56,13 +60,57 @@ static struct resource smc91x_resources[] = {
}
};
+static struct smc91x_platdata zylonite_smc91x_info = {
+ .flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT |
+ SMC91X_NOWAIT | SMC91X_USE_DMA,
+};
+
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = 0,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
+ .dev = {
+ .platform_data = &zylonite_smc91x_info,
+ },
+};
+
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+static struct gpio_led zylonite_debug_leds[] = {
+ [0] = {
+ .name = "zylonite:yellow:1",
+ .default_trigger = "heartbeat",
+ },
+ [1] = {
+ .name = "zylonite:yellow:2",
+ .default_trigger = "default-on",
+ },
};
+static struct gpio_led_platform_data zylonite_debug_leds_info = {
+ .leds = zylonite_debug_leds,
+ .num_leds = ARRAY_SIZE(zylonite_debug_leds),
+};
+
+static struct platform_device zylonite_device_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &zylonite_debug_leds_info,
+ }
+};
+
+static void __init zylonite_init_leds(void)
+{
+ zylonite_debug_leds[0].gpio = gpio_debug_led1;
+ zylonite_debug_leds[1].gpio = gpio_debug_led2;
+
+ platform_device_register(&zylonite_device_leds);
+}
+#else
+static inline void zylonite_init_leds(void) {}
+#endif
+
#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
static struct platform_pwm_backlight_data zylonite_backlight_data = {
.pwm_id = 3,
@@ -259,7 +307,7 @@ static void __init zylonite_init_mmc(void)
static inline void zylonite_init_mmc(void) {}
#endif
-#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
+#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
static unsigned int zylonite_matrix_key_map[] = {
/* KEY(row, col, key_code) */
KEY(0, 0, KEY_A), KEY(0, 1, KEY_B), KEY(0, 2, KEY_C), KEY(0, 5, KEY_D),
@@ -324,6 +372,57 @@ static void __init zylonite_init_keypad(void)
static inline void zylonite_init_keypad(void) {}
#endif
+#if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE)
+static struct mtd_partition zylonite_nand_partitions[] = {
+ [0] = {
+ .name = "Bootloader",
+ .offset = 0,
+ .size = 0x060000,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ [1] = {
+ .name = "Kernel",
+ .offset = 0x060000,
+ .size = 0x200000,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ [2] = {
+ .name = "Filesystem",
+ .offset = 0x0260000,
+ .size = 0x3000000, /* 48M - rootfs */
+ },
+ [3] = {
+ .name = "MassStorage",
+ .offset = 0x3260000,
+ .size = 0x3d40000,
+ },
+ [4] = {
+ .name = "BBT",
+ .offset = 0x6FA0000,
+ .size = 0x80000,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* NOTE: we reserve some blocks at the end of the NAND flash for
+ * bad block management, and the max number of relocation blocks
+ * differs on different platforms. Please take care with it when
+ * defining the partition table.
+ */
+};
+
+static struct pxa3xx_nand_platform_data zylonite_nand_info = {
+ .enable_arbiter = 1,
+ .parts = zylonite_nand_partitions,
+ .nr_parts = ARRAY_SIZE(zylonite_nand_partitions),
+};
+
+static void __init zylonite_init_nand(void)
+{
+ pxa3xx_set_nand_info(&zylonite_nand_info);
+}
+#else
+static inline void zylonite_init_nand(void) {}
+#endif /* CONFIG_MTD_NAND_PXA3xx || CONFIG_MTD_NAND_PXA3xx_MODULE */
+
static void __init zylonite_init(void)
{
/* board-processor specific initialization */
@@ -342,6 +441,8 @@ static void __init zylonite_init(void)
zylonite_init_lcd();
zylonite_init_mmc();
zylonite_init_keypad();
+ zylonite_init_nand();
+ zylonite_init_leds();
}
MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
diff --git a/arch/arm/mach-pxa/zylonite_pxa300.c b/arch/arm/mach-pxa/zylonite_pxa300.c
index 6f7ae972b8d..b28d46e081d 100644
--- a/arch/arm/mach-pxa/zylonite_pxa300.c
+++ b/arch/arm/mach-pxa/zylonite_pxa300.c
@@ -16,9 +16,12 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
#include <asm/gpio.h>
#include <asm/arch/mfp-pxa300.h>
+#include <asm/arch/i2c.h>
#include <asm/arch/zylonite.h>
#include "generic.h"
@@ -109,6 +112,10 @@ static mfp_cfg_t common_mfp_cfg[] __initdata = {
GPIO12_MMC2_DAT3,
GPIO13_MMC2_CLK,
GPIO14_MMC2_CMD,
+
+ /* Standard I2C */
+ GPIO21_I2C_SCL,
+ GPIO22_I2C_SDA,
};
static mfp_cfg_t pxa300_mfp_cfg[] __initdata = {
@@ -192,6 +199,39 @@ static void __init zylonite_detect_lcd_panel(void)
pxa3xx_mfp_write(lcd_detect_pins[i], mfpr_save[i]);
}
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static struct pca953x_platform_data gpio_exp[] = {
+ [0] = {
+ .gpio_base = 128,
+ },
+ [1] = {
+ .gpio_base = 144,
+ },
+};
+
+struct i2c_board_info zylonite_i2c_board_info[] = {
+ {
+ .type = "pca9539",
+ .addr = 0x74,
+ .platform_data = &gpio_exp[0],
+ .irq = IRQ_GPIO(18),
+ }, {
+ .type = "pca9539",
+ .addr = 0x75,
+ .platform_data = &gpio_exp[1],
+ .irq = IRQ_GPIO(19),
+ },
+};
+
+static void __init zylonite_init_i2c(void)
+{
+ pxa_set_i2c_info(NULL);
+ i2c_register_board_info(0, ARRAY_AND_SIZE(zylonite_i2c_board_info));
+}
+#else
+static inline void zylonite_init_i2c(void) {}
+#endif
+
void __init zylonite_pxa300_init(void)
{
if (cpu_is_pxa300() || cpu_is_pxa310()) {
@@ -207,6 +247,8 @@ void __init zylonite_pxa300_init(void)
/* WM9713 IRQ */
wm9713_irq = mfp_to_gpio(MFP_PIN_GPIO26);
+
+ zylonite_init_i2c();
}
if (cpu_is_pxa300()) {
@@ -222,4 +264,8 @@ void __init zylonite_pxa300_init(void)
zylonite_mmc_slot[2].gpio_cd = EXT_GPIO(30);
zylonite_mmc_slot[2].gpio_wp = EXT_GPIO(31);
}
+
+ /* GPIOs for Debug LEDs */
+ gpio_debug_led1 = EXT_GPIO(25);
+ gpio_debug_led2 = EXT_GPIO(26);
}
diff --git a/arch/arm/mach-pxa/zylonite_pxa320.c b/arch/arm/mach-pxa/zylonite_pxa320.c
index 2b4fc34919a..2b7fba7a292 100644
--- a/arch/arm/mach-pxa/zylonite_pxa320.c
+++ b/arch/arm/mach-pxa/zylonite_pxa320.c
@@ -116,6 +116,10 @@ static mfp_cfg_t mfp_cfg[] __initdata = {
GPIO27_MMC2_DAT3,
GPIO28_MMC2_CLK,
GPIO29_MMC2_CMD,
+
+ /* Debug LEDs */
+ GPIO1_2_GPIO | MFP_LPM_DRIVE_HIGH,
+ GPIO4_2_GPIO | MFP_LPM_DRIVE_HIGH,
};
#define NUM_LCD_DETECT_PINS 7
@@ -189,6 +193,8 @@ void __init zylonite_pxa320_init(void)
/* GPIO pin assignment */
gpio_eth_irq = mfp_to_gpio(MFP_PIN_GPIO9);
+ gpio_debug_led1 = mfp_to_gpio(MFP_PIN_GPIO1_2);
+ gpio_debug_led2 = mfp_to_gpio(MFP_PIN_GPIO4_2);
/* MMC card detect & write protect for controller 0 */
zylonite_mmc_slot[0].gpio_cd = mfp_to_gpio(MFP_PIN_GPIO1);
diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c
index fc97fe57ee6..b5809c51d13 100644
--- a/arch/arm/mach-sa1100/clock.c
+++ b/arch/arm/mach-sa1100/clock.c
@@ -103,7 +103,7 @@ static void clk_gpio27_disable(void)
}
static struct clk clk_gpio27 = {
- .name = "GPIO27_CLK",
+ .name = "SA1111_CLK",
.rate = 3686400,
.enable = clk_gpio27_enable,
.disable = clk_gpio27_disable,
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index f64b92557b1..2e27a8c8372 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -76,3 +76,5 @@ obj-$(CONFIG_CPU_V7) += proc-v7.o
obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o
obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
+obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o
+
diff --git a/arch/arm/mm/discontig.c b/arch/arm/mm/discontig.c
index 1e560218950..c8c0c4b0f0a 100644
--- a/arch/arm/mm/discontig.c
+++ b/arch/arm/mm/discontig.c
@@ -21,26 +21,24 @@
* Our node_data structure for discontiguous memory.
*/
-static bootmem_data_t node_bootmem_data[MAX_NUMNODES];
-
pg_data_t discontig_node_data[MAX_NUMNODES] = {
- { .bdata = &node_bootmem_data[0] },
- { .bdata = &node_bootmem_data[1] },
- { .bdata = &node_bootmem_data[2] },
- { .bdata = &node_bootmem_data[3] },
+ { .bdata = &bootmem_node_data[0] },
+ { .bdata = &bootmem_node_data[1] },
+ { .bdata = &bootmem_node_data[2] },
+ { .bdata = &bootmem_node_data[3] },
#if MAX_NUMNODES == 16
- { .bdata = &node_bootmem_data[4] },
- { .bdata = &node_bootmem_data[5] },
- { .bdata = &node_bootmem_data[6] },
- { .bdata = &node_bootmem_data[7] },
- { .bdata = &node_bootmem_data[8] },
- { .bdata = &node_bootmem_data[9] },
- { .bdata = &node_bootmem_data[10] },
- { .bdata = &node_bootmem_data[11] },
- { .bdata = &node_bootmem_data[12] },
- { .bdata = &node_bootmem_data[13] },
- { .bdata = &node_bootmem_data[14] },
- { .bdata = &node_bootmem_data[15] },
+ { .bdata = &bootmem_node_data[4] },
+ { .bdata = &bootmem_node_data[5] },
+ { .bdata = &bootmem_node_data[6] },
+ { .bdata = &bootmem_node_data[7] },
+ { .bdata = &bootmem_node_data[8] },
+ { .bdata = &bootmem_node_data[9] },
+ { .bdata = &bootmem_node_data[10] },
+ { .bdata = &bootmem_node_data[11] },
+ { .bdata = &bootmem_node_data[12] },
+ { .bdata = &bootmem_node_data[13] },
+ { .bdata = &bootmem_node_data[14] },
+ { .bdata = &bootmem_node_data[15] },
#endif
};
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index b657f1719af..e6352946dde 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -284,7 +284,7 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
*/
arch_adjust_zones(node, zone_size, zhole_size);
- free_area_init_node(node, pgdat, zone_size, start_pfn, zhole_size);
+ free_area_init_node(node, zone_size, start_pfn, zhole_size);
return end_pfn;
}
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
index 7854f19b77c..5d107520e6b 100644
--- a/arch/arm/plat-omap/fb.c
+++ b/arch/arm/plat-omap/fb.c
@@ -23,6 +23,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/mm.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/bootmem.h>
@@ -182,7 +183,7 @@ void __init omapfb_reserve_sdram(void)
return;
bdata = NODE_DATA(0)->bdata;
- sdram_start = bdata->node_boot_start;
+ sdram_start = bdata->node_min_pfn << PAGE_SHIFT;
sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start;
reserved = 0;
for (i = 0; ; i++) {
@@ -340,5 +341,3 @@ unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
#endif
-
-
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 1903a3491ee..d8e9c2c3f0f 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -1488,6 +1488,9 @@ static int __init _omap_gpio_init(void)
bank->chip.set = gpio_set;
if (bank_is_mpuio(bank)) {
bank->chip.label = "mpuio";
+#ifdef CONFIG_ARCH_OMAP1
+ bank->chip.dev = &omap_mpuio_device.dev;
+#endif
bank->chip.base = OMAP_MPUIO(0);
} else {
bank->chip.label = "gpio";
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
index 6f33f58bca4..ff1413eae0b 100644
--- a/arch/arm/plat-omap/mailbox.c
+++ b/arch/arm/plat-omap/mailbox.c
@@ -334,7 +334,7 @@ static int omap_mbox_init(struct omap_mbox *mbox)
}
mbox->dev.class = &omap_mbox_class;
- strlcpy(mbox->dev.bus_id, mbox->name, KOBJ_NAME_LEN);
+ dev_set_name(&mbox->dev, "%s", mbox->name);
dev_set_drvdata(&mbox->dev, mbox);
ret = device_register(&mbox->dev);
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 0be5630ff56..8b8f564c3aa 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -12,7 +12,7 @@
#
# http://www.arm.linux.org.uk/developer/machines/?action=new
#
-# Last update: Mon Jul 7 16:25:39 2008
+# Last update: Sun Jul 13 12:04:05 2008
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@@ -1812,3 +1812,11 @@ jade MACH_JADE JADE 1821
ks8695_softplc MACH_KS8695_SOFTPLC KS8695_SOFTPLC 1822
gprisc4 MACH_GPRISC4 GPRISC4 1823
stamp9260 MACH_STAMP9260 STAMP9260 1824
+smdk6430 MACH_SMDK6430 SMDK6430 1825
+smdkc100 MACH_SMDKC100 SMDKC100 1826
+tavorevb MACH_TAVOREVB TAVOREVB 1827
+saar MACH_SAAR SAAR 1828
+deister_eyecam MACH_DEISTER_EYECAM DEISTER_EYECAM 1829
+at91sam9m10ek MACH_AT91SAM9M10EK AT91SAM9M10EK 1830
+linkstation_produo MACH_LINKSTATION_PRODUO LINKSTATION_PRODUO 1831
+hit_b0 MACH_HIT_B0 HIT_B0 1832
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index 45d63c98601..7c239a91627 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -10,6 +10,7 @@ config AVR32
# With EMBEDDED=n, we get lots of stuff automatically selected
# that we usually don't need on AVR32.
select EMBEDDED
+ select HAVE_CLK
select HAVE_OPROFILE
select HAVE_KPROBES
help
@@ -87,7 +88,7 @@ config PLATFORM_AT32AP
select SUBARCH_AVR32B
select MMU
select PERFORMANCE_COUNTERS
- select HAVE_GPIO_LIB
+ select ARCH_REQUIRE_GPIOLIB
select GENERIC_ALLOCATOR
#
diff --git a/arch/avr32/kernel/cpu.c b/arch/avr32/kernel/cpu.c
index b8409caeb23..e84faffbbec 100644
--- a/arch/avr32/kernel/cpu.c
+++ b/arch/avr32/kernel/cpu.c
@@ -26,14 +26,16 @@ static DEFINE_PER_CPU(struct cpu, cpu_devices);
* XXX: If/when a SMP-capable implementation of AVR32 will ever be
* made, we must make sure that the code executes on the correct CPU.
*/
-static ssize_t show_pc0event(struct sys_device *dev, char *buf)
+static ssize_t show_pc0event(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
unsigned long pccr;
pccr = sysreg_read(PCCR);
return sprintf(buf, "0x%lx\n", (pccr >> 12) & 0x3f);
}
-static ssize_t store_pc0event(struct sys_device *dev, const char *buf,
+static ssize_t store_pc0event(struct sys_device *dev,
+ struct sysdev_attribute *attr, const char *buf,
size_t count)
{
unsigned long val;
@@ -46,15 +48,17 @@ static ssize_t store_pc0event(struct sys_device *dev, const char *buf,
sysreg_write(PCCR, val);
return count;
}
-static ssize_t show_pc0count(struct sys_device *dev, char *buf)
+static ssize_t show_pc0count(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
unsigned long pcnt0;
pcnt0 = sysreg_read(PCNT0);
return sprintf(buf, "%lu\n", pcnt0);
}
-static ssize_t store_pc0count(struct sys_device *dev, const char *buf,
- size_t count)
+static ssize_t store_pc0count(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ const char *buf, size_t count)
{
unsigned long val;
char *endp;
@@ -67,14 +71,16 @@ static ssize_t store_pc0count(struct sys_device *dev, const char *buf,
return count;
}
-static ssize_t show_pc1event(struct sys_device *dev, char *buf)
+static ssize_t show_pc1event(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
unsigned long pccr;
pccr = sysreg_read(PCCR);
return sprintf(buf, "0x%lx\n", (pccr >> 18) & 0x3f);
}
-static ssize_t store_pc1event(struct sys_device *dev, const char *buf,
+static ssize_t store_pc1event(struct sys_device *dev,
+ struct sysdev_attribute *attr, const char *buf,
size_t count)
{
unsigned long val;
@@ -87,14 +93,16 @@ static ssize_t store_pc1event(struct sys_device *dev, const char *buf,
sysreg_write(PCCR, val);
return count;
}
-static ssize_t show_pc1count(struct sys_device *dev, char *buf)
+static ssize_t show_pc1count(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
unsigned long pcnt1;
pcnt1 = sysreg_read(PCNT1);
return sprintf(buf, "%lu\n", pcnt1);
}
-static ssize_t store_pc1count(struct sys_device *dev, const char *buf,
+static ssize_t store_pc1count(struct sys_device *dev,
+ struct sysdev_attribute *attr, const char *buf,
size_t count)
{
unsigned long val;
@@ -108,14 +116,16 @@ static ssize_t store_pc1count(struct sys_device *dev, const char *buf,
return count;
}
-static ssize_t show_pccycles(struct sys_device *dev, char *buf)
+static ssize_t show_pccycles(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
unsigned long pccnt;
pccnt = sysreg_read(PCCNT);
return sprintf(buf, "%lu\n", pccnt);
}
-static ssize_t store_pccycles(struct sys_device *dev, const char *buf,
+static ssize_t store_pccycles(struct sys_device *dev,
+ struct sysdev_attribute *attr, const char *buf,
size_t count)
{
unsigned long val;
@@ -129,14 +139,16 @@ static ssize_t store_pccycles(struct sys_device *dev, const char *buf,
return count;
}
-static ssize_t show_pcenable(struct sys_device *dev, char *buf)
+static ssize_t show_pcenable(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
unsigned long pccr;
pccr = sysreg_read(PCCR);
return sprintf(buf, "%c\n", (pccr & 1)?'1':'0');
}
-static ssize_t store_pcenable(struct sys_device *dev, const char *buf,
+static ssize_t store_pcenable(struct sys_device *dev,
+ struct sysdev_attribute *attr, const char *buf,
size_t count)
{
unsigned long pccr, val;
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c
index 6cf9df17627..ff820a9e743 100644
--- a/arch/avr32/kernel/process.c
+++ b/arch/avr32/kernel/process.c
@@ -31,7 +31,7 @@ void cpu_idle(void)
{
/* endless idle loop with no priority at all */
while (1) {
- tick_nohz_stop_sched_tick();
+ tick_nohz_stop_sched_tick(1);
while (!need_resched())
cpu_idle_sleep();
tick_nohz_restart_sched_tick();
diff --git a/arch/avr32/kernel/stacktrace.c b/arch/avr32/kernel/stacktrace.c
index f4bdb448049..c09f0d8dd67 100644
--- a/arch/avr32/kernel/stacktrace.c
+++ b/arch/avr32/kernel/stacktrace.c
@@ -10,6 +10,7 @@
#include <linux/sched.h>
#include <linux/stacktrace.h>
#include <linux/thread_info.h>
+#include <linux/module.h>
register unsigned long current_frame_pointer asm("r7");
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index 021d5121718..604f44f5dd1 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -7,6 +7,7 @@
*/
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/dw_dmac.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -594,6 +595,17 @@ static void __init genclk_init_parent(struct clk *clk)
clk->parent = parent;
}
+static struct dw_dma_platform_data dw_dmac0_data = {
+ .nr_channels = 3,
+};
+
+static struct resource dw_dmac0_resource[] = {
+ PBMEM(0xff200000),
+ IRQ(2),
+};
+DEFINE_DEV_DATA(dw_dmac, 0);
+DEV_CLK(hclk, dw_dmac0, hsb, 10);
+
/* --------------------------------------------------------------------
* System peripherals
* -------------------------------------------------------------------- */
@@ -708,17 +720,6 @@ static struct clk pico_clk = {
.users = 1,
};
-static struct resource dmaca0_resource[] = {
- {
- .start = 0xff200000,
- .end = 0xff20ffff,
- .flags = IORESOURCE_MEM,
- },
- IRQ(2),
-};
-DEFINE_DEV(dmaca, 0);
-DEV_CLK(hclk, dmaca0, hsb, 10);
-
/* --------------------------------------------------------------------
* HMATRIX
* -------------------------------------------------------------------- */
@@ -831,7 +832,7 @@ void __init at32_add_system_devices(void)
platform_device_register(&at32_eic0_device);
platform_device_register(&smc0_device);
platform_device_register(&pdc_device);
- platform_device_register(&dmaca0_device);
+ platform_device_register(&dw_dmac0_device);
platform_device_register(&at32_tcb0_device);
platform_device_register(&at32_tcb1_device);
@@ -2032,7 +2033,7 @@ struct clk *at32_clock_list[] = {
&smc0_mck,
&pdc_hclk,
&pdc_pclk,
- &dmaca0_hclk,
+ &dw_dmac0_hclk,
&pico_clk,
&pio0_mck,
&pio1_mck,
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index 60da03ba711..296294f8ed8 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -360,6 +360,8 @@ static int __init pio_probe(struct platform_device *pdev)
pio->chip.label = pio->name;
pio->chip.base = pdev->id * 32;
pio->chip.ngpio = 32;
+ pio->chip.dev = &pdev->dev;
+ pio->chip.owner = THIS_MODULE;
pio->chip.direction_input = direction_input;
pio->chip.get = gpio_get;
diff --git a/arch/avr32/mm/init.c b/arch/avr32/mm/init.c
index 3f90a87527b..3c85fdaa948 100644
--- a/arch/avr32/mm/init.c
+++ b/arch/avr32/mm/init.c
@@ -119,8 +119,7 @@ void __init paging_init(void)
unsigned long zones_size[MAX_NR_ZONES];
unsigned long low, start_pfn;
- start_pfn = pgdat->bdata->node_boot_start;
- start_pfn >>= PAGE_SHIFT;
+ start_pfn = pgdat->bdata->node_min_pfn;
low = pgdat->bdata->node_low_pfn;
memset(zones_size, 0, sizeof(zones_size));
@@ -129,7 +128,7 @@ void __init paging_init(void)
printk("Node %u: start_pfn = 0x%lx, low = 0x%lx\n",
nid, start_pfn, low);
- free_area_init_node(nid, pgdat, zones_size, start_pfn, NULL);
+ free_area_init_node(nid, zones_size, start_pfn, NULL);
printk("Node %u: mem_map starts at %p\n",
pgdat->node_id, pgdat->node_mem_map);
diff --git a/arch/avr32/mm/ioremap.c b/arch/avr32/mm/ioremap.c
index 3437c82434a..f03b79f0e0a 100644
--- a/arch/avr32/mm/ioremap.c
+++ b/arch/avr32/mm/ioremap.c
@@ -6,6 +6,7 @@
* published by the Free Software Foundation.
*/
#include <linux/vmalloc.h>
+#include <linux/mm.h>
#include <linux/module.h>
#include <linux/io.h>
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index b87634e75f2..b83b8ef84e9 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -873,8 +873,8 @@ config HOTPLUG
plugged into slots found on all modern laptop computers. Another
example, used on modern desktops as well as laptops, is USB.
- Enable HOTPLUG and KMOD, and build a modular kernel. Get agent
- software (at <http://linux-hotplug.sourceforge.net/>) and install it.
+ Enable HOTPLUG and build a modular kernel. Get agent software
+ (from <http://linux-hotplug.sourceforge.net/>) and install it.
Then your kernel will automatically call out to a user mode "policy
agent" (/sbin/hotplug) to load modules and set up software needed
to use devices as you hotplug them.
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index 53c2cd25544..77800dd83e5 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -105,7 +105,7 @@ void cpu_idle(void)
#endif
if (!idle)
idle = default_idle;
- tick_nohz_stop_sched_tick();
+ tick_nohz_stop_sched_tick(1);
while (!need_resched())
idle();
tick_nohz_restart_sched_tick();
diff --git a/arch/cris/arch-v10/boot/compressed/misc.c b/arch/cris/arch-v10/boot/compressed/misc.c
index 18e13bce140..d933c89889d 100644
--- a/arch/cris/arch-v10/boot/compressed/misc.c
+++ b/arch/cris/arch-v10/boot/compressed/misc.c
@@ -102,50 +102,16 @@ extern char *input_data; /* lives in head.S */
static long bytes_out = 0;
static uch *output_data;
static unsigned long output_ptr = 0;
-
-static void *malloc(int size);
-static void free(void *where);
-static void gzip_mark(void **);
-static void gzip_release(void **);
-
static void puts(const char *);
/* the "heap" is put directly after the BSS ends, at end */
extern int _end;
static long free_mem_ptr = (long)&_end;
+static long free_mem_end_ptr;
#include "../../../../../lib/inflate.c"
-static void *malloc(int size)
-{
- void *p;
-
- if (size < 0)
- error("Malloc error");
-
- free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
- p = (void *)free_mem_ptr;
- free_mem_ptr += size;
-
- return p;
-}
-
-static void free(void *where)
-{ /* Don't care */
-}
-
-static void gzip_mark(void **ptr)
-{
- *ptr = (void *) free_mem_ptr;
-}
-
-static void gzip_release(void **ptr)
-{
- free_mem_ptr = (long) *ptr;
-}
-
/* decompressor info and error messages to serial console */
static void
diff --git a/arch/cris/arch-v10/mm/init.c b/arch/cris/arch-v10/mm/init.c
index e0fcd1a9bfd..742fd1974c2 100644
--- a/arch/cris/arch-v10/mm/init.c
+++ b/arch/cris/arch-v10/mm/init.c
@@ -182,7 +182,7 @@ paging_init(void)
* mem_map page array.
*/
- free_area_init_node(0, &contig_page_data, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
+ free_area_init_node(0, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
}
/* Initialize remaps of some I/O-ports. It is important that this
diff --git a/arch/cris/arch-v32/boot/compressed/misc.c b/arch/cris/arch-v32/boot/compressed/misc.c
index 55b2695c5d7..3595e16e82b 100644
--- a/arch/cris/arch-v32/boot/compressed/misc.c
+++ b/arch/cris/arch-v32/boot/compressed/misc.c
@@ -89,20 +89,14 @@ static unsigned outcnt = 0; /* bytes in output buffer */
static void flush_window(void);
static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
extern char *input_data; /* lives in head.S */
-static long bytes_out = 0;
+static long bytes_out;
static uch *output_data;
-static unsigned long output_ptr = 0;
+static unsigned long output_ptr;
-static void *malloc(int size);
-static void free(void *where);
static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
static void puts(const char *);
@@ -110,37 +104,10 @@ static void puts(const char *);
extern int _end;
static long free_mem_ptr = (long)&_end;
+static long free_mem_end_ptr;
#include "../../../../../lib/inflate.c"
-static void *malloc(int size)
-{
- void *p;
-
- if (size <0) error("Malloc error");
-
- free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
- p = (void *)free_mem_ptr;
- free_mem_ptr += size;
-
- return p;
-}
-
-static void free(void *where)
-{ /* Don't care */
-}
-
-static void gzip_mark(void **ptr)
-{
- *ptr = (void *) free_mem_ptr;
-}
-
-static void gzip_release(void **ptr)
-{
- free_mem_ptr = (long) *ptr;
-}
-
/* decompressor info and error messages to serial console */
static inline void
diff --git a/arch/cris/arch-v32/mm/init.c b/arch/cris/arch-v32/mm/init.c
index 5a9ac583464..8a34b8b7429 100644
--- a/arch/cris/arch-v32/mm/init.c
+++ b/arch/cris/arch-v32/mm/init.c
@@ -162,7 +162,7 @@ paging_init(void)
* substantially higher than 0, like us (we start at PAGE_OFFSET). This
* saves space in the mem_map page array.
*/
- free_area_init_node(0, &contig_page_data, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
+ free_area_init_node(0, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
mem_map = contig_page_data.node_mem_map;
}
diff --git a/arch/cris/kernel/profile.c b/arch/cris/kernel/profile.c
index 44f7b4f7947..9aa571169bc 100644
--- a/arch/cris/kernel/profile.c
+++ b/arch/cris/kernel/profile.c
@@ -35,19 +35,16 @@ read_cris_profile(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
+ ssize_t ret;
- if (p > SAMPLE_BUFFER_SIZE)
- return 0;
+ ret = simple_read_from_buffer(buf, count, ppos, sample_buffer,
+ SAMPLE_BUFFER_SIZE);
+ if (ret < 0)
+ return ret;
- if (p + count > SAMPLE_BUFFER_SIZE)
- count = SAMPLE_BUFFER_SIZE - p;
- if (copy_to_user(buf, sample_buffer + p,count))
- return -EFAULT;
+ memset(sample_buffer + p, 0, ret);
- memset(sample_buffer + p, 0, count);
- *ppos += count;
-
- return count;
+ return ret;
}
static ssize_t
diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c
index 73f3aeefd20..d1113c5031f 100644
--- a/arch/frv/kernel/pm.c
+++ b/arch/frv/kernel/pm.c
@@ -14,7 +14,6 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pm.h>
-#include <linux/pm_legacy.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/sysctl.h>
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 085dc6ec152..396ab059efa 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -203,20 +203,6 @@ config UNIX98_PTYS
Read the instructions in <file:Documentation/Changes> pertaining to
pseudo terminals. It's safe to say N.
-config UNIX98_PTY_COUNT
- int "Maximum number of Unix98 PTYs in use (0-2048)"
- depends on UNIX98_PTYS
- default "256"
- help
- The maximum number of Unix98 PTYs that can be used at any one time.
- The default is 256, and should be enough for desktop systems. Server
- machines which support incoming telnet/rlogin/ssh connections and/or
- serve several X terminals may want to increase this: every incoming
- connection and every xterm uses up one PTY.
-
- When not in use, each additional set of 256 PTYs occupy
- approximately 8 KB of kernel memory on 32-bit architectures.
-
source "drivers/char/pcmcia/Kconfig"
source "drivers/serial/Kconfig"
diff --git a/arch/h8300/boot/compressed/misc.c b/arch/h8300/boot/compressed/misc.c
index 845074588af..51ab6cbd030 100644
--- a/arch/h8300/boot/compressed/misc.c
+++ b/arch/h8300/boot/compressed/misc.c
@@ -67,8 +67,6 @@ static unsigned outcnt = 0; /* bytes in output buffer */
static int fill_inbuf(void);
static void flush_window(void);
static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
extern char input_data[];
extern int input_len;
@@ -77,11 +75,7 @@ static long bytes_out = 0;
static uch *output_data;
static unsigned long output_ptr = 0;
-static void *malloc(int size);
-static void free(void *where);
static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
int puts(const char *);
@@ -98,38 +92,6 @@ static unsigned long free_mem_end_ptr;
#define TDR *((volatile unsigned char *)0xffff8b)
#define SSR *((volatile unsigned char *)0xffff8c)
-static void *malloc(int size)
-{
- void *p;
-
- if (size <0) error("Malloc error");
- if (free_mem_ptr == 0) error("Memory error");
-
- free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
- p = (void *)free_mem_ptr;
- free_mem_ptr += size;
-
- if (free_mem_ptr >= free_mem_end_ptr)
- error("Out of memory");
-
- return p;
-}
-
-static void free(void *where)
-{ /* Don't care */
-}
-
-static void gzip_mark(void **ptr)
-{
- *ptr = (void *) free_mem_ptr;
-}
-
-static void gzip_release(void **ptr)
-{
- free_mem_ptr = (long) *ptr;
-}
-
int puts(const char *s)
{
return 0;
diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c
index b1f25c20a5d..7fda657110e 100644
--- a/arch/h8300/kernel/setup.c
+++ b/arch/h8300/kernel/setup.c
@@ -20,6 +20,7 @@
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/fb.h>
#include <linux/console.h>
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index 7e028ceb93b..465116aecb8 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -1139,7 +1139,7 @@ sys32_pipe (int __user *fd)
int retval;
int fds[2];
- retval = do_pipe(fds);
+ retval = do_pipe_flags(fds, 0);
if (retval)
goto out;
if (copy_to_user(fd, fds, sizeof(fds)))
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 56ab156c48a..0dd6c1419d8 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1691,6 +1691,12 @@ sys_call_table:
data8 sys_timerfd_create // 1310
data8 sys_timerfd_settime
data8 sys_timerfd_gettime
+ data8 sys_signalfd4
+ data8 sys_eventfd2
+ data8 sys_epoll_create1 // 1315
+ data8 sys_dup3
+ data8 sys_pipe2
+ data8 sys_inotify_init1
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
diff --git a/arch/ia64/kernel/err_inject.c b/arch/ia64/kernel/err_inject.c
index b642648cc2a..c539c689493 100644
--- a/arch/ia64/kernel/err_inject.c
+++ b/arch/ia64/kernel/err_inject.c
@@ -55,7 +55,8 @@ static u64 resources[NR_CPUS];
#define show(name) \
static ssize_t \
-show_##name(struct sys_device *dev, char *buf) \
+show_##name(struct sys_device *dev, struct sysdev_attribute *attr, \
+ char *buf) \
{ \
u32 cpu=dev->id; \
return sprintf(buf, "%lx\n", name[cpu]); \
@@ -63,7 +64,8 @@ show_##name(struct sys_device *dev, char *buf) \
#define store(name) \
static ssize_t \
-store_##name(struct sys_device *dev, const char *buf, size_t size) \
+store_##name(struct sys_device *dev, struct sysdev_attribute *attr, \
+ const char *buf, size_t size) \
{ \
unsigned int cpu=dev->id; \
name[cpu] = simple_strtoull(buf, NULL, 16); \
@@ -76,7 +78,8 @@ show(call_start)
* processor. The cpu number in driver is only used for storing data.
*/
static ssize_t
-store_call_start(struct sys_device *dev, const char *buf, size_t size)
+store_call_start(struct sys_device *dev, struct sysdev_attribute *attr,
+ const char *buf, size_t size)
{
unsigned int cpu=dev->id;
unsigned long call_start = simple_strtoull(buf, NULL, 16);
@@ -124,14 +127,16 @@ show(err_type_info)
store(err_type_info)
static ssize_t
-show_virtual_to_phys(struct sys_device *dev, char *buf)
+show_virtual_to_phys(struct sys_device *dev, struct sysdev_attribute *attr,
+ char *buf)
{
unsigned int cpu=dev->id;
return sprintf(buf, "%lx\n", phys_addr[cpu]);
}
static ssize_t
-store_virtual_to_phys(struct sys_device *dev, const char *buf, size_t size)
+store_virtual_to_phys(struct sys_device *dev, struct sysdev_attribute *attr,
+ const char *buf, size_t size)
{
unsigned int cpu=dev->id;
u64 virt_addr=simple_strtoull(buf, NULL, 16);
@@ -154,7 +159,8 @@ show(err_struct_info)
store(err_struct_info)
static ssize_t
-show_err_data_buffer(struct sys_device *dev, char *buf)
+show_err_data_buffer(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
unsigned int cpu=dev->id;
@@ -165,7 +171,9 @@ show_err_data_buffer(struct sys_device *dev, char *buf)
}
static ssize_t
-store_err_data_buffer(struct sys_device *dev, const char *buf, size_t size)
+store_err_data_buffer(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ const char *buf, size_t size)
{
unsigned int cpu=dev->id;
int ret;
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 233434f4f88..f07688da947 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -429,8 +429,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
((struct fnptr *)kretprobe_trampoline)->ip;
INIT_HLIST_HEAD(&empty_rp);
- spin_lock_irqsave(&kretprobe_lock, flags);
- head = kretprobe_inst_table_head(current);
+ kretprobe_hash_lock(current, &head, &flags);
/*
* It is possible to have multiple instances associated with a given
@@ -485,7 +484,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
kretprobe_assert(ri, orig_ret_address, trampoline_address);
reset_current_kprobe();
- spin_unlock_irqrestore(&kretprobe_lock, flags);
+ kretprobe_hash_unlock(current, &flags);
preempt_enable_no_resched();
hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
@@ -500,7 +499,6 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
return 1;
}
-/* Called with kretprobe_lock held */
void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
struct pt_regs *regs)
{
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
index 1eda194b955..bcbb6d8792d 100644
--- a/arch/ia64/kernel/sys_ia64.c
+++ b/arch/ia64/kernel/sys_ia64.c
@@ -160,7 +160,7 @@ sys_pipe (void)
int fd[2];
int retval;
- retval = do_pipe(fd);
+ retval = do_pipe_flags(fd, 0);
if (retval)
goto out;
retval = fd[0];
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 544dc420c65..d83125e1ed2 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -36,7 +36,6 @@ struct early_node_data {
struct ia64_node_data *node_data;
unsigned long pernode_addr;
unsigned long pernode_size;
- struct bootmem_data bootmem_data;
unsigned long num_physpages;
#ifdef CONFIG_ZONE_DMA
unsigned long num_dma_physpages;
@@ -75,17 +74,17 @@ pg_data_t *pgdat_list[MAX_NUMNODES];
static int __init build_node_maps(unsigned long start, unsigned long len,
int node)
{
- unsigned long cstart, epfn, end = start + len;
- struct bootmem_data *bdp = &mem_data[node].bootmem_data;
+ unsigned long spfn, epfn, end = start + len;
+ struct bootmem_data *bdp = &bootmem_node_data[node];
epfn = GRANULEROUNDUP(end) >> PAGE_SHIFT;
- cstart = GRANULEROUNDDOWN(start);
+ spfn = GRANULEROUNDDOWN(start) >> PAGE_SHIFT;
if (!bdp->node_low_pfn) {
- bdp->node_boot_start = cstart;
+ bdp->node_min_pfn = spfn;
bdp->node_low_pfn = epfn;
} else {
- bdp->node_boot_start = min(cstart, bdp->node_boot_start);
+ bdp->node_min_pfn = min(spfn, bdp->node_min_pfn);
bdp->node_low_pfn = max(epfn, bdp->node_low_pfn);
}
@@ -167,7 +166,7 @@ static void __init fill_pernode(int node, unsigned long pernode,
{
void *cpu_data;
int cpus = early_nr_cpus_node(node);
- struct bootmem_data *bdp = &mem_data[node].bootmem_data;
+ struct bootmem_data *bdp = &bootmem_node_data[node];
mem_data[node].pernode_addr = pernode;
mem_data[node].pernode_size = pernodesize;
@@ -222,20 +221,21 @@ static void __init fill_pernode(int node, unsigned long pernode,
static int __init find_pernode_space(unsigned long start, unsigned long len,
int node)
{
- unsigned long epfn;
+ unsigned long spfn, epfn;
unsigned long pernodesize = 0, pernode, pages, mapsize;
- struct bootmem_data *bdp = &mem_data[node].bootmem_data;
+ struct bootmem_data *bdp = &bootmem_node_data[node];
+ spfn = start >> PAGE_SHIFT;
epfn = (start + len) >> PAGE_SHIFT;
- pages = bdp->node_low_pfn - (bdp->node_boot_start >> PAGE_SHIFT);
+ pages = bdp->node_low_pfn - bdp->node_min_pfn;
mapsize = bootmem_bootmap_pages(pages) << PAGE_SHIFT;
/*
* Make sure this memory falls within this node's usable memory
* since we may have thrown some away in build_maps().
*/
- if (start < bdp->node_boot_start || epfn > bdp->node_low_pfn)
+ if (spfn < bdp->node_min_pfn || epfn > bdp->node_low_pfn)
return 0;
/* Don't setup this node's local space twice... */
@@ -297,7 +297,7 @@ static void __init reserve_pernode_space(void)
bdp = pdp->bdata;
/* First the bootmem_map itself */
- pages = bdp->node_low_pfn - (bdp->node_boot_start>>PAGE_SHIFT);
+ pages = bdp->node_low_pfn - bdp->node_min_pfn;
size = bootmem_bootmap_pages(pages) << PAGE_SHIFT;
base = __pa(bdp->node_bootmem_map);
reserve_bootmem_node(pdp, base, size, BOOTMEM_DEFAULT);
@@ -440,7 +440,7 @@ void __init find_memory(void)
efi_memmap_walk(find_max_min_low_pfn, NULL);
for_each_online_node(node)
- if (mem_data[node].bootmem_data.node_low_pfn) {
+ if (bootmem_node_data[node].node_low_pfn) {
node_clear(node, memory_less_mask);
mem_data[node].min_pfn = ~0UL;
}
@@ -460,14 +460,14 @@ void __init find_memory(void)
else if (node_isset(node, memory_less_mask))
continue;
- bdp = &mem_data[node].bootmem_data;
+ bdp = &bootmem_node_data[node];
pernode = mem_data[node].pernode_addr;
pernodesize = mem_data[node].pernode_size;
map = pernode + pernodesize;
init_bootmem_node(pgdat_list[node],
map>>PAGE_SHIFT,
- bdp->node_boot_start>>PAGE_SHIFT,
+ bdp->node_min_pfn,
bdp->node_low_pfn);
}
diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
index d3ce8f3bcaa..c45fc7f5a97 100644
--- a/arch/ia64/mm/hugetlbpage.c
+++ b/arch/ia64/mm/hugetlbpage.c
@@ -24,7 +24,7 @@
unsigned int hpage_shift=HPAGE_SHIFT_DEFAULT;
pte_t *
-huge_pte_alloc (struct mm_struct *mm, unsigned long addr)
+huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz)
{
unsigned long taddr = htlbpage_to_page(addr);
pgd_t *pgd;
@@ -75,7 +75,8 @@ int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
* Don't actually need to do any preparation, but need to make sure
* the address is in the right region.
*/
-int prepare_hugepage_range(unsigned long addr, unsigned long len)
+int prepare_hugepage_range(struct file *file,
+ unsigned long addr, unsigned long len)
{
if (len & ~HPAGE_MASK)
return -EINVAL;
@@ -106,13 +107,19 @@ int pmd_huge(pmd_t pmd)
{
return 0;
}
+
+int pud_huge(pud_t pud)
+{
+ return 0;
+}
+
struct page *
follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write)
{
return NULL;
}
-void hugetlb_free_pgd_range(struct mmu_gather **tlb,
+void hugetlb_free_pgd_range(struct mmu_gather *tlb,
unsigned long addr, unsigned long end,
unsigned long floor, unsigned long ceiling)
{
@@ -149,7 +156,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, u
/* Handle MAP_FIXED */
if (flags & MAP_FIXED) {
- if (prepare_hugepage_range(addr, len))
+ if (prepare_hugepage_range(file, addr, len))
return -EINVAL;
return addr;
}
diff --git a/arch/m32r/boot/compressed/misc.c b/arch/m32r/boot/compressed/misc.c
index 600d40e3349..d394292498c 100644
--- a/arch/m32r/boot/compressed/misc.c
+++ b/arch/m32r/boot/compressed/misc.c
@@ -70,8 +70,6 @@ static unsigned outcnt = 0; /* bytes in output buffer */
static int fill_inbuf(void);
static void flush_window(void);
static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
static unsigned char *input_data;
static int input_len;
@@ -82,9 +80,6 @@ static unsigned long output_ptr = 0;
#include "m32r_sio.c"
-static void *malloc(int size);
-static void free(void *where);
-
static unsigned long free_mem_ptr;
static unsigned long free_mem_end_ptr;
@@ -92,38 +87,6 @@ static unsigned long free_mem_end_ptr;
#include "../../../../lib/inflate.c"
-static void *malloc(int size)
-{
- void *p;
-
- if (size <0) error("Malloc error");
- if (free_mem_ptr == 0) error("Memory error");
-
- free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
- p = (void *)free_mem_ptr;
- free_mem_ptr += size;
-
- if (free_mem_ptr >= free_mem_end_ptr)
- error("Out of memory");
-
- return p;
-}
-
-static void free(void *where)
-{ /* Don't care */
-}
-
-static void gzip_mark(void **ptr)
-{
- *ptr = (void *) free_mem_ptr;
-}
-
-static void gzip_release(void **ptr)
-{
- free_mem_ptr = (long) *ptr;
-}
-
void* memset(void* s, int c, size_t n)
{
int i;
diff --git a/arch/m32r/mm/discontig.c b/arch/m32r/mm/discontig.c
index 07c1af7dc0e..cbc3c4c5456 100644
--- a/arch/m32r/mm/discontig.c
+++ b/arch/m32r/mm/discontig.c
@@ -20,7 +20,6 @@ extern char _end[];
struct pglist_data *node_data[MAX_NUMNODES];
EXPORT_SYMBOL(node_data);
-static bootmem_data_t node_bdata[MAX_NUMNODES] __initdata;
pg_data_t m32r_node_data[MAX_NUMNODES];
@@ -81,7 +80,7 @@ unsigned long __init setup_memory(void)
for_each_online_node(nid) {
mp = &mem_prof[nid];
NODE_DATA(nid)=(pg_data_t *)&m32r_node_data[nid];
- NODE_DATA(nid)->bdata = &node_bdata[nid];
+ NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
min_pfn = mp->start_pfn;
max_pfn = mp->start_pfn + mp->pages;
bootmap_size = init_bootmem_node(NODE_DATA(nid), mp->free_pfn,
@@ -124,8 +123,7 @@ unsigned long __init setup_memory(void)
return max_low_pfn;
}
-#define START_PFN(nid) \
- (NODE_DATA(nid)->bdata->node_boot_start >> PAGE_SHIFT)
+#define START_PFN(nid) (NODE_DATA(nid)->bdata->node_min_pfn)
#define MAX_LOW_PFN(nid) (NODE_DATA(nid)->bdata->node_low_pfn)
unsigned long __init zone_sizes_init(void)
@@ -148,8 +146,7 @@ unsigned long __init zone_sizes_init(void)
zholes_size[ZONE_DMA] = mp->holes;
holes += zholes_size[ZONE_DMA];
- free_area_init_node(nid, NODE_DATA(nid), zones_size,
- start_pfn, zholes_size);
+ free_area_init_node(nid, zones_size, start_pfn, zholes_size);
}
/*
@@ -163,4 +160,3 @@ unsigned long __init zone_sizes_init(void)
return holes;
}
-
diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c
index bbd97c85bc5..2554eb59cfe 100644
--- a/arch/m32r/mm/init.c
+++ b/arch/m32r/mm/init.c
@@ -93,8 +93,7 @@ void free_initrd_mem(unsigned long, unsigned long);
#endif
/* It'd be good if these lines were in the standard header file. */
-#define START_PFN(nid) \
- (NODE_DATA(nid)->bdata->node_boot_start >> PAGE_SHIFT)
+#define START_PFN(nid) (NODE_DATA(nid)->bdata->node_min_pfn)
#define MAX_LOW_PFN(nid) (NODE_DATA(nid)->bdata->node_low_pfn)
#ifndef CONFIG_DISCONTIGMEM
@@ -123,7 +122,7 @@ unsigned long __init zone_sizes_init(void)
start_pfn = __MEMORY_START >> PAGE_SHIFT;
#endif /* CONFIG_MMU */
- free_area_init_node(0, NODE_DATA(0), zones_size, start_pfn, 0);
+ free_area_init_node(0, zones_size, start_pfn, 0);
return 0;
}
@@ -252,4 +251,3 @@ void free_initrd_mem(unsigned long start, unsigned long end)
printk (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
}
#endif
-
diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c
index cbe36538af4..61df1d33c05 100644
--- a/arch/m68k/amiga/chipram.c
+++ b/arch/m68k/amiga/chipram.c
@@ -9,6 +9,7 @@
#include <linux/types.h>
#include <linux/kernel.h>
+#include <linux/mm.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/slab.h>
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
index d8fb9c5303c..79f5f94d480 100644
--- a/arch/m68k/mm/init.c
+++ b/arch/m68k/mm/init.c
@@ -32,8 +32,6 @@
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
-static bootmem_data_t __initdata bootmem_data[MAX_NUMNODES];
-
pg_data_t pg_data_map[MAX_NUMNODES];
EXPORT_SYMBOL(pg_data_map);
@@ -58,7 +56,7 @@ void __init m68k_setup_node(int node)
pg_data_table[i] = pg_data_map + node;
}
#endif
- pg_data_map[node].bdata = bootmem_data + node;
+ pg_data_map[node].bdata = bootmem_node_data + node;
node_set_online(node);
}
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
index 226795bdf35..c5dbb9bdb32 100644
--- a/arch/m68k/mm/motorola.c
+++ b/arch/m68k/mm/motorola.c
@@ -296,7 +296,7 @@ void __init paging_init(void)
#endif
for (i = 0; i < m68k_num_memory; i++) {
zones_size[ZONE_DMA] = m68k_memory[i].size >> PAGE_SHIFT;
- free_area_init_node(i, pg_data_map + i, zones_size,
+ free_area_init_node(i, zones_size,
m68k_memory[i].addr >> PAGE_SHIFT, NULL);
}
}
diff --git a/arch/m68k/mm/sun3mmu.c b/arch/m68k/mm/sun3mmu.c
index edceefc1887..1b902dbd437 100644
--- a/arch/m68k/mm/sun3mmu.c
+++ b/arch/m68k/mm/sun3mmu.c
@@ -94,7 +94,7 @@ void __init paging_init(void)
/* I really wish I knew why the following change made things better... -- Sam */
/* free_area_init(zones_size); */
- free_area_init_node(0, NODE_DATA(0), zones_size,
+ free_area_init_node(0, zones_size,
(__pa(PAGE_OFFSET) >> PAGE_SHIFT) + 1, NULL);
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 8e8441587c2..2e7515e8db9 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -58,10 +58,18 @@ config GENERIC_TIME
bool
default y
+config GENERIC_CMOS_UPDATE
+ bool
+ default y
+
config TIME_LOW_RES
bool
default y
+config GENERIC_CLOCKEVENTS
+ bool
+ default n
+
config NO_IOPORT
def_bool y
@@ -108,11 +116,13 @@ config M5206e
config M520x
bool "MCF520x"
+ select GENERIC_CLOCKEVENTS
help
Freescale Coldfire 5207/5208 processor support.
config M523x
bool "MCF523x"
+ select GENERIC_CLOCKEVENTS
help
Freescale Coldfire 5230/1/2/4/5 processor support
@@ -138,6 +148,7 @@ config M5275
config M528x
bool "MCF528x"
+ select GENERIC_CLOCKEVENTS
help
Motorola ColdFire 5280/5282 processor support.
@@ -161,6 +172,7 @@ endchoice
config M527x
bool
depends on (M5271 || M5275)
+ select GENERIC_CLOCKEVENTS
default y
config COLDFIRE
@@ -674,6 +686,9 @@ endchoice
if COLDFIRE
source "kernel/Kconfig.preempt"
endif
+
+source "kernel/time/Kconfig"
+
source "mm/Kconfig"
endmenu
diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile
index e0b5f62e395..b63bbcf874f 100644
--- a/arch/m68knommu/Makefile
+++ b/arch/m68knommu/Makefile
@@ -8,6 +8,8 @@
# (C) Copyright 2002, Greg Ungerer <gerg@snapgear.com>
#
+KBUILD_DEFCONFIG := m5208evb_defconfig
+
platform-$(CONFIG_M68328) := 68328
platform-$(CONFIG_M68EZ328) := 68EZ328
platform-$(CONFIG_M68VZ328) := 68VZ328
@@ -90,13 +92,14 @@ export PLATFORM BOARD MODEL CPUCLASS
cflags-$(CONFIG_M5206) := -m5200
cflags-$(CONFIG_M5206e) := -m5200
cflags-$(CONFIG_M520x) := -m5307
-cflags-$(CONFIG_M523x) := -m5307
+cflags-$(CONFIG_M523x) := $(call cc-option,-mcpu=523x,-m5307)
cflags-$(CONFIG_M5249) := -m5200
-cflags-$(CONFIG_M527x) := -m5307
+cflags-$(CONFIG_M5271) := $(call cc-option,-mcpu=5271,-m5307)
cflags-$(CONFIG_M5272) := -m5307
-cflags-$(CONFIG_M528x) := -m5307
+cflags-$(CONFIG_M5275) := $(call cc-option,-mcpu=5275,-m5307)
+cflags-$(CONFIG_M528x) := $(call cc-option,-m528x,-m5307)
cflags-$(CONFIG_M5307) := -m5307
-cflags-$(CONFIG_M532x) := -m5307
+cflags-$(CONFIG_M532x) := $(call cc-option,-mcpu=532x,-m5307)
cflags-$(CONFIG_M5407) := -m5200
cflags-$(CONFIG_M68328) := -m68000
cflags-$(CONFIG_M68EZ328) := -m68000
diff --git a/arch/m68knommu/configs/m5208evb_defconfig b/arch/m68knommu/configs/m5208evb_defconfig
new file mode 100644
index 00000000000..6fae33a05e2
--- /dev/null
+++ b/arch/m68knommu/configs/m5208evb_defconfig
@@ -0,0 +1,610 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc1
+#
+CONFIG_M68K=y
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_ZONE_DMA=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_TIME_LOW_RES=y
+CONFIG_NO_IOPORT=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+# CONFIG_HAVE_OPROFILE is not set
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_SLABINFO=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Processor type and features
+#
+# CONFIG_M68328 is not set
+# CONFIG_M68EZ328 is not set
+# CONFIG_M68VZ328 is not set
+# CONFIG_M68360 is not set
+# CONFIG_M5206 is not set
+# CONFIG_M5206e is not set
+CONFIG_M520x=y
+# CONFIG_M523x is not set
+# CONFIG_M5249 is not set
+# CONFIG_M5271 is not set
+# CONFIG_M5272 is not set
+# CONFIG_M5275 is not set
+# CONFIG_M528x is not set
+# CONFIG_M5307 is not set
+# CONFIG_M532x is not set
+# CONFIG_M5407 is not set
+CONFIG_COLDFIRE=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=166666666
+CONFIG_CLOCK_DIV=2
+
+#
+# Platform
+#
+CONFIG_M5208EVB=y
+CONFIG_FREESCALE=y
+# CONFIG_4KSTACKS is not set
+CONFIG_HZ=100
+
+#
+# RAM configuration
+#
+CONFIG_RAMBASE=0x40000000
+CONFIG_RAMSIZE=0x2000000
+CONFIG_VECTORBASE=0x40000000
+CONFIG_KERNELBASE=0x40020000
+# CONFIG_RAMAUTOBIT is not set
+# CONFIG_RAM8BIT is not set
+CONFIG_RAM16BIT=y
+# CONFIG_RAM32BIT is not set
+
+#
+# ROM configuration
+#
+# CONFIG_ROM is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# 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_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+CONFIG_FEC=y
+# CONFIG_FEC2 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_COLDFIRE is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_BAUDRATE=115200
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+# CONFIG_SYSFS is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_FULLDEBUG=y
+# CONFIG_HIGHPROFILE is not set
+# CONFIG_BOOTPARAM is not set
+# CONFIG_NO_KERNEL_MSG is not set
+# CONFIG_BDM_DISABLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
diff --git a/arch/m68knommu/configs/m5249evb_defconfig b/arch/m68knommu/configs/m5249evb_defconfig
new file mode 100644
index 00000000000..cc6458333d6
--- /dev/null
+++ b/arch/m68knommu/configs/m5249evb_defconfig
@@ -0,0 +1,497 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc1
+#
+CONFIG_M68K=y
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_ZONE_DMA=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_TIME_LOW_RES=y
+CONFIG_NO_IOPORT=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+# CONFIG_HAVE_OPROFILE is not set
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_SLABINFO=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Processor type and features
+#
+# CONFIG_M68328 is not set
+# CONFIG_M68EZ328 is not set
+# CONFIG_M68VZ328 is not set
+# CONFIG_M68360 is not set
+# CONFIG_M5206 is not set
+# CONFIG_M5206e is not set
+# CONFIG_M520x is not set
+# CONFIG_M523x is not set
+CONFIG_M5249=y
+# CONFIG_M5271 is not set
+# CONFIG_M5272 is not set
+# CONFIG_M5275 is not set
+# CONFIG_M528x is not set
+# CONFIG_M5307 is not set
+# CONFIG_M532x is not set
+# CONFIG_M5407 is not set
+CONFIG_COLDFIRE=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=140000000
+CONFIG_CLOCK_DIV=2
+
+#
+# Platform
+#
+CONFIG_M5249C3=y
+CONFIG_FREESCALE=y
+CONFIG_4KSTACKS=y
+CONFIG_HZ=100
+
+#
+# RAM configuration
+#
+CONFIG_RAMBASE=0x00000000
+CONFIG_RAMSIZE=0x00800000
+CONFIG_VECTORBASE=0x00000000
+CONFIG_KERNELBASE=0x00020000
+CONFIG_RAMAUTOBIT=y
+# CONFIG_RAM8BIT is not set
+# CONFIG_RAM16BIT is not set
+# CONFIG_RAM32BIT is not set
+
+#
+# ROM configuration
+#
+# CONFIG_ROM is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_MD is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_COLDFIRE is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_BAUDRATE=19200
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_FULLDEBUG is not set
+# CONFIG_HIGHPROFILE is not set
+# CONFIG_BOOTPARAM is not set
+# CONFIG_NO_KERNEL_MSG is not set
+# CONFIG_BDM_DISABLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
diff --git a/arch/m68knommu/configs/m5275evb_defconfig b/arch/m68knommu/configs/m5275evb_defconfig
new file mode 100644
index 00000000000..0d1256f5add
--- /dev/null
+++ b/arch/m68knommu/configs/m5275evb_defconfig
@@ -0,0 +1,627 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc1
+#
+CONFIG_M68K=y
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_ZONE_DMA=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_TIME_LOW_RES=y
+CONFIG_NO_IOPORT=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+# CONFIG_HAVE_OPROFILE is not set
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_SLABINFO=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Processor type and features
+#
+# CONFIG_M68328 is not set
+# CONFIG_M68EZ328 is not set
+# CONFIG_M68VZ328 is not set
+# CONFIG_M68360 is not set
+# CONFIG_M5206 is not set
+# CONFIG_M5206e is not set
+# CONFIG_M520x is not set
+# CONFIG_M523x is not set
+# CONFIG_M5249 is not set
+# CONFIG_M5271 is not set
+# CONFIG_M5272 is not set
+CONFIG_M5275=y
+# CONFIG_M528x is not set
+# CONFIG_M5307 is not set
+# CONFIG_M532x is not set
+# CONFIG_M5407 is not set
+CONFIG_M527x=y
+CONFIG_COLDFIRE=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=150000000
+CONFIG_CLOCK_DIV=2
+
+#
+# Platform
+#
+CONFIG_M5275EVB=y
+CONFIG_FREESCALE=y
+# CONFIG_4KSTACKS is not set
+CONFIG_HZ=100
+
+#
+# RAM configuration
+#
+CONFIG_RAMBASE=0x00000000
+CONFIG_RAMSIZE=0x00000000
+CONFIG_VECTORBASE=0x00000000
+CONFIG_KERNELBASE=0x00020000
+CONFIG_RAMAUTOBIT=y
+# CONFIG_RAM8BIT is not set
+# CONFIG_RAM16BIT is not set
+# CONFIG_RAM32BIT is not set
+
+#
+# ROM configuration
+#
+# CONFIG_ROM is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# 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_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+CONFIG_FEC=y
+CONFIG_FEC2=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_COLDFIRE is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_BAUDRATE=19200
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_FULLDEBUG is not set
+# CONFIG_HIGHPROFILE is not set
+# CONFIG_BOOTPARAM is not set
+# CONFIG_NO_KERNEL_MSG is not set
+# CONFIG_BDM_DISABLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
diff --git a/arch/m68knommu/configs/m5307c3_defconfig b/arch/m68knommu/configs/m5307c3_defconfig
new file mode 100644
index 00000000000..fe2acdfa4d7
--- /dev/null
+++ b/arch/m68knommu/configs/m5307c3_defconfig
@@ -0,0 +1,580 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc1
+#
+CONFIG_M68K=y
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_ZONE_DMA=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_TIME_LOW_RES=y
+CONFIG_NO_IOPORT=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+# CONFIG_HAVE_OPROFILE is not set
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_SLABINFO=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Processor type and features
+#
+# CONFIG_M68328 is not set
+# CONFIG_M68EZ328 is not set
+# CONFIG_M68VZ328 is not set
+# CONFIG_M68360 is not set
+# CONFIG_M5206 is not set
+# CONFIG_M5206e is not set
+# CONFIG_M520x is not set
+# CONFIG_M523x is not set
+# CONFIG_M5249 is not set
+# CONFIG_M5271 is not set
+# CONFIG_M5272 is not set
+# CONFIG_M5275 is not set
+# CONFIG_M528x is not set
+CONFIG_M5307=y
+# CONFIG_M532x is not set
+# CONFIG_M5407 is not set
+CONFIG_COLDFIRE=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=90000000
+CONFIG_CLOCK_DIV=2
+# CONFIG_OLDMASK is not set
+
+#
+# Platform
+#
+# CONFIG_ARN5307 is not set
+CONFIG_M5307C3=y
+# CONFIG_eLIA is not set
+# CONFIG_SECUREEDGEMP3 is not set
+# CONFIG_CLEOPATRA is not set
+# CONFIG_NETtel is not set
+CONFIG_FREESCALE=y
+# CONFIG_4KSTACKS is not set
+CONFIG_HZ=100
+
+#
+# RAM configuration
+#
+CONFIG_RAMBASE=0x00000000
+CONFIG_RAMSIZE=0x00800000
+CONFIG_VECTORBASE=0x00000000
+CONFIG_KERNELBASE=0x00020000
+CONFIG_RAMAUTOBIT=y
+# CONFIG_RAM8BIT is not set
+# CONFIG_RAM16BIT is not set
+# CONFIG_RAM32BIT is not set
+
+#
+# ROM configuration
+#
+# CONFIG_ROM is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_COMEMPCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# 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_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=y
+# CONFIG_SLIP_SMART is not set
+# CONFIG_SLIP_MODE_SLIP6 is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_COLDFIRE is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_BAUDRATE=19200
+CONFIG_SERIAL_MCF_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_FULLDEBUG=y
+# CONFIG_HIGHPROFILE is not set
+# CONFIG_BOOTPARAM is not set
+# CONFIG_NO_KERNEL_MSG is not set
+# CONFIG_BDM_DISABLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
diff --git a/arch/m68knommu/configs/m5407c3_defconfig b/arch/m68knommu/configs/m5407c3_defconfig
new file mode 100644
index 00000000000..1118936d20e
--- /dev/null
+++ b/arch/m68knommu/configs/m5407c3_defconfig
@@ -0,0 +1,641 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc1
+# Wed May 7 10:25:16 2008
+#
+CONFIG_M68K=y
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_ZONE_DMA=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_TIME_LOW_RES=y
+CONFIG_NO_IOPORT=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+# CONFIG_HAVE_OPROFILE is not set
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_SLABINFO=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Processor type and features
+#
+# CONFIG_M68328 is not set
+# CONFIG_M68EZ328 is not set
+# CONFIG_M68VZ328 is not set
+# CONFIG_M68360 is not set
+# CONFIG_M5206 is not set
+# CONFIG_M5206e is not set
+# CONFIG_M520x is not set
+# CONFIG_M523x is not set
+# CONFIG_M5249 is not set
+# CONFIG_M5271 is not set
+# CONFIG_M5272 is not set
+# CONFIG_M5275 is not set
+# CONFIG_M528x is not set
+# CONFIG_M5307 is not set
+# CONFIG_M532x is not set
+CONFIG_M5407=y
+CONFIG_COLDFIRE=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=50000000
+CONFIG_CLOCK_DIV=1
+
+#
+# Platform
+#
+CONFIG_M5407C3=y
+# CONFIG_CLEOPATRA is not set
+CONFIG_FREESCALE=y
+CONFIG_4KSTACKS=y
+CONFIG_HZ=100
+
+#
+# RAM configuration
+#
+CONFIG_RAMBASE=0x00000000
+CONFIG_RAMSIZE=0x00000000
+CONFIG_VECTORBASE=0x00000000
+CONFIG_KERNELBASE=0x00020000
+CONFIG_RAMAUTOBIT=y
+# CONFIG_RAM8BIT is not set
+# CONFIG_RAM16BIT is not set
+# CONFIG_RAM32BIT is not set
+
+#
+# ROM configuration
+#
+# CONFIG_ROM is not set
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_COMEMPCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# 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_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_COLDFIRE is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_BAUDRATE=19200
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_FULLDEBUG is not set
+# CONFIG_HIGHPROFILE is not set
+# CONFIG_BOOTPARAM is not set
+# CONFIG_NO_KERNEL_MSG is not set
+# CONFIG_BDM_DISABLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index 03f4fe6a2fc..5985f198902 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -22,6 +22,7 @@
#include <linux/interrupt.h>
#include <linux/fb.h>
#include <linux/module.h>
+#include <linux/mm.h>
#include <linux/console.h>
#include <linux/errno.h>
#include <linux/string.h>
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
index 0ccfb2ad638..d182b2f7221 100644
--- a/arch/m68knommu/kernel/time.c
+++ b/arch/m68knommu/kernel/time.c
@@ -33,14 +33,13 @@ static inline int set_rtc_mmss(unsigned long nowtime)
return -1;
}
+#ifndef CONFIG_GENERIC_CLOCKEVENTS
/*
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
*/
irqreturn_t arch_timer_interrupt(int irq, void *dummy)
{
- /* last time the cmos clock got updated */
- static long last_rtc_update=0;
if (current->pid)
profile_tick(CPU_PROFILING);
@@ -49,21 +48,6 @@ irqreturn_t arch_timer_interrupt(int irq, void *dummy)
do_timer(1);
- /*
- * If we have an externally synchronized Linux clock, then update
- * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
- * called as close as possible to 500 ms before the new second starts.
- */
- if (ntp_synced() &&
- xtime.tv_sec > last_rtc_update + 660 &&
- (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
- (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
- if (set_rtc_mmss(xtime.tv_sec) == 0)
- last_rtc_update = xtime.tv_sec;
- else
- last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
- }
-
write_sequnlock(&xtime_lock);
#ifndef CONFIG_SMP
@@ -71,8 +55,9 @@ irqreturn_t arch_timer_interrupt(int irq, void *dummy)
#endif
return(IRQ_HANDLED);
}
+#endif
-void time_init(void)
+static unsigned long read_rtc_mmss(void)
{
unsigned int year, mon, day, hour, min, sec;
@@ -83,10 +68,21 @@ void time_init(void)
if ((year += 1900) < 1970)
year += 100;
- xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
- xtime.tv_nsec = 0;
- wall_to_monotonic.tv_sec = -xtime.tv_sec;
- hw_timer_init();
+ return mktime(year, mon, day, hour, min, sec);;
+}
+
+unsigned long read_persistent_clock(void)
+{
+ return read_rtc_mmss();
}
+int update_persistent_clock(struct timespec now)
+{
+ return set_rtc_mmss(now.tv_sec);
+}
+
+void time_init(void)
+{
+ hw_timer_init();
+}
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c
index ec9aea652e7..46f8f9d0c40 100644
--- a/arch/m68knommu/kernel/traps.c
+++ b/arch/m68knommu/kernel/traps.c
@@ -103,12 +103,28 @@ asmlinkage void buserr_c(struct frame *fp)
force_sig(SIGSEGV, current);
}
+static void print_this_address(unsigned long addr, int i)
+{
+#ifdef CONFIG_KALLSYMS
+ printk(KERN_EMERG " [%08lx] ", addr);
+ print_symbol(KERN_CONT "%s\n", addr);
+#else
+ if (i % 5)
+ printk(KERN_CONT " [%08lx] ", addr);
+ else
+ printk(KERN_CONT "\n" KERN_EMERG " [%08lx] ", addr);
+ i++;
+#endif
+}
+
int kstack_depth_to_print = 48;
static void __show_stack(struct task_struct *task, unsigned long *stack)
{
unsigned long *endstack, addr;
+#ifdef CONFIG_FRAME_POINTER
unsigned long *last_stack;
+#endif
int i;
if (!stack)
@@ -126,6 +142,7 @@ static void __show_stack(struct task_struct *task, unsigned long *stack)
printk(" %08lx", *(stack + i));
}
printk("\n");
+ i = 0;
#ifdef CONFIG_FRAME_POINTER
printk(KERN_EMERG "Call Trace:\n");
@@ -134,15 +151,30 @@ static void __show_stack(struct task_struct *task, unsigned long *stack)
while (stack <= endstack && stack > last_stack) {
addr = *(stack + 1);
- printk(KERN_EMERG " [%08lx] ", addr);
- print_symbol(KERN_CONT "%s\n", addr);
+ print_this_address(addr, i);
+ i++;
last_stack = stack;
stack = (unsigned long *)*stack;
}
printk("\n");
#else
- printk(KERN_EMERG "CONFIG_FRAME_POINTER disabled, no symbolic call trace\n");
+ printk(KERN_EMERG "Call Trace with CONFIG_FRAME_POINTER disabled:\n");
+ while (stack <= endstack) {
+ addr = *stack++;
+ /*
+ * If the address is either in the text segment of the kernel,
+ * or in a region which is occupied by a module then it *may*
+ * be the address of a calling routine; if so, print it so that
+ * someone tracing down the cause of the crash will be able to
+ * figure out the call path that was taken.
+ */
+ if (__kernel_text_address(addr)) {
+ print_this_address(addr, i);
+ i++;
+ }
+ }
+ printk(KERN_CONT "\n");
#endif
}
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index 93e69236ed6..69ba9b10767 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -62,6 +62,7 @@ SECTIONS {
.text : {
_text = .;
_stext = . ;
+ HEAD_TEXT
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
diff --git a/arch/m68knommu/platform/coldfire/Makefile b/arch/m68knommu/platform/coldfire/Makefile
index 40cf20be1b9..4f416a91a82 100644
--- a/arch/m68knommu/platform/coldfire/Makefile
+++ b/arch/m68knommu/platform/coldfire/Makefile
@@ -18,7 +18,7 @@ obj-$(CONFIG_COLDFIRE) += dma.o entry.o vectors.o
obj-$(CONFIG_M5206) += timers.o
obj-$(CONFIG_M5206e) += timers.o
obj-$(CONFIG_M520x) += pit.o
-obj-$(CONFIG_M523x) += pit.o
+obj-$(CONFIG_M523x) += pit.o dma_timer.o
obj-$(CONFIG_M5249) += timers.o
obj-$(CONFIG_M527x) += pit.o
obj-$(CONFIG_M5272) += timers.o
diff --git a/arch/m68knommu/platform/coldfire/dma_timer.c b/arch/m68knommu/platform/coldfire/dma_timer.c
new file mode 100644
index 00000000000..772578b1084
--- /dev/null
+++ b/arch/m68knommu/platform/coldfire/dma_timer.c
@@ -0,0 +1,84 @@
+/*
+ * dma_timer.c -- Freescale ColdFire DMA Timer.
+ *
+ * Copyright (C) 2007, Benedikt Spranger <b.spranger@linutronix.de>
+ * Copyright (C) 2008. Sebastian Siewior, Linutronix
+ *
+ */
+
+#include <linux/clocksource.h>
+#include <linux/io.h>
+
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfpit.h>
+#include <asm/mcfsim.h>
+
+#define DMA_TIMER_0 (0x00)
+#define DMA_TIMER_1 (0x40)
+#define DMA_TIMER_2 (0x80)
+#define DMA_TIMER_3 (0xc0)
+
+#define DTMR0 (MCF_IPSBAR + DMA_TIMER_0 + 0x400)
+#define DTXMR0 (MCF_IPSBAR + DMA_TIMER_0 + 0x402)
+#define DTER0 (MCF_IPSBAR + DMA_TIMER_0 + 0x403)
+#define DTRR0 (MCF_IPSBAR + DMA_TIMER_0 + 0x404)
+#define DTCR0 (MCF_IPSBAR + DMA_TIMER_0 + 0x408)
+#define DTCN0 (MCF_IPSBAR + DMA_TIMER_0 + 0x40c)
+
+#define DMA_FREQ ((MCF_CLK / 2) / 16)
+
+/* DTMR */
+#define DMA_DTMR_RESTART (1 << 3)
+#define DMA_DTMR_CLK_DIV_1 (1 << 1)
+#define DMA_DTMR_CLK_DIV_16 (2 << 1)
+#define DMA_DTMR_ENABLE (1 << 0)
+
+static cycle_t cf_dt_get_cycles(void)
+{
+ return __raw_readl(DTCN0);
+}
+
+static struct clocksource clocksource_cf_dt = {
+ .name = "coldfire_dma_timer",
+ .rating = 200,
+ .read = cf_dt_get_cycles,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 20,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init init_cf_dt_clocksource(void)
+{
+ /*
+ * We setup DMA timer 0 in free run mode. This incrementing counter is
+ * used as a highly precious clock source. With MCF_CLOCK = 150 MHz we
+ * get a ~213 ns resolution and the 32bit register will overflow almost
+ * every 15 minutes.
+ */
+ __raw_writeb(0x00, DTXMR0);
+ __raw_writeb(0x00, DTER0);
+ __raw_writel(0x00000000, DTRR0);
+ __raw_writew(DMA_DTMR_CLK_DIV_16 | DMA_DTMR_ENABLE, DTMR0);
+ clocksource_cf_dt.mult = clocksource_hz2mult(DMA_FREQ,
+ clocksource_cf_dt.shift);
+ return clocksource_register(&clocksource_cf_dt);
+}
+
+arch_initcall(init_cf_dt_clocksource);
+
+#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
+#define CYC2NS_SCALE ((1000000 << CYC2NS_SCALE_FACTOR) / (DMA_FREQ / 1000))
+
+static unsigned long long cycles2ns(unsigned long cycl)
+{
+ return (unsigned long long) ((unsigned long long)cycl *
+ CYC2NS_SCALE) >> CYC2NS_SCALE_FACTOR;
+}
+
+unsigned long long sched_clock(void)
+{
+ unsigned long cycl = __raw_readl(DTCN0);
+
+ return cycles2ns(cycl);
+}
diff --git a/arch/m68knommu/platform/coldfire/head.S b/arch/m68knommu/platform/coldfire/head.S
index b9aa0ca29bf..2b0d73c0cc3 100644
--- a/arch/m68knommu/platform/coldfire/head.S
+++ b/arch/m68knommu/platform/coldfire/head.S
@@ -10,6 +10,7 @@
#include <linux/sys.h>
#include <linux/linkage.h>
+#include <linux/init.h>
#include <asm/asm-offsets.h>
#include <asm/coldfire.h>
#include <asm/mcfcache.h>
@@ -126,7 +127,7 @@ _ramend:
/*****************************************************************************/
-.text
+__HEAD
/*
* This is the codes first entry point. This is where it all
diff --git a/arch/m68knommu/platform/coldfire/pit.c b/arch/m68knommu/platform/coldfire/pit.c
index 4290638012e..c5b916700b2 100644
--- a/arch/m68knommu/platform/coldfire/pit.c
+++ b/arch/m68knommu/platform/coldfire/pit.c
@@ -18,7 +18,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/clocksource.h>
+#include <linux/clockchips.h>
#include <asm/machdep.h>
#include <asm/io.h>
#include <asm/coldfire.h>
@@ -33,22 +33,86 @@
#define FREQ ((MCF_CLK / 2) / 64)
#define TA(a) (MCF_IPSBAR + MCFPIT_BASE1 + (a))
#define INTC0 (MCF_IPSBAR + MCFICM_INTC0)
+#define PIT_CYCLES_PER_JIFFY (FREQ / HZ)
-static u32 pit_cycles_per_jiffy;
static u32 pit_cnt;
+/*
+ * Initialize the PIT timer.
+ *
+ * This is also called after resume to bring the PIT into operation again.
+ */
+
+static void init_cf_pit_timer(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+
+ __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
+ __raw_writew(PIT_CYCLES_PER_JIFFY, TA(MCFPIT_PMR));
+ __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | \
+ MCFPIT_PCSR_OVW | MCFPIT_PCSR_RLD | \
+ MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR));
+ break;
+
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_UNUSED:
+
+ __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
+ break;
+
+ case CLOCK_EVT_MODE_ONESHOT:
+
+ __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
+ __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | \
+ MCFPIT_PCSR_OVW | MCFPIT_PCSR_CLK64, \
+ TA(MCFPIT_PCSR));
+ break;
+
+ case CLOCK_EVT_MODE_RESUME:
+ /* Nothing to do here */
+ break;
+ }
+}
+
+/*
+ * Program the next event in oneshot mode
+ *
+ * Delta is given in PIT ticks
+ */
+static int cf_pit_next_event(unsigned long delta,
+ struct clock_event_device *evt)
+{
+ __raw_writew(delta, TA(MCFPIT_PMR));
+ return 0;
+}
+
+struct clock_event_device cf_pit_clockevent = {
+ .name = "pit",
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_mode = init_cf_pit_timer,
+ .set_next_event = cf_pit_next_event,
+ .shift = 32,
+ .irq = MCFINT_VECBASE + MCFINT_PIT1,
+};
+
+
+
/***************************************************************************/
static irqreturn_t pit_tick(int irq, void *dummy)
{
+ struct clock_event_device *evt = &cf_pit_clockevent;
u16 pcsr;
/* Reset the ColdFire timer */
pcsr = __raw_readw(TA(MCFPIT_PCSR));
__raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR));
- pit_cnt += pit_cycles_per_jiffy;
- return arch_timer_interrupt(irq, dummy);
+ pit_cnt += PIT_CYCLES_PER_JIFFY;
+ evt->event_handler(evt);
+ return IRQ_HANDLED;
}
/***************************************************************************/
@@ -72,14 +136,14 @@ static cycle_t pit_read_clk(void)
cycles = pit_cnt;
local_irq_restore(flags);
- return cycles + pit_cycles_per_jiffy - pcntr;
+ return cycles + PIT_CYCLES_PER_JIFFY - pcntr;
}
/***************************************************************************/
static struct clocksource pit_clk = {
.name = "pit",
- .rating = 250,
+ .rating = 100,
.read = pit_read_clk,
.shift = 20,
.mask = CLOCKSOURCE_MASK(32),
@@ -92,6 +156,14 @@ void hw_timer_init(void)
{
u32 imr;
+ cf_pit_clockevent.cpumask = cpumask_of_cpu(smp_processor_id());
+ cf_pit_clockevent.mult = div_sc(FREQ, NSEC_PER_SEC, 32);
+ cf_pit_clockevent.max_delta_ns =
+ clockevent_delta2ns(0xFFFF, &cf_pit_clockevent);
+ cf_pit_clockevent.min_delta_ns =
+ clockevent_delta2ns(0x3f, &cf_pit_clockevent);
+ clockevents_register_device(&cf_pit_clockevent);
+
setup_irq(MCFINT_VECBASE + MCFINT_PIT1, &pit_irq);
__raw_writeb(ICR_INTRCONF, INTC0 + MCFINTC_ICR0 + MCFINT_PIT1);
@@ -99,13 +171,6 @@ void hw_timer_init(void)
imr &= ~MCFPIT_IMR_IBIT;
__raw_writel(imr, INTC0 + MCFPIT_IMR);
- /* Set up PIT timer 1 as poll clock */
- pit_cycles_per_jiffy = FREQ / HZ;
- __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
- __raw_writew(pit_cycles_per_jiffy, TA(MCFPIT_PMR));
- __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW |
- MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR));
-
pit_clk.mult = clocksource_hz2mult(FREQ, pit_clk.shift);
clocksource_register(&pit_clk);
}
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index b9c754f4070..b4c4eaa5dd2 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -713,7 +713,7 @@ config CSRC_SB1250
config GPIO_TXX9
select GENERIC_GPIO
- select HAVE_GPIO_LIB
+ select ARCH_REQUIRE_GPIOLIB
bool
config CFE
diff --git a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c
index 2166b9e1e80..bd854a6d1d8 100644
--- a/arch/mips/au1000/common/power.c
+++ b/arch/mips/au1000/common/power.c
@@ -31,7 +31,6 @@
#include <linux/init.h>
#include <linux/pm.h>
-#include <linux/pm_legacy.h>
#include <linux/sysctl.h>
#include <linux/jiffies.h>
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index c266211ed65..2fefb14414b 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -11,7 +11,6 @@
#include <linux/file.h>
#include <linux/smp_lock.h>
#include <linux/highuid.h>
-#include <linux/dirent.h>
#include <linux/resource.h>
#include <linux/highmem.h>
#include <linux/time.h>
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index e7ed0ac4853..1f60e27523d 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -22,6 +22,7 @@
#include <linux/moduleloader.h>
#include <linux/elf.h>
+#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/fs.h>
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index c06f5b5d764..b16facd9ea8 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -53,7 +53,7 @@ void __noreturn cpu_idle(void)
{
/* endless idle loop with no priority at all */
while (1) {
- tick_nohz_stop_sched_tick();
+ tick_nohz_stop_sched_tick(1);
while (!need_resched()) {
#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
extern void smtc_idle_loop_hook(void);
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index b5564196123..dfd868b6836 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -522,8 +522,8 @@ static int __init rtlx_module_init(void)
atomic_set(&channel_wqs[i].in_open, 0);
mutex_init(&channel_wqs[i].mutex);
- dev = device_create(mt_class, NULL, MKDEV(major, i),
- "%s%d", module_name, i);
+ dev = device_create_drvdata(mt_class, NULL, MKDEV(major, i),
+ NULL, "%s%d", module_name, i);
if (IS_ERR(dev)) {
err = PTR_ERR(dev);
goto out_chrdev;
diff --git a/arch/mips/kernel/stacktrace.c b/arch/mips/kernel/stacktrace.c
index 5eb4681a73d..0632e2a849c 100644
--- a/arch/mips/kernel/stacktrace.c
+++ b/arch/mips/kernel/stacktrace.c
@@ -7,6 +7,7 @@
*/
#include <linux/sched.h>
#include <linux/stacktrace.h>
+#include <linux/module.h>
#include <asm/stacktrace.h>
/*
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 3523c8d12ed..343015a2f41 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -52,7 +52,7 @@ asmlinkage int sysm_pipe(nabi_no_regargs volatile struct pt_regs regs)
int fd[2];
int error, res;
- error = do_pipe(fd);
+ error = do_pipe_flags(fd, 0);
if (error) {
res = error;
goto out;
diff --git a/arch/mips/sgi-ip27/ip27-klnuma.c b/arch/mips/sgi-ip27/ip27-klnuma.c
index 48932ce1d73..d9c79d8be81 100644
--- a/arch/mips/sgi-ip27/ip27-klnuma.c
+++ b/arch/mips/sgi-ip27/ip27-klnuma.c
@@ -4,6 +4,7 @@
* Copyright 2000 - 2001 Kanoj Sarcar (kanoj@sgi.com)
*/
#include <linux/init.h>
+#include <linux/mm.h>
#include <linux/mmzone.h>
#include <linux/kernel.h>
#include <linux/nodemask.h>
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
index 42cd1095630..060d853d7b3 100644
--- a/arch/mips/sgi-ip27/ip27-memory.c
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -33,8 +33,6 @@
#define SLOT_PFNSHIFT (SLOT_SHIFT - PAGE_SHIFT)
#define PFN_NASIDSHFT (NASID_SHFT - PAGE_SHIFT)
-static struct bootmem_data __initdata plat_node_bdata[MAX_COMPACT_NODES];
-
struct node_data *__node_data[MAX_COMPACT_NODES];
EXPORT_SYMBOL(__node_data);
@@ -403,7 +401,7 @@ static void __init node_mem_init(cnodeid_t node)
*/
__node_data[node] = __va(slot_freepfn << PAGE_SHIFT);
- NODE_DATA(node)->bdata = &plat_node_bdata[node];
+ NODE_DATA(node)->bdata = &bootmem_node_data[node];
NODE_DATA(node)->node_start_pfn = start_pfn;
NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn;
diff --git a/arch/mips/sibyte/common/sb_tbprof.c b/arch/mips/sibyte/common/sb_tbprof.c
index 28b012ab8dc..66e3e3fb311 100644
--- a/arch/mips/sibyte/common/sb_tbprof.c
+++ b/arch/mips/sibyte/common/sb_tbprof.c
@@ -576,7 +576,8 @@ static int __init sbprof_tb_init(void)
tb_class = tbc;
- dev = device_create(tbc, NULL, MKDEV(SBPROF_TB_MAJOR, 0), "tb");
+ dev = device_create_drvdata(tbc, NULL, MKDEV(SBPROF_TB_MAJOR, 0),
+ NULL, "tb");
if (IS_ERR(dev)) {
err = PTR_ERR(dev);
goto out_class;
diff --git a/arch/mn10300/boot/compressed/misc.c b/arch/mn10300/boot/compressed/misc.c
index ded207efc97..f673383518e 100644
--- a/arch/mn10300/boot/compressed/misc.c
+++ b/arch/mn10300/boot/compressed/misc.c
@@ -153,26 +153,9 @@ static uch *output_data;
static unsigned long output_ptr;
-static void *malloc(int size);
-
-static inline void free(void *where)
-{ /* Don't care */
-}
-
static unsigned long free_mem_ptr = (unsigned long) &end;
static unsigned long free_mem_end_ptr = (unsigned long) &end + 0x90000;
-static inline void gzip_mark(void **ptr)
-{
- kputs(".");
- *ptr = (void *) free_mem_ptr;
-}
-
-static inline void gzip_release(void **ptr)
-{
- free_mem_ptr = (unsigned long) *ptr;
-}
-
#define INPLACE_MOVE_ROUTINE 0x1000
#define LOW_BUFFER_START 0x2000
#define LOW_BUFFER_END 0x90000
@@ -186,26 +169,6 @@ static int lines, cols;
#include "../../../../lib/inflate.c"
-static void *malloc(int size)
-{
- void *p;
-
- if (size < 0)
- error("Malloc error\n");
- if (!free_mem_ptr)
- error("Memory error\n");
-
- free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
- p = (void *) free_mem_ptr;
- free_mem_ptr += size;
-
- if (free_mem_ptr >= free_mem_end_ptr)
- error("\nOut of memory\n");
-
- return p;
-}
-
static inline void scroll(void)
{
int i;
diff --git a/arch/mn10300/mm/init.c b/arch/mn10300/mm/init.c
index 8c5d88c7b90..8cee387a24f 100644
--- a/arch/mn10300/mm/init.c
+++ b/arch/mn10300/mm/init.c
@@ -67,8 +67,8 @@ void __init paging_init(void)
/* declare the sizes of the RAM zones (only use the normal zone) */
zones_size[ZONE_NORMAL] =
- (contig_page_data.bdata->node_low_pfn) -
- (contig_page_data.bdata->node_boot_start >> PAGE_SHIFT);
+ contig_page_data.bdata->node_low_pfn -
+ contig_page_data.bdata->node_min_pfn;
/* pass the memory from the bootmem allocator to the main allocator */
free_area_init(zones_size);
@@ -87,7 +87,7 @@ void __init mem_init(void)
if (!mem_map)
BUG();
-#define START_PFN (contig_page_data.bdata->node_boot_start >> PAGE_SHIFT)
+#define START_PFN (contig_page_data.bdata->node_min_pfn)
#define MAX_LOW_PFN (contig_page_data.bdata->node_low_pfn)
max_mapnr = num_physpages = MAX_LOW_PFN - START_PFN;
diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
index 0c5b9dabb47..be255ebb609 100644
--- a/arch/parisc/hpux/sys_hpux.c
+++ b/arch/parisc/hpux/sys_hpux.c
@@ -448,7 +448,7 @@ int hpux_pipe(int *kstack_fildes)
int error;
lock_kernel();
- error = do_pipe(kstack_fildes);
+ error = do_pipe_flags(kstack_fildes, 0);
unlock_kernel();
return error;
}
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index b4d6c8777ed..7c155c254e7 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -36,7 +36,6 @@ extern int data_start;
#ifdef CONFIG_DISCONTIGMEM
struct node_map_data node_data[MAX_NUMNODES] __read_mostly;
-bootmem_data_t bmem_data[MAX_NUMNODES] __read_mostly;
unsigned char pfnnid_map[PFNNID_MAP_MAX] __read_mostly;
#endif
@@ -262,7 +261,7 @@ static void __init setup_bootmem(void)
#ifdef CONFIG_DISCONTIGMEM
for (i = 0; i < MAX_PHYSMEM_RANGES; i++) {
memset(NODE_DATA(i), 0, sizeof(pg_data_t));
- NODE_DATA(i)->bdata = &bmem_data[i];
+ NODE_DATA(i)->bdata = &bootmem_node_data[i];
}
memset(pfnnid_map, 0xff, sizeof(pfnnid_map));
@@ -888,7 +887,7 @@ void __init paging_init(void)
}
#endif
- free_area_init_node(i, NODE_DATA(i), zones_size,
+ free_area_init_node(i, zones_size,
pmem_ranges[i].start_pfn, NULL);
}
}
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index de88972c589..fe88418167c 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -110,8 +110,12 @@ config PPC
default y
select HAVE_DYNAMIC_FTRACE
select HAVE_FTRACE
+ select ARCH_WANT_OPTIONAL_GPIOLIB
select HAVE_IDE
+ select HAVE_IOREMAP_PROT
+ select HAVE_EFFICIENT_UNALIGNED_ACCESS
select HAVE_KPROBES
+ select HAVE_ARCH_KGDB
select HAVE_KRETPROBES
select HAVE_LMB
select HAVE_DMA_ATTRS if PPC64
@@ -199,7 +203,7 @@ config ARCH_HIBERNATION_POSSIBLE
config ARCH_SUSPEND_POSSIBLE
def_bool y
- depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200
+ depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx
config PPC_DCR_NATIVE
bool
@@ -568,11 +572,15 @@ config FSL_GTM
config MCA
bool
+# Platforms that what PCI turned unconditionally just do select PCI
+# in their config node. Platforms that want to choose at config
+# time should select PPC_PCI_CHOICE
+config PPC_PCI_CHOICE
+ bool
+
config PCI
- bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
- || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \
- || PPC_PS3 || 44x
- default y if !40x && !CPM2 && !8xx && !PPC_MPC512x && !PPC_83xx \
+ bool "PCI support" if PPC_PCI_CHOICE
+ default y if !40x && !CPM2 && !8xx && !PPC_83xx \
&& !PPC_85xx && !PPC_86xx
default PCI_PERMEDIA if !4xx && !CPM2 && !8xx
default PCI_QSPAN if !4xx && !CPM2 && 8xx
@@ -838,6 +846,7 @@ source "crypto/Kconfig"
config PPC_CLOCK
bool
default n
+ select HAVE_CLK
config PPC_LIB_RHEAP
bool
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 2840ab69ef4..8c8aadbe956 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -41,22 +41,6 @@ config HCALL_STATS
This option will add a small amount of overhead to all hypervisor
calls.
-config DEBUGGER
- bool "Enable debugger hooks"
- depends on DEBUG_KERNEL
- help
- Include in-kernel hooks for kernel debuggers. Unless you are
- intending to debug the kernel, say N here.
-
-config KGDB
- bool "Include kgdb kernel debugger"
- depends on DEBUGGER && (BROKEN || PPC_GEN550 || 4xx)
- select DEBUG_INFO
- help
- Include in-kernel hooks for kgdb, the Linux kernel source level
- debugger. See <http://kgdb.sourceforge.net/> for more information.
- Unless you are intending to debug the kernel, say N here.
-
config CODE_PATCHING_SELFTEST
bool "Run self-tests of the code-patching code."
depends on DEBUG_KERNEL
@@ -67,36 +51,9 @@ config FTR_FIXUP_SELFTEST
depends on DEBUG_KERNEL
default n
-choice
- prompt "Serial Port"
- depends on KGDB
- default KGDB_TTYS1
-
-config KGDB_TTYS0
- bool "ttyS0"
-
-config KGDB_TTYS1
- bool "ttyS1"
-
-config KGDB_TTYS2
- bool "ttyS2"
-
-config KGDB_TTYS3
- bool "ttyS3"
-
-endchoice
-
-config KGDB_CONSOLE
- bool "Enable serial console thru kgdb port"
- depends on KGDB && 8xx || CPM2
- help
- If you enable this, all serial console messages will be sent
- over the gdb stub.
- If unsure, say N.
-
config XMON
bool "Include xmon kernel debugger"
- depends on DEBUGGER
+ depends on DEBUG_KERNEL
help
Include in-kernel hooks for the xmon kernel monitor/debugger.
Unless you are intending to debug the kernel, say N here.
@@ -126,6 +83,11 @@ config XMON_DISASSEMBLY
to say Y here, unless you're building for a memory-constrained
system.
+config DEBUGGER
+ bool
+ depends on KGDB || XMON
+ default y
+
config IRQSTACKS
bool "Use separate kernel stacks when processing interrupts"
help
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 19f83c8f219..14174aa2407 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -163,12 +163,12 @@ quiet_cmd_flex = FLEX $@
cmd_flex = $(FLEX) -o$@ $<; cp $@ $@_shipped
$(obj)/dtc-src/dtc-parser.tab.c: $(src)/dtc-src/dtc-parser.y FORCE
- $(call if_changed,bison)
+ $(call if_changed,bison)
$(obj)/dtc-src/dtc-parser.tab.h: $(obj)/dtc-src/dtc-parser.tab.c
$(obj)/dtc-src/dtc-lexer.lex.c: $(src)/dtc-src/dtc-lexer.l FORCE
- $(call if_changed,flex)
+ $(call if_changed,flex)
endif
#############
diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
index 705c23c14f3..2544f3ecd6e 100644
--- a/arch/powerpc/boot/dts/mpc7448hpc2.dts
+++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
@@ -18,6 +18,16 @@
#address-cells = <1>;
#size-cells = <1>;
+ aliases {
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+
+ serial0 = &serial0;
+ serial1 = &serial1;
+
+ pci0 = &pci0;
+ };
+
cpus {
#address-cells = <1>;
#size-cells =<0>;
@@ -78,7 +88,7 @@
};
- ethernet@6200 {
+ enet0: ethernet@6200 {
linux,network-index = <0>;
#size-cells = <0>;
device_type = "network";
@@ -91,7 +101,7 @@
phy-handle = <&phy8>;
};
- ethernet@6600 {
+ enet1: ethernet@6600 {
linux,network-index = <1>;
#address-cells = <1>;
#size-cells = <0>;
@@ -105,7 +115,7 @@
phy-handle = <&phy9>;
};
- serial@7808 {
+ serial0: serial@7808 {
device_type = "serial";
compatible = "ns16550";
reg = <0x7808 0x200>;
@@ -114,7 +124,7 @@
interrupt-parent = <&mpic>;
};
- serial@7c08 {
+ serial1: serial@7c08 {
device_type = "serial";
compatible = "ns16550";
reg = <0x7c08 0x200>;
@@ -131,7 +141,7 @@
compatible = "chrp,open-pic";
device_type = "open-pic";
};
- pci@1000 {
+ pci0: pci@1000 {
compatible = "tsi108-pci";
device_type = "pci";
#interrupt-cells = <1>;
@@ -184,8 +194,4 @@
};
};
};
- chosen {
- linux,stdout-path = "/tsi108@c0000000/serial@7808";
- };
-
};
diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts
index 3664fb58402..2a94ae0dc8b 100644
--- a/arch/powerpc/boot/dts/mpc8313erdb.dts
+++ b/arch/powerpc/boot/dts/mpc8313erdb.dts
@@ -109,18 +109,38 @@
reg = <0x200 0x100>;
};
- i2c@3000 {
+ sleep-nexus {
#address-cells = <1>;
- #size-cells = <0>;
- cell-index = <0>;
- compatible = "fsl-i2c";
- reg = <0x3000 0x100>;
- interrupts = <14 0x8>;
- interrupt-parent = <&ipic>;
- dfsrr;
- rtc@68 {
- compatible = "dallas,ds1339";
- reg = <0x68>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ sleep = <&pmc 0x03000000>;
+ ranges;
+
+ i2c@3000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x3000 0x100>;
+ interrupts = <14 0x8>;
+ interrupt-parent = <&ipic>;
+ dfsrr;
+ rtc@68 {
+ compatible = "dallas,ds1339";
+ reg = <0x68>;
+ };
+ };
+
+ crypto@30000 {
+ compatible = "fsl,sec2.2", "fsl,sec2.1",
+ "fsl,sec2.0";
+ reg = <0x30000 0x10000>;
+ interrupts = <11 0x8>;
+ interrupt-parent = <&ipic>;
+ fsl,num-channels = <1>;
+ fsl,channel-fifo-len = <24>;
+ fsl,exec-units-mask = <0x4c>;
+ fsl,descriptor-types-mask = <0x0122003f>;
};
};
@@ -188,37 +208,44 @@
interrupt-parent = <&ipic>;
interrupts = <38 0x8>;
phy_type = "utmi_wide";
+ sleep = <&pmc 0x00300000>;
};
- mdio@24520 {
+ enet0: ethernet@24000 {
#address-cells = <1>;
- #size-cells = <0>;
- compatible = "fsl,gianfar-mdio";
- reg = <0x24520 0x20>;
- phy1: ethernet-phy@1 {
- interrupt-parent = <&ipic>;
- interrupts = <19 0x8>;
- reg = <0x1>;
- device_type = "ethernet-phy";
- };
- phy4: ethernet-phy@4 {
- interrupt-parent = <&ipic>;
- interrupts = <20 0x8>;
- reg = <0x4>;
- device_type = "ethernet-phy";
- };
- };
+ #size-cells = <1>;
+ sleep = <&pmc 0x20000000>;
+ ranges;
- enet0: ethernet@24000 {
cell-index = <0>;
device_type = "network";
model = "eTSEC";
- compatible = "gianfar";
+ compatible = "gianfar", "simple-bus";
reg = <0x24000 0x1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <37 0x8 36 0x8 35 0x8>;
interrupt-parent = <&ipic>;
phy-handle = < &phy1 >;
+ fsl,magic-packet;
+
+ mdio@24520 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-mdio";
+ reg = <0x24520 0x20>;
+ phy1: ethernet-phy@1 {
+ interrupt-parent = <&ipic>;
+ interrupts = <19 0x8>;
+ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ phy4: ethernet-phy@4 {
+ interrupt-parent = <&ipic>;
+ interrupts = <20 0x8>;
+ reg = <0x4>;
+ device_type = "ethernet-phy";
+ };
+ };
};
enet1: ethernet@25000 {
@@ -231,6 +258,8 @@
interrupts = <34 0x8 33 0x8 32 0x8>;
interrupt-parent = <&ipic>;
phy-handle = < &phy4 >;
+ sleep = <&pmc 0x10000000>;
+ fsl,magic-packet;
};
serial0: serial@4500 {
@@ -253,17 +282,6 @@
interrupt-parent = <&ipic>;
};
- crypto@30000 {
- compatible = "fsl,sec2.2", "fsl,sec2.1", "fsl,sec2.0";
- reg = <0x30000 0x10000>;
- interrupts = <11 0x8>;
- interrupt-parent = <&ipic>;
- fsl,num-channels = <1>;
- fsl,channel-fifo-len = <24>;
- fsl,exec-units-mask = <0x4c>;
- fsl,descriptor-types-mask = <0x0122003f>;
- };
-
/* IPIC
* interrupts cell = <intr #, sense>
* sense values match linux IORESOURCE_IRQ_* defines:
@@ -277,36 +295,119 @@
reg = <0x700 0x100>;
device_type = "ipic";
};
+
+ pmc: power@b00 {
+ compatible = "fsl,mpc8313-pmc", "fsl,mpc8349-pmc";
+ reg = <0xb00 0x100 0xa00 0x100>;
+ interrupts = <80 8>;
+ interrupt-parent = <&ipic>;
+ fsl,mpc8313-wakeup-timer = <&gtm1>;
+
+ /* Remove this (or change to "okay") if you have
+ * a REVA3 or later board, if you apply one of the
+ * workarounds listed in section 8.5 of the board
+ * manual, or if you are adapting this device tree
+ * to a different board.
+ */
+ status = "fail";
+ };
+
+ gtm1: timer@500 {
+ compatible = "fsl,mpc8313-gtm", "fsl,gtm";
+ reg = <0x500 0x100>;
+ interrupts = <90 8 78 8 84 8 72 8>;
+ interrupt-parent = <&ipic>;
+ };
+
+ timer@600 {
+ compatible = "fsl,mpc8313-gtm", "fsl,gtm";
+ reg = <0x600 0x100>;
+ interrupts = <91 8 79 8 85 8 73 8>;
+ interrupt-parent = <&ipic>;
+ };
};
- pci0: pci@e0008500 {
- cell-index = <1>;
- interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
- interrupt-map = <
-
- /* IDSEL 0x0E -mini PCI */
- 0x7000 0x0 0x0 0x1 &ipic 18 0x8
- 0x7000 0x0 0x0 0x2 &ipic 18 0x8
- 0x7000 0x0 0x0 0x3 &ipic 18 0x8
- 0x7000 0x0 0x0 0x4 &ipic 18 0x8
-
- /* IDSEL 0x0F - PCI slot */
- 0x7800 0x0 0x0 0x1 &ipic 17 0x8
- 0x7800 0x0 0x0 0x2 &ipic 18 0x8
- 0x7800 0x0 0x0 0x3 &ipic 17 0x8
- 0x7800 0x0 0x0 0x4 &ipic 18 0x8>;
- interrupt-parent = <&ipic>;
- interrupts = <66 0x8>;
- bus-range = <0x0 0x0>;
- ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
- 0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
- 0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
- clock-frequency = <66666666>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
- reg = <0xe0008500 0x100>;
- compatible = "fsl,mpc8349-pci";
- device_type = "pci";
+ sleep-nexus {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ sleep = <&pmc 0x00010000>;
+ ranges;
+
+ pci0: pci@e0008500 {
+ cell-index = <1>;
+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0E -mini PCI */
+ 0x7000 0x0 0x0 0x1 &ipic 18 0x8
+ 0x7000 0x0 0x0 0x2 &ipic 18 0x8
+ 0x7000 0x0 0x0 0x3 &ipic 18 0x8
+ 0x7000 0x0 0x0 0x4 &ipic 18 0x8
+
+ /* IDSEL 0x0F - PCI slot */
+ 0x7800 0x0 0x0 0x1 &ipic 17 0x8
+ 0x7800 0x0 0x0 0x2 &ipic 18 0x8
+ 0x7800 0x0 0x0 0x3 &ipic 17 0x8
+ 0x7800 0x0 0x0 0x4 &ipic 18 0x8>;
+ interrupt-parent = <&ipic>;
+ interrupts = <66 0x8>;
+ bus-range = <0x0 0x0>;
+ ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
+ 0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
+ 0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
+ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <0xe0008500 0x100>;
+ compatible = "fsl,mpc8349-pci";
+ device_type = "pci";
+ };
+
+ dma@82a8 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8313-dma", "fsl,elo-dma";
+ reg = <0xe00082a8 4>;
+ ranges = <0 0xe0008100 0x1a8>;
+ interrupt-parent = <&ipic>;
+ interrupts = <71 8>;
+
+ dma-channel@0 {
+ compatible = "fsl,mpc8313-dma-channel",
+ "fsl,elo-dma-channel";
+ reg = <0 0x28>;
+ interrupt-parent = <&ipic>;
+ interrupts = <71 8>;
+ cell-index = <0>;
+ };
+
+ dma-channel@80 {
+ compatible = "fsl,mpc8313-dma-channel",
+ "fsl,elo-dma-channel";
+ reg = <0x80 0x28>;
+ interrupt-parent = <&ipic>;
+ interrupts = <71 8>;
+ cell-index = <1>;
+ };
+
+ dma-channel@100 {
+ compatible = "fsl,mpc8313-dma-channel",
+ "fsl,elo-dma-channel";
+ reg = <0x100 0x28>;
+ interrupt-parent = <&ipic>;
+ interrupts = <71 8>;
+ cell-index = <2>;
+ };
+
+ dma-channel@180 {
+ compatible = "fsl,mpc8313-dma-channel",
+ "fsl,elo-dma-channel";
+ reg = <0x180 0x28>;
+ interrupt-parent = <&ipic>;
+ interrupts = <71 8>;
+ cell-index = <3>;
+ };
+ };
};
};
diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts
index 981941e5d7a..666185f5945 100644
--- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts
+++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts
@@ -388,6 +388,20 @@
0x01000000 0x0 0x00000000
0x01000000 0x0 0x00000000
0x0 0x00100000>;
+
+ isa@1e {
+ device_type = "isa";
+ #size-cells = <1>;
+ #address-cells = <2>;
+ reg = <0xf000 0 0 0 0>;
+ ranges = <1 0 0x01000000 0 0
+ 0x00001000>;
+
+ rtc@70 {
+ compatible = "pnpPNP,b00";
+ reg = <1 0x70 2>;
+ };
+ };
};
};
};
diff --git a/arch/powerpc/configs/85xx/mpc8544_ds_defconfig b/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
index 042a85ea7b7..a0583e5119f 100644
--- a/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
+++ b/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
@@ -997,10 +997,12 @@ CONFIG_SND=y
CONFIG_SND_TIMER=y
CONFIG_SND_PCM=y
# CONFIG_SND_SEQUENCER is not set
-# CONFIG_SND_MIXER_OSS is not set
-# CONFIG_SND_PCM_OSS is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
# CONFIG_SND_DYNAMIC_MINORS is not set
-CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
diff --git a/arch/powerpc/configs/85xx/mpc8572_ds_defconfig b/arch/powerpc/configs/85xx/mpc8572_ds_defconfig
index 03627cfebcb..164fd9606ee 100644
--- a/arch/powerpc/configs/85xx/mpc8572_ds_defconfig
+++ b/arch/powerpc/configs/85xx/mpc8572_ds_defconfig
@@ -997,10 +997,12 @@ CONFIG_SND=y
CONFIG_SND_TIMER=y
CONFIG_SND_PCM=y
# CONFIG_SND_SEQUENCER is not set
-# CONFIG_SND_MIXER_OSS is not set
-# CONFIG_SND_PCM_OSS is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
# CONFIG_SND_DYNAMIC_MINORS is not set
-CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index 3efab71a603..fa0170504b8 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -1005,10 +1005,12 @@ CONFIG_SND=y
CONFIG_SND_TIMER=y
CONFIG_SND_PCM=y
# CONFIG_SND_SEQUENCER is not set
-# CONFIG_SND_MIXER_OSS is not set
-# CONFIG_SND_PCM_OSS is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
# CONFIG_SND_DYNAMIC_MINORS is not set
-CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
diff --git a/arch/powerpc/configs/mpc8610_hpcd_defconfig b/arch/powerpc/configs/mpc8610_hpcd_defconfig
index 5612d40d046..cdf98ae3682 100644
--- a/arch/powerpc/configs/mpc8610_hpcd_defconfig
+++ b/arch/powerpc/configs/mpc8610_hpcd_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc5
-# Mon Jun 9 08:50:24 2008
+# Linux kernel version: 2.6.26
+# Tue Jul 15 08:31:01 2008
#
# CONFIG_PPC64 is not set
@@ -51,6 +51,8 @@ CONFIG_PPC_UDBG_16550=y
CONFIG_AUDIT_ARCH=y
CONFIG_GENERIC_BUG=y
CONFIG_DEFAULT_UIMAGE=y
+CONFIG_HIBERNATE_32=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -97,6 +99,7 @@ CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
# CONFIG_ELF_CORE is not set
+CONFIG_PCSPKR_PLATFORM=y
CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
@@ -117,7 +120,7 @@ CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_HAVE_DMA_ATTRS=y
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
@@ -153,31 +156,43 @@ CONFIG_CLASSIC_RCU=y
#
# Platform support
#
-# CONFIG_PPC_MULTIPLATFORM is not set
-# CONFIG_PPC_82xx is not set
-# CONFIG_PPC_83xx is not set
-CONFIG_PPC_86xx=y
+CONFIG_PPC_MULTIPLATFORM=y
+CONFIG_CLASSIC32=y
+CONFIG_PPC_CHRP=y
# CONFIG_PPC_MPC512x is not set
# CONFIG_PPC_MPC5121 is not set
+# CONFIG_MPC5121_ADS is not set
+# CONFIG_PPC_MPC52xx is not set
+CONFIG_PPC_PMAC=y
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+CONFIG_PPC_86xx=y
# CONFIG_MPC8641_HPCN is not set
# CONFIG_SBC8641D is not set
CONFIG_MPC8610_HPCD=y
CONFIG_MPC8610=y
+# CONFIG_EMBEDDED6xx is not set
+CONFIG_PPC_NATIVE=y
+# CONFIG_UDBG_RTAS_CONSOLE is not set
# CONFIG_IPIC is not set
CONFIG_MPIC=y
# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
-# CONFIG_PPC_RTAS is not set
+CONFIG_PPC_I8259=y
+CONFIG_PPC_RTAS=y
+# CONFIG_RTAS_ERROR_LOGGING is not set
+CONFIG_RTAS_PROC=y
# CONFIG_MMIO_NVRAM is not set
-# CONFIG_PPC_MPC106 is not set
+CONFIG_PPC_MPC106=y
# CONFIG_PPC_970_NAP is not set
# CONFIG_PPC_INDIRECT_IO is not set
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
-# CONFIG_FSL_ULI1575 is not set
+# CONFIG_PPC601_SYNC_FIX is not set
+# CONFIG_TAU is not set
+CONFIG_FSL_ULI1575=y
#
# Kernel options
@@ -202,6 +217,7 @@ CONFIG_BINFMT_ELF=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_KEXEC is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -228,11 +244,13 @@ CONFIG_ISA_DMA_API=y
#
# Bus options
#
+# CONFIG_ISA is not set
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_PPC_INDIRECT_PCI=y
CONFIG_FSL_SOC=y
CONFIG_FSL_PCI=y
+CONFIG_PPC_PCI_CHOICE=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_SYSCALL=y
@@ -469,6 +487,7 @@ CONFIG_OF_I2C=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_FD is not set
+# CONFIG_MAC_FLOPPY is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
@@ -571,6 +590,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_MESH is not set
+# CONFIG_SCSI_MAC53C94 is not set
# CONFIG_SCSI_SRP is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
@@ -639,6 +660,10 @@ CONFIG_PATA_ALI=y
#
# IEEE 1394 (FireWire) support
#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
@@ -655,6 +680,8 @@ CONFIG_DUMMY=y
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
@@ -762,14 +789,16 @@ CONFIG_SERIAL_8250_RSA=y
# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_PMACZILOG is not set
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
+# CONFIG_BRIQ_PANEL is not set
+# CONFIG_HVC_RTAS is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_RAW_DRIVER is not set
@@ -787,9 +816,11 @@ CONFIG_I2C_BOARDINFO=y
# CONFIG_I2C_ALI15X3 is not set
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_HYDRA is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_POWERMAC=y
CONFIG_I2C_MPC=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_OCORES is not set
@@ -826,6 +857,7 @@ CONFIG_I2C_MPC=y
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
#
@@ -888,6 +920,9 @@ CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
# CONFIG_FB_OF is not set
+# CONFIG_FB_CONTROL is not set
+# CONFIG_FB_PLATINUM is not set
+# CONFIG_FB_VALKYRIE is not set
# CONFIG_FB_CT65550 is not set
# CONFIG_FB_ASILIANT is not set
# CONFIG_FB_IMSTT is not set
@@ -1027,12 +1062,19 @@ CONFIG_SND_VERBOSE_PROCFS=y
#
# ALSA PowerMac devices
#
+# CONFIG_SND_POWERMAC is not set
#
# ALSA PowerPC devices
#
#
+# Apple Onboard Audio driver
+#
+# CONFIG_SND_AOA is not set
+# CONFIG_SND_AOA_SOUNDBUS is not set
+
+#
# System on Chip audio support
#
CONFIG_SND_SOC=y
@@ -1075,7 +1117,57 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
# CONFIG_EDAC is not set
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PPC is not set
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
@@ -1295,8 +1387,11 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_DEBUGGER is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
# CONFIG_IRQSTACKS is not set
# CONFIG_BDI_SWITCH is not set
+# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
#
diff --git a/arch/powerpc/configs/mpc8641_hpcn_defconfig b/arch/powerpc/configs/mpc8641_hpcn_defconfig
index 4a817150739..867b8c0215f 100644
--- a/arch/powerpc/configs/mpc8641_hpcn_defconfig
+++ b/arch/powerpc/configs/mpc8641_hpcn_defconfig
@@ -991,10 +991,12 @@ CONFIG_SND=y
CONFIG_SND_TIMER=y
CONFIG_SND_PCM=y
# CONFIG_SND_SEQUENCER is not set
-# CONFIG_SND_MIXER_OSS is not set
-# CONFIG_SND_PCM_OSS is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
# CONFIG_SND_DYNAMIC_MINORS is not set
-CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
new file mode 100644
index 00000000000..e6e91c85da3
--- /dev/null
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -0,0 +1,3304 @@
+# powerpc
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-git2
+# Tue Jul 15 23:54:18 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_6xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
+CONFIG_FSL_EMB_PERFMON=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_DEFAULT_UIMAGE=y
+CONFIG_REDBOOT=y
+CONFIG_HIBERNATE_32=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+CONFIG_AUDIT_TREE=y
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_CGROUP_NS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+# CONFIG_USER_SCHED is not set
+CONFIG_CGROUP_SCHED=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+# CONFIG_CGROUP_MEM_RES_CTLR is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+CONFIG_RELAY=y
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_USER_NS=y
+CONFIG_PID_NS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_MARKERS=y
+CONFIG_OPROFILE=m
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_KRETPROBES=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_DMA_ATTRS is not set
+# CONFIG_USE_GENERIC_SMP_HELPERS is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+CONFIG_BLK_DEV_BSG=y
+CONFIG_BLK_DEV_INTEGRITY=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+CONFIG_CLASSIC32=y
+CONFIG_PPC_CHRP=y
+# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
+CONFIG_PPC_MPC52xx=y
+# CONFIG_PPC_MPC5200_SIMPLE is not set
+CONFIG_PPC_EFIKA=y
+# CONFIG_PPC_LITE5200 is not set
+CONFIG_PPC_MPC5200_BUGFIX=y
+CONFIG_PPC_MPC5200_GPIO=y
+CONFIG_PPC_PMAC=y
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+CONFIG_PPC_82xx=y
+CONFIG_MPC8272_ADS=y
+CONFIG_PQ2FADS=y
+CONFIG_EP8248E=y
+CONFIG_PQ2ADS=y
+CONFIG_8260=y
+CONFIG_8272=y
+CONFIG_PQ2_ADS_PCI_PIC=y
+CONFIG_PPC_83xx=y
+CONFIG_MPC831x_RDB=y
+CONFIG_MPC832x_MDS=y
+CONFIG_MPC832x_RDB=y
+CONFIG_MPC834x_MDS=y
+CONFIG_MPC834x_ITX=y
+CONFIG_MPC836x_MDS=y
+CONFIG_MPC836x_RDK=y
+CONFIG_MPC837x_MDS=y
+CONFIG_MPC837x_RDB=y
+CONFIG_SBC834x=y
+CONFIG_ASP834x=y
+CONFIG_PPC_MPC831x=y
+CONFIG_PPC_MPC832x=y
+CONFIG_PPC_MPC834x=y
+CONFIG_PPC_MPC837x=y
+CONFIG_PPC_86xx=y
+CONFIG_MPC8641_HPCN=y
+CONFIG_SBC8641D=y
+CONFIG_MPC8610_HPCD=y
+CONFIG_MPC8641=y
+CONFIG_MPC8610=y
+# CONFIG_EMBEDDED6xx is not set
+CONFIG_PPC_NATIVE=y
+# CONFIG_UDBG_RTAS_CONSOLE is not set
+CONFIG_IPIC=y
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
+CONFIG_PPC_RTAS=y
+# CONFIG_RTAS_ERROR_LOGGING is not set
+CONFIG_RTAS_PROC=y
+# CONFIG_MMIO_NVRAM is not set
+CONFIG_PPC_MPC106=y
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPU Frequency drivers
+#
+CONFIG_CPU_FREQ_PMAC=y
+# CONFIG_PPC601_SYNC_FIX is not set
+CONFIG_TAU=y
+# CONFIG_TAU_INT is not set
+CONFIG_TAU_AVERAGE=y
+CONFIG_QUICC_ENGINE=y
+CONFIG_CPM2=y
+CONFIG_PPC_CPM_NEW_BINDING=y
+CONFIG_FSL_ULI1575=y
+CONFIG_CPM=y
+CONFIG_PPC_BESTCOMM=y
+CONFIG_PPC_BESTCOMM_ATA=m
+CONFIG_PPC_BESTCOMM_FEC=m
+CONFIG_PPC_BESTCOMM_GEN_BD=m
+
+#
+# Kernel options
+#
+CONFIG_HIGHMEM=y
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_KEXEC is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
+CONFIG_ARCH_WANTS_FREEZER_CONTROL=y
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION=""
+CONFIG_APM_EMULATION=y
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ISA=y
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_FSL_PCI=y
+CONFIG_FSL_LBC=y
+CONFIG_FSL_GTM=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+CONFIG_PCI_8260=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+CONFIG_PCIEASPM=y
+# CONFIG_PCIEASPM_DEBUG is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_I82365=m
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_PROBE=y
+CONFIG_PCCARD_NONSTATIC=y
+# CONFIG_HOTPLUG_PCI is not set
+CONFIG_HAS_RAPIDIO=y
+# CONFIG_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+# CONFIG_PAGE_OFFSET_BOOL is not set
+CONFIG_PAGE_OFFSET=0xc0000000
+# CONFIG_KERNEL_START_BOOL is not set
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0xc0000000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=m
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+# CONFIG_DEFAULT_BIC is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NETLABEL=y
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV4=m
+# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=m
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+CONFIG_NET_DCCPPROBE=m
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+# CONFIG_ATM_MPOA is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_TOSHIBA_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+
+#
+# Wireless
+#
+CONFIG_CFG80211=m
+CONFIG_NL80211=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_MAC80211=m
+CONFIG_MAC80211_QOS=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+CONFIG_MAC80211_RC_DEFAULT="pid"
+CONFIG_MAC80211_MESH=y
+CONFIG_MAC80211_LEDS=y
+CONFIG_MAC80211_DEBUGFS=y
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_IEEE80211=m
+CONFIG_IEEE80211_DEBUG=y
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_RFKILL is not set
+CONFIG_NET_9P=m
+CONFIG_NET_9P_VIRTIO=m
+# CONFIG_NET_9P_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+CONFIG_DEBUG_DEVRES=y
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+# CONFIG_MTD is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_I2C=y
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_PC_PCMCIA is not set
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+CONFIG_PARPORT_NOT_PC=y
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_ISAPNP=y
+# CONFIG_PNPACPI is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_MAC_FLOPPY=m
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_VIRTIO_BLK=m
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+CONFIG_EEPROM_93CX6=m
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_ATAPI=y
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_DELKIN is not set
+CONFIG_BLK_DEV_IDECD=m
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=m
+# CONFIG_BLK_DEV_IDESCSI is not set
+CONFIG_IDE_TASK_IOCTL=y
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_PLATFORM is not set
+# CONFIG_BLK_DEV_IDEPNP is not set
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
+CONFIG_BLK_DEV_IDE_PMAC=y
+CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
+CONFIG_BLK_DEV_IDEDMA_PMAC=y
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_BLK_DEV_HD_ONLY=y
+CONFIG_BLK_DEV_HD=y
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_TGT=m
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_ENCLOSURE=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=m
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_SRP_ATTRS=m
+CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_SCSI_MESH=m
+CONFIG_SCSI_MESH_SYNC_RATE=5
+CONFIG_SCSI_MESH_RESET_DELAY_MS=4000
+CONFIG_SCSI_MAC53C94=m
+CONFIG_SCSI_SRP=m
+CONFIG_SCSI_LOWLEVEL_PCMCIA=y
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+CONFIG_SCSI_DH=y
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_PMP is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SIL24 is not set
+CONFIG_SATA_FSL=m
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_SVW is not set
+CONFIG_ATA_PIIX=m
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+CONFIG_PDC_ADMA=m
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+CONFIG_ATA_GENERIC=m
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_ISAPNP is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_LEGACY is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+CONFIG_PATA_MPC52xx=m
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OPTI is not set
+CONFIG_PATA_OPTIDMA=m
+# CONFIG_PATA_PCMCIA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_QDI is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+CONFIG_PATA_VIA=m
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_WINBOND_VLB is not set
+CONFIG_PATA_PLATFORM=m
+CONFIG_PATA_OF_PLATFORM=m
+CONFIG_PATA_SCH=m
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_DELAY is not set
+CONFIG_DM_UEVENT=y
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+CONFIG_FIREWIRE=m
+CONFIG_FIREWIRE_OHCI=m
+CONFIG_FIREWIRE_OHCI_DEBUG=y
+CONFIG_FIREWIRE_SBP2=m
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_MACINTOSH_DRIVERS=y
+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=y
+CONFIG_PMAC_MEDIABAY=y
+CONFIG_PMAC_BACKLIGHT=y
+# CONFIG_PMAC_BACKLIGHT_LEGACY is not set
+CONFIG_ADB_MACIO=y
+CONFIG_INPUT_ADBHID=y
+CONFIG_MAC_EMUMOUSEBTN=y
+CONFIG_THERM_WINDTUNNEL=m
+CONFIG_THERM_ADT746X=m
+CONFIG_WINDFARM=y
+# CONFIG_ANSLCD is not set
+CONFIG_PMAC_RACKMETER=m
+CONFIG_NETDEVICES=y
+CONFIG_NETDEVICES_MULTIQUEUE=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_NET_SB1000=m
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_ICPLUS_PHY=m
+CONFIG_REALTEK_PHY=m
+CONFIG_MDIO_BITBANG=y
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_MACE=m
+# CONFIG_MACE_AAUI_PORT is not set
+CONFIG_BMAC=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+CONFIG_EL3=m
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+CONFIG_ULTRA=m
+# CONFIG_SMC9194 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+CONFIG_EWRK3=m
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=m
+# CONFIG_ZNET is not set
+# CONFIG_SEEQ8005 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+CONFIG_B44=m
+CONFIG_B44_PCI_AUTOSELECT=y
+CONFIG_B44_PCICORE_AUTOSELECT=y
+CONFIG_B44_PCI=y
+CONFIG_FORCEDETH=m
+CONFIG_FORCEDETH_NAPI=y
+# CONFIG_CS89x0 is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_R6040=m
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_SC92031=m
+CONFIG_NET_POCKET=y
+CONFIG_DE600=m
+CONFIG_DE620=m
+CONFIG_FEC_MPC52xx=m
+CONFIG_FEC_MPC52xx_MDIO=y
+# CONFIG_FS_ENET is not set
+CONFIG_NETDEV_1000=y
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_E1000E=m
+CONFIG_E1000E_ENABLED=y
+CONFIG_IP1000=m
+CONFIG_IGB=m
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+# CONFIG_SKGE_DEBUG is not set
+CONFIG_SKY2=m
+# CONFIG_SKY2_DEBUG is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+CONFIG_GIANFAR=m
+CONFIG_GFAR_NAPI=y
+# CONFIG_UCC_GETH is not set
+CONFIG_MV643XX_ETH=m
+CONFIG_QLA3XXX=m
+CONFIG_ATL1=m
+CONFIG_NETDEV_10000=y
+CONFIG_CHELSIO_T1=m
+CONFIG_CHELSIO_T1_1G=y
+CONFIG_CHELSIO_T1_NAPI=y
+CONFIG_CHELSIO_T3=m
+CONFIG_IXGBE=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+CONFIG_NETXEN_NIC=m
+CONFIG_NIU=m
+# CONFIG_MLX4_CORE is not set
+CONFIG_TEHUTI=m
+CONFIG_BNX2X=m
+CONFIG_SFC=m
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+# CONFIG_ATM_FIRESTREAM is not set
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+# CONFIG_ATM_AMBASSADOR is not set
+# CONFIG_ATM_HORIZON is not set
+# CONFIG_ATM_IA is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_PPPOL2TP=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_VIRTIO_NET=m
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+CONFIG_INPUT_POLLDEV=m
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_APPLETOUCH=m
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+CONFIG_MOUSE_VSXXXAA=m
+# CONFIG_MOUSE_GPIO is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_ZHENHUA=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_JOYSTICK_XPAD=m
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+CONFIG_INPUT_TABLET=y
+CONFIG_TABLET_USB_ACECAD=m
+CONFIG_TABLET_USB_AIPTEK=m
+CONFIG_TABLET_USB_GTCO=m
+CONFIG_TABLET_USB_KBTAB=m
+CONFIG_TABLET_USB_WACOM=m
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_ATI_REMOTE=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_YEALINK=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+CONFIG_INPUT_LIRC=y
+CONFIG_LIRC_DEV=m
+CONFIG_LIRC_ATIUSB=m
+CONFIG_LIRC_BT829=m
+CONFIG_LIRC_CMDIR=m
+CONFIG_LIRC_I2C=m
+CONFIG_LIRC_IGORPLUGUSB=m
+CONFIG_LIRC_IMON=m
+CONFIG_LIRC_IT87=m
+CONFIG_LIRC_MCEUSB=m
+CONFIG_LIRC_MCEUSB2=m
+CONFIG_LIRC_PVR150=m
+CONFIG_LIRC_PARALLEL=m
+CONFIG_LIRC_SERIAL=m
+CONFIG_LIRC_SIR=m
+CONFIG_LIRC_STREAMZAP=m
+CONFIG_LIRC_TTUSBIR=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+CONFIG_ROCKETPORT=m
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+CONFIG_NOZOMI=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+# CONFIG_SERIAL_8250_FOURPORT is not set
+# CONFIG_SERIAL_8250_ACCENT is not set
+# CONFIG_SERIAL_8250_BOCA is not set
+# CONFIG_SERIAL_8250_EXAR_ST16C554 is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_UARTLITE=m
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_PMACZILOG=m
+# CONFIG_SERIAL_PMACZILOG_TTYS is not set
+# CONFIG_SERIAL_CPM is not set
+CONFIG_SERIAL_MPC52xx=y
+CONFIG_SERIAL_MPC52xx_CONSOLE=y
+CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
+CONFIG_SERIAL_JSM=m
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_QE is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_CRASH is not set
+CONFIG_BRIQ_PANEL=m
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+# CONFIG_HVC_RTAS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_NVRAM=y
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_IPWIRELESS=m
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_ALGOBIT=y
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# Mac SMBus host controller drivers
+#
+CONFIG_I2C_HYDRA=m
+CONFIG_I2C_POWERMAC=y
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CPM is not set
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_MPC=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_SIMTEC=m
+
+#
+# External I2C/SMBus adapter drivers
+#
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+# CONFIG_I2C_TAOS_EVM is not set
+CONFIG_I2C_TINY_USB=m
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+CONFIG_I2C_VOODOO3=m
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_ELEKTOR is not set
+CONFIG_I2C_PCA_ISA=m
+CONFIG_I2C_PCA_PLATFORM=m
+CONFIG_I2C_STUB=m
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+CONFIG_AT24=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_PCF8575=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+# CONFIG_TPS65010 is not set
+CONFIG_SENSORS_MAX6875=m
+CONFIG_SENSORS_TSL2550=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_HAVE_GPIO_LIB=y
+
+#
+# GPIO Support
+#
+# CONFIG_DEBUG_GPIO is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# SPI GPIO expanders:
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_MATROX is not set
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+# CONFIG_W1_MASTER_GPIO is not set
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+CONFIG_W1_SLAVE_DS2760=m
+CONFIG_POWER_SUPPLY=m
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+CONFIG_APM_POWER=m
+# CONFIG_BATTERY_DS2760 is not set
+CONFIG_BATTERY_PMU=m
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_AD7418=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1029=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ADT7470=m
+CONFIG_SENSORS_ADT7473=m
+CONFIG_SENSORS_AMS=m
+CONFIG_SENSORS_AMS_PMU=y
+CONFIG_SENSORS_AMS_I2C=y
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+# CONFIG_SENSORS_I5K_AMB is not set
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_F71882FG=m
+CONFIG_SENSORS_F75375S=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_LM93=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_MAX6650=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_PC87427=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_DME1737=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_ADS7828=m
+CONFIG_SENSORS_THMC50=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT1211=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83793=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83L786NG=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_THERMAL=y
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_MPC5200_WDT is not set
+CONFIG_83xx_WDT=m
+CONFIG_WATCHDOG_RTAS=m
+
+#
+# ISA-based Watchdog Cards
+#
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+CONFIG_SSB=m
+CONFIG_SSB_SPROM=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+# CONFIG_SSB_B43_PCI_BRIDGE is not set
+CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
+CONFIG_SSB_PCMCIAHOST=y
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_DRIVER_PCICORE=y
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_SM501=m
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_MT2131=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR_I2C=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+CONFIG_VIDEO_TVAUDIO=m
+CONFIG_VIDEO_TDA7432=m
+CONFIG_VIDEO_TDA9840=m
+CONFIG_VIDEO_TDA9875=m
+CONFIG_VIDEO_TEA6415C=m
+CONFIG_VIDEO_TEA6420=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS5345=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_M52790=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_VP27SMPX=m
+
+#
+# Video decoders
+#
+CONFIG_VIDEO_BT819=m
+CONFIG_VIDEO_BT856=m
+CONFIG_VIDEO_BT866=m
+CONFIG_VIDEO_KS0127=m
+CONFIG_VIDEO_OV7670=m
+CONFIG_VIDEO_TCM825X=m
+CONFIG_VIDEO_SAA7110=m
+CONFIG_VIDEO_SAA7111=m
+CONFIG_VIDEO_SAA7114=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA717X=m
+CONFIG_VIDEO_SAA7191=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_VPX3220=m
+
+#
+# Video and audio decoders
+#
+CONFIG_VIDEO_CX25840=m
+
+#
+# MPEG video encoders
+#
+CONFIG_VIDEO_CX2341X=m
+
+#
+# Video encoders
+#
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_SAA7185=m
+CONFIG_VIDEO_ADV7170=m
+CONFIG_VIDEO_ADV7175=m
+
+#
+# Video improvement chips
+#
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+# CONFIG_VIDEO_PMS is not set
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX23885=m
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_IVTV=m
+CONFIG_VIDEO_FB_IVTV=m
+CONFIG_VIDEO_CX18=m
+# CONFIG_VIDEO_CAFE_CCIC is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_SOC_CAMERA=m
+CONFIG_SOC_CAMERA_MT9M001=m
+# CONFIG_MT9M001_PCA9536_SWITCH is not set
+CONFIG_SOC_CAMERA_MT9V022=m
+# CONFIG_MT9V022_PCA9536_SWITCH is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+CONFIG_USB_DSBR=m
+CONFIG_USB_SI470X=m
+CONFIG_DVB_CAPTURE_DRIVERS=y
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_TTPCI_EEPROM=m
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET_CORE=m
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6405=m
+CONFIG_DVB_ISL6421=m
+CONFIG_DAB=y
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+CONFIG_AGP=y
+CONFIG_AGP_UNINORTH=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+CONFIG_VGASTATE=y
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_DDC=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_SVGALIB=m
+CONFIG_FB_MACMODES=y
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_OF=y
+# CONFIG_FB_CONTROL is not set
+CONFIG_FB_PLATINUM=y
+CONFIG_FB_VALKYRIE=y
+CONFIG_FB_CT65550=y
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NVIDIA=y
+CONFIG_FB_NVIDIA_I2C=y
+# CONFIG_FB_NVIDIA_DEBUG is not set
+CONFIG_FB_NVIDIA_BACKLIGHT=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_RIVA_BACKLIGHT=y
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+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=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_BACKLIGHT=y
+CONFIG_FB_S3=m
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+# CONFIG_FB_VT8623 is not set
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_FSL_DIU is not set
+CONFIG_FB_SM501=m
+CONFIG_FB_IBM_GXT4500=y
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_CORGI is not set
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=m
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=m
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+CONFIG_SND_DEBUG_VERBOSE=y
+CONFIG_SND_PCM_XRUN_DEBUG=y
+CONFIG_SND_VMASTER=y
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_DRIVERS=y
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_MTS64=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_PORTMAN2X4=m
+CONFIG_SND_AC97_POWER_SAVE=y
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT=5
+CONFIG_SND_SB_COMMON=m
+CONFIG_SND_SB16_DSP=m
+CONFIG_SND_ISA=y
+# CONFIG_SND_ADLIB is not set
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+# CONFIG_SND_CS4236 is not set
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_SC6000 is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+# CONFIG_SND_OPL3SA2 is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_MIRO is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+# CONFIG_SND_WAVEFRONT is not set
+CONFIG_SND_PCI=y
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AW2=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_OXYGEN_LIB=m
+CONFIG_SND_OXYGEN=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5530=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+# CONFIG_SND_HDA_INTEL is not set
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_HIFIER=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VIRTUOSO=m
+CONFIG_SND_VX222=m
+# CONFIG_SND_YMFPCI is not set
+CONFIG_SND_PPC=y
+CONFIG_SND_POWERMAC=m
+CONFIG_SND_POWERMAC_AUTO_DRC=y
+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
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+# CONFIG_SND_PCMCIA is not set
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+CONFIG_HIDRAW=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT_POWERBOOK=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_PANTHERLORD_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_ZEROPLUS_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_EHCI_FSL=y
+CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_PPC_SOC=y
+CONFIG_USB_OHCI_HCD_PPC_OF=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_OHCI_HCD_PCI=y
+# CONFIG_USB_OHCI_HCD_SSB is not set
+CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_U132_HCD=m
+CONFIG_USB_SL811_HCD=m
+# CONFIG_USB_SL811_CS is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+# CONFIG_USB_STORAGE_ISD200 is not set
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+# CONFIG_USB_SERIAL_GARMIN is not set
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_AUERSWALD=m
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_BERRY_CHARGE=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGET=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETMOTORCONTROL=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+CONFIG_USB_IOWARRIOR=m
+# CONFIG_USB_TEST is not set
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_GPIO is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_ACCESSIBILITY=y
+CONFIG_A11Y_BRAILLE_CONSOLE=y
+# CONFIG_INFINIBAND is not set
+CONFIG_EDAC=y
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=m
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1374=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_MAX6900=m
+CONFIG_RTC_DRV_RS5C372=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_M41T80=m
+CONFIG_RTC_DRV_M41T80_WDT=y
+# CONFIG_RTC_DRV_S35390A is not set
+CONFIG_RTC_DRV_FM3130=m
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_RTC_DRV_DS1511=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_STK17TA8=m
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_M48T59=m
+CONFIG_RTC_DRV_V3020=m
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_PPC=y
+CONFIG_DMADEVICES=y
+
+#
+# DMA Devices
+#
+# CONFIG_FSL_DMA is not set
+CONFIG_AUXDISPLAY=y
+CONFIG_KS0108=m
+CONFIG_KS0108_PORT=0x378
+CONFIG_KS0108_DELAY=2
+CONFIG_UIO=m
+CONFIG_UIO_CIF=m
+CONFIG_UIO_SMX=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4DEV_FS=m
+CONFIG_EXT4DEV_FS_XATTR=y
+CONFIG_EXT4DEV_FS_POSIX_ACL=y
+CONFIG_EXT4DEV_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+CONFIG_JBD2_DEBUG=y
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=m
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+# CONFIG_OCFS2_DEBUG_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_SUNRPC_BIND34=y
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+CONFIG_CIFS_UPCALL=y
+CONFIG_CIFS_DFS_UPCALL=y
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+CONFIG_DLM=m
+CONFIG_DLM_DEBUG=y
+CONFIG_QE_GPIO=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=m
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+CONFIG_HEADERS_CHECK=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_OBJECTS=y
+# CONFIG_DEBUG_OBJECTS_SELFTEST is not set
+CONFIG_DEBUG_OBJECTS_FREE=y
+CONFIG_DEBUG_OBJECTS_TIMERS=y
+CONFIG_SLUB_DEBUG_ON=y
+# CONFIG_SLUB_STATS is not set
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_HIGHMEM=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_VM=y
+CONFIG_DEBUG_WRITECOUNT=y
+CONFIG_DEBUG_LIST=y
+CONFIG_DEBUG_SG=y
+CONFIG_FRAME_POINTER=y
+CONFIG_BOOT_PRINTK_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_KPROBES_SANITY_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_LKDTM is not set
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAILSLAB=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAIL_MAKE_REQUEST=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_LATENCYTOP=y
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_TRACER_MAX_TRACE=y
+CONFIG_TRACING=y
+CONFIG_FTRACE=y
+CONFIG_SCHED_TRACER=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set
+# CONFIG_SAMPLES is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUGGER=y
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_KGDB_CONSOLE is not set
+CONFIG_XMON=y
+# CONFIG_XMON_DEFAULT is not set
+CONFIG_XMON_DISASSEMBLY=y
+CONFIG_IRQSTACKS=y
+# CONFIG_VIRQ_DEBUG is not set
+# CONFIG_BDI_SWITCH is not set
+CONFIG_BOOTX_TEXT=y
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_NETWORK_XFRM=y
+CONFIG_SECURITY_FILE_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=65536
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT=y
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+# CONFIG_SECURITY_SMACK is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_HIFN_795X=m
+CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y
+CONFIG_CRYPTO_DEV_TALITOS=m
+CONFIG_PPC_CLOCK=y
+CONFIG_PPC_LIB_RHEAP=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_VIRTIO=m
+CONFIG_VIRTIO_RING=m
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_BALLOON=m
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index 71d79e428d2..f9a3d3b394c 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25
-# Mon Apr 28 12:39:10 2008
+# Linux kernel version: 2.6.26
+# Wed Jul 16 13:59:24 2008
#
CONFIG_PPC64=y
@@ -14,8 +14,9 @@ CONFIG_POWER4=y
CONFIG_TUNE_CELL=y
CONFIG_PPC_FPU=y
CONFIG_ALTIVEC=y
+# CONFIG_VSX is not set
CONFIG_PPC_STD_MMU=y
-# CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_MM_SLICES=y
CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=2
@@ -31,6 +32,7 @@ CONFIG_GENERIC_HARDIRQS=y
CONFIG_HAVE_SETUP_PER_CPU_AREA=y
CONFIG_IRQ_PER_CPU=y
CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -90,6 +92,7 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_KALLSYMS_EXTRA_PASS=y
@@ -117,12 +120,15 @@ CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
@@ -132,6 +138,7 @@ CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
CONFIG_BLOCK_COMPAT=y
#
@@ -152,13 +159,8 @@ CONFIG_CLASSIC_RCU=y
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_82xx is not set
-# CONFIG_PPC_83xx is not set
-# CONFIG_PPC_86xx is not set
# CONFIG_PPC_PSERIES is not set
# CONFIG_PPC_ISERIES is not set
-# CONFIG_PPC_MPC512x is not set
-# CONFIG_PPC_MPC5121 is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_MAPLE is not set
# CONFIG_PPC_PASEMI is not set
@@ -187,6 +189,7 @@ CONFIG_PPC_CELL=y
# Cell Broadband Engine options
#
CONFIG_SPU_FS=y
+CONFIG_SPU_FS_64K_LS=y
CONFIG_SPU_BASE=y
# CONFIG_PQ2ADS is not set
# CONFIG_IPIC is not set
@@ -222,6 +225,7 @@ CONFIG_PREEMPT_NONE=y
CONFIG_BINFMT_ELF=y
CONFIG_COMPAT_BINFMT_ELF=y
CONFIG_BINFMT_MISC=y
+CONFIG_HUGETLB_PAGE_SIZE_VARIABLE=y
# CONFIG_IOMMU_VMERGE is not set
CONFIG_IOMMU_HELPER=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
@@ -248,18 +252,22 @@ CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
# CONFIG_SPARSEMEM_VMEMMAP is not set
CONFIG_MEMORY_HOTPLUG=y
CONFIG_MEMORY_HOTPLUG_SPARSE=y
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_ARCH_MEMORY_PROBE=y
-# CONFIG_PPC_HAS_HASH_64K is not set
+CONFIG_PPC_HAS_HASH_64K=y
# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=13
-# CONFIG_SCHED_SMT is not set
+CONFIG_SCHED_SMT=y
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
-# CONFIG_PM is not set
+CONFIG_EXTRA_TARGETS=""
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
# CONFIG_SECCOMP is not set
CONFIG_ISA_DMA_API=y
@@ -273,6 +281,7 @@ CONFIG_GENERIC_ISA_DMA=y
# CONFIG_PCI_SYSCALL is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
+# CONFIG_HAS_RAPIDIO is not set
CONFIG_PAGE_OFFSET=0xc000000000000000
CONFIG_KERNEL_START=0xc000000000000000
CONFIG_PHYSICAL_START=0x00000000
@@ -412,6 +421,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=m
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
@@ -478,6 +489,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SAS_LIBSAS is not set
# CONFIG_SCSI_SRP_ATTRS is not set
# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
# CONFIG_ATA is not set
# CONFIG_MD is not set
# CONFIG_MACINTOSH_DRIVERS is not set
@@ -533,8 +545,18 @@ CONFIG_USB_NET_MCS7830=m
# CONFIG_USB_NET_CDC_SUBSET is not set
# CONFIG_USB_NET_ZAURUS is not set
# CONFIG_WAN is not set
-# CONFIG_PPP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
+# CONFIG_PPPOL2TP is not set
# CONFIG_SLIP is not set
+CONFIG_SLHC=m
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -603,6 +625,7 @@ CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -618,23 +641,17 @@ CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=16
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_HANGCHECK_TIMER is not set
# CONFIG_TCG_TPM is not set
# CONFIG_I2C is not set
-
-#
-# SPI support
-#
# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
#
@@ -652,8 +669,17 @@ CONFIG_SSB_POSSIBLE=y
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
@@ -671,8 +697,8 @@ CONFIG_FB=y
CONFIG_FB_SYS_FILLRECT=y
CONFIG_FB_SYS_COPYAREA=y
CONFIG_FB_SYS_IMAGEBLIT=y
+# CONFIG_FB_FOREIGN_ENDIAN is not set
CONFIG_FB_SYS_FOPS=y
-CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
@@ -712,18 +738,12 @@ CONFIG_FB_LOGO_EXTRA=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
CONFIG_SOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
CONFIG_SND=m
CONFIG_SND_TIMER=m
CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
# CONFIG_SND_SEQUENCER is not set
# CONFIG_SND_MIXER_OSS is not set
# CONFIG_SND_PCM_OSS is not set
@@ -732,53 +752,20 @@ CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-
-#
-# ALSA PowerMac devices
-#
-
-#
-# ALSA PowerMac requires I2C
-#
-
-#
-# ALSA PowerPC devices
-#
+# CONFIG_SND_DRIVERS is not set
+CONFIG_SND_PPC=y
CONFIG_SND_PS3=m
CONFIG_SND_PS3_DEFAULT_START_DELAY=2000
-
-#
-# USB devices
-#
-# CONFIG_SND_USB_AUDIO is not set
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
# CONFIG_SND_USB_USX2Y is not set
# CONFIG_SND_USB_CAIAQ is not set
-
-#
-# System on Chip audio support
-#
# CONFIG_SND_SOC is not set
-
-#
-# ALSA SoC audio for Freescale SOCs
-#
-
-#
-# Open Sound System
-#
# CONFIG_SOUND_PRIME is not set
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
-# CONFIG_HIDRAW is not set
+CONFIG_HIDRAW=y
#
# USB Input Devices
@@ -807,17 +794,20 @@ CONFIG_USB=m
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
# CONFIG_USB_OTG is not set
#
# USB Host Controller Drivers
#
+# CONFIG_USB_C67X00_HCD is not set
CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y
# CONFIG_USB_EHCI_HCD_PPC_OF is not set
# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=m
# CONFIG_USB_OHCI_HCD_PPC_OF is not set
# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
@@ -831,6 +821,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
#
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -890,12 +881,45 @@ CONFIG_USB_MON=y
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_EDAC is not set
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_PPC=m
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
@@ -911,6 +935,7 @@ CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_SECURITY is not set
# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
@@ -959,8 +984,8 @@ CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
-# CONFIG_HUGETLBFS is not set
-# CONFIG_HUGETLB_PAGE is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -1059,12 +1084,15 @@ CONFIG_NLS_ISO8859_1=y
#
CONFIG_BITREVERSE=y
# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_CRC_CCITT is not set
+CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
CONFIG_CRC_ITU_T=m
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
CONFIG_LZO_COMPRESS=m
CONFIG_LZO_DECOMPRESS=m
CONFIG_PLIST=y
@@ -1082,7 +1110,7 @@ CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=2048
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
@@ -1090,33 +1118,49 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_LOCK_ALLOC is not set
-# CONFIG_PROVE_LOCKING is not set
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_LOCKDEP=y
# CONFIG_LOCK_STAT is not set
+CONFIG_DEBUG_LOCKDEP=y
+CONFIG_TRACE_IRQFLAGS=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
-# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_WRITECOUNT=y
CONFIG_DEBUG_LIST=y
# CONFIG_DEBUG_SG is not set
+CONFIG_FRAME_POINTER=y
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_SAMPLES is not set
CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_DEBUGGER is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
CONFIG_IRQSTACKS=y
+# CONFIG_VIRQ_DEBUG is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1172,6 +1216,10 @@ CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index bf0b1fd0ec3..1a4094704b1 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -74,6 +74,7 @@ obj-y += time.o prom.o traps.o setup-common.o \
misc_$(CONFIG_WORD_SIZE).o
obj-$(CONFIG_PPC32) += entry_32.o setup_32.o
obj-$(CONFIG_PPC64) += dma_64.o iommu.o
+obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o
obj-$(CONFIG_MODULES) += ppc_ksyms.o
obj-$(CONFIG_BOOTX_TEXT) += btext.o
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index f7f3c215d06..25c273c761d 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -23,6 +23,9 @@
struct cpu_spec* cur_cpu_spec = NULL;
EXPORT_SYMBOL(cur_cpu_spec);
+/* The platform string corresponding to the real PVR */
+const char *powerpc_base_platform;
+
/* NOTE:
* Unlike ppc32, ppc64 will only call this once for the boot CPU, it's
* the responsibility of the appropriate CPU save/restore functions to
@@ -355,6 +358,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.machine_check = machine_check_generic,
+ .oprofile_cpu_type = "ppc64/compat-power5+",
.platform = "power5+",
},
{ /* Power6 */
@@ -386,6 +390,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.machine_check = machine_check_generic,
+ .oprofile_cpu_type = "ppc64/compat-power6",
.platform = "power6",
},
{ /* 2.06-compliant processor, i.e. Power7 "architected" mode */
@@ -397,6 +402,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.machine_check = machine_check_generic,
+ .oprofile_cpu_type = "ppc64/compat-power7",
.platform = "power7",
},
{ /* Power7 */
@@ -1629,9 +1635,34 @@ struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
t->cpu_setup = s->cpu_setup;
t->cpu_restore = s->cpu_restore;
t->platform = s->platform;
+ /*
+ * If we have passed through this logic once
+ * before and have pulled the default case
+ * because the real PVR was not found inside
+ * cpu_specs[], then we are possibly running in
+ * compatibility mode. In that case, let the
+ * oprofiler know which set of compatibility
+ * counters to pull from by making sure the
+ * oprofile_cpu_type string is set to that of
+ * compatibility mode. If the oprofile_cpu_type
+ * already has a value, then we are possibly
+ * overriding a real PVR with a logical one, and,
+ * in that case, keep the current value for
+ * oprofile_cpu_type.
+ */
+ if (t->oprofile_cpu_type == NULL)
+ t->oprofile_cpu_type = s->oprofile_cpu_type;
} else
*t = *s;
*PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
+
+ /*
+ * Set the base platform string once; assumes
+ * we're called with real pvr first.
+ */
+ if (*PTRRELOC(&powerpc_base_platform) == NULL)
+ *PTRRELOC(&powerpc_base_platform) = t->platform;
+
#if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE)
/* ppc64 and booke expect identify_cpu to also call
* setup_cpu for that processor. I will consolidate
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index da52269aec1..81c8324a4a3 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -148,7 +148,7 @@ transfer_to_handler:
/* Check to see if the dbcr0 register is set up to debug. Use the
internal debug mode bit to do this. */
lwz r12,THREAD_DBCR0(r12)
- andis. r12,r12,DBCR0_IDM@h
+ andis. r12,r12,(DBCR0_IDM | DBSR_DAC1R | DBSR_DAC1W)@h
beq+ 3f
/* From user and task is ptraced - load up global dbcr0 */
li r12,-1 /* clear all pending debug events */
@@ -292,7 +292,7 @@ syscall_exit_cont:
/* If the process has its own DBCR0 value, load it up. The internal
debug mode bit tells us that dbcr0 should be loaded. */
lwz r0,THREAD+THREAD_DBCR0(r2)
- andis. r10,r0,DBCR0_IDM@h
+ andis. r10,r0,(DBCR0_IDM | DBSR_DAC1R | DBSR_DAC1W)@h
bnel- load_dbcr0
#endif
#ifdef CONFIG_44x
@@ -720,7 +720,7 @@ restore_user:
/* Check whether this process has its own DBCR0 value. The internal
debug mode bit tells us that dbcr0 should be loaded. */
lwz r0,THREAD+THREAD_DBCR0(r2)
- andis. r10,r0,DBCR0_IDM@h
+ andis. r10,r0,(DBCR0_IDM | DBSR_DAC1R | DBSR_DAC1W)@h
bnel- load_dbcr0
#endif
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index c4268500e85..3cb52fa0eda 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -151,16 +151,11 @@ skpinv: addi r6,r6,1 /* Increment */
/* Invalidate TLB0 */
li r6,0x04
tlbivax 0,r6
-#ifdef CONFIG_SMP
- tlbsync
-#endif
+ TLBSYNC
/* Invalidate TLB1 */
li r6,0x0c
tlbivax 0,r6
-#ifdef CONFIG_SMP
- tlbsync
-#endif
- msync
+ TLBSYNC
/* 3. Setup a temp mapping and jump to it */
andi. r5, r3, 0x1 /* Find an entry not used and is non-zero */
@@ -238,10 +233,7 @@ skpinv: addi r6,r6,1 /* Increment */
/* Invalidate TLB1 */
li r9,0x0c
tlbivax 0,r9
-#ifdef CONFIG_SMP
- tlbsync
-#endif
- msync
+ TLBSYNC
/* 6. Setup KERNELBASE mapping in TLB1[0] */
lis r6,0x1000 /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
@@ -283,10 +275,7 @@ skpinv: addi r6,r6,1 /* Increment */
/* Invalidate TLB1 */
li r9,0x0c
tlbivax 0,r9
-#ifdef CONFIG_SMP
- tlbsync
-#endif
- msync
+ TLBSYNC
/* Establish the interrupt vector offsets */
SET_IVOR(0, CriticalInput);
@@ -483,90 +472,16 @@ interrupt_base:
/* Data Storage Interrupt */
START_EXCEPTION(DataStorage)
- mtspr SPRN_SPRG0, r10 /* Save some working registers */
- mtspr SPRN_SPRG1, r11
- mtspr SPRN_SPRG4W, r12
- mtspr SPRN_SPRG5W, r13
- mfcr r11
- mtspr SPRN_SPRG7W, r11
-
- /*
- * Check if it was a store fault, if not then bail
- * because a user tried to access a kernel or
- * read-protected page. Otherwise, get the
- * offending address and handle it.
- */
- mfspr r10, SPRN_ESR
- andis. r10, r10, ESR_ST@h
- beq 2f
-
- mfspr r10, SPRN_DEAR /* Get faulting address */
-
- /* If we are faulting a kernel address, we have to use the
- * kernel page tables.
- */
- lis r11, PAGE_OFFSET@h
- cmplw 0, r10, r11
- bge 2f
-
- /* Get the PGD for the current thread */
-3:
- mfspr r11,SPRN_SPRG3
- lwz r11,PGDIR(r11)
-4:
- FIND_PTE
-
- /* Are _PAGE_USER & _PAGE_RW set & _PAGE_HWWRITE not? */
- andi. r13, r11, _PAGE_RW|_PAGE_USER|_PAGE_HWWRITE
- cmpwi 0, r13, _PAGE_RW|_PAGE_USER
- bne 2f /* Bail if not */
-
- /* Update 'changed'. */
- ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
- stw r11, PTE_FLAGS_OFFSET(r12) /* Update Linux page table */
-
- /* MAS2 not updated as the entry does exist in the tlb, this
- fault taken to detect state transition (eg: COW -> DIRTY)
- */
- andi. r11, r11, _PAGE_HWEXEC
- rlwimi r11, r11, 31, 27, 27 /* SX <- _PAGE_HWEXEC */
- ori r11, r11, (MAS3_UW|MAS3_SW|MAS3_UR|MAS3_SR)@l /* set static perms */
-
- /* update search PID in MAS6, AS = 0 */
- mfspr r12, SPRN_PID0
- slwi r12, r12, 16
- mtspr SPRN_MAS6, r12
-
- /* find the TLB index that caused the fault. It has to be here. */
- tlbsx 0, r10
-
- /* only update the perm bits, assume the RPN is fine */
- mfspr r12, SPRN_MAS3
- rlwimi r12, r11, 0, 20, 31
- mtspr SPRN_MAS3,r12
- tlbwe
-
- /* Done...restore registers and get out of here. */
- mfspr r11, SPRN_SPRG7R
- mtcr r11
- mfspr r13, SPRN_SPRG5R
- mfspr r12, SPRN_SPRG4R
- mfspr r11, SPRN_SPRG1
- mfspr r10, SPRN_SPRG0
- rfi /* Force context change */
-
-2:
- /*
- * The bailout. Restore registers to pre-exception conditions
- * and call the heavyweights to help us out.
- */
- mfspr r11, SPRN_SPRG7R
- mtcr r11
- mfspr r13, SPRN_SPRG5R
- mfspr r12, SPRN_SPRG4R
- mfspr r11, SPRN_SPRG1
- mfspr r10, SPRN_SPRG0
- b data_access
+ NORMAL_EXCEPTION_PROLOG
+ mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */
+ stw r5,_ESR(r11)
+ mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */
+ andis. r10,r5,(ESR_ILK|ESR_DLK)@h
+ bne 1f
+ EXC_XFER_EE_LITE(0x0300, handle_page_fault)
+1:
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_EE_LITE(0x0300, CacheLockingException)
/* Instruction Storage Interrupt */
INSTRUCTION_STORAGE_EXCEPTION
@@ -645,15 +560,30 @@ interrupt_base:
lwz r11,PGDIR(r11)
4:
+ /* Mask of required permission bits. Note that while we
+ * do copy ESR:ST to _PAGE_RW position as trying to write
+ * to an RO page is pretty common, we don't do it with
+ * _PAGE_DIRTY. We could do it, but it's a fairly rare
+ * event so I'd rather take the overhead when it happens
+ * rather than adding an instruction here. We should measure
+ * whether the whole thing is worth it in the first place
+ * as we could avoid loading SPRN_ESR completely in the first
+ * place...
+ *
+ * TODO: Is it worth doing that mfspr & rlwimi in the first
+ * place or can we save a couple of instructions here ?
+ */
+ mfspr r12,SPRN_ESR
+ li r13,_PAGE_PRESENT|_PAGE_ACCESSED
+ rlwimi r13,r12,11,29,29
+
FIND_PTE
- andi. r13, r11, _PAGE_PRESENT /* Is the page present? */
- beq 2f /* Bail if not present */
+ andc. r13,r13,r11 /* Check permission */
+ bne 2f /* Bail if permission mismach */
#ifdef CONFIG_PTE_64BIT
lwz r13, 0(r12)
#endif
- ori r11, r11, _PAGE_ACCESSED
- stw r11, PTE_FLAGS_OFFSET(r12)
/* Jump to common tlb load */
b finish_tlb_load
@@ -667,7 +597,7 @@ interrupt_base:
mfspr r12, SPRN_SPRG4R
mfspr r11, SPRN_SPRG1
mfspr r10, SPRN_SPRG0
- b data_access
+ b DataStorage
/* Instruction TLB Error Interrupt */
/*
@@ -705,15 +635,16 @@ interrupt_base:
lwz r11,PGDIR(r11)
4:
+ /* Make up the required permissions */
+ li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_HWEXEC
+
FIND_PTE
- andi. r13, r11, _PAGE_PRESENT /* Is the page present? */
- beq 2f /* Bail if not present */
+ andc. r13,r13,r11 /* Check permission */
+ bne 2f /* Bail if permission mismach */
#ifdef CONFIG_PTE_64BIT
lwz r13, 0(r12)
#endif
- ori r11, r11, _PAGE_ACCESSED
- stw r11, PTE_FLAGS_OFFSET(r12)
/* Jump to common TLB load point */
b finish_tlb_load
@@ -768,29 +699,13 @@ interrupt_base:
* Local functions
*/
- /*
- * Data TLB exceptions will bail out to this point
- * if they can't resolve the lightweight TLB fault.
- */
-data_access:
- NORMAL_EXCEPTION_PROLOG
- mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */
- stw r5,_ESR(r11)
- mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */
- andis. r10,r5,(ESR_ILK|ESR_DLK)@h
- bne 1f
- EXC_XFER_EE_LITE(0x0300, handle_page_fault)
-1:
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_EE_LITE(0x0300, CacheLockingException)
-
/*
-
* Both the instruction and data TLB miss get to this
* point to load the TLB.
* r10 - EA of fault
* r11 - TLB (info from Linux PTE)
- * r12, r13 - available to use
+ * r12 - available to use
+ * r13 - upper bits of PTE (if PTE_64BIT) or available to use
* CR5 - results of addr >= PAGE_OFFSET
* MAS0, MAS1 - loaded with proper value when we get here
* MAS2, MAS3 - will need additional info from Linux PTE
@@ -812,20 +727,14 @@ finish_tlb_load:
#endif
mtspr SPRN_MAS2, r12
- bge 5, 1f
-
- /* is user addr */
- andi. r12, r11, (_PAGE_USER | _PAGE_HWWRITE | _PAGE_HWEXEC)
+ li r10, (_PAGE_HWEXEC | _PAGE_PRESENT)
+ rlwimi r10, r11, 31, 29, 29 /* extract _PAGE_DIRTY into SW */
+ and r12, r11, r10
andi. r10, r11, _PAGE_USER /* Test for _PAGE_USER */
- srwi r10, r12, 1
- or r12, r12, r10 /* Copy user perms into supervisor */
- iseleq r12, 0, r12
- b 2f
-
- /* is kernel addr */
-1: rlwinm r12, r11, 31, 29, 29 /* Extract _PAGE_HWWRITE into SW */
- ori r12, r12, (MAS3_SX | MAS3_SR)
-
+ slwi r10, r12, 1
+ or r10, r10, r12
+ iseleq r12, r12, r10
+
#ifdef CONFIG_PTE_64BIT
2: rlwimi r12, r13, 24, 0, 7 /* grab RPN[32:39] */
rlwimi r12, r11, 24, 8, 19 /* grab RPN[40:51] */
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
index c3cf0e8f3ac..d308a9f70f1 100644
--- a/arch/powerpc/kernel/idle.c
+++ b/arch/powerpc/kernel/idle.c
@@ -60,7 +60,7 @@ void cpu_idle(void)
set_thread_flag(TIF_POLLING_NRFLAG);
while (1) {
- tick_nohz_stop_sched_tick();
+ tick_nohz_stop_sched_tick(1);
while (!need_resched() && !cpu_should_die()) {
ppc64_runlatch_off();
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 8c68ee9e5d1..550a19399bf 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -49,6 +49,8 @@ static int novmerge = 1;
static int protect4gb = 1;
+static void __iommu_free(struct iommu_table *, dma_addr_t, unsigned int);
+
static inline unsigned long iommu_num_pages(unsigned long vaddr,
unsigned long slen)
{
@@ -186,10 +188,12 @@ static unsigned long iommu_range_alloc(struct device *dev,
static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
void *page, unsigned int npages,
enum dma_data_direction direction,
- unsigned long mask, unsigned int align_order)
+ unsigned long mask, unsigned int align_order,
+ struct dma_attrs *attrs)
{
unsigned long entry, flags;
dma_addr_t ret = DMA_ERROR_CODE;
+ int build_fail;
spin_lock_irqsave(&(tbl->it_lock), flags);
@@ -204,9 +208,21 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
ret = entry << IOMMU_PAGE_SHIFT; /* Set the return dma address */
/* Put the TCEs in the HW table */
- ppc_md.tce_build(tbl, entry, npages, (unsigned long)page & IOMMU_PAGE_MASK,
- direction);
+ build_fail = ppc_md.tce_build(tbl, entry, npages,
+ (unsigned long)page & IOMMU_PAGE_MASK,
+ direction, attrs);
+
+ /* ppc_md.tce_build() only returns non-zero for transient errors.
+ * Clean up the table bitmap in this case and return
+ * DMA_ERROR_CODE. For all other errors the functionality is
+ * not altered.
+ */
+ if (unlikely(build_fail)) {
+ __iommu_free(tbl, ret, npages);
+ spin_unlock_irqrestore(&(tbl->it_lock), flags);
+ return DMA_ERROR_CODE;
+ }
/* Flush/invalidate TLB caches if necessary */
if (ppc_md.tce_flush)
@@ -275,7 +291,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
dma_addr_t dma_next = 0, dma_addr;
unsigned long flags;
struct scatterlist *s, *outs, *segstart;
- int outcount, incount, i;
+ int outcount, incount, i, build_fail = 0;
unsigned int align;
unsigned long handle;
unsigned int max_seg_size;
@@ -336,7 +352,11 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
npages, entry, dma_addr);
/* Insert into HW table */
- ppc_md.tce_build(tbl, entry, npages, vaddr & IOMMU_PAGE_MASK, direction);
+ build_fail = ppc_md.tce_build(tbl, entry, npages,
+ vaddr & IOMMU_PAGE_MASK,
+ direction, attrs);
+ if(unlikely(build_fail))
+ goto failure;
/* If we are in an open segment, try merging */
if (segstart != s) {
@@ -573,7 +593,8 @@ dma_addr_t iommu_map_single(struct device *dev, struct iommu_table *tbl,
align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction,
- mask >> IOMMU_PAGE_SHIFT, align);
+ mask >> IOMMU_PAGE_SHIFT, align,
+ attrs);
if (dma_handle == DMA_ERROR_CODE) {
if (printk_ratelimit()) {
printk(KERN_INFO "iommu_alloc failed, "
@@ -642,7 +663,7 @@ void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
nio_pages = size >> IOMMU_PAGE_SHIFT;
io_order = get_iommu_order(size);
mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
- mask >> IOMMU_PAGE_SHIFT, io_order);
+ mask >> IOMMU_PAGE_SHIFT, io_order, NULL);
if (mapping == DMA_ERROR_CODE) {
free_pages((unsigned long)ret, order);
return NULL;
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
new file mode 100644
index 00000000000..b4fdf2f2743
--- /dev/null
+++ b/arch/powerpc/kernel/kgdb.c
@@ -0,0 +1,410 @@
+/*
+ * PowerPC backend to the KGDB stub.
+ *
+ * 1998 (c) Michael AK Tesch (tesch@cs.wisc.edu)
+ * Copyright (C) 2003 Timesys Corporation.
+ * Copyright (C) 2004-2006 MontaVista Software, Inc.
+ * PPC64 Mods (C) 2005 Frank Rowand (frowand@mvista.com)
+ * PPC32 support restored by Vitaly Wool <vwool@ru.mvista.com> and
+ * Sergei Shtylyov <sshtylyov@ru.mvista.com>
+ * Copyright (C) 2007-2008 Wind River Systems, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program as licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/kgdb.h>
+#include <linux/smp.h>
+#include <linux/signal.h>
+#include <linux/ptrace.h>
+#include <asm/current.h>
+#include <asm/processor.h>
+#include <asm/machdep.h>
+
+/*
+ * This table contains the mapping between PowerPC hardware trap types, and
+ * signals, which are primarily what GDB understands. GDB and the kernel
+ * don't always agree on values, so we use constants taken from gdb-6.2.
+ */
+static struct hard_trap_info
+{
+ unsigned int tt; /* Trap type code for powerpc */
+ unsigned char signo; /* Signal that we map this trap into */
+} hard_trap_info[] = {
+ { 0x0100, 0x02 /* SIGINT */ }, /* system reset */
+ { 0x0200, 0x0b /* SIGSEGV */ }, /* machine check */
+ { 0x0300, 0x0b /* SIGSEGV */ }, /* data access */
+ { 0x0400, 0x0b /* SIGSEGV */ }, /* instruction access */
+ { 0x0500, 0x02 /* SIGINT */ }, /* external interrupt */
+ { 0x0600, 0x0a /* SIGBUS */ }, /* alignment */
+ { 0x0700, 0x05 /* SIGTRAP */ }, /* program check */
+ { 0x0800, 0x08 /* SIGFPE */ }, /* fp unavailable */
+ { 0x0900, 0x0e /* SIGALRM */ }, /* decrementer */
+ { 0x0c00, 0x14 /* SIGCHLD */ }, /* system call */
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ { 0x2002, 0x05 /* SIGTRAP */ }, /* debug */
+#if defined(CONFIG_FSL_BOOKE)
+ { 0x2010, 0x08 /* SIGFPE */ }, /* spe unavailable */
+ { 0x2020, 0x08 /* SIGFPE */ }, /* spe unavailable */
+ { 0x2030, 0x08 /* SIGFPE */ }, /* spe fp data */
+ { 0x2040, 0x08 /* SIGFPE */ }, /* spe fp data */
+ { 0x2050, 0x08 /* SIGFPE */ }, /* spe fp round */
+ { 0x2060, 0x0e /* SIGILL */ }, /* performace monitor */
+ { 0x2900, 0x08 /* SIGFPE */ }, /* apu unavailable */
+ { 0x3100, 0x0e /* SIGALRM */ }, /* fixed interval timer */
+ { 0x3200, 0x02 /* SIGINT */ }, /* watchdog */
+#else /* ! CONFIG_FSL_BOOKE */
+ { 0x1000, 0x0e /* SIGALRM */ }, /* prog interval timer */
+ { 0x1010, 0x0e /* SIGALRM */ }, /* fixed interval timer */
+ { 0x1020, 0x02 /* SIGINT */ }, /* watchdog */
+ { 0x2010, 0x08 /* SIGFPE */ }, /* fp unavailable */
+ { 0x2020, 0x08 /* SIGFPE */ }, /* ap unavailable */
+#endif
+#else /* ! (defined(CONFIG_40x) || defined(CONFIG_BOOKE)) */
+ { 0x0d00, 0x05 /* SIGTRAP */ }, /* single-step */
+#if defined(CONFIG_8xx)
+ { 0x1000, 0x04 /* SIGILL */ }, /* software emulation */
+#else /* ! CONFIG_8xx */
+ { 0x0f00, 0x04 /* SIGILL */ }, /* performance monitor */
+ { 0x0f20, 0x08 /* SIGFPE */ }, /* altivec unavailable */
+ { 0x1300, 0x05 /* SIGTRAP */ }, /* instruction address break */
+#if defined(CONFIG_PPC64)
+ { 0x1200, 0x05 /* SIGILL */ }, /* system error */
+ { 0x1500, 0x04 /* SIGILL */ }, /* soft patch */
+ { 0x1600, 0x04 /* SIGILL */ }, /* maintenance */
+ { 0x1700, 0x08 /* SIGFPE */ }, /* altivec assist */
+ { 0x1800, 0x04 /* SIGILL */ }, /* thermal */
+#else /* ! CONFIG_PPC64 */
+ { 0x1400, 0x02 /* SIGINT */ }, /* SMI */
+ { 0x1600, 0x08 /* SIGFPE */ }, /* altivec assist */
+ { 0x1700, 0x04 /* SIGILL */ }, /* TAU */
+ { 0x2000, 0x05 /* SIGTRAP */ }, /* run mode */
+#endif
+#endif
+#endif
+ { 0x0000, 0x00 } /* Must be last */
+};
+
+static int computeSignal(unsigned int tt)
+{
+ struct hard_trap_info *ht;
+
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ if (ht->tt == tt)
+ return ht->signo;
+
+ return SIGHUP; /* default for things we don't know about */
+}
+
+static int kgdb_call_nmi_hook(struct pt_regs *regs)
+{
+ kgdb_nmicallback(raw_smp_processor_id(), regs);
+ return 0;
+}
+
+#ifdef CONFIG_SMP
+void kgdb_roundup_cpus(unsigned long flags)
+{
+ smp_send_debugger_break(MSG_ALL_BUT_SELF);
+}
+#endif
+
+/* KGDB functions to use existing PowerPC64 hooks. */
+static int kgdb_debugger(struct pt_regs *regs)
+{
+ return kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
+}
+
+static int kgdb_handle_breakpoint(struct pt_regs *regs)
+{
+ if (user_mode(regs))
+ return 0;
+
+ if (kgdb_handle_exception(0, SIGTRAP, 0, regs) != 0)
+ return 0;
+
+ if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
+ regs->nip += 4;
+
+ return 1;
+}
+
+static int kgdb_singlestep(struct pt_regs *regs)
+{
+ struct thread_info *thread_info, *exception_thread_info;
+
+ if (user_mode(regs))
+ return 0;
+
+ /*
+ * On Book E and perhaps other processsors, singlestep is handled on
+ * the critical exception stack. This causes current_thread_info()
+ * to fail, since it it locates the thread_info by masking off
+ * the low bits of the current stack pointer. We work around
+ * this issue by copying the thread_info from the kernel stack
+ * before calling kgdb_handle_exception, and copying it back
+ * afterwards. On most processors the copy is avoided since
+ * exception_thread_info == thread_info.
+ */
+ thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));
+ exception_thread_info = current_thread_info();
+
+ if (thread_info != exception_thread_info)
+ memcpy(exception_thread_info, thread_info, sizeof *thread_info);
+
+ kgdb_handle_exception(0, SIGTRAP, 0, regs);
+
+ if (thread_info != exception_thread_info)
+ memcpy(thread_info, exception_thread_info, sizeof *thread_info);
+
+ return 1;
+}
+
+static int kgdb_iabr_match(struct pt_regs *regs)
+{
+ if (user_mode(regs))
+ return 0;
+
+ if (kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs) != 0)
+ return 0;
+ return 1;
+}
+
+static int kgdb_dabr_match(struct pt_regs *regs)
+{
+ if (user_mode(regs))
+ return 0;
+
+ if (kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs) != 0)
+ return 0;
+ return 1;
+}
+
+#define PACK64(ptr, src) do { *(ptr++) = (src); } while (0)
+
+#define PACK32(ptr, src) do { \
+ u32 *ptr32; \
+ ptr32 = (u32 *)ptr; \
+ *(ptr32++) = (src); \
+ ptr = (unsigned long *)ptr32; \
+ } while (0)
+
+
+void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+ unsigned long *ptr = gdb_regs;
+ int reg;
+
+ memset(gdb_regs, 0, NUMREGBYTES);
+
+ for (reg = 0; reg < 32; reg++)
+ PACK64(ptr, regs->gpr[reg]);
+
+#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_SPE
+ for (reg = 0; reg < 32; reg++)
+ PACK64(ptr, current->thread.evr[reg]);
+#else
+ ptr += 32;
+#endif
+#else
+ /* fp registers not used by kernel, leave zero */
+ ptr += 32 * 8 / sizeof(long);
+#endif
+
+ PACK64(ptr, regs->nip);
+ PACK64(ptr, regs->msr);
+ PACK32(ptr, regs->ccr);
+ PACK64(ptr, regs->link);
+ PACK64(ptr, regs->ctr);
+ PACK32(ptr, regs->xer);
+
+ BUG_ON((unsigned long)ptr >
+ (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
+}
+
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
+{
+ struct pt_regs *regs = (struct pt_regs *)(p->thread.ksp +
+ STACK_FRAME_OVERHEAD);
+ unsigned long *ptr = gdb_regs;
+ int reg;
+
+ memset(gdb_regs, 0, NUMREGBYTES);
+
+ /* Regs GPR0-2 */
+ for (reg = 0; reg < 3; reg++)
+ PACK64(ptr, regs->gpr[reg]);
+
+ /* Regs GPR3-13 are caller saved, not in regs->gpr[] */
+ ptr += 11;
+
+ /* Regs GPR14-31 */
+ for (reg = 14; reg < 32; reg++)
+ PACK64(ptr, regs->gpr[reg]);
+
+#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_SPE
+ for (reg = 0; reg < 32; reg++)
+ PACK64(ptr, p->thread.evr[reg]);
+#else
+ ptr += 32;
+#endif
+#else
+ /* fp registers not used by kernel, leave zero */
+ ptr += 32 * 8 / sizeof(long);
+#endif
+
+ PACK64(ptr, regs->nip);
+ PACK64(ptr, regs->msr);
+ PACK32(ptr, regs->ccr);
+ PACK64(ptr, regs->link);
+ PACK64(ptr, regs->ctr);
+ PACK32(ptr, regs->xer);
+
+ BUG_ON((unsigned long)ptr >
+ (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
+}
+
+#define UNPACK64(dest, ptr) do { dest = *(ptr++); } while (0)
+
+#define UNPACK32(dest, ptr) do { \
+ u32 *ptr32; \
+ ptr32 = (u32 *)ptr; \
+ dest = *(ptr32++); \
+ ptr = (unsigned long *)ptr32; \
+ } while (0)
+
+void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+ unsigned long *ptr = gdb_regs;
+ int reg;
+#ifdef CONFIG_SPE
+ union {
+ u32 v32[2];
+ u64 v64;
+ } acc;
+#endif
+
+ for (reg = 0; reg < 32; reg++)
+ UNPACK64(regs->gpr[reg], ptr);
+
+#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_SPE
+ for (reg = 0; reg < 32; reg++)
+ UNPACK64(current->thread.evr[reg], ptr);
+#else
+ ptr += 32;
+#endif
+#else
+ /* fp registers not used by kernel, leave zero */
+ ptr += 32 * 8 / sizeof(int);
+#endif
+
+ UNPACK64(regs->nip, ptr);
+ UNPACK64(regs->msr, ptr);
+ UNPACK32(regs->ccr, ptr);
+ UNPACK64(regs->link, ptr);
+ UNPACK64(regs->ctr, ptr);
+ UNPACK32(regs->xer, ptr);
+
+ BUG_ON((unsigned long)ptr >
+ (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
+}
+
+/*
+ * This function does PowerPC specific procesing for interfacing to gdb.
+ */
+int kgdb_arch_handle_exception(int vector, int signo, int err_code,
+ char *remcom_in_buffer, char *remcom_out_buffer,
+ struct pt_regs *linux_regs)
+{
+ char *ptr = &remcom_in_buffer[1];
+ unsigned long addr;
+
+ switch (remcom_in_buffer[0]) {
+ /*
+ * sAA..AA Step one instruction from AA..AA
+ * This will return an error to gdb ..
+ */
+ case 's':
+ case 'c':
+ /* handle the optional parameter */
+ if (kgdb_hex2long(&ptr, &addr))
+ linux_regs->nip = addr;
+
+ atomic_set(&kgdb_cpu_doing_single_step, -1);
+ /* set the trace bit if we're stepping */
+ if (remcom_in_buffer[0] == 's') {
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ mtspr(SPRN_DBCR0,
+ mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
+ linux_regs->msr |= MSR_DE;
+#else
+ linux_regs->msr |= MSR_SE;
+#endif
+ kgdb_single_step = 1;
+ if (kgdb_contthread)
+ atomic_set(&kgdb_cpu_doing_single_step,
+ raw_smp_processor_id());
+ }
+ return 0;
+ }
+
+ return -1;
+}
+
+/*
+ * Global data
+ */
+struct kgdb_arch arch_kgdb_ops = {
+ .gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08},
+};
+
+static int kgdb_not_implemented(struct pt_regs *regs)
+{
+ return 0;
+}
+
+static void *old__debugger_ipi;
+static void *old__debugger;
+static void *old__debugger_bpt;
+static void *old__debugger_sstep;
+static void *old__debugger_iabr_match;
+static void *old__debugger_dabr_match;
+static void *old__debugger_fault_handler;
+
+int kgdb_arch_init(void)
+{
+ old__debugger_ipi = __debugger_ipi;
+ old__debugger = __debugger;
+ old__debugger_bpt = __debugger_bpt;
+ old__debugger_sstep = __debugger_sstep;
+ old__debugger_iabr_match = __debugger_iabr_match;
+ old__debugger_dabr_match = __debugger_dabr_match;
+ old__debugger_fault_handler = __debugger_fault_handler;
+
+ __debugger_ipi = kgdb_call_nmi_hook;
+ __debugger = kgdb_debugger;
+ __debugger_bpt = kgdb_handle_breakpoint;
+ __debugger_sstep = kgdb_singlestep;
+ __debugger_iabr_match = kgdb_iabr_match;
+ __debugger_dabr_match = kgdb_dabr_match;
+ __debugger_fault_handler = kgdb_not_implemented;
+
+ return 0;
+}
+
+void kgdb_arch_exit(void)
+{
+ __debugger_ipi = old__debugger_ipi;
+ __debugger = old__debugger;
+ __debugger_bpt = old__debugger_bpt;
+ __debugger_sstep = old__debugger_sstep;
+ __debugger_iabr_match = old__debugger_iabr_match;
+ __debugger_dabr_match = old__debugger_dabr_match;
+ __debugger_fault_handler = old__debugger_fault_handler;
+}
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 4ba2af12545..de79915452c 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -144,7 +144,6 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
kcb->kprobe_saved_msr = regs->msr;
}
-/* Called with kretprobe_lock held */
void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
struct pt_regs *regs)
{
@@ -312,8 +311,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p,
unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
INIT_HLIST_HEAD(&empty_rp);
- spin_lock_irqsave(&kretprobe_lock, flags);
- head = kretprobe_inst_table_head(current);
+ kretprobe_hash_lock(current, &head, &flags);
/*
* It is possible to have multiple instances associated with a given
@@ -352,7 +350,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p,
regs->nip = orig_ret_address;
reset_current_kprobe();
- spin_unlock_irqrestore(&kretprobe_lock, flags);
+ kretprobe_hash_unlock(current, &flags);
preempt_enable_no_resched();
hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 827a5726a03..9f856a0c3e3 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -34,8 +34,9 @@
#include <asm/time.h>
#include <asm/prom.h>
#include <asm/vdso_datapage.h>
+#include <asm/vio.h>
-#define MODULE_VERS "1.7"
+#define MODULE_VERS "1.8"
#define MODULE_NAME "lparcfg"
/* #define LPARCFG_DEBUG */
@@ -129,32 +130,46 @@ static int iseries_lparcfg_data(struct seq_file *m, void *v)
/*
* Methods used to fetch LPAR data when running on a pSeries platform.
*/
-static void log_plpar_hcall_return(unsigned long rc, char *tag)
+/**
+ * h_get_mpp
+ * H_GET_MPP hcall returns info in 7 parms
+ */
+int h_get_mpp(struct hvcall_mpp_data *mpp_data)
{
- switch(rc) {
- case 0:
- return;
- case H_HARDWARE:
- printk(KERN_INFO "plpar-hcall (%s) "
- "Hardware fault\n", tag);
- return;
- case H_FUNCTION:
- printk(KERN_INFO "plpar-hcall (%s) "
- "Function not allowed\n", tag);
- return;
- case H_AUTHORITY:
- printk(KERN_INFO "plpar-hcall (%s) "
- "Not authorized to this function\n", tag);
- return;
- case H_PARAMETER:
- printk(KERN_INFO "plpar-hcall (%s) "
- "Bad parameter(s)\n",tag);
- return;
- default:
- printk(KERN_INFO "plpar-hcall (%s) "
- "Unexpected rc(0x%lx)\n", tag, rc);
- }
+ int rc;
+ unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
+
+ rc = plpar_hcall9(H_GET_MPP, retbuf);
+
+ mpp_data->entitled_mem = retbuf[0];
+ mpp_data->mapped_mem = retbuf[1];
+
+ mpp_data->group_num = (retbuf[2] >> 2 * 8) & 0xffff;
+ mpp_data->pool_num = retbuf[2] & 0xffff;
+
+ mpp_data->mem_weight = (retbuf[3] >> 7 * 8) & 0xff;
+ mpp_data->unallocated_mem_weight = (retbuf[3] >> 6 * 8) & 0xff;
+ mpp_data->unallocated_entitlement = retbuf[3] & 0xffffffffffff;
+
+ mpp_data->pool_size = retbuf[4];
+ mpp_data->loan_request = retbuf[5];
+ mpp_data->backing_mem = retbuf[6];
+
+ return rc;
}
+EXPORT_SYMBOL(h_get_mpp);
+
+struct hvcall_ppp_data {
+ u64 entitlement;
+ u64 unallocated_entitlement;
+ u16 group_num;
+ u16 pool_num;
+ u8 capped;
+ u8 weight;
+ u8 unallocated_weight;
+ u16 active_procs_in_pool;
+ u16 active_system_procs;
+};
/*
* H_GET_PPP hcall returns info in 4 parms.
@@ -176,27 +191,30 @@ static void log_plpar_hcall_return(unsigned long rc, char *tag)
* XXXX - Active processors in Physical Processor Pool.
* XXXX - Processors active on platform.
*/
-static unsigned int h_get_ppp(unsigned long *entitled,
- unsigned long *unallocated,
- unsigned long *aggregation,
- unsigned long *resource)
+static unsigned int h_get_ppp(struct hvcall_ppp_data *ppp_data)
{
unsigned long rc;
unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
rc = plpar_hcall(H_GET_PPP, retbuf);
- *entitled = retbuf[0];
- *unallocated = retbuf[1];
- *aggregation = retbuf[2];
- *resource = retbuf[3];
+ ppp_data->entitlement = retbuf[0];
+ ppp_data->unallocated_entitlement = retbuf[1];
+
+ ppp_data->group_num = (retbuf[2] >> 2 * 8) & 0xffff;
+ ppp_data->pool_num = retbuf[2] & 0xffff;
- log_plpar_hcall_return(rc, "H_GET_PPP");
+ ppp_data->capped = (retbuf[3] >> 6 * 8) & 0x01;
+ ppp_data->weight = (retbuf[3] >> 5 * 8) & 0xff;
+ ppp_data->unallocated_weight = (retbuf[3] >> 4 * 8) & 0xff;
+ ppp_data->active_procs_in_pool = (retbuf[3] >> 2 * 8) & 0xffff;
+ ppp_data->active_system_procs = retbuf[3] & 0xffff;
return rc;
}
-static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs)
+static unsigned h_pic(unsigned long *pool_idle_time,
+ unsigned long *num_procs)
{
unsigned long rc;
unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
@@ -206,8 +224,87 @@ static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs)
*pool_idle_time = retbuf[0];
*num_procs = retbuf[1];
- if (rc != H_AUTHORITY)
- log_plpar_hcall_return(rc, "H_PIC");
+ return rc;
+}
+
+/*
+ * parse_ppp_data
+ * Parse out the data returned from h_get_ppp and h_pic
+ */
+static void parse_ppp_data(struct seq_file *m)
+{
+ struct hvcall_ppp_data ppp_data;
+ int rc;
+
+ rc = h_get_ppp(&ppp_data);
+ if (rc)
+ return;
+
+ seq_printf(m, "partition_entitled_capacity=%ld\n",
+ ppp_data.entitlement);
+ seq_printf(m, "group=%d\n", ppp_data.group_num);
+ seq_printf(m, "system_active_processors=%d\n",
+ ppp_data.active_system_procs);
+
+ /* pool related entries are apropriate for shared configs */
+ if (lppaca[0].shared_proc) {
+ unsigned long pool_idle_time, pool_procs;
+
+ seq_printf(m, "pool=%d\n", ppp_data.pool_num);
+
+ /* report pool_capacity in percentage */
+ seq_printf(m, "pool_capacity=%d\n",
+ ppp_data.active_procs_in_pool * 100);
+
+ h_pic(&pool_idle_time, &pool_procs);
+ seq_printf(m, "pool_idle_time=%ld\n", pool_idle_time);
+ seq_printf(m, "pool_num_procs=%ld\n", pool_procs);
+ }
+
+ seq_printf(m, "unallocated_capacity_weight=%d\n",
+ ppp_data.unallocated_weight);
+ seq_printf(m, "capacity_weight=%d\n", ppp_data.weight);
+ seq_printf(m, "capped=%d\n", ppp_data.capped);
+ seq_printf(m, "unallocated_capacity=%ld\n",
+ ppp_data.unallocated_entitlement);
+}
+
+/**
+ * parse_mpp_data
+ * Parse out data returned from h_get_mpp
+ */
+static void parse_mpp_data(struct seq_file *m)
+{
+ struct hvcall_mpp_data mpp_data;
+ int rc;
+
+ rc = h_get_mpp(&mpp_data);
+ if (rc)
+ return;
+
+ seq_printf(m, "entitled_memory=%ld\n", mpp_data.entitled_mem);
+
+ if (mpp_data.mapped_mem != -1)
+ seq_printf(m, "mapped_entitled_memory=%ld\n",
+ mpp_data.mapped_mem);
+
+ seq_printf(m, "entitled_memory_group_number=%d\n", mpp_data.group_num);
+ seq_printf(m, "entitled_memory_pool_number=%d\n", mpp_data.pool_num);
+
+ seq_printf(m, "entitled_memory_weight=%d\n", mpp_data.mem_weight);
+ seq_printf(m, "unallocated_entitled_memory_weight=%d\n",
+ mpp_data.unallocated_mem_weight);
+ seq_printf(m, "unallocated_io_mapping_entitlement=%ld\n",
+ mpp_data.unallocated_entitlement);
+
+ if (mpp_data.pool_size != -1)
+ seq_printf(m, "entitled_memory_pool_size=%ld bytes\n",
+ mpp_data.pool_size);
+
+ seq_printf(m, "entitled_memory_loan_request=%ld\n",
+ mpp_data.loan_request);
+
+ seq_printf(m, "backing_memory=%ld bytes\n", mpp_data.backing_mem);
}
#define SPLPAR_CHARACTERISTICS_TOKEN 20
@@ -313,6 +410,25 @@ static int lparcfg_count_active_processors(void)
return count;
}
+static void pseries_cmo_data(struct seq_file *m)
+{
+ int cpu;
+ unsigned long cmo_faults = 0;
+ unsigned long cmo_fault_time = 0;
+
+ if (!firmware_has_feature(FW_FEATURE_CMO))
+ return;
+
+ for_each_possible_cpu(cpu) {
+ cmo_faults += lppaca[cpu].cmo_faults;
+ cmo_fault_time += lppaca[cpu].cmo_fault_time;
+ }
+
+ seq_printf(m, "cmo_faults=%lu\n", cmo_faults);
+ seq_printf(m, "cmo_fault_time_usec=%lu\n",
+ cmo_fault_time / tb_ticks_per_usec);
+}
+
static int pseries_lparcfg_data(struct seq_file *m, void *v)
{
int partition_potential_processors;
@@ -334,60 +450,13 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
partition_active_processors = lparcfg_count_active_processors();
if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
- unsigned long h_entitled, h_unallocated;
- unsigned long h_aggregation, h_resource;
- unsigned long pool_idle_time, pool_procs;
- unsigned long purr;
-
- h_get_ppp(&h_entitled, &h_unallocated, &h_aggregation,
- &h_resource);
-
- seq_printf(m, "R4=0x%lx\n", h_entitled);
- seq_printf(m, "R5=0x%lx\n", h_unallocated);
- seq_printf(m, "R6=0x%lx\n", h_aggregation);
- seq_printf(m, "R7=0x%lx\n", h_resource);
-
- purr = get_purr();
-
/* this call handles the ibm,get-system-parameter contents */
parse_system_parameter_string(m);
+ parse_ppp_data(m);
+ parse_mpp_data(m);
+ pseries_cmo_data(m);
- seq_printf(m, "partition_entitled_capacity=%ld\n", h_entitled);
-
- seq_printf(m, "group=%ld\n", (h_aggregation >> 2 * 8) & 0xffff);
-
- seq_printf(m, "system_active_processors=%ld\n",
- (h_resource >> 0 * 8) & 0xffff);
-
- /* pool related entries are apropriate for shared configs */
- if (lppaca[0].shared_proc) {
-
- h_pic(&pool_idle_time, &pool_procs);
-
- seq_printf(m, "pool=%ld\n",
- (h_aggregation >> 0 * 8) & 0xffff);
-
- /* report pool_capacity in percentage */
- seq_printf(m, "pool_capacity=%ld\n",
- ((h_resource >> 2 * 8) & 0xffff) * 100);
-
- seq_printf(m, "pool_idle_time=%ld\n", pool_idle_time);
-
- seq_printf(m, "pool_num_procs=%ld\n", pool_procs);
- }
-
- seq_printf(m, "unallocated_capacity_weight=%ld\n",
- (h_resource >> 4 * 8) & 0xFF);
-
- seq_printf(m, "capacity_weight=%ld\n",
- (h_resource >> 5 * 8) & 0xFF);
-
- seq_printf(m, "capped=%ld\n", (h_resource >> 6 * 8) & 0x01);
-
- seq_printf(m, "unallocated_capacity=%ld\n", h_unallocated);
-
- seq_printf(m, "purr=%ld\n", purr);
-
+ seq_printf(m, "purr=%ld\n", get_purr());
} else { /* non SPLPAR case */
seq_printf(m, "system_active_processors=%d\n",
@@ -414,6 +483,83 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
return 0;
}
+static ssize_t update_ppp(u64 *entitlement, u8 *weight)
+{
+ struct hvcall_ppp_data ppp_data;
+ u8 new_weight;
+ u64 new_entitled;
+ ssize_t retval;
+
+ /* Get our current parameters */
+ retval = h_get_ppp(&ppp_data);
+ if (retval)
+ return retval;
+
+ if (entitlement) {
+ new_weight = ppp_data.weight;
+ new_entitled = *entitlement;
+ } else if (weight) {
+ new_weight = *weight;
+ new_entitled = ppp_data.entitlement;
+ } else
+ return -EINVAL;
+
+ pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
+ __FUNCTION__, ppp_data.entitlement, ppp_data.weight);
+
+ pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
+ __FUNCTION__, new_entitled, new_weight);
+
+ retval = plpar_hcall_norets(H_SET_PPP, new_entitled, new_weight);
+ return retval;
+}
+
+/**
+ * update_mpp
+ *
+ * Update the memory entitlement and weight for the partition. Caller must
+ * specify either a new entitlement or weight, not both, to be updated
+ * since the h_set_mpp call takes both entitlement and weight as parameters.
+ */
+static ssize_t update_mpp(u64 *entitlement, u8 *weight)
+{
+ struct hvcall_mpp_data mpp_data;
+ u64 new_entitled;
+ u8 new_weight;
+ ssize_t rc;
+
+ if (entitlement) {
+ /* Check with vio to ensure the new memory entitlement
+ * can be handled.
+ */
+ rc = vio_cmo_entitlement_update(*entitlement);
+ if (rc)
+ return rc;
+ }
+
+ rc = h_get_mpp(&mpp_data);
+ if (rc)
+ return rc;
+
+ if (entitlement) {
+ new_weight = mpp_data.mem_weight;
+ new_entitled = *entitlement;
+ } else if (weight) {
+ new_weight = *weight;
+ new_entitled = mpp_data.entitled_mem;
+ } else
+ return -EINVAL;
+
+ pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
+ __FUNCTION__, mpp_data.entitled_mem, mpp_data.mem_weight);
+
+ pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
+ __FUNCTION__, new_entitled, new_weight);
+
+ rc = plpar_hcall_norets(H_SET_MPP, new_entitled, new_weight);
+ return rc;
+}
+
/*
* Interface for changing system parameters (variable capacity weight
* and entitled capacity). Format of input is "param_name=value";
@@ -427,35 +573,27 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
static ssize_t lparcfg_write(struct file *file, const char __user * buf,
size_t count, loff_t * off)
{
- char *kbuf;
+ int kbuf_sz = 64;
+ char kbuf[kbuf_sz];
char *tmp;
u64 new_entitled, *new_entitled_ptr = &new_entitled;
u8 new_weight, *new_weight_ptr = &new_weight;
-
- unsigned long current_entitled; /* parameters for h_get_ppp */
- unsigned long dummy;
- unsigned long resource;
- u8 current_weight;
-
- ssize_t retval = -ENOMEM;
+ ssize_t retval;
if (!firmware_has_feature(FW_FEATURE_SPLPAR) ||
firmware_has_feature(FW_FEATURE_ISERIES))
return -EINVAL;
- kbuf = kmalloc(count, GFP_KERNEL);
- if (!kbuf)
- goto out;
+ if (count > kbuf_sz)
+ return -EINVAL;
- retval = -EFAULT;
if (copy_from_user(kbuf, buf, count))
- goto out;
+ return -EFAULT;
- retval = -EINVAL;
kbuf[count - 1] = '\0';
tmp = strchr(kbuf, '=');
if (!tmp)
- goto out;
+ return -EINVAL;
*tmp++ = '\0';
@@ -463,34 +601,32 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
char *endp;
*new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10);
if (endp == tmp)
- goto out;
- new_weight_ptr = &current_weight;
+ return -EINVAL;
+
+ retval = update_ppp(new_entitled_ptr, NULL);
} else if (!strcmp(kbuf, "capacity_weight")) {
char *endp;
*new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10);
if (endp == tmp)
- goto out;
- new_entitled_ptr = &current_entitled;
- } else
- goto out;
-
- /* Get our current parameters */
- retval = h_get_ppp(&current_entitled, &dummy, &dummy, &resource);
- if (retval) {
- retval = -EIO;
- goto out;
- }
-
- current_weight = (resource >> 5 * 8) & 0xFF;
+ return -EINVAL;
- pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
- __func__, current_entitled, current_weight);
+ retval = update_ppp(NULL, new_weight_ptr);
+ } else if (!strcmp(kbuf, "entitled_memory")) {
+ char *endp;
+ *new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10);
+ if (endp == tmp)
+ return -EINVAL;
- pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
- __func__, *new_entitled_ptr, *new_weight_ptr);
+ retval = update_mpp(new_entitled_ptr, NULL);
+ } else if (!strcmp(kbuf, "entitled_memory_weight")) {
+ char *endp;
+ *new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10);
+ if (endp == tmp)
+ return -EINVAL;
- retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
- *new_weight_ptr);
+ retval = update_mpp(NULL, new_weight_ptr);
+ } else
+ return -EINVAL;
if (retval == H_SUCCESS || retval == H_CONSTRAINED) {
retval = count;
@@ -506,8 +642,6 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
retval = -EIO;
}
-out:
- kfree(kbuf);
return retval;
}
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 063cdd41304..224e9a11765 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -598,6 +598,7 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
res->start = pci_addr;
break;
case 2: /* PCI Memory space */
+ case 3: /* PCI 64 bits Memory space */
printk(KERN_INFO
" MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n",
cpu_addr, cpu_addr + size - 1, pci_addr,
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 219f3634115..db2497ccc11 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -47,6 +47,8 @@
#ifdef CONFIG_PPC64
#include <asm/firmware.h>
#endif
+#include <linux/kprobes.h>
+#include <linux/kdebug.h>
extern unsigned long _get_SP(void);
@@ -239,6 +241,35 @@ void discard_lazy_cpu_state(void)
}
#endif /* CONFIG_SMP */
+void do_dabr(struct pt_regs *regs, unsigned long address,
+ unsigned long error_code)
+{
+ siginfo_t info;
+
+ if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
+ 11, SIGSEGV) == NOTIFY_STOP)
+ return;
+
+ if (debugger_dabr_match(regs))
+ return;
+
+ /* Clear the DAC and struct entries. One shot trigger */
+#if (defined(CONFIG_44x) || defined(CONFIG_BOOKE))
+ mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | DBSR_DAC1W
+ | DBCR0_IDM));
+#endif
+
+ /* Clear the DABR */
+ set_dabr(0);
+
+ /* Deliver the signal to userspace */
+ info.si_signo = SIGTRAP;
+ info.si_errno = 0;
+ info.si_code = TRAP_HWBKPT;
+ info.si_addr = (void __user *)address;
+ force_sig_info(SIGTRAP, &info, current);
+}
+
static DEFINE_PER_CPU(unsigned long, current_dabr);
int set_dabr(unsigned long dabr)
@@ -254,6 +285,11 @@ int set_dabr(unsigned long dabr)
#if defined(CONFIG_PPC64) || defined(CONFIG_6xx)
mtspr(SPRN_DABR, dabr);
#endif
+
+#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
+ mtspr(SPRN_DAC1, dabr);
+#endif
+
return 0;
}
@@ -337,6 +373,12 @@ struct task_struct *__switch_to(struct task_struct *prev,
if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
set_dabr(new->thread.dabr);
+#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
+ /* If new thread DAC (HW breakpoint) is the same then leave it */
+ if (new->thread.dabr)
+ set_dabr(new->thread.dabr);
+#endif
+
new_thread = &new->thread;
old_thread = &current->thread;
@@ -525,6 +567,10 @@ void flush_thread(void)
if (current->thread.dabr) {
current->thread.dabr = 0;
set_dabr(0);
+
+#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
+ current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W);
+#endif
}
}
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 1ea8c8d3ce8..c4ab2195b9c 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -643,6 +643,11 @@ static void __init early_cmdline_parse(void)
#else
#define OV5_MSI 0x00
#endif /* CONFIG_PCI_MSI */
+#ifdef CONFIG_PPC_SMLPAR
+#define OV5_CMO 0x80 /* Cooperative Memory Overcommitment */
+#else
+#define OV5_CMO 0x00
+#endif
/*
* The architecture vector has an array of PVR mask/value pairs,
@@ -687,10 +692,12 @@ static unsigned char ibm_architecture_vec[] = {
0, /* don't halt */
/* option vector 5: PAPR/OF options */
- 3 - 2, /* length */
+ 5 - 2, /* length */
0, /* don't ignore, don't halt */
OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
OV5_DONATE_DEDICATE_CPU | OV5_MSI,
+ 0,
+ OV5_CMO,
};
/* Old method - ELF header with PT_NOTE sections */
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 90eb3a3e383..bc1fb27368a 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -128,12 +128,35 @@ static void of_bus_pci_count_cells(struct device_node *np,
*sizec = 2;
}
+static unsigned int of_bus_pci_get_flags(const u32 *addr)
+{
+ unsigned int flags = 0;
+ u32 w = addr[0];
+
+ switch((w >> 24) & 0x03) {
+ case 0x01:
+ flags |= IORESOURCE_IO;
+ break;
+ case 0x02: /* 32 bits */
+ case 0x03: /* 64 bits */
+ flags |= IORESOURCE_MEM;
+ break;
+ }
+ if (w & 0x40000000)
+ flags |= IORESOURCE_PREFETCH;
+ return flags;
+}
+
static u64 of_bus_pci_map(u32 *addr, const u32 *range, int na, int ns, int pna)
{
u64 cp, s, da;
+ unsigned int af, rf;
+
+ af = of_bus_pci_get_flags(addr);
+ rf = of_bus_pci_get_flags(range);
/* Check address type match */
- if ((addr[0] ^ range[0]) & 0x03000000)
+ if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO))
return OF_BAD_ADDR;
/* Read address values, skipping high cell */
@@ -153,25 +176,6 @@ static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
return of_bus_default_translate(addr + 1, offset, na - 1);
}
-static unsigned int of_bus_pci_get_flags(const u32 *addr)
-{
- unsigned int flags = 0;
- u32 w = addr[0];
-
- switch((w >> 24) & 0x03) {
- case 0x01:
- flags |= IORESOURCE_IO;
- break;
- case 0x02: /* 32 bits */
- case 0x03: /* 64 bits */
- flags |= IORESOURCE_MEM;
- break;
- }
- if (w & 0x40000000)
- flags |= IORESOURCE_PREFETCH;
- return flags;
-}
-
const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
unsigned int *flags)
{
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 8feb93e7890..a5d0e78779c 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -703,7 +703,7 @@ void user_enable_single_step(struct task_struct *task)
if (regs != NULL) {
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
- task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC;
+ task->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC;
regs->msr |= MSR_DE;
#else
regs->msr |= MSR_SE;
@@ -716,9 +716,16 @@ void user_disable_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
+
+#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
+ /* If DAC then do not single step, skip */
+ if (task->thread.dabr)
+ return;
+#endif
+
if (regs != NULL) {
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
- task->thread.dbcr0 = 0;
+ task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_IDM);
regs->msr &= ~MSR_DE;
#else
regs->msr &= ~MSR_SE;
@@ -727,22 +734,75 @@ void user_disable_single_step(struct task_struct *task)
clear_tsk_thread_flag(task, TIF_SINGLESTEP);
}
-static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
+int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
unsigned long data)
{
- /* We only support one DABR and no IABRS at the moment */
+ /* For ppc64 we support one DABR and no IABR's at the moment (ppc64).
+ * For embedded processors we support one DAC and no IAC's at the
+ * moment.
+ */
if (addr > 0)
return -EINVAL;
- /* The bottom 3 bits are flags */
if ((data & ~0x7UL) >= TASK_SIZE)
return -EIO;
- /* Ensure translation is on */
+#ifdef CONFIG_PPC64
+
+ /* For processors using DABR (i.e. 970), the bottom 3 bits are flags.
+ * It was assumed, on previous implementations, that 3 bits were
+ * passed together with the data address, fitting the design of the
+ * DABR register, as follows:
+ *
+ * bit 0: Read flag
+ * bit 1: Write flag
+ * bit 2: Breakpoint translation
+ *
+ * Thus, we use them here as so.
+ */
+
+ /* Ensure breakpoint translation bit is set */
if (data && !(data & DABR_TRANSLATION))
return -EIO;
+ /* Move contents to the DABR register */
task->thread.dabr = data;
+
+#endif
+#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
+
+ /* As described above, it was assumed 3 bits were passed with the data
+ * address, but we will assume only the mode bits will be passed
+ * as to not cause alignment restrictions for DAC-based processors.
+ */
+
+ /* DAC's hold the whole address without any mode flags */
+ task->thread.dabr = data & ~0x3UL;
+
+ if (task->thread.dabr == 0) {
+ task->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | DBCR0_IDM);
+ task->thread.regs->msr &= ~MSR_DE;
+ return 0;
+ }
+
+ /* Read or Write bits must be set */
+
+ if (!(data & 0x3UL))
+ return -EINVAL;
+
+ /* Set the Internal Debugging flag (IDM bit 1) for the DBCR0
+ register */
+ task->thread.dbcr0 = DBCR0_IDM;
+
+ /* Check for write and read flags and set DBCR0
+ accordingly */
+ if (data & 0x1UL)
+ task->thread.dbcr0 |= DBSR_DAC1R;
+ if (data & 0x2UL)
+ task->thread.dbcr0 |= DBSR_DAC1W;
+
+ task->thread.regs->msr |= MSR_DE;
+#endif
return 0;
}
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 4efebe88e64..066e65c59b5 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -43,10 +43,6 @@
#define DBG(fmt...)
-#if defined CONFIG_KGDB
-#include <asm/kgdb.h>
-#endif
-
extern void bootx_init(unsigned long r4, unsigned long phys);
int boot_cpuid;
@@ -302,18 +298,6 @@ void __init setup_arch(char **cmdline_p)
xmon_setup();
-#if defined(CONFIG_KGDB)
- if (ppc_md.kgdb_map_scc)
- ppc_md.kgdb_map_scc();
- set_debug_traps();
- if (strstr(cmd_line, "gdb")) {
- if (ppc_md.progress)
- ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
- printk("kgdb breakpoint activated\n");
- breakpoint();
- }
-#endif
-
/*
* Set cache line size based on type of cpu as a default.
* Systems with OF can look in the properties on the cpu node(s)
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index ad55488939c..7aada783ec6 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -145,8 +145,12 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
* user space. The DABR will have been cleared if it
* triggered inside the kernel.
*/
- if (current->thread.dabr)
+ if (current->thread.dabr) {
set_dabr(current->thread.dabr);
+#if defined(CONFIG_44x) || defined(CONFIG_BOOKE)
+ mtspr(SPRN_DBCR0, current->thread.dbcr0);
+#endif
+ }
if (is32) {
if (ka.sa.sa_flags & SA_SIGINFO)
diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c
index 071bee3ec74..f2589645870 100644
--- a/arch/powerpc/kernel/stacktrace.c
+++ b/arch/powerpc/kernel/stacktrace.c
@@ -59,6 +59,6 @@ EXPORT_SYMBOL_GPL(save_stack_trace);
void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
{
- save_context_stack(trace, tsk->thread.regs->gpr[1], tsk, 0);
+ save_context_stack(trace, tsk->thread.ksp, tsk, 0);
}
EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
diff --git a/arch/powerpc/kernel/suspend.c b/arch/powerpc/kernel/suspend.c
index 8cee5710754..6fc6328dc62 100644
--- a/arch/powerpc/kernel/suspend.c
+++ b/arch/powerpc/kernel/suspend.c
@@ -7,6 +7,7 @@
* Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
*/
+#include <linux/mm.h>
#include <asm/page.h>
/* References to section boundaries */
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index c8127f832df..800e5e9a087 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -28,7 +28,9 @@ static DEFINE_PER_CPU(struct cpu, cpu_devices);
/* Time in microseconds we delay before sleeping in the idle loop */
DEFINE_PER_CPU(unsigned long, smt_snooze_delay) = { 100 };
-static ssize_t store_smt_snooze_delay(struct sys_device *dev, const char *buf,
+static ssize_t store_smt_snooze_delay(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ const char *buf,
size_t count)
{
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
@@ -44,7 +46,9 @@ static ssize_t store_smt_snooze_delay(struct sys_device *dev, const char *buf,
return count;
}
-static ssize_t show_smt_snooze_delay(struct sys_device *dev, char *buf)
+static ssize_t show_smt_snooze_delay(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ char *buf)
{
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
@@ -152,14 +156,17 @@ static unsigned long write_##NAME(unsigned long val) \
mtspr(ADDRESS, val); \
return 0; \
} \
-static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+static ssize_t show_##NAME(struct sys_device *dev, \
+ struct sysdev_attribute *attr, \
+ char *buf) \
{ \
struct cpu *cpu = container_of(dev, struct cpu, sysdev); \
unsigned long val = run_on_cpu(cpu->sysdev.id, read_##NAME, 0); \
return sprintf(buf, "%lx\n", val); \
} \
static ssize_t __used \
- store_##NAME(struct sys_device *dev, const char *buf, size_t count) \
+ store_##NAME(struct sys_device *dev, struct sysdev_attribute *attr, \
+ const char *buf, size_t count) \
{ \
struct cpu *cpu = container_of(dev, struct cpu, sysdev); \
unsigned long val; \
@@ -522,7 +529,8 @@ static void register_nodes(void)
#endif
/* Only valid if CPU is present. */
-static ssize_t show_physical_id(struct sys_device *dev, char *buf)
+static ssize_t show_physical_id(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 878fbddb6ae..81ccb8dd1a5 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1067,6 +1067,22 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
}
_exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
+ } else if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) {
+ regs->msr &= ~MSR_DE;
+
+ if (user_mode(regs)) {
+ current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W |
+ DBCR0_IDM);
+ } else {
+ /* Disable DAC interupts */
+ mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R |
+ DBSR_DAC1W | DBCR0_IDM));
+
+ /* Clear the DAC event */
+ mtspr(SPRN_DBSR, (DBSR_DAC1R | DBSR_DAC1W));
+ }
+ /* Setup and send the trap to the handler */
+ do_dabr(regs, mfspr(SPRN_DAC1), debug_status);
}
}
#endif /* CONFIG_4xx || CONFIG_BOOKE */
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index b77f8af7ddd..ade8aeaa2e7 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -1,11 +1,12 @@
/*
* IBM PowerPC Virtual I/O Infrastructure Support.
*
- * Copyright (c) 2003-2005 IBM Corp.
+ * Copyright (c) 2003,2008 IBM Corp.
* Dave Engebretsen engebret@us.ibm.com
* Santiago Leon santil@us.ibm.com
* Hollis Blanchard <hollisb@us.ibm.com>
* Stephen Rothwell
+ * Robert Jennings <rcjenn@us.ibm.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -46,6 +47,996 @@ static struct vio_dev vio_bus_device = { /* fake "parent" device */
.dev.bus = &vio_bus_type,
};
+#ifdef CONFIG_PPC_SMLPAR
+/**
+ * vio_cmo_pool - A pool of IO memory for CMO use
+ *
+ * @size: The size of the pool in bytes
+ * @free: The amount of free memory in the pool
+ */
+struct vio_cmo_pool {
+ size_t size;
+ size_t free;
+};
+
+/* How many ms to delay queued balance work */
+#define VIO_CMO_BALANCE_DELAY 100
+
+/* Portion out IO memory to CMO devices by this chunk size */
+#define VIO_CMO_BALANCE_CHUNK 131072
+
+/**
+ * vio_cmo_dev_entry - A device that is CMO-enabled and requires entitlement
+ *
+ * @vio_dev: struct vio_dev pointer
+ * @list: pointer to other devices on bus that are being tracked
+ */
+struct vio_cmo_dev_entry {
+ struct vio_dev *viodev;
+ struct list_head list;
+};
+
+/**
+ * vio_cmo - VIO bus accounting structure for CMO entitlement
+ *
+ * @lock: spinlock for entire structure
+ * @balance_q: work queue for balancing system entitlement
+ * @device_list: list of CMO-enabled devices requiring entitlement
+ * @entitled: total system entitlement in bytes
+ * @reserve: pool of memory from which devices reserve entitlement, incl. spare
+ * @excess: pool of excess entitlement not needed for device reserves or spare
+ * @spare: IO memory for device hotplug functionality
+ * @min: minimum necessary for system operation
+ * @desired: desired memory for system operation
+ * @curr: bytes currently allocated
+ * @high: high water mark for IO data usage
+ */
+struct vio_cmo {
+ spinlock_t lock;
+ struct delayed_work balance_q;
+ struct list_head device_list;
+ size_t entitled;
+ struct vio_cmo_pool reserve;
+ struct vio_cmo_pool excess;
+ size_t spare;
+ size_t min;
+ size_t desired;
+ size_t curr;
+ size_t high;
+} vio_cmo;
+
+/**
+ * vio_cmo_OF_devices - Count the number of OF devices that have DMA windows
+ */
+static int vio_cmo_num_OF_devs(void)
+{
+ struct device_node *node_vroot;
+ int count = 0;
+
+ /*
+ * Count the number of vdevice entries with an
+ * ibm,my-dma-window OF property
+ */
+ node_vroot = of_find_node_by_name(NULL, "vdevice");
+ if (node_vroot) {
+ struct device_node *of_node;
+ struct property *prop;
+
+ for_each_child_of_node(node_vroot, of_node) {
+ prop = of_find_property(of_node, "ibm,my-dma-window",
+ NULL);
+ if (prop)
+ count++;
+ }
+ }
+ of_node_put(node_vroot);
+ return count;
+}
+
+/**
+ * vio_cmo_alloc - allocate IO memory for CMO-enable devices
+ *
+ * @viodev: VIO device requesting IO memory
+ * @size: size of allocation requested
+ *
+ * Allocations come from memory reserved for the devices and any excess
+ * IO memory available to all devices. The spare pool used to service
+ * hotplug must be equal to %VIO_CMO_MIN_ENT for the excess pool to be
+ * made available.
+ *
+ * Return codes:
+ * 0 for successful allocation and -ENOMEM for a failure
+ */
+static inline int vio_cmo_alloc(struct vio_dev *viodev, size_t size)
+{
+ unsigned long flags;
+ size_t reserve_free = 0;
+ size_t excess_free = 0;
+ int ret = -ENOMEM;
+
+ spin_lock_irqsave(&vio_cmo.lock, flags);
+
+ /* Determine the amount of free entitlement available in reserve */
+ if (viodev->cmo.entitled > viodev->cmo.allocated)
+ reserve_free = viodev->cmo.entitled - viodev->cmo.allocated;
+
+ /* If spare is not fulfilled, the excess pool can not be used. */
+ if (vio_cmo.spare >= VIO_CMO_MIN_ENT)
+ excess_free = vio_cmo.excess.free;
+
+ /* The request can be satisfied */
+ if ((reserve_free + excess_free) >= size) {
+ vio_cmo.curr += size;
+ if (vio_cmo.curr > vio_cmo.high)
+ vio_cmo.high = vio_cmo.curr;
+ viodev->cmo.allocated += size;
+ size -= min(reserve_free, size);
+ vio_cmo.excess.free -= size;
+ ret = 0;
+ }
+
+ spin_unlock_irqrestore(&vio_cmo.lock, flags);
+ return ret;
+}
+
+/**
+ * vio_cmo_dealloc - deallocate IO memory from CMO-enable devices
+ * @viodev: VIO device freeing IO memory
+ * @size: size of deallocation
+ *
+ * IO memory is freed by the device back to the correct memory pools.
+ * The spare pool is replenished first from either memory pool, then
+ * the reserve pool is used to reduce device entitlement, the excess
+ * pool is used to increase the reserve pool toward the desired entitlement
+ * target, and then the remaining memory is returned to the pools.
+ *
+ */
+static inline void vio_cmo_dealloc(struct vio_dev *viodev, size_t size)
+{
+ unsigned long flags;
+ size_t spare_needed = 0;
+ size_t excess_freed = 0;
+ size_t reserve_freed = size;
+ size_t tmp;
+ int balance = 0;
+
+ spin_lock_irqsave(&vio_cmo.lock, flags);
+ vio_cmo.curr -= size;
+
+ /* Amount of memory freed from the excess pool */
+ if (viodev->cmo.allocated > viodev->cmo.entitled) {
+ excess_freed = min(reserve_freed, (viodev->cmo.allocated -
+ viodev->cmo.entitled));
+ reserve_freed -= excess_freed;
+ }
+
+ /* Remove allocation from device */
+ viodev->cmo.allocated -= (reserve_freed + excess_freed);
+
+ /* Spare is a subset of the reserve pool, replenish it first. */
+ spare_needed = VIO_CMO_MIN_ENT - vio_cmo.spare;
+
+ /*
+ * Replenish the spare in the reserve pool from the excess pool.
+ * This moves entitlement into the reserve pool.
+ */
+ if (spare_needed && excess_freed) {
+ tmp = min(excess_freed, spare_needed);
+ vio_cmo.excess.size -= tmp;
+ vio_cmo.reserve.size += tmp;
+ vio_cmo.spare += tmp;
+ excess_freed -= tmp;
+ spare_needed -= tmp;
+ balance = 1;
+ }
+
+ /*
+ * Replenish the spare in the reserve pool from the reserve pool.
+ * This removes entitlement from the device down to VIO_CMO_MIN_ENT,
+ * if needed, and gives it to the spare pool. The amount of used
+ * memory in this pool does not change.
+ */
+ if (spare_needed && reserve_freed) {
+ tmp = min(spare_needed, min(reserve_freed,
+ (viodev->cmo.entitled -
+ VIO_CMO_MIN_ENT)));
+
+ vio_cmo.spare += tmp;
+ viodev->cmo.entitled -= tmp;
+ reserve_freed -= tmp;
+ spare_needed -= tmp;
+ balance = 1;
+ }
+
+ /*
+ * Increase the reserve pool until the desired allocation is met.
+ * Move an allocation freed from the excess pool into the reserve
+ * pool and schedule a balance operation.
+ */
+ if (excess_freed && (vio_cmo.desired > vio_cmo.reserve.size)) {
+ tmp = min(excess_freed, (vio_cmo.desired - vio_cmo.reserve.size));
+
+ vio_cmo.excess.size -= tmp;
+ vio_cmo.reserve.size += tmp;
+ excess_freed -= tmp;
+ balance = 1;
+ }
+
+ /* Return memory from the excess pool to that pool */
+ if (excess_freed)
+ vio_cmo.excess.free += excess_freed;
+
+ if (balance)
+ schedule_delayed_work(&vio_cmo.balance_q, VIO_CMO_BALANCE_DELAY);
+ spin_unlock_irqrestore(&vio_cmo.lock, flags);
+}
+
+/**
+ * vio_cmo_entitlement_update - Manage system entitlement changes
+ *
+ * @new_entitlement: new system entitlement to attempt to accommodate
+ *
+ * Increases in entitlement will be used to fulfill the spare entitlement
+ * and the rest is given to the excess pool. Decreases, if they are
+ * possible, come from the excess pool and from unused device entitlement
+ *
+ * Returns: 0 on success, -ENOMEM when change can not be made
+ */
+int vio_cmo_entitlement_update(size_t new_entitlement)
+{
+ struct vio_dev *viodev;
+ struct vio_cmo_dev_entry *dev_ent;
+ unsigned long flags;
+ size_t avail, delta, tmp;
+
+ spin_lock_irqsave(&vio_cmo.lock, flags);
+
+ /* Entitlement increases */
+ if (new_entitlement > vio_cmo.entitled) {
+ delta = new_entitlement - vio_cmo.entitled;
+
+ /* Fulfill spare allocation */
+ if (vio_cmo.spare < VIO_CMO_MIN_ENT) {
+ tmp = min(delta, (VIO_CMO_MIN_ENT - vio_cmo.spare));
+ vio_cmo.spare += tmp;
+ vio_cmo.reserve.size += tmp;
+ delta -= tmp;
+ }
+
+ /* Remaining new allocation goes to the excess pool */
+ vio_cmo.entitled += delta;
+ vio_cmo.excess.size += delta;
+ vio_cmo.excess.free += delta;
+
+ goto out;
+ }
+
+ /* Entitlement decreases */
+ delta = vio_cmo.entitled - new_entitlement;
+ avail = vio_cmo.excess.free;
+
+ /*
+ * Need to check how much unused entitlement each device can
+ * sacrifice to fulfill entitlement change.
+ */
+ list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
+ if (avail >= delta)
+ break;
+
+ viodev = dev_ent->viodev;
+ if ((viodev->cmo.entitled > viodev->cmo.allocated) &&
+ (viodev->cmo.entitled > VIO_CMO_MIN_ENT))
+ avail += viodev->cmo.entitled -
+ max_t(size_t, viodev->cmo.allocated,
+ VIO_CMO_MIN_ENT);
+ }
+
+ if (delta <= avail) {
+ vio_cmo.entitled -= delta;
+
+ /* Take entitlement from the excess pool first */
+ tmp = min(vio_cmo.excess.free, delta);
+ vio_cmo.excess.size -= tmp;
+ vio_cmo.excess.free -= tmp;
+ delta -= tmp;
+
+ /*
+ * Remove all but VIO_CMO_MIN_ENT bytes from devices
+ * until entitlement change is served
+ */
+ list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
+ if (!delta)
+ break;
+
+ viodev = dev_ent->viodev;
+ tmp = 0;
+ if ((viodev->cmo.entitled > viodev->cmo.allocated) &&
+ (viodev->cmo.entitled > VIO_CMO_MIN_ENT))
+ tmp = viodev->cmo.entitled -
+ max_t(size_t, viodev->cmo.allocated,
+ VIO_CMO_MIN_ENT);
+ viodev->cmo.entitled -= min(tmp, delta);
+ delta -= min(tmp, delta);
+ }
+ } else {
+ spin_unlock_irqrestore(&vio_cmo.lock, flags);
+ return -ENOMEM;
+ }
+
+out:
+ schedule_delayed_work(&vio_cmo.balance_q, 0);
+ spin_unlock_irqrestore(&vio_cmo.lock, flags);
+ return 0;
+}
+
+/**
+ * vio_cmo_balance - Balance entitlement among devices
+ *
+ * @work: work queue structure for this operation
+ *
+ * Any system entitlement above the minimum needed for devices, or
+ * already allocated to devices, can be distributed to the devices.
+ * The list of devices is iterated through to recalculate the desired
+ * entitlement level and to determine how much entitlement above the
+ * minimum entitlement is allocated to devices.
+ *
+ * Small chunks of the available entitlement are given to devices until
+ * their requirements are fulfilled or there is no entitlement left to give.
+ * Upon completion sizes of the reserve and excess pools are calculated.
+ *
+ * The system minimum entitlement level is also recalculated here.
+ * Entitlement will be reserved for devices even after vio_bus_remove to
+ * accommodate reloading the driver. The OF tree is walked to count the
+ * number of devices present and this will remove entitlement for devices
+ * that have actually left the system after having vio_bus_remove called.
+ */
+static void vio_cmo_balance(struct work_struct *work)
+{
+ struct vio_cmo *cmo;
+ struct vio_dev *viodev;
+ struct vio_cmo_dev_entry *dev_ent;
+ unsigned long flags;
+ size_t avail = 0, level, chunk, need;
+ int devcount = 0, fulfilled;
+
+ cmo = container_of(work, struct vio_cmo, balance_q.work);
+
+ spin_lock_irqsave(&vio_cmo.lock, flags);
+
+ /* Calculate minimum entitlement and fulfill spare */
+ cmo->min = vio_cmo_num_OF_devs() * VIO_CMO_MIN_ENT;
+ BUG_ON(cmo->min > cmo->entitled);
+ cmo->spare = min_t(size_t, VIO_CMO_MIN_ENT, (cmo->entitled - cmo->min));
+ cmo->min += cmo->spare;
+ cmo->desired = cmo->min;
+
+ /*
+ * Determine how much entitlement is available and reset device
+ * entitlements
+ */
+ avail = cmo->entitled - cmo->spare;
+ list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
+ viodev = dev_ent->viodev;
+ devcount++;
+ viodev->cmo.entitled = VIO_CMO_MIN_ENT;
+ cmo->desired += (viodev->cmo.desired - VIO_CMO_MIN_ENT);
+ avail -= max_t(size_t, viodev->cmo.allocated, VIO_CMO_MIN_ENT);
+ }
+
+ /*
+ * Having provided each device with the minimum entitlement, loop
+ * over the devices portioning out the remaining entitlement
+ * until there is nothing left.
+ */
+ level = VIO_CMO_MIN_ENT;
+ while (avail) {
+ fulfilled = 0;
+ list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
+ viodev = dev_ent->viodev;
+
+ if (viodev->cmo.desired <= level) {
+ fulfilled++;
+ continue;
+ }
+
+ /*
+ * Give the device up to VIO_CMO_BALANCE_CHUNK
+ * bytes of entitlement, but do not exceed the
+ * desired level of entitlement for the device.
+ */
+ chunk = min_t(size_t, avail, VIO_CMO_BALANCE_CHUNK);
+ chunk = min(chunk, (viodev->cmo.desired -
+ viodev->cmo.entitled));
+ viodev->cmo.entitled += chunk;
+
+ /*
+ * If the memory for this entitlement increase was
+ * already allocated to the device it does not come
+ * from the available pool being portioned out.
+ */
+ need = max(viodev->cmo.allocated, viodev->cmo.entitled)-
+ max(viodev->cmo.allocated, level);
+ avail -= need;
+
+ }
+ if (fulfilled == devcount)
+ break;
+ level += VIO_CMO_BALANCE_CHUNK;
+ }
+
+ /* Calculate new reserve and excess pool sizes */
+ cmo->reserve.size = cmo->min;
+ cmo->excess.free = 0;
+ cmo->excess.size = 0;
+ need = 0;
+ list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
+ viodev = dev_ent->viodev;
+ /* Calculated reserve size above the minimum entitlement */
+ if (viodev->cmo.entitled)
+ cmo->reserve.size += (viodev->cmo.entitled -
+ VIO_CMO_MIN_ENT);
+ /* Calculated used excess entitlement */
+ if (viodev->cmo.allocated > viodev->cmo.entitled)
+ need += viodev->cmo.allocated - viodev->cmo.entitled;
+ }
+ cmo->excess.size = cmo->entitled - cmo->reserve.size;
+ cmo->excess.free = cmo->excess.size - need;
+
+ cancel_delayed_work(container_of(work, struct delayed_work, work));
+ spin_unlock_irqrestore(&vio_cmo.lock, flags);
+}
+
+static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
+{
+ struct vio_dev *viodev = to_vio_dev(dev);
+ void *ret;
+
+ if (vio_cmo_alloc(viodev, roundup(size, IOMMU_PAGE_SIZE))) {
+ atomic_inc(&viodev->cmo.allocs_failed);
+ return NULL;
+ }
+
+ ret = dma_iommu_ops.alloc_coherent(dev, size, dma_handle, flag);
+ if (unlikely(ret == NULL)) {
+ vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
+ atomic_inc(&viodev->cmo.allocs_failed);
+ }
+
+ return ret;
+}
+
+static void vio_dma_iommu_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ struct vio_dev *viodev = to_vio_dev(dev);
+
+ dma_iommu_ops.free_coherent(dev, size, vaddr, dma_handle);
+
+ vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
+}
+
+static dma_addr_t vio_dma_iommu_map_single(struct device *dev, void *vaddr,
+ size_t size,
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ struct vio_dev *viodev = to_vio_dev(dev);
+ dma_addr_t ret = DMA_ERROR_CODE;
+
+ if (vio_cmo_alloc(viodev, roundup(size, IOMMU_PAGE_SIZE))) {
+ atomic_inc(&viodev->cmo.allocs_failed);
+ return ret;
+ }
+
+ ret = dma_iommu_ops.map_single(dev, vaddr, size, direction, attrs);
+ if (unlikely(dma_mapping_error(ret))) {
+ vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
+ atomic_inc(&viodev->cmo.allocs_failed);
+ }
+
+ return ret;
+}
+
+static void vio_dma_iommu_unmap_single(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ struct vio_dev *viodev = to_vio_dev(dev);
+
+ dma_iommu_ops.unmap_single(dev, dma_handle, size, direction, attrs);
+
+ vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
+}
+
+static int vio_dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
+ int nelems, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ struct vio_dev *viodev = to_vio_dev(dev);
+ struct scatterlist *sgl;
+ int ret, count = 0;
+ size_t alloc_size = 0;
+
+ for (sgl = sglist; count < nelems; count++, sgl++)
+ alloc_size += roundup(sgl->length, IOMMU_PAGE_SIZE);
+
+ if (vio_cmo_alloc(viodev, alloc_size)) {
+ atomic_inc(&viodev->cmo.allocs_failed);
+ return 0;
+ }
+
+ ret = dma_iommu_ops.map_sg(dev, sglist, nelems, direction, attrs);
+
+ if (unlikely(!ret)) {
+ vio_cmo_dealloc(viodev, alloc_size);
+ atomic_inc(&viodev->cmo.allocs_failed);
+ }
+
+ for (sgl = sglist, count = 0; count < ret; count++, sgl++)
+ alloc_size -= roundup(sgl->dma_length, IOMMU_PAGE_SIZE);
+ if (alloc_size)
+ vio_cmo_dealloc(viodev, alloc_size);
+
+ return ret;
+}
+
+static void vio_dma_iommu_unmap_sg(struct device *dev,
+ struct scatterlist *sglist, int nelems,
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ struct vio_dev *viodev = to_vio_dev(dev);
+ struct scatterlist *sgl;
+ size_t alloc_size = 0;
+ int count = 0;
+
+ for (sgl = sglist; count < nelems; count++, sgl++)
+ alloc_size += roundup(sgl->dma_length, IOMMU_PAGE_SIZE);
+
+ dma_iommu_ops.unmap_sg(dev, sglist, nelems, direction, attrs);
+
+ vio_cmo_dealloc(viodev, alloc_size);
+}
+
+struct dma_mapping_ops vio_dma_mapping_ops = {
+ .alloc_coherent = vio_dma_iommu_alloc_coherent,
+ .free_coherent = vio_dma_iommu_free_coherent,
+ .map_single = vio_dma_iommu_map_single,
+ .unmap_single = vio_dma_iommu_unmap_single,
+ .map_sg = vio_dma_iommu_map_sg,
+ .unmap_sg = vio_dma_iommu_unmap_sg,
+};
+
+/**
+ * vio_cmo_set_dev_desired - Set desired entitlement for a device
+ *
+ * @viodev: struct vio_dev for device to alter
+ * @new_desired: new desired entitlement level in bytes
+ *
+ * For use by devices to request a change to their entitlement at runtime or
+ * through sysfs. The desired entitlement level is changed and a balancing
+ * of system resources is scheduled to run in the future.
+ */
+void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired)
+{
+ unsigned long flags;
+ struct vio_cmo_dev_entry *dev_ent;
+ int found = 0;
+
+ if (!firmware_has_feature(FW_FEATURE_CMO))
+ return;
+
+ spin_lock_irqsave(&vio_cmo.lock, flags);
+ if (desired < VIO_CMO_MIN_ENT)
+ desired = VIO_CMO_MIN_ENT;
+
+ /*
+ * Changes will not be made for devices not in the device list.
+ * If it is not in the device list, then no driver is loaded
+ * for the device and it can not receive entitlement.
+ */
+ list_for_each_entry(dev_ent, &vio_cmo.device_list, list)
+ if (viodev == dev_ent->viodev) {
+ found = 1;
+ break;
+ }
+ if (!found)
+ return;
+
+ /* Increase/decrease in desired device entitlement */
+ if (desired >= viodev->cmo.desired) {
+ /* Just bump the bus and device values prior to a balance*/
+ vio_cmo.desired += desired - viodev->cmo.desired;
+ viodev->cmo.desired = desired;
+ } else {
+ /* Decrease bus and device values for desired entitlement */
+ vio_cmo.desired -= viodev->cmo.desired - desired;
+ viodev->cmo.desired = desired;
+ /*
+ * If less entitlement is desired than current entitlement, move
+ * any reserve memory in the change region to the excess pool.
+ */
+ if (viodev->cmo.entitled > desired) {
+ vio_cmo.reserve.size -= viodev->cmo.entitled - desired;
+ vio_cmo.excess.size += viodev->cmo.entitled - desired;
+ /*
+ * If entitlement moving from the reserve pool to the
+ * excess pool is currently unused, add to the excess
+ * free counter.
+ */
+ if (viodev->cmo.allocated < viodev->cmo.entitled)
+ vio_cmo.excess.free += viodev->cmo.entitled -
+ max(viodev->cmo.allocated, desired);
+ viodev->cmo.entitled = desired;
+ }
+ }
+ schedule_delayed_work(&vio_cmo.balance_q, 0);
+ spin_unlock_irqrestore(&vio_cmo.lock, flags);
+}
+
+/**
+ * vio_cmo_bus_probe - Handle CMO specific bus probe activities
+ *
+ * @viodev - Pointer to struct vio_dev for device
+ *
+ * Determine the devices IO memory entitlement needs, attempting
+ * to satisfy the system minimum entitlement at first and scheduling
+ * a balance operation to take care of the rest at a later time.
+ *
+ * Returns: 0 on success, -EINVAL when device doesn't support CMO, and
+ * -ENOMEM when entitlement is not available for device or
+ * device entry.
+ *
+ */
+static int vio_cmo_bus_probe(struct vio_dev *viodev)
+{
+ struct vio_cmo_dev_entry *dev_ent;
+ struct device *dev = &viodev->dev;
+ struct vio_driver *viodrv = to_vio_driver(dev->driver);
+ unsigned long flags;
+ size_t size;
+
+ /*
+ * Check to see that device has a DMA window and configure
+ * entitlement for the device.
+ */
+ if (of_get_property(viodev->dev.archdata.of_node,
+ "ibm,my-dma-window", NULL)) {
+ /* Check that the driver is CMO enabled and get desired DMA */
+ if (!viodrv->get_desired_dma) {
+ dev_err(dev, "%s: device driver does not support CMO\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ viodev->cmo.desired = IOMMU_PAGE_ALIGN(viodrv->get_desired_dma(viodev));
+ if (viodev->cmo.desired < VIO_CMO_MIN_ENT)
+ viodev->cmo.desired = VIO_CMO_MIN_ENT;
+ size = VIO_CMO_MIN_ENT;
+
+ dev_ent = kmalloc(sizeof(struct vio_cmo_dev_entry),
+ GFP_KERNEL);
+ if (!dev_ent)
+ return -ENOMEM;
+
+ dev_ent->viodev = viodev;
+ spin_lock_irqsave(&vio_cmo.lock, flags);
+ list_add(&dev_ent->list, &vio_cmo.device_list);
+ } else {
+ viodev->cmo.desired = 0;
+ size = 0;
+ spin_lock_irqsave(&vio_cmo.lock, flags);
+ }
+
+ /*
+ * If the needs for vio_cmo.min have not changed since they
+ * were last set, the number of devices in the OF tree has
+ * been constant and the IO memory for this is already in
+ * the reserve pool.
+ */
+ if (vio_cmo.min == ((vio_cmo_num_OF_devs() + 1) *
+ VIO_CMO_MIN_ENT)) {
+ /* Updated desired entitlement if device requires it */
+ if (size)
+ vio_cmo.desired += (viodev->cmo.desired -
+ VIO_CMO_MIN_ENT);
+ } else {
+ size_t tmp;
+
+ tmp = vio_cmo.spare + vio_cmo.excess.free;
+ if (tmp < size) {
+ dev_err(dev, "%s: insufficient free "
+ "entitlement to add device. "
+ "Need %lu, have %lu\n", __func__,
+ size, (vio_cmo.spare + tmp));
+ spin_unlock_irqrestore(&vio_cmo.lock, flags);
+ return -ENOMEM;
+ }
+
+ /* Use excess pool first to fulfill request */
+ tmp = min(size, vio_cmo.excess.free);
+ vio_cmo.excess.free -= tmp;
+ vio_cmo.excess.size -= tmp;
+ vio_cmo.reserve.size += tmp;
+
+ /* Use spare if excess pool was insufficient */
+ vio_cmo.spare -= size - tmp;
+
+ /* Update bus accounting */
+ vio_cmo.min += size;
+ vio_cmo.desired += viodev->cmo.desired;
+ }
+ spin_unlock_irqrestore(&vio_cmo.lock, flags);
+ return 0;
+}
+
+/**
+ * vio_cmo_bus_remove - Handle CMO specific bus removal activities
+ *
+ * @viodev - Pointer to struct vio_dev for device
+ *
+ * Remove the device from the cmo device list. The minimum entitlement
+ * will be reserved for the device as long as it is in the system. The
+ * rest of the entitlement the device had been allocated will be returned
+ * to the system.
+ */
+static void vio_cmo_bus_remove(struct vio_dev *viodev)
+{
+ struct vio_cmo_dev_entry *dev_ent;
+ unsigned long flags;
+ size_t tmp;
+
+ spin_lock_irqsave(&vio_cmo.lock, flags);
+ if (viodev->cmo.allocated) {
+ dev_err(&viodev->dev, "%s: device had %lu bytes of IO "
+ "allocated after remove operation.\n",
+ __func__, viodev->cmo.allocated);
+ BUG();
+ }
+
+ /*
+ * Remove the device from the device list being maintained for
+ * CMO enabled devices.
+ */
+ list_for_each_entry(dev_ent, &vio_cmo.device_list, list)
+ if (viodev == dev_ent->viodev) {
+ list_del(&dev_ent->list);
+ kfree(dev_ent);
+ break;
+ }
+
+ /*
+ * Devices may not require any entitlement and they do not need
+ * to be processed. Otherwise, return the device's entitlement
+ * back to the pools.
+ */
+ if (viodev->cmo.entitled) {
+ /*
+ * This device has not yet left the OF tree, it's
+ * minimum entitlement remains in vio_cmo.min and
+ * vio_cmo.desired
+ */
+ vio_cmo.desired -= (viodev->cmo.desired - VIO_CMO_MIN_ENT);
+
+ /*
+ * Save min allocation for device in reserve as long
+ * as it exists in OF tree as determined by later
+ * balance operation
+ */
+ viodev->cmo.entitled -= VIO_CMO_MIN_ENT;
+
+ /* Replenish spare from freed reserve pool */
+ if (viodev->cmo.entitled && (vio_cmo.spare < VIO_CMO_MIN_ENT)) {
+ tmp = min(viodev->cmo.entitled, (VIO_CMO_MIN_ENT -
+ vio_cmo.spare));
+ vio_cmo.spare += tmp;
+ viodev->cmo.entitled -= tmp;
+ }
+
+ /* Remaining reserve goes to excess pool */
+ vio_cmo.excess.size += viodev->cmo.entitled;
+ vio_cmo.excess.free += viodev->cmo.entitled;
+ vio_cmo.reserve.size -= viodev->cmo.entitled;
+
+ /*
+ * Until the device is removed it will keep a
+ * minimum entitlement; this will guarantee that
+ * a module unload/load will result in a success.
+ */
+ viodev->cmo.entitled = VIO_CMO_MIN_ENT;
+ viodev->cmo.desired = VIO_CMO_MIN_ENT;
+ atomic_set(&viodev->cmo.allocs_failed, 0);
+ }
+
+ spin_unlock_irqrestore(&vio_cmo.lock, flags);
+}
+
+static void vio_cmo_set_dma_ops(struct vio_dev *viodev)
+{
+ vio_dma_mapping_ops.dma_supported = dma_iommu_ops.dma_supported;
+ viodev->dev.archdata.dma_ops = &vio_dma_mapping_ops;
+}
+
+/**
+ * vio_cmo_bus_init - CMO entitlement initialization at bus init time
+ *
+ * Set up the reserve and excess entitlement pools based on available
+ * system entitlement and the number of devices in the OF tree that
+ * require entitlement in the reserve pool.
+ */
+static void vio_cmo_bus_init(void)
+{
+ struct hvcall_mpp_data mpp_data;
+ int err;
+
+ memset(&vio_cmo, 0, sizeof(struct vio_cmo));
+ spin_lock_init(&vio_cmo.lock);
+ INIT_LIST_HEAD(&vio_cmo.device_list);
+ INIT_DELAYED_WORK(&vio_cmo.balance_q, vio_cmo_balance);
+
+ /* Get current system entitlement */
+ err = h_get_mpp(&mpp_data);
+
+ /*
+ * On failure, continue with entitlement set to 0, will panic()
+ * later when spare is reserved.
+ */
+ if (err != H_SUCCESS) {
+ printk(KERN_ERR "%s: unable to determine system IO "\
+ "entitlement. (%d)\n", __func__, err);
+ vio_cmo.entitled = 0;
+ } else {
+ vio_cmo.entitled = mpp_data.entitled_mem;
+ }
+
+ /* Set reservation and check against entitlement */
+ vio_cmo.spare = VIO_CMO_MIN_ENT;
+ vio_cmo.reserve.size = vio_cmo.spare;
+ vio_cmo.reserve.size += (vio_cmo_num_OF_devs() *
+ VIO_CMO_MIN_ENT);
+ if (vio_cmo.reserve.size > vio_cmo.entitled) {
+ printk(KERN_ERR "%s: insufficient system entitlement\n",
+ __func__);
+ panic("%s: Insufficient system entitlement", __func__);
+ }
+
+ /* Set the remaining accounting variables */
+ vio_cmo.excess.size = vio_cmo.entitled - vio_cmo.reserve.size;
+ vio_cmo.excess.free = vio_cmo.excess.size;
+ vio_cmo.min = vio_cmo.reserve.size;
+ vio_cmo.desired = vio_cmo.reserve.size;
+}
+
+/* sysfs device functions and data structures for CMO */
+
+#define viodev_cmo_rd_attr(name) \
+static ssize_t viodev_cmo_##name##_show(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ return sprintf(buf, "%lu\n", to_vio_dev(dev)->cmo.name); \
+}
+
+static ssize_t viodev_cmo_allocs_failed_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct vio_dev *viodev = to_vio_dev(dev);
+ return sprintf(buf, "%d\n", atomic_read(&viodev->cmo.allocs_failed));
+}
+
+static ssize_t viodev_cmo_allocs_failed_reset(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct vio_dev *viodev = to_vio_dev(dev);
+ atomic_set(&viodev->cmo.allocs_failed, 0);
+ return count;
+}
+
+static ssize_t viodev_cmo_desired_set(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct vio_dev *viodev = to_vio_dev(dev);
+ size_t new_desired;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &new_desired);
+ if (ret)
+ return ret;
+
+ vio_cmo_set_dev_desired(viodev, new_desired);
+ return count;
+}
+
+viodev_cmo_rd_attr(desired);
+viodev_cmo_rd_attr(entitled);
+viodev_cmo_rd_attr(allocated);
+
+static ssize_t name_show(struct device *, struct device_attribute *, char *);
+static ssize_t devspec_show(struct device *, struct device_attribute *, char *);
+static struct device_attribute vio_cmo_dev_attrs[] = {
+ __ATTR_RO(name),
+ __ATTR_RO(devspec),
+ __ATTR(cmo_desired, S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH,
+ viodev_cmo_desired_show, viodev_cmo_desired_set),
+ __ATTR(cmo_entitled, S_IRUGO, viodev_cmo_entitled_show, NULL),
+ __ATTR(cmo_allocated, S_IRUGO, viodev_cmo_allocated_show, NULL),
+ __ATTR(cmo_allocs_failed, S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH,
+ viodev_cmo_allocs_failed_show, viodev_cmo_allocs_failed_reset),
+ __ATTR_NULL
+};
+
+/* sysfs bus functions and data structures for CMO */
+
+#define viobus_cmo_rd_attr(name) \
+static ssize_t \
+viobus_cmo_##name##_show(struct bus_type *bt, char *buf) \
+{ \
+ return sprintf(buf, "%lu\n", vio_cmo.name); \
+}
+
+#define viobus_cmo_pool_rd_attr(name, var) \
+static ssize_t \
+viobus_cmo_##name##_pool_show_##var(struct bus_type *bt, char *buf) \
+{ \
+ return sprintf(buf, "%lu\n", vio_cmo.name.var); \
+}
+
+static ssize_t viobus_cmo_high_reset(struct bus_type *bt, const char *buf,
+ size_t count)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&vio_cmo.lock, flags);
+ vio_cmo.high = vio_cmo.curr;
+ spin_unlock_irqrestore(&vio_cmo.lock, flags);
+
+ return count;
+}
+
+viobus_cmo_rd_attr(entitled);
+viobus_cmo_pool_rd_attr(reserve, size);
+viobus_cmo_pool_rd_attr(excess, size);
+viobus_cmo_pool_rd_attr(excess, free);
+viobus_cmo_rd_attr(spare);
+viobus_cmo_rd_attr(min);
+viobus_cmo_rd_attr(desired);
+viobus_cmo_rd_attr(curr);
+viobus_cmo_rd_attr(high);
+
+static struct bus_attribute vio_cmo_bus_attrs[] = {
+ __ATTR(cmo_entitled, S_IRUGO, viobus_cmo_entitled_show, NULL),
+ __ATTR(cmo_reserve_size, S_IRUGO, viobus_cmo_reserve_pool_show_size, NULL),
+ __ATTR(cmo_excess_size, S_IRUGO, viobus_cmo_excess_pool_show_size, NULL),
+ __ATTR(cmo_excess_free, S_IRUGO, viobus_cmo_excess_pool_show_free, NULL),
+ __ATTR(cmo_spare, S_IRUGO, viobus_cmo_spare_show, NULL),
+ __ATTR(cmo_min, S_IRUGO, viobus_cmo_min_show, NULL),
+ __ATTR(cmo_desired, S_IRUGO, viobus_cmo_desired_show, NULL),
+ __ATTR(cmo_curr, S_IRUGO, viobus_cmo_curr_show, NULL),
+ __ATTR(cmo_high, S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH,
+ viobus_cmo_high_show, viobus_cmo_high_reset),
+ __ATTR_NULL
+};
+
+static void vio_cmo_sysfs_init(void)
+{
+ vio_bus_type.dev_attrs = vio_cmo_dev_attrs;
+ vio_bus_type.bus_attrs = vio_cmo_bus_attrs;
+}
+#else /* CONFIG_PPC_SMLPAR */
+/* Dummy functions for iSeries platform */
+int vio_cmo_entitlement_update(size_t new_entitlement) { return 0; }
+void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired) {}
+static int vio_cmo_bus_probe(struct vio_dev *viodev) { return 0; }
+static void vio_cmo_bus_remove(struct vio_dev *viodev) {}
+static void vio_cmo_set_dma_ops(struct vio_dev *viodev) {}
+static void vio_cmo_bus_init() {}
+static void vio_cmo_sysfs_init() { }
+#endif /* CONFIG_PPC_SMLPAR */
+EXPORT_SYMBOL(vio_cmo_entitlement_update);
+EXPORT_SYMBOL(vio_cmo_set_dev_desired);
+
static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
{
const unsigned char *dma_window;
@@ -114,8 +1105,17 @@ static int vio_bus_probe(struct device *dev)
return error;
id = vio_match_device(viodrv->id_table, viodev);
- if (id)
+ if (id) {
+ memset(&viodev->cmo, 0, sizeof(viodev->cmo));
+ if (firmware_has_feature(FW_FEATURE_CMO)) {
+ error = vio_cmo_bus_probe(viodev);
+ if (error)
+ return error;
+ }
error = viodrv->probe(viodev, id);
+ if (error)
+ vio_cmo_bus_remove(viodev);
+ }
return error;
}
@@ -125,12 +1125,23 @@ static int vio_bus_remove(struct device *dev)
{
struct vio_dev *viodev = to_vio_dev(dev);
struct vio_driver *viodrv = to_vio_driver(dev->driver);
+ struct device *devptr;
+ int ret = 1;
+
+ /*
+ * Hold a reference to the device after the remove function is called
+ * to allow for CMO accounting cleanup for the device.
+ */
+ devptr = get_device(dev);
if (viodrv->remove)
- return viodrv->remove(viodev);
+ ret = viodrv->remove(viodev);
+
+ if (!ret && firmware_has_feature(FW_FEATURE_CMO))
+ vio_cmo_bus_remove(viodev);
- /* driver can't remove */
- return 1;
+ put_device(devptr);
+ return ret;
}
/**
@@ -215,7 +1226,11 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
viodev->unit_address = *unit_address;
}
viodev->dev.archdata.of_node = of_node_get(of_node);
- viodev->dev.archdata.dma_ops = &dma_iommu_ops;
+
+ if (firmware_has_feature(FW_FEATURE_CMO))
+ vio_cmo_set_dma_ops(viodev);
+ else
+ viodev->dev.archdata.dma_ops = &dma_iommu_ops;
viodev->dev.archdata.dma_data = vio_build_iommu_table(viodev);
viodev->dev.archdata.numa_node = of_node_to_nid(of_node);
@@ -245,6 +1260,9 @@ static int __init vio_bus_init(void)
int err;
struct device_node *node_vroot;
+ if (firmware_has_feature(FW_FEATURE_CMO))
+ vio_cmo_sysfs_init();
+
err = bus_register(&vio_bus_type);
if (err) {
printk(KERN_ERR "failed to register VIO bus\n");
@@ -262,6 +1280,9 @@ static int __init vio_bus_init(void)
return err;
}
+ if (firmware_has_feature(FW_FEATURE_CMO))
+ vio_cmo_bus_init();
+
node_vroot = of_find_node_by_name(NULL, "vdevice");
if (node_vroot) {
struct device_node *of_node;
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 87a72c66ce2..4a8ce62fe11 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -9,6 +9,25 @@
ENTRY(_stext)
+PHDRS {
+ kernel PT_LOAD FLAGS(7); /* RWX */
+ notes PT_NOTE FLAGS(0);
+ dummy PT_NOTE FLAGS(0);
+
+ /* binutils < 2.18 has a bug that makes it misbehave when taking an
+ ELF file with all segments at load address 0 as input. This
+ happens when running "strip" on vmlinux, because of the AT() magic
+ in this linker script. People using GCC >= 4.2 won't run into
+ this problem, because the "build-id" support will put some data
+ into the "notes" segment (at a non-zero load address).
+
+ To work around this, we force some data into both the "dummy"
+ segment and the kernel segment, so the dummy segment will get a
+ non-zero load address. It's not enough to always create the
+ "notes" segment, since if nothing gets assigned to it, its load
+ address will be zero. */
+}
+
#ifdef CONFIG_PPC64
OUTPUT_ARCH(powerpc:common64)
jiffies = jiffies_64;
@@ -50,7 +69,7 @@ SECTIONS
. = ALIGN(PAGE_SIZE);
_etext = .;
PROVIDE32 (etext = .);
- }
+ } :kernel
/* Read-only data */
RODATA
@@ -62,7 +81,13 @@ SECTIONS
__stop___ex_table = .;
}
- NOTES
+ NOTES :kernel :notes
+
+ /* The dummy segment contents for the bug workaround mentioned above
+ near PHDRS. */
+ .dummy : AT(ADDR(.dummy) - LOAD_OFFSET) {
+ LONG(0xf177)
+ } :kernel :dummy
/*
* Init sections discarded at runtime
@@ -74,7 +99,7 @@ SECTIONS
_sinittext = .;
INIT_TEXT
_einittext = .;
- }
+ } :kernel
/* .exit.text is discarded at runtime, not link time,
* to deal with references from __bug_table
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 0559fe086eb..7c975d43e3f 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
+#include <linux/mm.h>
#include <asm/page.h>
#include <asm/code-patching.h>
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index 4e43702b981..8c5a03be31e 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -99,7 +99,7 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
for (; fcur < fend; fcur++) {
if (patch_feature_section(value, fcur)) {
- __WARN();
+ WARN_ON(1);
printk("Unable to patch feature section at %p - %p" \
" with %p - %p\n",
calc_addr(fcur, fcur->start_off),
diff --git a/arch/powerpc/lib/string.S b/arch/powerpc/lib/string.S
index 49eb1f1a2bb..64e2e499e32 100644
--- a/arch/powerpc/lib/string.S
+++ b/arch/powerpc/lib/string.S
@@ -13,13 +13,7 @@
#include <asm/ppc_asm.h>
.section __ex_table,"a"
-#ifdef CONFIG_PPC64
- .align 3
-#define EXTBL .llong
-#else
- .align 2
-#define EXTBL .long
-#endif
+ PPC_LONG_ALIGN
.text
_GLOBAL(strcpy)
@@ -160,9 +154,9 @@ _GLOBAL(__clear_user)
blr
.section __ex_table,"a"
- EXTBL 11b,90b
- EXTBL 1b,91b
- EXTBL 8b,92b
+ PPC_LONG 11b,90b
+ PPC_LONG 1b,91b
+ PPC_LONG 8b,92b
.text
_GLOBAL(__strncpy_from_user)
@@ -183,7 +177,7 @@ _GLOBAL(__strncpy_from_user)
blr
.section __ex_table,"a"
- EXTBL 1b,99b
+ PPC_LONG 1b,99b
.text
/* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
@@ -208,4 +202,4 @@ _GLOBAL(__strnlen_user)
blr
.section __ex_table,"a"
- EXTBL 1b,99b
+ PPC_LONG 1b,99b
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 1707d00331f..565b7a237c8 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -100,31 +100,6 @@ static int store_updates_sp(struct pt_regs *regs)
return 0;
}
-#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
-static void do_dabr(struct pt_regs *regs, unsigned long address,
- unsigned long error_code)
-{
- siginfo_t info;
-
- if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
- 11, SIGSEGV) == NOTIFY_STOP)
- return;
-
- if (debugger_dabr_match(regs))
- return;
-
- /* Clear the DABR */
- set_dabr(0);
-
- /* Deliver the signal to userspace */
- info.si_signo = SIGTRAP;
- info.si_errno = 0;
- info.si_code = TRAP_HWBKPT;
- info.si_addr = (void __user *)address;
- force_sig_info(SIGTRAP, &info, current);
-}
-#endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
-
/*
* For 600- and 800-family processors, the error_code parameter is DSISR
* for a data fault, SRR1 for an instruction fault. For 400-family processors
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 8d3b58ebd38..5ce5a4dcd00 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -68,6 +68,7 @@
#define KB (1024)
#define MB (1024*KB)
+#define GB (1024L*MB)
/*
* Note: pte --> Linux PTE
@@ -102,7 +103,6 @@ int mmu_kernel_ssize = MMU_SEGSIZE_256M;
int mmu_highuser_ssize = MMU_SEGSIZE_256M;
u16 mmu_slb_size = 64;
#ifdef CONFIG_HUGETLB_PAGE
-int mmu_huge_psize = MMU_PAGE_16M;
unsigned int HPAGE_SHIFT;
#endif
#ifdef CONFIG_PPC_64K_PAGES
@@ -329,6 +329,44 @@ static int __init htab_dt_scan_page_sizes(unsigned long node,
return 0;
}
+/* Scan for 16G memory blocks that have been set aside for huge pages
+ * and reserve those blocks for 16G huge pages.
+ */
+static int __init htab_dt_scan_hugepage_blocks(unsigned long node,
+ const char *uname, int depth,
+ void *data) {
+ char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+ unsigned long *addr_prop;
+ u32 *page_count_prop;
+ unsigned int expected_pages;
+ long unsigned int phys_addr;
+ long unsigned int block_size;
+
+ /* We are scanning "memory" nodes only */
+ if (type == NULL || strcmp(type, "memory") != 0)
+ return 0;
+
+ /* This property is the log base 2 of the number of virtual pages that
+ * will represent this memory block. */
+ page_count_prop = of_get_flat_dt_prop(node, "ibm,expected#pages", NULL);
+ if (page_count_prop == NULL)
+ return 0;
+ expected_pages = (1 << page_count_prop[0]);
+ addr_prop = of_get_flat_dt_prop(node, "reg", NULL);
+ if (addr_prop == NULL)
+ return 0;
+ phys_addr = addr_prop[0];
+ block_size = addr_prop[1];
+ if (block_size != (16 * GB))
+ return 0;
+ printk(KERN_INFO "Huge page(16GB) memory: "
+ "addr = 0x%lX size = 0x%lX pages = %d\n",
+ phys_addr, block_size, expected_pages);
+ lmb_reserve(phys_addr, block_size * expected_pages);
+ add_gpage(phys_addr, block_size, expected_pages);
+ return 0;
+}
+
static void __init htab_init_page_sizes(void)
{
int rc;
@@ -418,15 +456,18 @@ static void __init htab_init_page_sizes(void)
);
#ifdef CONFIG_HUGETLB_PAGE
- /* Init large page size. Currently, we pick 16M or 1M depending
+ /* Reserve 16G huge page memory sections for huge pages */
+ of_scan_flat_dt(htab_dt_scan_hugepage_blocks, NULL);
+
+/* Set default large page size. Currently, we pick 16M or 1M depending
* on what is available
*/
if (mmu_psize_defs[MMU_PAGE_16M].shift)
- set_huge_psize(MMU_PAGE_16M);
+ HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_16M].shift;
/* With 4k/4level pagetables, we can't (for now) cope with a
* huge page size < PMD_SIZE */
else if (mmu_psize_defs[MMU_PAGE_1M].shift)
- set_huge_psize(MMU_PAGE_1M);
+ HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_1M].shift;
#endif /* CONFIG_HUGETLB_PAGE */
}
@@ -847,7 +888,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
#ifdef CONFIG_HUGETLB_PAGE
/* Handle hugepage regions */
- if (HPAGE_SHIFT && psize == mmu_huge_psize) {
+ if (HPAGE_SHIFT && mmu_huge_psizes[psize]) {
DBG_LOW(" -> huge page !\n");
return hash_huge_page(mm, access, ea, vsid, local, trap);
}
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 0d12fba31bc..fb42c4dd321 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -24,21 +24,43 @@
#include <asm/cputable.h>
#include <asm/spu.h>
-#define HPAGE_SHIFT_64K 16
-#define HPAGE_SHIFT_16M 24
+#define PAGE_SHIFT_64K 16
+#define PAGE_SHIFT_16M 24
+#define PAGE_SHIFT_16G 34
#define NUM_LOW_AREAS (0x100000000UL >> SID_SHIFT)
#define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT)
+#define MAX_NUMBER_GPAGES 1024
-unsigned int hugepte_shift;
-#define PTRS_PER_HUGEPTE (1 << hugepte_shift)
-#define HUGEPTE_TABLE_SIZE (sizeof(pte_t) << hugepte_shift)
+/* Tracks the 16G pages after the device tree is scanned and before the
+ * huge_boot_pages list is ready. */
+static unsigned long gpage_freearray[MAX_NUMBER_GPAGES];
+static unsigned nr_gpages;
-#define HUGEPD_SHIFT (HPAGE_SHIFT + hugepte_shift)
-#define HUGEPD_SIZE (1UL << HUGEPD_SHIFT)
-#define HUGEPD_MASK (~(HUGEPD_SIZE-1))
+/* Array of valid huge page sizes - non-zero value(hugepte_shift) is
+ * stored for the huge page sizes that are valid.
+ */
+unsigned int mmu_huge_psizes[MMU_PAGE_COUNT] = { }; /* initialize all to 0 */
+
+#define hugepte_shift mmu_huge_psizes
+#define PTRS_PER_HUGEPTE(psize) (1 << hugepte_shift[psize])
+#define HUGEPTE_TABLE_SIZE(psize) (sizeof(pte_t) << hugepte_shift[psize])
+
+#define HUGEPD_SHIFT(psize) (mmu_psize_to_shift(psize) \
+ + hugepte_shift[psize])
+#define HUGEPD_SIZE(psize) (1UL << HUGEPD_SHIFT(psize))
+#define HUGEPD_MASK(psize) (~(HUGEPD_SIZE(psize)-1))
+
+/* Subtract one from array size because we don't need a cache for 4K since
+ * is not a huge page size */
+#define huge_pgtable_cache(psize) (pgtable_cache[HUGEPTE_CACHE_NUM \
+ + psize-1])
+#define HUGEPTE_CACHE_NAME(psize) (huge_pgtable_cache_name[psize])
-#define huge_pgtable_cache (pgtable_cache[HUGEPTE_CACHE_NUM])
+static const char *huge_pgtable_cache_name[MMU_PAGE_COUNT] = {
+ "unused_4K", "hugepte_cache_64K", "unused_64K_AP",
+ "hugepte_cache_1M", "hugepte_cache_16M", "hugepte_cache_16G"
+};
/* Flag to mark huge PD pointers. This means pmd_bad() and pud_bad()
* will choke on pointers to hugepte tables, which is handy for
@@ -49,24 +71,49 @@ typedef struct { unsigned long pd; } hugepd_t;
#define hugepd_none(hpd) ((hpd).pd == 0)
+static inline int shift_to_mmu_psize(unsigned int shift)
+{
+ switch (shift) {
+#ifndef CONFIG_PPC_64K_PAGES
+ case PAGE_SHIFT_64K:
+ return MMU_PAGE_64K;
+#endif
+ case PAGE_SHIFT_16M:
+ return MMU_PAGE_16M;
+ case PAGE_SHIFT_16G:
+ return MMU_PAGE_16G;
+ }
+ return -1;
+}
+
+static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
+{
+ if (mmu_psize_defs[mmu_psize].shift)
+ return mmu_psize_defs[mmu_psize].shift;
+ BUG();
+}
+
static inline pte_t *hugepd_page(hugepd_t hpd)
{
BUG_ON(!(hpd.pd & HUGEPD_OK));
return (pte_t *)(hpd.pd & ~HUGEPD_OK);
}
-static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr)
+static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr,
+ struct hstate *hstate)
{
- unsigned long idx = ((addr >> HPAGE_SHIFT) & (PTRS_PER_HUGEPTE-1));
+ unsigned int shift = huge_page_shift(hstate);
+ int psize = shift_to_mmu_psize(shift);
+ unsigned long idx = ((addr >> shift) & (PTRS_PER_HUGEPTE(psize)-1));
pte_t *dir = hugepd_page(*hpdp);
return dir + idx;
}
static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
- unsigned long address)
+ unsigned long address, unsigned int psize)
{
- pte_t *new = kmem_cache_alloc(huge_pgtable_cache,
+ pte_t *new = kmem_cache_alloc(huge_pgtable_cache(psize),
GFP_KERNEL|__GFP_REPEAT);
if (! new)
@@ -74,7 +121,7 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
spin_lock(&mm->page_table_lock);
if (!hugepd_none(*hpdp))
- kmem_cache_free(huge_pgtable_cache, new);
+ kmem_cache_free(huge_pgtable_cache(psize), new);
else
hpdp->pd = (unsigned long)new | HUGEPD_OK;
spin_unlock(&mm->page_table_lock);
@@ -83,27 +130,60 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
/* Base page size affects how we walk hugetlb page tables */
#ifdef CONFIG_PPC_64K_PAGES
-#define hpmd_offset(pud, addr) pmd_offset(pud, addr)
-#define hpmd_alloc(mm, pud, addr) pmd_alloc(mm, pud, addr)
+#define hpmd_offset(pud, addr, h) pmd_offset(pud, addr)
+#define hpmd_alloc(mm, pud, addr, h) pmd_alloc(mm, pud, addr)
#else
static inline
-pmd_t *hpmd_offset(pud_t *pud, unsigned long addr)
+pmd_t *hpmd_offset(pud_t *pud, unsigned long addr, struct hstate *hstate)
{
- if (HPAGE_SHIFT == HPAGE_SHIFT_64K)
+ if (huge_page_shift(hstate) == PAGE_SHIFT_64K)
return pmd_offset(pud, addr);
else
return (pmd_t *) pud;
}
static inline
-pmd_t *hpmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr)
+pmd_t *hpmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr,
+ struct hstate *hstate)
{
- if (HPAGE_SHIFT == HPAGE_SHIFT_64K)
+ if (huge_page_shift(hstate) == PAGE_SHIFT_64K)
return pmd_alloc(mm, pud, addr);
else
return (pmd_t *) pud;
}
#endif
+/* Build list of addresses of gigantic pages. This function is used in early
+ * boot before the buddy or bootmem allocator is setup.
+ */
+void add_gpage(unsigned long addr, unsigned long page_size,
+ unsigned long number_of_pages)
+{
+ if (!addr)
+ return;
+ while (number_of_pages > 0) {
+ gpage_freearray[nr_gpages] = addr;
+ nr_gpages++;
+ number_of_pages--;
+ addr += page_size;
+ }
+}
+
+/* Moves the gigantic page addresses from the temporary list to the
+ * huge_boot_pages list.
+ */
+int alloc_bootmem_huge_page(struct hstate *hstate)
+{
+ struct huge_bootmem_page *m;
+ if (nr_gpages == 0)
+ return 0;
+ m = phys_to_virt(gpage_freearray[--nr_gpages]);
+ gpage_freearray[nr_gpages] = 0;
+ list_add(&m->list, &huge_boot_pages);
+ m->hstate = hstate;
+ return 1;
+}
+
+
/* Modelled after find_linux_pte() */
pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
{
@@ -111,39 +191,52 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
pud_t *pu;
pmd_t *pm;
- BUG_ON(get_slice_psize(mm, addr) != mmu_huge_psize);
+ unsigned int psize;
+ unsigned int shift;
+ unsigned long sz;
+ struct hstate *hstate;
+ psize = get_slice_psize(mm, addr);
+ shift = mmu_psize_to_shift(psize);
+ sz = ((1UL) << shift);
+ hstate = size_to_hstate(sz);
- addr &= HPAGE_MASK;
+ addr &= hstate->mask;
pg = pgd_offset(mm, addr);
if (!pgd_none(*pg)) {
pu = pud_offset(pg, addr);
if (!pud_none(*pu)) {
- pm = hpmd_offset(pu, addr);
+ pm = hpmd_offset(pu, addr, hstate);
if (!pmd_none(*pm))
- return hugepte_offset((hugepd_t *)pm, addr);
+ return hugepte_offset((hugepd_t *)pm, addr,
+ hstate);
}
}
return NULL;
}
-pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+ unsigned long addr, unsigned long sz)
{
pgd_t *pg;
pud_t *pu;
pmd_t *pm;
hugepd_t *hpdp = NULL;
+ struct hstate *hstate;
+ unsigned int psize;
+ hstate = size_to_hstate(sz);
- BUG_ON(get_slice_psize(mm, addr) != mmu_huge_psize);
+ psize = get_slice_psize(mm, addr);
+ BUG_ON(!mmu_huge_psizes[psize]);
- addr &= HPAGE_MASK;
+ addr &= hstate->mask;
pg = pgd_offset(mm, addr);
pu = pud_alloc(mm, pg, addr);
if (pu) {
- pm = hpmd_alloc(mm, pu, addr);
+ pm = hpmd_alloc(mm, pu, addr, hstate);
if (pm)
hpdp = (hugepd_t *)pm;
}
@@ -151,10 +244,10 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
if (! hpdp)
return NULL;
- if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr))
+ if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr, psize))
return NULL;
- return hugepte_offset(hpdp, addr);
+ return hugepte_offset(hpdp, addr, hstate);
}
int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
@@ -162,19 +255,22 @@ int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
return 0;
}
-static void free_hugepte_range(struct mmu_gather *tlb, hugepd_t *hpdp)
+static void free_hugepte_range(struct mmu_gather *tlb, hugepd_t *hpdp,
+ unsigned int psize)
{
pte_t *hugepte = hugepd_page(*hpdp);
hpdp->pd = 0;
tlb->need_flush = 1;
- pgtable_free_tlb(tlb, pgtable_free_cache(hugepte, HUGEPTE_CACHE_NUM,
+ pgtable_free_tlb(tlb, pgtable_free_cache(hugepte,
+ HUGEPTE_CACHE_NUM+psize-1,
PGF_CACHENUM_MASK));
}
static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
unsigned long addr, unsigned long end,
- unsigned long floor, unsigned long ceiling)
+ unsigned long floor, unsigned long ceiling,
+ unsigned int psize)
{
pmd_t *pmd;
unsigned long next;
@@ -186,7 +282,7 @@ static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
next = pmd_addr_end(addr, end);
if (pmd_none(*pmd))
continue;
- free_hugepte_range(tlb, (hugepd_t *)pmd);
+ free_hugepte_range(tlb, (hugepd_t *)pmd, psize);
} while (pmd++, addr = next, addr != end);
start &= PUD_MASK;
@@ -212,6 +308,9 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
pud_t *pud;
unsigned long next;
unsigned long start;
+ unsigned int shift;
+ unsigned int psize = get_slice_psize(tlb->mm, addr);
+ shift = mmu_psize_to_shift(psize);
start = addr;
pud = pud_offset(pgd, addr);
@@ -220,16 +319,18 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
#ifdef CONFIG_PPC_64K_PAGES
if (pud_none_or_clear_bad(pud))
continue;
- hugetlb_free_pmd_range(tlb, pud, addr, next, floor, ceiling);
+ hugetlb_free_pmd_range(tlb, pud, addr, next, floor, ceiling,
+ psize);
#else
- if (HPAGE_SHIFT == HPAGE_SHIFT_64K) {
+ if (shift == PAGE_SHIFT_64K) {
if (pud_none_or_clear_bad(pud))
continue;
- hugetlb_free_pmd_range(tlb, pud, addr, next, floor, ceiling);
+ hugetlb_free_pmd_range(tlb, pud, addr, next, floor,
+ ceiling, psize);
} else {
if (pud_none(*pud))
continue;
- free_hugepte_range(tlb, (hugepd_t *)pud);
+ free_hugepte_range(tlb, (hugepd_t *)pud, psize);
}
#endif
} while (pud++, addr = next, addr != end);
@@ -255,7 +356,7 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
*
* Must be called with pagetable lock held.
*/
-void hugetlb_free_pgd_range(struct mmu_gather **tlb,
+void hugetlb_free_pgd_range(struct mmu_gather *tlb,
unsigned long addr, unsigned long end,
unsigned long floor, unsigned long ceiling)
{
@@ -297,31 +398,33 @@ void hugetlb_free_pgd_range(struct mmu_gather **tlb,
* now has no other vmas using it, so can be freed, we don't
* bother to round floor or end up - the tests don't need that.
*/
+ unsigned int psize = get_slice_psize(tlb->mm, addr);
- addr &= HUGEPD_MASK;
+ addr &= HUGEPD_MASK(psize);
if (addr < floor) {
- addr += HUGEPD_SIZE;
+ addr += HUGEPD_SIZE(psize);
if (!addr)
return;
}
if (ceiling) {
- ceiling &= HUGEPD_MASK;
+ ceiling &= HUGEPD_MASK(psize);
if (!ceiling)
return;
}
if (end - 1 > ceiling - 1)
- end -= HUGEPD_SIZE;
+ end -= HUGEPD_SIZE(psize);
if (addr > end - 1)
return;
start = addr;
- pgd = pgd_offset((*tlb)->mm, addr);
+ pgd = pgd_offset(tlb->mm, addr);
do {
- BUG_ON(get_slice_psize((*tlb)->mm, addr) != mmu_huge_psize);
+ psize = get_slice_psize(tlb->mm, addr);
+ BUG_ON(!mmu_huge_psizes[psize]);
next = pgd_addr_end(addr, end);
if (pgd_none_or_clear_bad(pgd))
continue;
- hugetlb_free_pud_range(*tlb, pgd, addr, next, floor, ceiling);
+ hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling);
} while (pgd++, addr = next, addr != end);
}
@@ -334,7 +437,11 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
* necessary anymore if we make hpte_need_flush() get the
* page size from the slices
*/
- pte_update(mm, addr & HPAGE_MASK, ptep, ~0UL, 1);
+ unsigned int psize = get_slice_psize(mm, addr);
+ unsigned int shift = mmu_psize_to_shift(psize);
+ unsigned long sz = ((1UL) << shift);
+ struct hstate *hstate = size_to_hstate(sz);
+ pte_update(mm, addr & hstate->mask, ptep, ~0UL, 1);
}
*ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
}
@@ -351,14 +458,19 @@ follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
{
pte_t *ptep;
struct page *page;
+ unsigned int mmu_psize = get_slice_psize(mm, address);
- if (get_slice_psize(mm, address) != mmu_huge_psize)
+ /* Verify it is a huge page else bail. */
+ if (!mmu_huge_psizes[mmu_psize])
return ERR_PTR(-EINVAL);
ptep = huge_pte_offset(mm, address);
page = pte_page(*ptep);
- if (page)
- page += (address % HPAGE_SIZE) / PAGE_SIZE;
+ if (page) {
+ unsigned int shift = mmu_psize_to_shift(mmu_psize);
+ unsigned long sz = ((1UL) << shift);
+ page += (address % sz) / PAGE_SIZE;
+ }
return page;
}
@@ -368,6 +480,11 @@ int pmd_huge(pmd_t pmd)
return 0;
}
+int pud_huge(pud_t pud)
+{
+ return 0;
+}
+
struct page *
follow_huge_pmd(struct mm_struct *mm, unsigned long address,
pmd_t *pmd, int write)
@@ -381,15 +498,16 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
unsigned long len, unsigned long pgoff,
unsigned long flags)
{
- return slice_get_unmapped_area(addr, len, flags,
- mmu_huge_psize, 1, 0);
+ struct hstate *hstate = hstate_file(file);
+ int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate));
+ return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0);
}
/*
* Called by asm hashtable.S for doing lazy icache flush
*/
static unsigned int hash_huge_page_do_lazy_icache(unsigned long rflags,
- pte_t pte, int trap)
+ pte_t pte, int trap, unsigned long sz)
{
struct page *page;
int i;
@@ -402,7 +520,7 @@ static unsigned int hash_huge_page_do_lazy_icache(unsigned long rflags,
/* page is dirty */
if (!test_bit(PG_arch_1, &page->flags) && !PageReserved(page)) {
if (trap == 0x400) {
- for (i = 0; i < (HPAGE_SIZE / PAGE_SIZE); i++)
+ for (i = 0; i < (sz / PAGE_SIZE); i++)
__flush_dcache_icache(page_address(page+i));
set_bit(PG_arch_1, &page->flags);
} else {
@@ -418,11 +536,16 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access,
{
pte_t *ptep;
unsigned long old_pte, new_pte;
- unsigned long va, rflags, pa;
+ unsigned long va, rflags, pa, sz;
long slot;
int err = 1;
int ssize = user_segment_size(ea);
+ unsigned int mmu_psize;
+ int shift;
+ mmu_psize = get_slice_psize(mm, ea);
+ if (!mmu_huge_psizes[mmu_psize])
+ goto out;
ptep = huge_pte_offset(mm, ea);
/* Search the Linux page table for a match with va */
@@ -465,30 +588,32 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access,
rflags = 0x2 | (!(new_pte & _PAGE_RW));
/* _PAGE_EXEC -> HW_NO_EXEC since it's inverted */
rflags |= ((new_pte & _PAGE_EXEC) ? 0 : HPTE_R_N);
+ shift = mmu_psize_to_shift(mmu_psize);
+ sz = ((1UL) << shift);
if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
/* No CPU has hugepages but lacks no execute, so we
* don't need to worry about that case */
rflags = hash_huge_page_do_lazy_icache(rflags, __pte(old_pte),
- trap);
+ trap, sz);
/* Check if pte already has an hpte (case 2) */
if (unlikely(old_pte & _PAGE_HASHPTE)) {
/* There MIGHT be an HPTE for this pte */
unsigned long hash, slot;
- hash = hpt_hash(va, HPAGE_SHIFT, ssize);
+ hash = hpt_hash(va, shift, ssize);
if (old_pte & _PAGE_F_SECOND)
hash = ~hash;
slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
slot += (old_pte & _PAGE_F_GIX) >> 12;
- if (ppc_md.hpte_updatepp(slot, rflags, va, mmu_huge_psize,
+ if (ppc_md.hpte_updatepp(slot, rflags, va, mmu_psize,
ssize, local) == -1)
old_pte &= ~_PAGE_HPTEFLAGS;
}
if (likely(!(old_pte & _PAGE_HASHPTE))) {
- unsigned long hash = hpt_hash(va, HPAGE_SHIFT, ssize);
+ unsigned long hash = hpt_hash(va, shift, ssize);
unsigned long hpte_group;
pa = pte_pfn(__pte(old_pte)) << PAGE_SHIFT;
@@ -509,7 +634,7 @@ repeat:
/* Insert into the hash table, primary slot */
slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, 0,
- mmu_huge_psize, ssize);
+ mmu_psize, ssize);
/* Primary is full, try the secondary */
if (unlikely(slot == -1)) {
@@ -517,7 +642,7 @@ repeat:
HPTES_PER_GROUP) & ~0x7UL;
slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags,
HPTE_V_SECONDARY,
- mmu_huge_psize, ssize);
+ mmu_psize, ssize);
if (slot == -1) {
if (mftb() & 0x1)
hpte_group = ((hash & htab_hash_mask) *
@@ -549,45 +674,54 @@ void set_huge_psize(int psize)
{
/* Check that it is a page size supported by the hardware and
* that it fits within pagetable limits. */
- if (mmu_psize_defs[psize].shift && mmu_psize_defs[psize].shift < SID_SHIFT &&
+ if (mmu_psize_defs[psize].shift &&
+ mmu_psize_defs[psize].shift < SID_SHIFT_1T &&
(mmu_psize_defs[psize].shift > MIN_HUGEPTE_SHIFT ||
- mmu_psize_defs[psize].shift == HPAGE_SHIFT_64K)) {
- HPAGE_SHIFT = mmu_psize_defs[psize].shift;
- mmu_huge_psize = psize;
-#ifdef CONFIG_PPC_64K_PAGES
- hugepte_shift = (PMD_SHIFT-HPAGE_SHIFT);
-#else
- if (HPAGE_SHIFT == HPAGE_SHIFT_64K)
- hugepte_shift = (PMD_SHIFT-HPAGE_SHIFT);
- else
- hugepte_shift = (PUD_SHIFT-HPAGE_SHIFT);
-#endif
-
+ mmu_psize_defs[psize].shift == PAGE_SHIFT_64K ||
+ mmu_psize_defs[psize].shift == PAGE_SHIFT_16G)) {
+ /* Return if huge page size has already been setup or is the
+ * same as the base page size. */
+ if (mmu_huge_psizes[psize] ||
+ mmu_psize_defs[psize].shift == PAGE_SHIFT)
+ return;
+ hugetlb_add_hstate(mmu_psize_defs[psize].shift - PAGE_SHIFT);
+
+ switch (mmu_psize_defs[psize].shift) {
+ case PAGE_SHIFT_64K:
+ /* We only allow 64k hpages with 4k base page,
+ * which was checked above, and always put them
+ * at the PMD */
+ hugepte_shift[psize] = PMD_SHIFT;
+ break;
+ case PAGE_SHIFT_16M:
+ /* 16M pages can be at two different levels
+ * of pagestables based on base page size */
+ if (PAGE_SHIFT == PAGE_SHIFT_64K)
+ hugepte_shift[psize] = PMD_SHIFT;
+ else /* 4k base page */
+ hugepte_shift[psize] = PUD_SHIFT;
+ break;
+ case PAGE_SHIFT_16G:
+ /* 16G pages are always at PGD level */
+ hugepte_shift[psize] = PGDIR_SHIFT;
+ break;
+ }
+ hugepte_shift[psize] -= mmu_psize_defs[psize].shift;
} else
- HPAGE_SHIFT = 0;
+ hugepte_shift[psize] = 0;
}
static int __init hugepage_setup_sz(char *str)
{
unsigned long long size;
- int mmu_psize = -1;
+ int mmu_psize;
int shift;
size = memparse(str, &str);
shift = __ffs(size);
- switch (shift) {
-#ifndef CONFIG_PPC_64K_PAGES
- case HPAGE_SHIFT_64K:
- mmu_psize = MMU_PAGE_64K;
- break;
-#endif
- case HPAGE_SHIFT_16M:
- mmu_psize = MMU_PAGE_16M;
- break;
- }
-
- if (mmu_psize >=0 && mmu_psize_defs[mmu_psize].shift)
+ mmu_psize = shift_to_mmu_psize(shift);
+ if (mmu_psize >= 0 && mmu_psize_defs[mmu_psize].shift)
set_huge_psize(mmu_psize);
else
printk(KERN_WARNING "Invalid huge page size specified(%llu)\n", size);
@@ -603,16 +737,31 @@ static void zero_ctor(struct kmem_cache *cache, void *addr)
static int __init hugetlbpage_init(void)
{
+ unsigned int psize;
+
if (!cpu_has_feature(CPU_FTR_16M_PAGE))
return -ENODEV;
-
- huge_pgtable_cache = kmem_cache_create("hugepte_cache",
- HUGEPTE_TABLE_SIZE,
- HUGEPTE_TABLE_SIZE,
- 0,
- zero_ctor);
- if (! huge_pgtable_cache)
- panic("hugetlbpage_init(): could not create hugepte cache\n");
+ /* Add supported huge page sizes. Need to change HUGE_MAX_HSTATE
+ * and adjust PTE_NONCACHE_NUM if the number of supported huge page
+ * sizes changes.
+ */
+ set_huge_psize(MMU_PAGE_16M);
+ set_huge_psize(MMU_PAGE_64K);
+ set_huge_psize(MMU_PAGE_16G);
+
+ for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
+ if (mmu_huge_psizes[psize]) {
+ huge_pgtable_cache(psize) = kmem_cache_create(
+ HUGEPTE_CACHE_NAME(psize),
+ HUGEPTE_TABLE_SIZE(psize),
+ HUGEPTE_TABLE_SIZE(psize),
+ 0,
+ zero_ctor);
+ if (!huge_pgtable_cache(psize))
+ panic("hugetlbpage_init(): could not create %s"\
+ "\n", HUGEPTE_CACHE_NAME(psize));
+ }
+ }
return 0;
}
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 6ef63caca68..a41bc5aa204 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -153,10 +153,10 @@ static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
};
#ifdef CONFIG_HUGETLB_PAGE
-/* Hugepages need one extra cache, initialized in hugetlbpage.c. We
- * can't put into the tables above, because HPAGE_SHIFT is not compile
- * time constant. */
-struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+1];
+/* Hugepages need an extra cache per hugepagesize, initialized in
+ * hugetlbpage.c. We can't put into the tables above, because HPAGE_SHIFT
+ * is not compile time constant. */
+struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+MMU_PAGE_COUNT];
#else
struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)];
#endif
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index cf4bffba6f7..d9a18135133 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -39,7 +39,6 @@ EXPORT_SYMBOL(numa_cpu_lookup_table);
EXPORT_SYMBOL(numa_cpumask_lookup_table);
EXPORT_SYMBOL(node_data);
-static bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES];
static int min_common_depth;
static int n_mem_addr_cells, n_mem_size_cells;
@@ -816,7 +815,7 @@ void __init do_init_bootmem(void)
dbg("node %d\n", nid);
dbg("NODE_DATA() = %p\n", NODE_DATA(nid));
- NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
+ NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
NODE_DATA(nid)->node_start_pfn = start_pfn;
NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index c7584072dfc..2001abdb191 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -145,13 +145,20 @@ void pte_free(struct mm_struct *mm, pgtable_t ptepage)
void __iomem *
ioremap(phys_addr_t addr, unsigned long size)
{
- return __ioremap(addr, size, _PAGE_NO_CACHE);
+ return __ioremap(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED);
}
EXPORT_SYMBOL(ioremap);
void __iomem *
ioremap_flags(phys_addr_t addr, unsigned long size, unsigned long flags)
{
+ /* writeable implies dirty for kernel addresses */
+ if (flags & _PAGE_RW)
+ flags |= _PAGE_DIRTY | _PAGE_HWWRITE;
+
+ /* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */
+ flags &= ~(_PAGE_USER | _PAGE_EXEC | _PAGE_HWEXEC);
+
return __ioremap(addr, size, flags);
}
EXPORT_SYMBOL(ioremap_flags);
@@ -163,6 +170,14 @@ __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags)
phys_addr_t p;
int err;
+ /* Make sure we have the base flags */
+ if ((flags & _PAGE_PRESENT) == 0)
+ flags |= _PAGE_KERNEL;
+
+ /* Non-cacheable page cannot be coherent */
+ if (flags & _PAGE_NO_CACHE)
+ flags &= ~_PAGE_COHERENT;
+
/*
* Choose an address to map it to.
* Once the vmalloc system is running, we use it.
@@ -219,11 +234,6 @@ __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags)
v = (ioremap_bot -= size);
}
- if ((flags & _PAGE_PRESENT) == 0)
- flags |= _PAGE_KERNEL;
- if (flags & _PAGE_NO_CACHE)
- flags |= _PAGE_GUARDED;
-
/*
* Should check if it is a candidate for a BAT mapping
*/
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 3ef0ad2f9ca..365e61ae5db 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -107,9 +107,18 @@ void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size,
{
unsigned long i;
+ /* Make sure we have the base flags */
if ((flags & _PAGE_PRESENT) == 0)
flags |= pgprot_val(PAGE_KERNEL);
+ /* Non-cacheable page cannot be coherent */
+ if (flags & _PAGE_NO_CACHE)
+ flags &= ~_PAGE_COHERENT;
+
+ /* We don't support the 4K PFN hack with ioremap */
+ if (flags & _PAGE_4K_PFN)
+ return NULL;
+
WARN_ON(pa & ~PAGE_MASK);
WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
WARN_ON(size & ~PAGE_MASK);
@@ -190,6 +199,13 @@ void __iomem * ioremap(phys_addr_t addr, unsigned long size)
void __iomem * ioremap_flags(phys_addr_t addr, unsigned long size,
unsigned long flags)
{
+ /* writeable implies dirty for kernel addresses */
+ if (flags & _PAGE_RW)
+ flags |= _PAGE_DIRTY;
+
+ /* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */
+ flags &= ~(_PAGE_USER | _PAGE_EXEC);
+
if (ppc_md.ioremap)
return ppc_md.ioremap(addr, size, flags);
return __ioremap(addr, size, flags);
diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c
index a01b5c608ff..409fcc7b63c 100644
--- a/arch/powerpc/mm/tlb_64.c
+++ b/arch/powerpc/mm/tlb_64.c
@@ -147,7 +147,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
*/
if (huge) {
#ifdef CONFIG_HUGETLB_PAGE
- psize = mmu_huge_psize;
+ psize = get_slice_psize(mm, addr);;
#else
BUG();
psize = pte_pagesize_index(mm, addr, pte); /* shutup gcc */
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig
index acd2fc8cf49..696a5ee4962 100644
--- a/arch/powerpc/platforms/52xx/Kconfig
+++ b/arch/powerpc/platforms/52xx/Kconfig
@@ -1,8 +1,8 @@
config PPC_MPC52xx
bool "52xx-based boards"
depends on PPC_MULTIPLATFORM && PPC32
- select FSL_SOC
select PPC_CLOCK
+ select PPC_PCI_CHOICE
config PPC_MPC5200_SIMPLE
bool "Generic support for simple MPC5200 based boards"
@@ -47,6 +47,7 @@ config PPC_MPC5200_BUGFIX
config PPC_MPC5200_GPIO
bool "MPC5200 GPIO support"
depends on PPC_MPC52xx
- select HAVE_GPIO_LIB
+ select ARCH_REQUIRE_GPIOLIB
+ select GENERIC_GPIO
help
Enable gpiolib support for mpc5200 based boards
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig
index 1c8034bfa79..75eb1ede549 100644
--- a/arch/powerpc/platforms/82xx/Kconfig
+++ b/arch/powerpc/platforms/82xx/Kconfig
@@ -30,6 +30,7 @@ config EP8248E
select 8272
select 8260
select FSL_SOC
+ select PHYLIB
select MDIO_BITBANG
help
This enables support for the Embedded Planet EP8248E board.
diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c
index 373e993a5ed..d5770fdf7f0 100644
--- a/arch/powerpc/platforms/82xx/ep8248e.c
+++ b/arch/powerpc/platforms/82xx/ep8248e.c
@@ -59,7 +59,6 @@ static void __init ep8248e_pic_init(void)
of_node_put(np);
}
-#ifdef CONFIG_FS_ENET_MDIO_FCC
static void ep8248e_set_mdc(struct mdiobb_ctrl *ctrl, int level)
{
if (level)
@@ -165,7 +164,6 @@ static struct of_platform_driver ep8248e_mdio_driver = {
.probe = ep8248e_mdio_probe,
.remove = ep8248e_mdio_remove,
};
-#endif
struct cpm_pin {
int port, pin, flags;
@@ -298,9 +296,7 @@ static __initdata struct of_device_id of_bus_ids[] = {
static int __init declare_of_platform_devices(void)
{
of_platform_bus_probe(NULL, of_bus_ids, NULL);
-#ifdef CONFIG_FS_ENET_MDIO_FCC
of_register_platform_driver(&ep8248e_mdio_driver);
-#endif
return 0;
}
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 27d9bf86de0..6159c5d4e5f 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -2,7 +2,8 @@ menuconfig PPC_83xx
bool "83xx-based boards"
depends on 6xx && PPC_MULTIPLATFORM
select PPC_UDBG_16550
- select PPC_INDIRECT_PCI
+ select PPC_PCI_CHOICE
+ select FSL_PCI if PCI
select FSL_SOC
select IPIC
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index f331fd7dd83..ba5028e2989 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -2,7 +2,7 @@
# Makefile for the PowerPC 83xx linux kernel.
#
obj-y := misc.o usb.o
-obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_SUSPEND) += suspend.o suspend-asm.o
obj-$(CONFIG_MPC831x_RDB) += mpc831x_rdb.o
obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o
obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o
diff --git a/arch/powerpc/platforms/83xx/mpc831x_rdb.c b/arch/powerpc/platforms/83xx/mpc831x_rdb.c
index c4db5172b27..a428f8d1ac8 100644
--- a/arch/powerpc/platforms/83xx/mpc831x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc831x_rdb.c
@@ -19,6 +19,7 @@
#include <asm/time.h>
#include <asm/ipic.h>
#include <asm/udbg.h>
+#include <sysdev/fsl_pci.h>
#include "mpc83xx.h"
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index 6dbc6eabcb0..dd4be4aee31 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -36,6 +36,7 @@
#include <asm/prom.h>
#include <asm/udbg.h>
#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
#include <asm/qe.h>
#include <asm/qe_ic.h>
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index e7f706b624f..f049d692d4c 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -27,6 +27,7 @@
#include <asm/qe.h>
#include <asm/qe_ic.h>
#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
#include "mpc83xx.h"
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index 50e8f632061..7301d77a08e 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -35,6 +35,7 @@
#include <asm/prom.h>
#include <asm/udbg.h>
#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
#include "mpc83xx.h"
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index 2b8a0a3f855..30d509aa9f0 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -35,6 +35,7 @@
#include <asm/prom.h>
#include <asm/udbg.h>
#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
#include "mpc83xx.h"
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index c2e5de60c05..75b80e83657 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -42,6 +42,7 @@
#include <asm/prom.h>
#include <asm/udbg.h>
#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
#include <asm/qe.h>
#include <asm/qe_ic.h>
diff --git a/arch/powerpc/platforms/83xx/mpc836x_rdk.c b/arch/powerpc/platforms/83xx/mpc836x_rdk.c
index c10dec4bf17..a5273bb28e1 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_rdk.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_rdk.c
@@ -23,6 +23,7 @@
#include <asm/qe.h>
#include <asm/qe_ic.h>
#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
#include "mpc83xx.h"
diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
index 64d17b0d645..be62de23bea 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
@@ -19,6 +19,7 @@
#include <asm/ipic.h>
#include <asm/udbg.h>
#include <asm/prom.h>
+#include <sysdev/fsl_pci.h>
#include "mpc83xx.h"
diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
index c00356bdb1d..da030afa2e2 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
@@ -17,6 +17,7 @@
#include <asm/time.h>
#include <asm/ipic.h>
#include <asm/udbg.h>
+#include <sysdev/fsl_pci.h>
#include "mpc83xx.h"
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index 88a3b5cabb1..2a7cbabb410 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -26,6 +26,8 @@
#define MPC834X_SICRL_USB1 0x20000000
#define MPC831X_SICRL_USB_MASK 0x00000c00
#define MPC831X_SICRL_USB_ULPI 0x00000800
+#define MPC8315_SICRL_USB_MASK 0x000000fc
+#define MPC8315_SICRL_USB_ULPI 0x00000054
#define MPC837X_SICRL_USB_MASK 0xf0000000
#define MPC837X_SICRL_USB_ULPI 0x50000000
@@ -34,6 +36,8 @@
#define MPC834X_SICRH_USB_UTMI 0x00020000
#define MPC831X_SICRH_USB_MASK 0x000000e0
#define MPC831X_SICRH_USB_ULPI 0x000000a0
+#define MPC8315_SICRH_USB_MASK 0x0000ff00
+#define MPC8315_SICRH_USB_ULPI 0x00000000
/* USB Control Register */
#define FSL_USB2_CONTROL_OFFS 0x500
@@ -55,7 +59,6 @@
* mpc83xx_* files. Mostly for use by mpc83xx_setup
*/
-extern int mpc83xx_add_bridge(struct device_node *dev);
extern void mpc83xx_restart(char *cmd);
extern long mpc83xx_time_init(void);
extern int mpc834x_usb_cfg(void);
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
deleted file mode 100644
index 14f1080c6c9..00000000000
--- a/arch/powerpc/platforms/83xx/pci.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * FSL SoC setup code
- *
- * Maintained by Kumar Gala (see MAINTAINERS for contact information)
- *
- * 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.
- */
-
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-
-#include <asm/system.h>
-#include <asm/atomic.h>
-#include <asm/io.h>
-#include <asm/pci-bridge.h>
-#include <asm/prom.h>
-#include <sysdev/fsl_soc.h>
-
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-int __init mpc83xx_add_bridge(struct device_node *dev)
-{
- int len;
- struct pci_controller *hose;
- struct resource rsrc;
- const int *bus_range;
- int primary = 1, has_address = 0;
- phys_addr_t immr = get_immrbase();
-
- DBG("Adding PCI host bridge %s\n", dev->full_name);
-
- /* Fetch host bridge registers address */
- has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
-
- /* Get bus range if any */
- bus_range = of_get_property(dev, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %s, assume"
- " bus 0\n", dev->full_name);
- }
-
- ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
- hose = pcibios_alloc_controller(dev);
- if (!hose)
- return -ENOMEM;
-
- hose->first_busno = bus_range ? bus_range[0] : 0;
- hose->last_busno = bus_range ? bus_range[1] : 0xff;
-
- /* MPC83xx supports up to two host controllers one at 0x8500 from immrbar
- * the other at 0x8600, we consider the 0x8500 the primary controller
- */
- /* PCI 1 */
- if ((rsrc.start & 0xfffff) == 0x8500) {
- setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304, 0);
- }
- /* PCI 2 */
- if ((rsrc.start & 0xfffff) == 0x8600) {
- setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384, 0);
- primary = 0;
- }
-
- printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. "
- "Firmware bus number: %d->%d\n",
- (unsigned long long)rsrc.start, hose->first_busno,
- hose->last_busno);
-
- DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
- hose, hose->cfg_addr, hose->cfg_data);
-
- /* Interpret the "ranges" property */
- /* This also maps the I/O region and sets isa_io/mem_base */
- pci_process_bridge_OF_ranges(hose, dev, primary);
-
- return 0;
-}
diff --git a/arch/powerpc/platforms/83xx/sbc834x.c b/arch/powerpc/platforms/83xx/sbc834x.c
index cf382474a83..fc21f5c15ba 100644
--- a/arch/powerpc/platforms/83xx/sbc834x.c
+++ b/arch/powerpc/platforms/83xx/sbc834x.c
@@ -37,6 +37,7 @@
#include <asm/prom.h>
#include <asm/udbg.h>
#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
#include "mpc83xx.h"
diff --git a/arch/powerpc/platforms/83xx/suspend-asm.S b/arch/powerpc/platforms/83xx/suspend-asm.S
new file mode 100644
index 00000000000..1930543c98d
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/suspend-asm.S
@@ -0,0 +1,533 @@
+/*
+ * Enter and leave deep sleep state on MPC83xx
+ *
+ * Copyright (c) 2006-2008 Freescale Semiconductor, Inc.
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * 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 <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/reg.h>
+#include <asm/asm-offsets.h>
+
+#define SS_MEMSAVE 0x00 /* First 8 bytes of RAM */
+#define SS_HID 0x08 /* 3 HIDs */
+#define SS_IABR 0x14 /* 2 IABRs */
+#define SS_IBCR 0x1c
+#define SS_DABR 0x20 /* 2 DABRs */
+#define SS_DBCR 0x28
+#define SS_SP 0x2c
+#define SS_SR 0x30 /* 16 segment registers */
+#define SS_R2 0x70
+#define SS_MSR 0x74
+#define SS_SDR1 0x78
+#define SS_LR 0x7c
+#define SS_SPRG 0x80 /* 4 SPRGs */
+#define SS_DBAT 0x90 /* 8 DBATs */
+#define SS_IBAT 0xd0 /* 8 IBATs */
+#define SS_TB 0x110
+#define SS_CR 0x118
+#define SS_GPREG 0x11c /* r12-r31 */
+#define STATE_SAVE_SIZE 0x16c
+
+ .section .data
+ .align 5
+
+mpc83xx_sleep_save_area:
+ .space STATE_SAVE_SIZE
+immrbase:
+ .long 0
+
+ .section .text
+ .align 5
+
+ /* r3 = physical address of IMMR */
+_GLOBAL(mpc83xx_enter_deep_sleep)
+ lis r4, immrbase@ha
+ stw r3, immrbase@l(r4)
+
+ /* The first 2 words of memory are used to communicate with the
+ * bootloader, to tell it how to resume.
+ *
+ * The first word is the magic number 0xf5153ae5, and the second
+ * is the pointer to mpc83xx_deep_resume.
+ *
+ * The original content of these two words is saved in SS_MEMSAVE.
+ */
+
+ lis r3, mpc83xx_sleep_save_area@h
+ ori r3, r3, mpc83xx_sleep_save_area@l
+
+ lis r4, KERNELBASE@h
+ lwz r5, 0(r4)
+ lwz r6, 4(r4)
+
+ stw r5, SS_MEMSAVE+0(r3)
+ stw r6, SS_MEMSAVE+4(r3)
+
+ mfspr r5, SPRN_HID0
+ mfspr r6, SPRN_HID1
+ mfspr r7, SPRN_HID2
+
+ stw r5, SS_HID+0(r3)
+ stw r6, SS_HID+4(r3)
+ stw r7, SS_HID+8(r3)
+
+ mfspr r4, SPRN_IABR
+ mfspr r5, SPRN_IABR2
+ mfspr r6, SPRN_IBCR
+ mfspr r7, SPRN_DABR
+ mfspr r8, SPRN_DABR2
+ mfspr r9, SPRN_DBCR
+
+ stw r4, SS_IABR+0(r3)
+ stw r5, SS_IABR+4(r3)
+ stw r6, SS_IBCR(r3)
+ stw r7, SS_DABR+0(r3)
+ stw r8, SS_DABR+4(r3)
+ stw r9, SS_DBCR(r3)
+
+ mfspr r4, SPRN_SPRG0
+ mfspr r5, SPRN_SPRG1
+ mfspr r6, SPRN_SPRG2
+ mfspr r7, SPRN_SPRG3
+ mfsdr1 r8
+
+ stw r4, SS_SPRG+0(r3)
+ stw r5, SS_SPRG+4(r3)
+ stw r6, SS_SPRG+8(r3)
+ stw r7, SS_SPRG+12(r3)
+ stw r8, SS_SDR1(r3)
+
+ mfspr r4, SPRN_DBAT0U
+ mfspr r5, SPRN_DBAT0L
+ mfspr r6, SPRN_DBAT1U
+ mfspr r7, SPRN_DBAT1L
+
+ stw r4, SS_DBAT+0x00(r3)
+ stw r5, SS_DBAT+0x04(r3)
+ stw r6, SS_DBAT+0x08(r3)
+ stw r7, SS_DBAT+0x0c(r3)
+
+ mfspr r4, SPRN_DBAT2U
+ mfspr r5, SPRN_DBAT2L
+ mfspr r6, SPRN_DBAT3U
+ mfspr r7, SPRN_DBAT3L
+
+ stw r4, SS_DBAT+0x10(r3)
+ stw r5, SS_DBAT+0x14(r3)
+ stw r6, SS_DBAT+0x18(r3)
+ stw r7, SS_DBAT+0x1c(r3)
+
+ mfspr r4, SPRN_DBAT4U
+ mfspr r5, SPRN_DBAT4L
+ mfspr r6, SPRN_DBAT5U
+ mfspr r7, SPRN_DBAT5L
+
+ stw r4, SS_DBAT+0x20(r3)
+ stw r5, SS_DBAT+0x24(r3)
+ stw r6, SS_DBAT+0x28(r3)
+ stw r7, SS_DBAT+0x2c(r3)
+
+ mfspr r4, SPRN_DBAT6U
+ mfspr r5, SPRN_DBAT6L
+ mfspr r6, SPRN_DBAT7U
+ mfspr r7, SPRN_DBAT7L
+
+ stw r4, SS_DBAT+0x30(r3)
+ stw r5, SS_DBAT+0x34(r3)
+ stw r6, SS_DBAT+0x38(r3)
+ stw r7, SS_DBAT+0x3c(r3)
+
+ mfspr r4, SPRN_IBAT0U
+ mfspr r5, SPRN_IBAT0L
+ mfspr r6, SPRN_IBAT1U
+ mfspr r7, SPRN_IBAT1L
+
+ stw r4, SS_IBAT+0x00(r3)
+ stw r5, SS_IBAT+0x04(r3)
+ stw r6, SS_IBAT+0x08(r3)
+ stw r7, SS_IBAT+0x0c(r3)
+
+ mfspr r4, SPRN_IBAT2U
+ mfspr r5, SPRN_IBAT2L
+ mfspr r6, SPRN_IBAT3U
+ mfspr r7, SPRN_IBAT3L
+
+ stw r4, SS_IBAT+0x10(r3)
+ stw r5, SS_IBAT+0x14(r3)
+ stw r6, SS_IBAT+0x18(r3)
+ stw r7, SS_IBAT+0x1c(r3)
+
+ mfspr r4, SPRN_IBAT4U
+ mfspr r5, SPRN_IBAT4L
+ mfspr r6, SPRN_IBAT5U
+ mfspr r7, SPRN_IBAT5L
+
+ stw r4, SS_IBAT+0x20(r3)
+ stw r5, SS_IBAT+0x24(r3)
+ stw r6, SS_IBAT+0x28(r3)
+ stw r7, SS_IBAT+0x2c(r3)
+
+ mfspr r4, SPRN_IBAT6U
+ mfspr r5, SPRN_IBAT6L
+ mfspr r6, SPRN_IBAT7U
+ mfspr r7, SPRN_IBAT7L
+
+ stw r4, SS_IBAT+0x30(r3)
+ stw r5, SS_IBAT+0x34(r3)
+ stw r6, SS_IBAT+0x38(r3)
+ stw r7, SS_IBAT+0x3c(r3)
+
+ mfmsr r4
+ mflr r5
+ mfcr r6
+
+ stw r4, SS_MSR(r3)
+ stw r5, SS_LR(r3)
+ stw r6, SS_CR(r3)
+ stw r1, SS_SP(r3)
+ stw r2, SS_R2(r3)
+
+1: mftbu r4
+ mftb r5
+ mftbu r6
+ cmpw r4, r6
+ bne 1b
+
+ stw r4, SS_TB+0(r3)
+ stw r5, SS_TB+4(r3)
+
+ stmw r12, SS_GPREG(r3)
+
+ li r4, 0
+ addi r6, r3, SS_SR-4
+1: mfsrin r5, r4
+ stwu r5, 4(r6)
+ addis r4, r4, 0x1000
+ cmpwi r4, 0
+ bne 1b
+
+ /* Disable machine checks and critical exceptions */
+ mfmsr r4
+ rlwinm r4, r4, 0, ~MSR_CE
+ rlwinm r4, r4, 0, ~MSR_ME
+ mtmsr r4
+ isync
+
+#define TMP_VIRT_IMMR 0xf0000000
+#define DEFAULT_IMMR_VALUE 0xff400000
+#define IMMRBAR_BASE 0x0000
+
+ lis r4, immrbase@ha
+ lwz r4, immrbase@l(r4)
+
+ /* Use DBAT0 to address the current IMMR space */
+
+ ori r4, r4, 0x002a
+ mtspr SPRN_DBAT0L, r4
+ lis r8, TMP_VIRT_IMMR@h
+ ori r4, r8, 0x001e /* 1 MByte accessable from Kernel Space only */
+ mtspr SPRN_DBAT0U, r4
+ isync
+
+ /* Use DBAT1 to address the original IMMR space */
+
+ lis r4, DEFAULT_IMMR_VALUE@h
+ ori r4, r4, 0x002a
+ mtspr SPRN_DBAT1L, r4
+ lis r9, (TMP_VIRT_IMMR + 0x01000000)@h
+ ori r4, r9, 0x001e /* 1 MByte accessable from Kernel Space only */
+ mtspr SPRN_DBAT1U, r4
+ isync
+
+ /* Use DBAT2 to address the beginning of RAM. This isn't done
+ * using the normal virtual mapping, because with page debugging
+ * enabled it will be read-only.
+ */
+
+ li r4, 0x0002
+ mtspr SPRN_DBAT2L, r4
+ lis r4, KERNELBASE@h
+ ori r4, r4, 0x001e /* 1 MByte accessable from Kernel Space only */
+ mtspr SPRN_DBAT2U, r4
+ isync
+
+ /* Flush the cache with our BAT, as there will be TLB misses
+ * otherwise if page debugging is enabled, and these misses
+ * will disturb the PLRU algorithm.
+ */
+
+ bl __flush_disable_L1
+
+ /* Keep the i-cache enabled, so the hack below for low-boot
+ * flash will work.
+ */
+ mfspr r3, SPRN_HID0
+ ori r3, r3, HID0_ICE
+ mtspr SPRN_HID0, r3
+ isync
+
+ lis r6, 0xf515
+ ori r6, r6, 0x3ae5
+
+ lis r7, mpc83xx_deep_resume@h
+ ori r7, r7, mpc83xx_deep_resume@l
+ tophys(r7, r7)
+
+ lis r5, KERNELBASE@h
+ stw r6, 0(r5)
+ stw r7, 4(r5)
+
+ /* Reset BARs */
+
+ li r4, 0
+ stw r4, 0x0024(r8)
+ stw r4, 0x002c(r8)
+ stw r4, 0x0034(r8)
+ stw r4, 0x003c(r8)
+ stw r4, 0x0064(r8)
+ stw r4, 0x006c(r8)
+
+ /* Rev 1 of the 8313 has problems with wakeup events that are
+ * pending during the transition to deep sleep state (such as if
+ * the PCI host sets the state to D3 and then D0 in rapid
+ * succession). This check shrinks the race window somewhat.
+ *
+ * See erratum PCI23, though the problem is not limited
+ * to PCI.
+ */
+
+ lwz r3, 0x0b04(r8)
+ andi. r3, r3, 1
+ bne- mpc83xx_deep_resume
+
+ /* Move IMMR back to the default location, following the
+ * procedure specified in the MPC8313 manual.
+ */
+ lwz r4, IMMRBAR_BASE(r8)
+ isync
+ lis r4, DEFAULT_IMMR_VALUE@h
+ stw r4, IMMRBAR_BASE(r8)
+ lis r4, KERNELBASE@h
+ lwz r4, 0(r4)
+ isync
+ lwz r4, IMMRBAR_BASE(r9)
+ mr r8, r9
+ isync
+
+ /* Check the Reset Configuration Word to see whether flash needs
+ * to be mapped at a low address or a high address.
+ */
+
+ lwz r4, 0x0904(r8)
+ andis. r4, r4, 0x0400
+ li r4, 0
+ beq boot_low
+ lis r4, 0xff80
+boot_low:
+ stw r4, 0x0020(r8)
+ lis r7, 0x8000
+ ori r7, r7, 0x0016
+
+ mfspr r5, SPRN_HID0
+ rlwinm r5, r5, 0, ~(HID0_DOZE | HID0_NAP)
+ oris r5, r5, HID0_SLEEP@h
+ mtspr SPRN_HID0, r5
+ isync
+
+ mfmsr r5
+ oris r5, r5, MSR_POW@h
+
+ /* Enable the flash mapping at the appropriate address. This
+ * mapping will override the RAM mapping if booting low, so there's
+ * no need to disable the latter. This must be done inside the same
+ * cache line as setting MSR_POW, so that no instruction fetches
+ * from RAM happen after the flash mapping is turned on.
+ */
+
+ .align 5
+ stw r7, 0x0024(r8)
+ sync
+ isync
+ mtmsr r5
+ isync
+1: b 1b
+
+mpc83xx_deep_resume:
+ lis r4, 1f@h
+ ori r4, r4, 1f@l
+ tophys(r4, r4)
+ mtsrr0 r4
+
+ mfmsr r4
+ rlwinm r4, r4, 0, ~(MSR_IR | MSR_DR)
+ mtsrr1 r4
+
+ rfi
+
+1: tlbia
+ bl __inval_enable_L1
+
+ lis r3, mpc83xx_sleep_save_area@h
+ ori r3, r3, mpc83xx_sleep_save_area@l
+ tophys(r3, r3)
+
+ lwz r5, SS_MEMSAVE+0(r3)
+ lwz r6, SS_MEMSAVE+4(r3)
+
+ stw r5, 0(0)
+ stw r6, 4(0)
+
+ lwz r5, SS_HID+0(r3)
+ lwz r6, SS_HID+4(r3)
+ lwz r7, SS_HID+8(r3)
+
+ mtspr SPRN_HID0, r5
+ mtspr SPRN_HID1, r6
+ mtspr SPRN_HID2, r7
+
+ lwz r4, SS_IABR+0(r3)
+ lwz r5, SS_IABR+4(r3)
+ lwz r6, SS_IBCR(r3)
+ lwz r7, SS_DABR+0(r3)
+ lwz r8, SS_DABR+4(r3)
+ lwz r9, SS_DBCR(r3)
+
+ mtspr SPRN_IABR, r4
+ mtspr SPRN_IABR2, r5
+ mtspr SPRN_IBCR, r6
+ mtspr SPRN_DABR, r7
+ mtspr SPRN_DABR2, r8
+ mtspr SPRN_DBCR, r9
+
+ li r4, 0
+ addi r6, r3, SS_SR-4
+1: lwzu r5, 4(r6)
+ mtsrin r5, r4
+ addis r4, r4, 0x1000
+ cmpwi r4, 0
+ bne 1b
+
+ lwz r4, SS_DBAT+0x00(r3)
+ lwz r5, SS_DBAT+0x04(r3)
+ lwz r6, SS_DBAT+0x08(r3)
+ lwz r7, SS_DBAT+0x0c(r3)
+
+ mtspr SPRN_DBAT0U, r4
+ mtspr SPRN_DBAT0L, r5
+ mtspr SPRN_DBAT1U, r6
+ mtspr SPRN_DBAT1L, r7
+
+ lwz r4, SS_DBAT+0x10(r3)
+ lwz r5, SS_DBAT+0x14(r3)
+ lwz r6, SS_DBAT+0x18(r3)
+ lwz r7, SS_DBAT+0x1c(r3)
+
+ mtspr SPRN_DBAT2U, r4
+ mtspr SPRN_DBAT2L, r5
+ mtspr SPRN_DBAT3U, r6
+ mtspr SPRN_DBAT3L, r7
+
+ lwz r4, SS_DBAT+0x20(r3)
+ lwz r5, SS_DBAT+0x24(r3)
+ lwz r6, SS_DBAT+0x28(r3)
+ lwz r7, SS_DBAT+0x2c(r3)
+
+ mtspr SPRN_DBAT4U, r4
+ mtspr SPRN_DBAT4L, r5
+ mtspr SPRN_DBAT5U, r6
+ mtspr SPRN_DBAT5L, r7
+
+ lwz r4, SS_DBAT+0x30(r3)
+ lwz r5, SS_DBAT+0x34(r3)
+ lwz r6, SS_DBAT+0x38(r3)
+ lwz r7, SS_DBAT+0x3c(r3)
+
+ mtspr SPRN_DBAT6U, r4
+ mtspr SPRN_DBAT6L, r5
+ mtspr SPRN_DBAT7U, r6
+ mtspr SPRN_DBAT7L, r7
+
+ lwz r4, SS_IBAT+0x00(r3)
+ lwz r5, SS_IBAT+0x04(r3)
+ lwz r6, SS_IBAT+0x08(r3)
+ lwz r7, SS_IBAT+0x0c(r3)
+
+ mtspr SPRN_IBAT0U, r4
+ mtspr SPRN_IBAT0L, r5
+ mtspr SPRN_IBAT1U, r6
+ mtspr SPRN_IBAT1L, r7
+
+ lwz r4, SS_IBAT+0x10(r3)
+ lwz r5, SS_IBAT+0x14(r3)
+ lwz r6, SS_IBAT+0x18(r3)
+ lwz r7, SS_IBAT+0x1c(r3)
+
+ mtspr SPRN_IBAT2U, r4
+ mtspr SPRN_IBAT2L, r5
+ mtspr SPRN_IBAT3U, r6
+ mtspr SPRN_IBAT3L, r7
+
+ lwz r4, SS_IBAT+0x20(r3)
+ lwz r5, SS_IBAT+0x24(r3)
+ lwz r6, SS_IBAT+0x28(r3)
+ lwz r7, SS_IBAT+0x2c(r3)
+
+ mtspr SPRN_IBAT4U, r4
+ mtspr SPRN_IBAT4L, r5
+ mtspr SPRN_IBAT5U, r6
+ mtspr SPRN_IBAT5L, r7
+
+ lwz r4, SS_IBAT+0x30(r3)
+ lwz r5, SS_IBAT+0x34(r3)
+ lwz r6, SS_IBAT+0x38(r3)
+ lwz r7, SS_IBAT+0x3c(r3)
+
+ mtspr SPRN_IBAT6U, r4
+ mtspr SPRN_IBAT6L, r5
+ mtspr SPRN_IBAT7U, r6
+ mtspr SPRN_IBAT7L, r7
+
+ lwz r4, SS_SPRG+0(r3)
+ lwz r5, SS_SPRG+4(r3)
+ lwz r6, SS_SPRG+8(r3)
+ lwz r7, SS_SPRG+12(r3)
+ lwz r8, SS_SDR1(r3)
+
+ mtspr SPRN_SPRG0, r4
+ mtspr SPRN_SPRG1, r5
+ mtspr SPRN_SPRG2, r6
+ mtspr SPRN_SPRG3, r7
+ mtsdr1 r8
+
+ lwz r4, SS_MSR(r3)
+ lwz r5, SS_LR(r3)
+ lwz r6, SS_CR(r3)
+ lwz r1, SS_SP(r3)
+ lwz r2, SS_R2(r3)
+
+ mtsrr1 r4
+ mtsrr0 r5
+ mtcr r6
+
+ li r4, 0
+ mtspr SPRN_TBWL, r4
+
+ lwz r4, SS_TB+0(r3)
+ lwz r5, SS_TB+4(r3)
+
+ mtspr SPRN_TBWU, r4
+ mtspr SPRN_TBWL, r5
+
+ lmw r12, SS_GPREG(r3)
+
+ /* Kick decrementer */
+ li r0, 1
+ mtdec r0
+
+ rfi
diff --git a/arch/powerpc/platforms/83xx/suspend.c b/arch/powerpc/platforms/83xx/suspend.c
new file mode 100644
index 00000000000..08e65fc8b98
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/suspend.c
@@ -0,0 +1,388 @@
+/*
+ * MPC83xx suspend support
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * Copyright (c) 2006-2007 Freescale Semiconductor, Inc.
+ *
+ * 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/init.h>
+#include <linux/pm.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/suspend.h>
+#include <linux/fsl_devices.h>
+#include <linux/of_platform.h>
+
+#include <asm/reg.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/mpc6xx.h>
+
+#include <sysdev/fsl_soc.h>
+
+#define PMCCR1_NEXT_STATE 0x0C /* Next state for power management */
+#define PMCCR1_NEXT_STATE_SHIFT 2
+#define PMCCR1_CURR_STATE 0x03 /* Current state for power management*/
+#define IMMR_RCW_OFFSET 0x900
+#define RCW_PCI_HOST 0x80000000
+
+void mpc83xx_enter_deep_sleep(phys_addr_t immrbase);
+
+struct mpc83xx_pmc {
+ u32 config;
+#define PMCCR_DLPEN 2 /* DDR SDRAM low power enable */
+#define PMCCR_SLPEN 1 /* System low power enable */
+
+ u32 event;
+ u32 mask;
+/* All but PMCI are deep-sleep only */
+#define PMCER_GPIO 0x100
+#define PMCER_PCI 0x080
+#define PMCER_USB 0x040
+#define PMCER_ETSEC1 0x020
+#define PMCER_ETSEC2 0x010
+#define PMCER_TIMER 0x008
+#define PMCER_INT1 0x004
+#define PMCER_INT2 0x002
+#define PMCER_PMCI 0x001
+#define PMCER_ALL 0x1FF
+
+ /* deep-sleep only */
+ u32 config1;
+#define PMCCR1_USE_STATE 0x80000000
+#define PMCCR1_PME_EN 0x00000080
+#define PMCCR1_ASSERT_PME 0x00000040
+#define PMCCR1_POWER_OFF 0x00000020
+
+ /* deep-sleep only */
+ u32 config2;
+};
+
+struct mpc83xx_rcw {
+ u32 rcwlr;
+ u32 rcwhr;
+};
+
+struct mpc83xx_clock {
+ u32 spmr;
+ u32 occr;
+ u32 sccr;
+};
+
+struct pmc_type {
+ int has_deep_sleep;
+};
+
+static struct of_device *pmc_dev;
+static int has_deep_sleep, deep_sleeping;
+static int pmc_irq;
+static struct mpc83xx_pmc __iomem *pmc_regs;
+static struct mpc83xx_clock __iomem *clock_regs;
+static int is_pci_agent, wake_from_pci;
+static phys_addr_t immrbase;
+static int pci_pm_state;
+static DECLARE_WAIT_QUEUE_HEAD(agent_wq);
+
+int fsl_deep_sleep(void)
+{
+ return deep_sleeping;
+}
+
+static int mpc83xx_change_state(void)
+{
+ u32 curr_state;
+ u32 reg_cfg1 = in_be32(&pmc_regs->config1);
+
+ if (is_pci_agent) {
+ pci_pm_state = (reg_cfg1 & PMCCR1_NEXT_STATE) >>
+ PMCCR1_NEXT_STATE_SHIFT;
+ curr_state = reg_cfg1 & PMCCR1_CURR_STATE;
+
+ if (curr_state != pci_pm_state) {
+ reg_cfg1 &= ~PMCCR1_CURR_STATE;
+ reg_cfg1 |= pci_pm_state;
+ out_be32(&pmc_regs->config1, reg_cfg1);
+
+ wake_up(&agent_wq);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static irqreturn_t pmc_irq_handler(int irq, void *dev_id)
+{
+ u32 event = in_be32(&pmc_regs->event);
+ int ret = IRQ_NONE;
+
+ if (mpc83xx_change_state())
+ ret = IRQ_HANDLED;
+
+ if (event) {
+ out_be32(&pmc_regs->event, event);
+ ret = IRQ_HANDLED;
+ }
+
+ return ret;
+}
+
+static int mpc83xx_suspend_enter(suspend_state_t state)
+{
+ int ret = -EAGAIN;
+
+ /* Don't go to sleep if there's a race where pci_pm_state changes
+ * between the agent thread checking it and the PM code disabling
+ * interrupts.
+ */
+ if (wake_from_pci) {
+ if (pci_pm_state != (deep_sleeping ? 3 : 2))
+ goto out;
+
+ out_be32(&pmc_regs->config1,
+ in_be32(&pmc_regs->config1) | PMCCR1_PME_EN);
+ }
+
+ /* Put the system into low-power mode and the RAM
+ * into self-refresh mode once the core goes to
+ * sleep.
+ */
+
+ out_be32(&pmc_regs->config, PMCCR_SLPEN | PMCCR_DLPEN);
+
+ /* If it has deep sleep (i.e. it's an 831x or compatible),
+ * disable power to the core upon entering sleep mode. This will
+ * require going through the boot firmware upon a wakeup event.
+ */
+
+ if (deep_sleeping) {
+ out_be32(&pmc_regs->mask, PMCER_ALL);
+
+ out_be32(&pmc_regs->config1,
+ in_be32(&pmc_regs->config1) | PMCCR1_POWER_OFF);
+
+ enable_kernel_fp();
+
+ mpc83xx_enter_deep_sleep(immrbase);
+
+ out_be32(&pmc_regs->config1,
+ in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF);
+
+ out_be32(&pmc_regs->mask, PMCER_PMCI);
+ } else {
+ out_be32(&pmc_regs->mask, PMCER_PMCI);
+
+ mpc6xx_enter_standby();
+ }
+
+ ret = 0;
+
+out:
+ out_be32(&pmc_regs->config1,
+ in_be32(&pmc_regs->config1) & ~PMCCR1_PME_EN);
+
+ return ret;
+}
+
+static void mpc83xx_suspend_finish(void)
+{
+ deep_sleeping = 0;
+}
+
+static int mpc83xx_suspend_valid(suspend_state_t state)
+{
+ return state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM;
+}
+
+static int mpc83xx_suspend_begin(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_STANDBY:
+ deep_sleeping = 0;
+ return 0;
+
+ case PM_SUSPEND_MEM:
+ if (has_deep_sleep)
+ deep_sleeping = 1;
+
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int agent_thread_fn(void *data)
+{
+ while (1) {
+ wait_event_interruptible(agent_wq, pci_pm_state >= 2);
+ try_to_freeze();
+
+ if (signal_pending(current) || pci_pm_state < 2)
+ continue;
+
+ /* With a preemptible kernel (or SMP), this could race with
+ * a userspace-driven suspend request. It's probably best
+ * to avoid mixing the two with such a configuration (or
+ * else fix it by adding a mutex to state_store that we can
+ * synchronize with).
+ */
+
+ wake_from_pci = 1;
+
+ pm_suspend(pci_pm_state == 3 ? PM_SUSPEND_MEM :
+ PM_SUSPEND_STANDBY);
+
+ wake_from_pci = 0;
+ }
+
+ return 0;
+}
+
+static void mpc83xx_set_agent(void)
+{
+ out_be32(&pmc_regs->config1, PMCCR1_USE_STATE);
+ out_be32(&pmc_regs->mask, PMCER_PMCI);
+
+ kthread_run(agent_thread_fn, NULL, "PCI power mgt");
+}
+
+static int mpc83xx_is_pci_agent(void)
+{
+ struct mpc83xx_rcw __iomem *rcw_regs;
+ int ret;
+
+ rcw_regs = ioremap(get_immrbase() + IMMR_RCW_OFFSET,
+ sizeof(struct mpc83xx_rcw));
+
+ if (!rcw_regs)
+ return -ENOMEM;
+
+ ret = !(in_be32(&rcw_regs->rcwhr) & RCW_PCI_HOST);
+
+ iounmap(rcw_regs);
+ return ret;
+}
+
+static struct platform_suspend_ops mpc83xx_suspend_ops = {
+ .valid = mpc83xx_suspend_valid,
+ .begin = mpc83xx_suspend_begin,
+ .enter = mpc83xx_suspend_enter,
+ .finish = mpc83xx_suspend_finish,
+};
+
+static int pmc_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct device_node *np = ofdev->node;
+ struct resource res;
+ struct pmc_type *type = match->data;
+ int ret = 0;
+
+ if (!of_device_is_available(np))
+ return -ENODEV;
+
+ has_deep_sleep = type->has_deep_sleep;
+ immrbase = get_immrbase();
+ pmc_dev = ofdev;
+
+ is_pci_agent = mpc83xx_is_pci_agent();
+ if (is_pci_agent < 0)
+ return is_pci_agent;
+
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret)
+ return -ENODEV;
+
+ pmc_irq = irq_of_parse_and_map(np, 0);
+ if (pmc_irq != NO_IRQ) {
+ ret = request_irq(pmc_irq, pmc_irq_handler, IRQF_SHARED,
+ "pmc", ofdev);
+
+ if (ret)
+ return -EBUSY;
+ }
+
+ pmc_regs = ioremap(res.start, sizeof(struct mpc83xx_pmc));
+
+ if (!pmc_regs) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = of_address_to_resource(np, 1, &res);
+ if (ret) {
+ ret = -ENODEV;
+ goto out_pmc;
+ }
+
+ clock_regs = ioremap(res.start, sizeof(struct mpc83xx_pmc));
+
+ if (!clock_regs) {
+ ret = -ENOMEM;
+ goto out_pmc;
+ }
+
+ if (is_pci_agent)
+ mpc83xx_set_agent();
+
+ suspend_set_ops(&mpc83xx_suspend_ops);
+ return 0;
+
+out_pmc:
+ iounmap(pmc_regs);
+out:
+ if (pmc_irq != NO_IRQ)
+ free_irq(pmc_irq, ofdev);
+
+ return ret;
+}
+
+static int pmc_remove(struct of_device *ofdev)
+{
+ return -EPERM;
+};
+
+static struct pmc_type pmc_types[] = {
+ {
+ .has_deep_sleep = 1,
+ },
+ {
+ .has_deep_sleep = 0,
+ }
+};
+
+static struct of_device_id pmc_match[] = {
+ {
+ .compatible = "fsl,mpc8313-pmc",
+ .data = &pmc_types[0],
+ },
+ {
+ .compatible = "fsl,mpc8349-pmc",
+ .data = &pmc_types[1],
+ },
+ {}
+};
+
+static struct of_platform_driver pmc_driver = {
+ .name = "mpc83xx-pmc",
+ .match_table = pmc_match,
+ .probe = pmc_probe,
+ .remove = pmc_remove
+};
+
+static int pmc_init(void)
+{
+ return of_register_platform_driver(&pmc_driver);
+}
+
+module_init(pmc_init);
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c
index 64bcf0a33c7..cc99c280aad 100644
--- a/arch/powerpc/platforms/83xx/usb.c
+++ b/arch/powerpc/platforms/83xx/usb.c
@@ -137,15 +137,21 @@ int mpc831x_usb_cfg(void)
/* Configure pin mux for ULPI. There is no pin mux for UTMI */
if (prop && !strcmp(prop, "ulpi")) {
- temp = in_be32(immap + MPC83XX_SICRL_OFFS);
- temp &= ~MPC831X_SICRL_USB_MASK;
- temp |= MPC831X_SICRL_USB_ULPI;
- out_be32(immap + MPC83XX_SICRL_OFFS, temp);
-
- temp = in_be32(immap + MPC83XX_SICRH_OFFS);
- temp &= ~MPC831X_SICRH_USB_MASK;
- temp |= MPC831X_SICRH_USB_ULPI;
- out_be32(immap + MPC83XX_SICRH_OFFS, temp);
+ if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr")) {
+ clrsetbits_be32(immap + MPC83XX_SICRL_OFFS,
+ MPC8315_SICRL_USB_MASK,
+ MPC8315_SICRL_USB_ULPI);
+ clrsetbits_be32(immap + MPC83XX_SICRH_OFFS,
+ MPC8315_SICRH_USB_MASK,
+ MPC8315_SICRH_USB_ULPI);
+ } else {
+ clrsetbits_be32(immap + MPC83XX_SICRL_OFFS,
+ MPC831X_SICRL_USB_MASK,
+ MPC831X_SICRL_USB_ULPI);
+ clrsetbits_be32(immap + MPC83XX_SICRH_OFFS,
+ MPC831X_SICRH_USB_MASK,
+ MPC831X_SICRH_USB_ULPI);
+ }
}
iounmap(immap);
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index cebea5cadbc..291675b0097 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -2,8 +2,8 @@ menuconfig MPC85xx
bool "Machine Type"
depends on PPC_85xx
select PPC_UDBG_16550
- select PPC_INDIRECT_PCI if PCI
select MPIC
+ select PPC_PCI_CHOICE
select FSL_PCI if PCI
select SERIAL_8250_SHARE_IRQ if SERIAL_8250
default y
@@ -86,7 +86,6 @@ config TQM8548
help
This option enables support for the TQ Components TQM8548 board.
select DEFAULT_UIMAGE
- select PPC_CPM_NEW_BINDING
select TQM85xx
config TQM8555
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index 25f41cd2d33..00c53580664 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -115,7 +115,6 @@ void __init mpc85xx_ds_pic_init(void)
#ifdef CONFIG_PCI
static int primary_phb_addr;
-extern int uses_fsl_uli_m1575;
extern int uli_exclude_device(struct pci_controller *hose,
u_char bus, u_char devfn);
@@ -161,7 +160,6 @@ static void __init mpc85xx_ds_setup_arch(void)
}
}
- uses_fsl_uli_m1575 = 1;
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
#endif
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index 80a81e02bb5..9355a526943 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -27,6 +27,7 @@ config SBC8641D
config MPC8610_HPCD
bool "Freescale MPC8610 HPCD"
select DEFAULT_UIMAGE
+ select FSL_ULI1575
help
This option enables support for the MPC8610 HPCD board.
@@ -34,6 +35,7 @@ endif
config MPC8641
bool
+ select PPC_PCI_CHOICE
select FSL_PCI if PCI
select PPC_UDBG_16550
select MPIC
@@ -41,6 +43,7 @@ config MPC8641
config MPC8610
bool
+ select PPC_PCI_CHOICE
select FSL_PCI if PCI
select PPC_UDBG_16550
select MPIC
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index 30725302884..5eedb710896 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -58,93 +58,6 @@ static int __init mpc8610_declare_of_platform_devices(void)
}
machine_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
-#ifdef CONFIG_PCI
-static void __devinit quirk_uli1575(struct pci_dev *dev)
-{
- u32 temp32;
-
- /* Disable INTx */
- pci_read_config_dword(dev, 0x48, &temp32);
- pci_write_config_dword(dev, 0x48, (temp32 | 1<<26));
-
- /* Enable sideband interrupt */
- pci_read_config_dword(dev, 0x90, &temp32);
- pci_write_config_dword(dev, 0x90, (temp32 | 1<<22));
-}
-
-static void __devinit quirk_uli5288(struct pci_dev *dev)
-{
- unsigned char c;
- unsigned short temp;
-
- /* Interrupt Disable, Needed when SATA disabled */
- pci_read_config_word(dev, PCI_COMMAND, &temp);
- temp |= 1<<10;
- pci_write_config_word(dev, PCI_COMMAND, temp);
-
- pci_read_config_byte(dev, 0x83, &c);
- c |= 0x80;
- pci_write_config_byte(dev, 0x83, c);
-
- pci_write_config_byte(dev, PCI_CLASS_PROG, 0x01);
- pci_write_config_byte(dev, PCI_CLASS_DEVICE, 0x06);
-
- pci_read_config_byte(dev, 0x83, &c);
- c &= 0x7f;
- pci_write_config_byte(dev, 0x83, c);
-}
-
-/*
- * Since 8259PIC was disabled on the board, the IDE device can not
- * use the legacy IRQ, we need to let the IDE device work under
- * native mode and use the interrupt line like other PCI devices.
- * IRQ14 is a sideband interrupt from IDE device to CPU and we use this
- * as the interrupt for IDE device.
- */
-static void __devinit quirk_uli5229(struct pci_dev *dev)
-{
- unsigned char c;
-
- pci_read_config_byte(dev, 0x4b, &c);
- c |= 0x10;
- pci_write_config_byte(dev, 0x4b, c);
-}
-
-/*
- * SATA interrupt pin bug fix
- * There's a chip bug for 5288, The interrupt pin should be 2,
- * not the read only value 1, So it use INTB#, not INTA# which
- * actually used by the IDE device 5229.
- * As of this bug, during the PCI initialization, 5288 read the
- * irq of IDE device from the device tree, this function fix this
- * bug by re-assigning a correct irq to 5288.
- *
- */
-static void __devinit final_uli5288(struct pci_dev *dev)
-{
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
- struct device_node *hosenode = hose ? hose->dn : NULL;
- struct of_irq oirq;
- int virq, pin = 2;
- u32 laddr[3];
-
- if (!hosenode)
- return;
-
- laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(31, 0) << 8);
- laddr[1] = laddr[2] = 0;
- of_irq_map_raw(hosenode, &pin, 1, laddr, &oirq);
- virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
- oirq.size);
- dev->irq = virq;
-}
-
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_uli1575);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x5288, final_uli5288);
-#endif /* CONFIG_PCI */
-
#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
static u32 get_busfreq(void)
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 7916599c912..f712d9c0991 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -45,7 +45,6 @@
#endif
#ifdef CONFIG_PCI
-extern int uses_fsl_uli_m1575;
extern int uli_exclude_device(struct pci_controller *hose,
u_char bus, u_char devfn);
@@ -87,7 +86,6 @@ mpc86xx_hpcn_setup_arch(void)
fsl_add_bridge(np, 0);
}
- uses_fsl_uli_m1575 = 1;
ppc_md.pci_exclude_device = mpc86xx_exclude_device;
#endif
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 690c1f46e69..1d0968775c0 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -253,17 +253,13 @@ config CPM2
depends on MPC85xx || 8260
select CPM
select PPC_LIB_RHEAP
+ select PPC_PCI_CHOICE
help
The CPM2 (Communications Processor Module) is a coprocessor on
embedded CPUs made by Freescale. Selecting this option means that
you wish to build a kernel for a machine with a CPM2 coprocessor
on it (826x, 827x, 8560).
-config PPC_CPM_NEW_BINDING
- bool
- depends on CPM1 || CPM2
- default y
-
config AXON_RAM
tristate "Axon DDR2 memory device driver"
depends on PPC_IBM_CELL_BLADE
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 5bc4b611ff8..7f651273386 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -42,12 +42,14 @@ config 40x
select PPC_DCR_NATIVE
select PPC_UDBG_16550
select 4xx_SOC
+ select PPC_PCI_CHOICE
config 44x
bool "AMCC 44x"
select PPC_DCR_NATIVE
select PPC_UDBG_16550
select 4xx_SOC
+ select PPC_PCI_CHOICE
config E200
bool "Freescale e200"
@@ -84,9 +86,6 @@ config TUNE_CELL
machines. When building a kernel that is supposed to run only
on Cell, you should also select the POWER4_ONLY option.
-config 6xx
- bool
-
# this is temp to handle compat with arch=ppc
config 8xx
bool
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 3959fcfe731..c14d7d8d96c 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -83,6 +83,22 @@ config CBE_RAS
depends on PPC_CELL_NATIVE
default y
+config PPC_IBM_CELL_RESETBUTTON
+ bool "IBM Cell Blade Pinhole reset button"
+ depends on CBE_RAS && PPC_IBM_CELL_BLADE
+ default y
+ help
+ Support Pinhole Resetbutton on IBM Cell blades.
+ This adds a method to trigger system reset via front panel pinhole button.
+
+config PPC_IBM_CELL_POWERBUTTON
+ tristate "IBM Cell Blade power button"
+ depends on PPC_IBM_CELL_BLADE && PPC_PMI && INPUT_EVDEV
+ default y
+ help
+ Support Powerbutton on IBM Cell blades.
+ This will enable the powerbutton as an input device.
+
config CBE_THERM
tristate "CBE thermal support"
default m
@@ -107,6 +123,15 @@ config CBE_CPUFREQ_PMI
processor will not only be able to run at lower speed,
but also at lower core voltage.
+config CBE_CPUFREQ_SPU_GOVERNOR
+ tristate "CBE frequency scaling based on SPU usage"
+ depends on SPU_FS && CPU_FREQ
+ default m
+ help
+ This governor checks for spu usage to adjust the cpu frequency.
+ If no spu is running on a given cpu, that cpu will be throttled to
+ the minimal possible frequency.
+
endmenu
config OPROFILE_CELL
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index c2a7e4e5ddf..7fd830872c4 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -8,6 +8,9 @@ obj-$(CONFIG_CBE_THERM) += cbe_thermal.o
obj-$(CONFIG_CBE_CPUFREQ_PMI) += cbe_cpufreq_pmi.o
obj-$(CONFIG_CBE_CPUFREQ) += cbe-cpufreq.o
cbe-cpufreq-y += cbe_cpufreq_pervasive.o cbe_cpufreq.o
+obj-$(CONFIG_CBE_CPUFREQ_SPU_GOVERNOR) += cpufreq_spudemand.o
+
+obj-$(CONFIG_PPC_IBM_CELL_POWERBUTTON) += cbe_powerbutton.o
ifeq ($(CONFIG_SMP),y)
obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o
diff --git a/arch/powerpc/platforms/cell/cbe_powerbutton.c b/arch/powerpc/platforms/cell/cbe_powerbutton.c
new file mode 100644
index 00000000000..dcddaa5fcb6
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cbe_powerbutton.c
@@ -0,0 +1,117 @@
+/*
+ * driver for powerbutton on IBM cell blades
+ *
+ * (C) Copyright IBM Corp. 2005-2008
+ *
+ * Author: Christian Krafft <krafft@de.ibm.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <asm/pmi.h>
+#include <asm/prom.h>
+
+static struct input_dev *button_dev;
+static struct platform_device *button_pdev;
+
+static void cbe_powerbutton_handle_pmi(pmi_message_t pmi_msg)
+{
+ BUG_ON(pmi_msg.type != PMI_TYPE_POWER_BUTTON);
+
+ input_report_key(button_dev, KEY_POWER, 1);
+ input_sync(button_dev);
+ input_report_key(button_dev, KEY_POWER, 0);
+ input_sync(button_dev);
+}
+
+static struct pmi_handler cbe_pmi_handler = {
+ .type = PMI_TYPE_POWER_BUTTON,
+ .handle_pmi_message = cbe_powerbutton_handle_pmi,
+};
+
+static int __init cbe_powerbutton_init(void)
+{
+ int ret = 0;
+ struct input_dev *dev;
+
+ if (!machine_is_compatible("IBM,CBPLUS-1.0")) {
+ printk(KERN_ERR "%s: Not a cell blade.\n", __func__);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ dev = input_allocate_device();
+ if (!dev) {
+ ret = -ENOMEM;
+ printk(KERN_ERR "%s: Not enough memory.\n", __func__);
+ goto out;
+ }
+
+ set_bit(EV_KEY, dev->evbit);
+ set_bit(KEY_POWER, dev->keybit);
+
+ dev->name = "Power Button";
+ dev->id.bustype = BUS_HOST;
+
+ /* this makes the button look like an acpi power button
+ * no clue whether anyone relies on that though */
+ dev->id.product = 0x02;
+ dev->phys = "LNXPWRBN/button/input0";
+
+ button_pdev = platform_device_register_simple("power_button", 0, NULL, 0);
+ if (IS_ERR(button_pdev)) {
+ ret = PTR_ERR(button_pdev);
+ goto out_free_input;
+ }
+
+ dev->dev.parent = &button_pdev->dev;
+ ret = input_register_device(dev);
+ if (ret) {
+ printk(KERN_ERR "%s: Failed to register device\n", __func__);
+ goto out_free_pdev;
+ }
+
+ button_dev = dev;
+
+ ret = pmi_register_handler(&cbe_pmi_handler);
+ if (ret) {
+ printk(KERN_ERR "%s: Failed to register with pmi.\n", __func__);
+ goto out_free_pdev;
+ }
+
+ goto out;
+
+out_free_pdev:
+ platform_device_unregister(button_pdev);
+out_free_input:
+ input_free_device(dev);
+out:
+ return ret;
+}
+
+static void __exit cbe_powerbutton_exit(void)
+{
+ pmi_unregister_handler(&cbe_pmi_handler);
+ platform_device_unregister(button_pdev);
+ input_free_device(button_dev);
+}
+
+module_init(cbe_powerbutton_init);
+module_exit(cbe_powerbutton_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c
index 4852bf312d8..4d4c8c16912 100644
--- a/arch/powerpc/platforms/cell/cbe_thermal.c
+++ b/arch/powerpc/platforms/cell/cbe_thermal.c
@@ -97,7 +97,8 @@ static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iom
return value.spe[spu->spe_id];
}
-static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf)
+static ssize_t spu_show_temp(struct sys_device *sysdev, struct sysdev_attribute *attr,
+ char *buf)
{
u8 value;
struct cbe_pmd_regs __iomem *pmd_regs;
@@ -146,32 +147,38 @@ static ssize_t store_throttle(struct cbe_pmd_regs __iomem *pmd_regs, const char
return size;
}
-static ssize_t spu_show_throttle_end(struct sys_device *sysdev, char *buf)
+static ssize_t spu_show_throttle_end(struct sys_device *sysdev,
+ struct sysdev_attribute *attr, char *buf)
{
return show_throttle(get_pmd_regs(sysdev), buf, 0);
}
-static ssize_t spu_show_throttle_begin(struct sys_device *sysdev, char *buf)
+static ssize_t spu_show_throttle_begin(struct sys_device *sysdev,
+ struct sysdev_attribute *attr, char *buf)
{
return show_throttle(get_pmd_regs(sysdev), buf, 8);
}
-static ssize_t spu_show_throttle_full_stop(struct sys_device *sysdev, char *buf)
+static ssize_t spu_show_throttle_full_stop(struct sys_device *sysdev,
+ struct sysdev_attribute *attr, char *buf)
{
return show_throttle(get_pmd_regs(sysdev), buf, 16);
}
-static ssize_t spu_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size)
+static ssize_t spu_store_throttle_end(struct sys_device *sysdev,
+ struct sysdev_attribute *attr, const char *buf, size_t size)
{
return store_throttle(get_pmd_regs(sysdev), buf, size, 0);
}
-static ssize_t spu_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size)
+static ssize_t spu_store_throttle_begin(struct sys_device *sysdev,
+ struct sysdev_attribute *attr, const char *buf, size_t size)
{
return store_throttle(get_pmd_regs(sysdev), buf, size, 8);
}
-static ssize_t spu_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size)
+static ssize_t spu_store_throttle_full_stop(struct sys_device *sysdev,
+ struct sysdev_attribute *attr, const char *buf, size_t size)
{
return store_throttle(get_pmd_regs(sysdev), buf, size, 16);
}
@@ -192,43 +199,51 @@ static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos)
/* shows the temperature of the DTS on the PPE,
* located near the linear thermal sensor */
-static ssize_t ppe_show_temp0(struct sys_device *sysdev, char *buf)
+static ssize_t ppe_show_temp0(struct sys_device *sysdev,
+ struct sysdev_attribute *attr, char *buf)
{
return ppe_show_temp(sysdev, buf, 32);
}
/* shows the temperature of the second DTS on the PPE */
-static ssize_t ppe_show_temp1(struct sys_device *sysdev, char *buf)
+static ssize_t ppe_show_temp1(struct sys_device *sysdev,
+ struct sysdev_attribute *attr, char *buf)
{
return ppe_show_temp(sysdev, buf, 0);
}
-static ssize_t ppe_show_throttle_end(struct sys_device *sysdev, char *buf)
+static ssize_t ppe_show_throttle_end(struct sys_device *sysdev,
+ struct sysdev_attribute *attr, char *buf)
{
return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 32);
}
-static ssize_t ppe_show_throttle_begin(struct sys_device *sysdev, char *buf)
+static ssize_t ppe_show_throttle_begin(struct sys_device *sysdev,
+ struct sysdev_attribute *attr, char *buf)
{
return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 40);
}
-static ssize_t ppe_show_throttle_full_stop(struct sys_device *sysdev, char *buf)
+static ssize_t ppe_show_throttle_full_stop(struct sys_device *sysdev,
+ struct sysdev_attribute *attr, char *buf)
{
return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 48);
}
-static ssize_t ppe_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size)
+static ssize_t ppe_store_throttle_end(struct sys_device *sysdev,
+ struct sysdev_attribute *attr, const char *buf, size_t size)
{
return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 32);
}
-static ssize_t ppe_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size)
+static ssize_t ppe_store_throttle_begin(struct sys_device *sysdev,
+ struct sysdev_attribute *attr, const char *buf, size_t size)
{
return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 40);
}
-static ssize_t ppe_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size)
+static ssize_t ppe_store_throttle_full_stop(struct sys_device *sysdev,
+ struct sysdev_attribute *attr, const char *buf, size_t size)
{
return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 48);
}
diff --git a/arch/powerpc/platforms/cell/cpufreq_spudemand.c b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
new file mode 100644
index 00000000000..a3c6c01bd6d
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
@@ -0,0 +1,184 @@
+/*
+ * spu aware cpufreq governor for the cell processor
+ *
+ * © Copyright IBM Corporation 2006-2008
+ *
+ * Author: Christian Krafft <krafft@de.ibm.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/cpufreq.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+#include <asm/machdep.h>
+#include <asm/spu.h>
+
+#define POLL_TIME 100000 /* in µs */
+#define EXP 753 /* exp(-1) in fixed-point */
+
+struct spu_gov_info_struct {
+ unsigned long busy_spus; /* fixed-point */
+ struct cpufreq_policy *policy;
+ struct delayed_work work;
+ unsigned int poll_int; /* µs */
+};
+static DEFINE_PER_CPU(struct spu_gov_info_struct, spu_gov_info);
+
+static struct workqueue_struct *kspugov_wq;
+
+static int calc_freq(struct spu_gov_info_struct *info)
+{
+ int cpu;
+ int busy_spus;
+
+ cpu = info->policy->cpu;
+ busy_spus = atomic_read(&cbe_spu_info[cpu_to_node(cpu)].busy_spus);
+
+ CALC_LOAD(info->busy_spus, EXP, busy_spus * FIXED_1);
+ pr_debug("cpu %d: busy_spus=%d, info->busy_spus=%ld\n",
+ cpu, busy_spus, info->busy_spus);
+
+ return info->policy->max * info->busy_spus / FIXED_1;
+}
+
+static void spu_gov_work(struct work_struct *work)
+{
+ struct spu_gov_info_struct *info;
+ int delay;
+ unsigned long target_freq;
+
+ info = container_of(work, struct spu_gov_info_struct, work.work);
+
+ /* after cancel_delayed_work_sync we unset info->policy */
+ BUG_ON(info->policy == NULL);
+
+ target_freq = calc_freq(info);
+ __cpufreq_driver_target(info->policy, target_freq, CPUFREQ_RELATION_H);
+
+ delay = usecs_to_jiffies(info->poll_int);
+ queue_delayed_work_on(info->policy->cpu, kspugov_wq, &info->work, delay);
+}
+
+static void spu_gov_init_work(struct spu_gov_info_struct *info)
+{
+ int delay = usecs_to_jiffies(info->poll_int);
+ INIT_DELAYED_WORK_DEFERRABLE(&info->work, spu_gov_work);
+ queue_delayed_work_on(info->policy->cpu, kspugov_wq, &info->work, delay);
+}
+
+static void spu_gov_cancel_work(struct spu_gov_info_struct *info)
+{
+ cancel_delayed_work_sync(&info->work);
+}
+
+static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event)
+{
+ unsigned int cpu = policy->cpu;
+ struct spu_gov_info_struct *info, *affected_info;
+ int i;
+ int ret = 0;
+
+ info = &per_cpu(spu_gov_info, cpu);
+
+ switch (event) {
+ case CPUFREQ_GOV_START:
+ if (!cpu_online(cpu)) {
+ printk(KERN_ERR "cpu %d is not online\n", cpu);
+ ret = -EINVAL;
+ break;
+ }
+
+ if (!policy->cur) {
+ printk(KERN_ERR "no cpu specified in policy\n");
+ ret = -EINVAL;
+ break;
+ }
+
+ /* initialize spu_gov_info for all affected cpus */
+ for_each_cpu_mask(i, policy->cpus) {
+ affected_info = &per_cpu(spu_gov_info, i);
+ affected_info->policy = policy;
+ }
+
+ info->poll_int = POLL_TIME;
+
+ /* setup timer */
+ spu_gov_init_work(info);
+
+ break;
+
+ case CPUFREQ_GOV_STOP:
+ /* cancel timer */
+ spu_gov_cancel_work(info);
+
+ /* clean spu_gov_info for all affected cpus */
+ for_each_cpu_mask (i, policy->cpus) {
+ info = &per_cpu(spu_gov_info, i);
+ info->policy = NULL;
+ }
+
+ break;
+ }
+
+ return ret;
+}
+
+static struct cpufreq_governor spu_governor = {
+ .name = "spudemand",
+ .governor = spu_gov_govern,
+ .owner = THIS_MODULE,
+};
+
+/*
+ * module init and destoy
+ */
+
+static int __init spu_gov_init(void)
+{
+ int ret;
+
+ kspugov_wq = create_workqueue("kspugov");
+ if (!kspugov_wq) {
+ printk(KERN_ERR "creation of kspugov failed\n");
+ ret = -EFAULT;
+ goto out;
+ }
+
+ ret = cpufreq_register_governor(&spu_governor);
+ if (ret) {
+ printk(KERN_ERR "registration of governor failed\n");
+ destroy_workqueue(kspugov_wq);
+ goto out;
+ }
+out:
+ return ret;
+}
+
+static void __exit spu_gov_exit(void)
+{
+ cpufreq_unregister_governor(&spu_governor);
+ destroy_workqueue(kspugov_wq);
+}
+
+
+module_init(spu_gov_init);
+module_exit(spu_gov_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
+
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index eeacb3a52ca..e06420af5fe 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -172,8 +172,9 @@ static void invalidate_tce_cache(struct cbe_iommu *iommu, unsigned long *pte,
}
}
-static void tce_build_cell(struct iommu_table *tbl, long index, long npages,
- unsigned long uaddr, enum dma_data_direction direction)
+static int tce_build_cell(struct iommu_table *tbl, long index, long npages,
+ unsigned long uaddr, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
int i;
unsigned long *io_pte, base_pte;
@@ -198,6 +199,8 @@ static void tce_build_cell(struct iommu_table *tbl, long index, long npages,
base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW |
(window->ioid & IOPTE_IOID_Mask);
#endif
+ if (unlikely(dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs)))
+ base_pte &= ~IOPTE_SO_RW;
io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset);
@@ -210,6 +213,7 @@ static void tce_build_cell(struct iommu_table *tbl, long index, long npages,
pr_debug("tce_build_cell(index=%lx,n=%lx,dir=%d,base_pte=%lx)\n",
index, npages, direction, base_pte);
+ return 0;
}
static void tce_free_cell(struct iommu_table *tbl, long index, long npages)
@@ -519,7 +523,7 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np,
__set_bit(0, window->table.it_map);
tce_build_cell(&window->table, window->table.it_offset, 1,
- (unsigned long)iommu->pad_page, DMA_TO_DEVICE);
+ (unsigned long)iommu->pad_page, DMA_TO_DEVICE, NULL);
window->table.it_hint = window->table.it_blocksize;
return window;
@@ -538,7 +542,9 @@ static struct cbe_iommu *cell_iommu_for_node(int nid)
static unsigned long cell_dma_direct_offset;
static unsigned long dma_iommu_fixed_base;
-struct dma_mapping_ops dma_iommu_fixed_ops;
+
+/* iommu_fixed_is_weak is set if booted with iommu_fixed=weak */
+static int iommu_fixed_is_weak;
static struct iommu_table *cell_get_iommu_table(struct device *dev)
{
@@ -562,6 +568,98 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev)
return &window->table;
}
+/* A coherent allocation implies strong ordering */
+
+static void *dma_fixed_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
+{
+ if (iommu_fixed_is_weak)
+ return iommu_alloc_coherent(dev, cell_get_iommu_table(dev),
+ size, dma_handle,
+ device_to_mask(dev), flag,
+ dev->archdata.numa_node);
+ else
+ return dma_direct_ops.alloc_coherent(dev, size, dma_handle,
+ flag);
+}
+
+static void dma_fixed_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ if (iommu_fixed_is_weak)
+ iommu_free_coherent(cell_get_iommu_table(dev), size, vaddr,
+ dma_handle);
+ else
+ dma_direct_ops.free_coherent(dev, size, vaddr, dma_handle);
+}
+
+static dma_addr_t dma_fixed_map_single(struct device *dev, void *ptr,
+ size_t size,
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+ return dma_direct_ops.map_single(dev, ptr, size, direction,
+ attrs);
+ else
+ return iommu_map_single(dev, cell_get_iommu_table(dev), ptr,
+ size, device_to_mask(dev), direction,
+ attrs);
+}
+
+static void dma_fixed_unmap_single(struct device *dev, dma_addr_t dma_addr,
+ size_t size,
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+ dma_direct_ops.unmap_single(dev, dma_addr, size, direction,
+ attrs);
+ else
+ iommu_unmap_single(cell_get_iommu_table(dev), dma_addr, size,
+ direction, attrs);
+}
+
+static int dma_fixed_map_sg(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+ return dma_direct_ops.map_sg(dev, sg, nents, direction, attrs);
+ else
+ return iommu_map_sg(dev, cell_get_iommu_table(dev), sg, nents,
+ device_to_mask(dev), direction, attrs);
+}
+
+static void dma_fixed_unmap_sg(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
+{
+ if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+ dma_direct_ops.unmap_sg(dev, sg, nents, direction, attrs);
+ else
+ iommu_unmap_sg(cell_get_iommu_table(dev), sg, nents, direction,
+ attrs);
+}
+
+static int dma_fixed_dma_supported(struct device *dev, u64 mask)
+{
+ return mask == DMA_64BIT_MASK;
+}
+
+static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask);
+
+struct dma_mapping_ops dma_iommu_fixed_ops = {
+ .alloc_coherent = dma_fixed_alloc_coherent,
+ .free_coherent = dma_fixed_free_coherent,
+ .map_single = dma_fixed_map_single,
+ .unmap_single = dma_fixed_unmap_single,
+ .map_sg = dma_fixed_map_sg,
+ .unmap_sg = dma_fixed_unmap_sg,
+ .dma_supported = dma_fixed_dma_supported,
+ .set_dma_mask = dma_set_mask_and_switch,
+};
+
static void cell_dma_dev_setup_fixed(struct device *dev);
static void cell_dma_dev_setup(struct device *dev)
@@ -918,9 +1016,16 @@ static void cell_iommu_setup_fixed_ptab(struct cbe_iommu *iommu,
pr_debug("iommu: mapping 0x%lx pages from 0x%lx\n", fsize, fbase);
- base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW
+ base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M
| (cell_iommu_get_ioid(np) & IOPTE_IOID_Mask);
+ if (iommu_fixed_is_weak)
+ pr_info("IOMMU: Using weak ordering for fixed mapping\n");
+ else {
+ pr_info("IOMMU: Using strong ordering for fixed mapping\n");
+ base_pte |= IOPTE_SO_RW;
+ }
+
for (uaddr = 0; uaddr < fsize; uaddr += (1 << 24)) {
/* Don't touch the dynamic region */
ioaddr = uaddr + fbase;
@@ -1036,9 +1141,6 @@ static int __init cell_iommu_fixed_mapping_init(void)
cell_iommu_setup_window(iommu, np, dbase, dsize, 0);
}
- dma_iommu_fixed_ops = dma_direct_ops;
- dma_iommu_fixed_ops.set_dma_mask = dma_set_mask_and_switch;
-
dma_iommu_ops.set_dma_mask = dma_set_mask_and_switch;
set_pci_dma_ops(&dma_iommu_ops);
@@ -1049,9 +1151,23 @@ static int iommu_fixed_disabled;
static int __init setup_iommu_fixed(char *str)
{
+ struct device_node *pciep;
+
if (strcmp(str, "off") == 0)
iommu_fixed_disabled = 1;
+ /* If we can find a pcie-endpoint in the device tree assume that
+ * we're on a triblade or a CAB so by default the fixed mapping
+ * should be set to be weakly ordered; but only if the boot
+ * option WASN'T set for strong ordering
+ */
+ pciep = of_find_node_by_type(NULL, "pcie-endpoint");
+
+ if (strcmp(str, "weak") == 0 || (pciep && strcmp(str, "strong") != 0))
+ iommu_fixed_is_weak = 1;
+
+ of_node_put(pciep);
+
return 1;
}
__setup("iommu_fixed=", setup_iommu_fixed);
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index 8a3631ce912..efdacc82957 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -38,8 +38,6 @@
#include "pervasive.h"
-static int sysreset_hack;
-
static void cbe_power_save(void)
{
unsigned long ctrl, thread_switch_control;
@@ -87,9 +85,6 @@ static void cbe_power_save(void)
static int cbe_system_reset_exception(struct pt_regs *regs)
{
- int cpu;
- struct cbe_pmd_regs __iomem *pmd;
-
switch (regs->msr & SRR1_WAKEMASK) {
case SRR1_WAKEEE:
do_IRQ(regs);
@@ -98,19 +93,7 @@ static int cbe_system_reset_exception(struct pt_regs *regs)
timer_interrupt(regs);
break;
case SRR1_WAKEMT:
- /*
- * The BMC can inject user triggered system reset exceptions,
- * but cannot set the system reset reason in srr1,
- * so check an extra register here.
- */
- if (sysreset_hack && (cpu = smp_processor_id()) == 0) {
- pmd = cbe_get_cpu_pmd_regs(cpu);
- if (in_be64(&pmd->ras_esc_0) & 0xffff) {
- out_be64(&pmd->ras_esc_0, 0);
- return 0;
- }
- }
- break;
+ return cbe_sysreset_hack();
#ifdef CONFIG_CBE_RAS
case SRR1_WAKESYSERR:
cbe_system_error_exception(regs);
@@ -134,8 +117,6 @@ void __init cbe_pervasive_init(void)
if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
return;
- sysreset_hack = machine_is_compatible("IBM,CBPLUS-1.0");
-
for_each_possible_cpu(cpu) {
struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu);
if (!regs)
@@ -144,12 +125,6 @@ void __init cbe_pervasive_init(void)
/* Enable Pause(0) control bit */
out_be64(&regs->pmcr, in_be64(&regs->pmcr) |
CBE_PMD_PAUSE_ZERO_CONTROL);
-
- /* Enable JTAG system-reset hack */
- if (sysreset_hack)
- out_be32(&regs->fir_mode_reg,
- in_be32(&regs->fir_mode_reg) |
- CBE_PMD_FIR_MODE_M8);
}
ppc_md.power_save = cbe_power_save;
diff --git a/arch/powerpc/platforms/cell/pervasive.h b/arch/powerpc/platforms/cell/pervasive.h
index 7b50947f804..fd4d7b7092b 100644
--- a/arch/powerpc/platforms/cell/pervasive.h
+++ b/arch/powerpc/platforms/cell/pervasive.h
@@ -30,4 +30,13 @@ extern void cbe_system_error_exception(struct pt_regs *regs);
extern void cbe_maintenance_exception(struct pt_regs *regs);
extern void cbe_thermal_exception(struct pt_regs *regs);
+#ifdef CONFIG_PPC_IBM_CELL_RESETBUTTON
+extern int cbe_sysreset_hack(void);
+#else
+static inline int cbe_sysreset_hack(void)
+{
+ return 1;
+}
+#endif /* CONFIG_PPC_IBM_CELL_RESETBUTTON */
+
#endif
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
index 505f9b9bdf0..2a14b052abc 100644
--- a/arch/powerpc/platforms/cell/ras.c
+++ b/arch/powerpc/platforms/cell/ras.c
@@ -236,6 +236,52 @@ static struct notifier_block cbe_ptcal_reboot_notifier = {
.notifier_call = cbe_ptcal_notify_reboot
};
+#ifdef CONFIG_PPC_IBM_CELL_RESETBUTTON
+static int sysreset_hack;
+
+static int __init cbe_sysreset_init(void)
+{
+ struct cbe_pmd_regs __iomem *regs;
+
+ sysreset_hack = machine_is_compatible("IBM,CBPLUS-1.0");
+ if (!sysreset_hack)
+ return 0;
+
+ regs = cbe_get_cpu_pmd_regs(0);
+ if (!regs)
+ return 0;
+
+ /* Enable JTAG system-reset hack */
+ out_be32(&regs->fir_mode_reg,
+ in_be32(&regs->fir_mode_reg) |
+ CBE_PMD_FIR_MODE_M8);
+
+ return 0;
+}
+device_initcall(cbe_sysreset_init);
+
+int cbe_sysreset_hack(void)
+{
+ struct cbe_pmd_regs __iomem *regs;
+
+ /*
+ * The BMC can inject user triggered system reset exceptions,
+ * but cannot set the system reset reason in srr1,
+ * so check an extra register here.
+ */
+ if (sysreset_hack && (smp_processor_id() == 0)) {
+ regs = cbe_get_cpu_pmd_regs(0);
+ if (!regs)
+ return 0;
+ if (in_be64(&regs->ras_esc_0) & 0x0000ffff) {
+ out_be64(&regs->ras_esc_0, 0);
+ return 0;
+ }
+ }
+ return 1;
+}
+#endif /* CONFIG_PPC_IBM_CELL_RESETBUTTON */
+
int __init cbe_ptcal_init(void)
{
int ret;
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index 78f905bc6a4..a5bdb89a17c 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -703,7 +703,8 @@ static unsigned long long spu_acct_time(struct spu *spu,
}
-static ssize_t spu_stat_show(struct sys_device *sysdev, char *buf)
+static ssize_t spu_stat_show(struct sys_device *sysdev,
+ struct sysdev_attribute *attr, char *buf)
{
struct spu *spu = container_of(sysdev, struct spu, sysdev);
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 99c73066b82..010a51f5979 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -288,9 +288,32 @@ spufs_mem_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
return VM_FAULT_NOPAGE;
}
+static int spufs_mem_mmap_access(struct vm_area_struct *vma,
+ unsigned long address,
+ void *buf, int len, int write)
+{
+ struct spu_context *ctx = vma->vm_file->private_data;
+ unsigned long offset = address - vma->vm_start;
+ char *local_store;
+
+ if (write && !(vma->vm_flags & VM_WRITE))
+ return -EACCES;
+ if (spu_acquire(ctx))
+ return -EINTR;
+ if ((offset + len) > vma->vm_end)
+ len = vma->vm_end - offset;
+ local_store = ctx->ops->get_ls(ctx);
+ if (write)
+ memcpy_toio(local_store + offset, buf, len);
+ else
+ memcpy_fromio(buf, local_store + offset, len);
+ spu_release(ctx);
+ return len;
+}
static struct vm_operations_struct spufs_mem_mmap_vmops = {
.fault = spufs_mem_mmap_fault,
+ .access = spufs_mem_mmap_access,
};
static int spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 34654743363..2deeeba7ecc 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -312,11 +312,28 @@ static struct spu *aff_ref_location(struct spu_context *ctx, int mem_aff,
*/
node = cpu_to_node(raw_smp_processor_id());
for (n = 0; n < MAX_NUMNODES; n++, node++) {
+ int available_spus;
+
node = (node < MAX_NUMNODES) ? node : 0;
if (!node_allowed(ctx, node))
continue;
+
+ available_spus = 0;
mutex_lock(&cbe_spu_info[node].list_mutex);
list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) {
+ if (spu->ctx && spu->ctx->gang
+ && spu->ctx->aff_offset == 0)
+ available_spus -=
+ (spu->ctx->gang->contexts - 1);
+ else
+ available_spus++;
+ }
+ if (available_spus < ctx->gang->contexts) {
+ mutex_unlock(&cbe_spu_info[node].list_mutex);
+ continue;
+ }
+
+ list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) {
if ((!mem_aff || spu->has_mem_affinity) &&
sched_spu(spu)) {
mutex_unlock(&cbe_spu_info[node].list_mutex);
@@ -389,6 +406,9 @@ static int has_affinity(struct spu_context *ctx)
if (list_empty(&ctx->aff_list))
return 0;
+ if (atomic_read(&ctx->gang->aff_sched_count) == 0)
+ ctx->gang->aff_ref_spu = NULL;
+
if (!gang->aff_ref_spu) {
if (!(gang->aff_flags & AFF_MERGED))
aff_merge_remaining_ctxs(gang);
@@ -416,14 +436,8 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
if (spu->ctx->flags & SPU_CREATE_NOSCHED)
atomic_dec(&cbe_spu_info[spu->node].reserved_spus);
- if (ctx->gang){
- mutex_lock(&ctx->gang->aff_mutex);
- if (has_affinity(ctx)) {
- if (atomic_dec_and_test(&ctx->gang->aff_sched_count))
- ctx->gang->aff_ref_spu = NULL;
- }
- mutex_unlock(&ctx->gang->aff_mutex);
- }
+ if (ctx->gang)
+ atomic_dec_if_positive(&ctx->gang->aff_sched_count);
spu_switch_notify(spu, NULL);
spu_unmap_mappings(ctx);
@@ -562,10 +576,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx)
goto found;
mutex_unlock(&cbe_spu_info[node].list_mutex);
- mutex_lock(&ctx->gang->aff_mutex);
- if (atomic_dec_and_test(&ctx->gang->aff_sched_count))
- ctx->gang->aff_ref_spu = NULL;
- mutex_unlock(&ctx->gang->aff_mutex);
+ atomic_dec(&ctx->gang->aff_sched_count);
goto not_found;
}
mutex_unlock(&ctx->gang->aff_mutex);
diff --git a/arch/powerpc/platforms/cell/spufs/sputrace.c b/arch/powerpc/platforms/cell/spufs/sputrace.c
index 8c0e95766a6..92d20e993ed 100644
--- a/arch/powerpc/platforms/cell/spufs/sputrace.c
+++ b/arch/powerpc/platforms/cell/spufs/sputrace.c
@@ -196,8 +196,7 @@ static int __init sputrace_init(void)
struct proc_dir_entry *entry;
int i, error = -ENOMEM;
- sputrace_log = kcalloc(sizeof(struct sputrace),
- bufsize, GFP_KERNEL);
+ sputrace_log = kcalloc(bufsize, sizeof(struct sputrace), GFP_KERNEL);
if (!sputrace_log)
goto out;
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index 609c46db4a1..768c262b936 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -367,7 +367,7 @@ static void chrp_pci_fixup_vt8231_ata(struct pci_dev *viaide)
viaisa = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, NULL);
if (!viaisa)
return;
- printk("Fixing VIA IDE, force legacy mode on '%s'\n", viaide->dev.bus_id);
+ dev_info(&viaide->dev, "Fixing VIA IDE, force legacy mode on\n");
pci_read_config_byte(viaide, PCI_CLASS_PROG, &progif);
pci_write_config_byte(viaide, PCI_CLASS_PROG, progif & ~0x5);
diff --git a/arch/powerpc/platforms/fsl_uli1575.c b/arch/powerpc/platforms/fsl_uli1575.c
index afc9141be63..ef74a0763ec 100644
--- a/arch/powerpc/platforms/fsl_uli1575.c
+++ b/arch/powerpc/platforms/fsl_uli1575.c
@@ -51,15 +51,13 @@ u8 uli_pirq_to_irq[8] = {
ULI_8259_NONE, /* PIRQH */
};
-/* set in board code if you want this quirks to do something */
-int uses_fsl_uli_m1575;
-
/* Bridge */
static void __devinit early_uli5249(struct pci_dev *dev)
{
unsigned char temp;
- if (!uses_fsl_uli_m1575)
+ if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
+ !machine_is(mpc8572_ds))
return;
pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_IO |
@@ -82,7 +80,8 @@ static void __devinit quirk_uli1575(struct pci_dev *dev)
{
int i;
- if (!uses_fsl_uli_m1575)
+ if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
+ !machine_is(mpc8572_ds))
return;
/*
@@ -150,7 +149,8 @@ static void __devinit quirk_final_uli1575(struct pci_dev *dev)
* IRQ 14: Edge
* IRQ 15: Edge
*/
- if (!uses_fsl_uli_m1575)
+ if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
+ !machine_is(mpc8572_ds))
return;
outb(0xfa, 0x4d0);
@@ -176,7 +176,8 @@ static void __devinit quirk_uli5288(struct pci_dev *dev)
unsigned char c;
unsigned int d;
- if (!uses_fsl_uli_m1575)
+ if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
+ !machine_is(mpc8572_ds))
return;
/* read/write lock */
@@ -200,7 +201,8 @@ static void __devinit quirk_uli5229(struct pci_dev *dev)
{
unsigned short temp;
- if (!uses_fsl_uli_m1575)
+ if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
+ !machine_is(mpc8572_ds))
return;
pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE |
@@ -221,7 +223,7 @@ static void __devinit quirk_final_uli5249(struct pci_dev *dev)
for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
if ((bus->resource[i]) &&
(bus->resource[i]->flags & IORESOURCE_MEM)) {
- dummy = ioremap(bus->resource[i]->start, 0x4);
+ dummy = ioremap(bus->resource[i]->end - 3, 0x4);
if (dummy) {
in_8(dummy);
iounmap(dummy);
@@ -238,6 +240,103 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x5249, quirk_final_uli5249);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x1575, quirk_final_uli1575);
+static void __devinit hpcd_quirk_uli1575(struct pci_dev *dev)
+{
+ u32 temp32;
+
+ if (!machine_is(mpc86xx_hpcd))
+ return;
+
+ /* Disable INTx */
+ pci_read_config_dword(dev, 0x48, &temp32);
+ pci_write_config_dword(dev, 0x48, (temp32 | 1<<26));
+
+ /* Enable sideband interrupt */
+ pci_read_config_dword(dev, 0x90, &temp32);
+ pci_write_config_dword(dev, 0x90, (temp32 | 1<<22));
+}
+
+static void __devinit hpcd_quirk_uli5288(struct pci_dev *dev)
+{
+ unsigned char c;
+ unsigned short temp;
+
+ if (!machine_is(mpc86xx_hpcd))
+ return;
+
+ /* Interrupt Disable, Needed when SATA disabled */
+ pci_read_config_word(dev, PCI_COMMAND, &temp);
+ temp |= 1<<10;
+ pci_write_config_word(dev, PCI_COMMAND, temp);
+
+ pci_read_config_byte(dev, 0x83, &c);
+ c |= 0x80;
+ pci_write_config_byte(dev, 0x83, c);
+
+ pci_write_config_byte(dev, PCI_CLASS_PROG, 0x01);
+ pci_write_config_byte(dev, PCI_CLASS_DEVICE, 0x06);
+
+ pci_read_config_byte(dev, 0x83, &c);
+ c &= 0x7f;
+ pci_write_config_byte(dev, 0x83, c);
+}
+
+/*
+ * Since 8259PIC was disabled on the board, the IDE device can not
+ * use the legacy IRQ, we need to let the IDE device work under
+ * native mode and use the interrupt line like other PCI devices.
+ * IRQ14 is a sideband interrupt from IDE device to CPU and we use this
+ * as the interrupt for IDE device.
+ */
+static void __devinit hpcd_quirk_uli5229(struct pci_dev *dev)
+{
+ unsigned char c;
+
+ if (!machine_is(mpc86xx_hpcd))
+ return;
+
+ pci_read_config_byte(dev, 0x4b, &c);
+ c |= 0x10;
+ pci_write_config_byte(dev, 0x4b, c);
+}
+
+/*
+ * SATA interrupt pin bug fix
+ * There's a chip bug for 5288, The interrupt pin should be 2,
+ * not the read only value 1, So it use INTB#, not INTA# which
+ * actually used by the IDE device 5229.
+ * As of this bug, during the PCI initialization, 5288 read the
+ * irq of IDE device from the device tree, this function fix this
+ * bug by re-assigning a correct irq to 5288.
+ *
+ */
+static void __devinit hpcd_final_uli5288(struct pci_dev *dev)
+{
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct device_node *hosenode = hose ? hose->dn : NULL;
+ struct of_irq oirq;
+ int virq, pin = 2;
+ u32 laddr[3];
+
+ if (!machine_is(mpc86xx_hpcd))
+ return;
+
+ if (!hosenode)
+ return;
+
+ laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(31, 0) << 8);
+ laddr[1] = laddr[2] = 0;
+ of_irq_map_raw(hosenode, &pin, 1, laddr, &oirq);
+ virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+ oirq.size);
+ dev->irq = virq;
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, hpcd_quirk_uli1575);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, hpcd_quirk_uli5288);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, hpcd_quirk_uli5229);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x5288, hpcd_final_uli5288);
+
int uli_exclude_device(struct pci_controller *hose,
u_char bus, u_char devfn)
{
diff --git a/arch/powerpc/platforms/iseries/Kconfig b/arch/powerpc/platforms/iseries/Kconfig
index 761d9e971fc..ea3e541ac74 100644
--- a/arch/powerpc/platforms/iseries/Kconfig
+++ b/arch/powerpc/platforms/iseries/Kconfig
@@ -2,6 +2,7 @@ config PPC_ISERIES
bool "IBM Legacy iSeries"
depends on PPC_MULTIPLATFORM && PPC64
select PPC_INDIRECT_IO
+ select PPC_PCI_CHOICE if EMBEDDED
menu "iSeries device drivers"
depends on PPC_ISERIES
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index ab5d8687c3c..bb464d1211b 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -41,8 +41,9 @@
#include <asm/iseries/hv_call_event.h>
#include <asm/iseries/iommu.h>
-static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
- unsigned long uaddr, enum dma_data_direction direction)
+static int tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
+ unsigned long uaddr, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
u64 rc;
u64 tce, rpn;
@@ -70,6 +71,7 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
index++;
uaddr += TCE_PAGE_SIZE;
}
+ return 0;
}
static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages)
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index b72120751bb..70b688c1aef 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -561,7 +561,7 @@ static void yield_shared_processor(void)
static void iseries_shared_idle(void)
{
while (1) {
- tick_nohz_stop_sched_tick();
+ tick_nohz_stop_sched_tick(1);
while (!need_resched() && !hvlpevent_is_pending()) {
local_irq_disable();
ppc64_runlatch_off();
@@ -591,7 +591,7 @@ static void iseries_dedicated_idle(void)
set_thread_flag(TIF_POLLING_NRFLAG);
while (1) {
- tick_nohz_stop_sched_tick();
+ tick_nohz_stop_sched_tick(1);
if (!need_resched()) {
while (!need_resched()) {
ppc64_runlatch_off();
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c
index 86967bdd877..a0ff03a3d8d 100644
--- a/arch/powerpc/platforms/pasemi/iommu.c
+++ b/arch/powerpc/platforms/pasemi/iommu.c
@@ -83,9 +83,10 @@ static u32 *iob_l2_base;
static struct iommu_table iommu_table_iobmap;
static int iommu_table_iobmap_inited;
-static void iobmap_build(struct iommu_table *tbl, long index,
+static int iobmap_build(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
u32 *ip;
u32 rpn;
@@ -107,6 +108,7 @@ static void iobmap_build(struct iommu_table *tbl, long index,
uaddr += IOBMAP_PAGE_SIZE;
bus_addr += IOBMAP_PAGE_SIZE;
}
+ return 0;
}
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 00bd0166d07..31635446901 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -97,8 +97,6 @@ extern struct machdep_calls pmac_md;
int sccdbg;
#endif
-extern void zs_kgdb_hook(int tty_num);
-
sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
EXPORT_SYMBOL(sys_ctrler);
@@ -329,10 +327,6 @@ static void __init pmac_setup_arch(void)
l2cr_init();
#endif /* CONFIG_PPC32 */
-#ifdef CONFIG_KGDB
- zs_kgdb_hook(0);
-#endif
-
find_via_cuda();
find_via_pmu();
smu_init();
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index a5f4e95dfc3..920cf7a454b 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -8,6 +8,7 @@ config PPC_PS3
select USB_ARCH_HAS_EHCI
select USB_EHCI_BIG_ENDIAN_MMIO
select MEMORY_HOTPLUG
+ select PPC_PCI_CHOICE
help
This option enables support for the Sony PS3 game console
and other platforms using the PS3 hypervisor. Enabling this
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c
index 3866debfa3c..ffdd8e963fb 100644
--- a/arch/powerpc/platforms/ps3/device-init.c
+++ b/arch/powerpc/platforms/ps3/device-init.c
@@ -486,6 +486,7 @@ static int __init ps3_register_graphics_devices(void)
return -ENOMEM;
p->dev.match_id = PS3_MATCH_ID_GRAPHICS;
+ p->dev.match_sub_id = PS3_MATCH_SUB_ID_FB;
p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
result = ps3_system_bus_device_register(&p->dev);
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index d66c3628a11..280ee88cb0b 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -347,16 +347,23 @@ static int ps3_system_bus_match(struct device *_dev,
struct ps3_system_bus_driver *drv = ps3_drv_to_system_bus_drv(_drv);
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
- result = dev->match_id == drv->match_id;
+ if (!dev->match_sub_id)
+ result = dev->match_id == drv->match_id;
+ else
+ result = dev->match_sub_id == drv->match_sub_id &&
+ dev->match_id == drv->match_id;
if (result)
- pr_info("%s:%d: dev=%u(%s), drv=%u(%s): match\n", __func__,
- __LINE__, dev->match_id, dev->core.bus_id,
- drv->match_id, drv->core.name);
+ pr_info("%s:%d: dev=%u.%u(%s), drv=%u.%u(%s): match\n",
+ __func__, __LINE__,
+ dev->match_id, dev->match_sub_id, dev->core.bus_id,
+ drv->match_id, drv->match_sub_id, drv->core.name);
else
- pr_debug("%s:%d: dev=%u(%s), drv=%u(%s): miss\n", __func__,
- __LINE__, dev->match_id, dev->core.bus_id,
- drv->match_id, drv->core.name);
+ pr_debug("%s:%d: dev=%u.%u(%s), drv=%u.%u(%s): miss\n",
+ __func__, __LINE__,
+ dev->match_id, dev->match_sub_id, dev->core.bus_id,
+ drv->match_id, drv->match_sub_id, drv->core.name);
+
return result;
}
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index 07fe5b69b9e..97619fd51e3 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -7,6 +7,7 @@ config PPC_PSERIES
select RTAS_ERROR_LOGGING
select PPC_UDBG_16550
select PPC_NATIVE
+ select PPC_PCI_CHOICE if EMBEDDED
default y
config PPC_SPLPAR
@@ -39,3 +40,26 @@ config PPC_PSERIES_DEBUG
depends on PPC_PSERIES && PPC_EARLY_DEBUG
bool "Enable extra debug logging in platforms/pseries"
default y
+
+config PPC_SMLPAR
+ bool "Support for shared-memory logical partitions"
+ depends on PPC_PSERIES
+ select LPARCFG
+ default n
+ help
+ Select this option to enable shared memory partition support.
+ With this option a system running in an LPAR can be given more
+ memory than physically available and will allow firmware to
+ balance memory across many LPARs.
+
+config CMM
+ tristate "Collaborative memory management"
+ depends on PPC_SMLPAR
+ default y
+ help
+ Select this option, if you want to enable the kernel interface
+ to reduce the memory size of the system. This is accomplished
+ by allocating pages of memory and put them "on hold". This only
+ makes sense for a system running in an LPAR where the unused pages
+ will be reused for other LPARs. The interface allows firmware to
+ balance memory across many LPARs.
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 554c6e42ef2..dfe574af2dc 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -24,3 +24,4 @@ obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
obj-$(CONFIG_HVCS) += hvcserver.o
obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o
obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o
+obj-$(CONFIG_CMM) += cmm.o
diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c
new file mode 100644
index 00000000000..c6b3be03168
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/cmm.c
@@ -0,0 +1,468 @@
+/*
+ * Collaborative memory management interface.
+ *
+ * Copyright (C) 2008 IBM Corporation
+ * Author(s): Brian King (brking@linux.vnet.ibm.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/oom.h>
+#include <linux/sched.h>
+#include <linux/stringify.h>
+#include <linux/swap.h>
+#include <linux/sysdev.h>
+#include <asm/firmware.h>
+#include <asm/hvcall.h>
+#include <asm/mmu.h>
+#include <asm/pgalloc.h>
+#include <asm/uaccess.h>
+
+#include "plpar_wrappers.h"
+
+#define CMM_DRIVER_VERSION "1.0.0"
+#define CMM_DEFAULT_DELAY 1
+#define CMM_DEBUG 0
+#define CMM_DISABLE 0
+#define CMM_OOM_KB 1024
+#define CMM_MIN_MEM_MB 256
+#define KB2PAGES(_p) ((_p)>>(PAGE_SHIFT-10))
+#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
+
+static unsigned int delay = CMM_DEFAULT_DELAY;
+static unsigned int oom_kb = CMM_OOM_KB;
+static unsigned int cmm_debug = CMM_DEBUG;
+static unsigned int cmm_disabled = CMM_DISABLE;
+static unsigned long min_mem_mb = CMM_MIN_MEM_MB;
+static struct sys_device cmm_sysdev;
+
+MODULE_AUTHOR("Brian King <brking@linux.vnet.ibm.com>");
+MODULE_DESCRIPTION("IBM System p Collaborative Memory Manager");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CMM_DRIVER_VERSION);
+
+module_param_named(delay, delay, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(delay, "Delay (in seconds) between polls to query hypervisor paging requests. "
+ "[Default=" __stringify(CMM_DEFAULT_DELAY) "]");
+module_param_named(oom_kb, oom_kb, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(oom_kb, "Amount of memory in kb to free on OOM. "
+ "[Default=" __stringify(CMM_OOM_KB) "]");
+module_param_named(min_mem_mb, min_mem_mb, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(min_mem_mb, "Minimum amount of memory (in MB) to not balloon. "
+ "[Default=" __stringify(CMM_MIN_MEM_MB) "]");
+module_param_named(debug, cmm_debug, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable module debugging logging. Set to 1 to enable. "
+ "[Default=" __stringify(CMM_DEBUG) "]");
+
+#define CMM_NR_PAGES ((PAGE_SIZE - sizeof(void *) - sizeof(unsigned long)) / sizeof(unsigned long))
+
+#define cmm_dbg(...) if (cmm_debug) { printk(KERN_INFO "cmm: "__VA_ARGS__); }
+
+struct cmm_page_array {
+ struct cmm_page_array *next;
+ unsigned long index;
+ unsigned long page[CMM_NR_PAGES];
+};
+
+static unsigned long loaned_pages;
+static unsigned long loaned_pages_target;
+static unsigned long oom_freed_pages;
+
+static struct cmm_page_array *cmm_page_list;
+static DEFINE_SPINLOCK(cmm_lock);
+
+static struct task_struct *cmm_thread_ptr;
+
+/**
+ * cmm_alloc_pages - Allocate pages and mark them as loaned
+ * @nr: number of pages to allocate
+ *
+ * Return value:
+ * number of pages requested to be allocated which were not
+ **/
+static long cmm_alloc_pages(long nr)
+{
+ struct cmm_page_array *pa, *npa;
+ unsigned long addr;
+ long rc;
+
+ cmm_dbg("Begin request for %ld pages\n", nr);
+
+ while (nr) {
+ addr = __get_free_page(GFP_NOIO | __GFP_NOWARN |
+ __GFP_NORETRY | __GFP_NOMEMALLOC);
+ if (!addr)
+ break;
+ spin_lock(&cmm_lock);
+ pa = cmm_page_list;
+ if (!pa || pa->index >= CMM_NR_PAGES) {
+ /* Need a new page for the page list. */
+ spin_unlock(&cmm_lock);
+ npa = (struct cmm_page_array *)__get_free_page(GFP_NOIO | __GFP_NOWARN |
+ __GFP_NORETRY | __GFP_NOMEMALLOC);
+ if (!npa) {
+ pr_info("%s: Can not allocate new page list\n", __FUNCTION__);
+ free_page(addr);
+ break;
+ }
+ spin_lock(&cmm_lock);
+ pa = cmm_page_list;
+
+ if (!pa || pa->index >= CMM_NR_PAGES) {
+ npa->next = pa;
+ npa->index = 0;
+ pa = npa;
+ cmm_page_list = pa;
+ } else
+ free_page((unsigned long) npa);
+ }
+
+ if ((rc = plpar_page_set_loaned(__pa(addr)))) {
+ pr_err("%s: Can not set page to loaned. rc=%ld\n", __FUNCTION__, rc);
+ spin_unlock(&cmm_lock);
+ free_page(addr);
+ break;
+ }
+
+ pa->page[pa->index++] = addr;
+ loaned_pages++;
+ totalram_pages--;
+ spin_unlock(&cmm_lock);
+ nr--;
+ }
+
+ cmm_dbg("End request with %ld pages unfulfilled\n", nr);
+ return nr;
+}
+
+/**
+ * cmm_free_pages - Free pages and mark them as active
+ * @nr: number of pages to free
+ *
+ * Return value:
+ * number of pages requested to be freed which were not
+ **/
+static long cmm_free_pages(long nr)
+{
+ struct cmm_page_array *pa;
+ unsigned long addr;
+
+ cmm_dbg("Begin free of %ld pages.\n", nr);
+ spin_lock(&cmm_lock);
+ pa = cmm_page_list;
+ while (nr) {
+ if (!pa || pa->index <= 0)
+ break;
+ addr = pa->page[--pa->index];
+
+ if (pa->index == 0) {
+ pa = pa->next;
+ free_page((unsigned long) cmm_page_list);
+ cmm_page_list = pa;
+ }
+
+ plpar_page_set_active(__pa(addr));
+ free_page(addr);
+ loaned_pages--;
+ nr--;
+ totalram_pages++;
+ }
+ spin_unlock(&cmm_lock);
+ cmm_dbg("End request with %ld pages unfulfilled\n", nr);
+ return nr;
+}
+
+/**
+ * cmm_oom_notify - OOM notifier
+ * @self: notifier block struct
+ * @dummy: not used
+ * @parm: returned - number of pages freed
+ *
+ * Return value:
+ * NOTIFY_OK
+ **/
+static int cmm_oom_notify(struct notifier_block *self,
+ unsigned long dummy, void *parm)
+{
+ unsigned long *freed = parm;
+ long nr = KB2PAGES(oom_kb);
+
+ cmm_dbg("OOM processing started\n");
+ nr = cmm_free_pages(nr);
+ loaned_pages_target = loaned_pages;
+ *freed += KB2PAGES(oom_kb) - nr;
+ oom_freed_pages += KB2PAGES(oom_kb) - nr;
+ cmm_dbg("OOM processing complete\n");
+ return NOTIFY_OK;
+}
+
+/**
+ * cmm_get_mpp - Read memory performance parameters
+ *
+ * Makes hcall to query the current page loan request from the hypervisor.
+ *
+ * Return value:
+ * nothing
+ **/
+static void cmm_get_mpp(void)
+{
+ int rc;
+ struct hvcall_mpp_data mpp_data;
+ unsigned long active_pages_target;
+ signed long page_loan_request;
+
+ rc = h_get_mpp(&mpp_data);
+
+ if (rc != H_SUCCESS)
+ return;
+
+ page_loan_request = div_s64((s64)mpp_data.loan_request, PAGE_SIZE);
+ loaned_pages_target = page_loan_request + loaned_pages;
+ if (loaned_pages_target > oom_freed_pages)
+ loaned_pages_target -= oom_freed_pages;
+ else
+ loaned_pages_target = 0;
+
+ active_pages_target = totalram_pages + loaned_pages - loaned_pages_target;
+
+ if ((min_mem_mb * 1024 * 1024) > (active_pages_target * PAGE_SIZE))
+ loaned_pages_target = totalram_pages + loaned_pages -
+ ((min_mem_mb * 1024 * 1024) / PAGE_SIZE);
+
+ cmm_dbg("delta = %ld, loaned = %lu, target = %lu, oom = %lu, totalram = %lu\n",
+ page_loan_request, loaned_pages, loaned_pages_target,
+ oom_freed_pages, totalram_pages);
+}
+
+static struct notifier_block cmm_oom_nb = {
+ .notifier_call = cmm_oom_notify
+};
+
+/**
+ * cmm_thread - CMM task thread
+ * @dummy: not used
+ *
+ * Return value:
+ * 0
+ **/
+static int cmm_thread(void *dummy)
+{
+ unsigned long timeleft;
+
+ while (1) {
+ timeleft = msleep_interruptible(delay * 1000);
+
+ if (kthread_should_stop() || timeleft) {
+ loaned_pages_target = loaned_pages;
+ break;
+ }
+
+ cmm_get_mpp();
+
+ if (loaned_pages_target > loaned_pages) {
+ if (cmm_alloc_pages(loaned_pages_target - loaned_pages))
+ loaned_pages_target = loaned_pages;
+ } else if (loaned_pages_target < loaned_pages)
+ cmm_free_pages(loaned_pages - loaned_pages_target);
+ }
+ return 0;
+}
+
+#define CMM_SHOW(name, format, args...) \
+ static ssize_t show_##name(struct sys_device *dev, char *buf) \
+ { \
+ return sprintf(buf, format, ##args); \
+ } \
+ static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL)
+
+CMM_SHOW(loaned_kb, "%lu\n", PAGES2KB(loaned_pages));
+CMM_SHOW(loaned_target_kb, "%lu\n", PAGES2KB(loaned_pages_target));
+
+static ssize_t show_oom_pages(struct sys_device *dev, char *buf)
+{
+ return sprintf(buf, "%lu\n", PAGES2KB(oom_freed_pages));
+}
+
+static ssize_t store_oom_pages(struct sys_device *dev,
+ const char *buf, size_t count)
+{
+ unsigned long val = simple_strtoul (buf, NULL, 10);
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (val != 0)
+ return -EBADMSG;
+
+ oom_freed_pages = 0;
+ return count;
+}
+
+static SYSDEV_ATTR(oom_freed_kb, S_IWUSR| S_IRUGO,
+ show_oom_pages, store_oom_pages);
+
+static struct sysdev_attribute *cmm_attrs[] = {
+ &attr_loaned_kb,
+ &attr_loaned_target_kb,
+ &attr_oom_freed_kb,
+};
+
+static struct sysdev_class cmm_sysdev_class = {
+ .name = "cmm",
+};
+
+/**
+ * cmm_sysfs_register - Register with sysfs
+ *
+ * Return value:
+ * 0 on success / other on failure
+ **/
+static int cmm_sysfs_register(struct sys_device *sysdev)
+{
+ int i, rc;
+
+ if ((rc = sysdev_class_register(&cmm_sysdev_class)))
+ return rc;
+
+ sysdev->id = 0;
+ sysdev->cls = &cmm_sysdev_class;
+
+ if ((rc = sysdev_register(sysdev)))
+ goto class_unregister;
+
+ for (i = 0; i < ARRAY_SIZE(cmm_attrs); i++) {
+ if ((rc = sysdev_create_file(sysdev, cmm_attrs[i])))
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ while (--i >= 0)
+ sysdev_remove_file(sysdev, cmm_attrs[i]);
+ sysdev_unregister(sysdev);
+class_unregister:
+ sysdev_class_unregister(&cmm_sysdev_class);
+ return rc;
+}
+
+/**
+ * cmm_unregister_sysfs - Unregister from sysfs
+ *
+ **/
+static void cmm_unregister_sysfs(struct sys_device *sysdev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cmm_attrs); i++)
+ sysdev_remove_file(sysdev, cmm_attrs[i]);
+ sysdev_unregister(sysdev);
+ sysdev_class_unregister(&cmm_sysdev_class);
+}
+
+/**
+ * cmm_init - Module initialization
+ *
+ * Return value:
+ * 0 on success / other on failure
+ **/
+static int cmm_init(void)
+{
+ int rc = -ENOMEM;
+
+ if (!firmware_has_feature(FW_FEATURE_CMO))
+ return -EOPNOTSUPP;
+
+ if ((rc = register_oom_notifier(&cmm_oom_nb)) < 0)
+ return rc;
+
+ if ((rc = cmm_sysfs_register(&cmm_sysdev)))
+ goto out_oom_notifier;
+
+ if (cmm_disabled)
+ return rc;
+
+ cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
+ if (IS_ERR(cmm_thread_ptr)) {
+ rc = PTR_ERR(cmm_thread_ptr);
+ goto out_unregister_sysfs;
+ }
+
+ return rc;
+
+out_unregister_sysfs:
+ cmm_unregister_sysfs(&cmm_sysdev);
+out_oom_notifier:
+ unregister_oom_notifier(&cmm_oom_nb);
+ return rc;
+}
+
+/**
+ * cmm_exit - Module exit
+ *
+ * Return value:
+ * nothing
+ **/
+static void cmm_exit(void)
+{
+ if (cmm_thread_ptr)
+ kthread_stop(cmm_thread_ptr);
+ unregister_oom_notifier(&cmm_oom_nb);
+ cmm_free_pages(loaned_pages);
+ cmm_unregister_sysfs(&cmm_sysdev);
+}
+
+/**
+ * cmm_set_disable - Disable/Enable CMM
+ *
+ * Return value:
+ * 0 on success / other on failure
+ **/
+static int cmm_set_disable(const char *val, struct kernel_param *kp)
+{
+ int disable = simple_strtoul(val, NULL, 10);
+
+ if (disable != 0 && disable != 1)
+ return -EINVAL;
+
+ if (disable && !cmm_disabled) {
+ if (cmm_thread_ptr)
+ kthread_stop(cmm_thread_ptr);
+ cmm_thread_ptr = NULL;
+ cmm_free_pages(loaned_pages);
+ } else if (!disable && cmm_disabled) {
+ cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
+ if (IS_ERR(cmm_thread_ptr))
+ return PTR_ERR(cmm_thread_ptr);
+ }
+
+ cmm_disabled = disable;
+ return 0;
+}
+
+module_param_call(disable, cmm_set_disable, param_get_uint,
+ &cmm_disabled, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(disable, "Disable CMM. Set to 1 to disable. "
+ "[Default=" __stringify(CMM_DISABLE) "]");
+
+module_init(cmm_init);
+module_exit(cmm_exit);
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index c027f0a70a0..54816d75b57 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -75,9 +75,9 @@
*/
/* If a device driver keeps reading an MMIO register in an interrupt
- * handler after a slot isolation event has occurred, we assume it
- * is broken and panic. This sets the threshold for how many read
- * attempts we allow before panicking.
+ * handler after a slot isolation event, it might be broken.
+ * This sets the threshold for how many read attempts we allow
+ * before printing an error message.
*/
#define EEH_MAX_FAILS 2100000
@@ -470,6 +470,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
unsigned long flags;
struct pci_dn *pdn;
int rc = 0;
+ const char *location;
total_mmio_ffs++;
@@ -509,18 +510,15 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
rc = 1;
if (pdn->eeh_mode & EEH_MODE_ISOLATED) {
pdn->eeh_check_count ++;
- if (pdn->eeh_check_count >= EEH_MAX_FAILS) {
- printk (KERN_ERR "EEH: Device driver ignored %d bad reads, panicing\n",
- pdn->eeh_check_count);
+ if (pdn->eeh_check_count % EEH_MAX_FAILS == 0) {
+ location = of_get_property(dn, "ibm,loc-code", NULL);
+ printk (KERN_ERR "EEH: %d reads ignored for recovering device at "
+ "location=%s driver=%s pci addr=%s\n",
+ pdn->eeh_check_count, location,
+ dev->driver->name, pci_name(dev));
+ printk (KERN_ERR "EEH: Might be infinite loop in %s driver\n",
+ dev->driver->name);
dump_stack();
- msleep(5000);
-
- /* re-read the slot reset state */
- if (read_slot_reset_state(pdn, rets) != 0)
- rets[0] = -1; /* reset state unknown */
-
- /* If we are here, then we hit an infinite loop. Stop. */
- panic("EEH: MMIO halt (%d) on device:%s\n", rets[0], pci_name(dev));
}
goto dn_unlock;
}
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 9a12908510f..a8c446697f9 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -48,9 +48,10 @@
#include "plpar_wrappers.h"
-static void tce_build_pSeries(struct iommu_table *tbl, long index,
+static int tce_build_pSeries(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
u64 proto_tce;
u64 *tcep;
@@ -71,6 +72,7 @@ static void tce_build_pSeries(struct iommu_table *tbl, long index,
uaddr += TCE_PAGE_SIZE;
tcep++;
}
+ return 0;
}
@@ -93,13 +95,19 @@ static unsigned long tce_get_pseries(struct iommu_table *tbl, long index)
return *tcep;
}
-static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
+static void tce_free_pSeriesLP(struct iommu_table*, long, long);
+static void tce_freemulti_pSeriesLP(struct iommu_table*, long, long);
+
+static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
long npages, unsigned long uaddr,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
- u64 rc;
+ u64 rc = 0;
u64 proto_tce, tce;
u64 rpn;
+ int ret = 0;
+ long tcenum_start = tcenum, npages_start = npages;
rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
proto_tce = TCE_PCI_READ;
@@ -110,6 +118,13 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce);
+ if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) {
+ ret = (int)rc;
+ tce_free_pSeriesLP(tbl, tcenum_start,
+ (npages_start - (npages + 1)));
+ break;
+ }
+
if (rc && printk_ratelimit()) {
printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
@@ -121,23 +136,27 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
tcenum++;
rpn++;
}
+ return ret;
}
static DEFINE_PER_CPU(u64 *, tce_page) = NULL;
-static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
+static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
long npages, unsigned long uaddr,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
- u64 rc;
+ u64 rc = 0;
u64 proto_tce;
u64 *tcep;
u64 rpn;
long l, limit;
+ long tcenum_start = tcenum, npages_start = npages;
+ int ret = 0;
if (npages == 1) {
- tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, direction);
- return;
+ return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
+ direction, attrs);
}
tcep = __get_cpu_var(tce_page);
@@ -149,9 +168,8 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
tcep = (u64 *)__get_free_page(GFP_ATOMIC);
/* If allocation fails, fall back to the loop implementation */
if (!tcep) {
- tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
- direction);
- return;
+ return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
+ direction, attrs);
}
__get_cpu_var(tce_page) = tcep;
}
@@ -183,6 +201,13 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
tcenum += limit;
} while (npages > 0 && !rc);
+ if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) {
+ ret = (int)rc;
+ tce_freemulti_pSeriesLP(tbl, tcenum_start,
+ (npages_start - (npages + limit)));
+ return ret;
+ }
+
if (rc && printk_ratelimit()) {
printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
@@ -190,6 +215,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
printk("\ttce[0] val = 0x%lx\n", tcep[0]);
show_stack(current, (unsigned long *)__get_SP());
}
+ return ret;
}
static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index d8680b589dc..a437267c6bf 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -42,6 +42,16 @@ static inline long register_slb_shadow(unsigned long cpu, unsigned long vpa)
return vpa_call(0x3, cpu, vpa);
}
+static inline long plpar_page_set_loaned(unsigned long vpa)
+{
+ return plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED, vpa, 0);
+}
+
+static inline long plpar_page_set_active(unsigned long vpa)
+{
+ return plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE, vpa, 0);
+}
+
extern void vpa_init(int cpu);
static inline long plpar_pte_enter(unsigned long flags,
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 90beb444e1d..063a0d2fba3 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -314,6 +314,76 @@ static int pseries_set_xdabr(unsigned long dabr)
H_DABRX_KERNEL | H_DABRX_USER);
}
+#define CMO_CHARACTERISTICS_TOKEN 44
+#define CMO_MAXLENGTH 1026
+
+/**
+ * fw_cmo_feature_init - FW_FEATURE_CMO is not stored in ibm,hypertas-functions,
+ * handle that here. (Stolen from parse_system_parameter_string)
+ */
+void pSeries_cmo_feature_init(void)
+{
+ char *ptr, *key, *value, *end;
+ int call_status;
+ int PrPSP = -1;
+ int SecPSP = -1;
+
+ pr_debug(" -> fw_cmo_feature_init()\n");
+ spin_lock(&rtas_data_buf_lock);
+ memset(rtas_data_buf, 0, RTAS_DATA_BUF_SIZE);
+ call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,
+ NULL,
+ CMO_CHARACTERISTICS_TOKEN,
+ __pa(rtas_data_buf),
+ RTAS_DATA_BUF_SIZE);
+
+ if (call_status != 0) {
+ spin_unlock(&rtas_data_buf_lock);
+ pr_debug("CMO not available\n");
+ pr_debug(" <- fw_cmo_feature_init()\n");
+ return;
+ }
+
+ end = rtas_data_buf + CMO_MAXLENGTH - 2;
+ ptr = rtas_data_buf + 2; /* step over strlen value */
+ key = value = ptr;
+
+ while (*ptr && (ptr <= end)) {
+ /* Separate the key and value by replacing '=' with '\0' and
+ * point the value at the string after the '='
+ */
+ if (ptr[0] == '=') {
+ ptr[0] = '\0';
+ value = ptr + 1;
+ } else if (ptr[0] == '\0' || ptr[0] == ',') {
+ /* Terminate the string containing the key/value pair */
+ ptr[0] = '\0';
+
+ if (key == value) {
+ pr_debug("Malformed key/value pair\n");
+ /* Never found a '=', end processing */
+ break;
+ }
+
+ if (0 == strcmp(key, "PrPSP"))
+ PrPSP = simple_strtol(value, NULL, 10);
+ else if (0 == strcmp(key, "SecPSP"))
+ SecPSP = simple_strtol(value, NULL, 10);
+ value = key = ptr + 1;
+ }
+ ptr++;
+ }
+
+ if (PrPSP != -1 || SecPSP != -1) {
+ pr_info("CMO enabled\n");
+ pr_debug("CMO enabled, PrPSP=%d, SecPSP=%d\n", PrPSP, SecPSP);
+ powerpc_firmware_features |= FW_FEATURE_CMO;
+ } else
+ pr_debug("CMO not enabled, PrPSP=%d, SecPSP=%d\n", PrPSP, SecPSP);
+ spin_unlock(&rtas_data_buf_lock);
+ pr_debug(" <- fw_cmo_feature_init()\n");
+}
+
/*
* Early initialization. Relocation is on but do not reference unbolted pages
*/
@@ -329,6 +399,7 @@ static void __init pSeries_init_early(void)
else if (firmware_has_feature(FW_FEATURE_XDABR))
ppc_md.set_dabr = pseries_set_xdabr;
+ pSeries_cmo_feature_init();
iommu_init_early_pSeries();
pr_debug(" <- pSeries_init_early()\n");
diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c
index 7f59188cd9a..9e105cbc5e5 100644
--- a/arch/powerpc/sysdev/axonram.c
+++ b/arch/powerpc/sysdev/axonram.c
@@ -57,6 +57,8 @@
#define AXON_RAM_SECTOR_SIZE 1 << AXON_RAM_SECTOR_SHIFT
#define AXON_RAM_IRQ_FLAGS IRQF_SHARED | IRQF_TRIGGER_RISING
+static int azfs_major, azfs_minor;
+
struct axon_ram_bank {
struct of_device *device;
struct gendisk *disk;
@@ -148,7 +150,10 @@ axon_ram_direct_access(struct block_device *device, sector_t sector,
struct axon_ram_bank *bank = device->bd_disk->private_data;
loff_t offset;
- offset = sector << AXON_RAM_SECTOR_SHIFT;
+ offset = sector;
+ if (device->bd_part != NULL)
+ offset += device->bd_part->start_sect;
+ offset <<= AXON_RAM_SECTOR_SHIFT;
if (offset >= bank->size) {
dev_err(&bank->device->dev, "Access outside of address space\n");
return -ERANGE;
@@ -227,19 +232,14 @@ axon_ram_probe(struct of_device *device, const struct of_device_id *device_id)
goto failed;
}
- bank->disk->first_minor = 0;
+ bank->disk->major = azfs_major;
+ bank->disk->first_minor = azfs_minor;
bank->disk->fops = &axon_ram_devops;
bank->disk->private_data = bank;
bank->disk->driverfs_dev = &device->dev;
sprintf(bank->disk->disk_name, "%s%d",
AXON_RAM_DEVICE_NAME, axon_ram_bank_id);
- bank->disk->major = register_blkdev(0, bank->disk->disk_name);
- if (bank->disk->major < 0) {
- dev_err(&device->dev, "Cannot register block device\n");
- rc = -EFAULT;
- goto failed;
- }
bank->disk->queue = blk_alloc_queue(GFP_KERNEL);
if (bank->disk->queue == NULL) {
@@ -276,6 +276,8 @@ axon_ram_probe(struct of_device *device, const struct of_device_id *device_id)
goto failed;
}
+ azfs_minor += bank->disk->minors;
+
return 0;
failed:
@@ -310,7 +312,6 @@ axon_ram_remove(struct of_device *device)
device_remove_file(&device->dev, &dev_attr_ecc);
free_irq(bank->irq_id, device);
- unregister_blkdev(bank->disk->major, bank->disk->disk_name);
del_gendisk(bank->disk);
iounmap((void __iomem *) bank->io_addr);
kfree(bank);
@@ -341,6 +342,14 @@ static struct of_platform_driver axon_ram_driver = {
static int __init
axon_ram_init(void)
{
+ azfs_major = register_blkdev(azfs_major, AXON_RAM_DEVICE_NAME);
+ if (azfs_major < 0) {
+ printk(KERN_ERR "%s cannot become block device major number\n",
+ AXON_RAM_MODULE_NAME);
+ return -EFAULT;
+ }
+ azfs_minor = 0;
+
return of_register_platform_driver(&axon_ram_driver);
}
@@ -351,6 +360,7 @@ static void __exit
axon_ram_exit(void)
{
of_unregister_platform_driver(&axon_ram_driver);
+ unregister_blkdev(azfs_major, AXON_RAM_DEVICE_NAME);
}
module_init(axon_ram_init);
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 005c2ecf976..89639ecbf38 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -147,9 +147,10 @@ static void dart_flush(struct iommu_table *tbl)
}
}
-static void dart_build(struct iommu_table *tbl, long index,
+static int dart_build(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
unsigned int *dp;
unsigned int rpn;
@@ -183,6 +184,7 @@ static void dart_build(struct iommu_table *tbl, long index,
} else {
dart_dirty = 1;
}
+ return 0;
}
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 87b0aa13ab4..61e6d77efa4 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -27,6 +27,7 @@
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
+#if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx)
/* atmu setup for fsl pci/pcie controller */
void __init setup_pci_atmu(struct pci_controller *hose, struct resource *rsrc)
{
@@ -248,3 +249,63 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8536, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header);
DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header);
+#endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */
+
+#if defined(CONFIG_PPC_83xx)
+int __init mpc83xx_add_bridge(struct device_node *dev)
+{
+ int len;
+ struct pci_controller *hose;
+ struct resource rsrc;
+ const int *bus_range;
+ int primary = 1, has_address = 0;
+ phys_addr_t immr = get_immrbase();
+
+ pr_debug("Adding PCI host bridge %s\n", dev->full_name);
+
+ /* Fetch host bridge registers address */
+ has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
+
+ /* Get bus range if any */
+ bus_range = of_get_property(dev, "bus-range", &len);
+ if (bus_range == NULL || len < 2 * sizeof(int)) {
+ printk(KERN_WARNING "Can't get bus-range for %s, assume"
+ " bus 0\n", dev->full_name);
+ }
+
+ ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
+ hose = pcibios_alloc_controller(dev);
+ if (!hose)
+ return -ENOMEM;
+
+ hose->first_busno = bus_range ? bus_range[0] : 0;
+ hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+ /* MPC83xx supports up to two host controllers one at 0x8500 from immrbar
+ * the other at 0x8600, we consider the 0x8500 the primary controller
+ */
+ /* PCI 1 */
+ if ((rsrc.start & 0xfffff) == 0x8500) {
+ setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304, 0);
+ }
+ /* PCI 2 */
+ if ((rsrc.start & 0xfffff) == 0x8600) {
+ setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384, 0);
+ primary = 0;
+ }
+
+ printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. "
+ "Firmware bus number: %d->%d\n",
+ (unsigned long long)rsrc.start, hose->first_busno,
+ hose->last_busno);
+
+ pr_debug(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
+ hose, hose->cfg_addr, hose->cfg_data);
+
+ /* Interpret the "ranges" property */
+ /* This also maps the I/O region and sets isa_io/mem_base */
+ pci_process_bridge_OF_ranges(hose, dev, primary);
+
+ return 0;
+}
+#endif /* CONFIG_PPC_83xx */
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index 37b04ad2657..13f30c2a61e 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -83,6 +83,7 @@ struct ccsr_pci {
extern int fsl_add_bridge(struct device_node *dev, int is_primary);
extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
+extern int mpc83xx_add_bridge(struct device_node *dev);
#endif /* __POWERPC_FSL_PCI_H */
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index ebcec7362f9..214388e1180 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -207,66 +207,58 @@ static int __init of_add_fixed_phys(void)
arch_initcall(of_add_fixed_phys);
#endif /* CONFIG_FIXED_PHY */
-static int __init gfar_mdio_of_init(void)
+static int gfar_mdio_of_init_one(struct device_node *np)
{
- struct device_node *np = NULL;
+ int k;
+ struct device_node *child = NULL;
+ struct gianfar_mdio_data mdio_data;
struct platform_device *mdio_dev;
struct resource res;
int ret;
- np = of_find_compatible_node(np, NULL, "fsl,gianfar-mdio");
+ memset(&res, 0, sizeof(res));
+ memset(&mdio_data, 0, sizeof(mdio_data));
- /* try the deprecated version */
- if (!np)
- np = of_find_compatible_node(np, "mdio", "gianfar");
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret)
+ return ret;
- if (np) {
- int k;
- struct device_node *child = NULL;
- struct gianfar_mdio_data mdio_data;
+ mdio_dev = platform_device_register_simple("fsl-gianfar_mdio",
+ res.start&0xfffff, &res, 1);
+ if (IS_ERR(mdio_dev))
+ return PTR_ERR(mdio_dev);
- memset(&res, 0, sizeof(res));
- memset(&mdio_data, 0, sizeof(mdio_data));
+ for (k = 0; k < 32; k++)
+ mdio_data.irq[k] = PHY_POLL;
- ret = of_address_to_resource(np, 0, &res);
- if (ret)
- goto err;
-
- mdio_dev =
- platform_device_register_simple("fsl-gianfar_mdio",
- res.start, &res, 1);
- if (IS_ERR(mdio_dev)) {
- ret = PTR_ERR(mdio_dev);
- goto err;
+ while ((child = of_get_next_child(np, child)) != NULL) {
+ int irq = irq_of_parse_and_map(child, 0);
+ if (irq != NO_IRQ) {
+ const u32 *id = of_get_property(child, "reg", NULL);
+ mdio_data.irq[*id] = irq;
}
+ }
- for (k = 0; k < 32; k++)
- mdio_data.irq[k] = PHY_POLL;
+ ret = platform_device_add_data(mdio_dev, &mdio_data,
+ sizeof(struct gianfar_mdio_data));
+ if (ret)
+ platform_device_unregister(mdio_dev);
- while ((child = of_get_next_child(np, child)) != NULL) {
- int irq = irq_of_parse_and_map(child, 0);
- if (irq != NO_IRQ) {
- const u32 *id = of_get_property(child,
- "reg", NULL);
- mdio_data.irq[*id] = irq;
- }
- }
+ return ret;
+}
- ret =
- platform_device_add_data(mdio_dev, &mdio_data,
- sizeof(struct gianfar_mdio_data));
- if (ret)
- goto unreg;
- }
+static int __init gfar_mdio_of_init(void)
+{
+ struct device_node *np = NULL;
- of_node_put(np);
- return 0;
+ for_each_compatible_node(np, NULL, "fsl,gianfar-mdio")
+ gfar_mdio_of_init_one(np);
-unreg:
- platform_device_unregister(mdio_dev);
-err:
- of_node_put(np);
- return ret;
+ /* try the deprecated version */
+ for_each_compatible_node(np, "mdio", "gianfar");
+ gfar_mdio_of_init_one(np);
+
+ return 0;
}
arch_initcall(gfar_mdio_of_init);
@@ -296,6 +288,9 @@ static int __init gfar_of_init(void)
const phandle *ph;
int n_res = 2;
+ if (!of_device_is_available(np))
+ continue;
+
memset(r, 0, sizeof(r));
memset(&gfar_data, 0, sizeof(gfar_data));
@@ -357,6 +352,9 @@ static int __init gfar_of_init(void)
else
gfar_data.interface = PHY_INTERFACE_MODE_MII;
+ if (of_get_property(np, "fsl,magic-packet", NULL))
+ gfar_data.device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET;
+
ph = of_get_property(np, "phy-handle", NULL);
if (ph == NULL) {
u32 *fixed_link;
@@ -390,7 +388,7 @@ static int __init gfar_of_init(void)
gfar_data.phy_id = *id;
snprintf(gfar_data.bus_id, MII_BUS_ID_SIZE, "%llx",
- (unsigned long long)res.start);
+ (unsigned long long)res.start&0xfffff);
of_node_put(phy);
of_node_put(mdio);
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 52c831fa188..02429988735 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -10,6 +10,7 @@ extern u32 get_baudrate(void);
extern u32 fsl_get_sys_freq(void);
struct spi_board_info;
+struct device_node;
extern int fsl_spi_init(struct spi_board_info *board_infos,
unsigned int num_board_infos,
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index caba1c0be5a..88a983ece5c 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -22,6 +22,7 @@
#include <linux/device.h>
#include <linux/bootmem.h>
#include <linux/spinlock.h>
+#include <linux/fsl_devices.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/prom.h>
@@ -889,8 +890,78 @@ unsigned int ipic_get_irq(void)
return irq_linear_revmap(primary_ipic->irqhost, irq);
}
+#ifdef CONFIG_PM
+static struct {
+ u32 sicfr;
+ u32 siprr[2];
+ u32 simsr[2];
+ u32 sicnr;
+ u32 smprr[2];
+ u32 semsr;
+ u32 secnr;
+ u32 sermr;
+ u32 sercr;
+} ipic_saved_state;
+
+static int ipic_suspend(struct sys_device *sdev, pm_message_t state)
+{
+ struct ipic *ipic = primary_ipic;
+
+ ipic_saved_state.sicfr = ipic_read(ipic->regs, IPIC_SICFR);
+ ipic_saved_state.siprr[0] = ipic_read(ipic->regs, IPIC_SIPRR_A);
+ ipic_saved_state.siprr[1] = ipic_read(ipic->regs, IPIC_SIPRR_D);
+ ipic_saved_state.simsr[0] = ipic_read(ipic->regs, IPIC_SIMSR_H);
+ ipic_saved_state.simsr[1] = ipic_read(ipic->regs, IPIC_SIMSR_L);
+ ipic_saved_state.sicnr = ipic_read(ipic->regs, IPIC_SICNR);
+ ipic_saved_state.smprr[0] = ipic_read(ipic->regs, IPIC_SMPRR_A);
+ ipic_saved_state.smprr[1] = ipic_read(ipic->regs, IPIC_SMPRR_B);
+ ipic_saved_state.semsr = ipic_read(ipic->regs, IPIC_SEMSR);
+ ipic_saved_state.secnr = ipic_read(ipic->regs, IPIC_SECNR);
+ ipic_saved_state.sermr = ipic_read(ipic->regs, IPIC_SERMR);
+ ipic_saved_state.sercr = ipic_read(ipic->regs, IPIC_SERCR);
+
+ if (fsl_deep_sleep()) {
+ /* In deep sleep, make sure there can be no
+ * pending interrupts, as this can cause
+ * problems on 831x.
+ */
+ ipic_write(ipic->regs, IPIC_SIMSR_H, 0);
+ ipic_write(ipic->regs, IPIC_SIMSR_L, 0);
+ ipic_write(ipic->regs, IPIC_SEMSR, 0);
+ ipic_write(ipic->regs, IPIC_SERMR, 0);
+ }
+
+ return 0;
+}
+
+static int ipic_resume(struct sys_device *sdev)
+{
+ struct ipic *ipic = primary_ipic;
+
+ ipic_write(ipic->regs, IPIC_SICFR, ipic_saved_state.sicfr);
+ ipic_write(ipic->regs, IPIC_SIPRR_A, ipic_saved_state.siprr[0]);
+ ipic_write(ipic->regs, IPIC_SIPRR_D, ipic_saved_state.siprr[1]);
+ ipic_write(ipic->regs, IPIC_SIMSR_H, ipic_saved_state.simsr[0]);
+ ipic_write(ipic->regs, IPIC_SIMSR_L, ipic_saved_state.simsr[1]);
+ ipic_write(ipic->regs, IPIC_SICNR, ipic_saved_state.sicnr);
+ ipic_write(ipic->regs, IPIC_SMPRR_A, ipic_saved_state.smprr[0]);
+ ipic_write(ipic->regs, IPIC_SMPRR_B, ipic_saved_state.smprr[1]);
+ ipic_write(ipic->regs, IPIC_SEMSR, ipic_saved_state.semsr);
+ ipic_write(ipic->regs, IPIC_SECNR, ipic_saved_state.secnr);
+ ipic_write(ipic->regs, IPIC_SERMR, ipic_saved_state.sermr);
+ ipic_write(ipic->regs, IPIC_SERCR, ipic_saved_state.sercr);
+
+ return 0;
+}
+#else
+#define ipic_suspend NULL
+#define ipic_resume NULL
+#endif
+
static struct sysdev_class ipic_sysclass = {
.name = "ipic",
+ .suspend = ipic_suspend,
+ .resume = ipic_resume,
};
static struct sys_device device_ipic = {
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
index 4bb18f57901..1ce546462be 100644
--- a/arch/powerpc/sysdev/qe_lib/Kconfig
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -29,7 +29,7 @@ config QE_GPIO
bool "QE GPIO support"
depends on QUICC_ENGINE
select GENERIC_GPIO
- select HAVE_GPIO_LIB
+ select ARCH_REQUIRE_GPIOLIB
help
Say Y here if you're going to use hardware that connects to the
QE GPIOs.
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 9e82d7e725a..b3b73ae57d6 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -64,7 +64,7 @@ static phys_addr_t qebase = -1;
phys_addr_t get_qe_base(void)
{
struct device_node *qe;
- unsigned int size;
+ int size;
const u32 *prop;
if (qebase != -1)
@@ -158,7 +158,7 @@ static unsigned int brg_clk = 0;
unsigned int qe_get_brg_clk(void)
{
struct device_node *qe;
- unsigned int size;
+ int size;
const u32 *prop;
if (brg_clk)
@@ -305,7 +305,7 @@ EXPORT_SYMBOL(qe_put_snum);
static int qe_sdma_init(void)
{
- struct sdma *sdma = &qe_immr->sdma;
+ struct sdma __iomem *sdma = &qe_immr->sdma;
unsigned long sdma_buf_offset;
if (!sdma)
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c
index d3c7f5af9bc..1d78071aad7 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc.c
@@ -88,7 +88,7 @@ int ucc_set_type(unsigned int ucc_num, enum ucc_speed_type speed)
return 0;
}
-static void get_cmxucr_reg(unsigned int ucc_num, __be32 **cmxucr,
+static void get_cmxucr_reg(unsigned int ucc_num, __be32 __iomem **cmxucr,
unsigned int *reg_num, unsigned int *shift)
{
unsigned int cmx = ((ucc_num & 1) << 1) + (ucc_num > 3);
@@ -100,7 +100,7 @@ static void get_cmxucr_reg(unsigned int ucc_num, __be32 **cmxucr,
int ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask)
{
- __be32 *cmxucr;
+ __be32 __iomem *cmxucr;
unsigned int reg_num;
unsigned int shift;
@@ -121,7 +121,7 @@ int ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask)
int ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,
enum comm_dir mode)
{
- __be32 *cmxucr;
+ __be32 __iomem *cmxucr;
unsigned int reg_num;
unsigned int shift;
u32 clock_bits = 0;
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
index bcf88e6ce96..1aecb075a72 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
@@ -46,7 +46,7 @@ void ucc_fast_dump_regs(struct ucc_fast_private * uccf)
printk(KERN_INFO "uccm : addr=0x%p, val=0x%08x\n",
&uccf->uf_regs->uccm, in_be32(&uccf->uf_regs->uccm));
printk(KERN_INFO "uccs : addr=0x%p, val=0x%02x\n",
- &uccf->uf_regs->uccs, uccf->uf_regs->uccs);
+ &uccf->uf_regs->uccs, in_8(&uccf->uf_regs->uccs));
printk(KERN_INFO "urfb : addr=0x%p, val=0x%08x\n",
&uccf->uf_regs->urfb, in_be32(&uccf->uf_regs->urfb));
printk(KERN_INFO "urfs : addr=0x%p, val=0x%04x\n",
@@ -68,7 +68,7 @@ void ucc_fast_dump_regs(struct ucc_fast_private * uccf)
printk(KERN_INFO "urtry : addr=0x%p, val=0x%08x\n",
&uccf->uf_regs->urtry, in_be32(&uccf->uf_regs->urtry));
printk(KERN_INFO "guemr : addr=0x%p, val=0x%02x\n",
- &uccf->uf_regs->guemr, uccf->uf_regs->guemr);
+ &uccf->uf_regs->guemr, in_8(&uccf->uf_regs->guemr));
}
EXPORT_SYMBOL(ucc_fast_dump_regs);
@@ -96,7 +96,7 @@ EXPORT_SYMBOL(ucc_fast_transmit_on_demand);
void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode)
{
- struct ucc_fast *uf_regs;
+ struct ucc_fast __iomem *uf_regs;
u32 gumr;
uf_regs = uccf->uf_regs;
@@ -117,7 +117,7 @@ EXPORT_SYMBOL(ucc_fast_enable);
void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode)
{
- struct ucc_fast *uf_regs;
+ struct ucc_fast __iomem *uf_regs;
u32 gumr;
uf_regs = uccf->uf_regs;
@@ -139,7 +139,7 @@ EXPORT_SYMBOL(ucc_fast_disable);
int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret)
{
struct ucc_fast_private *uccf;
- struct ucc_fast *uf_regs;
+ struct ucc_fast __iomem *uf_regs;
u32 gumr;
int ret;
@@ -216,10 +216,10 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
uccf->stopped_tx = 0;
uccf->stopped_rx = 0;
uf_regs = uccf->uf_regs;
- uccf->p_ucce = (u32 *) & (uf_regs->ucce);
- uccf->p_uccm = (u32 *) & (uf_regs->uccm);
+ uccf->p_ucce = &uf_regs->ucce;
+ uccf->p_uccm = &uf_regs->uccm;
#ifdef CONFIG_UGETH_TX_ON_DEMAND
- uccf->p_utodr = (u16 *) & (uf_regs->utodr);
+ uccf->p_utodr = &uf_regs->utodr;
#endif
#ifdef STATISTICS
uccf->tx_frames = 0;
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index eb530b4128b..2ed88122be9 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -565,6 +565,7 @@ bool "s390 guest support (EXPERIMENTAL)"
depends on 64BIT && EXPERIMENTAL
select VIRTIO
select VIRTIO_RING
+ select VIRTIO_CONSOLE
help
Select this option if you want to run the kernel under s390 linux
endmenu
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 288ad490a6d..4f82e5b5f87 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -270,7 +270,6 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
__ctl_store(kcb->kprobe_saved_ctl, 9, 11);
}
-/* Called with kretprobe_lock held */
void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
struct pt_regs *regs)
{
@@ -377,8 +376,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p,
unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
INIT_HLIST_HEAD(&empty_rp);
- spin_lock_irqsave(&kretprobe_lock, flags);
- head = kretprobe_inst_table_head(current);
+ kretprobe_hash_lock(current, &head, &flags);
/*
* It is possible to have multiple instances associated with a given
@@ -417,7 +415,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p,
regs->psw.addr = orig_ret_address | PSW_ADDR_AMODE;
reset_current_kprobe();
- spin_unlock_irqrestore(&kretprobe_lock, flags);
+ kretprobe_hash_unlock(current, &flags);
preempt_enable_no_resched();
hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 85defd01d29..9839767d084 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -142,7 +142,7 @@ static void default_idle(void)
void cpu_idle(void)
{
for (;;) {
- tick_nohz_stop_sched_tick();
+ tick_nohz_stop_sched_tick(1);
while (!need_resched())
default_idle();
tick_nohz_restart_sched_tick();
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index b358e18273b..62122bad1e3 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -54,6 +54,7 @@
#include <asm/sections.h>
#include <asm/ebcdic.h>
#include <asm/compat.h>
+#include <asm/kvm_virtio.h>
long psw_kernel_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY |
PSW_MASK_MCHECK | PSW_DEFAULT_KEY);
@@ -766,7 +767,8 @@ setup_arch(char **cmdline_p)
printk("We are running under VM (64 bit mode)\n");
else if (MACHINE_IS_KVM) {
printk("We are running under KVM (64 bit mode)\n");
- add_preferred_console("ttyS", 1, NULL);
+ add_preferred_console("hvc", 0, NULL);
+ s390_virtio_console_init();
} else
printk("We are running native (64 bit mode)\n");
#endif /* CONFIG_64BIT */
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index b6781030cfb..b795b3e24af 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -864,7 +864,8 @@ int setup_profiling_timer(unsigned int multiplier)
}
#ifdef CONFIG_HOTPLUG_CPU
-static ssize_t cpu_configure_show(struct sys_device *dev, char *buf)
+static ssize_t cpu_configure_show(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
ssize_t count;
@@ -874,8 +875,9 @@ static ssize_t cpu_configure_show(struct sys_device *dev, char *buf)
return count;
}
-static ssize_t cpu_configure_store(struct sys_device *dev, const char *buf,
- size_t count)
+static ssize_t cpu_configure_store(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ const char *buf, size_t count)
{
int cpu = dev->id;
int val, rc;
@@ -922,7 +924,8 @@ out:
static SYSDEV_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store);
#endif /* CONFIG_HOTPLUG_CPU */
-static ssize_t cpu_polarization_show(struct sys_device *dev, char *buf)
+static ssize_t cpu_polarization_show(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
int cpu = dev->id;
ssize_t count;
@@ -950,7 +953,8 @@ static ssize_t cpu_polarization_show(struct sys_device *dev, char *buf)
}
static SYSDEV_ATTR(polarization, 0444, cpu_polarization_show, NULL);
-static ssize_t show_cpu_address(struct sys_device *dev, char *buf)
+static ssize_t show_cpu_address(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", __cpu_logical_map[dev->id]);
}
@@ -970,7 +974,8 @@ static struct attribute_group cpu_common_attr_group = {
.attrs = cpu_common_attrs,
};
-static ssize_t show_capability(struct sys_device *dev, char *buf)
+static ssize_t show_capability(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
unsigned int capability;
int rc;
@@ -982,7 +987,8 @@ static ssize_t show_capability(struct sys_device *dev, char *buf)
}
static SYSDEV_ATTR(capability, 0444, show_capability, NULL);
-static ssize_t show_idle_count(struct sys_device *dev, char *buf)
+static ssize_t show_idle_count(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct s390_idle_data *idle;
unsigned long long idle_count;
@@ -995,7 +1001,8 @@ static ssize_t show_idle_count(struct sys_device *dev, char *buf)
}
static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL);
-static ssize_t show_idle_time(struct sys_device *dev, char *buf)
+static ssize_t show_idle_time(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct s390_idle_data *idle;
unsigned long long new_time;
@@ -1112,7 +1119,9 @@ out:
return rc;
}
-static ssize_t __ref rescan_store(struct sys_device *dev, const char *buf,
+static ssize_t __ref rescan_store(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ const char *buf,
size_t count)
{
int rc;
@@ -1123,7 +1132,9 @@ static ssize_t __ref rescan_store(struct sys_device *dev, const char *buf,
static SYSDEV_ATTR(rescan, 0200, NULL, rescan_store);
#endif /* CONFIG_HOTPLUG_CPU */
-static ssize_t dispatching_show(struct sys_device *dev, char *buf)
+static ssize_t dispatching_show(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ char *buf)
{
ssize_t count;
@@ -1133,8 +1144,9 @@ static ssize_t dispatching_show(struct sys_device *dev, char *buf)
return count;
}
-static ssize_t dispatching_store(struct sys_device *dev, const char *buf,
- size_t count)
+static ssize_t dispatching_store(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ const char *buf, size_t count)
{
int val, rc;
char delim;
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index f2cede3947b..ab70d9bd926 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -1100,7 +1100,9 @@ static inline struct etr_aib *etr_aib_from_dev(struct sys_device *dev)
return etr_port1_online ? &etr_port1 : NULL;
}
-static ssize_t etr_online_show(struct sys_device *dev, char *buf)
+static ssize_t etr_online_show(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ char *buf)
{
unsigned int online;
@@ -1109,7 +1111,8 @@ static ssize_t etr_online_show(struct sys_device *dev, char *buf)
}
static ssize_t etr_online_store(struct sys_device *dev,
- const char *buf, size_t count)
+ struct sysdev_attribute *attr,
+ const char *buf, size_t count)
{
unsigned int value;
@@ -1136,7 +1139,9 @@ static ssize_t etr_online_store(struct sys_device *dev,
static SYSDEV_ATTR(online, 0600, etr_online_show, etr_online_store);
-static ssize_t etr_stepping_control_show(struct sys_device *dev, char *buf)
+static ssize_t etr_stepping_control_show(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ char *buf)
{
return sprintf(buf, "%i\n", (dev == &etr_port0_dev) ?
etr_eacr.e0 : etr_eacr.e1);
@@ -1144,7 +1149,8 @@ static ssize_t etr_stepping_control_show(struct sys_device *dev, char *buf)
static SYSDEV_ATTR(stepping_control, 0400, etr_stepping_control_show, NULL);
-static ssize_t etr_mode_code_show(struct sys_device *dev, char *buf)
+static ssize_t etr_mode_code_show(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
if (!etr_port0_online && !etr_port1_online)
/* Status word is not uptodate if both ports are offline. */
@@ -1155,7 +1161,8 @@ static ssize_t etr_mode_code_show(struct sys_device *dev, char *buf)
static SYSDEV_ATTR(state_code, 0400, etr_mode_code_show, NULL);
-static ssize_t etr_untuned_show(struct sys_device *dev, char *buf)
+static ssize_t etr_untuned_show(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct etr_aib *aib = etr_aib_from_dev(dev);
@@ -1166,7 +1173,8 @@ static ssize_t etr_untuned_show(struct sys_device *dev, char *buf)
static SYSDEV_ATTR(untuned, 0400, etr_untuned_show, NULL);
-static ssize_t etr_network_id_show(struct sys_device *dev, char *buf)
+static ssize_t etr_network_id_show(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct etr_aib *aib = etr_aib_from_dev(dev);
@@ -1177,7 +1185,8 @@ static ssize_t etr_network_id_show(struct sys_device *dev, char *buf)
static SYSDEV_ATTR(network, 0400, etr_network_id_show, NULL);
-static ssize_t etr_id_show(struct sys_device *dev, char *buf)
+static ssize_t etr_id_show(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct etr_aib *aib = etr_aib_from_dev(dev);
@@ -1188,7 +1197,8 @@ static ssize_t etr_id_show(struct sys_device *dev, char *buf)
static SYSDEV_ATTR(id, 0400, etr_id_show, NULL);
-static ssize_t etr_port_number_show(struct sys_device *dev, char *buf)
+static ssize_t etr_port_number_show(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct etr_aib *aib = etr_aib_from_dev(dev);
@@ -1199,7 +1209,8 @@ static ssize_t etr_port_number_show(struct sys_device *dev, char *buf)
static SYSDEV_ATTR(port, 0400, etr_port_number_show, NULL);
-static ssize_t etr_coupled_show(struct sys_device *dev, char *buf)
+static ssize_t etr_coupled_show(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct etr_aib *aib = etr_aib_from_dev(dev);
@@ -1210,7 +1221,8 @@ static ssize_t etr_coupled_show(struct sys_device *dev, char *buf)
static SYSDEV_ATTR(coupled, 0400, etr_coupled_show, NULL);
-static ssize_t etr_local_time_show(struct sys_device *dev, char *buf)
+static ssize_t etr_local_time_show(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct etr_aib *aib = etr_aib_from_dev(dev);
@@ -1221,7 +1233,8 @@ static ssize_t etr_local_time_show(struct sys_device *dev, char *buf)
static SYSDEV_ATTR(local_time, 0400, etr_local_time_show, NULL);
-static ssize_t etr_utc_offset_show(struct sys_device *dev, char *buf)
+static ssize_t etr_utc_offset_show(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct etr_aib *aib = etr_aib_from_dev(dev);
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index 212d618b009..632b13e1005 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -9,7 +9,6 @@
#include <linux/device.h>
#include <linux/bootmem.h>
#include <linux/sched.h>
-#include <linux/kthread.h>
#include <linux/workqueue.h>
#include <linux/cpu.h>
#include <linux/smp.h>
@@ -230,20 +229,9 @@ void arch_update_cpu_topology(void)
}
}
-static int topology_kthread(void *data)
-{
- arch_reinit_sched_domains();
- return 0;
-}
-
static void topology_work_fn(struct work_struct *work)
{
- /* We can't call arch_reinit_sched_domains() from a multi-threaded
- * workqueue context since it may deadlock in case of cpu hotplug.
- * So we have to create a kernel thread in order to call
- * arch_reinit_sched_domains().
- */
- kthread_run(topology_kthread, NULL, "topology_update");
+ arch_reinit_sched_domains();
}
void topology_schedule_update(void)
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
index f4b6124fdb7..f28c43d2f61 100644
--- a/arch/s390/mm/hugetlbpage.c
+++ b/arch/s390/mm/hugetlbpage.c
@@ -72,7 +72,8 @@ void arch_release_hugepage(struct page *page)
page[1].index = 0;
}
-pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+ unsigned long addr, unsigned long sz)
{
pgd_t *pgdp;
pud_t *pudp;
@@ -119,6 +120,11 @@ int pmd_huge(pmd_t pmd)
return !!(pmd_val(pmd) & _SEGMENT_ENTRY_LARGE);
}
+int pud_huge(pud_t pud)
+{
+ return 0;
+}
+
struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
pmd_t *pmdp, int write)
{
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 3e7384f4619..8879938f335 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -8,6 +8,7 @@ mainmenu "Linux/SuperH Kernel Configuration"
config SUPERH
def_bool y
select EMBEDDED
+ select HAVE_CLK
select HAVE_IDE
select HAVE_OPROFILE
help
diff --git a/arch/sh/boards/renesas/migor/setup.c b/arch/sh/boards/renesas/migor/setup.c
index 01af44245b5..963c9932209 100644
--- a/arch/sh/boards/renesas/migor/setup.c
+++ b/arch/sh/boards/renesas/migor/setup.c
@@ -30,7 +30,6 @@
static struct smc91x_platdata smc91x_info = {
.flags = SMC91X_USE_16BIT,
- .irq_flags = IRQF_TRIGGER_HIGH,
};
static struct resource smc91x_eth_resources[] = {
@@ -42,7 +41,7 @@ static struct resource smc91x_eth_resources[] = {
},
[1] = {
.start = 32, /* IRQ0 */
- .flags = IORESOURCE_IRQ,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
},
};
diff --git a/arch/sh/boot/compressed/misc_32.c b/arch/sh/boot/compressed/misc_32.c
index adcea31e663..f386997e4d9 100644
--- a/arch/sh/boot/compressed/misc_32.c
+++ b/arch/sh/boot/compressed/misc_32.c
@@ -74,8 +74,6 @@ static unsigned outcnt = 0; /* bytes in output buffer */
static int fill_inbuf(void);
static void flush_window(void);
static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
extern char input_data[];
extern int input_len;
@@ -84,11 +82,7 @@ static long bytes_out = 0;
static uch *output_data;
static unsigned long output_ptr = 0;
-static void *malloc(int size);
-static void free(void *where);
static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
int puts(const char *);
@@ -101,38 +95,6 @@ static unsigned long free_mem_end_ptr;
#include "../../../../lib/inflate.c"
-static void *malloc(int size)
-{
- void *p;
-
- if (size <0) error("Malloc error");
- if (free_mem_ptr == 0) error("Memory error");
-
- free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
- p = (void *)free_mem_ptr;
- free_mem_ptr += size;
-
- if (free_mem_ptr >= free_mem_end_ptr)
- error("Out of memory");
-
- return p;
-}
-
-static void free(void *where)
-{ /* Don't care */
-}
-
-static void gzip_mark(void **ptr)
-{
- *ptr = (void *) free_mem_ptr;
-}
-
-static void gzip_release(void **ptr)
-{
- free_mem_ptr = (long) *ptr;
-}
-
#ifdef CONFIG_SH_STANDARD_BIOS
size_t strlen(const char *s)
{
diff --git a/arch/sh/boot/compressed/misc_64.c b/arch/sh/boot/compressed/misc_64.c
index a006ef89b9d..2941657e18a 100644
--- a/arch/sh/boot/compressed/misc_64.c
+++ b/arch/sh/boot/compressed/misc_64.c
@@ -72,8 +72,6 @@ static unsigned outcnt = 0; /* bytes in output buffer */
static int fill_inbuf(void);
static void flush_window(void);
static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
extern char input_data[];
extern int input_len;
@@ -82,11 +80,7 @@ static long bytes_out = 0;
static uch *output_data;
static unsigned long output_ptr = 0;
-static void *malloc(int size);
-static void free(void *where);
static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
static void puts(const char *);
@@ -99,40 +93,6 @@ static unsigned long free_mem_end_ptr;
#include "../../../../lib/inflate.c"
-static void *malloc(int size)
-{
- void *p;
-
- if (size < 0)
- error("Malloc error\n");
- if (free_mem_ptr == 0)
- error("Memory error\n");
-
- free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
- p = (void *) free_mem_ptr;
- free_mem_ptr += size;
-
- if (free_mem_ptr >= free_mem_end_ptr)
- error("\nOut of memory\n");
-
- return p;
-}
-
-static void free(void *where)
-{ /* Don't care */
-}
-
-static void gzip_mark(void **ptr)
-{
- *ptr = (void *) free_mem_ptr;
-}
-
-static void gzip_release(void **ptr)
-{
- free_mem_ptr = (long) *ptr;
-}
-
void puts(const char *s)
{
}
diff --git a/arch/sh/drivers/dma/dma-sysfs.c b/arch/sh/drivers/dma/dma-sysfs.c
index 51b57c0d1a3..347ee11351e 100644
--- a/arch/sh/drivers/dma/dma-sysfs.c
+++ b/arch/sh/drivers/dma/dma-sysfs.c
@@ -23,7 +23,8 @@ static struct sysdev_class dma_sysclass = {
};
EXPORT_SYMBOL(dma_sysclass);
-static ssize_t dma_show_devices(struct sys_device *dev, char *buf)
+static ssize_t dma_show_devices(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
ssize_t len = 0;
int i;
@@ -57,13 +58,15 @@ static int __init dma_sysclass_init(void)
}
postcore_initcall(dma_sysclass_init);
-static ssize_t dma_show_dev_id(struct sys_device *dev, char *buf)
+static ssize_t dma_show_dev_id(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct dma_channel *channel = to_dma_channel(dev);
return sprintf(buf, "%s\n", channel->dev_id);
}
static ssize_t dma_store_dev_id(struct sys_device *dev,
+ struct sysdev_attribute *attr,
const char *buf, size_t count)
{
struct dma_channel *channel = to_dma_channel(dev);
@@ -74,6 +77,7 @@ static ssize_t dma_store_dev_id(struct sys_device *dev,
static SYSDEV_ATTR(dev_id, S_IRUGO | S_IWUSR, dma_show_dev_id, dma_store_dev_id);
static ssize_t dma_store_config(struct sys_device *dev,
+ struct sysdev_attribute *attr,
const char *buf, size_t count)
{
struct dma_channel *channel = to_dma_channel(dev);
@@ -87,13 +91,15 @@ static ssize_t dma_store_config(struct sys_device *dev,
static SYSDEV_ATTR(config, S_IWUSR, NULL, dma_store_config);
-static ssize_t dma_show_mode(struct sys_device *dev, char *buf)
+static ssize_t dma_show_mode(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct dma_channel *channel = to_dma_channel(dev);
return sprintf(buf, "0x%08x\n", channel->mode);
}
static ssize_t dma_store_mode(struct sys_device *dev,
+ struct sysdev_attribute *attr,
const char *buf, size_t count)
{
struct dma_channel *channel = to_dma_channel(dev);
@@ -104,7 +110,8 @@ static ssize_t dma_store_mode(struct sys_device *dev,
static SYSDEV_ATTR(mode, S_IRUGO | S_IWUSR, dma_show_mode, dma_store_mode);
#define dma_ro_attr(field, fmt) \
-static ssize_t dma_show_##field(struct sys_device *dev, char *buf) \
+static ssize_t dma_show_##field(struct sys_device *dev, \
+ struct sysdev_attribute *attr, char *buf)\
{ \
struct dma_channel *channel = to_dma_channel(dev); \
return sprintf(buf, fmt, channel->field); \
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index b98e37a1f54..921892c351d 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -86,7 +86,7 @@ void cpu_idle(void)
if (!idle)
idle = default_idle;
- tick_nohz_stop_sched_tick();
+ tick_nohz_stop_sched_tick(1);
while (!need_resched())
idle();
tick_nohz_restart_sched_tick();
diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c
index 1b2ae35c4a7..54d1f61aa00 100644
--- a/arch/sh/kernel/stacktrace.c
+++ b/arch/sh/kernel/stacktrace.c
@@ -12,6 +12,7 @@
#include <linux/sched.h>
#include <linux/stacktrace.h>
#include <linux/thread_info.h>
+#include <linux/module.h>
#include <asm/ptrace.h>
/*
diff --git a/arch/sh/kernel/sys_sh32.c b/arch/sh/kernel/sys_sh32.c
index 125e493ead8..f0aa5c39865 100644
--- a/arch/sh/kernel/sys_sh32.c
+++ b/arch/sh/kernel/sys_sh32.c
@@ -29,7 +29,7 @@ asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
int fd[2];
int error;
- error = do_pipe(fd);
+ error = do_pipe_flags(fd, 0);
if (!error) {
regs->regs[1] = fd[1];
return fd[0];
diff --git a/arch/sh/mm/hugetlbpage.c b/arch/sh/mm/hugetlbpage.c
index ae8c321d6e2..9304117039c 100644
--- a/arch/sh/mm/hugetlbpage.c
+++ b/arch/sh/mm/hugetlbpage.c
@@ -22,7 +22,8 @@
#include <asm/tlbflush.h>
#include <asm/cacheflush.h>
-pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+ unsigned long addr, unsigned long sz)
{
pgd_t *pgd;
pud_t *pud;
@@ -78,6 +79,11 @@ int pmd_huge(pmd_t pmd)
return 0;
}
+int pud_huge(pud_t pud)
+{
+ return 0;
+}
+
struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
pmd_t *pmd, int write)
{
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index d7df26bd1e5..d652d375eb1 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -191,7 +191,7 @@ void __init paging_init(void)
pg_data_t *pgdat = NODE_DATA(nid);
unsigned long low, start_pfn;
- start_pfn = pgdat->bdata->node_boot_start >> PAGE_SHIFT;
+ start_pfn = pgdat->bdata->node_min_pfn;
low = pgdat->bdata->node_low_pfn;
if (max_zone_pfns[ZONE_NORMAL] < low)
diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c
index 1663199ce88..095d93bec7c 100644
--- a/arch/sh/mm/numa.c
+++ b/arch/sh/mm/numa.c
@@ -14,7 +14,6 @@
#include <linux/pfn.h>
#include <asm/sections.h>
-static bootmem_data_t plat_node_bdata[MAX_NUMNODES];
struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
EXPORT_SYMBOL_GPL(node_data);
@@ -35,7 +34,7 @@ void __init setup_memory(void)
NODE_DATA(0) = pfn_to_kaddr(free_pfn);
memset(NODE_DATA(0), 0, sizeof(struct pglist_data));
free_pfn += PFN_UP(sizeof(struct pglist_data));
- NODE_DATA(0)->bdata = &plat_node_bdata[0];
+ NODE_DATA(0)->bdata = &bootmem_node_data[0];
/* Set up node 0 */
setup_bootmem_allocator(free_pfn);
@@ -66,7 +65,7 @@ void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
free_pfn += PFN_UP(sizeof(struct pglist_data));
memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
- NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
+ NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
NODE_DATA(nid)->node_start_pfn = start_pfn;
NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 789724e61e8..375de7c6d08 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -298,20 +298,6 @@ config UNIX98_PTYS
Read the instructions in <file:Documentation/Changes> pertaining to
pseudo terminals. It's safe to say N.
-config UNIX98_PTY_COUNT
- int "Maximum number of Unix98 PTYs in use (0-2048)"
- depends on UNIX98_PTYS
- default "256"
- help
- The maximum number of Unix98 PTYs that can be used at any one time.
- The default is 256, and should be enough for desktop systems. Server
- machines which support incoming telnet/rlogin/ssh connections and/or
- serve several X terminals may want to increase this: every incoming
- connection and every xterm uses up one PTY.
-
- When not in use, each additional set of 256 PTYs occupy
- approximately 8 KB of kernel memory on 32-bit architectures.
-
endmenu
source "fs/Kconfig"
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index fef28e267a5..6668e6037af 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -18,6 +18,7 @@ CHECKFLAGS += -D__sparc__
#KBUILD_CFLAGS += -g -pipe -fcall-used-g5 -fcall-used-g7
KBUILD_CFLAGS += -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
KBUILD_AFLAGS += -m32
+CPPFLAGS_vmlinux.lds += -m32
#LDFLAGS_vmlinux = -N -Ttext 0xf0004000
# Since 2.5.40, the first stage is left not btfix-ed.
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
index 3c6b49a53ae..4d73421559c 100644
--- a/arch/sparc/kernel/sys_sparc.c
+++ b/arch/sparc/kernel/sys_sparc.c
@@ -97,7 +97,7 @@ asmlinkage int sparc_pipe(struct pt_regs *regs)
int fd[2];
int error;
- error = do_pipe(fd);
+ error = do_pipe_flags(fd, 0);
if (error)
goto out;
regs->u_regs[UREG_I1] = fd[1];
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index 5a7c4c8345c..e1b9233b90a 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -80,4 +80,5 @@ sys_call_table:
/*300*/ .long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
/*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
/*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
-/*315*/ .long sys_timerfd_settime, sys_timerfd_gettime
+/*315*/ .long sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
+/*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index c624e04ff03..ee30462598f 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -1352,8 +1352,7 @@ void __init srmmu_paging_init(void)
zones_size[ZONE_HIGHMEM] = npages;
zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
- free_area_init_node(0, &contig_page_data, zones_size,
- pfn_base, zholes_size);
+ free_area_init_node(0, zones_size, pfn_base, zholes_size);
}
}
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index 2375fe9dc31..d1782f6368b 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -2123,8 +2123,7 @@ void __init sun4c_paging_init(void)
zones_size[ZONE_HIGHMEM] = npages;
zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
- free_area_init_node(0, &contig_page_data, zones_size,
- pfn_base, zholes_size);
+ free_area_init_node(0, zones_size, pfn_base, zholes_size);
}
cnt = 0;
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c
index c49d0388b79..4d58d7ce708 100644
--- a/arch/sparc64/kernel/ebus.c
+++ b/arch/sparc64/kernel/ebus.c
@@ -401,7 +401,7 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de
dev->ofdev.node = dp;
dev->ofdev.dev.parent = &dev->bus->ofdev.dev;
dev->ofdev.dev.bus = &ebus_bus_type;
- sprintf(dev->ofdev.dev.bus_id, "ebus[%08x]", dp->node);
+ dev_set_name(&dev->ofdev.dev, "ebus[%08x]", dp->node);
/* Register with core */
if (of_device_register(&dev->ofdev) != 0)
@@ -501,7 +501,7 @@ void __init ebus_init(void)
ebus->ofdev.node = dp;
ebus->ofdev.dev.parent = &pdev->dev;
ebus->ofdev.dev.bus = &ebus_bus_type;
- sprintf(ebus->ofdev.dev.bus_id, "ebus%d", num_ebus);
+ dev_set_name(&ebus->ofdev.dev, "ebus%d", num_ebus);
/* Register with core */
if (of_device_register(&ebus->ofdev) != 0)
diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc64/kernel/iommu_common.h
index f3575a614fa..53b19c8231a 100644
--- a/arch/sparc64/kernel/iommu_common.h
+++ b/arch/sparc64/kernel/iommu_common.h
@@ -23,7 +23,7 @@
#define IO_PAGE_SHIFT 13
#define IO_PAGE_SIZE (1UL << IO_PAGE_SHIFT)
#define IO_PAGE_MASK (~(IO_PAGE_SIZE-1))
-#define IO_PAGE_ALIGN(addr) (((addr)+IO_PAGE_SIZE-1)&IO_PAGE_MASK)
+#define IO_PAGE_ALIGN(addr) ALIGN(addr, IO_PAGE_SIZE)
#define IO_TSB_ENTRIES (128*1024)
#define IO_TSB_SIZE (IO_TSB_ENTRIES * 8)
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index b441a26b73b..c481673d249 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -621,8 +621,9 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
{
struct irq_handler_data *data;
- struct ino_bucket *bucket;
unsigned long hv_err, cookie;
+ struct ino_bucket *bucket;
+ struct irq_desc *desc;
unsigned int virt_irq;
bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC);
@@ -643,6 +644,13 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
if (unlikely(!data))
return 0;
+ /* In order to make the LDC channel startup sequence easier,
+ * especially wrt. locking, we do not let request_irq() enable
+ * the interrupt.
+ */
+ desc = irq_desc + virt_irq;
+ desc->status |= IRQ_NOAUTOEN;
+
set_irq_chip_data(virt_irq, data);
/* Catch accidental accesses to these things. IMAP/ICLR handling
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index f43b5d75535..201a6e547e4 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -478,9 +478,9 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
return 0;
}
-/* Called with kretprobe_lock held. The value stored in the return
- * address register is actually 2 instructions before where the
- * callee will return to. Sequences usually look something like this
+/* The value stored in the return address register is actually 2
+ * instructions before where the callee will return to.
+ * Sequences usually look something like this
*
* call some_function <--- return register points here
* nop <--- call delay slot
@@ -512,8 +512,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
INIT_HLIST_HEAD(&empty_rp);
- spin_lock_irqsave(&kretprobe_lock, flags);
- head = kretprobe_inst_table_head(current);
+ kretprobe_hash_lock(current, &head, &flags);
/*
* It is possible to have multiple instances associated with a given
@@ -553,7 +552,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
regs->tnpc = orig_ret_address + 4;
reset_current_kprobe();
- spin_unlock_irqrestore(&kretprobe_lock, flags);
+ kretprobe_hash_unlock(current, &flags);
preempt_enable_no_resched();
hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
diff --git a/arch/sparc64/kernel/ldc.c b/arch/sparc64/kernel/ldc.c
index 63969f61028..d68982330f6 100644
--- a/arch/sparc64/kernel/ldc.c
+++ b/arch/sparc64/kernel/ldc.c
@@ -1,6 +1,6 @@
/* ldc.c: Logical Domain Channel link-layer protocol driver.
*
- * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
*/
#include <linux/kernel.h>
@@ -23,8 +23,8 @@
#define DRV_MODULE_NAME "ldc"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.0"
-#define DRV_MODULE_RELDATE "June 25, 2007"
+#define DRV_MODULE_VERSION "1.1"
+#define DRV_MODULE_RELDATE "July 22, 2008"
static char version[] __devinitdata =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -1235,13 +1235,9 @@ int ldc_bind(struct ldc_channel *lp, const char *name)
unsigned long hv_err, flags;
int err = -EINVAL;
- spin_lock_irqsave(&lp->lock, flags);
-
- if (!name)
- goto out_err;
-
- if (lp->state != LDC_STATE_INIT)
- goto out_err;
+ if (!name ||
+ (lp->state != LDC_STATE_INIT))
+ return -EINVAL;
snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name);
snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);
@@ -1250,25 +1246,32 @@ int ldc_bind(struct ldc_channel *lp, const char *name)
IRQF_SAMPLE_RANDOM | IRQF_SHARED,
lp->rx_irq_name, lp);
if (err)
- goto out_err;
+ return err;
err = request_irq(lp->cfg.tx_irq, ldc_tx,
IRQF_SAMPLE_RANDOM | IRQF_SHARED,
lp->tx_irq_name, lp);
- if (err)
- goto out_free_rx_irq;
+ if (err) {
+ free_irq(lp->cfg.rx_irq, lp);
+ return err;
+ }
+
+ spin_lock_irqsave(&lp->lock, flags);
+
+ enable_irq(lp->cfg.rx_irq);
+ enable_irq(lp->cfg.tx_irq);
lp->flags |= LDC_FLAG_REGISTERED_IRQS;
err = -ENODEV;
hv_err = sun4v_ldc_tx_qconf(lp->id, 0, 0);
if (hv_err)
- goto out_free_tx_irq;
+ goto out_free_irqs;
hv_err = sun4v_ldc_tx_qconf(lp->id, lp->tx_ra, lp->tx_num_entries);
if (hv_err)
- goto out_free_tx_irq;
+ goto out_free_irqs;
hv_err = sun4v_ldc_rx_qconf(lp->id, 0, 0);
if (hv_err)
@@ -1304,14 +1307,11 @@ out_unmap_rx:
out_unmap_tx:
sun4v_ldc_tx_qconf(lp->id, 0, 0);
-out_free_tx_irq:
+out_free_irqs:
lp->flags &= ~LDC_FLAG_REGISTERED_IRQS;
free_irq(lp->cfg.tx_irq, lp);
-
-out_free_rx_irq:
free_irq(lp->cfg.rx_irq, lp);
-out_err:
spin_unlock_irqrestore(&lp->lock, flags);
return err;
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index d569f60c24b..4fd48ab7dda 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -797,9 +797,9 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
op->dev.parent = parent;
op->dev.bus = &of_platform_bus_type;
if (!parent)
- strcpy(op->dev.bus_id, "root");
+ dev_set_name(&op->dev, "root");
else
- sprintf(op->dev.bus_id, "%08x", dp->node);
+ dev_set_name(&op->dev, "%08x", dp->node);
if (of_device_register(op)) {
printk("%s: Could not register of device.\n",
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index d00a3656c28..55096195458 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -408,7 +408,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
dev->class = class >> 8;
dev->revision = class & 0xff;
- sprintf(dev->dev.bus_id, "%04x:%02x:%02x.%d", pci_domain_nr(bus),
+ dev_set_name(&dev->dev, "%04x:%02x:%02x.%d", pci_domain_nr(bus),
dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
if (ofpci_verbose)
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index c1f1ff29e97..8a9cd3e165b 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -96,7 +96,7 @@ void cpu_idle(void)
set_thread_flag(TIF_POLLING_NRFLAG);
while(1) {
- tick_nohz_stop_sched_tick();
+ tick_nohz_stop_sched_tick(1);
while (!need_resched() && !cpu_is_offline(cpu))
sparc64_yield(cpu);
@@ -683,9 +683,9 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
((unsigned long) child_sf) - STACK_BIAS;
/* Special case, if we are spawning a kernel thread from
- * a userspace task (via KMOD, NFS, or similar) we must
- * disable performance counters in the child because the
- * address space and protection realm are changing.
+ * a userspace task (usermode helper, NFS or similar), we
+ * must disable performance counters in the child because
+ * the address space and protection realm are changing.
*/
if (t->flags & _TIF_PERFCTR) {
t->user_cntd0 = t->user_cntd1 = NULL;
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index e1f4eba2e57..39749e32dc7 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -418,7 +418,7 @@ asmlinkage long sparc_pipe(struct pt_regs *regs)
int fd[2];
int error;
- error = do_pipe(fd);
+ error = do_pipe_flags(fd, 0);
if (error)
goto out;
regs->u_regs[UREG_I1] = fd[1];
diff --git a/arch/sparc64/kernel/sysfs.c b/arch/sparc64/kernel/sysfs.c
index e885034a6b7..84e5ce14671 100644
--- a/arch/sparc64/kernel/sysfs.c
+++ b/arch/sparc64/kernel/sysfs.c
@@ -14,7 +14,8 @@
static DEFINE_PER_CPU(struct hv_mmu_statistics, mmu_stats) __attribute__((aligned(64)));
#define SHOW_MMUSTAT_ULONG(NAME) \
-static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+static ssize_t show_##NAME(struct sys_device *dev, \
+ struct sysdev_attribute *attr, char *buf) \
{ \
struct hv_mmu_statistics *p = &per_cpu(mmu_stats, dev->id); \
return sprintf(buf, "%lu\n", p->NAME); \
@@ -135,13 +136,16 @@ static unsigned long write_mmustat_enable(unsigned long val)
return sun4v_mmustat_conf(ra, &orig_ra);
}
-static ssize_t show_mmustat_enable(struct sys_device *s, char *buf)
+static ssize_t show_mmustat_enable(struct sys_device *s,
+ struct sysdev_attribute *attr, char *buf)
{
unsigned long val = run_on_cpu(s->id, read_mmustat_enable, 0);
return sprintf(buf, "%lx\n", val);
}
-static ssize_t store_mmustat_enable(struct sys_device *s, const char *buf, size_t count)
+static ssize_t store_mmustat_enable(struct sys_device *s,
+ struct sysdev_attribute *attr, const char *buf,
+ size_t count)
{
unsigned long val, err;
int ret = sscanf(buf, "%ld", &val);
@@ -179,14 +183,16 @@ static void unregister_mmu_stats(struct sys_device *s)
#endif
#define SHOW_CPUDATA_ULONG_NAME(NAME, MEMBER) \
-static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+static ssize_t show_##NAME(struct sys_device *dev, \
+ struct sysdev_attribute *attr, char *buf) \
{ \
cpuinfo_sparc *c = &cpu_data(dev->id); \
return sprintf(buf, "%lu\n", c->MEMBER); \
}
#define SHOW_CPUDATA_UINT_NAME(NAME, MEMBER) \
-static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+static ssize_t show_##NAME(struct sys_device *dev, \
+ struct sysdev_attribute *attr, char *buf) \
{ \
cpuinfo_sparc *c = &cpu_data(dev->id); \
return sprintf(buf, "%u\n", c->MEMBER); \
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 8b5282d433c..1095bf4c510 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -81,7 +81,8 @@ sys_call_table32:
/*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy
.word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait
/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, sys_timerfd_create, sys_eventfd, compat_sys_fallocate
- .word compat_sys_timerfd_settime, compat_sys_timerfd_gettime
+ .word compat_sys_timerfd_settime, compat_sys_timerfd_gettime, compat_sys_signalfd4, sys_eventfd2, sys_epoll_create1
+/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1
#endif /* CONFIG_COMPAT */
@@ -154,4 +155,5 @@ sys_call_table:
/*300*/ .word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
.word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
/*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
- .word sys_timerfd_settime, sys_timerfd_gettime
+ .word sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
+/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index bedc4c159b1..a0c6a97eec6 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -884,6 +884,16 @@ static struct notifier_block sparc64_cpufreq_notifier_block = {
.notifier_call = sparc64_cpufreq_notifier
};
+static int __init register_sparc64_cpufreq_notifier(void)
+{
+
+ cpufreq_register_notifier(&sparc64_cpufreq_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
+ return 0;
+}
+
+core_initcall(register_sparc64_cpufreq_notifier);
+
#endif /* CONFIG_CPU_FREQ */
static int sparc64_next_event(unsigned long delta,
@@ -1050,11 +1060,6 @@ void __init time_init(void)
sparc64_clockevent.mult, sparc64_clockevent.shift);
setup_sparc64_timer();
-
-#ifdef CONFIG_CPU_FREQ
- cpufreq_register_notifier(&sparc64_cpufreq_notifier_block,
- CPUFREQ_TRANSITION_NOTIFIER);
-#endif
}
unsigned long long sched_clock(void)
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 0aa819c29db..bd30ecba563 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -36,9 +36,6 @@
#include <asm/processor.h>
#include <asm/timer.h>
#include <asm/head.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
#include <asm/prom.h>
#include "entry.h"
diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c
index e78b3517940..a490077891a 100644
--- a/arch/sparc64/kernel/vio.c
+++ b/arch/sparc64/kernel/vio.c
@@ -224,7 +224,7 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
if (!strcmp(type, "domain-services-port"))
bus_id_name = "ds";
- if (strlen(bus_id_name) >= KOBJ_NAME_LEN - 4) {
+ if (strlen(bus_id_name) >= BUS_ID_SIZE - 4) {
printk(KERN_ERR "VIO: bus_id_name [%s] is too long.\n",
bus_id_name);
return NULL;
@@ -260,16 +260,14 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
vio_fill_channel_info(hp, mp, vdev);
if (!id) {
- snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s",
- bus_id_name);
+ dev_set_name(&vdev->dev, "%s", bus_id_name);
vdev->dev_no = ~(u64)0;
} else if (!cfg_handle) {
- snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu",
- bus_id_name, *id);
+ dev_set_name(&vdev->dev, "%s-%lu", bus_id_name, *id);
vdev->dev_no = *id;
} else {
- snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu-%lu",
- bus_id_name, *cfg_handle, *id);
+ dev_set_name(&vdev->dev, "%s-%lu-%lu", bus_id_name,
+ *cfg_handle, *id);
vdev->dev_no = *cfg_handle;
}
@@ -292,12 +290,12 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
}
vdev->dp = dp;
- printk(KERN_INFO "VIO: Adding device %s\n", vdev->dev.bus_id);
+ printk(KERN_INFO "VIO: Adding device %s\n", dev_name(&vdev->dev));
err = device_register(&vdev->dev);
if (err) {
printk(KERN_ERR "VIO: Could not register device %s, err=%d\n",
- vdev->dev.bus_id, err);
+ dev_name(&vdev->dev), err);
kfree(vdev);
return NULL;
}
@@ -330,7 +328,7 @@ static void vio_remove(struct mdesc_handle *hp, u64 node)
dev = device_find_child(&root_vdev->dev, (void *) node,
vio_md_node_match);
if (dev) {
- printk(KERN_INFO "VIO: Removing device %s\n", dev->bus_id);
+ printk(KERN_INFO "VIO: Removing device %s\n", dev_name(dev));
device_unregister(dev);
}
diff --git a/arch/sparc64/mm/hugetlbpage.c b/arch/sparc64/mm/hugetlbpage.c
index ebefd2a1437..f27d10369e0 100644
--- a/arch/sparc64/mm/hugetlbpage.c
+++ b/arch/sparc64/mm/hugetlbpage.c
@@ -175,7 +175,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
return -ENOMEM;
if (flags & MAP_FIXED) {
- if (prepare_hugepage_range(addr, len))
+ if (prepare_hugepage_range(file, addr, len))
return -EINVAL;
return addr;
}
@@ -195,7 +195,8 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
pgoff, flags);
}
-pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+ unsigned long addr, unsigned long sz)
{
pgd_t *pgd;
pud_t *pud;
@@ -294,6 +295,11 @@ int pmd_huge(pmd_t pmd)
return 0;
}
+int pud_huge(pud_t pud)
+{
+ return 0;
+}
+
struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
pmd_t *pmd, int write)
{
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 84898c44dd4..71329747395 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -788,7 +788,6 @@ int numa_cpu_lookup_table[NR_CPUS];
cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES];
#ifdef CONFIG_NEED_MULTIPLE_NODES
-static bootmem_data_t plat_node_bdata[MAX_NUMNODES];
struct mdesc_mblock {
u64 base;
@@ -871,7 +870,7 @@ static void __init allocate_node_data(int nid)
NODE_DATA(nid) = __va(paddr);
memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
- NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
+ NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
#endif
p = NODE_DATA(nid);
diff --git a/arch/um/include/init.h b/arch/um/include/init.h
index b00a95741d4..37dd097c16c 100644
--- a/arch/um/include/init.h
+++ b/arch/um/include/init.h
@@ -45,6 +45,8 @@ typedef void (*exitcall_t)(void);
# define __section(S) __attribute__ ((__section__(#S)))
#endif
+#if __GNUC__ == 3
+
#if __GNUC_MINOR__ >= 3
# define __used __attribute__((__used__))
#else
@@ -52,6 +54,12 @@ typedef void (*exitcall_t)(void);
#endif
#else
+#if __GNUC__ == 4
+# define __used __attribute__((__used__))
+#endif
+#endif
+
+#else
#include <linux/compiler.h>
#endif
/* These are for everybody (although not all archs will actually
diff --git a/arch/um/include/irq_kern.h b/arch/um/include/irq_kern.h
index 4f775597fd5..fba3895274f 100644
--- a/arch/um/include/irq_kern.h
+++ b/arch/um/include/irq_kern.h
@@ -13,8 +13,6 @@ extern int um_request_irq(unsigned int irq, int fd, int type,
irq_handler_t handler,
unsigned long irqflags, const char * devname,
void *dev_id);
-extern int init_aio_irq(int irq, char *name,
- irq_handler_t handler);
#endif
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
index e60b31873de..c6c784df267 100644
--- a/arch/um/include/irq_user.h
+++ b/arch/um/include/irq_user.h
@@ -21,8 +21,6 @@ struct irq_fd {
enum { IRQ_READ, IRQ_WRITE };
extern void sigio_handler(int sig, struct uml_pt_regs *regs);
-extern int activate_fd(int irq, int fd, int type, void *dev_id);
-extern void free_irq_by_irq_and_dev(unsigned int irq, void *dev_id);
extern void free_irq_by_fd(int fd);
extern void reactivate_fd(int fd, int irqnum);
extern void deactivate_fd(int fd, int irqnum);
diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h
index b073f8a86bd..64d2c744330 100644
--- a/arch/um/include/skas/skas.h
+++ b/arch/um/include/skas/skas.h
@@ -16,7 +16,6 @@ extern int user_thread(unsigned long stack, int flags);
extern void new_thread_handler(void);
extern void handle_syscall(struct uml_pt_regs *regs);
extern int new_mm(unsigned long stack);
-extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
extern long execute_syscall_skas(void *r);
extern unsigned long current_stub_stack(void);
diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h
index 2b6fc8e0f07..45c04999d67 100644
--- a/arch/um/include/um_uaccess.h
+++ b/arch/um/include/um_uaccess.h
@@ -34,7 +34,6 @@ extern int copy_to_user(void __user *to, const void *from, int n);
extern int __do_copy_to_user(void *to, const void *from, int n,
void **fault_addr, jmp_buf **fault_catcher);
-extern void __do_copy(void *to, const void *from, int n);
/*
* strncpy_from_user: - Copy a NUL terminated string from userspace.
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 91587f8db34..3d7aad09b17 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -102,7 +102,7 @@ void sigio_handler(int sig, struct uml_pt_regs *regs)
static DEFINE_SPINLOCK(irq_lock);
-int activate_fd(int irq, int fd, int type, void *dev_id)
+static int activate_fd(int irq, int fd, int type, void *dev_id)
{
struct pollfd *tmp_pfd;
struct irq_fd *new_fd, *irq_fd;
@@ -216,7 +216,7 @@ static int same_irq_and_dev(struct irq_fd *irq, void *d)
return ((irq->irq == data->irq) && (irq->id == data->dev));
}
-void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
+static void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
{
struct irq_and_dev data = ((struct irq_and_dev) { .irq = irq,
.dev = dev });
@@ -403,37 +403,6 @@ void __init init_IRQ(void)
}
}
-int init_aio_irq(int irq, char *name, irq_handler_t handler)
-{
- int fds[2], err;
-
- err = os_pipe(fds, 1, 1);
- if (err) {
- printk(KERN_ERR "init_aio_irq - os_pipe failed, err = %d\n",
- -err);
- goto out;
- }
-
- err = um_request_irq(irq, fds[0], IRQ_READ, handler,
- IRQF_DISABLED | IRQF_SAMPLE_RANDOM, name,
- (void *) (long) fds[0]);
- if (err) {
- printk(KERN_ERR "init_aio_irq - : um_request_irq failed, "
- "err = %d\n",
- err);
- goto out_close;
- }
-
- err = fds[1];
- goto out;
-
- out_close:
- os_close_file(fds[0]);
- os_close_file(fds[1]);
- out:
- return err;
-}
-
/*
* IRQ stack entry and exit:
*
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index ccc02a616c2..836fc9b9470 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -18,7 +18,6 @@ EXPORT_SYMBOL(get_signals);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(sys_waitpid);
EXPORT_SYMBOL(flush_tlb_range);
-EXPORT_SYMBOL(arch_validate);
EXPORT_SYMBOL(high_physmem);
EXPORT_SYMBOL(empty_zero_page);
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index b0ee64622ff..e2274ef3155 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -21,7 +21,7 @@
/* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
unsigned long *empty_zero_page = NULL;
/* allocated in paging_init and unchanged thereafter */
-unsigned long *empty_bad_page = NULL;
+static unsigned long *empty_bad_page = NULL;
/*
* Initialized during boot, and readonly for initializing page tables
@@ -240,37 +240,6 @@ void __init paging_init(void)
#endif
}
-struct page *arch_validate(struct page *page, gfp_t mask, int order)
-{
- unsigned long addr, zero = 0;
- int i;
-
- again:
- if (page == NULL)
- return page;
- if (PageHighMem(page))
- return page;
-
- addr = (unsigned long) page_address(page);
- for (i = 0; i < (1 << order); i++) {
- current->thread.fault_addr = (void *) addr;
- if (__do_copy_to_user((void __user *) addr, &zero,
- sizeof(zero),
- &current->thread.fault_addr,
- &current->thread.fault_catcher)) {
- if (!(mask & __GFP_WAIT))
- return NULL;
- else break;
- }
- addr += PAGE_SIZE;
- }
-
- if (i == (1 << order))
- return page;
- page = alloc_pages(mask, order);
- goto again;
-}
-
/*
* This can't do anything because nothing in the kernel image can be freed
* since it's not in kernel physical memory.
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index 9757085a022..a1a9090254c 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -185,7 +185,7 @@ unsigned long find_iomem(char *driver, unsigned long *len_out)
return 0;
}
-int setup_iomem(void)
+static int setup_iomem(void)
{
struct iomem_region *region = iomem_regions;
unsigned long iomem_start = high_physmem + PAGE_SIZE;
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 83603cfbde8..a1c6d07cac3 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -243,7 +243,7 @@ void default_idle(void)
if (need_resched())
schedule();
- tick_nohz_stop_sched_tick();
+ tick_nohz_stop_sched_tick(1);
nsecs = disable_timer();
idle_sleep(nsecs);
tick_nohz_restart_sched_tick();
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 47b57b497d5..15e8b7c4de1 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -225,7 +225,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
return ret;
}
-void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs,
+static void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs,
int error_code)
{
struct siginfo info;
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index c3e2f369c33..47f04f4a346 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -13,14 +13,6 @@
#include "kern_util.h"
#include "os.h"
-/*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long sched_clock(void)
-{
- return (unsigned long long)jiffies_64 * (NSEC_PER_SEC / HZ);
-}
-
void timer_handler(int sig, struct uml_pt_regs *regs)
{
unsigned long flags;
diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c
index f0f4b040d7c..dd33f040c52 100644
--- a/arch/um/kernel/uaccess.c
+++ b/arch/um/kernel/uaccess.c
@@ -12,7 +12,7 @@
#include <linux/string.h>
#include "os.h"
-void __do_copy(void *to, const void *from, int n)
+static void __do_copy(void *to, const void *from, int n)
{
memcpy(to, from, n);
}
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index eb8f2e4be19..63d299df152 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -530,7 +530,7 @@ static void tty_close(int master, int slave)
printk(UM_KERN_CONT "No, enabling workaround\n");
}
-void __init check_sigio(void)
+static void __init check_sigio(void)
{
if ((access("/dev/ptmx", R_OK) < 0) &&
(access("/dev/ptyp0", R_OK) < 0)) {
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 5aade6027e4..6ae180703a6 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -126,7 +126,7 @@ void set_sigstack(void *sig_stack, int size)
panic("enabling signal stack failed, errno = %d\n", errno);
}
-void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
+static void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
void handle_signal(int sig, struct sigcontext *sc)
{
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 172ad8f72e1..d6e0a2234b8 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -96,7 +96,7 @@ bad_wait:
extern unsigned long current_stub_stack(void);
-void get_skas_faultinfo(int pid, struct faultinfo * fi)
+static void get_skas_faultinfo(int pid, struct faultinfo *fi)
{
int err;
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index 106fa864155..a27defb8188 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -245,7 +245,7 @@ int __init set_umid(char *name)
/* Changed in make_umid, which is called during early boot */
static int umid_setup = 0;
-int __init make_umid(void)
+static int __init make_umid(void)
{
int fd, err;
char tmp[256];
diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c
index a74442d1376..2c6d0d731c1 100644
--- a/arch/um/sys-i386/bugs.c
+++ b/arch/um/sys-i386/bugs.c
@@ -12,7 +12,7 @@
#include "sysdep/ptrace.h"
/* Set during early boot */
-int host_has_cmov = 1;
+static int host_has_cmov = 1;
static jmp_buf cmov_test_return;
static void cmov_sigill_test_handler(int sig)
diff --git a/arch/um/sys-i386/checksum.S b/arch/um/sys-i386/checksum.S
index 62c7e564f22..f058d2f82e1 100644
--- a/arch/um/sys-i386/checksum.S
+++ b/arch/um/sys-i386/checksum.S
@@ -243,13 +243,12 @@ unsigned int csum_partial_copy_generic (const char *src, char *dst,
.previous
.align 4
-.globl csum_partial_copy_generic_i386
-
+
#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
#define ARGBASE 16
#define FP 12
-
+
csum_partial_copy_generic_i386:
subl $4,%esp
pushl %edi
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index a34263e6b08..a4846a84a7b 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -14,8 +14,8 @@
extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
-long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
- void **addr, int done)
+static long write_ldt_entry(struct mm_id *mm_idp, int func,
+ struct user_desc *desc, void **addr, int done)
{
long res;
diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig
deleted file mode 100644
index 4379f43505e..00000000000
--- a/arch/v850/Kconfig
+++ /dev/null
@@ -1,353 +0,0 @@
-#############################################################################
-#
-# For a description of the syntax of this configuration file,
-# see Documentation/kbuild/kconfig-language.txt.
-#
-#############################################################################
-
-mainmenu "uClinux/v850 (w/o MMU) Kernel Configuration"
-
-config MMU
- bool
- default n
-config ZONE_DMA
- bool
- default y
-config RWSEM_GENERIC_SPINLOCK
- bool
- default y
-config RWSEM_XCHGADD_ALGORITHM
- bool
- default n
-config GENERIC_FIND_NEXT_BIT
- bool
- default y
-config GENERIC_HWEIGHT
- bool
- default y
-config GENERIC_CALIBRATE_DELAY
- bool
- default y
-
-config GENERIC_HARDIRQS
- bool
- default y
-
-config GENERIC_IRQ_PROBE
- bool
- default y
-
-config GENERIC_TIME
- bool
- default y
-
-config TIME_LOW_RES
- bool
- default y
-
-config ARCH_HAS_ILOG2_U32
- bool
- default n
-
-config ARCH_HAS_ILOG2_U64
- bool
- default n
-
-config ARCH_SUPPORTS_AOUT
- def_bool y
-
-# Turn off some random 386 crap that can affect device config
-config ISA
- bool
- default n
-config ISAPNP
- bool
- default n
-config EISA
- bool
- default n
-config MCA
- bool
- default n
-
-
-#############################################################################
-#### v850-specific config
-
-# Define the architecture
-config V850
- bool
- default y
- select HAVE_IDE
-
-menu "Processor type and features"
-
- choice
- prompt "Platform"
- default GDB
- config V850E_SIM
- bool "GDB"
- config RTE_CB_MA1
- bool "RTE-V850E/MA1-CB"
- config RTE_CB_NB85E
- bool "RTE-V850E/NB85E-CB"
- config RTE_CB_ME2
- bool "RTE-V850E/ME2-CB"
- config V850E_AS85EP1
- bool "AS85EP1"
- config V850E2_SIM85E2C
- bool "sim85e2c"
- config V850E2_SIM85E2S
- bool "sim85e2s"
- config V850E2_FPGA85E2C
- bool "NA85E2C-FPGA"
- config V850E2_ANNA
- bool "Anna"
- endchoice
-
- #### V850E processor-specific config
-
- # All CPUs currently supported use the v850e architecture
- config V850E
- bool
- default y
-
- # The RTE-V850E/MA1-CB is the only type of V850E/MA1 platform we
- # currently support
- config V850E_MA1
- bool
- depends on RTE_CB_MA1
- default y
- # Similarly for the RTE-V850E/NB85E-CB - V850E/TEG
- config V850E_TEG
- bool
- depends on RTE_CB_NB85E
- default y
- # ... and the RTE-V850E/ME2-CB - V850E/ME2
- config V850E_ME2
- bool
- depends on RTE_CB_ME2
- default y
-
-
- #### sim85e2-specific config
-
- config V850E2_SIM85E2
- bool
- depends on V850E2_SIM85E2C || V850E2_SIM85E2S
- default y
-
-
- #### V850E2 processor-specific config
-
- # V850E2 processors
- config V850E2
- bool
- depends on V850E2_SIM85E2 || V850E2_FPGA85E2C || V850E2_ANNA
- default y
-
-
- #### RTE-CB platform-specific config
-
- # Boards in the RTE-x-CB series
- config RTE_CB
- bool
- depends on RTE_CB_MA1 || RTE_CB_NB85E || RTE_CB_ME2
- default y
-
- config RTE_CB_MULTI
- bool
- # RTE_CB_NB85E can either have multi ROM support or not, but
- # other platforms (currently only RTE_CB_MA1) require it.
- prompt "Multi monitor ROM support" if RTE_CB_NB85E
- depends on RTE_CB_MA1 || RTE_CB_NB85E
- default y
-
- config RTE_CB_MULTI_DBTRAP
- bool "Pass illegal insn trap / dbtrap to kernel"
- depends on RTE_CB_MULTI
- default n
-
- config RTE_CB_MA1_KSRAM
- bool "Kernel in SRAM (limits size of kernel)"
- depends on RTE_CB_MA1 && RTE_CB_MULTI
- default n
-
- config RTE_MB_A_PCI
- bool "Mother-A PCI support"
- depends on RTE_CB
- default y
-
- # The GBUS is used to talk to the RTE-MOTHER-A board
- config RTE_GBUS_INT
- bool
- depends on RTE_MB_A_PCI
- default y
-
- # The only PCI bus we support is on the RTE-MOTHER-A board
- config PCI
- bool
- default RTE_MB_A_PCI
-
- #### Some feature-specific configs
-
- # Everything except for the GDB simulator uses the same interrupt controller
- config V850E_INTC
- bool
- default !V850E_SIM
-
- # Everything except for the various simulators uses the "Timer D" unit
- config V850E_TIMER_D
- bool
- default !V850E_SIM && !V850E2_SIM85E2
-
- # Cache control used on some v850e1 processors
- config V850E_CACHE
- bool
- default V850E_TEG || V850E_ME2
-
- # Cache control used on v850e2 processors; I think this should
- # actually apply to more, but currently only the SIM85E2S uses it
- config V850E2_CACHE
- bool
- default V850E2_SIM85E2S
-
- config NO_CACHE
- bool
- default !V850E_CACHE && !V850E2_CACHE
-
- # HZ depends on the platform
- config HZ
- int
- default 24 if V850E_SIM || V850E2_SIM85E2
- default 122 if V850E2_FPGA85E2C
- default 100
-
- #### Misc config
-
- config ROM_KERNEL
- bool "Kernel in ROM"
- depends on V850E2_ANNA || V850E_AS85EP1 || RTE_CB_ME2
-
- # Some platforms pre-zero memory, in which case the kernel doesn't need to
- config ZERO_BSS
- bool
- depends on !V850E2_SIM85E2C
- default y
-
- # The crappy-ass zone allocator requires that the start of allocatable
- # memory be aligned to the largest possible allocation.
- config FORCE_MAX_ZONEORDER
- int
- default 8 if V850E2_SIM85E2C || V850E2_FPGA85E2C
-
- config V850E_HIGHRES_TIMER
- bool "High resolution timer support"
- depends on V850E_TIMER_D
- config TIME_BOOTUP
- bool "Time bootup"
- depends on V850E_HIGHRES_TIMER
-
- config RESET_GUARD
- bool "Reset Guard"
-
-source "mm/Kconfig"
-
-endmenu
-
-
-#############################################################################
-
-source init/Kconfig
-
-#############################################################################
-
-menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
-
-# config PCI
-# bool "PCI support"
-# help
-# Support for PCI bus.
-
-source "drivers/pci/Kconfig"
-
-source "drivers/pcmcia/Kconfig"
-
-source "drivers/pci/hotplug/Kconfig"
-
-endmenu
-
-menu "Executable file formats"
-
-source "fs/Kconfig.binfmt"
-
-endmenu
-
-source "net/Kconfig"
-
-#############################################################################
-
-source "drivers/base/Kconfig"
-
-source drivers/mtd/Kconfig
-
-source drivers/parport/Kconfig
-
-#source drivers/pnp/Kconfig
-
-source drivers/block/Kconfig
-
-#############################################################################
-
-menu "Disk device support"
-
-source "drivers/ide/Kconfig"
-
-source "drivers/scsi/Kconfig"
-
-endmenu
-
-#############################################################################
-
-
-source "drivers/md/Kconfig"
-
-source "drivers/message/fusion/Kconfig"
-
-source "drivers/ieee1394/Kconfig"
-
-source "drivers/message/i2o/Kconfig"
-
-source "drivers/net/Kconfig"
-
-source "drivers/isdn/Kconfig"
-
-#source "drivers/telephony/Kconfig"
-
-#
-# input before char - char/joystick depends on it. As does USB.
-#
-source "drivers/input/Kconfig"
-
-source "drivers/char/Kconfig"
-
-#source drivers/misc/Config.in
-source "drivers/media/Kconfig"
-
-source "fs/Kconfig"
-
-source "drivers/video/Kconfig"
-
-source "sound/Kconfig"
-
-source "drivers/usb/Kconfig"
-
-source "arch/v850/Kconfig.debug"
-
-source "security/Kconfig"
-
-source "crypto/Kconfig"
-
-source "lib/Kconfig"
-
-#############################################################################
diff --git a/arch/v850/Kconfig.debug b/arch/v850/Kconfig.debug
deleted file mode 100644
index 4acfb9cca1c..00000000000
--- a/arch/v850/Kconfig.debug
+++ /dev/null
@@ -1,10 +0,0 @@
-menu "Kernel hacking"
-
-source "lib/Kconfig.debug"
-
-config NO_KERNEL_MSG
- bool "Suppress Kernel BUG Messages"
- help
- Do not output any debug BUG messages within the kernel.
-
-endmenu
diff --git a/arch/v850/Makefile b/arch/v850/Makefile
deleted file mode 100644
index 8b629df0029..00000000000
--- a/arch/v850/Makefile
+++ /dev/null
@@ -1,54 +0,0 @@
-#
-# arch/v850/Makefile
-#
-# Copyright (C) 2001,02,03,05 NEC Corporation
-# Copyright (C) 2001,02,03,05 Miles Bader <miles@gnu.org>
-#
-# This file is included by the global makefile so that you can add your own
-# architecture-specific flags and dependencies. Remember to do have actions
-# for "archclean" and "archdep" for cleaning up and making dependencies for
-# this architecture
-#
-# 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.
-#
-
-arch_dir = arch/v850
-
-KBUILD_CFLAGS += -mv850e
-# r16 is a fixed pointer to the current task
-KBUILD_CFLAGS += -ffixed-r16 -mno-prolog-function
-KBUILD_CFLAGS += -fno-builtin
-KBUILD_CFLAGS += -D__linux__ -DUTS_SYSNAME=\"uClinux\"
-
-# By default, build a kernel that runs on the gdb v850 simulator.
-KBUILD_DEFCONFIG := sim_defconfig
-
-# This prevents the linker from consolidating the .gnu.linkonce.this_module
-# section into .text (which the v850 default linker script for -r does for
-# some reason)
-LDFLAGS_MODULE += --unique=.gnu.linkonce.this_module
-
-OBJCOPY_FLAGS_BLOB := -I binary -O elf32-little -B v850e
-
-
-head-y := $(arch_dir)/kernel/head.o $(arch_dir)/kernel/init_task.o
-core-y += $(arch_dir)/kernel/
-libs-y += $(arch_dir)/lib/
-
-
-# Deal with the initial contents of the root device
-ifdef ROOT_FS_IMAGE
-core-y += root_fs_image.o
-
-# Because the kernel build-system erases all explicit .o build rules, we
-# have to use an intermediate target to fool it into building for us.
-# This results in it being built anew each time, but that's alright.
-root_fs_image.o: root_fs_image_force
-
-root_fs_image_force: $(ROOT_FS_IMAGE)
- $(OBJCOPY) $(OBJCOPY_FLAGS_BLOB) --rename-section .data=.root,alloc,load,readonly,data,contents $< root_fs_image.o
-endif
-
-CLEAN_FILES += root_fs_image.o
diff --git a/arch/v850/README b/arch/v850/README
deleted file mode 100644
index 12f7f7a665e..00000000000
--- a/arch/v850/README
+++ /dev/null
@@ -1,44 +0,0 @@
-This port to the NEC V850E processor supports the following platforms:
-
- "sim"
- The gdb v850e simulator (CONFIG_V850E_SIM).
-
- "rte-ma1-cb"
- The Midas labs RTE-V850E/MA1-CB and RTE-V850E/NB85E-CB evaluation
- boards (CONFIG_RTE_CB_MA1 and CONFIG_RTE_CB_NB85E). This support
- has only been tested when running with the Multi-debugger monitor
- ROM (for the Green Hills Multi debugger). The optional NEC
- Solution Gear RTE-MOTHER-A motherboard is also supported, which
- allows PCI boards to be used (CONFIG_RTE_MB_A_PCI).
-
- "rte-me2-cb"
- The Midas labs RTE-V850E/ME2-CB evaluation board (CONFIG_RTE_CB_ME2).
- This has only been tested using a kernel downloaded via an ICE
- connection using the Multi debugger. Support for the RTE-MOTHER-A is
- present, but hasn't been tested (unlike the other Midas labs cpu
- boards, the RTE-V850E/ME2-CB includes an ethernet adaptor).
-
- "as85ep1"
- The NEC AS85EP1 V850E evaluation chip/board (CONFIG_V850E_AS85EP1).
-
- "anna"
- The NEC `Anna' (board/chip) implementation of the V850E2 processor
- (CONFIG_V850E2_ANNA).
-
- "sim85e2c", "sim85e2s"
- The sim85e2c and sim85e2s simulators, which are verilog simulations
- of the V850E2 NA85E2C/NA85E2S cpu cores (CONFIG_V850E2_SIM85E2C and
- CONFIG_V850E2_SIM85E2S).
-
- "fpga85e2c"
- A FPGA implementation of the V850E2 NA85E2C cpu core
- (CONFIG_V850E2_FPGA85E2C).
-
-To get a default kernel configuration for a particular platform, you can
-use a <platform>_defconfig make target (e.g., "make rte-me2-cb_defconfig");
-to see which default configurations are possible, look in the directory
-"arch/v850/configs".
-
-Porting to anything with a V850E/MA1 or MA2 processor should be simple.
-See the file <asm-v850/machdep.h> and the files it includes for an example of
-how to add platform/chip-specific support.
diff --git a/arch/v850/configs/rte-ma1-cb_defconfig b/arch/v850/configs/rte-ma1-cb_defconfig
deleted file mode 100644
index 1a5beda36e2..00000000000
--- a/arch/v850/configs/rte-ma1-cb_defconfig
+++ /dev/null
@@ -1,617 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-uc0
-# Fri Sep 2 13:54:27 2005
-#
-# CONFIG_MMU is not set
-# CONFIG_UID16 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-# CONFIG_ISA is not set
-# CONFIG_ISAPNP is not set
-# CONFIG_EISA is not set
-# CONFIG_MCA is not set
-CONFIG_V850=y
-
-#
-# Processor type and features
-#
-# CONFIG_V850E_SIM is not set
-CONFIG_RTE_CB_MA1=y
-# CONFIG_RTE_CB_NB85E is not set
-# CONFIG_RTE_CB_ME2 is not set
-# CONFIG_V850E_AS85EP1 is not set
-# CONFIG_V850E2_SIM85E2C is not set
-# CONFIG_V850E2_SIM85E2S is not set
-# CONFIG_V850E2_FPGA85E2C is not set
-# CONFIG_V850E2_ANNA is not set
-CONFIG_V850E=y
-CONFIG_V850E_MA1=y
-CONFIG_RTE_CB=y
-CONFIG_RTE_CB_MULTI=y
-CONFIG_RTE_CB_MULTI_DBTRAP=y
-# CONFIG_RTE_CB_MA1_KSRAM is not set
-CONFIG_RTE_MB_A_PCI=y
-CONFIG_RTE_GBUS_INT=y
-CONFIG_PCI=y
-CONFIG_V850E_INTC=y
-CONFIG_V850E_TIMER_D=y
-# CONFIG_V850E_CACHE is not set
-# CONFIG_V850E2_CACHE is not set
-CONFIG_NO_CACHE=y
-CONFIG_ZERO_BSS=y
-# CONFIG_V850E_HIGHRES_TIMER is not set
-# CONFIG_RESET_GUARD is not set
-CONFIG_LARGE_ALLOCS=y
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-
-#
-# Code maturity level options
-#
-# CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
-# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-# CONFIG_KALLSYMS is not set
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-# CONFIG_BASE_FULL is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-CONFIG_BASE_SMALL=1
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-# CONFIG_PCI_LEGACY_PROC is not set
-# CONFIG_PCI_NAMES is not set
-# CONFIG_PCI_DEBUG is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_FLAT=y
-# CONFIG_BINFMT_ZFLAT is not set
-# CONFIG_BINFMT_SHARED_FLAT is not set
-# CONFIG_BINFMT_MISC is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-# CONFIG_UNIX is not set
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-# CONFIG_MTD_PARTITIONS is not set
-
-#
-# User Modules And Translation Layers
-#
-# CONFIG_MTD_CHAR is not set
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-CONFIG_MTD_SLRAM=y
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# Disk device support
-#
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_NET_VENDOR_SMC is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NE2000 is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_V850E_UART=y
-CONFIG_V850E_UART_CONSOLE=y
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_LEGACY_PTYS is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-
-#
-# XFS support
-#
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_ROMFS_FS=y
-# CONFIG_MAGIC_ROM_PTR is not set
-CONFIG_INOTIFY=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFSD is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_MAGIC_SYSRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_KOBJECT is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_FS is not set
-# CONFIG_NO_KERNEL_MSG is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
diff --git a/arch/v850/configs/rte-me2-cb_defconfig b/arch/v850/configs/rte-me2-cb_defconfig
deleted file mode 100644
index 15e66647806..00000000000
--- a/arch/v850/configs/rte-me2-cb_defconfig
+++ /dev/null
@@ -1,462 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-uc0
-# Fri Sep 2 13:47:50 2005
-#
-# CONFIG_MMU is not set
-# CONFIG_UID16 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-# CONFIG_ISA is not set
-# CONFIG_ISAPNP is not set
-# CONFIG_EISA is not set
-# CONFIG_MCA is not set
-CONFIG_V850=y
-
-#
-# Processor type and features
-#
-# CONFIG_V850E_SIM is not set
-# CONFIG_RTE_CB_MA1 is not set
-# CONFIG_RTE_CB_NB85E is not set
-CONFIG_RTE_CB_ME2=y
-# CONFIG_V850E_AS85EP1 is not set
-# CONFIG_V850E2_SIM85E2C is not set
-# CONFIG_V850E2_SIM85E2S is not set
-# CONFIG_V850E2_FPGA85E2C is not set
-# CONFIG_V850E2_ANNA is not set
-CONFIG_V850E=y
-CONFIG_V850E_ME2=y
-CONFIG_RTE_CB=y
-# CONFIG_RTE_MB_A_PCI is not set
-# CONFIG_PCI is not set
-CONFIG_V850E_INTC=y
-CONFIG_V850E_TIMER_D=y
-CONFIG_V850E_CACHE=y
-# CONFIG_V850E2_CACHE is not set
-# CONFIG_NO_CACHE is not set
-# CONFIG_ROM_KERNEL is not set
-CONFIG_ZERO_BSS=y
-# CONFIG_V850E_HIGHRES_TIMER is not set
-# CONFIG_RESET_GUARD is not set
-CONFIG_LARGE_ALLOCS=y
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-
-#
-# Code maturity level options
-#
-# CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-# CONFIG_KALLSYMS is not set
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-# CONFIG_BASE_FULL is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-CONFIG_BASE_SMALL=1
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_FLAT=y
-# CONFIG_BINFMT_ZFLAT is not set
-# CONFIG_BINFMT_SHARED_FLAT is not set
-# CONFIG_BINFMT_MISC is not set
-
-#
-# Networking
-#
-# CONFIG_NET is not set
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-# CONFIG_MTD_PARTITIONS is not set
-
-#
-# User Modules And Translation Layers
-#
-# CONFIG_MTD_CHAR is not set
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-CONFIG_MTD_SLRAM=y
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-
-#
-# Disk device support
-#
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Network device support
-#
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=1
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_V850E_UART is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_LEGACY_PTYS is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-
-#
-# XFS support
-#
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_ROMFS_FS=y
-# CONFIG_MAGIC_ROM_PTR is not set
-CONFIG_INOTIFY=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_ARCH_HAS_HCD is not set
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_MAGIC_SYSRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_KOBJECT is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_FS is not set
-# CONFIG_NO_KERNEL_MSG is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
diff --git a/arch/v850/configs/sim_defconfig b/arch/v850/configs/sim_defconfig
deleted file mode 100644
index f31ba7398ad..00000000000
--- a/arch/v850/configs/sim_defconfig
+++ /dev/null
@@ -1,451 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-uc0
-# Fri Sep 2 13:36:43 2005
-#
-# CONFIG_MMU is not set
-# CONFIG_UID16 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-# CONFIG_ISA is not set
-# CONFIG_ISAPNP is not set
-# CONFIG_EISA is not set
-# CONFIG_MCA is not set
-CONFIG_V850=y
-
-#
-# Processor type and features
-#
-CONFIG_V850E_SIM=y
-# CONFIG_RTE_CB_MA1 is not set
-# CONFIG_RTE_CB_NB85E is not set
-# CONFIG_RTE_CB_ME2 is not set
-# CONFIG_V850E_AS85EP1 is not set
-# CONFIG_V850E2_SIM85E2C is not set
-# CONFIG_V850E2_SIM85E2S is not set
-# CONFIG_V850E2_FPGA85E2C is not set
-# CONFIG_V850E2_ANNA is not set
-CONFIG_V850E=y
-# CONFIG_PCI is not set
-# CONFIG_V850E_INTC is not set
-# CONFIG_V850E_TIMER_D is not set
-# CONFIG_V850E_CACHE is not set
-# CONFIG_V850E2_CACHE is not set
-CONFIG_NO_CACHE=y
-CONFIG_ZERO_BSS=y
-# CONFIG_RESET_GUARD is not set
-CONFIG_LARGE_ALLOCS=y
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-
-#
-# Code maturity level options
-#
-# CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-# CONFIG_KALLSYMS is not set
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-# CONFIG_BASE_FULL is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-CONFIG_BASE_SMALL=1
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_FLAT=y
-# CONFIG_BINFMT_ZFLAT is not set
-# CONFIG_BINFMT_SHARED_FLAT is not set
-# CONFIG_BINFMT_MISC is not set
-
-#
-# Networking
-#
-# CONFIG_NET is not set
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-# CONFIG_MTD_PARTITIONS is not set
-
-#
-# User Modules And Translation Layers
-#
-# CONFIG_MTD_CHAR is not set
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-CONFIG_MTD_SLRAM=y
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-
-#
-# Disk device support
-#
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Network device support
-#
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_LEGACY_PTYS is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-
-#
-# XFS support
-#
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_ROMFS_FS=y
-# CONFIG_MAGIC_ROM_PTR is not set
-CONFIG_INOTIFY=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB_ARCH_HAS_HCD is not set
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_MAGIC_SYSRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_KOBJECT is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_FS is not set
-# CONFIG_NO_KERNEL_MSG is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
-# CONFIG_LIBCRC32C is not set
diff --git a/arch/v850/kernel/Makefile b/arch/v850/kernel/Makefile
deleted file mode 100644
index da5889c5357..00000000000
--- a/arch/v850/kernel/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# arch/v850/kernel/Makefile
-#
-# Copyright (C) 2001,02,03 NEC Electronics Corporation
-# Copyright (C) 2001,02,03 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 archive
-# for more details.
-#
-
-extra-y := head.o init_task.o vmlinux.lds
-
-obj-y += intv.o entry.o process.o syscalls.o time.o setup.o \
- signal.o irq.o mach.o ptrace.o bug.o
-obj-$(CONFIG_MODULES) += module.o v850_ksyms.o
-# chip-specific code
-obj-$(CONFIG_V850E_MA1) += ma.o
-obj-$(CONFIG_V850E_ME2) += me2.o
-obj-$(CONFIG_V850E_TEG) += teg.o
-obj-$(CONFIG_V850E_AS85EP1) += as85ep1.o
-obj-$(CONFIG_V850E2_ANNA) += anna.o
-# platform-specific code
-obj-$(CONFIG_V850E_SIM) += sim.o simcons.o
-obj-$(CONFIG_V850E2_SIM85E2) += sim85e2.o memcons.o
-obj-$(CONFIG_V850E2_FPGA85E2C) += fpga85e2c.o memcons.o
-obj-$(CONFIG_RTE_CB) += rte_cb.o rte_cb_leds.o
-obj-$(CONFIG_RTE_CB_MA1) += rte_ma1_cb.o
-obj-$(CONFIG_RTE_CB_ME2) += rte_me2_cb.o
-obj-$(CONFIG_RTE_CB_NB85E) += rte_nb85e_cb.o
-obj-$(CONFIG_RTE_CB_MULTI) += rte_cb_multi.o
-obj-$(CONFIG_RTE_MB_A_PCI) += rte_mb_a_pci.o
-obj-$(CONFIG_RTE_GBUS_INT) += gbus_int.o
-# feature-specific code
-obj-$(CONFIG_V850E_INTC) += v850e_intc.o
-obj-$(CONFIG_V850E_TIMER_D) += v850e_timer_d.o v850e_utils.o
-obj-$(CONFIG_V850E_CACHE) += v850e_cache.o
-obj-$(CONFIG_V850E2_CACHE) += v850e2_cache.o
-obj-$(CONFIG_V850E_HIGHRES_TIMER) += highres_timer.o
-obj-$(CONFIG_PROC_FS) += procfs.o
diff --git a/arch/v850/kernel/anna-rom.ld b/arch/v850/kernel/anna-rom.ld
deleted file mode 100644
index 7c54e7e3f1b..00000000000
--- a/arch/v850/kernel/anna-rom.ld
+++ /dev/null
@@ -1,16 +0,0 @@
-/* Linker script for the Midas labs Anna V850E2 evaluation board
- (CONFIG_V850E2_ANNA), with kernel in ROM (CONFIG_ROM_KERNEL). */
-
-MEMORY {
- /* 8MB of flash ROM. */
- ROM : ORIGIN = 0, LENGTH = 0x00800000
-
- /* 1MB of static RAM. This memory is mirrored 64 times. */
- SRAM : ORIGIN = SRAM_ADDR, LENGTH = SRAM_SIZE
- /* 64MB of DRAM. */
- SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-SECTIONS {
- ROMK_SECTIONS(ROM, SRAM)
-}
diff --git a/arch/v850/kernel/anna.c b/arch/v850/kernel/anna.c
deleted file mode 100644
index 5978a25170f..00000000000
--- a/arch/v850/kernel/anna.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * arch/v850/kernel/anna.c -- Anna V850E2 evaluation chip/board
- *
- * Copyright (C) 2002,03 NEC Electronics Corporation
- * Copyright (C) 2002,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/major.h>
-#include <linux/irq.h>
-
-#include <asm/machdep.h>
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/v850e_timer_d.h>
-#include <asm/v850e_uart.h>
-
-#include "mach.h"
-
-
-/* SRAM and SDRAM are vaguely contiguous (with a big hole in between; see
- mach_reserve_bootmem for details); use both as one big area. */
-#define RAM_START SRAM_ADDR
-#define RAM_END (SDRAM_ADDR + SDRAM_SIZE)
-
-/* The bits of this port are connected to an 8-LED bar-graph. */
-#define LEDS_PORT 0
-
-
-static void anna_led_tick (void);
-
-
-void __init mach_early_init (void)
-{
- ANNA_ILBEN = 0;
-
- V850E2_CSC(0) = 0x402F;
- V850E2_CSC(1) = 0x4000;
- V850E2_BPC = 0;
- V850E2_BSC = 0xAAAA;
- V850E2_BEC = 0;
-
-#if 0
- V850E2_BHC = 0xFFFF; /* icache all memory, dcache all */
-#else
- V850E2_BHC = 0; /* cache no memory */
-#endif
- V850E2_BCT(0) = 0xB088;
- V850E2_BCT(1) = 0x0008;
- V850E2_DWC(0) = 0x0027;
- V850E2_DWC(1) = 0;
- V850E2_BCC = 0x0006;
- V850E2_ASC = 0;
- V850E2_LBS = 0x0089;
- V850E2_SCR(3) = 0x21A9;
- V850E2_RFS(3) = 0x8121;
-
- v850e_intc_disable_irqs ();
-}
-
-void __init mach_setup (char **cmdline)
-{
- ANNA_PORT_PM (LEDS_PORT) = 0; /* Make all LED pins output pins. */
- mach_tick = anna_led_tick;
-}
-
-void __init mach_get_physical_ram (unsigned long *ram_start,
- unsigned long *ram_len)
-{
- *ram_start = RAM_START;
- *ram_len = RAM_END - RAM_START;
-}
-
-void __init mach_reserve_bootmem ()
-{
- /* The space between SRAM and SDRAM is filled with duplicate
- images of SRAM. Prevent the kernel from using them. */
- reserve_bootmem (SRAM_ADDR + SRAM_SIZE,
- SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE),
- BOOTMEM_DEFAULT);
-}
-
-void mach_gettimeofday (struct timespec *tv)
-{
- tv->tv_sec = 0;
- tv->tv_nsec = 0;
-}
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
- /* Start hardware timer. */
- v850e_timer_d_configure (0, HZ);
- /* Install timer interrupt handler. */
- setup_irq (IRQ_INTCMD(0), timer_action);
-}
-
-static struct v850e_intc_irq_init irq_inits[] = {
- { "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
- { "PIN", IRQ_INTP(0), IRQ_INTP_NUM, 1, 4 },
- { "CCC", IRQ_INTCCC(0), IRQ_INTCCC_NUM, 1, 5 },
- { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 },
- { "DMA", IRQ_INTDMA(0), IRQ_INTDMA_NUM, 1, 2 },
- { "DMXER", IRQ_INTDMXER,1, 1, 2 },
- { "SRE", IRQ_INTSRE(0), IRQ_INTSRE_NUM, 3, 3 },
- { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 3, 4 },
- { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 3, 5 },
- { 0 }
-};
-#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
-
-static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
-
-void __init mach_init_irqs (void)
-{
- v850e_intc_init_irq_types (irq_inits, hw_itypes);
-}
-
-void machine_restart (char *__unused)
-{
-#ifdef CONFIG_RESET_GUARD
- disable_reset_guard ();
-#endif
- asm ("jmp r0"); /* Jump to the reset vector. */
-}
-
-void machine_halt (void)
-{
-#ifdef CONFIG_RESET_GUARD
- disable_reset_guard ();
-#endif
- local_irq_disable (); /* Ignore all interrupts. */
- ANNA_PORT_IO(LEDS_PORT) = 0xAA; /* Note that we halted. */
- for (;;)
- asm ("halt; nop; nop; nop; nop; nop");
-}
-
-void machine_power_off (void)
-{
- machine_halt ();
-}
-
-/* Called before configuring an on-chip UART. */
-void anna_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
-{
- /* The Anna connects some general-purpose I/O pins on the CPU to
- the RTS/CTS lines of UART 1's serial connection. I/O pins P07
- and P37 are RTS and CTS respectively. */
- if (chan == 1) {
- ANNA_PORT_PM(0) &= ~0x80; /* P07 in output mode */
- ANNA_PORT_PM(3) |= 0x80; /* P37 in input mode */
- }
-}
-
-/* Minimum and maximum bounds for the moving upper LED boundary in the
- clock tick display. We can't use the last bit because it's used for
- UART0's CTS output. */
-#define MIN_MAX_POS 0
-#define MAX_MAX_POS 6
-
-/* There are MAX_MAX_POS^2 - MIN_MAX_POS^2 cycles in the animation, so if
- we pick 6 and 0 as above, we get 49 cycles, which is when divided into
- the standard 100 value for HZ, gives us an almost 1s total time. */
-#define TICKS_PER_FRAME \
- (HZ / (MAX_MAX_POS * MAX_MAX_POS - MIN_MAX_POS * MIN_MAX_POS))
-
-static void anna_led_tick ()
-{
- static unsigned counter = 0;
-
- if (++counter == TICKS_PER_FRAME) {
- static int pos = 0, max_pos = MAX_MAX_POS, dir = 1;
-
- if (dir > 0 && pos == max_pos) {
- dir = -1;
- if (max_pos == MIN_MAX_POS)
- max_pos = MAX_MAX_POS;
- else
- max_pos--;
- } else {
- if (dir < 0 && pos == 0)
- dir = 1;
-
- if (pos + dir <= max_pos) {
- /* Each bit of port 0 has a LED. */
- clear_bit (pos, &ANNA_PORT_IO(LEDS_PORT));
- pos += dir;
- set_bit (pos, &ANNA_PORT_IO(LEDS_PORT));
- }
- }
-
- counter = 0;
- }
-}
diff --git a/arch/v850/kernel/anna.ld b/arch/v850/kernel/anna.ld
deleted file mode 100644
index df7f80f2833..00000000000
--- a/arch/v850/kernel/anna.ld
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Linker script for the Midas labs Anna V850E2 evaluation board
- (CONFIG_V850E2_ANNA). */
-
-MEMORY {
- /* 256KB of internal memory (followed by one mirror). */
- iMEM0 : ORIGIN = 0, LENGTH = 0x00040000
- /* 256KB of internal memory (followed by one mirror). */
- iMEM1 : ORIGIN = 0x00040000, LENGTH = 0x00040000
-
- /* 1MB of static RAM. This memory is mirrored 64 times. */
- SRAM : ORIGIN = SRAM_ADDR, LENGTH = SRAM_SIZE
- /* 64MB of DRAM. */
- SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-SECTIONS {
- .intv : { INTV_CONTENTS } > iMEM0
- .sram : { RAMK_KRAM_CONTENTS } > SRAM
- .root : { ROOT_FS_CONTENTS } > SDRAM
-}
diff --git a/arch/v850/kernel/as85ep1-rom.ld b/arch/v850/kernel/as85ep1-rom.ld
deleted file mode 100644
index fe2a9a3ab52..00000000000
--- a/arch/v850/kernel/as85ep1-rom.ld
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Linker script for the NEC AS85EP1 V850E evaluation board
- (CONFIG_V850E_AS85EP1), with kernel in ROM (CONFIG_ROM_KERNEL). */
-
-MEMORY {
- /* 4MB of flash ROM. */
- ROM : ORIGIN = 0, LENGTH = 0x00400000
-
- /* 1MB of static RAM. */
- SRAM : ORIGIN = SRAM_ADDR, LENGTH = SRAM_SIZE
-
- /* About 58MB of DRAM. This can actually be at one of two
- positions, determined by jumper JP3; we have to use the first
- position because the second is partially out of processor
- instruction addressing range (though in the second position
- there's actually 64MB available). */
- SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-SECTIONS {
- ROMK_SECTIONS(ROM, SRAM)
-}
diff --git a/arch/v850/kernel/as85ep1.c b/arch/v850/kernel/as85ep1.c
deleted file mode 100644
index b525ecf3aea..00000000000
--- a/arch/v850/kernel/as85ep1.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * arch/v850/kernel/as85ep1.c -- AS85EP1 V850E evaluation chip/board
- *
- * Copyright (C) 2002,03 NEC Electronics Corporation
- * Copyright (C) 2002,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/major.h>
-#include <linux/irq.h>
-
-#include <asm/machdep.h>
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/v850e_timer_d.h>
-#include <asm/v850e_uart.h>
-
-#include "mach.h"
-
-
-/* SRAM and SDRAM are vaguely contiguous (with a big hole in between; see
- mach_reserve_bootmem for details); use both as one big area. */
-#define RAM_START SRAM_ADDR
-#define RAM_END (SDRAM_ADDR + SDRAM_SIZE)
-
-/* The bits of this port are connected to an 8-LED bar-graph. */
-#define LEDS_PORT 4
-
-
-static void as85ep1_led_tick (void);
-
-extern char _intv_copy_src_start, _intv_copy_src_end;
-extern char _intv_copy_dst_start;
-
-
-void __init mach_early_init (void)
-{
-#ifndef CONFIG_ROM_KERNEL
- const u32 *src;
- register u32 *dst asm ("ep");
-#endif
-
- AS85EP1_CSC(0) = 0x0403;
- AS85EP1_BCT(0) = 0xB8B8;
- AS85EP1_DWC(0) = 0x0104;
- AS85EP1_BCC = 0x0012;
- AS85EP1_ASC = 0;
- AS85EP1_LBS = 0x00A9;
-
- AS85EP1_PORT_PMC(6) = 0xFF; /* valid A0,A1,A20-A25 */
- AS85EP1_PORT_PMC(7) = 0x0E; /* valid CS1-CS3 */
- AS85EP1_PORT_PMC(9) = 0xFF; /* valid D16-D23 */
- AS85EP1_PORT_PMC(10) = 0xFF; /* valid D24-D31 */
-
- AS85EP1_RFS(1) = 0x800c;
- AS85EP1_RFS(3) = 0x800c;
- AS85EP1_SCR(1) = 0x20A9;
- AS85EP1_SCR(3) = 0x20A9;
-
-#ifndef CONFIG_ROM_KERNEL
- /* The early chip we have is buggy, and writing the interrupt
- vectors into low RAM may screw up, so for non-ROM kernels, we
- only rely on the reset vector being downloaded, and copy the
- rest of the interrupt vectors into place here. The specific bug
- is that writing address N, where (N & 0x10) == 0x10, will _also_
- write to address (N - 0x10). We avoid this (effectively) by
- writing in 16-byte chunks backwards from the end. */
-
- AS85EP1_IRAMM = 0x3; /* "write-mode" for the internal instruction memory */
-
- src = (u32 *)(((u32)&_intv_copy_src_end - 1) & ~0xF);
- dst = (u32 *)&_intv_copy_dst_start
- + (src - (u32 *)&_intv_copy_src_start);
- do {
- u32 t0 = src[0], t1 = src[1], t2 = src[2], t3 = src[3];
- dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3;
- dst -= 4;
- src -= 4;
- } while (src > (u32 *)&_intv_copy_src_start);
-
- AS85EP1_IRAMM = 0x0; /* "read-mode" for the internal instruction memory */
-#endif /* !CONFIG_ROM_KERNEL */
-
- v850e_intc_disable_irqs ();
-}
-
-void __init mach_setup (char **cmdline)
-{
- AS85EP1_PORT_PMC (LEDS_PORT) = 0; /* Make the LEDs port an I/O port. */
- AS85EP1_PORT_PM (LEDS_PORT) = 0; /* Make all the bits output pins. */
- mach_tick = as85ep1_led_tick;
-}
-
-void __init mach_get_physical_ram (unsigned long *ram_start,
- unsigned long *ram_len)
-{
- *ram_start = RAM_START;
- *ram_len = RAM_END - RAM_START;
-}
-
-/* Convenience macros. */
-#define SRAM_END (SRAM_ADDR + SRAM_SIZE)
-#define SDRAM_END (SDRAM_ADDR + SDRAM_SIZE)
-
-void __init mach_reserve_bootmem ()
-{
- if (SDRAM_ADDR < RAM_END && SDRAM_ADDR > RAM_START)
- /* We can't use the space between SRAM and SDRAM, so
- prevent the kernel from trying. */
- reserve_bootmem(SRAM_END, SDRAM_ADDR - SRAM_END,
- BOOTMEM_DEFAULT);
-}
-
-void mach_gettimeofday (struct timespec *tv)
-{
- tv->tv_sec = 0;
- tv->tv_nsec = 0;
-}
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
- /* Start hardware timer. */
- v850e_timer_d_configure (0, HZ);
- /* Install timer interrupt handler. */
- setup_irq (IRQ_INTCMD(0), timer_action);
-}
-
-static struct v850e_intc_irq_init irq_inits[] = {
- { "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
- { "CCC", IRQ_INTCCC(0), IRQ_INTCCC_NUM, 1, 5 },
- { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 },
- { "SRE", IRQ_INTSRE(0), IRQ_INTSRE_NUM, 3, 3 },
- { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 3, 4 },
- { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 3, 5 },
- { 0 }
-};
-#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
-
-static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
-
-void __init mach_init_irqs (void)
-{
- v850e_intc_init_irq_types (irq_inits, hw_itypes);
-}
-
-void machine_restart (char *__unused)
-{
-#ifdef CONFIG_RESET_GUARD
- disable_reset_guard ();
-#endif
- asm ("jmp r0"); /* Jump to the reset vector. */
-}
-
-void machine_halt (void)
-{
-#ifdef CONFIG_RESET_GUARD
- disable_reset_guard ();
-#endif
- local_irq_disable (); /* Ignore all interrupts. */
- AS85EP1_PORT_IO (LEDS_PORT) = 0xAA; /* Note that we halted. */
- for (;;)
- asm ("halt; nop; nop; nop; nop; nop");
-}
-
-void machine_power_off (void)
-{
- machine_halt ();
-}
-
-/* Called before configuring an on-chip UART. */
-void as85ep1_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
-{
- /* Make the shared uart/port pins be uart pins. */
- AS85EP1_PORT_PMC(3) |= (0x5 << chan);
-
- /* The AS85EP1 connects some general-purpose I/O pins on the CPU to
- the RTS/CTS lines of UART 1's serial connection. I/O pins P53
- and P54 are RTS and CTS respectively. */
- if (chan == 1) {
- /* Put P53 & P54 in I/O port mode. */
- AS85EP1_PORT_PMC(5) &= ~0x18;
- /* Make P53 an output, and P54 an input. */
- AS85EP1_PORT_PM(5) |= 0x10;
- }
-}
-
-/* Minimum and maximum bounds for the moving upper LED boundary in the
- clock tick display. */
-#define MIN_MAX_POS 0
-#define MAX_MAX_POS 7
-
-/* There are MAX_MAX_POS^2 - MIN_MAX_POS^2 cycles in the animation, so if
- we pick 6 and 0 as above, we get 49 cycles, which is when divided into
- the standard 100 value for HZ, gives us an almost 1s total time. */
-#define TICKS_PER_FRAME \
- (HZ / (MAX_MAX_POS * MAX_MAX_POS - MIN_MAX_POS * MIN_MAX_POS))
-
-static void as85ep1_led_tick ()
-{
- static unsigned counter = 0;
-
- if (++counter == TICKS_PER_FRAME) {
- static int pos = 0, max_pos = MAX_MAX_POS, dir = 1;
-
- if (dir > 0 && pos == max_pos) {
- dir = -1;
- if (max_pos == MIN_MAX_POS)
- max_pos = MAX_MAX_POS;
- else
- max_pos--;
- } else {
- if (dir < 0 && pos == 0)
- dir = 1;
-
- if (pos + dir <= max_pos) {
- /* Each bit of port 0 has a LED. */
- set_bit (pos, &AS85EP1_PORT_IO(LEDS_PORT));
- pos += dir;
- clear_bit (pos, &AS85EP1_PORT_IO(LEDS_PORT));
- }
- }
-
- counter = 0;
- }
-}
diff --git a/arch/v850/kernel/as85ep1.ld b/arch/v850/kernel/as85ep1.ld
deleted file mode 100644
index ef2c4399063..00000000000
--- a/arch/v850/kernel/as85ep1.ld
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Linker script for the NEC AS85EP1 V850E evaluation board
- (CONFIG_V850E_AS85EP1). */
-
-MEMORY {
- /* 1MB of internal instruction memory. */
- iMEM0 : ORIGIN = 0, LENGTH = 0x00100000
-
- /* 1MB of static RAM. */
- SRAM : ORIGIN = SRAM_ADDR, LENGTH = SRAM_SIZE
-
- /* About 58MB of DRAM. This can actually be at one of two
- positions, determined by jump JP3; we have to use the first
- position because the second is partially out of processor
- instruction addressing range (though in the second position
- there's actually 64MB available). */
- SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-SECTIONS {
- .resetv : {
- __intv_start = . ;
- *(.intv.reset) /* Reset vector */
- } > iMEM0
-
- .sram : {
- RAMK_KRAM_CONTENTS
-
- /* We stick most of the interrupt vectors here; they'll be
- copied into the proper location by the early init code (we
- can't put them directly in the right place because of
- hardware bugs). The vectors shouldn't need to be
- relocated, so we don't have to use `> ... AT> ...' to
- split the load/vm addresses (and we can't because of
- problems with the loader). */
- . = ALIGN (0x10) ;
- __intv_copy_src_start = . ;
- *(.intv.common) /* Vectors common to all v850e proc. */
- *(.intv.mach) /* Machine-specific int. vectors. */
- . = ALIGN (0x10) ;
- __intv_copy_src_end = . ;
- } > SRAM
-
- /* Where we end up putting the vectors. */
- __intv_copy_dst_start = 0x10 ;
- __intv_copy_dst_end = __intv_copy_dst_start + (__intv_copy_src_end - __intv_copy_src_start) ;
- __intv_end = __intv_copy_dst_end ;
-
- .root : { ROOT_FS_CONTENTS } > SDRAM
-}
diff --git a/arch/v850/kernel/asm-offsets.c b/arch/v850/kernel/asm-offsets.c
deleted file mode 100644
index 581e6986a77..00000000000
--- a/arch/v850/kernel/asm-offsets.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This program is used to generate definitions needed by
- * assembly language modules.
- *
- * We use the technique used in the OSF Mach kernel code:
- * generate asm statements containing #defines,
- * compile this file to assembler, and then extract the
- * #defines from the assembly-language output.
- */
-
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <linux/ptrace.h>
-#include <linux/hardirq.h>
-#include <linux/kbuild.h>
-
-#include <asm/irq.h>
-#include <asm/errno.h>
-
-int main (void)
-{
- /* offsets into the task struct */
- DEFINE (TASK_STATE, offsetof (struct task_struct, state));
- DEFINE (TASK_FLAGS, offsetof (struct task_struct, flags));
- DEFINE (TASK_PTRACE, offsetof (struct task_struct, ptrace));
- DEFINE (TASK_BLOCKED, offsetof (struct task_struct, blocked));
- DEFINE (TASK_THREAD, offsetof (struct task_struct, thread));
- DEFINE (TASK_THREAD_INFO, offsetof (struct task_struct, stack));
- DEFINE (TASK_MM, offsetof (struct task_struct, mm));
- DEFINE (TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm));
- DEFINE (TASK_PID, offsetof (struct task_struct, pid));
-
- /* offsets into the kernel_stat struct */
- DEFINE (STAT_IRQ, offsetof (struct kernel_stat, irqs));
-
-
- /* signal defines */
- DEFINE (SIGSEGV, SIGSEGV);
- DEFINE (SEGV_MAPERR, SEGV_MAPERR);
- DEFINE (SIGTRAP, SIGTRAP);
- DEFINE (SIGCHLD, SIGCHLD);
- DEFINE (SIGILL, SIGILL);
- DEFINE (TRAP_TRACE, TRAP_TRACE);
-
- /* ptrace flag bits */
- DEFINE (PT_PTRACED, PT_PTRACED);
- DEFINE (PT_DTRACE, PT_DTRACE);
-
- /* error values */
- DEFINE (ENOSYS, ENOSYS);
-
- /* clone flag bits */
- DEFINE (CLONE_VFORK, CLONE_VFORK);
- DEFINE (CLONE_VM, CLONE_VM);
-
- return 0;
-}
diff --git a/arch/v850/kernel/bug.c b/arch/v850/kernel/bug.c
deleted file mode 100644
index c78cf750915..00000000000
--- a/arch/v850/kernel/bug.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * arch/v850/kernel/bug.c -- Bug reporting functions
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/reboot.h>
-#include <linux/sched.h>
-#include <linux/module.h>
-
-#include <asm/errno.h>
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/current.h>
-
-/* We should use __builtin_return_address, but it doesn't work in gcc-2.90
- (which is currently our standard compiler on the v850). */
-#define ret_addr() ({ register u32 lp asm ("lp"); lp; })
-#define stack_addr() ({ register u32 sp asm ("sp"); sp; })
-
-void __bug ()
-{
- printk (KERN_CRIT "kernel BUG at PC 0x%x (SP ~0x%x)!\n",
- ret_addr() - 4, /* - 4 for `jarl' */
- stack_addr());
- machine_halt ();
-}
-
-int bad_trap (int trap_num, struct pt_regs *regs)
-{
- printk (KERN_CRIT
- "unimplemented trap %d called at 0x%08lx, pid %d!\n",
- trap_num, regs->pc, current->pid);
- return -ENOSYS;
-}
-
-#ifdef CONFIG_RESET_GUARD
-void unexpected_reset (unsigned long ret_addr, unsigned long kmode,
- struct task_struct *task, unsigned long sp)
-{
- printk (KERN_CRIT
- "unexpected reset in %s mode, pid %d"
- " (ret_addr = 0x%lx, sp = 0x%lx)\n",
- kmode ? "kernel" : "user",
- task ? task->pid : -1,
- ret_addr, sp);
-
- machine_halt ();
-}
-#endif /* CONFIG_RESET_GUARD */
-
-
-
-struct spec_reg_name {
- const char *name;
- int gpr;
-};
-
-struct spec_reg_name spec_reg_names[] = {
- { "sp", GPR_SP },
- { "gp", GPR_GP },
- { "tp", GPR_TP },
- { "ep", GPR_EP },
- { "lp", GPR_LP },
- { 0, 0 }
-};
-
-void show_regs (struct pt_regs *regs)
-{
- int gpr_base, gpr_offs;
-
- printk (" pc 0x%08lx psw 0x%08lx kernel_mode %d\n",
- regs->pc, regs->psw, regs->kernel_mode);
- printk (" ctpc 0x%08lx ctpsw 0x%08lx ctbp 0x%08lx\n",
- regs->ctpc, regs->ctpsw, regs->ctbp);
-
- for (gpr_base = 0; gpr_base < NUM_GPRS; gpr_base += 4) {
- for (gpr_offs = 0; gpr_offs < 4; gpr_offs++) {
- int gpr = gpr_base + gpr_offs;
- long val = regs->gpr[gpr];
- struct spec_reg_name *srn;
-
- for (srn = spec_reg_names; srn->name; srn++)
- if (srn->gpr == gpr)
- break;
-
- if (srn->name)
- printk ("%7s 0x%08lx", srn->name, val);
- else
- printk (" r%02d 0x%08lx", gpr, val);
- }
-
- printk ("\n");
- }
-}
-
-/*
- * TASK is a pointer to the task whose backtrace we want to see (or NULL
- * for current task), SP is the stack pointer of the first frame that
- * should be shown in the back trace (or NULL if the entire call-chain of
- * the task should be shown).
- */
-void show_stack (struct task_struct *task, unsigned long *sp)
-{
- unsigned long addr, end;
-
- if (sp)
- addr = (unsigned long)sp;
- else if (task)
- addr = task_sp (task);
- else
- addr = stack_addr ();
-
- addr = addr & ~3;
- end = (addr + THREAD_SIZE - 1) & THREAD_MASK;
-
- while (addr < end) {
- printk ("%8lX: ", addr);
- while (addr < end) {
- printk (" %8lX", *(unsigned long *)addr);
- addr += sizeof (unsigned long);
- if (! (addr & 0xF))
- break;
- }
- printk ("\n");
- }
-}
-
-void dump_stack ()
-{
- show_stack (0, 0);
-}
-
-EXPORT_SYMBOL(dump_stack);
diff --git a/arch/v850/kernel/entry.S b/arch/v850/kernel/entry.S
deleted file mode 100644
index e4327a8d6bc..00000000000
--- a/arch/v850/kernel/entry.S
+++ /dev/null
@@ -1,1121 +0,0 @@
-/*
- * arch/v850/kernel/entry.S -- Low-level system-call handling, trap handlers,
- * and context-switching
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/sys.h>
-
-#include <asm/entry.h>
-#include <asm/current.h>
-#include <asm/thread_info.h>
-#include <asm/clinkage.h>
-#include <asm/processor.h>
-#include <asm/irq.h>
-#include <asm/errno.h>
-
-#include <asm/asm-offsets.h>
-
-
-/* Make a slightly more convenient alias for C_SYMBOL_NAME. */
-#define CSYM C_SYMBOL_NAME
-
-
-/* The offset of the struct pt_regs in a state-save-frame on the stack. */
-#define PTO STATE_SAVE_PT_OFFSET
-
-
-/* Save argument registers to the state-save-frame pointed to by EP. */
-#define SAVE_ARG_REGS \
- sst.w r6, PTO+PT_GPR(6)[ep]; \
- sst.w r7, PTO+PT_GPR(7)[ep]; \
- sst.w r8, PTO+PT_GPR(8)[ep]; \
- sst.w r9, PTO+PT_GPR(9)[ep]
-/* Restore argument registers from the state-save-frame pointed to by EP. */
-#define RESTORE_ARG_REGS \
- sld.w PTO+PT_GPR(6)[ep], r6; \
- sld.w PTO+PT_GPR(7)[ep], r7; \
- sld.w PTO+PT_GPR(8)[ep], r8; \
- sld.w PTO+PT_GPR(9)[ep], r9
-
-/* Save value return registers to the state-save-frame pointed to by EP. */
-#define SAVE_RVAL_REGS \
- sst.w r10, PTO+PT_GPR(10)[ep]; \
- sst.w r11, PTO+PT_GPR(11)[ep]
-/* Restore value return registers from the state-save-frame pointed to by EP. */
-#define RESTORE_RVAL_REGS \
- sld.w PTO+PT_GPR(10)[ep], r10; \
- sld.w PTO+PT_GPR(11)[ep], r11
-
-
-#define SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS \
- sst.w r1, PTO+PT_GPR(1)[ep]; \
- sst.w r5, PTO+PT_GPR(5)[ep]
-#define SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL \
- sst.w r12, PTO+PT_GPR(12)[ep]; \
- sst.w r13, PTO+PT_GPR(13)[ep]; \
- sst.w r14, PTO+PT_GPR(14)[ep]; \
- sst.w r15, PTO+PT_GPR(15)[ep]; \
- sst.w r16, PTO+PT_GPR(16)[ep]; \
- sst.w r17, PTO+PT_GPR(17)[ep]; \
- sst.w r18, PTO+PT_GPR(18)[ep]; \
- sst.w r19, PTO+PT_GPR(19)[ep]
-#define RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS \
- sld.w PTO+PT_GPR(1)[ep], r1; \
- sld.w PTO+PT_GPR(5)[ep], r5
-#define RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL \
- sld.w PTO+PT_GPR(12)[ep], r12; \
- sld.w PTO+PT_GPR(13)[ep], r13; \
- sld.w PTO+PT_GPR(14)[ep], r14; \
- sld.w PTO+PT_GPR(15)[ep], r15; \
- sld.w PTO+PT_GPR(16)[ep], r16; \
- sld.w PTO+PT_GPR(17)[ep], r17; \
- sld.w PTO+PT_GPR(18)[ep], r18; \
- sld.w PTO+PT_GPR(19)[ep], r19
-
-/* Save `call clobbered' registers to the state-save-frame pointed to by EP. */
-#define SAVE_CALL_CLOBBERED_REGS \
- SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \
- SAVE_ARG_REGS; \
- SAVE_RVAL_REGS; \
- SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL
-/* Restore `call clobbered' registers from the state-save-frame pointed to
- by EP. */
-#define RESTORE_CALL_CLOBBERED_REGS \
- RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \
- RESTORE_ARG_REGS; \
- RESTORE_RVAL_REGS; \
- RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL
-
-/* Save `call clobbered' registers except for the return-value registers
- to the state-save-frame pointed to by EP. */
-#define SAVE_CALL_CLOBBERED_REGS_NO_RVAL \
- SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \
- SAVE_ARG_REGS; \
- SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL
-/* Restore `call clobbered' registers except for the return-value registers
- from the state-save-frame pointed to by EP. */
-#define RESTORE_CALL_CLOBBERED_REGS_NO_RVAL \
- RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \
- RESTORE_ARG_REGS; \
- RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL
-
-/* Save `call saved' registers to the state-save-frame pointed to by EP. */
-#define SAVE_CALL_SAVED_REGS \
- sst.w r2, PTO+PT_GPR(2)[ep]; \
- sst.w r20, PTO+PT_GPR(20)[ep]; \
- sst.w r21, PTO+PT_GPR(21)[ep]; \
- sst.w r22, PTO+PT_GPR(22)[ep]; \
- sst.w r23, PTO+PT_GPR(23)[ep]; \
- sst.w r24, PTO+PT_GPR(24)[ep]; \
- sst.w r25, PTO+PT_GPR(25)[ep]; \
- sst.w r26, PTO+PT_GPR(26)[ep]; \
- sst.w r27, PTO+PT_GPR(27)[ep]; \
- sst.w r28, PTO+PT_GPR(28)[ep]; \
- sst.w r29, PTO+PT_GPR(29)[ep]
-/* Restore `call saved' registers from the state-save-frame pointed to by EP. */
-#define RESTORE_CALL_SAVED_REGS \
- sld.w PTO+PT_GPR(2)[ep], r2; \
- sld.w PTO+PT_GPR(20)[ep], r20; \
- sld.w PTO+PT_GPR(21)[ep], r21; \
- sld.w PTO+PT_GPR(22)[ep], r22; \
- sld.w PTO+PT_GPR(23)[ep], r23; \
- sld.w PTO+PT_GPR(24)[ep], r24; \
- sld.w PTO+PT_GPR(25)[ep], r25; \
- sld.w PTO+PT_GPR(26)[ep], r26; \
- sld.w PTO+PT_GPR(27)[ep], r27; \
- sld.w PTO+PT_GPR(28)[ep], r28; \
- sld.w PTO+PT_GPR(29)[ep], r29
-
-
-/* Save the PC stored in the special register SAVEREG to the state-save-frame
- pointed to by EP. r19 is clobbered. */
-#define SAVE_PC(savereg) \
- stsr SR_ ## savereg, r19; \
- sst.w r19, PTO+PT_PC[ep]
-/* Restore the PC from the state-save-frame pointed to by EP, to the special
- register SAVEREG. LP is clobbered (it is used as a scratch register
- because the POP_STATE macro restores it, and this macro is usually used
- inside POP_STATE). */
-#define RESTORE_PC(savereg) \
- sld.w PTO+PT_PC[ep], lp; \
- ldsr lp, SR_ ## savereg
-/* Save the PSW register stored in the special register SAVREG to the
- state-save-frame pointed to by EP. r19 is clobbered. */
-#define SAVE_PSW(savereg) \
- stsr SR_ ## savereg, r19; \
- sst.w r19, PTO+PT_PSW[ep]
-/* Restore the PSW register from the state-save-frame pointed to by EP, to
- the special register SAVEREG. LP is clobbered (it is used as a scratch
- register because the POP_STATE macro restores it, and this macro is
- usually used inside POP_STATE). */
-#define RESTORE_PSW(savereg) \
- sld.w PTO+PT_PSW[ep], lp; \
- ldsr lp, SR_ ## savereg
-
-/* Save CTPC/CTPSW/CTBP registers to the state-save-frame pointed to by REG.
- r19 is clobbered. */
-#define SAVE_CT_REGS \
- stsr SR_CTPC, r19; \
- sst.w r19, PTO+PT_CTPC[ep]; \
- stsr SR_CTPSW, r19; \
- sst.w r19, PTO+PT_CTPSW[ep]; \
- stsr SR_CTBP, r19; \
- sst.w r19, PTO+PT_CTBP[ep]
-/* Restore CTPC/CTPSW/CTBP registers from the state-save-frame pointed to by EP.
- LP is clobbered (it is used as a scratch register because the POP_STATE
- macro restores it, and this macro is usually used inside POP_STATE). */
-#define RESTORE_CT_REGS \
- sld.w PTO+PT_CTPC[ep], lp; \
- ldsr lp, SR_CTPC; \
- sld.w PTO+PT_CTPSW[ep], lp; \
- ldsr lp, SR_CTPSW; \
- sld.w PTO+PT_CTBP[ep], lp; \
- ldsr lp, SR_CTBP
-
-
-/* Push register state, except for the stack pointer, on the stack in the
- form of a state-save-frame (plus some extra padding), in preparation for
- a system call. This macro makes sure that the EP, GP, and LP
- registers are saved, and TYPE identifies the set of extra registers to
- be saved as well. Also copies (the new value of) SP to EP. */
-#define PUSH_STATE(type) \
- addi -STATE_SAVE_SIZE, sp, sp; /* Make room on the stack. */ \
- st.w ep, PTO+PT_GPR(GPR_EP)[sp]; \
- mov sp, ep; \
- sst.w gp, PTO+PT_GPR(GPR_GP)[ep]; \
- sst.w lp, PTO+PT_GPR(GPR_LP)[ep]; \
- type ## _STATE_SAVER
-/* Pop a register state pushed by PUSH_STATE, except for the stack pointer,
- from the stack. */
-#define POP_STATE(type) \
- mov sp, ep; \
- type ## _STATE_RESTORER; \
- sld.w PTO+PT_GPR(GPR_GP)[ep], gp; \
- sld.w PTO+PT_GPR(GPR_LP)[ep], lp; \
- sld.w PTO+PT_GPR(GPR_EP)[ep], ep; \
- addi STATE_SAVE_SIZE, sp, sp /* Clean up our stack space. */
-
-
-/* Switch to the kernel stack if necessary, and push register state on the
- stack in the form of a state-save-frame. Also load the current task
- pointer if switching from user mode. The stack-pointer (r3) should have
- already been saved to the memory location SP_SAVE_LOC (the reason for
- this is that the interrupt vectors may be beyond a 22-bit signed offset
- jump from the actual interrupt handler, and this allows them to save the
- stack-pointer and use that register to do an indirect jump). This macro
- makes sure that `special' registers, system registers, and the stack
- pointer are saved; TYPE identifies the set of extra registers to be
- saved as well. SYSCALL_NUM is the register in which the system-call
- number this state is for is stored (r0 if this isn't a system call).
- Interrupts should already be disabled when calling this. */
-#define SAVE_STATE(type, syscall_num, sp_save_loc) \
- tst1 0, KM; /* See if already in kernel mode. */ \
- bz 1f; \
- ld.w sp_save_loc, sp; /* ... yes, use saved SP. */ \
- br 2f; \
-1: ld.w KSP, sp; /* ... no, switch to kernel stack. */ \
-2: PUSH_STATE(type); \
- ld.b KM, r19; /* Remember old kernel-mode. */ \
- sst.w r19, PTO+PT_KERNEL_MODE[ep]; \
- ld.w sp_save_loc, r19; /* Remember old SP. */ \
- sst.w r19, PTO+PT_GPR(GPR_SP)[ep]; \
- mov 1, r19; /* Now definitely in kernel-mode. */ \
- st.b r19, KM; \
- GET_CURRENT_TASK(CURRENT_TASK); /* Fetch the current task pointer. */ \
- /* Save away the syscall number. */ \
- sst.w syscall_num, PTO+PT_CUR_SYSCALL[ep]
-
-
-/* Save register state not normally saved by PUSH_STATE for TYPE, to the
- state-save-frame on the stack; also copies SP to EP. r19 may be trashed. */
-#define SAVE_EXTRA_STATE(type) \
- mov sp, ep; \
- type ## _EXTRA_STATE_SAVER
-/* Restore register state not normally restored by POP_STATE for TYPE,
- from the state-save-frame on the stack; also copies SP to EP.
- r19 may be trashed. */
-#define RESTORE_EXTRA_STATE(type) \
- mov sp, ep; \
- type ## _EXTRA_STATE_RESTORER
-
-/* Save any call-clobbered registers not normally saved by PUSH_STATE for
- TYPE, to the state-save-frame on the stack.
- EP may be trashed, but is not guaranteed to contain a copy of SP
- (unlike after most SAVE_... macros). r19 may be trashed. */
-#define SAVE_EXTRA_STATE_FOR_SCHEDULE(type) \
- type ## _SCHEDULE_EXTRA_STATE_SAVER
-/* Restore any call-clobbered registers not normally restored by
- POP_STATE for TYPE, to the state-save-frame on the stack.
- EP may be trashed, but is not guaranteed to contain a copy of SP
- (unlike after most RESTORE_... macros). r19 may be trashed. */
-#define RESTORE_EXTRA_STATE_FOR_SCHEDULE(type) \
- type ## _SCHEDULE_EXTRA_STATE_RESTORER
-
-
-/* These are extra_state_saver/restorer values for a user trap. Note
- that we save the argument registers so that restarted syscalls will
- function properly (otherwise it wouldn't be necessary), and we must
- _not_ restore the return-value registers (so that traps can return a
- value!), but call-clobbered registers are not saved at all, as the
- caller of the syscall function should have saved them. */
-
-#define TRAP_RET reti
-/* Traps don't save call-clobbered registers (but do still save arg regs).
- We preserve PSw to keep long-term state, namely interrupt status (for traps
- from kernel-mode), and the single-step flag (for user traps). */
-#define TRAP_STATE_SAVER \
- SAVE_ARG_REGS; \
- SAVE_PC(EIPC); \
- SAVE_PSW(EIPSW)
-/* When traps return, they just leave call-clobbered registers (except for arg
- regs) with whatever value they have from the kernel. Traps don't preserve
- the PSW, but we zero EIPSW to ensure it doesn't contain anything dangerous
- (in particular, the single-step flag). */
-#define TRAP_STATE_RESTORER \
- RESTORE_ARG_REGS; \
- RESTORE_PC(EIPC); \
- RESTORE_PSW(EIPSW)
-/* Save registers not normally saved by traps. We need to save r12, even
- though it's nominally call-clobbered, because it's used when restarting
- a system call (the signal-handling path uses SAVE_EXTRA_STATE, and
- expects r12 to be restored when the trap returns). */
-#define TRAP_EXTRA_STATE_SAVER \
- SAVE_RVAL_REGS; \
- sst.w r12, PTO+PT_GPR(12)[ep]; \
- SAVE_CALL_SAVED_REGS; \
- SAVE_CT_REGS
-#define TRAP_EXTRA_STATE_RESTORER \
- RESTORE_RVAL_REGS; \
- sld.w PTO+PT_GPR(12)[ep], r12; \
- RESTORE_CALL_SAVED_REGS; \
- RESTORE_CT_REGS
-/* Save registers prior to calling scheduler (just before trap returns).
- We have to save the return-value registers to preserve the trap's return
- value. Note that ..._SCHEDULE_EXTRA_STATE_SAVER, unlike most ..._SAVER
- macros, is required to setup EP itself if EP is needed (this is because
- in many cases, the macro is empty). */
-#define TRAP_SCHEDULE_EXTRA_STATE_SAVER \
- mov sp, ep; \
- SAVE_RVAL_REGS
-/* Note that ..._SCHEDULE_EXTRA_STATE_RESTORER, unlike most ..._RESTORER
- macros, is required to setup EP itself if EP is needed (this is because
- in many cases, the macro is empty). */
-#define TRAP_SCHEDULE_EXTRA_STATE_RESTORER \
- mov sp, ep; \
- RESTORE_RVAL_REGS
-
-/* Register saving/restoring for maskable interrupts. */
-#define IRQ_RET reti
-#define IRQ_STATE_SAVER \
- SAVE_CALL_CLOBBERED_REGS; \
- SAVE_PC(EIPC); \
- SAVE_PSW(EIPSW)
-#define IRQ_STATE_RESTORER \
- RESTORE_CALL_CLOBBERED_REGS; \
- RESTORE_PC(EIPC); \
- RESTORE_PSW(EIPSW)
-#define IRQ_EXTRA_STATE_SAVER \
- SAVE_CALL_SAVED_REGS; \
- SAVE_CT_REGS
-#define IRQ_EXTRA_STATE_RESTORER \
- RESTORE_CALL_SAVED_REGS; \
- RESTORE_CT_REGS
-#define IRQ_SCHEDULE_EXTRA_STATE_SAVER /* nothing */
-#define IRQ_SCHEDULE_EXTRA_STATE_RESTORER /* nothing */
-
-/* Register saving/restoring for non-maskable interrupts. */
-#define NMI_RET reti
-#define NMI_STATE_SAVER \
- SAVE_CALL_CLOBBERED_REGS; \
- SAVE_PC(FEPC); \
- SAVE_PSW(FEPSW);
-#define NMI_STATE_RESTORER \
- RESTORE_CALL_CLOBBERED_REGS; \
- RESTORE_PC(FEPC); \
- RESTORE_PSW(FEPSW);
-#define NMI_EXTRA_STATE_SAVER \
- SAVE_CALL_SAVED_REGS; \
- SAVE_CT_REGS
-#define NMI_EXTRA_STATE_RESTORER \
- RESTORE_CALL_SAVED_REGS; \
- RESTORE_CT_REGS
-#define NMI_SCHEDULE_EXTRA_STATE_SAVER /* nothing */
-#define NMI_SCHEDULE_EXTRA_STATE_RESTORER /* nothing */
-
-/* Register saving/restoring for debug traps. */
-#define DBTRAP_RET .long 0x014607E0 /* `dbret', but gas doesn't support it. */
-#define DBTRAP_STATE_SAVER \
- SAVE_CALL_CLOBBERED_REGS; \
- SAVE_PC(DBPC); \
- SAVE_PSW(DBPSW)
-#define DBTRAP_STATE_RESTORER \
- RESTORE_CALL_CLOBBERED_REGS; \
- RESTORE_PC(DBPC); \
- RESTORE_PSW(DBPSW)
-#define DBTRAP_EXTRA_STATE_SAVER \
- SAVE_CALL_SAVED_REGS; \
- SAVE_CT_REGS
-#define DBTRAP_EXTRA_STATE_RESTORER \
- RESTORE_CALL_SAVED_REGS; \
- RESTORE_CT_REGS
-#define DBTRAP_SCHEDULE_EXTRA_STATE_SAVER /* nothing */
-#define DBTRAP_SCHEDULE_EXTRA_STATE_RESTORER /* nothing */
-
-/* Register saving/restoring for a context switch. We don't need to save
- too many registers, because context-switching looks like a function call
- (via the function `switch_thread'), so callers will save any
- call-clobbered registers themselves. We do need to save the CT regs, as
- they're normally not saved during kernel entry (the kernel doesn't use
- them). We save PSW so that interrupt-status state will correctly follow
- each thread (mostly NMI vs. normal-IRQ/trap), though for the most part
- it doesn't matter since threads are always in almost exactly the same
- processor state during a context switch. The stack pointer and return
- value are handled by switch_thread itself. */
-#define SWITCH_STATE_SAVER \
- SAVE_CALL_SAVED_REGS; \
- SAVE_PSW(PSW); \
- SAVE_CT_REGS
-#define SWITCH_STATE_RESTORER \
- RESTORE_CALL_SAVED_REGS; \
- RESTORE_PSW(PSW); \
- RESTORE_CT_REGS
-
-
-/* Restore register state from the state-save-frame on the stack, switch back
- to the user stack if necessary, and return from the trap/interrupt.
- EXTRA_STATE_RESTORER is a sequence of assembly language statements to
- restore anything not restored by this macro. Only registers not saved by
- the C compiler are restored (that is, R3(sp), R4(gp), R31(lp), and
- anything restored by EXTRA_STATE_RESTORER). */
-#define RETURN(type) \
- ld.b PTO+PT_KERNEL_MODE[sp], r19; \
- di; /* Disable interrupts */ \
- cmp r19, r0; /* See if returning to kernel mode, */\
- bne 2f; /* ... if so, skip resched &c. */ \
- \
- /* We're returning to user mode, so check for various conditions that \
- trigger rescheduling. */ \
- GET_CURRENT_THREAD(r18); \
- ld.w TI_FLAGS[r18], r19; \
- andi _TIF_NEED_RESCHED, r19, r0; \
- bnz 3f; /* Call the scheduler. */ \
-5: andi _TIF_SIGPENDING, r19, r18; \
- ld.w TASK_PTRACE[CURRENT_TASK], r19; /* ptrace flags */ \
- or r18, r19; /* see if either is non-zero */ \
- bnz 4f; /* if so, handle them */ \
- \
-/* Return to user state. */ \
-1: st.b r0, KM; /* Now officially in user state. */ \
- \
-/* Final return. The stack-pointer fiddling is not needed when returning \
- to kernel-mode, but they don't hurt, and this way we can share the \
- (sometimes rather lengthy) POP_STATE macro. */ \
-2: POP_STATE(type); \
- st.w sp, KSP; /* Save the kernel stack pointer. */ \
- ld.w PT_GPR(GPR_SP)-PT_SIZE[sp], sp; /* Restore stack pointer. */ \
- type ## _RET; /* Return from the trap/interrupt. */ \
- \
-/* Call the scheduler before returning from a syscall/trap. */ \
-3: SAVE_EXTRA_STATE_FOR_SCHEDULE(type); /* Prepare to call scheduler. */ \
- jarl call_scheduler, lp; /* Call scheduler */ \
- di; /* The scheduler enables interrupts */\
- RESTORE_EXTRA_STATE_FOR_SCHEDULE(type); \
- GET_CURRENT_THREAD(r18); \
- ld.w TI_FLAGS[r18], r19; \
- br 5b; /* Continue with return path. */ \
- \
-/* Handle a signal or ptraced process return. \
- r18 should be non-zero if there are pending signals. */ \
-4: /* Not all registers are saved by the normal trap/interrupt entry \
- points (for instance, call-saved registers (because the normal \
- C-compiler calling sequence in the kernel makes sure they're \
- preserved), and call-clobbered registers in the case of \
- traps), but signal handlers may want to examine or change the \
- complete register state. Here we save anything not saved by \
- the normal entry sequence, so that it may be safely restored \
- (in a possibly modified form) after do_signal returns. */ \
- SAVE_EXTRA_STATE(type); /* Save state not saved by entry. */ \
- jarl handle_signal_or_ptrace_return, lp; \
- RESTORE_EXTRA_STATE(type); /* Restore extra regs. */ \
- br 1b
-
-
-/* Jump to the appropriate function for the system call number in r12
- (r12 is not preserved), or return an error if r12 is not valid. The
- LP register should point to the location where the called function
- should return. [note that MAKE_SYS_CALL uses label 1] */
-#define MAKE_SYS_CALL \
- /* Figure out which function to use for this system call. */ \
- shl 2, r12; \
- /* See if the system call number is valid. */ \
- addi lo(CSYM(sys_call_table) - sys_call_table_end), r12, r0; \
- bnh 1f; \
- mov hilo(CSYM(sys_call_table)), r19; \
- add r19, r12; \
- ld.w 0[r12], r12; \
- /* Make the system call. */ \
- jmp [r12]; \
- /* The syscall number is invalid, return an error. */ \
-1: addi -ENOSYS, r0, r10; \
- jmp [lp]
-
-
- .text
-
-/*
- * User trap.
- *
- * Trap 0 system calls are also handled here.
- *
- * The stack-pointer (r3) should have already been saved to the memory
- * location ENTRY_SP (the reason for this is that the interrupt vectors may be
- * beyond a 22-bit signed offset jump from the actual interrupt handler, and
- * this allows them to save the stack-pointer and use that register to do an
- * indirect jump).
- *
- * Syscall protocol:
- * Syscall number in r12, args in r6-r9
- * Return value in r10
- */
-G_ENTRY(trap):
- SAVE_STATE (TRAP, r12, ENTRY_SP) // Save registers.
- stsr SR_ECR, r19 // Find out which trap it was.
- ei // Enable interrupts.
- mov hilo(ret_from_trap), lp // where the trap should return
-
- // The following two shifts (1) clear out extraneous NMI data in the
- // upper 16-bits, (2) convert the 0x40 - 0x5f range of trap ECR
- // numbers into the (0-31) << 2 range we want, (3) set the flags.
- shl 27, r19 // chop off all high bits
- shr 25, r19 // scale back down and then << 2
- bnz 2f // See if not trap 0.
-
- // Trap 0 is a `short' system call, skip general trap table.
- MAKE_SYS_CALL // Jump to the syscall function.
-
-2: // For other traps, use a table lookup.
- mov hilo(CSYM(trap_table)), r18
- add r19, r18
- ld.w 0[r18], r18
- jmp [r18] // Jump to the trap handler.
-END(trap)
-
-/* This is just like ret_from_trap, but first restores extra registers
- saved by some wrappers. */
-L_ENTRY(restore_extra_regs_and_ret_from_trap):
- RESTORE_EXTRA_STATE(TRAP)
- // fall through
-END(restore_extra_regs_and_ret_from_trap)
-
-/* Entry point used to return from a syscall/trap. */
-L_ENTRY(ret_from_trap):
- RETURN(TRAP)
-END(ret_from_trap)
-
-
-/* This the initial entry point for a new child thread, with an appropriate
- stack in place that makes it look that the child is in the middle of an
- syscall. This function is actually `returned to' from switch_thread
- (copy_thread makes ret_from_fork the return address in each new thread's
- saved context). */
-C_ENTRY(ret_from_fork):
- mov r10, r6 // switch_thread returns the prev task.
- jarl CSYM(schedule_tail), lp // ...which is schedule_tail's arg
- mov r0, r10 // Child's fork call should return 0.
- br ret_from_trap // Do normal trap return.
-C_END(ret_from_fork)
-
-
-/*
- * Trap 1: `long' system calls
- * `Long' syscall protocol:
- * Syscall number in r12, args in r6-r9, r13-r14
- * Return value in r10
- */
-L_ENTRY(syscall_long):
- // Push extra arguments on the stack. Note that by default, the trap
- // handler reserves enough stack space for 6 arguments, so we don't
- // have to make any additional room.
- st.w r13, 16[sp] // arg 5
- st.w r14, 20[sp] // arg 6
-
- // Make sure r13 and r14 are preserved, in case we have to restart a
- // system call because of a signal (ep has already been set by caller).
- st.w r13, PTO+PT_GPR(13)[sp]
- st.w r14, PTO+PT_GPR(13)[sp]
- mov hilo(ret_from_long_syscall), lp
-
- MAKE_SYS_CALL // Jump to the syscall function.
-END(syscall_long)
-
-/* Entry point used to return from a long syscall. Only needed to restore
- r13/r14 if the general trap mechanism doesnt' do so. */
-L_ENTRY(ret_from_long_syscall):
- ld.w PTO+PT_GPR(13)[sp], r13 // Restore the extra registers
- ld.w PTO+PT_GPR(13)[sp], r14
- br ret_from_trap // The rest is the same as other traps
-END(ret_from_long_syscall)
-
-
-/* These syscalls need access to the struct pt_regs on the stack, so we
- implement them in assembly (they're basically all wrappers anyway). */
-
-L_ENTRY(sys_fork_wrapper):
-#ifdef CONFIG_MMU
- addi SIGCHLD, r0, r6 // Arg 0: flags
- ld.w PTO+PT_GPR(GPR_SP)[sp], r7 // Arg 1: child SP (use parent's)
- movea PTO, sp, r8 // Arg 2: parent context
- mov r0, r9 // Arg 3/4/5: 0
- st.w r0, 16[sp]
- st.w r0, 20[sp]
- mov hilo(CSYM(do_fork)), r18 // Where the real work gets done
- br save_extra_state_tramp // Save state and go there
-#else
- // fork almost works, enough to trick you into looking elsewhere :-(
- addi -EINVAL, r0, r10
- jmp [lp]
-#endif
-END(sys_fork_wrapper)
-
-L_ENTRY(sys_vfork_wrapper):
- addi CLONE_VFORK | CLONE_VM | SIGCHLD, r0, r6 // Arg 0: flags
- ld.w PTO+PT_GPR(GPR_SP)[sp], r7 // Arg 1: child SP (use parent's)
- movea PTO, sp, r8 // Arg 2: parent context
- mov r0, r9 // Arg 3/4/5: 0
- st.w r0, 16[sp]
- st.w r0, 20[sp]
- mov hilo(CSYM(do_fork)), r18 // Where the real work gets done
- br save_extra_state_tramp // Save state and go there
-END(sys_vfork_wrapper)
-
-L_ENTRY(sys_clone_wrapper):
- ld.w PTO+PT_GPR(GPR_SP)[sp], r19// parent's stack pointer
- cmp r7, r0 // See if child SP arg (arg 1) is 0.
- cmov z, r19, r7, r7 // ... and use the parent's if so.
- movea PTO, sp, r8 // Arg 2: parent context
- mov r0, r9 // Arg 3/4/5: 0
- st.w r0, 16[sp]
- st.w r0, 20[sp]
- mov hilo(CSYM(do_fork)), r18 // Where the real work gets done
- br save_extra_state_tramp // Save state and go there
-END(sys_clone_wrapper)
-
-
-L_ENTRY(sys_execve_wrapper):
- movea PTO, sp, r9 // add user context as 4th arg
- jr CSYM(sys_execve) // Do real work (tail-call).
-END(sys_execve_wrapper)
-
-
-L_ENTRY(sys_sigsuspend_wrapper):
- movea PTO, sp, r7 // add user context as 2nd arg
- mov hilo(CSYM(sys_sigsuspend)), r18 // syscall function
- jarl save_extra_state_tramp, lp // Save state and do it
- br restore_extra_regs_and_ret_from_trap
-END(sys_sigsuspend_wrapper)
-L_ENTRY(sys_rt_sigsuspend_wrapper):
- movea PTO, sp, r8 // add user context as 3rd arg
- mov hilo(CSYM(sys_rt_sigsuspend)), r18 // syscall function
- jarl save_extra_state_tramp, lp // Save state and do it
- br restore_extra_regs_and_ret_from_trap
-END(sys_rt_sigsuspend_wrapper)
-
-L_ENTRY(sys_sigreturn_wrapper):
- movea PTO, sp, r6 // add user context as 1st arg
- mov hilo(CSYM(sys_sigreturn)), r18 // syscall function
- jarl save_extra_state_tramp, lp // Save state and do it
- br restore_extra_regs_and_ret_from_trap
-END(sys_sigreturn_wrapper)
-L_ENTRY(sys_rt_sigreturn_wrapper):
- movea PTO, sp, r6 // add user context as 1st arg
- mov hilo(CSYM(sys_rt_sigreturn)), r18// syscall function
- jarl save_extra_state_tramp, lp // Save state and do it
- br restore_extra_regs_and_ret_from_trap
-END(sys_rt_sigreturn_wrapper)
-
-
-/* Save any state not saved by SAVE_STATE(TRAP), and jump to r18.
- It's main purpose is to share the rather lengthy code sequence that
- SAVE_STATE expands into among the above wrapper functions. */
-L_ENTRY(save_extra_state_tramp):
- SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry.
- jmp [r18] // Do the work the caller wants
-END(save_extra_state_tramp)
-
-
-/*
- * Hardware maskable interrupts.
- *
- * The stack-pointer (r3) should have already been saved to the memory
- * location ENTRY_SP (the reason for this is that the interrupt vectors may be
- * beyond a 22-bit signed offset jump from the actual interrupt handler, and
- * this allows them to save the stack-pointer and use that register to do an
- * indirect jump).
- */
-G_ENTRY(irq):
- SAVE_STATE (IRQ, r0, ENTRY_SP) // Save registers.
-
- stsr SR_ECR, r6 // Find out which interrupt it was.
- movea PTO, sp, r7 // User regs are arg2
-
- // All v850 implementations I know about encode their interrupts as
- // multiples of 0x10, starting at 0x80 (after NMIs and software
- // interrupts). Convert this number into a simple IRQ index for the
- // rest of the kernel. We also clear the upper 16 bits, which hold
- // NMI info, and don't appear to be cleared when a NMI returns.
- shl 16, r6 // clear upper 16 bits
- shr 20, r6 // shift back, and remove lower nibble
- add -8, r6 // remove bias for irqs
-
- // Call the high-level interrupt handling code.
- jarl CSYM(handle_irq), lp
-
- RETURN(IRQ)
-END(irq)
-
-
-/*
- * Debug trap / illegal-instruction exception
- *
- * The stack-pointer (r3) should have already been saved to the memory
- * location ENTRY_SP (the reason for this is that the interrupt vectors may be
- * beyond a 22-bit signed offset jump from the actual interrupt handler, and
- * this allows them to save the stack-pointer and use that register to do an
- * indirect jump).
- */
-G_ENTRY(dbtrap):
- SAVE_STATE (DBTRAP, r0, ENTRY_SP)// Save registers.
-
- /* First see if we came from kernel mode; if so, the dbtrap
- instruction has a special meaning, to set the DIR (`debug
- information register') register. This is because the DIR register
- can _only_ be manipulated/read while in `debug mode,' and debug
- mode is only active while we're inside the dbtrap handler. The
- exact functionality is: { DIR = (DIR | r6) & ~r7; return DIR; }. */
- ld.b PTO+PT_KERNEL_MODE[sp], r19
- cmp r19, r0
- bz 1f
-
- stsr SR_DIR, r10
- or r6, r10
- not r7, r7
- and r7, r10
- ldsr r10, SR_DIR
- stsr SR_DIR, r10 // Confirm the value we set
- st.w r10, PTO+PT_GPR(10)[sp] // return it
- br 3f
-
-1: ei // Enable interrupts.
-
- /* The default signal type we raise. */
- mov SIGTRAP, r6
-
- /* See if it's a single-step trap. */
- stsr SR_DBPSW, r19
- andi 0x0800, r19, r19
- bnz 2f
-
- /* Look to see if the preceding instruction was is a dbtrap or not,
- to decide which signal we should use. */
- stsr SR_DBPC, r19 // PC following trapping insn
- ld.hu -2[r19], r19
- ori 0xf840, r0, r20 // DBTRAP insn
- cmp r19, r20 // Was this trap caused by DBTRAP?
- cmov ne, SIGILL, r6, r6 // Choose signal appropriately
-
- /* Raise the desired signal. */
-2: mov CURRENT_TASK, r7 // Arg 1: task
- jarl CSYM(send_sig), lp // tail call
-
-3: RETURN(DBTRAP)
-END(dbtrap)
-
-
-/*
- * Hardware non-maskable interrupts.
- *
- * The stack-pointer (r3) should have already been saved to the memory
- * location ENTRY_SP (the reason for this is that the interrupt vectors may be
- * beyond a 22-bit signed offset jump from the actual interrupt handler, and
- * this allows them to save the stack-pointer and use that register to do an
- * indirect jump).
- */
-G_ENTRY(nmi):
- SAVE_STATE (NMI, r0, NMI_ENTRY_SP); /* Save registers. */
-
- stsr SR_ECR, r6; /* Find out which nmi it was. */
- shr 20, r6; /* Extract NMI code in bits 20-24. */
- movea PTO, sp, r7; /* User regs are arg2. */
-
- /* Non-maskable interrupts always lie right after maskable interrupts.
- Call the generic IRQ handler, with two arguments, the IRQ number,
- and a pointer to the user registers, to handle the specifics.
- (we subtract one because the first NMI has code 1). */
- addi FIRST_NMI - 1, r6, r6
- jarl CSYM(handle_irq), lp
-
- RETURN(NMI)
-END(nmi)
-
-
-/*
- * Trap with no handler
- */
-L_ENTRY(bad_trap_wrapper):
- mov r19, r6 // Arg 0: trap number
- movea PTO, sp, r7 // Arg 1: user regs
- jr CSYM(bad_trap) // tail call handler
-END(bad_trap_wrapper)
-
-
-/*
- * Invoke the scheduler, called from the trap/irq kernel exit path.
- *
- * This basically just calls `schedule', but also arranges for extra
- * registers to be saved for ptrace'd processes, so ptrace can modify them.
- */
-L_ENTRY(call_scheduler):
- ld.w TASK_PTRACE[CURRENT_TASK], r19 // See if task is ptrace'd
- cmp r19, r0
- bnz 1f // ... yes, do special stuff
- jr CSYM(schedule) // ... no, just tail-call scheduler
-
- // Save extra regs for ptrace'd task. We want to save anything
- // that would otherwise only be `implicitly' saved by the normal
- // compiler calling-convention.
-1: mov sp, ep // Setup EP for SAVE_CALL_SAVED_REGS
- SAVE_CALL_SAVED_REGS // Save call-saved registers to stack
- mov lp, r20 // Save LP in a callee-saved register
-
- jarl CSYM(schedule), lp // Call scheduler
-
- mov r20, lp
- mov sp, ep // We can't rely on EP after return
- RESTORE_CALL_SAVED_REGS // Restore (possibly modified) regs
- jmp [lp] // Return to the return path
-END(call_scheduler)
-
-
-/*
- * This is an out-of-line handler for two special cases during the kernel
- * trap/irq exit sequence:
- *
- * (1) If r18 is non-zero then a signal needs to be handled, which is
- * done, and then the caller returned to.
- *
- * (2) If r18 is non-zero then we're returning to a ptraced process, which
- * has several special cases -- single-stepping and trap tracing, both
- * of which require using the `dbret' instruction to exit the kernel
- * instead of the normal `reti' (this is because the CPU not correctly
- * single-step after a reti). In this case, of course, this handler
- * never returns to the caller.
- *
- * In either case, all registers should have been saved to the current
- * state-save-frame on the stack, except for callee-saved registers.
- *
- * [These two different cases are combined merely to avoid bloating the
- * macro-inlined code, not because they really make much sense together!]
- */
-L_ENTRY(handle_signal_or_ptrace_return):
- cmp r18, r0 // See if handling a signal
- bz 1f // ... nope, go do ptrace return
-
- // Handle a signal
- mov lp, r20 // Save link-pointer
- mov r10, r21 // Save return-values (for trap)
- mov r11, r22
-
- movea PTO, sp, r6 // Arg 1: struct pt_regs *regs
- mov r0, r7 // Arg 2: sigset_t *oldset
- jarl CSYM(do_signal), lp // Handle the signal
- di // sig handling enables interrupts
-
- mov r20, lp // Restore link-pointer
- mov r21, r10 // Restore return-values (for trap)
- mov r22, r11
- ld.w TASK_PTRACE[CURRENT_TASK], r19 // check ptrace flags too
- cmp r19, r0
- bnz 1f // ... some set, so look more
-2: jmp [lp] // ... none set, so return normally
-
- // ptrace return
-1: ld.w PTO+PT_PSW[sp], r19 // Look at user-processes's flags
- andi 0x0800, r19, r19 // See if single-step flag is set
- bz 2b // ... nope, return normally
-
- // Return as if from a dbtrap insn
- st.b r0, KM // Now officially in user state.
- POP_STATE(DBTRAP) // Restore regs
- st.w sp, KSP // Save the kernel stack pointer.
- ld.w PT_GPR(GPR_SP)-PT_SIZE[sp], sp // Restore user stack pointer.
- DBTRAP_RET // Return from the trap/interrupt.
-END(handle_signal_or_ptrace_return)
-
-
-/*
- * This is where we switch between two threads. The arguments are:
- * r6 -- pointer to the struct thread for the `current' process
- * r7 -- pointer to the struct thread for the `new' process.
- * when this function returns, it will return to the new thread.
- */
-C_ENTRY(switch_thread):
- // Return the previous task (r10 is not clobbered by restore below)
- mov CURRENT_TASK, r10
- // First, push the current processor state on the stack
- PUSH_STATE(SWITCH)
- // Now save the location of the kernel stack pointer for this thread;
- // since we've pushed all other state on the stack, this is enough to
- // restore it all later.
- st.w sp, THREAD_KSP[r6]
- // Now restore the stack pointer from the new process
- ld.w THREAD_KSP[r7], sp
- // ... and restore all state from that
- POP_STATE(SWITCH)
- // Update the current task pointer
- GET_CURRENT_TASK(CURRENT_TASK)
- // Now return into the new thread
- jmp [lp]
-C_END(switch_thread)
-
-
- .data
-
- .align 4
-C_DATA(trap_table):
- .long bad_trap_wrapper // trap 0, doesn't use trap table.
- .long syscall_long // trap 1, `long' syscall.
- .long bad_trap_wrapper
- .long bad_trap_wrapper
- .long bad_trap_wrapper
- .long bad_trap_wrapper
- .long bad_trap_wrapper
- .long bad_trap_wrapper
- .long bad_trap_wrapper
- .long bad_trap_wrapper
- .long bad_trap_wrapper
- .long bad_trap_wrapper
- .long bad_trap_wrapper
- .long bad_trap_wrapper
- .long bad_trap_wrapper
- .long bad_trap_wrapper
-C_END(trap_table)
-
-
- .section .rodata
-
- .align 4
-C_DATA(sys_call_table):
- .long CSYM(sys_restart_syscall) // 0
- .long CSYM(sys_exit)
- .long sys_fork_wrapper
- .long CSYM(sys_read)
- .long CSYM(sys_write)
- .long CSYM(sys_open) // 5
- .long CSYM(sys_close)
- .long CSYM(sys_waitpid)
- .long CSYM(sys_creat)
- .long CSYM(sys_link)
- .long CSYM(sys_unlink) // 10
- .long sys_execve_wrapper
- .long CSYM(sys_chdir)
- .long CSYM(sys_time)
- .long CSYM(sys_mknod)
- .long CSYM(sys_chmod) // 15
- .long CSYM(sys_chown)
- .long CSYM(sys_ni_syscall) // was: break
- .long CSYM(sys_ni_syscall) // was: oldstat (aka stat)
- .long CSYM(sys_lseek)
- .long CSYM(sys_getpid) // 20
- .long CSYM(sys_mount)
- .long CSYM(sys_oldumount)
- .long CSYM(sys_setuid)
- .long CSYM(sys_getuid)
- .long CSYM(sys_stime) // 25
- .long CSYM(sys_ptrace)
- .long CSYM(sys_alarm)
- .long CSYM(sys_ni_syscall) // was: oldfstat (aka fstat)
- .long CSYM(sys_pause)
- .long CSYM(sys_utime) // 30
- .long CSYM(sys_ni_syscall) // was: stty
- .long CSYM(sys_ni_syscall) // was: gtty
- .long CSYM(sys_access)
- .long CSYM(sys_nice)
- .long CSYM(sys_ni_syscall) // 35, was: ftime
- .long CSYM(sys_sync)
- .long CSYM(sys_kill)
- .long CSYM(sys_rename)
- .long CSYM(sys_mkdir)
- .long CSYM(sys_rmdir) // 40
- .long CSYM(sys_dup)
- .long CSYM(sys_pipe)
- .long CSYM(sys_times)
- .long CSYM(sys_ni_syscall) // was: prof
- .long CSYM(sys_brk) // 45
- .long CSYM(sys_setgid)
- .long CSYM(sys_getgid)
- .long CSYM(sys_signal)
- .long CSYM(sys_geteuid)
- .long CSYM(sys_getegid) // 50
- .long CSYM(sys_acct)
- .long CSYM(sys_umount) // recycled never used phys()
- .long CSYM(sys_ni_syscall) // was: lock
- .long CSYM(sys_ioctl)
- .long CSYM(sys_fcntl) // 55
- .long CSYM(sys_ni_syscall) // was: mpx
- .long CSYM(sys_setpgid)
- .long CSYM(sys_ni_syscall) // was: ulimit
- .long CSYM(sys_ni_syscall)
- .long CSYM(sys_umask) // 60
- .long CSYM(sys_chroot)
- .long CSYM(sys_ustat)
- .long CSYM(sys_dup2)
- .long CSYM(sys_getppid)
- .long CSYM(sys_getpgrp) // 65
- .long CSYM(sys_setsid)
- .long CSYM(sys_sigaction)
- .long CSYM(sys_sgetmask)
- .long CSYM(sys_ssetmask)
- .long CSYM(sys_setreuid) // 70
- .long CSYM(sys_setregid)
- .long sys_sigsuspend_wrapper
- .long CSYM(sys_sigpending)
- .long CSYM(sys_sethostname)
- .long CSYM(sys_setrlimit) // 75
- .long CSYM(sys_getrlimit)
- .long CSYM(sys_getrusage)
- .long CSYM(sys_gettimeofday)
- .long CSYM(sys_settimeofday)
- .long CSYM(sys_getgroups) // 80
- .long CSYM(sys_setgroups)
- .long CSYM(sys_select)
- .long CSYM(sys_symlink)
- .long CSYM(sys_ni_syscall) // was: oldlstat (aka lstat)
- .long CSYM(sys_readlink) // 85
- .long CSYM(sys_uselib)
- .long CSYM(sys_swapon)
- .long CSYM(sys_reboot)
- .long CSYM(old_readdir)
- .long CSYM(sys_mmap) // 90
- .long CSYM(sys_munmap)
- .long CSYM(sys_truncate)
- .long CSYM(sys_ftruncate)
- .long CSYM(sys_fchmod)
- .long CSYM(sys_fchown) // 95
- .long CSYM(sys_getpriority)
- .long CSYM(sys_setpriority)
- .long CSYM(sys_ni_syscall) // was: profil
- .long CSYM(sys_statfs)
- .long CSYM(sys_fstatfs) // 100
- .long CSYM(sys_ni_syscall) // i386: ioperm
- .long CSYM(sys_socketcall)
- .long CSYM(sys_syslog)
- .long CSYM(sys_setitimer)
- .long CSYM(sys_getitimer) // 105
- .long CSYM(sys_newstat)
- .long CSYM(sys_newlstat)
- .long CSYM(sys_newfstat)
- .long CSYM(sys_ni_syscall) // was: olduname (aka uname)
- .long CSYM(sys_ni_syscall) // 110, i386: iopl
- .long CSYM(sys_vhangup)
- .long CSYM(sys_ni_syscall) // was: idle
- .long CSYM(sys_ni_syscall) // i386: vm86old
- .long CSYM(sys_wait4)
- .long CSYM(sys_swapoff) // 115
- .long CSYM(sys_sysinfo)
- .long CSYM(sys_ipc)
- .long CSYM(sys_fsync)
- .long sys_sigreturn_wrapper
- .long sys_clone_wrapper // 120
- .long CSYM(sys_setdomainname)
- .long CSYM(sys_newuname)
- .long CSYM(sys_ni_syscall) // i386: modify_ldt, m68k: cacheflush
- .long CSYM(sys_adjtimex)
- .long CSYM(sys_ni_syscall) // 125 - sys_mprotect
- .long CSYM(sys_sigprocmask)
- .long CSYM(sys_ni_syscall) // sys_create_module
- .long CSYM(sys_init_module)
- .long CSYM(sys_delete_module)
- .long CSYM(sys_ni_syscall) // 130 - sys_get_kernel_syms
- .long CSYM(sys_quotactl)
- .long CSYM(sys_getpgid)
- .long CSYM(sys_fchdir)
- .long CSYM(sys_bdflush)
- .long CSYM(sys_sysfs) // 135
- .long CSYM(sys_personality)
- .long CSYM(sys_ni_syscall) // for afs_syscall
- .long CSYM(sys_setfsuid)
- .long CSYM(sys_setfsgid)
- .long CSYM(sys_llseek) // 140
- .long CSYM(sys_getdents)
- .long CSYM(sys_select) // for backward compat; remove someday
- .long CSYM(sys_flock)
- .long CSYM(sys_ni_syscall) // sys_msync
- .long CSYM(sys_readv) // 145
- .long CSYM(sys_writev)
- .long CSYM(sys_getsid)
- .long CSYM(sys_fdatasync)
- .long CSYM(sys_sysctl)
- .long CSYM(sys_ni_syscall) // 150 - sys_mlock
- .long CSYM(sys_ni_syscall) // sys_munlock
- .long CSYM(sys_ni_syscall) // sys_mlockall
- .long CSYM(sys_ni_syscall) // sys_munlockall
- .long CSYM(sys_sched_setparam)
- .long CSYM(sys_sched_getparam) // 155
- .long CSYM(sys_sched_setscheduler)
- .long CSYM(sys_sched_getscheduler)
- .long CSYM(sys_sched_yield)
- .long CSYM(sys_sched_get_priority_max)
- .long CSYM(sys_sched_get_priority_min) // 160
- .long CSYM(sys_sched_rr_get_interval)
- .long CSYM(sys_nanosleep)
- .long CSYM(sys_ni_syscall) // sys_mremap
- .long CSYM(sys_setresuid)
- .long CSYM(sys_getresuid) // 165
- .long CSYM(sys_ni_syscall) // for vm86
- .long CSYM(sys_ni_syscall) // sys_query_module
- .long CSYM(sys_poll)
- .long CSYM(sys_nfsservctl)
- .long CSYM(sys_setresgid) // 170
- .long CSYM(sys_getresgid)
- .long CSYM(sys_prctl)
- .long sys_rt_sigreturn_wrapper
- .long CSYM(sys_rt_sigaction)
- .long CSYM(sys_rt_sigprocmask) // 175
- .long CSYM(sys_rt_sigpending)
- .long CSYM(sys_rt_sigtimedwait)
- .long CSYM(sys_rt_sigqueueinfo)
- .long sys_rt_sigsuspend_wrapper
- .long CSYM(sys_pread64) // 180
- .long CSYM(sys_pwrite64)
- .long CSYM(sys_lchown)
- .long CSYM(sys_getcwd)
- .long CSYM(sys_capget)
- .long CSYM(sys_capset) // 185
- .long CSYM(sys_sigaltstack)
- .long CSYM(sys_sendfile)
- .long CSYM(sys_ni_syscall) // streams1
- .long CSYM(sys_ni_syscall) // streams2
- .long sys_vfork_wrapper // 190
- .long CSYM(sys_ni_syscall)
- .long CSYM(sys_mmap2)
- .long CSYM(sys_truncate64)
- .long CSYM(sys_ftruncate64)
- .long CSYM(sys_stat64) // 195
- .long CSYM(sys_lstat64)
- .long CSYM(sys_fstat64)
- .long CSYM(sys_fcntl64)
- .long CSYM(sys_getdents64)
- .long CSYM(sys_pivot_root) // 200
- .long CSYM(sys_gettid)
- .long CSYM(sys_tkill)
-sys_call_table_end:
-C_END(sys_call_table)
diff --git a/arch/v850/kernel/fpga85e2c.c b/arch/v850/kernel/fpga85e2c.c
deleted file mode 100644
index ab9cf16a85c..00000000000
--- a/arch/v850/kernel/fpga85e2c.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * arch/v850/kernel/fpga85e2c.h -- Machine-dependent defs for
- * FPGA implementation of V850E2/NA85E2C
- *
- * Copyright (C) 2002,03 NEC Electronics Corporation
- * Copyright (C) 2002,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-#include <linux/bitops.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/machdep.h>
-
-#include "mach.h"
-
-extern void memcons_setup (void);
-
-
-#define REG_DUMP_ADDR 0x220000
-
-
-extern struct irqaction reg_snap_action; /* fwd decl */
-
-
-void __init mach_early_init (void)
-{
- int i;
- const u32 *src;
- register u32 *dst asm ("ep");
- extern u32 _intv_end, _intv_load_start;
-
- /* Set bus sizes: CS0 32-bit, CS1 16-bit, CS7 8-bit,
- everything else 32-bit. */
- V850E2_BSC = 0x2AA6;
- for (i = 2; i <= 6; i++)
- CSDEV(i) = 0; /* 32 bit */
-
- /* Ensure that the simulator halts on a panic, instead of going
- into an infinite loop inside the panic function. */
- panic_timeout = -1;
-
- /* Move the interrupt vectors into their real location. Note that
- any relocations there are relative to the real location, so we
- don't have to fix anything up. We use a loop instead of calling
- memcpy to keep this a leaf function (to avoid a function
- prologue being generated). */
- dst = 0x10; /* &_intv_start + 0x10. */
- src = &_intv_load_start;
- do {
- u32 t0 = src[0], t1 = src[1], t2 = src[2], t3 = src[3];
- u32 t4 = src[4], t5 = src[5], t6 = src[6], t7 = src[7];
- dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3;
- dst[4] = t4; dst[5] = t5; dst[6] = t6; dst[7] = t7;
- dst += 8;
- src += 8;
- } while (dst < &_intv_end);
-}
-
-void __init mach_setup (char **cmdline)
-{
- memcons_setup ();
-
- /* Setup up NMI0 to copy the registers to a known memory location.
- The FGPA board has a button that produces NMI0 when pressed, so
- this allows us to push the button, and then look at memory to see
- what's in the registers (there's no other way to easily do so).
- We have to use `setup_irq' instead of `request_irq' because it's
- still too early to do memory allocation. */
- setup_irq (IRQ_NMI (0), &reg_snap_action);
-}
-
-void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len)
-{
- *ram_start = ERAM_ADDR;
- *ram_len = ERAM_SIZE;
-}
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
- /* Setup up the timer interrupt. The FPGA peripheral control
- registers _only_ work with single-bit writes (set1/clr1)! */
- __clear_bit (RPU_GTMC_CE_BIT, &RPU_GTMC);
- __clear_bit (RPU_GTMC_CLK_BIT, &RPU_GTMC);
- __set_bit (RPU_GTMC_CE_BIT, &RPU_GTMC);
-
- /* We use the first RPU interrupt, which occurs every 8.192ms. */
- setup_irq (IRQ_RPU (0), timer_action);
-}
-
-
-void mach_gettimeofday (struct timespec *tv)
-{
- tv->tv_sec = 0;
- tv->tv_nsec = 0;
-}
-
-void machine_halt (void) __attribute__ ((noreturn));
-void machine_halt (void)
-{
- for (;;) {
- DWC(0) = 0x7777;
- DWC(1) = 0x7777;
- ASC = 0xffff;
- FLGREG(0) = 1; /* Halt immediately. */
- asm ("di; halt; nop; nop; nop; nop; nop");
- }
-}
-
-void machine_restart (char *__unused)
-{
- machine_halt ();
-}
-
-void machine_power_off (void)
-{
- machine_halt ();
-}
-
-
-/* Interrupts */
-
-struct v850e_intc_irq_init irq_inits[] = {
- { "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
- { "RPU", IRQ_RPU(0), IRQ_RPU_NUM, 1, 6 },
- { 0 }
-};
-#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
-
-struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
-
-/* Initialize interrupts. */
-void __init mach_init_irqs (void)
-{
- v850e_intc_init_irq_types (irq_inits, hw_itypes);
-}
-
-
-/* An interrupt handler that copies the registers to a known memory location,
- for debugging purposes. */
-
-static void make_reg_snap (int irq, void *dummy, struct pt_regs *regs)
-{
- (*(unsigned *)REG_DUMP_ADDR)++;
- (*(struct pt_regs *)(REG_DUMP_ADDR + sizeof (unsigned))) = *regs;
-}
-
-static int reg_snap_dev_id;
-static struct irqaction reg_snap_action = {
- .handler = make_reg_snap,
- .mask = CPU_MASK_NONE,
- .name = "reg_snap",
- .dev_id = &reg_snap_dev_id,
-};
diff --git a/arch/v850/kernel/fpga85e2c.ld b/arch/v850/kernel/fpga85e2c.ld
deleted file mode 100644
index b5d4578ae41..00000000000
--- a/arch/v850/kernel/fpga85e2c.ld
+++ /dev/null
@@ -1,62 +0,0 @@
-/* Linker script for the FPGA implementation of the V850E2 NA85E2C cpu core
- (CONFIG_V850E2_FPGA85E2C). */
-
-MEMORY {
- /* Reset vector. */
- RESET : ORIGIN = 0, LENGTH = 0x10
- /* Interrupt vectors. */
- INTV : ORIGIN = 0x10, LENGTH = 0x470
- /* The `window' in RAM were we're allowed to load stuff. */
- RAM_LOW : ORIGIN = 0x480, LENGTH = 0x0005FB80
- /* Some more ram above the window were we can put bss &c. */
- RAM_HIGH : ORIGIN = 0x00060000, LENGTH = 0x000A0000
- /* This is the area visible from the outside world (we can use
- this only for uninitialized data). */
- VISIBLE : ORIGIN = 0x00200000, LENGTH = 0x00060000
-}
-
-SECTIONS {
- .reset : {
- __kram_start = . ;
- __intv_start = . ;
- *(.intv.reset) /* Reset vector */
- } > RESET
-
- .ram_low : {
- __r0_ram = . ; /* Must be near address 0. */
- . = . + 32 ;
-
- TEXT_CONTENTS
- DATA_CONTENTS
- ROOT_FS_CONTENTS
- RAMK_INIT_CONTENTS_NO_END
- INITRAMFS_CONTENTS
- } > RAM_LOW
-
- /* Where the interrupt vectors are initially loaded. */
- __intv_load_start = . ;
-
- .intv : {
- *(.intv.common) /* Vectors common to all v850e proc. */
- *(.intv.mach) /* Machine-specific int. vectors. */
- __intv_end = . ;
- } > INTV AT> RAM_LOW
-
- .ram_high : {
- /* This is here so that when we free init memory the
- load-time copy of the interrupt vectors and any empty
- space at the end of the `RAM_LOW' area is freed too. */
- . = ALIGN (4096);
- __init_end = . ;
-
- BSS_CONTENTS
- __kram_end = . ;
- BOOTMAP_CONTENTS
- } > RAM_HIGH
-
- .visible : {
- _memcons_output = . ;
- . = . + 0x8000 ;
- _memcons_output_end = . ;
- } > VISIBLE
-}
diff --git a/arch/v850/kernel/gbus_int.c b/arch/v850/kernel/gbus_int.c
deleted file mode 100644
index b2bcc251f65..00000000000
--- a/arch/v850/kernel/gbus_int.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * arch/v850/kernel/gbus_int.c -- Midas labs GBUS interrupt support
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/signal.h>
-#include <linux/kernel.h>
-
-#include <asm/machdep.h>
-
-
-/* The number of shared GINT interrupts. */
-#define NUM_GINTS 4
-
-/* For each GINT interrupt, how many GBUS interrupts are using it. */
-static unsigned gint_num_active_irqs[NUM_GINTS] = { 0 };
-
-/* A table of GINTn interrupts we actually use.
- Note that we don't use GINT0 because all the boards we support treat it
- specially. */
-struct used_gint {
- unsigned gint;
- unsigned priority;
-} used_gint[] = {
- { 1, GBUS_INT_PRIORITY_HIGH },
- { 3, GBUS_INT_PRIORITY_LOW }
-};
-#define NUM_USED_GINTS ARRAY_SIZE(used_gint)
-
-/* A table of which GINT is used by each GBUS interrupts (they are
- assigned based on priority). */
-static unsigned char gbus_int_gint[IRQ_GBUS_INT_NUM];
-
-
-/* Interrupt enabling/disabling. */
-
-/* Enable interrupt handling for interrupt IRQ. */
-void gbus_int_enable_irq (unsigned irq)
-{
- unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
- GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint)
- |= GBUS_INT_IRQ_MASK (irq);
-}
-
-/* Disable interrupt handling for interrupt IRQ. Note that any
- interrupts received while disabled will be delivered once the
- interrupt is enabled again, unless they are explicitly cleared using
- `gbus_int_clear_pending_irq'. */
-void gbus_int_disable_irq (unsigned irq)
-{
- unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
- GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint)
- &= ~GBUS_INT_IRQ_MASK (irq);
-}
-
-/* Return true if interrupt handling for interrupt IRQ is enabled. */
-int gbus_int_irq_enabled (unsigned irq)
-{
- unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
- return (GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint)
- & GBUS_INT_IRQ_MASK(irq));
-}
-
-/* Disable all GBUS irqs. */
-void gbus_int_disable_irqs ()
-{
- unsigned w, n;
- for (w = 0; w < GBUS_INT_NUM_WORDS; w++)
- for (n = 0; n < IRQ_GINT_NUM; n++)
- GBUS_INT_ENABLE (w, n) = 0;
-}
-
-/* Clear any pending interrupts for IRQ. */
-void gbus_int_clear_pending_irq (unsigned irq)
-{
- GBUS_INT_CLEAR (GBUS_INT_IRQ_WORD(irq)) = GBUS_INT_IRQ_MASK (irq);
-}
-
-/* Return true if interrupt IRQ is pending (but disabled). */
-int gbus_int_irq_pending (unsigned irq)
-{
- return (GBUS_INT_STATUS (GBUS_INT_IRQ_WORD(irq))
- & GBUS_INT_IRQ_MASK(irq));
-}
-
-
-/* Delegating interrupts. */
-
-/* Handle a shared GINT interrupt by passing to the appropriate GBUS
- interrupt handler. */
-static irqreturn_t gbus_int_handle_irq (int irq, void *dev_id,
- struct pt_regs *regs)
-{
- unsigned w;
- irqreturn_t rval = IRQ_NONE;
- unsigned gint = irq - IRQ_GINT (0);
-
- for (w = 0; w < GBUS_INT_NUM_WORDS; w++) {
- unsigned status = GBUS_INT_STATUS (w);
- unsigned enable = GBUS_INT_ENABLE (w, gint);
-
- /* Only pay attention to enabled interrupts. */
- status &= enable;
- if (status) {
- irq = IRQ_GBUS_INT (w * GBUS_INT_BITS_PER_WORD);
- do {
- /* There's an active interrupt in word
- W, find out which one, and call its
- handler. */
-
- while (! (status & 0x1)) {
- irq++;
- status >>= 1;
- }
- status &= ~0x1;
-
- /* Recursively call handle_irq to handle it. */
- handle_irq (irq, regs);
- rval = IRQ_HANDLED;
- } while (status);
- }
- }
-
- /* Toggle the `all enable' bit back and forth, which should cause
- another edge transition if there are any other interrupts
- still pending, and so result in another CPU interrupt. */
- GBUS_INT_ENABLE (0, gint) &= ~0x1;
- GBUS_INT_ENABLE (0, gint) |= 0x1;
-
- return rval;
-}
-
-
-/* Initialize GBUS interrupt sources. */
-
-static void irq_nop (unsigned irq) { }
-
-static unsigned gbus_int_startup_irq (unsigned irq)
-{
- unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
-
- if (gint_num_active_irqs[gint] == 0) {
- /* First enable the CPU interrupt. */
- int rval =
- request_irq (IRQ_GINT(gint), gbus_int_handle_irq,
- IRQF_DISABLED,
- "gbus_int_handler",
- &gint_num_active_irqs[gint]);
- if (rval != 0)
- return rval;
- }
-
- gint_num_active_irqs[gint]++;
-
- gbus_int_clear_pending_irq (irq);
- gbus_int_enable_irq (irq);
-
- return 0;
-}
-
-static void gbus_int_shutdown_irq (unsigned irq)
-{
- unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
-
- gbus_int_disable_irq (irq);
-
- if (--gint_num_active_irqs[gint] == 0)
- /* Disable the CPU interrupt. */
- free_irq (IRQ_GINT(gint), &gint_num_active_irqs[gint]);
-}
-
-/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
- INITS (which is terminated by an entry with the name field == 0). */
-void __init gbus_int_init_irq_types (struct gbus_int_irq_init *inits,
- struct hw_interrupt_type *hw_irq_types)
-{
- struct gbus_int_irq_init *init;
- for (init = inits; init->name; init++) {
- unsigned i;
- struct hw_interrupt_type *hwit = hw_irq_types++;
-
- hwit->typename = init->name;
-
- hwit->startup = gbus_int_startup_irq;
- hwit->shutdown = gbus_int_shutdown_irq;
- hwit->enable = gbus_int_enable_irq;
- hwit->disable = gbus_int_disable_irq;
- hwit->ack = irq_nop;
- hwit->end = irq_nop;
-
- /* Initialize kernel IRQ infrastructure for this interrupt. */
- init_irq_handlers(init->base, init->num, init->interval, hwit);
-
- /* Set the interrupt priorities. */
- for (i = 0; i < init->num; i++) {
- unsigned j;
- for (j = 0; j < NUM_USED_GINTS; j++)
- if (used_gint[j].priority > init->priority)
- break;
- /* Wherever we stopped looking is one past the
- GINT we want. */
- gbus_int_gint[init->base + i * init->interval
- - GBUS_INT_BASE_IRQ]
- = used_gint[j > 0 ? j - 1 : 0].gint;
- }
- }
-}
-
-
-/* Initialize IRQS. */
-
-/* Chip interrupts (GINTn) shared among GBUS interrupts. */
-static struct hw_interrupt_type gint_hw_itypes[NUM_USED_GINTS];
-
-
-/* GBUS interrupts themselves. */
-
-struct gbus_int_irq_init gbus_irq_inits[] __initdata = {
- /* First set defaults. */
- { "GBUS_INT", IRQ_GBUS_INT(0), IRQ_GBUS_INT_NUM, 1, 6},
- { 0 }
-};
-#define NUM_GBUS_IRQ_INITS (ARRAY_SIZE(gbus_irq_inits) - 1)
-
-static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS];
-
-
-/* Initialize GBUS interrupts. */
-void __init gbus_int_init_irqs (void)
-{
- unsigned i;
-
- /* First initialize the shared gint interrupts. */
- for (i = 0; i < NUM_USED_GINTS; i++) {
- unsigned gint = used_gint[i].gint;
- struct v850e_intc_irq_init gint_irq_init[2];
-
- /* We initialize one GINT interrupt at a time. */
- gint_irq_init[0].name = "GINT";
- gint_irq_init[0].base = IRQ_GINT (gint);
- gint_irq_init[0].num = 1;
- gint_irq_init[0].interval = 1;
- gint_irq_init[0].priority = used_gint[i].priority;
-
- gint_irq_init[1].name = 0; /* Terminate the vector. */
-
- v850e_intc_init_irq_types (gint_irq_init, gint_hw_itypes);
- }
-
- /* Then the GBUS interrupts. */
- gbus_int_disable_irqs ();
- gbus_int_init_irq_types (gbus_irq_inits, gbus_hw_itypes);
- /* Turn on the `all enable' bits, which are ANDed with
- individual interrupt enable bits; we only want to bother with
- the latter. They are the first bit in the first word of each
- interrupt-enable area. */
- for (i = 0; i < NUM_USED_GINTS; i++)
- GBUS_INT_ENABLE (0, used_gint[i].gint) = 0x1;
-}
diff --git a/arch/v850/kernel/head.S b/arch/v850/kernel/head.S
deleted file mode 100644
index c490b937ef1..00000000000
--- a/arch/v850/kernel/head.S
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * arch/v850/kernel/head.S -- Lowest-level startup code
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <asm/clinkage.h>
-#include <asm/current.h>
-#include <asm/entry.h>
-#include <asm/thread_info.h>
-#include <asm/irq.h>
-
-
-/* Make a slightly more convenient alias for C_SYMBOL_NAME. */
-#define CSYM C_SYMBOL_NAME
-
-
- .text
-
- // Define `mach_early_init' as a weak symbol
- .global CSYM(mach_early_init)
- .weak CSYM(mach_early_init)
-
-C_ENTRY(start):
- // Make sure interrupts are turned off, just in case
- di
-
-#ifdef CONFIG_RESET_GUARD
- // See if we got here via an unexpected reset
- ld.w RESET_GUARD, r19 // Check current value of reset guard
- mov RESET_GUARD_ACTIVE, r20
- cmp r19, r20
- bne 1f // Guard was not active
-
- // If we get here, the reset guard was active. Load up some
- // interesting values as arguments, and jump to the handler.
- st.w r0, RESET_GUARD // Allow further resets to succeed
- mov lp, r6 // Arg 0: return address
- ld.b KM, r7 // Arg 1: kernel mode
- mov sp, r9 // Arg 3: stack pointer
- ld.w KSP, r19 // maybe switch to kernel stack
- cmp r7, r0 // see if already in kernel mode
- cmov z, r19, sp, sp // and switch to kernel stack if not
- GET_CURRENT_TASK(r8) // Arg 2: task pointer
- jr CSYM(unexpected_reset)
-
-1: st.w r20, RESET_GUARD // Turn on reset guard
-#endif /* CONFIG_RESET_GUARD */
-
- // Setup a temporary stack for doing pre-initialization function calls.
- //
- // We can't use the initial kernel stack, because (1) it may be
- // located in memory we're not allowed to touch, and (2) since
- // it's in the data segment, calling memcpy to initialize that
- // area from ROM will overwrite memcpy's return address.
- mov hilo(CSYM(_init_stack_end) - 4), sp
-
- // See if there's a platform-specific early-initialization routine
- // defined; it's a weak symbol, so it will have an address of zero if
- // there's not.
- mov hilo(CSYM(mach_early_init)), r6
- cmp r6, r0
- bz 3f
-
- // There is one, so call it. If this function is written in C, it
- // should be very careful -- the stack pointer is valid, but very
- // little else is (e.g., bss is not zeroed yet, and initialized data
- // hasn't been).
- jarl 2f, lp // first figure out return address
-2: add 3f - ., lp
- jmp [r6] // do call
-3:
-
-#ifdef CONFIG_ROM_KERNEL
- // Copy the data area from ROM to RAM
- mov hilo(CSYM(_rom_copy_dst_start)), r6
- mov hilo(CSYM(_rom_copy_src_start)), r7
- mov hilo(CSYM(_rom_copy_dst_end)), r8
- sub r6, r8
- jarl CSYM(memcpy), lp
-#endif
-
- // Load the initial thread's stack, and current task pointer (in r16)
- mov hilo(CSYM(init_thread_union)), r19
- movea THREAD_SIZE, r19, sp
- ld.w TI_TASK[r19], CURRENT_TASK
-
-#ifdef CONFIG_TIME_BOOTUP
- /* This stuff must come after mach_early_init, because interrupts may
- not work until after its been called. */
- jarl CSYM(highres_timer_reset), lp
- jarl CSYM(highres_timer_start), lp
-#endif
-
- // Kernel stack pointer save location
- st.w sp, KSP
-
- // Assert that we're in `kernel mode'
- mov 1, r19
- st.w r19, KM
-
-#ifdef CONFIG_ZERO_BSS
- // Zero bss area, since we can't rely upon any loader to do so
- mov hilo(CSYM(_sbss)), r6
- mov r0, r7
- mov hilo(CSYM(_ebss)), r8
- sub r6, r8
- jarl CSYM(memset), lp
-#endif
-
- // What happens if the main kernel function returns (it shouldn't)
- mov hilo(CSYM(machine_halt)), lp
-
- // Start the linux kernel. We use an indirect jump to get extra
- // range, because on some platforms this initial startup code
- // (and the associated platform-specific code in mach_early_init)
- // are located far away from the main kernel, e.g. so that they
- // can initialize RAM first and copy the kernel or something.
- mov hilo(CSYM(start_kernel)), r12
- jmp [r12]
-C_END(start)
diff --git a/arch/v850/kernel/highres_timer.c b/arch/v850/kernel/highres_timer.c
deleted file mode 100644
index b16ad1eaf96..00000000000
--- a/arch/v850/kernel/highres_timer.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * arch/v850/kernel/highres_timer.c -- High resolution timing routines
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <asm/system.h>
-#include <asm/v850e_timer_d.h>
-#include <asm/highres_timer.h>
-
-#define HIGHRES_TIMER_USEC_SHIFT 12
-
-/* Pre-calculated constant used for converting ticks to real time
- units. We initialize it to prevent it being put into BSS. */
-static u32 highres_timer_usec_prescale = 1;
-
-void highres_timer_slow_tick_irq (void) __attribute__ ((noreturn));
-void highres_timer_slow_tick_irq (void)
-{
- /* This is an interrupt handler, so it must be very careful to
- not to trash any registers. At this point, the stack-pointer
- (r3) has been saved in the chip ram location ENTRY_SP by the
- interrupt vector, so we can use it as a scratch register; we
- must also restore it before returning. */
- asm ("ld.w %0[r0], sp;"
- "add 1, sp;"
- "st.w sp, %0[r0];"
- "ld.w %1[r0], sp;" /* restore pre-irq stack-pointer */
- "reti"
- ::
- "i" (HIGHRES_TIMER_SLOW_TICKS_ADDR),
- "i" (ENTRY_SP_ADDR)
- : "memory");
-}
-
-void highres_timer_reset (void)
-{
- V850E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT) = 0;
- HIGHRES_TIMER_SLOW_TICKS = 0;
-}
-
-void highres_timer_start (void)
-{
- u32 fast_tick_rate;
-
- /* Start hardware timer. */
- v850e_timer_d_configure (HIGHRES_TIMER_TIMER_D_UNIT,
- HIGHRES_TIMER_SLOW_TICK_RATE);
-
- fast_tick_rate =
- (V850E_TIMER_D_BASE_FREQ
- >> V850E_TIMER_D_DIVLOG2 (HIGHRES_TIMER_TIMER_D_UNIT));
-
- /* The obvious way of calculating microseconds from fast ticks
- is to do:
-
- usec = fast_ticks * 10^6 / fast_tick_rate
-
- However, divisions are much slower than multiplications, and
- the above calculation can overflow, so we do this instead:
-
- usec = fast_ticks * (10^6 * 2^12 / fast_tick_rate) / 2^12
-
- since we can pre-calculate (10^6 * (2^12 / fast_tick_rate))
- and use a shift for dividing by 2^12, this avoids division,
- and is almost as accurate (it differs by about 2 microseconds
- at the extreme value of the fast-tick counter's ranger). */
- highres_timer_usec_prescale = ((1000000 << HIGHRES_TIMER_USEC_SHIFT)
- / fast_tick_rate);
-
- /* Enable the interrupt (which is hardwired to this use), and
- give it the highest priority. */
- V850E_INTC_IC (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)) = 0;
-}
-
-void highres_timer_stop (void)
-{
- /* Stop the timer. */
- V850E_TIMER_D_TMCD (HIGHRES_TIMER_TIMER_D_UNIT) =
- V850E_TIMER_D_TMCD_CAE;
- /* Disable its interrupt, just in case. */
- v850e_intc_disable_irq (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT));
-}
-
-inline void highres_timer_read_ticks (u32 *slow_ticks, u32 *fast_ticks)
-{
- int flags;
- u32 fast_ticks_1, fast_ticks_2, _slow_ticks;
-
- local_irq_save (flags);
- fast_ticks_1 = V850E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT);
- _slow_ticks = HIGHRES_TIMER_SLOW_TICKS;
- fast_ticks_2 = V850E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT);
- local_irq_restore (flags);
-
- if (fast_ticks_2 < fast_ticks_1)
- _slow_ticks++;
-
- *slow_ticks = _slow_ticks;
- *fast_ticks = fast_ticks_2;
-}
-
-inline void highres_timer_ticks_to_timeval (u32 slow_ticks, u32 fast_ticks,
- struct timeval *tv)
-{
- unsigned long sec, sec_rem, usec;
-
- usec = ((fast_ticks * highres_timer_usec_prescale)
- >> HIGHRES_TIMER_USEC_SHIFT);
-
- sec = slow_ticks / HIGHRES_TIMER_SLOW_TICK_RATE;
- sec_rem = slow_ticks % HIGHRES_TIMER_SLOW_TICK_RATE;
-
- usec += sec_rem * (1000000 / HIGHRES_TIMER_SLOW_TICK_RATE);
-
- tv->tv_sec = sec;
- tv->tv_usec = usec;
-}
-
-void highres_timer_read (struct timeval *tv)
-{
- u32 fast_ticks, slow_ticks;
- highres_timer_read_ticks (&slow_ticks, &fast_ticks);
- highres_timer_ticks_to_timeval (slow_ticks, fast_ticks, tv);
-}
diff --git a/arch/v850/kernel/init_task.c b/arch/v850/kernel/init_task.c
deleted file mode 100644
index 44b274dff33..00000000000
--- a/arch/v850/kernel/init_task.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * arch/v850/kernel/init_task.c -- Initial task/thread structures
- *
- * Copyright (C) 2002,03 NEC Electronics Corporation
- * Copyright (C) 2002,03 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
- * archive for more details.
- */
-
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-
-static struct fs_struct init_fs = INIT_FS;
-static struct signal_struct init_signals = INIT_SIGNALS (init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM (init_mm);
-
-EXPORT_SYMBOL(init_mm);
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK (init_task);
-
-EXPORT_SYMBOL(init_task);
-
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is 8192-byte aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry.
- */
-union thread_union init_thread_union
- __attribute__((__section__(".data.init_task"))) =
- { INIT_THREAD_INFO(init_task) };
diff --git a/arch/v850/kernel/intv.S b/arch/v850/kernel/intv.S
deleted file mode 100644
index 671e4c6150d..00000000000
--- a/arch/v850/kernel/intv.S
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * arch/v850/kernel/intv.S -- Interrupt vectors
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <asm/clinkage.h>
-#include <asm/irq.h>
-#include <asm/machdep.h>
-#include <asm/entry.h>
-
-#ifdef CONFIG_V850E_HIGHRES_TIMER
-#include <asm/highres_timer.h>
-#endif
-
-/* Jump to an interrupt/trap handler. These handlers (defined in entry.S)
- expect the stack-pointer to be saved in ENTRY_SP, so we use sp to do an
- indirect jump (which avoids problems when the handler is more than a signed
- 22-bit offset away). */
-#define JUMP_TO_HANDLER(name, sp_save_loc) \
- st.w sp, sp_save_loc; \
- mov hilo(name), sp; \
- jmp [sp]
-
-
- /* Reset vector. */
- .section .intv.reset, "ax"
- .org 0x0
- mov hilo(C_SYMBOL_NAME(start)), r1;
- jmp [r1]
-
-
- /* Generic interrupt vectors. */
- .section .intv.common, "ax"
- .balign 0x10
- JUMP_TO_HANDLER (nmi, NMI_ENTRY_SP) // 0x10 - NMI0
- .balign 0x10
- JUMP_TO_HANDLER (nmi, NMI_ENTRY_SP) // 0x20 - NMI1
- .balign 0x10
- JUMP_TO_HANDLER (nmi, NMI_ENTRY_SP) // 0x30 - NMI2
-
- .balign 0x10
- JUMP_TO_HANDLER (trap, ENTRY_SP) // 0x40 - TRAP0n
- .balign 0x10
- JUMP_TO_HANDLER (trap, ENTRY_SP) // 0x50 - TRAP1n
-
- .balign 0x10
- JUMP_TO_HANDLER (dbtrap, ENTRY_SP) // 0x60 - Illegal op / DBTRAP insn
-
-
- /* Hardware interrupt vectors. */
- .section .intv.mach, "ax"
- .org 0x0
-
-#if defined (CONFIG_V850E_HIGHRES_TIMER) && defined (IRQ_INTCMD)
-
- /* Interrupts before the highres timer interrupt. */
- .rept IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)
- .balign 0x10
- JUMP_TO_HANDLER (irq, ENTRY_SP)
- .endr
-
- /* The highres timer interrupt. */
- .balign 0x10
- JUMP_TO_HANDLER (C_SYMBOL_NAME (highres_timer_slow_tick_irq), ENTRY_SP)
-
- /* Interrupts after the highres timer interrupt. */
- .rept NUM_CPU_IRQS - IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT) - 1
- .balign 0x10
- JUMP_TO_HANDLER (irq, ENTRY_SP)
- .endr
-
-#else /* No highres timer */
-
- .rept NUM_CPU_IRQS
- .balign 0x10
- JUMP_TO_HANDLER (irq, ENTRY_SP)
- .endr
-
-#endif /* Highres timer */
diff --git a/arch/v850/kernel/irq.c b/arch/v850/kernel/irq.c
deleted file mode 100644
index 858c45819aa..00000000000
--- a/arch/v850/kernel/irq.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * arch/v850/kernel/irq.c -- High-level interrupt handling
- *
- * Copyright (C) 2001,02,03,04,05 NEC Electronics Corporation
- * Copyright (C) 2001,02,03,04,05 Miles Bader <miles@gnu.org>
- * Copyright (C) 1994-2000 Ralf Baechle
- * Copyright (C) 1992 Linus Torvalds
- *
- * 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.
- *
- * This file was was derived from the mips version, arch/mips/kernel/irq.c
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/irq.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/random.h>
-#include <linux/seq_file.h>
-
-#include <asm/system.h>
-
-/*
- * 'what should we do if we get a hw irq event on an illegal vector'.
- * each architecture has to answer this themselves, it doesn't deserve
- * a generic callback i think.
- */
-void ack_bad_irq(unsigned int irq)
-{
- printk("received IRQ %d with unknown interrupt type\n", irq);
-}
-
-volatile unsigned long irq_err_count, spurious_count;
-
-/*
- * Generic, controller-independent functions:
- */
-
-int show_interrupts(struct seq_file *p, void *v)
-{
- int irq = *(loff_t *) v;
-
- if (irq == 0) {
- int cpu;
- seq_puts(p, " ");
- for (cpu=0; cpu < 1 /*smp_num_cpus*/; cpu++)
- seq_printf(p, "CPU%d ", cpu);
- seq_putc(p, '\n');
- }
-
- if (irq < NR_IRQS) {
- unsigned long flags;
- struct irqaction *action;
-
- spin_lock_irqsave(&irq_desc[irq].lock, flags);
-
- action = irq_desc[irq].action;
- if (action) {
- int j;
- int count = 0;
- int num = -1;
- const char *type_name = irq_desc[irq].chip->typename;
-
- for (j = 0; j < NR_IRQS; j++)
- if (irq_desc[j].chip->typename == type_name){
- if (irq == j)
- num = count;
- count++;
- }
-
- seq_printf(p, "%3d: ",irq);
- seq_printf(p, "%10u ", kstat_irqs(irq));
- if (count > 1) {
- int prec = (num >= 100 ? 3 : num >= 10 ? 2 : 1);
- seq_printf(p, " %*s%d", 14 - prec,
- type_name, num);
- } else
- seq_printf(p, " %14s", type_name);
-
- seq_printf(p, " %s", action->name);
- for (action=action->next; action; action = action->next)
- seq_printf(p, ", %s", action->name);
- seq_putc(p, '\n');
- }
-
- spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
- } else if (irq == NR_IRQS)
- seq_printf(p, "ERR: %10lu\n", irq_err_count);
-
- return 0;
-}
-
-/* Handle interrupt IRQ. REGS are the registers at the time of ther
- interrupt. */
-unsigned int handle_irq (int irq, struct pt_regs *regs)
-{
- irq_enter();
- __do_IRQ(irq, regs);
- irq_exit();
- return 1;
-}
-
-/* Initialize irq handling for IRQs.
- BASE_IRQ, BASE_IRQ+INTERVAL, ..., BASE_IRQ+NUM*INTERVAL
- to IRQ_TYPE. An IRQ_TYPE of 0 means to use a generic interrupt type. */
-void __init
-init_irq_handlers (int base_irq, int num, int interval,
- struct hw_interrupt_type *irq_type)
-{
- while (num-- > 0) {
- irq_desc[base_irq].status = IRQ_DISABLED;
- irq_desc[base_irq].action = NULL;
- irq_desc[base_irq].depth = 1;
- irq_desc[base_irq].chip = irq_type;
- base_irq += interval;
- }
-}
diff --git a/arch/v850/kernel/ma.c b/arch/v850/kernel/ma.c
deleted file mode 100644
index 143774de75e..00000000000
--- a/arch/v850/kernel/ma.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * arch/v850/kernel/ma.c -- V850E/MA series of cpu chips
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/machdep.h>
-#include <asm/v850e_timer_d.h>
-
-#include "mach.h"
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
- /* Start hardware timer. */
- v850e_timer_d_configure (0, HZ);
- /* Install timer interrupt handler. */
- setup_irq (IRQ_INTCMD(0), timer_action);
-}
-
-static struct v850e_intc_irq_init irq_inits[] = {
- { "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
- { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 },
- { "DMA", IRQ_INTDMA(0), IRQ_INTDMA_NUM, 1, 2 },
- { "CSI", IRQ_INTCSI(0), IRQ_INTCSI_NUM, 4, 4 },
- { "SER", IRQ_INTSER(0), IRQ_INTSER_NUM, 4, 3 },
- { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 4, 4 },
- { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 4, 5 },
- { 0 }
-};
-#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
-
-static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
-
-/* Initialize MA chip interrupts. */
-void __init ma_init_irqs (void)
-{
- v850e_intc_init_irq_types (irq_inits, hw_itypes);
-}
-
-/* Called before configuring an on-chip UART. */
-void ma_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
-{
- /* We only know about the first two UART channels (though
- specific chips may have more). */
- if (chan < 2) {
- unsigned bits = 0x3 << (chan * 3);
- /* Specify that the relevant pins on the chip should do
- serial I/O, not direct I/O. */
- MA_PORT4_PMC |= bits;
- /* Specify that we're using the UART, not the CSI device. */
- MA_PORT4_PFC |= bits;
- }
-}
diff --git a/arch/v850/kernel/mach.c b/arch/v850/kernel/mach.c
deleted file mode 100644
index b9db278d2b7..00000000000
--- a/arch/v850/kernel/mach.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * arch/v850/kernel/mach.c -- Defaults for some things defined by "mach.h"
- *
- * Copyright (C) 2001 NEC Corporation
- * Copyright (C) 2001 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include "mach.h"
-
-/* Called with each timer tick, if non-zero. */
-void (*mach_tick)(void) = 0;
diff --git a/arch/v850/kernel/mach.h b/arch/v850/kernel/mach.h
deleted file mode 100644
index 9e0e4816ec5..00000000000
--- a/arch/v850/kernel/mach.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * arch/v850/kernel/mach.h -- Machine-dependent functions used by v850 port
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_MACH_H__
-#define __V850_MACH_H__
-
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/seq_file.h>
-
-#include <asm/ptrace.h>
-#include <asm/entry.h>
-#include <asm/clinkage.h>
-
-void mach_setup (char **cmdline);
-void mach_gettimeofday (struct timespec *tv);
-void mach_sched_init (struct irqaction *timer_action);
-void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len);
-void mach_init_irqs (void);
-
-/* If defined, is called very early in the kernel initialization. The
- stack pointer is valid, but very little has been initialized (e.g.,
- bss is not zeroed yet) when this is called, so care must taken. */
-void mach_early_init (void);
-
-/* If defined, called after the bootmem allocator has been initialized,
- to allow the platform-dependent code to reserve any areas of RAM that
- the kernel shouldn't touch. */
-void mach_reserve_bootmem (void) __attribute__ ((__weak__));
-
-/* Called with each timer tick, if non-zero. */
-extern void (*mach_tick) (void);
-
-/* The following establishes aliases for various mach_ functions to the
- name by which the rest of the kernel calls them. These statements
- should only have an effect in the file that defines the actual functions. */
-#define MACH_ALIAS(to, from) \
- asm (".global " macrology_stringify (C_SYMBOL_NAME (to)) ";" \
- macrology_stringify (C_SYMBOL_NAME (to)) \
- " = " macrology_stringify (C_SYMBOL_NAME (from)))
-/* e.g.: MACH_ALIAS (kernel_name, arch_spec_name); */
-
-#endif /* __V850_MACH_H__ */
diff --git a/arch/v850/kernel/me2.c b/arch/v850/kernel/me2.c
deleted file mode 100644
index 007115dc9ce..00000000000
--- a/arch/v850/kernel/me2.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * arch/v850/kernel/me2.c -- V850E/ME2 chip-specific support
- *
- * Copyright (C) 2003 NEC Corporation
- * Copyright (C) 2003 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/machdep.h>
-#include <asm/v850e_timer_d.h>
-
-#include "mach.h"
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
- /* Start hardware timer. */
- v850e_timer_d_configure (0, HZ);
- /* Install timer interrupt handler. */
- setup_irq (IRQ_INTCMD(0), timer_action);
-}
-
-static struct v850e_intc_irq_init irq_inits[] = {
- { "IRQ", 0, NUM_CPU_IRQS, 1, 7 },
- { "INTP", IRQ_INTP(0), IRQ_INTP_NUM, 1, 5 },
- { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 3 },
- { "UBTIRE", IRQ_INTUBTIRE(0), IRQ_INTUBTIRE_NUM, 5, 4 },
- { "UBTIR", IRQ_INTUBTIR(0), IRQ_INTUBTIR_NUM, 5, 4 },
- { "UBTIT", IRQ_INTUBTIT(0), IRQ_INTUBTIT_NUM, 5, 4 },
- { "UBTIF", IRQ_INTUBTIF(0), IRQ_INTUBTIF_NUM, 5, 4 },
- { "UBTITO", IRQ_INTUBTITO(0), IRQ_INTUBTITO_NUM, 5, 4 },
- { 0 }
-};
-#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
-
-static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
-
-/* Initialize V850E/ME2 chip interrupts. */
-void __init me2_init_irqs (void)
-{
- v850e_intc_init_irq_types (irq_inits, hw_itypes);
-}
-
-/* Called before configuring an on-chip UART. */
-void me2_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
-{
- if (chan == 0) {
- /* Specify that the relevant pins on the chip should do
- serial I/O, not direct I/O. */
- ME2_PORT1_PMC |= 0xC;
- /* Specify that we're using the UART, not the CSI device. */
- ME2_PORT1_PFC |= 0xC;
- } else if (chan == 1) {
- /* Specify that the relevant pins on the chip should do
- serial I/O, not direct I/O. */
- ME2_PORT2_PMC |= 0x6;
- /* Specify that we're using the UART, not the CSI device. */
- ME2_PORT2_PFC |= 0x6;
- }
-}
diff --git a/arch/v850/kernel/memcons.c b/arch/v850/kernel/memcons.c
deleted file mode 100644
index 92f514fdcc7..00000000000
--- a/arch/v850/kernel/memcons.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * arch/v850/kernel/memcons.c -- Console I/O to a memory buffer
- *
- * Copyright (C) 2001,02 NEC Corporation
- * Copyright (C) 2001,02 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/console.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/init.h>
-
-/* If this device is enabled, the linker map should define start and
- end points for its buffer. */
-extern char memcons_output[], memcons_output_end;
-
-/* Current offset into the buffer. */
-static unsigned long memcons_offs = 0;
-
-/* Spinlock protecting memcons_offs. */
-static DEFINE_SPINLOCK(memcons_lock);
-
-
-static size_t write (const char *buf, size_t len)
-{
- unsigned long flags;
- char *point;
-
- spin_lock_irqsave (memcons_lock, flags);
-
- point = memcons_output + memcons_offs;
- if (point + len >= &memcons_output_end) {
- len = &memcons_output_end - point;
- memcons_offs = 0;
- } else
- memcons_offs += len;
-
- spin_unlock_irqrestore (memcons_lock, flags);
-
- memcpy (point, buf, len);
-
- return len;
-}
-
-
-/* Low-level console. */
-
-static void memcons_write (struct console *co, const char *buf, unsigned len)
-{
- while (len > 0)
- len -= write (buf, len);
-}
-
-static struct tty_driver *tty_driver;
-
-static struct tty_driver *memcons_device (struct console *co, int *index)
-{
- *index = co->index;
- return tty_driver;
-}
-
-static struct console memcons =
-{
- .name = "memcons",
- .write = memcons_write,
- .device = memcons_device,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-void memcons_setup (void)
-{
- register_console (&memcons);
- printk (KERN_INFO "Console: static memory buffer (memcons)\n");
-}
-
-/* Higher level TTY interface. */
-
-int memcons_tty_open (struct tty_struct *tty, struct file *filp)
-{
- return 0;
-}
-
-int memcons_tty_write (struct tty_struct *tty, const unsigned char *buf, int len)
-{
- return write (buf, len);
-}
-
-int memcons_tty_write_room (struct tty_struct *tty)
-{
- return &memcons_output_end - (memcons_output + memcons_offs);
-}
-
-int memcons_tty_chars_in_buffer (struct tty_struct *tty)
-{
- /* We have no buffer. */
- return 0;
-}
-
-static const struct tty_operations ops = {
- .open = memcons_tty_open,
- .write = memcons_tty_write,
- .write_room = memcons_tty_write_room,
- .chars_in_buffer = memcons_tty_chars_in_buffer,
-};
-
-int __init memcons_tty_init (void)
-{
- int err;
- struct tty_driver *driver = alloc_tty_driver(1);
- if (!driver)
- return -ENOMEM;
-
- driver->name = "memcons";
- driver->major = TTY_MAJOR;
- driver->minor_start = 64;
- driver->type = TTY_DRIVER_TYPE_SYSCONS;
- driver->init_termios = tty_std_termios;
- tty_set_operations(driver, &ops);
- err = tty_register_driver(driver);
- if (err) {
- put_tty_driver(driver);
- return err;
- }
- tty_driver = driver;
- return 0;
-}
-__initcall (memcons_tty_init);
diff --git a/arch/v850/kernel/module.c b/arch/v850/kernel/module.c
deleted file mode 100644
index 64aeb3e37c5..00000000000
--- a/arch/v850/kernel/module.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * arch/v850/kernel/module.c -- Architecture-specific module functions
- *
- * Copyright (C) 2002,03 NEC Electronics Corporation
- * Copyright (C) 2002,03 Miles Bader <miles@gnu.org>
- * Copyright (C) 2001,03 Rusty Russell
- *
- * 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.
- *
- * Written by Miles Bader <miles@gnu.org>
- *
- * Derived in part from arch/ppc/kernel/module.c
- */
-
-#include <linux/kernel.h>
-#include <linux/vmalloc.h>
-#include <linux/moduleloader.h>
-#include <linux/elf.h>
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(fmt , ...)
-#endif
-
-void *module_alloc (unsigned long size)
-{
- return size == 0 ? 0 : vmalloc (size);
-}
-
-void module_free (struct module *mod, void *module_region)
-{
- vfree (module_region);
- /* FIXME: If module_region == mod->init_region, trim exception
- table entries. */
-}
-
-int module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
- struct module *mod)
-{
- return 0;
-}
-
-/* Count how many different relocations (different symbol, different
- addend) */
-static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num)
-{
- unsigned int i, j, ret = 0;
-
- /* Sure, this is order(n^2), but it's usually short, and not
- time critical */
- for (i = 0; i < num; i++) {
- for (j = 0; j < i; j++) {
- /* If this addend appeared before, it's
- already been counted */
- if (ELF32_R_SYM(rela[i].r_info)
- == ELF32_R_SYM(rela[j].r_info)
- && rela[i].r_addend == rela[j].r_addend)
- break;
- }
- if (j == i) ret++;
- }
- return ret;
-}
-
-/* Get the potential trampolines size required of the init and
- non-init sections */
-static unsigned long get_plt_size(const Elf32_Ehdr *hdr,
- const Elf32_Shdr *sechdrs,
- const char *secstrings,
- int is_init)
-{
- unsigned long ret = 0;
- unsigned i;
-
- /* Everything marked ALLOC (this includes the exported
- symbols) */
- for (i = 1; i < hdr->e_shnum; i++) {
- /* If it's called *.init*, and we're not init, we're
- not interested */
- if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
- != is_init)
- continue;
-
- if (sechdrs[i].sh_type == SHT_RELA) {
- DEBUGP("Found relocations in section %u\n", i);
- DEBUGP("Ptr: %p. Number: %u\n",
- (void *)hdr + sechdrs[i].sh_offset,
- sechdrs[i].sh_size / sizeof(Elf32_Rela));
- ret += count_relocs((void *)hdr
- + sechdrs[i].sh_offset,
- sechdrs[i].sh_size
- / sizeof(Elf32_Rela))
- * sizeof(struct v850_plt_entry);
- }
- }
-
- return ret;
-}
-
-int module_frob_arch_sections(Elf32_Ehdr *hdr,
- Elf32_Shdr *sechdrs,
- char *secstrings,
- struct module *me)
-{
- unsigned int i;
-
- /* Find .plt and .pltinit sections */
- for (i = 0; i < hdr->e_shnum; i++) {
- if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0)
- me->arch.init_plt_section = i;
- else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0)
- me->arch.core_plt_section = i;
- }
- if (!me->arch.core_plt_section || !me->arch.init_plt_section) {
- printk("Module doesn't contain .plt or .plt.init sections.\n");
- return -ENOEXEC;
- }
-
- /* Override their sizes */
- sechdrs[me->arch.core_plt_section].sh_size
- = get_plt_size(hdr, sechdrs, secstrings, 0);
- sechdrs[me->arch.init_plt_section].sh_size
- = get_plt_size(hdr, sechdrs, secstrings, 1);
- return 0;
-}
-
-int apply_relocate (Elf32_Shdr *sechdrs, const char *strtab,
- unsigned int symindex, unsigned int relsec,
- struct module *mod)
-{
- printk ("Barf\n");
- return -ENOEXEC;
-}
-
-/* Set up a trampoline in the PLT to bounce us to the distant function */
-static uint32_t do_plt_call (void *location, Elf32_Addr val,
- Elf32_Shdr *sechdrs, struct module *mod)
-{
- struct v850_plt_entry *entry;
- /* Instructions used to do the indirect jump. */
- uint32_t tramp[2];
-
- /* We have to trash a register, so we assume that any control
- transfer more than 21-bits away must be a function call
- (so we can use a call-clobbered register). */
- tramp[0] = 0x0621 + ((val & 0xffff) << 16); /* mov sym, r1 ... */
- tramp[1] = ((val >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
-
- /* Init, or core PLT? */
- if (location >= mod->module_core
- && location < mod->module_core + mod->core_size)
- entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
- else
- entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
-
- /* Find this entry, or if that fails, the next avail. entry */
- while (entry->tramp[0])
- if (entry->tramp[0] == tramp[0] && entry->tramp[1] == tramp[1])
- return (uint32_t)entry;
- else
- entry++;
-
- entry->tramp[0] = tramp[0];
- entry->tramp[1] = tramp[1];
-
- return (uint32_t)entry;
-}
-
-int apply_relocate_add (Elf32_Shdr *sechdrs, const char *strtab,
- unsigned int symindex, unsigned int relsec,
- struct module *mod)
-{
- unsigned int i;
- Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
-
- DEBUGP ("Applying relocate section %u to %u\n", relsec,
- sechdrs[relsec].sh_info);
-
- for (i = 0; i < sechdrs[relsec].sh_size / sizeof (*rela); i++) {
- /* This is where to make the change */
- uint32_t *loc
- = ((void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
- + rela[i].r_offset);
- /* This is the symbol it is referring to. Note that all
- undefined symbols have been resolved. */
- Elf32_Sym *sym
- = ((Elf32_Sym *)sechdrs[symindex].sh_addr
- + ELF32_R_SYM (rela[i].r_info));
- uint32_t val = sym->st_value + rela[i].r_addend;
-
- switch (ELF32_R_TYPE (rela[i].r_info)) {
- case R_V850_32:
- /* We write two shorts instead of a long because even
- 32-bit insns only need half-word alignment, but
- 32-bit data writes need to be long-word aligned. */
- val += ((uint16_t *)loc)[0];
- val += ((uint16_t *)loc)[1] << 16;
- ((uint16_t *)loc)[0] = val & 0xffff;
- ((uint16_t *)loc)[1] = (val >> 16) & 0xffff;
- break;
-
- case R_V850_22_PCREL:
- /* Maybe jump indirectly via a PLT table entry. */
- if ((int32_t)(val - (uint32_t)loc) > 0x1fffff
- || (int32_t)(val - (uint32_t)loc) < -0x200000)
- val = do_plt_call (loc, val, sechdrs, mod);
-
- val -= (uint32_t)loc;
-
- /* We write two shorts instead of a long because
- even 32-bit insns only need half-word alignment,
- but 32-bit data writes need to be long-word
- aligned. */
- ((uint16_t *)loc)[0] =
- (*(uint16_t *)loc & 0xffc0) /* opcode + reg */
- | ((val >> 16) & 0xffc03f); /* offs high */
- ((uint16_t *)loc)[1] =
- (val & 0xffff); /* offs low */
- break;
-
- default:
- printk (KERN_ERR "module %s: Unknown reloc: %u\n",
- mod->name, ELF32_R_TYPE (rela[i].r_info));
- return -ENOEXEC;
- }
- }
-
- return 0;
-}
-
-void
-module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/v850/kernel/process.c b/arch/v850/kernel/process.c
deleted file mode 100644
index e4a4b8e7d5a..00000000000
--- a/arch/v850/kernel/process.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * arch/v850/kernel/process.c -- Arch-dependent process handling
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/reboot.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-
-void (*pm_power_off)(void) = NULL;
-EXPORT_SYMBOL(pm_power_off);
-
-extern void ret_from_fork (void);
-
-
-/* The idle loop. */
-static void default_idle (void)
-{
- while (! need_resched ())
- asm ("halt; nop; nop; nop; nop; nop" ::: "cc");
-}
-
-void (*idle)(void) = default_idle;
-
-/*
- * The idle thread. There's no useful work to be
- * done, so just try to conserve power and have a
- * low exit latency (ie sit in a loop waiting for
- * somebody to say that they'd like to reschedule)
- */
-void cpu_idle (void)
-{
- /* endless idle loop with no priority at all */
- while (1) {
- while (!need_resched())
- (*idle) ();
-
- preempt_enable_no_resched();
- schedule();
- preempt_disable();
- }
-}
-
-/*
- * This is the mechanism for creating a new kernel thread.
- *
- * NOTE! Only a kernel-only process (ie the swapper or direct descendants who
- * haven't done an "execve()") should use this: it will work within a system
- * call from a "real" process, but the process memory space will not be free'd
- * until both the parent and the child have exited.
- */
-int kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
-{
- register mm_segment_t fs = get_fs ();
- register unsigned long syscall asm (SYSCALL_NUM);
- register unsigned long arg0 asm (SYSCALL_ARG0);
- register unsigned long ret asm (SYSCALL_RET);
-
- set_fs (KERNEL_DS);
-
- /* Clone this thread. Note that we don't pass the clone syscall's
- second argument -- it's ignored for calls from kernel mode (the
- child's SP is always set to the top of the kernel stack). */
- arg0 = flags | CLONE_VM;
- syscall = __NR_clone;
- asm volatile ("trap " SYSCALL_SHORT_TRAP
- : "=r" (ret), "=r" (syscall)
- : "1" (syscall), "r" (arg0)
- : SYSCALL_SHORT_CLOBBERS);
-
- if (ret == 0) {
- /* In child thread, call FN and exit. */
- arg0 = (*fn) (arg);
- syscall = __NR_exit;
- asm volatile ("trap " SYSCALL_SHORT_TRAP
- : "=r" (ret), "=r" (syscall)
- : "1" (syscall), "r" (arg0)
- : SYSCALL_SHORT_CLOBBERS);
- }
-
- /* In parent. */
- set_fs (fs);
-
- return ret;
-}
-
-void flush_thread (void)
-{
- set_fs (USER_DS);
-}
-
-int copy_thread (int nr, unsigned long clone_flags,
- unsigned long stack_start, unsigned long stack_size,
- struct task_struct *p, struct pt_regs *regs)
-{
- /* Start pushing stuff from the top of the child's kernel stack. */
- unsigned long orig_ksp = task_tos(p);
- unsigned long ksp = orig_ksp;
- /* We push two `state save' stack fames (see entry.S) on the new
- kernel stack:
- 1) The innermost one is what switch_thread would have
- pushed, and is used when we context switch to the child
- thread for the first time. It's set up to return to
- ret_from_fork in entry.S.
- 2) The outermost one (nearest the top) is what a syscall
- trap would have pushed, and is set up to return to the
- same location as the parent thread, but with a return
- value of 0. */
- struct pt_regs *child_switch_regs, *child_trap_regs;
-
- /* Trap frame. */
- ksp -= STATE_SAVE_SIZE;
- child_trap_regs = (struct pt_regs *)(ksp + STATE_SAVE_PT_OFFSET);
- /* Switch frame. */
- ksp -= STATE_SAVE_SIZE;
- child_switch_regs = (struct pt_regs *)(ksp + STATE_SAVE_PT_OFFSET);
-
- /* First copy parent's register state to child. */
- *child_switch_regs = *regs;
- *child_trap_regs = *regs;
-
- /* switch_thread returns to the restored value of the lp
- register (r31), so we make that the place where we want to
- jump when the child thread begins running. */
- child_switch_regs->gpr[GPR_LP] = (v850_reg_t)ret_from_fork;
-
- if (regs->kernel_mode)
- /* Since we're returning to kernel-mode, make sure the child's
- stored kernel stack pointer agrees with what the actual
- stack pointer will be at that point (the trap return code
- always restores the SP, even when returning to
- kernel-mode). */
- child_trap_regs->gpr[GPR_SP] = orig_ksp;
- else
- /* Set the child's user-mode stack-pointer (the name
- `stack_start' is a misnomer, it's just the initial SP
- value). */
- child_trap_regs->gpr[GPR_SP] = stack_start;
-
- /* Thread state for the child (everything else is on the stack). */
- p->thread.ksp = ksp;
-
- return 0;
-}
-
-/*
- * sys_execve() executes a new program.
- */
-int sys_execve (char *name, char **argv, char **envp, struct pt_regs *regs)
-{
- char *filename = getname (name);
- int error = PTR_ERR (filename);
-
- if (! IS_ERR (filename)) {
- error = do_execve (filename, argv, envp, regs);
- putname (filename);
- }
-
- return error;
-}
-
-
-/*
- * These bracket the sleeping functions..
- */
-#define first_sched ((unsigned long)__sched_text_start)
-#define last_sched ((unsigned long)__sched_text_end)
-
-unsigned long get_wchan (struct task_struct *p)
-{
-#if 0 /* Barf. Figure out the stack-layout later. XXX */
- unsigned long fp, pc;
- int count = 0;
-
- if (!p || p == current || p->state == TASK_RUNNING)
- return 0;
-
- pc = thread_saved_pc (p);
-
- /* This quite disgusting function walks up the stack, following
- saved return address, until it something that's out of bounds
- (as defined by `first_sched' and `last_sched'). It then
- returns the last PC that was in-bounds. */
- do {
- if (fp < stack_page + sizeof (struct task_struct) ||
- fp >= 8184+stack_page)
- return 0;
- pc = ((unsigned long *)fp)[1];
- if (pc < first_sched || pc >= last_sched)
- return pc;
- fp = *(unsigned long *) fp;
- } while (count++ < 16);
-#endif
-
- return 0;
-}
diff --git a/arch/v850/kernel/procfs.c b/arch/v850/kernel/procfs.c
deleted file mode 100644
index e433cde789b..00000000000
--- a/arch/v850/kernel/procfs.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * arch/v850/kernel/procfs.c -- Introspection functions for /proc filesystem
- *
- * Copyright (C) 2001,02 NEC Corporation
- * Copyright (C) 2001,02 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include "mach.h"
-
-static int cpuinfo_print (struct seq_file *m, void *v)
-{
- extern unsigned long loops_per_jiffy;
-
- seq_printf (m, "CPU-Family: v850\nCPU-Arch: %s\n", CPU_ARCH);
-
-#ifdef CPU_MODEL_LONG
- seq_printf (m, "CPU-Model: %s (%s)\n", CPU_MODEL, CPU_MODEL_LONG);
-#else
- seq_printf (m, "CPU-Model: %s\n", CPU_MODEL);
-#endif
-
-#ifdef CPU_CLOCK_FREQ
- seq_printf (m, "CPU-Clock: %ld (%ld MHz)\n",
- (long)CPU_CLOCK_FREQ,
- (long)CPU_CLOCK_FREQ / 1000000);
-#endif
-
- seq_printf (m, "BogoMips: %lu.%02lu\n",
- loops_per_jiffy/(500000/HZ),
- (loops_per_jiffy/(5000/HZ)) % 100);
-
-#ifdef PLATFORM_LONG
- seq_printf (m, "Platform: %s (%s)\n", PLATFORM, PLATFORM_LONG);
-#elif defined (PLATFORM)
- seq_printf (m, "Platform: %s\n", PLATFORM);
-#endif
-
- return 0;
-}
-
-static void *cpuinfo_start (struct seq_file *m, loff_t *pos)
-{
- return *pos < NR_CPUS ? ((void *) 0x12345678) : NULL;
-}
-
-static void *cpuinfo_next (struct seq_file *m, void *v, loff_t *pos)
-{
- ++*pos;
- return cpuinfo_start (m, pos);
-}
-
-static void cpuinfo_stop (struct seq_file *m, void *v)
-{
-}
-
-const struct seq_operations cpuinfo_op = {
- .start = cpuinfo_start,
- .next = cpuinfo_next,
- .stop = cpuinfo_stop,
- .show = cpuinfo_print
-};
diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c
deleted file mode 100644
index a458ac941b2..00000000000
--- a/arch/v850/kernel/ptrace.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * arch/v850/kernel/ptrace.c -- `ptrace' system call
- *
- * Copyright (C) 2002,03,04 NEC Electronics Corporation
- * Copyright (C) 2002,03,04 Miles Bader <miles@gnu.org>
- *
- * Derived from arch/mips/kernel/ptrace.c:
- *
- * Copyright (C) 1992 Ross Biro
- * Copyright (C) Linus Torvalds
- * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
- * Copyright (C) 1996 David S. Miller
- * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999 MIPS Technologies, Inc.
- *
- * 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/kernel.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/signal.h>
-
-#include <asm/errno.h>
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-
-/* Returns the address where the register at REG_OFFS in P is stashed away. */
-static v850_reg_t *reg_save_addr (unsigned reg_offs, struct task_struct *t)
-{
- struct pt_regs *regs;
-
- /* Three basic cases:
-
- (1) A register normally saved before calling the scheduler, is
- available in the kernel entry pt_regs structure at the top
- of the kernel stack. The kernel trap/irq exit path takes
- care to save/restore almost all registers for ptrace'd
- processes.
-
- (2) A call-clobbered register, where the process P entered the
- kernel via [syscall] trap, is not stored anywhere; that's
- OK, because such registers are not expected to be preserved
- when the trap returns anyway (so we don't actually bother to
- test for this case).
-
- (3) A few registers not used at all by the kernel, and so
- normally never saved except by context-switches, are in the
- context switch state. */
-
- if (reg_offs == PT_CTPC || reg_offs == PT_CTPSW || reg_offs == PT_CTBP)
- /* Register saved during context switch. */
- regs = thread_saved_regs (t);
- else
- /* Register saved during kernel entry (or not available). */
- regs = task_pt_regs (t);
-
- return (v850_reg_t *)((char *)regs + reg_offs);
-}
-
-/* Set the bits SET and clear the bits CLEAR in the v850e DIR
- (`debug information register'). Returns the new value of DIR. */
-static inline v850_reg_t set_dir (v850_reg_t set, v850_reg_t clear)
-{
- register v850_reg_t rval asm ("r10");
- register v850_reg_t arg0 asm ("r6") = set;
- register v850_reg_t arg1 asm ("r7") = clear;
-
- /* The dbtrap handler has exactly this functionality when called
- from kernel mode. 0xf840 is a `dbtrap' insn. */
- asm (".short 0xf840" : "=r" (rval) : "r" (arg0), "r" (arg1));
-
- return rval;
-}
-
-/* Makes sure hardware single-stepping is (globally) enabled.
- Returns true if successful. */
-static inline int enable_single_stepping (void)
-{
- static int enabled = 0; /* Remember whether we already did it. */
- if (! enabled) {
- /* Turn on the SE (`single-step enable') bit, 0x100, in the
- DIR (`debug information register'). This may fail if a
- processor doesn't support it or something. We also try
- to clear bit 0x40 (`INI'), which is necessary to use the
- debug stuff on the v850e2; on the v850e, clearing 0x40
- shouldn't cause any problem. */
- v850_reg_t dir = set_dir (0x100, 0x40);
- /* Make sure it really got set. */
- if (dir & 0x100)
- enabled = 1;
- }
- return enabled;
-}
-
-/* Try to set CHILD's single-step flag to VAL. Returns true if successful. */
-static int set_single_step (struct task_struct *t, int val)
-{
- v850_reg_t *psw_addr = reg_save_addr(PT_PSW, t);
- if (val) {
- /* Make sure single-stepping is enabled. */
- if (! enable_single_stepping ())
- return 0;
- /* Set T's single-step flag. */
- *psw_addr |= 0x800;
- } else
- *psw_addr &= ~0x800;
- return 1;
-}
-
-long arch_ptrace(struct task_struct *child, long request, long addr, long data)
-{
- int rval;
-
- switch (request) {
- unsigned long val;
-
- case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA:
- rval = generic_ptrace_peekdata(child, addr, data);
- goto out;
-
- case PTRACE_POKETEXT: /* write the word at location addr. */
- case PTRACE_POKEDATA:
- rval = generic_ptrace_pokedata(child, addr, data);
- goto out;
-
- /* Read/write the word at location ADDR in the registers. */
- case PTRACE_PEEKUSR:
- case PTRACE_POKEUSR:
- rval = 0;
- if (addr >= PT_SIZE && request == PTRACE_PEEKUSR) {
- /* Special requests that don't actually correspond
- to offsets in struct pt_regs. */
- if (addr == PT_TEXT_ADDR)
- val = child->mm->start_code;
- else if (addr == PT_DATA_ADDR)
- val = child->mm->start_data;
- else if (addr == PT_TEXT_LEN)
- val = child->mm->end_code
- - child->mm->start_code;
- else
- rval = -EIO;
- } else if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) {
- v850_reg_t *reg_addr = reg_save_addr(addr, child);
- if (request == PTRACE_PEEKUSR)
- val = *reg_addr;
- else
- *reg_addr = data;
- } else
- rval = -EIO;
-
- if (rval == 0 && request == PTRACE_PEEKUSR)
- rval = put_user (val, (unsigned long *)data);
- goto out;
-
- /* Continue and stop at next (return from) syscall */
- case PTRACE_SYSCALL:
- /* Restart after a signal. */
- case PTRACE_CONT:
- /* Execute a single instruction. */
- case PTRACE_SINGLESTEP:
- rval = -EIO;
- if (!valid_signal(data))
- break;
-
- /* Turn CHILD's single-step flag on or off. */
- if (! set_single_step (child, request == PTRACE_SINGLESTEP))
- break;
-
- if (request == PTRACE_SYSCALL)
- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- else
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-
- child->exit_code = data;
- wake_up_process(child);
- rval = 0;
- break;
-
- /*
- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.
- */
- case PTRACE_KILL:
- rval = 0;
- if (child->exit_state == EXIT_ZOMBIE) /* already dead */
- break;
- child->exit_code = SIGKILL;
- wake_up_process(child);
- break;
-
- case PTRACE_DETACH: /* detach a process that was attached. */
- set_single_step (child, 0); /* Clear single-step flag */
- rval = ptrace_detach(child, data);
- break;
-
- default:
- rval = -EIO;
- goto out;
- }
- out:
- return rval;
-}
-
-asmlinkage void syscall_trace(void)
-{
- if (!test_thread_flag(TIF_SYSCALL_TRACE))
- return;
- if (!(current->ptrace & PT_PTRACED))
- return;
- /* The 0x80 provides a way for the tracing parent to distinguish
- between a syscall stop and SIGTRAP delivery */
- ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
- ? 0x80 : 0));
- /*
- * this isn't the same as continuing with a signal, but it will do
- * for normal use. strace only continues with a signal if the
- * stopping signal is not SIGTRAP. -brl
- */
- if (current->exit_code) {
- send_sig(current->exit_code, current, 1);
- current->exit_code = 0;
- }
-}
-
-void ptrace_disable (struct task_struct *child)
-{
- /* nothing to do */
-}
diff --git a/arch/v850/kernel/rte_cb.c b/arch/v850/kernel/rte_cb.c
deleted file mode 100644
index 43018e1edeb..00000000000
--- a/arch/v850/kernel/rte_cb.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * include/asm-v850/rte_cb.c -- Midas lab RTE-CB series of evaluation boards
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/fs.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-
-#include <asm/machdep.h>
-#include <asm/v850e_uart.h>
-
-#include "mach.h"
-
-static void led_tick (void);
-
-/* LED access routines. */
-extern unsigned read_leds (int pos, char *buf, int len);
-extern unsigned write_leds (int pos, const char *buf, int len);
-
-#ifdef CONFIG_RTE_CB_MULTI
-extern void multi_init (void);
-#endif
-
-
-void __init rte_cb_early_init (void)
-{
- v850e_intc_disable_irqs ();
-
-#ifdef CONFIG_RTE_CB_MULTI
- multi_init ();
-#endif
-}
-
-void __init mach_setup (char **cmdline)
-{
-#ifdef CONFIG_RTE_MB_A_PCI
- /* Probe for Mother-A, and print a message if we find it. */
- *(volatile unsigned long *)MB_A_SRAM_ADDR = 0xDEADBEEF;
- if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0xDEADBEEF) {
- *(volatile unsigned long *)MB_A_SRAM_ADDR = 0x12345678;
- if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0x12345678)
- printk (KERN_INFO
- " NEC SolutionGear/Midas lab"
- " RTE-MOTHER-A motherboard\n");
- }
-#endif /* CONFIG_RTE_MB_A_PCI */
-
- mach_tick = led_tick;
-}
-
-void machine_restart (char *__unused)
-{
-#ifdef CONFIG_RESET_GUARD
- disable_reset_guard ();
-#endif
- asm ("jmp r0"); /* Jump to the reset vector. */
-}
-
-/* This says `HALt.' in LEDese. */
-static unsigned char halt_leds_msg[] = { 0x76, 0x77, 0x38, 0xF8 };
-
-void machine_halt (void)
-{
-#ifdef CONFIG_RESET_GUARD
- disable_reset_guard ();
-#endif
-
- /* Ignore all interrupts. */
- local_irq_disable ();
-
- /* Write a little message. */
- write_leds (0, halt_leds_msg, sizeof halt_leds_msg);
-
- /* Really halt. */
- for (;;)
- asm ("halt; nop; nop; nop; nop; nop");
-}
-
-void machine_power_off (void)
-{
- machine_halt ();
-}
-
-
-/* Animated LED display for timer tick. */
-
-#define TICK_UPD_FREQ 6
-static int tick_frames[][10] = {
- { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, -1 },
- { 0x63, 0x5c, -1 },
- { 0x5c, 0x00, -1 },
- { 0x63, 0x00, -1 },
- { -1 }
-};
-
-static void led_tick ()
-{
- static unsigned counter = 0;
-
- if (++counter == (HZ / TICK_UPD_FREQ)) {
- /* Which frame we're currently displaying for each digit. */
- static unsigned frame_nums[LED_NUM_DIGITS] = { 0 };
- /* Display image. */
- static unsigned char image[LED_NUM_DIGITS] = { 0 };
- unsigned char prev_image[LED_NUM_DIGITS];
- int write_to_leds = 1; /* true if we should actually display */
- int digit;
-
- /* We check to see if the physical LEDs contains what we last
- wrote to them; if not, we suppress display (this is so that
- users can write to the LEDs, and not have their output
- overwritten). As a special case, we start writing again if
- all the LEDs are blank, or our display image is all zeros
- (indicating that this is the initial update, when the actual
- LEDs might contain random data). */
- read_leds (0, prev_image, LED_NUM_DIGITS);
- for (digit = 0; digit < LED_NUM_DIGITS; digit++)
- if (image[digit] != prev_image[digit]
- && image[digit] && prev_image[digit])
- {
- write_to_leds = 0;
- break;
- }
-
- /* Update display image. */
- for (digit = 0;
- digit < LED_NUM_DIGITS && tick_frames[digit][0] >= 0;
- digit++)
- {
- int frame = tick_frames[digit][frame_nums[digit]];
- if (frame < 0) {
- image[digit] = tick_frames[digit][0];
- frame_nums[digit] = 1;
- } else {
- image[digit] = frame;
- frame_nums[digit]++;
- break;
- }
- }
-
- if (write_to_leds)
- /* Write the display image to the physical LEDs. */
- write_leds (0, image, LED_NUM_DIGITS);
-
- counter = 0;
- }
-}
-
-
-/* Mother-A interrupts. */
-
-#ifdef CONFIG_RTE_GBUS_INT
-
-#define L GBUS_INT_PRIORITY_LOW
-#define M GBUS_INT_PRIORITY_MEDIUM
-#define H GBUS_INT_PRIORITY_HIGH
-
-static struct gbus_int_irq_init gbus_irq_inits[] = {
-#ifdef CONFIG_RTE_MB_A_PCI
- { "MB_A_LAN", IRQ_MB_A_LAN, 1, 1, L },
- { "MB_A_PCI1", IRQ_MB_A_PCI1(0), IRQ_MB_A_PCI1_NUM, 1, L },
- { "MB_A_PCI2", IRQ_MB_A_PCI2(0), IRQ_MB_A_PCI2_NUM, 1, L },
- { "MB_A_EXT", IRQ_MB_A_EXT(0), IRQ_MB_A_EXT_NUM, 1, L },
- { "MB_A_USB_OC",IRQ_MB_A_USB_OC(0), IRQ_MB_A_USB_OC_NUM, 1, L },
- { "MB_A_PCMCIA_OC",IRQ_MB_A_PCMCIA_OC, 1, 1, L },
-#endif
- { 0 }
-};
-#define NUM_GBUS_IRQ_INITS (ARRAY_SIZE(gbus_irq_inits) - 1)
-
-static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS];
-
-#endif /* CONFIG_RTE_GBUS_INT */
-
-
-void __init rte_cb_init_irqs (void)
-{
-#ifdef CONFIG_RTE_GBUS_INT
- gbus_int_init_irqs ();
- gbus_int_init_irq_types (gbus_irq_inits, gbus_hw_itypes);
-#endif /* CONFIG_RTE_GBUS_INT */
-}
diff --git a/arch/v850/kernel/rte_cb_leds.c b/arch/v850/kernel/rte_cb_leds.c
deleted file mode 100644
index aa47ab1dcd8..00000000000
--- a/arch/v850/kernel/rte_cb_leds.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * include/asm-v850/rte_cb_leds.c -- Midas lab RTE-CB board LED device support
- *
- * Copyright (C) 2002,03 NEC Electronics Corporation
- * Copyright (C) 2002,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-
-#include <asm/uaccess.h>
-
-#define LEDS_MINOR 169 /* Minor device number, using misc major. */
-
-/* The actual LED hardware is write-only, so we hold the contents here too. */
-static unsigned char leds_image[LED_NUM_DIGITS] = { 0 };
-
-/* Spinlock protecting the above leds. */
-static DEFINE_SPINLOCK(leds_lock);
-
-/* Common body of LED read/write functions, checks POS and LEN for
- correctness, declares a variable using IMG_DECL, initialized pointing at
- the POS position in the LED image buffer, and and iterates COPY_EXPR
- until BUF is equal to the last buffer position; finally, sets LEN to be
- the amount actually copied. IMG should be a variable declaration
- (without an initializer or a terminating semicolon); POS, BUF, and LEN
- should all be simple variables. */
-#define DO_LED_COPY(img_decl, pos, buf, len, copy_expr) \
-do { \
- if (pos > LED_NUM_DIGITS) \
- len = 0; \
- else { \
- if (pos + len > LED_NUM_DIGITS) \
- len = LED_NUM_DIGITS - pos; \
- \
- if (len > 0) { \
- unsigned long _flags; \
- const char *_end = buf + len; \
- img_decl = &leds_image[pos]; \
- \
- spin_lock_irqsave (leds_lock, _flags); \
- do \
- (copy_expr); \
- while (buf != _end); \
- spin_unlock_irqrestore (leds_lock, _flags); \
- } \
- } \
-} while (0)
-
-/* Read LEN bytes from LEDs at position POS, into BUF.
- Returns actual amount read. */
-unsigned read_leds (unsigned pos, char *buf, unsigned len)
-{
- DO_LED_COPY (const char *img, pos, buf, len, *buf++ = *img++);
- return len;
-}
-
-/* Write LEN bytes to LEDs at position POS, from BUF.
- Returns actual amount written. */
-unsigned write_leds (unsigned pos, const char *buf, unsigned len)
-{
- /* We write the actual LED values backwards, because
- increasing memory addresses reflect LEDs right-to-left. */
- volatile char *led = &LED (LED_NUM_DIGITS - pos - 1);
- /* We invert the value written to the hardware, because 1 = off,
- and 0 = on. */
- DO_LED_COPY (char *img, pos, buf, len,
- *led-- = 0xFF ^ (*img++ = *buf++));
- return len;
-}
-
-
-/* Device functions. */
-
-static ssize_t leds_dev_read (struct file *file, char *buf, size_t len,
- loff_t *pos)
-{
- char temp_buf[LED_NUM_DIGITS];
- len = read_leds (*pos, temp_buf, len);
- if (copy_to_user (buf, temp_buf, len))
- return -EFAULT;
- *pos += len;
- return len;
-}
-
-static ssize_t leds_dev_write (struct file *file, const char *buf, size_t len,
- loff_t *pos)
-{
- char temp_buf[LED_NUM_DIGITS];
- if (copy_from_user (temp_buf, buf, min_t(size_t, len, LED_NUM_DIGITS)))
- return -EFAULT;
- len = write_leds (*pos, temp_buf, len);
- *pos += len;
- return len;
-}
-
-static loff_t leds_dev_lseek (struct file *file, loff_t offs, int whence)
-{
- if (whence == 1)
- offs += file->f_pos; /* relative */
- else if (whence == 2)
- offs += LED_NUM_DIGITS; /* end-relative */
-
- if (offs < 0 || offs > LED_NUM_DIGITS)
- return -EINVAL;
-
- file->f_pos = offs;
-
- return 0;
-}
-
-static const struct file_operations leds_fops = {
- .read = leds_dev_read,
- .write = leds_dev_write,
- .llseek = leds_dev_lseek
-};
-
-static struct miscdevice leds_miscdev = {
- .name = "leds",
- .minor = LEDS_MINOR,
- .fops = &leds_fops
-};
-
-int __init leds_dev_init (void)
-{
- return misc_register (&leds_miscdev);
-}
-
-__initcall (leds_dev_init);
diff --git a/arch/v850/kernel/rte_cb_multi.c b/arch/v850/kernel/rte_cb_multi.c
deleted file mode 100644
index 963d55ab34c..00000000000
--- a/arch/v850/kernel/rte_cb_multi.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * include/asm-v850/rte_multi.c -- Support for Multi debugger monitor ROM
- * on Midas lab RTE-CB series of evaluation boards
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/init.h>
-
-#include <asm/machdep.h>
-
-#define IRQ_ADDR(irq) (0x80 + (irq) * 0x10)
-
-/* A table of which interrupt vectors to install, since blindly
- installing all of them makes the debugger stop working. This is a
- list of offsets in the interrupt vector area; each entry means to
- copy that particular 16-byte vector. An entry less than zero ends
- the table. */
-static long multi_intv_install_table[] = {
- /* Trap vectors */
- 0x40, 0x50,
-
-#ifdef CONFIG_RTE_CB_MULTI_DBTRAP
- /* Illegal insn / dbtrap. These are used by multi, so only handle
- them if configured to do so. */
- 0x60,
-#endif
-
- /* GINT1 - GINT3 (note, not GINT0!) */
- IRQ_ADDR (IRQ_GINT(1)),
- IRQ_ADDR (IRQ_GINT(2)),
- IRQ_ADDR (IRQ_GINT(3)),
-
- /* Timer D interrupts (up to 4 timers) */
- IRQ_ADDR (IRQ_INTCMD(0)),
-#if IRQ_INTCMD_NUM > 1
- IRQ_ADDR (IRQ_INTCMD(1)),
-#if IRQ_INTCMD_NUM > 2
- IRQ_ADDR (IRQ_INTCMD(2)),
-#if IRQ_INTCMD_NUM > 3
- IRQ_ADDR (IRQ_INTCMD(3)),
-#endif
-#endif
-#endif
-
- /* UART interrupts (up to 3 channels) */
- IRQ_ADDR (IRQ_INTSER (0)), /* err */
- IRQ_ADDR (IRQ_INTSR (0)), /* rx */
- IRQ_ADDR (IRQ_INTST (0)), /* tx */
-#if IRQ_INTSR_NUM > 1
- IRQ_ADDR (IRQ_INTSER (1)), /* err */
- IRQ_ADDR (IRQ_INTSR (1)), /* rx */
- IRQ_ADDR (IRQ_INTST (1)), /* tx */
-#if IRQ_INTSR_NUM > 2
- IRQ_ADDR (IRQ_INTSER (2)), /* err */
- IRQ_ADDR (IRQ_INTSR (2)), /* rx */
- IRQ_ADDR (IRQ_INTST (2)), /* tx */
-#endif
-#endif
-
- -1
-};
-
-/* Early initialization for kernel using Multi debugger ROM monitor. */
-void __init multi_init (void)
-{
- /* We're using the Multi debugger monitor, so we have to install
- the interrupt vectors. The monitor doesn't allow them to be
- initially downloaded into their final destination because
- it's in the monitor's scratch-RAM area. Unfortunately, Multi
- also doesn't deal correctly with ELF sections where the LMA
- and VMA differ -- it just ignores the LMA -- so we can't use
- that feature to work around the problem. What we do instead
- is just put the interrupt vectors into a normal section, and
- do the necessary copying and relocation here. Since the
- interrupt vector basically only contains `jr' instructions
- and no-ops, it's not that hard. */
- extern unsigned long _intv_load_start, _intv_start;
- register unsigned long *src = &_intv_load_start;
- register unsigned long *dst = (unsigned long *)INTV_BASE;
- register unsigned long jr_fixup = (char *)&_intv_start - (char *)dst;
- register long *ii;
-
- /* Copy interrupt vectors as instructed by multi_intv_install_table. */
- for (ii = multi_intv_install_table; *ii >= 0; ii++) {
- /* Copy 16-byte interrupt vector at offset *ii. */
- int boffs;
- for (boffs = 0; boffs < 0x10; boffs += sizeof *src) {
- /* Copy a single word, fixing up the jump offs
- if it's a `jr' instruction. */
- int woffs = (*ii + boffs) / sizeof *src;
- unsigned long word = src[woffs];
-
- if ((word & 0xFC0) == 0x780) {
- /* A `jr' insn, fix up its offset (and yes, the
- weird half-word swapping is intentional). */
- unsigned short hi = word & 0xFFFF;
- unsigned short lo = word >> 16;
- unsigned long udisp22
- = lo + ((hi & 0x3F) << 16);
- long disp22 = (long)(udisp22 << 10) >> 10;
-
- disp22 += jr_fixup;
-
- hi = ((disp22 >> 16) & 0x3F) | 0x780;
- lo = disp22 & 0xFFFF;
-
- word = hi + (lo << 16);
- }
-
- dst[woffs] = word;
- }
- }
-}
diff --git a/arch/v850/kernel/rte_ma1_cb-rom.ld b/arch/v850/kernel/rte_ma1_cb-rom.ld
deleted file mode 100644
index 87b618f8253..00000000000
--- a/arch/v850/kernel/rte_ma1_cb-rom.ld
+++ /dev/null
@@ -1,14 +0,0 @@
-/* Linker script for the Midas labs RTE-V850E/MA1-CB evaluation board
- (CONFIG_RTE_CB_MA1), with kernel in ROM. */
-
-MEMORY {
- ROM : ORIGIN = 0x00000000, LENGTH = 0x00100000
- /* 1MB of SRAM. This memory is mirrored 4 times. */
- SRAM : ORIGIN = SRAM_ADDR, LENGTH = SRAM_SIZE
- /* 32MB of SDRAM. */
- SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-SECTIONS {
- ROMK_SECTIONS(ROM, SRAM)
-}
diff --git a/arch/v850/kernel/rte_ma1_cb.c b/arch/v850/kernel/rte_ma1_cb.c
deleted file mode 100644
index 08abf3d5f8d..00000000000
--- a/arch/v850/kernel/rte_ma1_cb.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * arch/v850/kernel/rte_ma1_cb.c -- Midas labs RTE-V850E/MA1-CB board
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/ma1.h>
-#include <asm/rte_ma1_cb.h>
-#include <asm/v850e_timer_c.h>
-
-#include "mach.h"
-
-
-/* SRAM and SDRAM are almost contiguous (with a small hole in between;
- see mach_reserve_bootmem for details), so just use both as one big area. */
-#define RAM_START SRAM_ADDR
-#define RAM_END (SDRAM_ADDR + SDRAM_SIZE)
-
-
-void __init mach_early_init (void)
-{
- rte_cb_early_init ();
-}
-
-void __init mach_get_physical_ram (unsigned long *ram_start,
- unsigned long *ram_len)
-{
- *ram_start = RAM_START;
- *ram_len = RAM_END - RAM_START;
-}
-
-void __init mach_reserve_bootmem ()
-{
-#ifdef CONFIG_RTE_CB_MULTI
- /* Prevent the kernel from touching the monitor's scratch RAM. */
- reserve_bootmem(MON_SCRATCH_ADDR, MON_SCRATCH_SIZE,
- BOOTMEM_DEFAULT);
-#endif
-
- /* The space between SRAM and SDRAM is filled with duplicate
- images of SRAM. Prevent the kernel from using them. */
- reserve_bootmem (SRAM_ADDR + SRAM_SIZE,
- SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE),
- BOOTMEM_DEFAULT);
-}
-
-void mach_gettimeofday (struct timespec *tv)
-{
- tv->tv_sec = 0;
- tv->tv_nsec = 0;
-}
-
-/* Called before configuring an on-chip UART. */
-void rte_ma1_cb_uart_pre_configure (unsigned chan,
- unsigned cflags, unsigned baud)
-{
- /* The RTE-MA1-CB connects some general-purpose I/O pins on the
- CPU to the RTS/CTS lines of UART 0's serial connection.
- I/O pins P42 and P43 are RTS and CTS respectively. */
- if (chan == 0) {
- /* Put P42 & P43 in I/O port mode. */
- MA_PORT4_PMC &= ~0xC;
- /* Make P42 an output, and P43 an input. */
- MA_PORT4_PM = (MA_PORT4_PM & ~0xC) | 0x8;
- }
-
- /* Do pre-configuration for the actual UART. */
- ma_uart_pre_configure (chan, cflags, baud);
-}
-
-void __init mach_init_irqs (void)
-{
- unsigned tc;
-
- /* Initialize interrupts. */
- ma_init_irqs ();
- rte_cb_init_irqs ();
-
- /* Use falling-edge-sensitivity for interrupts . */
- V850E_TIMER_C_SESC (0) &= ~0xC;
- V850E_TIMER_C_SESC (1) &= ~0xF;
-
- /* INTP000-INTP011 are shared with `Timer C', so we have to set
- up Timer C to pass them through as raw interrupts. */
- for (tc = 0; tc < 2; tc++)
- /* Turn on the timer. */
- V850E_TIMER_C_TMCC0 (tc) |= V850E_TIMER_C_TMCC0_CAE;
-
- /* Make sure the relevant port0/port1 pins are assigned
- interrupt duty. We used INTP001-INTP011 (don't screw with
- INTP000 because the monitor uses it). */
- MA_PORT0_PMC |= 0x4; /* P02 (INTP001) in IRQ mode. */
- MA_PORT1_PMC |= 0x6; /* P11 (INTP010) & P12 (INTP011) in IRQ mode.*/
-}
diff --git a/arch/v850/kernel/rte_ma1_cb.ld b/arch/v850/kernel/rte_ma1_cb.ld
deleted file mode 100644
index c8e16d16be4..00000000000
--- a/arch/v850/kernel/rte_ma1_cb.ld
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Linker script for the Midas labs RTE-V850E/MA1-CB evaluation board
- (CONFIG_RTE_CB_MA1), with kernel in SDRAM, under Multi debugger. */
-
-MEMORY {
- /* 1MB of SRAM; we can't use the last 32KB, because it's used by
- the monitor scratch-RAM. This memory is mirrored 4 times. */
- SRAM : ORIGIN = SRAM_ADDR, LENGTH = (SRAM_SIZE - MON_SCRATCH_SIZE)
- /* Monitor scratch RAM; only the interrupt vectors should go here. */
- MRAM : ORIGIN = MON_SCRATCH_ADDR, LENGTH = MON_SCRATCH_SIZE
- /* 32MB of SDRAM. */
- SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-#ifdef CONFIG_RTE_CB_MA1_KSRAM
-# define KRAM SRAM
-#else
-# define KRAM SDRAM
-#endif
-
-SECTIONS {
- /* We can't use RAMK_KRAM_CONTENTS because that puts the whole
- kernel in a single ELF segment, and the Multi debugger (which
- we use to load the kernel) appears to have bizarre problems
- dealing with it. */
-
- .text : {
- __kram_start = . ;
- TEXT_CONTENTS
- } > KRAM
-
- .data : {
- DATA_CONTENTS
- BSS_CONTENTS
- RAMK_INIT_CONTENTS
- __kram_end = . ;
- BOOTMAP_CONTENTS
-
- /* The address at which the interrupt vectors are initially
- loaded by the loader. We can't load the interrupt vectors
- directly into their target location, because the monitor
- ROM for the GHS Multi debugger barfs if we try.
- Unfortunately, Multi also doesn't deal correctly with ELF
- sections where the LMA and VMA differ (it just ignores the
- LMA), so we can't use that feature to work around the
- problem! What we do instead is just put the interrupt
- vectors into a normal section, and have the
- `mach_early_init' function for Midas boards do the
- necessary copying and relocation at runtime (this section
- basically only contains `jr' instructions, so it's not
- that hard). */
- . = ALIGN (0x10) ;
- __intv_load_start = . ;
- INTV_CONTENTS
- } > KRAM
-
- .root ALIGN (4096) : { ROOT_FS_CONTENTS } > SDRAM
-}
diff --git a/arch/v850/kernel/rte_mb_a_pci.c b/arch/v850/kernel/rte_mb_a_pci.c
deleted file mode 100644
index 687e367d8b6..00000000000
--- a/arch/v850/kernel/rte_mb_a_pci.c
+++ /dev/null
@@ -1,819 +0,0 @@
-/*
- * arch/v850/kernel/mb_a_pci.c -- PCI support for Midas lab RTE-MOTHER-A board
- *
- * Copyright (C) 2001,02,03,05 NEC Electronics Corporation
- * Copyright (C) 2001,02,03,05 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/pci.h>
-
-#include <asm/machdep.h>
-
-/* __nomods_init is like __devinit, but is a no-op when modules are enabled.
- This is used by some routines that can be called either during boot
- or by a module. */
-#ifdef CONFIG_MODULES
-#define __nomods_init /*nothing*/
-#else
-#define __nomods_init __devinit
-#endif
-
-/* PCI devices on the Mother-A board can only do DMA to/from the MB SRAM
- (the RTE-V850E/MA1-CB cpu board doesn't support PCI access to
- CPU-board memory), and since linux DMA buffers are allocated in
- normal kernel memory, we basically have to copy DMA blocks around
- (this is like a `bounce buffer'). When a DMA block is `mapped', we
- allocate an identically sized block in MB SRAM, and if we're doing
- output to the device, copy the CPU-memory block to the MB-SRAM block.
- When an active block is `unmapped', we will copy the block back to
- CPU memory if necessary, and then deallocate the MB SRAM block.
- Ack. */
-
-/* Where the motherboard SRAM is in the PCI-bus address space (the
- first 512K of it is also mapped at PCI address 0). */
-#define PCI_MB_SRAM_ADDR 0x800000
-
-/* Convert CPU-view MB SRAM address to/from PCI-view addresses of the
- same memory. */
-#define MB_SRAM_TO_PCI(mb_sram_addr) \
- ((dma_addr_t)mb_sram_addr - MB_A_SRAM_ADDR + PCI_MB_SRAM_ADDR)
-#define PCI_TO_MB_SRAM(pci_addr) \
- (void *)(pci_addr - PCI_MB_SRAM_ADDR + MB_A_SRAM_ADDR)
-
-static void pcibios_assign_resources (void);
-
-struct mb_pci_dev_irq {
- unsigned dev; /* PCI device number */
- unsigned irq_base; /* First IRQ */
- unsigned query_pin; /* True if we should read the device's
- Interrupt Pin info, and allocate
- interrupt IRQ_BASE + PIN. */
-};
-
-/* PCI interrupts are mapped statically to GBUS interrupts. */
-static struct mb_pci_dev_irq mb_pci_dev_irqs[] = {
- /* Motherboard SB82558 ethernet controller */
- { 10, IRQ_MB_A_LAN, 0 },
- /* PCI slot 1 */
- { 8, IRQ_MB_A_PCI1(0), 1 },
- /* PCI slot 2 */
- { 9, IRQ_MB_A_PCI2(0), 1 }
-};
-#define NUM_MB_PCI_DEV_IRQS ARRAY_SIZE(mb_pci_dev_irqs)
-
-
-/* PCI configuration primitives. */
-
-#define CONFIG_DMCFGA(bus, devfn, offs) \
- (0x80000000 \
- | ((offs) & ~0x3) \
- | ((devfn) << 8) \
- | ((bus)->number << 16))
-
-static int
-mb_pci_read (struct pci_bus *bus, unsigned devfn, int offs, int size, u32 *rval)
-{
- u32 addr;
- int flags;
-
- local_irq_save (flags);
-
- MB_A_PCI_PCICR = 0x7;
- MB_A_PCI_DMCFGA = CONFIG_DMCFGA (bus, devfn, offs);
-
- addr = MB_A_PCI_IO_ADDR + (offs & 0x3);
-
- switch (size) {
- case 1: *rval = *(volatile u8 *)addr; break;
- case 2: *rval = *(volatile u16 *)addr; break;
- case 4: *rval = *(volatile u32 *)addr; break;
- }
-
- if (MB_A_PCI_PCISR & 0x2000) {
- MB_A_PCI_PCISR = 0x2000;
- *rval = ~0;
- }
-
- MB_A_PCI_DMCFGA = 0;
-
- local_irq_restore (flags);
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-mb_pci_write (struct pci_bus *bus, unsigned devfn, int offs, int size, u32 val)
-{
- u32 addr;
- int flags;
-
- local_irq_save (flags);
-
- MB_A_PCI_PCICR = 0x7;
- MB_A_PCI_DMCFGA = CONFIG_DMCFGA (bus, devfn, offs);
-
- addr = MB_A_PCI_IO_ADDR + (offs & 0x3);
-
- switch (size) {
- case 1: *(volatile u8 *)addr = val; break;
- case 2: *(volatile u16 *)addr = val; break;
- case 4: *(volatile u32 *)addr = val; break;
- }
-
- if (MB_A_PCI_PCISR & 0x2000)
- MB_A_PCI_PCISR = 0x2000;
-
- MB_A_PCI_DMCFGA = 0;
-
- local_irq_restore (flags);
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops mb_pci_config_ops = {
- .read = mb_pci_read,
- .write = mb_pci_write,
-};
-
-
-/* PCI Initialization. */
-
-static struct pci_bus *mb_pci_bus = 0;
-
-/* Do initial PCI setup. */
-static int __devinit pcibios_init (void)
-{
- u32 id = MB_A_PCI_PCIHIDR;
- u16 vendor = id & 0xFFFF;
- u16 device = (id >> 16) & 0xFFFF;
-
- if (vendor == PCI_VENDOR_ID_PLX && device == PCI_DEVICE_ID_PLX_9080) {
- printk (KERN_INFO
- "PCI: PLX Technology PCI9080 HOST/PCI bridge\n");
-
- MB_A_PCI_PCICR = 0x147;
-
- MB_A_PCI_PCIBAR0 = 0x007FFF00;
- MB_A_PCI_PCIBAR1 = 0x0000FF00;
- MB_A_PCI_PCIBAR2 = 0x00800000;
-
- MB_A_PCI_PCILTR = 0x20;
-
- MB_A_PCI_PCIPBAM |= 0x3;
-
- MB_A_PCI_PCISR = ~0; /* Clear errors. */
-
- /* Reprogram the motherboard's IO/config address space,
- as we don't support the GCS7 address space that the
- default uses. */
-
- /* Significant address bits used for decoding PCI GCS5 space
- accesses. */
- MB_A_PCI_DMRR = ~(MB_A_PCI_MEM_SIZE - 1);
-
- /* I don't understand this, but the SolutionGear example code
- uses such an offset, and it doesn't work without it. XXX */
-#if GCS5_SIZE == 0x00800000
-#define GCS5_CFG_OFFS 0x00800000
-#else
-#define GCS5_CFG_OFFS 0
-#endif
-
- /* Address bit values for matching. Note that we have to give
- the address from the motherboard's point of view, which is
- different than the CPU's. */
- /* PCI memory space. */
- MB_A_PCI_DMLBAM = GCS5_CFG_OFFS + 0x0;
- /* PCI I/O space. */
- MB_A_PCI_DMLBAI =
- GCS5_CFG_OFFS + (MB_A_PCI_IO_ADDR - GCS5_ADDR);
-
- mb_pci_bus = pci_scan_bus (0, &mb_pci_config_ops, 0);
-
- pcibios_assign_resources ();
- } else
- printk (KERN_ERR "PCI: HOST/PCI bridge not found\n");
-
- return 0;
-}
-
-subsys_initcall (pcibios_init);
-
-char __devinit *pcibios_setup (char *option)
-{
- /* Don't handle any options. */
- return option;
-}
-
-
-int __nomods_init pcibios_enable_device (struct pci_dev *dev, int mask)
-{
- u16 cmd, old_cmd;
- int idx;
- struct resource *r;
-
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- old_cmd = cmd;
- for (idx = 0; idx < 6; idx++) {
- r = &dev->resource[idx];
- if (!r->start && r->end) {
- printk(KERN_ERR "PCI: Device %s not available because "
- "of resource collisions\n", pci_name(dev));
- return -EINVAL;
- }
- if (r->flags & IORESOURCE_IO)
- cmd |= PCI_COMMAND_IO;
- if (r->flags & IORESOURCE_MEM)
- cmd |= PCI_COMMAND_MEMORY;
- }
- if (cmd != old_cmd) {
- printk("PCI: Enabling device %s (%04x -> %04x)\n",
- pci_name(dev), old_cmd, cmd);
- pci_write_config_word(dev, PCI_COMMAND, cmd);
- }
- return 0;
-}
-
-
-/* Resource allocation. */
-static void __devinit pcibios_assign_resources (void)
-{
- struct pci_dev *dev = NULL;
- struct resource *r;
-
- for_each_pci_dev(dev) {
- unsigned di_num;
- unsigned class = dev->class >> 8;
-
- if (class && class != PCI_CLASS_BRIDGE_HOST) {
- unsigned r_num;
- for(r_num = 0; r_num < 6; r_num++) {
- r = &dev->resource[r_num];
- if (!r->start && r->end)
- pci_assign_resource (dev, r_num);
- }
- }
-
- /* Assign interrupts. */
- for (di_num = 0; di_num < NUM_MB_PCI_DEV_IRQS; di_num++) {
- struct mb_pci_dev_irq *di = &mb_pci_dev_irqs[di_num];
-
- if (di->dev == PCI_SLOT (dev->devfn)) {
- unsigned irq = di->irq_base;
-
- if (di->query_pin) {
- /* Find out which interrupt pin
- this device uses (each PCI
- slot has 4). */
- u8 irq_pin;
-
- pci_read_config_byte (dev,
- PCI_INTERRUPT_PIN,
- &irq_pin);
-
- if (irq_pin == 0)
- /* Doesn't use interrupts. */
- continue;
- else
- irq += irq_pin - 1;
- }
-
- pcibios_update_irq (dev, irq);
- }
- }
- }
-}
-
-void __devinit pcibios_update_irq (struct pci_dev *dev, int irq)
-{
- dev->irq = irq;
- pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq);
-}
-
-void __devinit
-pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
- struct resource *res)
-{
- unsigned long offset = 0;
-
- if (res->flags & IORESOURCE_IO) {
- offset = MB_A_PCI_IO_ADDR;
- } else if (res->flags & IORESOURCE_MEM) {
- offset = MB_A_PCI_MEM_ADDR;
- }
-
- region->start = res->start - offset;
- region->end = res->end - offset;
-}
-
-
-/* Stubs for things we don't use. */
-
-/* Called after each bus is probed, but before its children are examined. */
-void pcibios_fixup_bus(struct pci_bus *b)
-{
-}
-
-void
-pcibios_align_resource (void *data, struct resource *res,
- resource_size_t size, resource_size_t align)
-{
-}
-
-void pcibios_set_master (struct pci_dev *dev)
-{
-}
-
-
-/* Mother-A SRAM memory allocation. This is a simple first-fit allocator. */
-
-/* A memory free-list node. */
-struct mb_sram_free_area {
- void *mem;
- unsigned long size;
- struct mb_sram_free_area *next;
-};
-
-/* The tail of the free-list, which starts out containing all the SRAM. */
-static struct mb_sram_free_area mb_sram_free_tail = {
- (void *)MB_A_SRAM_ADDR, MB_A_SRAM_SIZE, 0
-};
-
-/* The free-list. */
-static struct mb_sram_free_area *mb_sram_free_areas = &mb_sram_free_tail;
-
-/* The free-list of free free-list nodes. (:-) */
-static struct mb_sram_free_area *mb_sram_free_free_areas = 0;
-
-/* Spinlock protecting the above globals. */
-static DEFINE_SPINLOCK(mb_sram_lock);
-
-/* Allocate a memory block at least SIZE bytes long in the Mother-A SRAM
- space. */
-static void *alloc_mb_sram (size_t size)
-{
- struct mb_sram_free_area *prev, *fa;
- unsigned long flags;
- void *mem = 0;
-
- spin_lock_irqsave (mb_sram_lock, flags);
-
- /* Look for a free area that can contain SIZE bytes. */
- for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next)
- if (fa->size >= size) {
- /* Found one! */
- mem = fa->mem;
-
- if (fa->size == size) {
- /* In fact, it fits exactly, so remove
- this node from the free-list. */
- if (prev)
- prev->next = fa->next;
- else
- mb_sram_free_areas = fa->next;
- /* Put it on the free-list-entry-free-list. */
- fa->next = mb_sram_free_free_areas;
- mb_sram_free_free_areas = fa;
- } else {
- /* FA is bigger than SIZE, so just
- reduce its size to account for this
- allocation. */
- fa->mem += size;
- fa->size -= size;
- }
-
- break;
- }
-
- spin_unlock_irqrestore (mb_sram_lock, flags);
-
- return mem;
-}
-
-/* Return the memory area MEM of size SIZE to the MB SRAM free pool. */
-static void free_mb_sram (void *mem, size_t size)
-{
- struct mb_sram_free_area *prev, *fa, *new_fa;
- unsigned long flags;
- void *end = mem + size;
-
- spin_lock_irqsave (mb_sram_lock, flags);
-
- retry:
- /* Find an adjacent free-list entry. */
- for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next)
- if (fa->mem == end) {
- /* FA is just after MEM, grow down to encompass it. */
- fa->mem = mem;
- fa->size += size;
- goto done;
- } else if (fa->mem + fa->size == mem) {
- struct mb_sram_free_area *next_fa = fa->next;
-
- /* FA is just before MEM, expand to encompass it. */
- fa->size += size;
-
- /* See if FA can now be merged with its successor. */
- if (next_fa && fa->mem + fa->size == next_fa->mem) {
- /* Yup; merge NEXT_FA's info into FA. */
- fa->size += next_fa->size;
- fa->next = next_fa->next;
- /* Free NEXT_FA. */
- next_fa->next = mb_sram_free_free_areas;
- mb_sram_free_free_areas = next_fa;
- }
- goto done;
- } else if (fa->mem > mem)
- /* We've reached the right spot in the free-list
- without finding an adjacent free-area, so add
- a new free area to hold mem. */
- break;
-
- /* Make a new free-list entry. */
-
- /* First, get a free-list entry. */
- if (! mb_sram_free_free_areas) {
- /* There are none, so make some. */
- void *block;
- size_t block_size = sizeof (struct mb_sram_free_area) * 8;
-
- /* Don't hold the lock while calling kmalloc (I'm not
- sure whether it would be a problem, since we use
- GFP_ATOMIC, but it makes me nervous). */
- spin_unlock_irqrestore (mb_sram_lock, flags);
-
- block = kmalloc (block_size, GFP_ATOMIC);
- if (! block)
- panic ("free_mb_sram: can't allocate free-list entry");
-
- /* Now get the lock back. */
- spin_lock_irqsave (mb_sram_lock, flags);
-
- /* Add the new free free-list entries. */
- while (block_size > 0) {
- struct mb_sram_free_area *nfa = block;
- nfa->next = mb_sram_free_free_areas;
- mb_sram_free_free_areas = nfa;
- block += sizeof *nfa;
- block_size -= sizeof *nfa;
- }
-
- /* Since we dropped the lock to call kmalloc, the
- free-list could have changed, so retry from the
- beginning. */
- goto retry;
- }
-
- /* Remove NEW_FA from the free-list of free-list entries. */
- new_fa = mb_sram_free_free_areas;
- mb_sram_free_free_areas = new_fa->next;
-
- /* NEW_FA initially holds only MEM. */
- new_fa->mem = mem;
- new_fa->size = size;
-
- /* Insert NEW_FA in the free-list between PREV and FA. */
- new_fa->next = fa;
- if (prev)
- prev->next = new_fa;
- else
- mb_sram_free_areas = new_fa;
-
- done:
- spin_unlock_irqrestore (mb_sram_lock, flags);
-}
-
-
-/* Maintainence of CPU -> Mother-A DMA mappings. */
-
-struct dma_mapping {
- void *cpu_addr;
- void *mb_sram_addr;
- size_t size;
- struct dma_mapping *next;
-};
-
-/* A list of mappings from CPU addresses to MB SRAM addresses for active
- DMA blocks (that have been `granted' to the PCI device). */
-static struct dma_mapping *active_dma_mappings = 0;
-
-/* A list of free mapping objects. */
-static struct dma_mapping *free_dma_mappings = 0;
-
-/* Spinlock protecting the above globals. */
-static DEFINE_SPINLOCK(dma_mappings_lock);
-
-static struct dma_mapping *new_dma_mapping (size_t size)
-{
- unsigned long flags;
- struct dma_mapping *mapping;
- void *mb_sram_block = alloc_mb_sram (size);
-
- if (! mb_sram_block)
- return 0;
-
- spin_lock_irqsave (dma_mappings_lock, flags);
-
- if (! free_dma_mappings) {
- /* We're out of mapping structures, make more. */
- void *mblock;
- size_t mblock_size = sizeof (struct dma_mapping) * 8;
-
- /* Don't hold the lock while calling kmalloc (I'm not
- sure whether it would be a problem, since we use
- GFP_ATOMIC, but it makes me nervous). */
- spin_unlock_irqrestore (dma_mappings_lock, flags);
-
- mblock = kmalloc (mblock_size, GFP_ATOMIC);
- if (! mblock) {
- free_mb_sram (mb_sram_block, size);
- return 0;
- }
-
- /* Get the lock back. */
- spin_lock_irqsave (dma_mappings_lock, flags);
-
- /* Add the new mapping structures to the free-list. */
- while (mblock_size > 0) {
- struct dma_mapping *fm = mblock;
- fm->next = free_dma_mappings;
- free_dma_mappings = fm;
- mblock += sizeof *fm;
- mblock_size -= sizeof *fm;
- }
- }
-
- /* Get a mapping struct from the freelist. */
- mapping = free_dma_mappings;
- free_dma_mappings = mapping->next;
-
- /* Initialize the mapping. Other fields should be filled in by
- caller. */
- mapping->mb_sram_addr = mb_sram_block;
- mapping->size = size;
-
- /* Add it to the list of active mappings. */
- mapping->next = active_dma_mappings;
- active_dma_mappings = mapping;
-
- spin_unlock_irqrestore (dma_mappings_lock, flags);
-
- return mapping;
-}
-
-static struct dma_mapping *find_dma_mapping (void *mb_sram_addr)
-{
- unsigned long flags;
- struct dma_mapping *mapping;
-
- spin_lock_irqsave (dma_mappings_lock, flags);
-
- for (mapping = active_dma_mappings; mapping; mapping = mapping->next)
- if (mapping->mb_sram_addr == mb_sram_addr) {
- spin_unlock_irqrestore (dma_mappings_lock, flags);
- return mapping;
- }
-
- panic ("find_dma_mapping: unmapped PCI DMA addr 0x%x",
- MB_SRAM_TO_PCI (mb_sram_addr));
-}
-
-static struct dma_mapping *deactivate_dma_mapping (void *mb_sram_addr)
-{
- unsigned long flags;
- struct dma_mapping *mapping, *prev;
-
- spin_lock_irqsave (dma_mappings_lock, flags);
-
- for (prev = 0, mapping = active_dma_mappings;
- mapping;
- prev = mapping, mapping = mapping->next)
- {
- if (mapping->mb_sram_addr == mb_sram_addr) {
- /* This is the MAPPING; deactivate it. */
- if (prev)
- prev->next = mapping->next;
- else
- active_dma_mappings = mapping->next;
-
- spin_unlock_irqrestore (dma_mappings_lock, flags);
-
- return mapping;
- }
- }
-
- panic ("deactivate_dma_mapping: unmapped PCI DMA addr 0x%x",
- MB_SRAM_TO_PCI (mb_sram_addr));
-}
-
-/* Return MAPPING to the freelist. */
-static inline void
-free_dma_mapping (struct dma_mapping *mapping)
-{
- unsigned long flags;
-
- free_mb_sram (mapping->mb_sram_addr, mapping->size);
-
- spin_lock_irqsave (dma_mappings_lock, flags);
-
- mapping->next = free_dma_mappings;
- free_dma_mappings = mapping;
-
- spin_unlock_irqrestore (dma_mappings_lock, flags);
-}
-
-
-/* Single PCI DMA mappings. */
-
-/* `Grant' to PDEV the memory block at CPU_ADDR, for doing DMA. The
- 32-bit PCI bus mastering address to use is returned. the device owns
- this memory until either pci_unmap_single or pci_dma_sync_single is
- performed. */
-dma_addr_t
-pci_map_single (struct pci_dev *pdev, void *cpu_addr, size_t size, int dir)
-{
- struct dma_mapping *mapping = new_dma_mapping (size);
-
- if (! mapping)
- return 0;
-
- mapping->cpu_addr = cpu_addr;
-
- if (dir == PCI_DMA_BIDIRECTIONAL || dir == PCI_DMA_TODEVICE)
- memcpy (mapping->mb_sram_addr, cpu_addr, size);
-
- return MB_SRAM_TO_PCI (mapping->mb_sram_addr);
-}
-
-/* Return to the CPU the PCI DMA memory block previously `granted' to
- PDEV, at DMA_ADDR. */
-void pci_unmap_single (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
- int dir)
-{
- void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr);
- struct dma_mapping *mapping = deactivate_dma_mapping (mb_sram_addr);
-
- if (size != mapping->size)
- panic ("pci_unmap_single: size (%d) doesn't match"
- " size of mapping at PCI DMA addr 0x%x (%d)\n",
- size, dma_addr, mapping->size);
-
- /* Copy back the DMA'd contents if necessary. */
- if (dir == PCI_DMA_BIDIRECTIONAL || dir == PCI_DMA_FROMDEVICE)
- memcpy (mapping->cpu_addr, mb_sram_addr, size);
-
- /* Return mapping to the freelist. */
- free_dma_mapping (mapping);
-}
-
-/* Make physical memory consistent for a single streaming mode DMA
- translation after a transfer.
-
- If you perform a pci_map_single() but wish to interrogate the
- buffer using the cpu, yet do not wish to teardown the PCI dma
- mapping, you must call this function before doing so. At the next
- point you give the PCI dma address back to the card, you must first
- perform a pci_dma_sync_for_device, and then the device again owns
- the buffer. */
-void
-pci_dma_sync_single_for_cpu (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
- int dir)
-{
- void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr);
- struct dma_mapping *mapping = find_dma_mapping (mb_sram_addr);
-
- /* Synchronize the DMA buffer with the CPU buffer if necessary. */
- if (dir == PCI_DMA_FROMDEVICE)
- memcpy (mapping->cpu_addr, mb_sram_addr, size);
- else if (dir == PCI_DMA_TODEVICE)
- ; /* nothing to do */
- else
- panic("pci_dma_sync_single: unsupported sync dir: %d", dir);
-}
-
-void
-pci_dma_sync_single_for_device (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
- int dir)
-{
- void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr);
- struct dma_mapping *mapping = find_dma_mapping (mb_sram_addr);
-
- /* Synchronize the DMA buffer with the CPU buffer if necessary. */
- if (dir == PCI_DMA_FROMDEVICE)
- ; /* nothing to do */
- else if (dir == PCI_DMA_TODEVICE)
- memcpy (mb_sram_addr, mapping->cpu_addr, size);
- else
- panic("pci_dma_sync_single: unsupported sync dir: %d", dir);
-}
-
-
-/* Scatter-gather PCI DMA mappings. */
-
-/* Do multiple DMA mappings at once. */
-int
-pci_map_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len, int dir)
-{
- BUG ();
- return 0;
-}
-
-/* Unmap multiple DMA mappings at once. */
-void
-pci_unmap_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len,int dir)
-{
- BUG ();
-}
-
-/* Make physical memory consistent for a set of streaming mode DMA
- translations after a transfer. The same as pci_dma_sync_single_* but
- for a scatter-gather list, same rules and usage. */
-
-void
-pci_dma_sync_sg_for_cpu (struct pci_dev *dev,
- struct scatterlist *sg, int sg_len,
- int dir)
-{
- BUG ();
-}
-
-void
-pci_dma_sync_sg_for_device (struct pci_dev *dev,
- struct scatterlist *sg, int sg_len,
- int dir)
-{
- BUG ();
-}
-
-
-/* PCI mem mapping. */
-
-/* Allocate and map kernel buffer using consistent mode DMA for PCI
- device. Returns non-NULL cpu-view pointer to the buffer if
- successful and sets *DMA_ADDR to the pci side dma address as well,
- else DMA_ADDR is undefined. */
-void *
-pci_alloc_consistent (struct pci_dev *pdev, size_t size, dma_addr_t *dma_addr)
-{
- void *mb_sram_mem = alloc_mb_sram (size);
- if (mb_sram_mem)
- *dma_addr = MB_SRAM_TO_PCI (mb_sram_mem);
- return mb_sram_mem;
-}
-
-/* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must
- be values that were returned from pci_alloc_consistent. SIZE must be
- the same as what as passed into pci_alloc_consistent. References to
- the memory and mappings associated with CPU_ADDR or DMA_ADDR past
- this call are illegal. */
-void
-pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr,
- dma_addr_t dma_addr)
-{
- void *mb_sram_mem = PCI_TO_MB_SRAM (dma_addr);
- free_mb_sram (mb_sram_mem, size);
-}
-
-
-/* iomap/iomap */
-
-void __iomem *pci_iomap (struct pci_dev *dev, int bar, unsigned long max)
-{
- resource_size_t start = pci_resource_start (dev, bar);
- resource_size_t len = pci_resource_len (dev, bar);
-
- if (!start || len == 0)
- return 0;
-
- /* None of the ioremap functions actually do anything, other than
- re-casting their argument, so don't bother differentiating them. */
- return ioremap (start, len);
-}
-
-void pci_iounmap (struct pci_dev *dev, void __iomem *addr)
-{
- /* nothing */
-}
-
-
-/* symbol exports (for modules) */
-
-EXPORT_SYMBOL (pci_map_single);
-EXPORT_SYMBOL (pci_unmap_single);
-EXPORT_SYMBOL (pci_alloc_consistent);
-EXPORT_SYMBOL (pci_free_consistent);
-EXPORT_SYMBOL (pci_dma_sync_single_for_cpu);
-EXPORT_SYMBOL (pci_dma_sync_single_for_device);
-EXPORT_SYMBOL (pci_iomap);
-EXPORT_SYMBOL (pci_iounmap);
diff --git a/arch/v850/kernel/rte_me2_cb.c b/arch/v850/kernel/rte_me2_cb.c
deleted file mode 100644
index 46803d48dff..00000000000
--- a/arch/v850/kernel/rte_me2_cb.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * arch/v850/kernel/rte_me2_cb.c -- Midas labs RTE-V850E/ME2-CB board
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-#include <linux/fs.h>
-#include <linux/major.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/me2.h>
-#include <asm/rte_me2_cb.h>
-#include <asm/machdep.h>
-#include <asm/v850e_intc.h>
-#include <asm/v850e_cache.h>
-#include <asm/irq.h>
-
-#include "mach.h"
-
-extern unsigned long *_intv_start;
-extern unsigned long *_intv_end;
-
-/* LED access routines. */
-extern unsigned read_leds (int pos, char *buf, int len);
-extern unsigned write_leds (int pos, const char *buf, int len);
-
-
-/* SDRAM are almost contiguous (with a small hole in between;
- see mach_reserve_bootmem for details), so just use both as one big area. */
-#define RAM_START SDRAM_ADDR
-#define RAM_END (SDRAM_ADDR + SDRAM_SIZE)
-
-
-void __init mach_get_physical_ram (unsigned long *ram_start,
- unsigned long *ram_len)
-{
- *ram_start = RAM_START;
- *ram_len = RAM_END - RAM_START;
-}
-
-void mach_gettimeofday (struct timespec *tv)
-{
- tv->tv_sec = 0;
- tv->tv_nsec = 0;
-}
-
-/* Called before configuring an on-chip UART. */
-void rte_me2_cb_uart_pre_configure (unsigned chan,
- unsigned cflags, unsigned baud)
-{
- /* The RTE-V850E/ME2-CB connects some general-purpose I/O
- pins on the CPU to the RTS/CTS lines of UARTB channel 0's
- serial connection.
- I/O pins P21 and P22 are RTS and CTS respectively. */
- if (chan == 0) {
- /* Put P21 & P22 in I/O port mode. */
- ME2_PORT2_PMC &= ~0x6;
- /* Make P21 and output, and P22 an input. */
- ME2_PORT2_PM = (ME2_PORT2_PM & ~0xC) | 0x4;
- }
-
- me2_uart_pre_configure (chan, cflags, baud);
-}
-
-void __init mach_init_irqs (void)
-{
- /* Initialize interrupts. */
- me2_init_irqs ();
- rte_me2_cb_init_irqs ();
-}
-
-#ifdef CONFIG_ROM_KERNEL
-/* Initialization for kernel in ROM. */
-static inline rom_kernel_init (void)
-{
- /* If the kernel is in ROM, we have to copy any initialized data
- from ROM into RAM. */
- extern unsigned long _data_load_start, _sdata, _edata;
- register unsigned long *src = &_data_load_start;
- register unsigned long *dst = &_sdata, *end = &_edata;
-
- while (dst != end)
- *dst++ = *src++;
-}
-#endif /* CONFIG_ROM_KERNEL */
-
-static void install_interrupt_vectors (void)
-{
- unsigned long *p1, *p2;
-
- ME2_IRAMM = 0x03; /* V850E/ME2 iRAM write mode */
-
- /* vector copy to iRAM */
- p1 = (unsigned long *)0; /* v85x vector start */
- p2 = (unsigned long *)&_intv_start;
- while (p2 < (unsigned long *)&_intv_end)
- *p1++ = *p2++;
-
- ME2_IRAMM = 0x00; /* V850E/ME2 iRAM read mode */
-}
-
-/* CompactFlash */
-
-static void cf_power_on (void)
-{
- /* CF card detected? */
- if (CB_CF_STS0 & 0x0030)
- return;
-
- CB_CF_REG0 = 0x0002; /* reest on */
- mdelay (10);
- CB_CF_REG0 = 0x0003; /* power on */
- mdelay (10);
- CB_CF_REG0 = 0x0001; /* reset off */
- mdelay (10);
-}
-
-static void cf_power_off (void)
-{
- CB_CF_REG0 = 0x0003; /* power on */
- mdelay (10);
- CB_CF_REG0 = 0x0002; /* reest on */
- mdelay (10);
-}
-
-void __init mach_early_init (void)
-{
- install_interrupt_vectors ();
-
- /* CS1 SDRAM instruction cache enable */
- v850e_cache_enable (0x04, 0x03, 0);
-
- rte_cb_early_init ();
-
- /* CompactFlash power on */
- cf_power_on ();
-
-#if defined (CONFIG_ROM_KERNEL)
- rom_kernel_init ();
-#endif
-}
-
-
-/* RTE-V850E/ME2-CB Programmable Interrupt Controller. */
-
-static struct cb_pic_irq_init cb_pic_irq_inits[] = {
- { "CB_EXTTM0", IRQ_CB_EXTTM0, 1, 1, 6 },
- { "CB_EXTSIO", IRQ_CB_EXTSIO, 1, 1, 6 },
- { "CB_TOVER", IRQ_CB_TOVER, 1, 1, 6 },
- { "CB_GINT0", IRQ_CB_GINT0, 1, 1, 6 },
- { "CB_USB", IRQ_CB_USB, 1, 1, 6 },
- { "CB_LANC", IRQ_CB_LANC, 1, 1, 6 },
- { "CB_USB_VBUS_ON", IRQ_CB_USB_VBUS_ON, 1, 1, 6 },
- { "CB_USB_VBUS_OFF", IRQ_CB_USB_VBUS_OFF, 1, 1, 6 },
- { "CB_EXTTM1", IRQ_CB_EXTTM1, 1, 1, 6 },
- { "CB_EXTTM2", IRQ_CB_EXTTM2, 1, 1, 6 },
- { 0 }
-};
-#define NUM_CB_PIC_IRQ_INITS (ARRAY_SIZE(cb_pic_irq_inits) - 1)
-
-static struct hw_interrupt_type cb_pic_hw_itypes[NUM_CB_PIC_IRQ_INITS];
-static unsigned char cb_pic_active_irqs = 0;
-
-void __init rte_me2_cb_init_irqs (void)
-{
- cb_pic_init_irq_types (cb_pic_irq_inits, cb_pic_hw_itypes);
-
- /* Initalize on board PIC1 (not PIC0) enable */
- CB_PIC_INT0M = 0x0000;
- CB_PIC_INT1M = 0x0000;
- CB_PIC_INTR = 0x0000;
- CB_PIC_INTEN |= CB_PIC_INT1EN;
-
- ME2_PORT2_PMC |= 0x08; /* INTP23/SCK1 mode */
- ME2_PORT2_PFC &= ~0x08; /* INTP23 mode */
- ME2_INTR(2) &= ~0x08; /* INTP23 falling-edge detect */
- ME2_INTF(2) &= ~0x08; /* " */
-
- rte_cb_init_irqs (); /* gbus &c */
-}
-
-
-/* Enable interrupt handling for interrupt IRQ. */
-void cb_pic_enable_irq (unsigned irq)
-{
- CB_PIC_INT1M |= 1 << (irq - CB_PIC_BASE_IRQ);
-}
-
-void cb_pic_disable_irq (unsigned irq)
-{
- CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ));
-}
-
-void cb_pic_shutdown_irq (unsigned irq)
-{
- cb_pic_disable_irq (irq);
-
- if (--cb_pic_active_irqs == 0)
- free_irq (IRQ_CB_PIC, 0);
-
- CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ));
-}
-
-static irqreturn_t cb_pic_handle_irq (int irq, void *dev_id,
- struct pt_regs *regs)
-{
- irqreturn_t rval = IRQ_NONE;
- unsigned status = CB_PIC_INTR;
- unsigned enable = CB_PIC_INT1M;
-
- /* Only pay attention to enabled interrupts. */
- status &= enable;
-
- CB_PIC_INTEN &= ~CB_PIC_INT1EN;
-
- if (status) {
- unsigned mask = 1;
-
- irq = CB_PIC_BASE_IRQ;
- do {
- /* There's an active interrupt, find out which one,
- and call its handler. */
- while (! (status & mask)) {
- irq++;
- mask <<= 1;
- }
- status &= ~mask;
-
- CB_PIC_INTR = mask;
-
- /* Recursively call handle_irq to handle it. */
- handle_irq (irq, regs);
- rval = IRQ_HANDLED;
- } while (status);
- }
-
- CB_PIC_INTEN |= CB_PIC_INT1EN;
-
- return rval;
-}
-
-
-static void irq_nop (unsigned irq) { }
-
-static unsigned cb_pic_startup_irq (unsigned irq)
-{
- int rval;
-
- if (cb_pic_active_irqs == 0) {
- rval = request_irq (IRQ_CB_PIC, cb_pic_handle_irq,
- IRQF_DISABLED, "cb_pic_handler", 0);
- if (rval != 0)
- return rval;
- }
-
- cb_pic_active_irqs++;
-
- cb_pic_enable_irq (irq);
-
- return 0;
-}
-
-/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
- INITS (which is terminated by an entry with the name field == 0). */
-void __init cb_pic_init_irq_types (struct cb_pic_irq_init *inits,
- struct hw_interrupt_type *hw_irq_types)
-{
- struct cb_pic_irq_init *init;
- for (init = inits; init->name; init++) {
- struct hw_interrupt_type *hwit = hw_irq_types++;
-
- hwit->typename = init->name;
-
- hwit->startup = cb_pic_startup_irq;
- hwit->shutdown = cb_pic_shutdown_irq;
- hwit->enable = cb_pic_enable_irq;
- hwit->disable = cb_pic_disable_irq;
- hwit->ack = irq_nop;
- hwit->end = irq_nop;
-
- /* Initialize kernel IRQ infrastructure for this interrupt. */
- init_irq_handlers(init->base, init->num, init->interval, hwit);
- }
-}
diff --git a/arch/v850/kernel/rte_me2_cb.ld b/arch/v850/kernel/rte_me2_cb.ld
deleted file mode 100644
index cf0766065ec..00000000000
--- a/arch/v850/kernel/rte_me2_cb.ld
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Linker script for the Midas labs RTE-V850E/ME2-CB evaluation board
- (CONFIG_RTE_CB_ME2), with kernel in SDRAM. */
-
-MEMORY {
- /* 128Kbyte of IRAM */
- IRAM : ORIGIN = 0x00000000, LENGTH = 0x00020000
-
- /* 32MB of SDRAM. */
- SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-#define KRAM SDRAM
-
-SECTIONS {
- .text : {
- __kram_start = . ;
- TEXT_CONTENTS
- INTV_CONTENTS /* copy to iRAM (0x0-0x620) */
- } > KRAM
-
- .data : {
- DATA_CONTENTS
- BSS_CONTENTS
- RAMK_INIT_CONTENTS
- __kram_end = . ;
- BOOTMAP_CONTENTS
- } > KRAM
-
- .root ALIGN (4096) : { ROOT_FS_CONTENTS } > SDRAM
-}
diff --git a/arch/v850/kernel/rte_nb85e_cb-multi.ld b/arch/v850/kernel/rte_nb85e_cb-multi.ld
deleted file mode 100644
index de347b4fffa..00000000000
--- a/arch/v850/kernel/rte_nb85e_cb-multi.ld
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Linker script for the Midas labs RTE-NB85E-CB evaluation board
- (CONFIG_RTE_CB_NB85E), with the Multi debugger ROM monitor . */
-
-MEMORY {
- /* 1MB of SRAM; we can't use the last 96KB, because it's used by
- the monitor scratch-RAM. This memory is mirrored 4 times. */
- SRAM : ORIGIN = SRAM_ADDR, LENGTH = (SRAM_SIZE - MON_SCRATCH_SIZE)
- /* Monitor scratch RAM; only the interrupt vectors should go here. */
- MRAM : ORIGIN = MON_SCRATCH_ADDR, LENGTH = MON_SCRATCH_SIZE
- /* 16MB of SDRAM. */
- SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-#ifdef CONFIG_RTE_CB_NB85E_KSRAM
-# define KRAM SRAM
-#else
-# define KRAM SDRAM
-#endif
-
-SECTIONS {
- /* We can't use RAMK_KRAM_CONTENTS because that puts the whole
- kernel in a single ELF segment, and the Multi debugger (which
- we use to load the kernel) appears to have bizarre problems
- dealing with it. */
-
- .text : {
- __kram_start = . ;
- TEXT_CONTENTS
- } > KRAM
-
- .data : {
- DATA_CONTENTS
- BSS_CONTENTS
- RAMK_INIT_CONTENTS
- __kram_end = . ;
- BOOTMAP_CONTENTS
-
- /* The address at which the interrupt vectors are initially
- loaded by the loader. We can't load the interrupt vectors
- directly into their target location, because the monitor
- ROM for the GHS Multi debugger barfs if we try.
- Unfortunately, Multi also doesn't deal correctly with ELF
- sections where the LMA and VMA differ (it just ignores the
- LMA), so we can't use that feature to work around the
- problem! What we do instead is just put the interrupt
- vectors into a normal section, and have the
- `mach_early_init' function for Midas boards do the
- necessary copying and relocation at runtime (this section
- basically only contains `jr' instructions, so it's not
- that hard). */
- . = ALIGN (0x10) ;
- __intv_load_start = . ;
- INTV_CONTENTS
- } > KRAM
-
- .root ALIGN (4096) : { ROOT_FS_CONTENTS } > SDRAM
-}
diff --git a/arch/v850/kernel/rte_nb85e_cb.c b/arch/v850/kernel/rte_nb85e_cb.c
deleted file mode 100644
index b4a045da5d7..00000000000
--- a/arch/v850/kernel/rte_nb85e_cb.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * arch/v850/kernel/rte_nb85e_cb.c -- Midas labs RTE-V850E/NB85E-CB board
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/v850e.h>
-#include <asm/rte_nb85e_cb.h>
-
-#include "mach.h"
-
-void __init mach_early_init (void)
-{
- /* Configure caching; some possible settings:
-
- BHC = 0x0000, DCC = 0x0000 -- all caching disabled
- BHC = 0x0040, DCC = 0x0000 -- SDRAM: icache only
- BHC = 0x0080, DCC = 0x0C00 -- SDRAM: write-back dcache only
- BHC = 0x00C0, DCC = 0x0C00 -- SDRAM: icache + write-back dcache
- BHC = 0x00C0, DCC = 0x0800 -- SDRAM: icache + write-thru dcache
-
- We can only cache SDRAM (we can't use cache SRAM because it's in
- the same memory region as the on-chip RAM and I/O space).
-
- Unfortunately, the dcache seems to be buggy, so we only use the
- icache for now. */
- v850e_cache_enable (0x0040 /*BHC*/, 0x0003 /*ICC*/, 0x0000 /*DCC*/);
-
- rte_cb_early_init ();
-}
-
-void __init mach_get_physical_ram (unsigned long *ram_start,
- unsigned long *ram_len)
-{
- /* We just use SDRAM here. */
- *ram_start = SDRAM_ADDR;
- *ram_len = SDRAM_SIZE;
-}
-
-void mach_gettimeofday (struct timespec *tv)
-{
- tv->tv_sec = 0;
- tv->tv_nsec = 0;
-}
-
-/* Called before configuring an on-chip UART. */
-void rte_nb85e_cb_uart_pre_configure (unsigned chan,
- unsigned cflags, unsigned baud)
-{
- /* The RTE-NB85E-CB connects some general-purpose I/O pins on the
- CPU to the RTS/CTS lines the UART's serial connection, as follows:
- P00 = CTS (in), P01 = DSR (in), P02 = RTS (out), P03 = DTR (out). */
-
- TEG_PORT0_PM = 0x03; /* P00 and P01 inputs, P02 and P03 outputs */
- TEG_PORT0_IO = 0x03; /* Accept input */
-
- /* Do pre-configuration for the actual UART. */
- teg_uart_pre_configure (chan, cflags, baud);
-}
-
-void __init mach_init_irqs (void)
-{
- teg_init_irqs ();
- rte_cb_init_irqs ();
-}
diff --git a/arch/v850/kernel/rte_nb85e_cb.ld b/arch/v850/kernel/rte_nb85e_cb.ld
deleted file mode 100644
index b672f484f08..00000000000
--- a/arch/v850/kernel/rte_nb85e_cb.ld
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Linker script for the Midas labs RTE-NB85E-CB evaluation board
- (CONFIG_RTE_CB_NB85E). */
-
-MEMORY {
- LOW : ORIGIN = 0x0, LENGTH = 0x00100000
- /* 1MB of SRAM This memory is mirrored 4 times. */
- SRAM : ORIGIN = SRAM_ADDR, LENGTH = SRAM_SIZE
- /* 16MB of SDRAM. */
- SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-#ifdef CONFIG_RTE_CB_NB85E_KSRAM
-# define KRAM SRAM
-#else
-# define KRAM SDRAM
-#endif
-
-SECTIONS {
- .intv : { INTV_CONTENTS } > LOW
- .sram : { RAMK_KRAM_CONTENTS } > KRAM
- .root : { ROOT_FS_CONTENTS } > SDRAM
-}
diff --git a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c
deleted file mode 100644
index a0a8456a843..00000000000
--- a/arch/v850/kernel/setup.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * arch/v850/kernel/setup.c -- Arch-dependent initialization functions
- *
- * 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/swap.h> /* we don't have swap, but for nr_free_pages */
-#include <linux/irq.h>
-#include <linux/reboot.h>
-#include <linux/personality.h>
-#include <linux/major.h>
-#include <linux/root_dev.h>
-#include <linux/mtd/mtd.h>
-#include <linux/init.h>
-
-#include <asm/irq.h>
-#include <asm/setup.h>
-
-#include "mach.h"
-
-/* These symbols are all defined in the linker map to delineate various
- statically allocated regions of memory. */
-
-extern char _intv_start, _intv_end;
-/* `kram' is only used if the kernel uses part of normal user RAM. */
-extern char _kram_start __attribute__ ((__weak__));
-extern char _kram_end __attribute__ ((__weak__));
-extern char _init_start, _init_end;
-extern char _bootmap;
-extern char _stext, _etext, _sdata, _edata, _sbss, _ebss;
-/* Many platforms use an embedded root image. */
-extern char _root_fs_image_start __attribute__ ((__weak__));
-extern char _root_fs_image_end __attribute__ ((__weak__));
-
-
-char __initdata command_line[COMMAND_LINE_SIZE];
-
-/* Memory not used by the kernel. */
-static unsigned long total_ram_pages;
-
-/* System RAM. */
-static unsigned long ram_start = 0, ram_len = 0;
-
-
-#define ADDR_TO_PAGE_UP(x) ((((unsigned long)x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define ADDR_TO_PAGE(x) (((unsigned long)x) >> PAGE_SHIFT)
-#define PAGE_TO_ADDR(x) (((unsigned long)x) << PAGE_SHIFT)
-
-static void init_mem_alloc (unsigned long ram_start, unsigned long ram_len);
-
-void set_mem_root (void *addr, size_t len, char *cmd_line);
-
-
-void __init setup_arch (char **cmdline)
-{
- /* Keep a copy of command line */
- *cmdline = command_line;
- memcpy (boot_command_line, command_line, COMMAND_LINE_SIZE);
- boot_command_line[COMMAND_LINE_SIZE - 1] = '\0';
-
- console_verbose ();
-
- init_mm.start_code = (unsigned long) &_stext;
- init_mm.end_code = (unsigned long) &_etext;
- init_mm.end_data = (unsigned long) &_edata;
- init_mm.brk = (unsigned long) &_kram_end;
-
- /* Find out what mem this machine has. */
- mach_get_physical_ram (&ram_start, &ram_len);
- /* ... and tell the kernel about it. */
- init_mem_alloc (ram_start, ram_len);
-
- printk (KERN_INFO "CPU: %s\nPlatform: %s\n",
- CPU_MODEL_LONG, PLATFORM_LONG);
-
- /* do machine-specific setups. */
- mach_setup (cmdline);
-
-#ifdef CONFIG_MTD
- if (!ROOT_DEV && &_root_fs_image_end > &_root_fs_image_start)
- set_mem_root (&_root_fs_image_start,
- &_root_fs_image_end - &_root_fs_image_start,
- *cmdline);
-#endif
-}
-
-void __init trap_init (void)
-{
-}
-
-#ifdef CONFIG_MTD
-
-/* From drivers/mtd/devices/slram.c */
-#define SLRAM_BLK_SZ 0x4000
-
-/* Set the root filesystem to be the given memory region.
- Some parameter may be appended to CMD_LINE. */
-void set_mem_root (void *addr, size_t len, char *cmd_line)
-{
- /* Some sort of idiocy in MTD means we must supply a length that's
- a multiple of SLRAM_BLK_SZ. We just round up the real length,
- as the file system shouldn't attempt to access anything beyond
- the end of the image anyway. */
- len = (((len - 1) + SLRAM_BLK_SZ) / SLRAM_BLK_SZ) * SLRAM_BLK_SZ;
-
- /* The only way to pass info to the MTD slram driver is via
- the command line. */
- if (*cmd_line) {
- cmd_line += strlen (cmd_line);
- *cmd_line++ = ' ';
- }
- sprintf (cmd_line, "slram=root,0x%x,+0x%x", (u32)addr, (u32)len);
-
- ROOT_DEV = MKDEV (MTD_BLOCK_MAJOR, 0);
-}
-#endif
-
-
-static void irq_nop (unsigned irq) { }
-static unsigned irq_zero (unsigned irq) { return 0; }
-
-static void nmi_end (unsigned irq)
-{
- if (irq != IRQ_NMI (0)) {
- printk (KERN_CRIT "NMI %d is unrecoverable; restarting...",
- irq - IRQ_NMI (0));
- machine_restart (0);
- }
-}
-
-static struct hw_interrupt_type nmi_irq_type = {
- .typename = "NMI",
- .startup = irq_zero, /* startup */
- .shutdown = irq_nop, /* shutdown */
- .enable = irq_nop, /* enable */
- .disable = irq_nop, /* disable */
- .ack = irq_nop, /* ack */
- .end = nmi_end, /* end */
-};
-
-void __init init_IRQ (void)
-{
- init_irq_handlers (0, NUM_MACH_IRQS, 1, 0);
- init_irq_handlers (IRQ_NMI (0), NUM_NMIS, 1, &nmi_irq_type);
- mach_init_irqs ();
-}
-
-
-void __init mem_init (void)
-{
- max_mapnr = MAP_NR (ram_start + ram_len);
-
- num_physpages = ADDR_TO_PAGE (ram_len);
-
- total_ram_pages = free_all_bootmem ();
-
- printk (KERN_INFO
- "Memory: %luK/%luK available"
- " (%luK kernel code, %luK data)\n",
- PAGE_TO_ADDR (nr_free_pages()) / 1024,
- ram_len / 1024,
- ((unsigned long)&_etext - (unsigned long)&_stext) / 1024,
- ((unsigned long)&_ebss - (unsigned long)&_sdata) / 1024);
-}
-
-void free_initmem (void)
-{
- unsigned long ram_end = ram_start + ram_len;
- unsigned long start = PAGE_ALIGN ((unsigned long)(&_init_start));
-
- if (start >= ram_start && start < ram_end) {
- unsigned long addr;
- unsigned long end = PAGE_ALIGN ((unsigned long)(&_init_end));
-
- if (end > ram_end)
- end = ram_end;
-
- printk("Freeing unused kernel memory: %ldK freed\n",
- (end - start) / 1024);
-
- for (addr = start; addr < end; addr += PAGE_SIZE) {
- struct page *page = virt_to_page (addr);
- ClearPageReserved (page);
- init_page_count (page);
- __free_page (page);
- total_ram_pages++;
- }
- }
-}
-
-
-/* Initialize the `bootmem allocator'. RAM_START and RAM_LEN identify
- what RAM may be used. */
-static void __init
-init_bootmem_alloc (unsigned long ram_start, unsigned long ram_len)
-{
- /* The part of the kernel that's in the same managed RAM space
- used for general allocation. */
- unsigned long kram_start = (unsigned long)&_kram_start;
- unsigned long kram_end = (unsigned long)&_kram_end;
- /* End of the managed RAM space. */
- unsigned long ram_end = ram_start + ram_len;
- /* Address range of the interrupt vector table. */
- unsigned long intv_start = (unsigned long)&_intv_start;
- unsigned long intv_end = (unsigned long)&_intv_end;
- /* True if the interrupt vectors are in the managed RAM area. */
- int intv_in_ram = (intv_end > ram_start && intv_start < ram_end);
- /* True if the interrupt vectors are inside the kernel's RAM. */
- int intv_in_kram = (intv_end > kram_start && intv_start < kram_end);
- /* A pointer to an optional function that reserves platform-specific
- memory regions. We declare the pointer `volatile' to avoid gcc
- turning the call into a static call (the problem is that since
- it's a weak symbol, a static call may end up trying to reference
- the location 0x0, which is not always reachable). */
- void (*volatile mrb) (void) = mach_reserve_bootmem;
- /* The bootmem allocator's allocation bitmap. */
- unsigned long bootmap = (unsigned long)&_bootmap;
- unsigned long bootmap_len;
-
- /* Round bootmap location up to next page. */
- bootmap = PAGE_TO_ADDR (ADDR_TO_PAGE_UP (bootmap));
-
- /* Initialize bootmem allocator. */
- bootmap_len = init_bootmem_node (NODE_DATA (0),
- ADDR_TO_PAGE (bootmap),
- ADDR_TO_PAGE (PAGE_OFFSET),
- ADDR_TO_PAGE (ram_end));
-
- /* Now make the RAM actually allocatable (it starts out `reserved'). */
- free_bootmem (ram_start, ram_len);
-
- if (kram_end > kram_start)
- /* Reserve the RAM part of the kernel's address space, so it
- doesn't get allocated. */
- reserve_bootmem(kram_start, kram_end - kram_start,
- BOOTMEM_DEFAULT);
-
- if (intv_in_ram && !intv_in_kram)
- /* Reserve the interrupt vector space. */
- reserve_bootmem(intv_start, intv_end - intv_start,
- BOOTMEM_DEFAULT);
-
- if (bootmap >= ram_start && bootmap < ram_end)
- /* Reserve the bootmap space. */
- reserve_bootmem(bootmap, bootmap_len,
- BOOTMEM_DEFAULT);
-
- /* Reserve the memory used by the root filesystem image if it's
- in RAM. */
- if (&_root_fs_image_end > &_root_fs_image_start
- && (unsigned long)&_root_fs_image_start >= ram_start
- && (unsigned long)&_root_fs_image_start < ram_end)
- reserve_bootmem ((unsigned long)&_root_fs_image_start,
- &_root_fs_image_end - &_root_fs_image_start,
- BOOTMEM_DEFAULT);
-
- /* Let the platform-dependent code reserve some too. */
- if (mrb)
- (*mrb) ();
-}
-
-/* Tell the kernel about what RAM it may use for memory allocation. */
-static void __init
-init_mem_alloc (unsigned long ram_start, unsigned long ram_len)
-{
- unsigned i;
- unsigned long zones_size[MAX_NR_ZONES];
-
- init_bootmem_alloc (ram_start, ram_len);
-
- for (i = 0; i < MAX_NR_ZONES; i++)
- zones_size[i] = 0;
-
- /* We stuff all the memory into one area, which includes the
- initial gap from PAGE_OFFSET to ram_start. */
- zones_size[ZONE_DMA]
- = ADDR_TO_PAGE (ram_len + (ram_start - PAGE_OFFSET));
-
- /* The allocator is very picky about the address of the first
- allocatable page -- it must be at least as aligned as the
- maximum allocation -- so try to detect cases where it will get
- confused and signal them at compile time (this is a common
- problem when porting to a new platform with ). There is a
- similar runtime check in free_area_init_core. */
-#if ((PAGE_OFFSET >> PAGE_SHIFT) & ((1UL << (MAX_ORDER - 1)) - 1))
-#error MAX_ORDER is too large for given PAGE_OFFSET (use CONFIG_FORCE_MAX_ZONEORDER to change it)
-#endif
- NODE_DATA(0)->node_mem_map = NULL;
- free_area_init_node (0, NODE_DATA(0), zones_size,
- ADDR_TO_PAGE (PAGE_OFFSET), 0);
-}
-
-
-
-/* Taken from m68knommu */
-void show_mem(void)
-{
- unsigned long i;
- int free = 0, total = 0, reserved = 0, shared = 0;
- int cached = 0;
-
- printk(KERN_INFO "\nMem-info:\n");
- show_free_areas();
- i = max_mapnr;
- while (i-- > 0) {
- total++;
- if (PageReserved(mem_map+i))
- reserved++;
- else if (PageSwapCache(mem_map+i))
- cached++;
- else if (!page_count(mem_map+i))
- free++;
- else
- shared += page_count(mem_map+i) - 1;
- }
- printk(KERN_INFO "%d pages of RAM\n",total);
- printk(KERN_INFO "%d free pages\n",free);
- printk(KERN_INFO "%d reserved pages\n",reserved);
- printk(KERN_INFO "%d pages shared\n",shared);
- printk(KERN_INFO "%d pages swap cached\n",cached);
-}
diff --git a/arch/v850/kernel/signal.c b/arch/v850/kernel/signal.c
deleted file mode 100644
index bf166e7e762..00000000000
--- a/arch/v850/kernel/signal.c
+++ /dev/null
@@ -1,523 +0,0 @@
-/*
- * arch/v850/kernel/signal.c -- Signal handling
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
- * Copyright (C) 1999,2000,2002 Niibe Yutaka & Kaz Kojima
- * Copyright (C) 1991,1992 Linus Torvalds
- *
- * 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.
- *
- * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
- *
- * This file was derived from the sh version, arch/sh/kernel/signal.c
- */
-
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/wait.h>
-#include <linux/ptrace.h>
-#include <linux/unistd.h>
-#include <linux/stddef.h>
-#include <linux/personality.h>
-#include <linux/tty.h>
-
-#include <asm/ucontext.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/pgalloc.h>
-#include <asm/thread_info.h>
-#include <asm/cacheflush.h>
-
-#define DEBUG_SIG 0
-
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
-
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-asmlinkage int
-sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs)
-{
- sigset_t saveset;
-
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- regs->gpr[GPR_RVAL] = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(regs, &saveset))
- return -EINTR;
- }
-}
-
-asmlinkage int
-sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
- struct pt_regs *regs)
-{
- sigset_t saveset, newset;
-
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
-
- if (copy_from_user(&newset, unewset, sizeof(newset)))
- return -EFAULT;
- sigdelsetmask(&newset, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- regs->gpr[GPR_RVAL] = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(regs, &saveset))
- return -EINTR;
- }
-}
-
-asmlinkage int
-sys_sigaction(int sig, const struct old_sigaction *act,
- struct old_sigaction *oact)
-{
- struct k_sigaction new_ka, old_ka;
- int ret;
-
- if (act) {
- old_sigset_t mask;
- if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
- __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
- __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
- return -EFAULT;
- __get_user(new_ka.sa.sa_flags, &act->sa_flags);
- __get_user(mask, &act->sa_mask);
- siginitset(&new_ka.sa.sa_mask, mask);
- }
-
- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
- if (!ret && oact) {
- if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
- __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
- __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
- return -EFAULT;
- __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
- }
-
- return ret;
-}
-
-asmlinkage int
-sys_sigaltstack(const stack_t *uss, stack_t *uoss,
- struct pt_regs *regs)
-{
- return do_sigaltstack(uss, uoss, regs->gpr[GPR_SP]);
-}
-
-
-/*
- * Do a signal return; undo the signal stack.
- */
-
-struct sigframe
-{
- struct sigcontext sc;
- unsigned long extramask[_NSIG_WORDS-1];
- unsigned long tramp[2]; /* signal trampoline */
-};
-
-struct rt_sigframe
-{
- struct siginfo info;
- struct ucontext uc;
- unsigned long tramp[2]; /* signal trampoline */
-};
-
-static int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *rval_p)
-{
- unsigned int err = 0;
-
-#define COPY(x) err |= __get_user(regs->x, &sc->regs.x)
- COPY(gpr[0]); COPY(gpr[1]); COPY(gpr[2]); COPY(gpr[3]);
- COPY(gpr[4]); COPY(gpr[5]); COPY(gpr[6]); COPY(gpr[7]);
- COPY(gpr[8]); COPY(gpr[9]); COPY(gpr[10]); COPY(gpr[11]);
- COPY(gpr[12]); COPY(gpr[13]); COPY(gpr[14]); COPY(gpr[15]);
- COPY(gpr[16]); COPY(gpr[17]); COPY(gpr[18]); COPY(gpr[19]);
- COPY(gpr[20]); COPY(gpr[21]); COPY(gpr[22]); COPY(gpr[23]);
- COPY(gpr[24]); COPY(gpr[25]); COPY(gpr[26]); COPY(gpr[27]);
- COPY(gpr[28]); COPY(gpr[29]); COPY(gpr[30]); COPY(gpr[31]);
- COPY(pc); COPY(psw);
- COPY(ctpc); COPY(ctpsw); COPY(ctbp);
-#undef COPY
-
- return err;
-}
-
-asmlinkage int sys_sigreturn(struct pt_regs *regs)
-{
- struct sigframe *frame = (struct sigframe *)regs->gpr[GPR_SP];
- sigset_t set;
- int rval;
-
- if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
-
- if (__get_user(set.sig[0], &frame->sc.oldmask)
- || (_NSIG_WORDS > 1
- && __copy_from_user(&set.sig[1], &frame->extramask,
- sizeof(frame->extramask))))
- goto badframe;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- if (restore_sigcontext(regs, &frame->sc, &rval))
- goto badframe;
- return rval;
-
-badframe:
- force_sig(SIGSEGV, current);
- return 0;
-}
-
-asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
-{
- struct rt_sigframe *frame = (struct rt_sigframe *)regs->gpr[GPR_SP];
- sigset_t set;
- stack_t st;
- int rval;
-
- if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
-
- if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
- goto badframe;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
- goto badframe;
-
- if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
- goto badframe;
- /* It is more difficult to avoid calling this function than to
- call it and ignore errors. */
- do_sigaltstack(&st, NULL, regs->gpr[GPR_SP]);
-
- return rval;
-
-badframe:
- force_sig(SIGSEGV, current);
- return 0;
-}
-
-/*
- * Set up a signal frame.
- */
-
-static int
-setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
- unsigned long mask)
-{
- int err = 0;
-
-#define COPY(x) err |= __put_user(regs->x, &sc->regs.x)
- COPY(gpr[0]); COPY(gpr[1]); COPY(gpr[2]); COPY(gpr[3]);
- COPY(gpr[4]); COPY(gpr[5]); COPY(gpr[6]); COPY(gpr[7]);
- COPY(gpr[8]); COPY(gpr[9]); COPY(gpr[10]); COPY(gpr[11]);
- COPY(gpr[12]); COPY(gpr[13]); COPY(gpr[14]); COPY(gpr[15]);
- COPY(gpr[16]); COPY(gpr[17]); COPY(gpr[18]); COPY(gpr[19]);
- COPY(gpr[20]); COPY(gpr[21]); COPY(gpr[22]); COPY(gpr[23]);
- COPY(gpr[24]); COPY(gpr[25]); COPY(gpr[26]); COPY(gpr[27]);
- COPY(gpr[28]); COPY(gpr[29]); COPY(gpr[30]); COPY(gpr[31]);
- COPY(pc); COPY(psw);
- COPY(ctpc); COPY(ctpsw); COPY(ctbp);
-#undef COPY
-
- err |= __put_user(mask, &sc->oldmask);
-
- return err;
-}
-
-/*
- * Determine which stack to use..
- */
-static inline void *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
-{
- /* Default to using normal stack */
- unsigned long sp = regs->gpr[GPR_SP];
-
- if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
- sp = current->sas_ss_sp + current->sas_ss_size;
-
- return (void *)((sp - frame_size) & -8UL);
-}
-
-static void setup_frame(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs *regs)
-{
- struct sigframe *frame;
- int err = 0;
- int signal;
-
- frame = get_sigframe(ka, regs, sizeof(*frame));
-
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
-
- signal = current_thread_info()->exec_domain
- && current_thread_info()->exec_domain->signal_invmap
- && sig < 32
- ? current_thread_info()->exec_domain->signal_invmap[sig]
- : sig;
-
- err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
-
- if (_NSIG_WORDS > 1) {
- err |= __copy_to_user(frame->extramask, &set->sig[1],
- sizeof(frame->extramask));
- }
-
- /* Set up to return from userspace. If provided, use a stub
- already in userspace. */
- if (ka->sa.sa_flags & SA_RESTORER) {
- regs->gpr[GPR_LP] = (unsigned long) ka->sa.sa_restorer;
- } else {
- /* Note, these encodings are _little endian_! */
-
- /* addi __NR_sigreturn, r0, r12 */
- err |= __put_user(0x6600 | (__NR_sigreturn << 16),
- frame->tramp + 0);
- /* trap 0 */
- err |= __put_user(0x010007e0,
- frame->tramp + 1);
-
- regs->gpr[GPR_LP] = (unsigned long)frame->tramp;
-
- flush_cache_sigtramp (regs->gpr[GPR_LP]);
- }
-
- if (err)
- goto give_sigsegv;
-
- /* Set up registers for signal handler. */
- regs->pc = (v850_reg_t) ka->sa.sa_handler;
- regs->gpr[GPR_SP] = (v850_reg_t)frame;
- /* Signal handler args: */
- regs->gpr[GPR_ARG0] = signal; /* arg 0: signum */
- regs->gpr[GPR_ARG1] = (v850_reg_t)&frame->sc;/* arg 1: sigcontext */
-
- set_fs(USER_DS);
-
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=%p pc=%08lx ra=%08lx\n",
- current->comm, current->pid, frame, regs->pc, );
-#endif
-
- return;
-
-give_sigsegv:
- force_sigsegv(sig, current);
-}
-
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
-{
- struct rt_sigframe *frame;
- int err = 0;
- int signal;
-
- frame = get_sigframe(ka, regs, sizeof(*frame));
-
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
-
- signal = current_thread_info()->exec_domain
- && current_thread_info()->exec_domain->signal_invmap
- && sig < 32
- ? current_thread_info()->exec_domain->signal_invmap[sig]
- : sig;
-
- err |= copy_siginfo_to_user(&frame->info, info);
-
- /* Create the ucontext. */
- err |= __put_user(0, &frame->uc.uc_flags);
- err |= __put_user(0, &frame->uc.uc_link);
- err |= __put_user((void *)current->sas_ss_sp,
- &frame->uc.uc_stack.ss_sp);
- err |= __put_user(sas_ss_flags(regs->gpr[GPR_SP]),
- &frame->uc.uc_stack.ss_flags);
- err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
- err |= setup_sigcontext(&frame->uc.uc_mcontext,
- regs, set->sig[0]);
- err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
-
- /* Set up to return from userspace. If provided, use a stub
- already in userspace. */
- if (ka->sa.sa_flags & SA_RESTORER) {
- regs->gpr[GPR_LP] = (unsigned long) ka->sa.sa_restorer;
- } else {
- /* Note, these encodings are _little endian_! */
-
- /* addi __NR_sigreturn, r0, r12 */
- err |= __put_user(0x6600 | (__NR_sigreturn << 16),
- frame->tramp + 0);
- /* trap 0 */
- err |= __put_user(0x010007e0,
- frame->tramp + 1);
-
- regs->gpr[GPR_LP] = (unsigned long)frame->tramp;
-
- flush_cache_sigtramp (regs->gpr[GPR_LP]);
- }
-
- if (err)
- goto give_sigsegv;
-
- /* Set up registers for signal handler. */
- regs->pc = (v850_reg_t) ka->sa.sa_handler;
- regs->gpr[GPR_SP] = (v850_reg_t)frame;
- /* Signal handler args: */
- regs->gpr[GPR_ARG0] = signal; /* arg 0: signum */
- regs->gpr[GPR_ARG1] = (v850_reg_t)&frame->info; /* arg 1: siginfo */
- regs->gpr[GPR_ARG2] = (v850_reg_t)&frame->uc; /* arg 2: ucontext */
-
- set_fs(USER_DS);
-
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
- current->comm, current->pid, frame, regs->pc, regs->pr);
-#endif
-
- return;
-
-give_sigsegv:
- force_sigsegv(sig, current);
-}
-
-/*
- * OK, we're invoking a handler
- */
-
-static void
-handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
- sigset_t *oldset, struct pt_regs * regs)
-{
- /* Are we from a system call? */
- if (PT_REGS_SYSCALL (regs)) {
- /* If so, check system call restarting.. */
- switch (regs->gpr[GPR_RVAL]) {
- case -ERESTART_RESTARTBLOCK:
- current_thread_info()->restart_block.fn =
- do_no_restart_syscall;
- /* fall through */
- case -ERESTARTNOHAND:
- regs->gpr[GPR_RVAL] = -EINTR;
- break;
-
- case -ERESTARTSYS:
- if (!(ka->sa.sa_flags & SA_RESTART)) {
- regs->gpr[GPR_RVAL] = -EINTR;
- break;
- }
- /* fallthrough */
- case -ERESTARTNOINTR:
- regs->gpr[12] = PT_REGS_SYSCALL (regs);
- regs->pc -= 4; /* Size of `trap 0' insn. */
- }
-
- PT_REGS_SET_SYSCALL (regs, 0);
- }
-
- /* Set up the stack frame */
- if (ka->sa.sa_flags & SA_SIGINFO)
- setup_rt_frame(sig, ka, info, oldset, regs);
- else
- setup_frame(sig, ka, oldset, regs);
-
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-}
-
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- *
- * Note that we go through the signals twice: once to check the signals that
- * the kernel can handle, and then we build all the user-level signal handling
- * stack-frames in one go after that.
- */
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
-{
- siginfo_t info;
- int signr;
- struct k_sigaction ka;
-
- /*
- * We want the common case to go fast, which
- * is why we may in certain cases get here from
- * kernel mode. Just return without doing anything
- * if so.
- */
- if (!user_mode(regs))
- return 1;
-
- if (!oldset)
- oldset = &current->blocked;
-
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
- /* Whee! Actually deliver the signal. */
- handle_signal(signr, &info, &ka, oldset, regs);
- return 1;
- }
-
- /* Did we come from a system call? */
- if (PT_REGS_SYSCALL (regs)) {
- int rval = (int)regs->gpr[GPR_RVAL];
- /* Restart the system call - no handlers present */
- if (rval == -ERESTARTNOHAND
- || rval == -ERESTARTSYS
- || rval == -ERESTARTNOINTR)
- {
- regs->gpr[12] = PT_REGS_SYSCALL (regs);
- regs->pc -= 4; /* Size of `trap 0' insn. */
- }
- else if (rval == -ERESTART_RESTARTBLOCK) {
- regs->gpr[12] = __NR_restart_syscall;
- regs->pc -= 4; /* Size of `trap 0' insn. */
- }
- }
- return 0;
-}
diff --git a/arch/v850/kernel/sim.c b/arch/v850/kernel/sim.c
deleted file mode 100644
index 467b4aa0acd..00000000000
--- a/arch/v850/kernel/sim.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * arch/v850/kernel/sim.c -- Machine-specific stuff for GDB v850e simulator
- *
- * Copyright (C) 2001,02 NEC Corporation
- * Copyright (C) 2001,02 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/machdep.h>
-#include <asm/simsyscall.h>
-
-#include "mach.h"
-
-/* The name of a file containing the root filesystem. */
-#define ROOT_FS "rootfs.image"
-
-extern void simcons_setup (void);
-extern void simcons_poll_ttys (void);
-extern void set_mem_root (void *addr, size_t len, char *cmd_line);
-
-static int read_file (const char *name,
- unsigned long *addr, unsigned long *len,
- const char **err);
-
-void __init mach_setup (char **cmdline)
-{
- const char *err;
- unsigned long root_dev_addr, root_dev_len;
-
- simcons_setup ();
-
- printk (KERN_INFO "Reading root filesystem: %s", ROOT_FS);
-
- if (read_file (ROOT_FS, &root_dev_addr, &root_dev_len, &err)) {
- printk (" (size %luK)\n", root_dev_len / 1024);
- set_mem_root ((void *)root_dev_addr, (size_t)root_dev_len,
- *cmdline);
- } else
- printk ("...%s failed!\n", err);
-}
-
-void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len)
-{
- *ram_start = RAM_ADDR;
- *ram_len = RAM_SIZE;
-}
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
- /* ...do magic timer initialization?... */
- mach_tick = simcons_poll_ttys;
- setup_irq (0, timer_action);
-}
-
-
-static void irq_nop (unsigned irq) { }
-static unsigned irq_zero (unsigned irq) { return 0; }
-
-static struct hw_interrupt_type sim_irq_type = {
- .typename = "IRQ",
- .startup = irq_zero, /* startup */
- .shutdown = irq_nop, /* shutdown */
- .enable = irq_nop, /* enable */
- .disable = irq_nop, /* disable */
- .ack = irq_nop, /* ack */
- .end = irq_nop, /* end */
-};
-
-void __init mach_init_irqs (void)
-{
- init_irq_handlers (0, NUM_MACH_IRQS, 1, &sim_irq_type);
-}
-
-
-void mach_gettimeofday (struct timespec *tv)
-{
- long timeval[2], timezone[2];
- int rval = V850_SIM_SYSCALL (gettimeofday, timeval, timezone);
- if (rval == 0) {
- tv->tv_sec = timeval[0];
- tv->tv_nsec = timeval[1] * 1000;
- }
-}
-
-void machine_restart (char *__unused)
-{
- V850_SIM_SYSCALL (write, 1, "RESTART\n", 8);
- V850_SIM_SYSCALL (exit, 0);
-}
-
-void machine_halt (void)
-{
- V850_SIM_SYSCALL (write, 1, "HALT\n", 5);
- V850_SIM_SYSCALL (exit, 0);
-}
-
-void machine_power_off (void)
-{
- V850_SIM_SYSCALL (write, 1, "POWER OFF\n", 10);
- V850_SIM_SYSCALL (exit, 0);
-}
-
-
-/* Load data from a file called NAME into ram. The address and length
- of the data image are returned in ADDR and LEN. */
-static int __init
-read_file (const char *name,
- unsigned long *addr, unsigned long *len,
- const char **err)
-{
- int rval, fd;
- unsigned long cur, left;
- /* Note this is not a normal stat buffer, it's an ad-hoc
- structure defined by the simulator. */
- unsigned long stat_buf[10];
-
- /* Stat the file to find out the length. */
- rval = V850_SIM_SYSCALL (stat, name, stat_buf);
- if (rval < 0) {
- if (err) *err = "stat";
- return 0;
- }
- *len = stat_buf[4];
-
- /* Open the file; `0' is O_RDONLY. */
- fd = V850_SIM_SYSCALL (open, name, 0);
- if (fd < 0) {
- if (err) *err = "open";
- return 0;
- }
-
- *addr = (unsigned long)alloc_bootmem(*len);
- if (! *addr) {
- V850_SIM_SYSCALL (close, fd);
- if (err) *err = "alloc_bootmem";
- return 0;
- }
-
- cur = *addr;
- left = *len;
- while (left > 0) {
- int chunk = V850_SIM_SYSCALL (read, fd, cur, left);
- if (chunk <= 0)
- break;
- cur += chunk;
- left -= chunk;
- }
- V850_SIM_SYSCALL (close, fd);
- if (left > 0) {
- /* Some read failed. */
- free_bootmem (*addr, *len);
- if (err) *err = "read";
- return 0;
- }
-
- return 1;
-}
diff --git a/arch/v850/kernel/sim.ld b/arch/v850/kernel/sim.ld
deleted file mode 100644
index 101885f3c9f..00000000000
--- a/arch/v850/kernel/sim.ld
+++ /dev/null
@@ -1,13 +0,0 @@
-/* Linker script for the gdb v850e simulator (CONFIG_V850E_SIM). */
-
-MEMORY {
- /* Interrupt vectors. */
- INTV : ORIGIN = 0x0, LENGTH = 0xe0
- /* Main RAM. */
- RAM : ORIGIN = RAM_ADDR, LENGTH = RAM_SIZE
-}
-
-SECTIONS {
- .intv : { INTV_CONTENTS } > INTV
- .ram : { RAMK_KRAM_CONTENTS } > RAM
-}
diff --git a/arch/v850/kernel/sim85e2.c b/arch/v850/kernel/sim85e2.c
deleted file mode 100644
index 566dde5e607..00000000000
--- a/arch/v850/kernel/sim85e2.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * arch/v850/kernel/sim85e2.c -- Machine-specific stuff for
- * V850E2 RTL simulator
- *
- * Copyright (C) 2002,03 NEC Electronics Corporation
- * Copyright (C) 2002,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/machdep.h>
-
-#include "mach.h"
-
-
-/* There are 4 possible areas we can use:
-
- IRAM (1MB) is fast for instruction fetches, but slow for data
- DRAM (1020KB) is fast for data, but slow for instructions
- ERAM is cached, so should be fast for both insns and data
- SDRAM is external DRAM, similar to ERAM
-*/
-
-#define INIT_MEMC_FOR_SDRAM
-#define USE_SDRAM_AREA
-#define KERNEL_IN_SDRAM_AREA
-
-#define DCACHE_MODE V850E2_CACHE_BTSC_DCM_WT
-/*#define DCACHE_MODE V850E2_CACHE_BTSC_DCM_WB_ALLOC*/
-
-#ifdef USE_SDRAM_AREA
-#define RAM_START SDRAM_ADDR
-#define RAM_END (SDRAM_ADDR + SDRAM_SIZE)
-#else
-/* When we use DRAM, we need to account for the fact that the end of it is
- used for R0_RAM. */
-#define RAM_START DRAM_ADDR
-#define RAM_END R0_RAM_ADDR
-#endif
-
-
-extern void memcons_setup (void);
-
-
-#ifdef KERNEL_IN_SDRAM_AREA
-#define EARLY_INIT_SECTION_ATTR __attribute__ ((section (".early.text")))
-#else
-#define EARLY_INIT_SECTION_ATTR __init
-#endif
-
-void EARLY_INIT_SECTION_ATTR mach_early_init (void)
-{
- /* The sim85e2 simulator tracks `undefined' values, so to make
- debugging easier, we begin by zeroing out all otherwise
- undefined registers. This is not strictly necessary.
-
- The registers we zero are:
- Every GPR except:
- stack-pointer (r3)
- task-pointer (r16)
- our return addr (r31)
- Every system register (SPR) that we know about except for
- the PSW (SPR 5), which we zero except for the
- disable-interrupts bit.
- */
-
- /* GPRs */
- asm volatile (" mov r0, r1 ; mov r0, r2 ");
- asm volatile ("mov r0, r4 ; mov r0, r5 ; mov r0, r6 ; mov r0, r7 ");
- asm volatile ("mov r0, r8 ; mov r0, r9 ; mov r0, r10; mov r0, r11");
- asm volatile ("mov r0, r12; mov r0, r13; mov r0, r14; mov r0, r15");
- asm volatile (" mov r0, r17; mov r0, r18; mov r0, r19");
- asm volatile ("mov r0, r20; mov r0, r21; mov r0, r22; mov r0, r23");
- asm volatile ("mov r0, r24; mov r0, r25; mov r0, r26; mov r0, r27");
- asm volatile ("mov r0, r28; mov r0, r29; mov r0, r30");
-
- /* SPRs */
- asm volatile ("ldsr r0, 0; ldsr r0, 1; ldsr r0, 2; ldsr r0, 3");
- asm volatile ("ldsr r0, 4");
- asm volatile ("addi 0x20, r0, r1; ldsr r1, 5"); /* PSW */
- asm volatile ("ldsr r0, 16; ldsr r0, 17; ldsr r0, 18; ldsr r0, 19");
- asm volatile ("ldsr r0, 20");
-
-
-#ifdef INIT_MEMC_FOR_SDRAM
- /* Settings for SDRAM controller. */
- V850E2_VSWC = 0x0042;
- V850E2_BSC = 0x9286;
- V850E2_BCT(0) = 0xb000; /* was: 0 */
- V850E2_BCT(1) = 0x000b;
- V850E2_ASC = 0;
- V850E2_LBS = 0xa9aa; /* was: 0xaaaa */
- V850E2_LBC(0) = 0;
- V850E2_LBC(1) = 0; /* was: 0x3 */
- V850E2_BCC = 0;
- V850E2_RFS(4) = 0x800a; /* was: 0xf109 */
- V850E2_SCR(4) = 0x2091; /* was: 0x20a1 */
- V850E2_RFS(3) = 0x800c;
- V850E2_SCR(3) = 0x20a1;
- V850E2_DWC(0) = 0;
- V850E2_DWC(1) = 0;
-#endif
-
-#if 0
-#ifdef CONFIG_V850E2_SIM85E2S
- /* Turn on the caches. */
- V850E2_CACHE_BTSC = V850E2_CACHE_BTSC_ICM | DCACHE_MODE;
- V850E2_BHC = 0x1010;
-#elif CONFIG_V850E2_SIM85E2C
- V850E2_CACHE_BTSC |= (V850E2_CACHE_BTSC_ICM | V850E2_CACHE_BTSC_DCM0);
- V850E2_BUSM_BHC = 0xFFFF;
-#endif
-#else
- V850E2_BHC = 0;
-#endif
-
- /* Don't stop the simulator at `halt' instructions. */
- SIM85E2_NOTHAL = 1;
-
- /* Ensure that the simulator halts on a panic, instead of going
- into an infinite loop inside the panic function. */
- panic_timeout = -1;
-}
-
-void __init mach_setup (char **cmdline)
-{
- memcons_setup ();
-}
-
-void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len)
-{
- *ram_start = RAM_START;
- *ram_len = RAM_END - RAM_START;
-}
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
- /* The simulator actually cycles through all interrupts
- periodically. We just pay attention to IRQ0, which gives us
- 1/64 the rate of the periodic interrupts. */
- setup_irq (0, timer_action);
-}
-
-void mach_gettimeofday (struct timespec *tv)
-{
- tv->tv_sec = 0;
- tv->tv_nsec = 0;
-}
-
-/* Interrupts */
-
-struct v850e_intc_irq_init irq_inits[] = {
- { "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
- { 0 }
-};
-struct hw_interrupt_type hw_itypes[1];
-
-/* Initialize interrupts. */
-void __init mach_init_irqs (void)
-{
- v850e_intc_init_irq_types (irq_inits, hw_itypes);
-}
-
-
-void machine_halt (void) __attribute__ ((noreturn));
-void machine_halt (void)
-{
- SIM85E2_SIMFIN = 0; /* Halt immediately. */
- for (;;) {}
-}
-
-void machine_restart (char *__unused)
-{
- machine_halt ();
-}
-
-void machine_power_off (void)
-{
- machine_halt ();
-}
-
diff --git a/arch/v850/kernel/sim85e2.ld b/arch/v850/kernel/sim85e2.ld
deleted file mode 100644
index 7470fd2ffb5..00000000000
--- a/arch/v850/kernel/sim85e2.ld
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Linker script for the sim85e2c simulator, which is a verilog simulation of
- the V850E2 NA85E2C cpu core (CONFIG_V850E2_SIM85E2C). */
-
-MEMORY {
- /* 1MB of `instruction RAM', starting at 0.
- Instruction fetches are much faster from IRAM than from DRAM. */
- IRAM : ORIGIN = IRAM_ADDR, LENGTH = IRAM_SIZE
-
- /* 1MB of `data RAM', below and contiguous with the I/O space.
- Data fetches are much faster from DRAM than from IRAM. */
- DRAM : ORIGIN = DRAM_ADDR, LENGTH = DRAM_SIZE
-
- /* `external ram' (CS1 area), comes after IRAM. */
- ERAM : ORIGIN = ERAM_ADDR, LENGTH = ERAM_SIZE
-
- /* Dynamic RAM; uses memory controller. */
- SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
-}
-
-SECTIONS {
- .iram : {
- INTV_CONTENTS
- *arch/v850/kernel/head.o
- *(.early.text)
- } > IRAM
- .dram : {
- _memcons_output = . ;
- . = . + 0x8000 ;
- _memcons_output_end = . ;
- } > DRAM
- .sdram : {
- /* We stick console output into a buffer here. */
- RAMK_KRAM_CONTENTS
- ROOT_FS_CONTENTS
- } > SDRAM
-}
diff --git a/arch/v850/kernel/simcons.c b/arch/v850/kernel/simcons.c
deleted file mode 100644
index 9973596ae30..00000000000
--- a/arch/v850/kernel/simcons.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * arch/v850/kernel/simcons.c -- Console I/O for GDB v850e simulator
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/console.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/tty_driver.h>
-#include <linux/init.h>
-
-#include <asm/poll.h>
-#include <asm/string.h>
-#include <asm/simsyscall.h>
-
-
-/* Low-level console. */
-
-static void simcons_write (struct console *co, const char *buf, unsigned len)
-{
- V850_SIM_SYSCALL (write, 1, buf, len);
-}
-
-static int simcons_read (struct console *co, char *buf, unsigned len)
-{
- return V850_SIM_SYSCALL (read, 0, buf, len);
-}
-
-static struct tty_driver *tty_driver;
-static struct tty_driver *simcons_device (struct console *c, int *index)
-{
- *index = c->index;
- return tty_driver;
-}
-
-static struct console simcons =
-{
- .name = "simcons",
- .write = simcons_write,
- .read = simcons_read,
- .device = simcons_device,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-/* Higher level TTY interface. */
-
-int simcons_tty_open (struct tty_struct *tty, struct file *filp)
-{
- return 0;
-}
-
-int simcons_tty_write (struct tty_struct *tty,
- const unsigned char *buf, int count)
-{
- return V850_SIM_SYSCALL (write, 1, buf, count);
-}
-
-int simcons_tty_write_room (struct tty_struct *tty)
-{
- /* Completely arbitrary. */
- return 0x100000;
-}
-
-int simcons_tty_chars_in_buffer (struct tty_struct *tty)
-{
- /* We have no buffer. */
- return 0;
-}
-
-static const struct tty_operations ops = {
- .open = simcons_tty_open,
- .write = simcons_tty_write,
- .write_room = simcons_tty_write_room,
- .chars_in_buffer = simcons_tty_chars_in_buffer,
-};
-
-int __init simcons_tty_init (void)
-{
- struct tty_driver *driver = alloc_tty_driver(1);
- int err;
- if (!driver)
- return -ENOMEM;
- driver->name = "simcons";
- driver->major = TTY_MAJOR;
- driver->minor_start = 64;
- driver->type = TTY_DRIVER_TYPE_SYSCONS;
- driver->init_termios = tty_std_termios;
- tty_set_operations(driver, &ops);
- err = tty_register_driver(driver);
- if (err) {
- put_tty_driver(driver);
- return err;
- }
- tty_driver = driver;
- return 0;
-}
-/* We use `late_initcall' instead of just `__initcall' as a workaround for
- the fact that (1) simcons_tty_init can't be called before tty_init,
- (2) tty_init is called via `module_init', (3) if statically linked,
- module_init == device_init, and (4) there's no ordering of init lists.
- We can do this easily because simcons is always statically linked, but
- other tty drivers that depend on tty_init and which must use
- `module_init' to declare their init routines are likely to be broken. */
-late_initcall(simcons_tty_init);
-
-/* Poll for input on the console, and if there's any, deliver it to the
- tty driver. */
-void simcons_poll_tty (struct tty_struct *tty)
-{
- char buf[32]; /* Not the nicest way to do it but I need it correct first */
- int flip = 0, send_break = 0;
- struct pollfd pfd;
- pfd.fd = 0;
- pfd.events = POLLIN;
-
- if (V850_SIM_SYSCALL (poll, &pfd, 1, 0) > 0) {
- if (pfd.revents & POLLIN) {
- /* Real block hardware knows the transfer size before
- transfer so the new tty buffering doesn't try to handle
- this rather weird simulator specific case well */
- int rd = V850_SIM_SYSCALL (read, 0, buf, 32);
- if (rd > 0) {
- tty_insert_flip_string(tty, buf, rd);
- flip = 1;
- } else
- send_break = 1;
- } else if (pfd.revents & POLLERR)
- send_break = 1;
- }
-
- if (send_break) {
- tty_insert_flip_char (tty, 0, TTY_BREAK);
- flip = 1;
- }
-
- if (flip)
- tty_schedule_flip (tty);
-}
-
-void simcons_poll_ttys (void)
-{
- if (tty_driver && tty_driver->ttys[0])
- simcons_poll_tty (tty_driver->ttys[0]);
-}
-
-void simcons_setup (void)
-{
- V850_SIM_SYSCALL (make_raw, 0);
- register_console (&simcons);
- printk (KERN_INFO "Console: GDB V850E simulator stdio\n");
-}
diff --git a/arch/v850/kernel/syscalls.c b/arch/v850/kernel/syscalls.c
deleted file mode 100644
index 1a83daf8e24..00000000000
--- a/arch/v850/kernel/syscalls.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * arch/v850/kernel/syscalls.c -- Various system-call definitions not
- * defined in machine-independent code
- *
- * Copyright (C) 2001,02 NEC Corporation
- * Copyright (C) 2001,02 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
- * archive for more details.
- *
- * This file was derived the ppc version, arch/ppc/kernel/syscalls.c
- * ... which was derived from "arch/i386/kernel/sys_i386.c" by Gary Thomas;
- * modified by Cort Dougan (cort@cs.nmt.edu)
- * and Paul Mackerras (paulus@cs.anu.edu.au).
- */
-
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/syscalls.h>
-#include <linux/sem.h>
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <linux/stat.h>
-#include <linux/mman.h>
-#include <linux/sys.h>
-#include <linux/ipc.h>
-#include <linux/utsname.h>
-#include <linux/file.h>
-
-#include <asm/uaccess.h>
-#include <asm/unistd.h>
-
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-int
-sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
-{
- int version, ret;
-
- version = call >> 16; /* hack for backward compatibility */
- call &= 0xffff;
-
- ret = -EINVAL;
- switch (call) {
- case SEMOP:
- ret = sys_semop (first, (struct sembuf *)ptr, second);
- break;
- case SEMGET:
- ret = sys_semget (first, second, third);
- break;
- case SEMCTL:
- {
- union semun fourth;
-
- if (!ptr)
- break;
- if ((ret = access_ok(VERIFY_READ, ptr, sizeof(long)) ? 0 : -EFAULT)
- || (ret = get_user(fourth.__pad, (void **)ptr)))
- break;
- ret = sys_semctl (first, second, third, fourth);
- break;
- }
- case MSGSND:
- ret = sys_msgsnd (first, (struct msgbuf *) ptr, second, third);
- break;
- case MSGRCV:
- switch (version) {
- case 0: {
- struct ipc_kludge tmp;
-
- if (!ptr)
- break;
- if ((ret = access_ok(VERIFY_READ, ptr, sizeof(tmp)) ? 0 : -EFAULT)
- || (ret = copy_from_user(&tmp,
- (struct ipc_kludge *) ptr,
- sizeof (tmp))))
- break;
- ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp,
- third);
- break;
- }
- default:
- ret = sys_msgrcv (first, (struct msgbuf *) ptr,
- second, fifth, third);
- break;
- }
- break;
- case MSGGET:
- ret = sys_msgget ((key_t) first, second);
- break;
- case MSGCTL:
- ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
- break;
- case SHMAT:
- switch (version) {
- default: {
- ulong raddr;
-
- if ((ret = access_ok(VERIFY_WRITE, (ulong*) third,
- sizeof(ulong)) ? 0 : -EFAULT))
- break;
- ret = do_shmat (first, (char *) ptr, second, &raddr);
- if (ret)
- break;
- ret = put_user (raddr, (ulong *) third);
- break;
- }
- case 1: /* iBCS2 emulator entry point */
- if (!segment_eq(get_fs(), get_ds()))
- break;
- ret = do_shmat (first, (char *) ptr, second,
- (ulong *) third);
- break;
- }
- break;
- case SHMDT:
- ret = sys_shmdt ((char *)ptr);
- break;
- case SHMGET:
- ret = sys_shmget (first, second, third);
- break;
- case SHMCTL:
- ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
- break;
- }
-
- return ret;
-}
-
-static inline unsigned long
-do_mmap2 (unsigned long addr, size_t len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long pgoff)
-{
- struct file * file = NULL;
- int ret = -EBADF;
-
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- if (! (flags & MAP_ANONYMOUS)) {
- if (!(file = fget (fd)))
- goto out;
- }
-
- down_write (&current->mm->mmap_sem);
- ret = do_mmap_pgoff (file, addr, len, prot, flags, pgoff);
- up_write (&current->mm->mmap_sem);
- if (file)
- fput (file);
-out:
- return ret;
-}
-
-unsigned long sys_mmap2 (unsigned long addr, size_t len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long pgoff)
-{
- return do_mmap2 (addr, len, prot, flags, fd, pgoff);
-}
-
-unsigned long sys_mmap (unsigned long addr, size_t len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, off_t offset)
-{
- int err = -EINVAL;
-
- if (offset & ~PAGE_MASK)
- goto out;
-
- err = do_mmap2 (addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
-out:
- return err;
-}
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename, char *const argv[], char *const envp[])
-{
- register char *__a __asm__ ("r6") = filename;
- register void *__b __asm__ ("r7") = argv;
- register void *__c __asm__ ("r8") = envp;
- register unsigned long __syscall __asm__ ("r12") = __NR_execve;
- register unsigned long __ret __asm__ ("r10");
- __asm__ __volatile__ ("trap 0"
- : "=r" (__ret), "=r" (__syscall)
- : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c)
- : "r1", "r5", "r11", "r13", "r14",
- "r15", "r16", "r17", "r18", "r19");
- return __ret;
-}
diff --git a/arch/v850/kernel/teg.c b/arch/v850/kernel/teg.c
deleted file mode 100644
index 699248f92aa..00000000000
--- a/arch/v850/kernel/teg.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * arch/v850/kernel/teg.c -- NB85E-TEG cpu chip
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/machdep.h>
-#include <asm/v850e_timer_d.h>
-
-#include "mach.h"
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
- /* Select timer interrupt instead of external pin. */
- TEG_ISS |= 0x1;
- /* Start hardware timer. */
- v850e_timer_d_configure (0, HZ);
- /* Install timer interrupt handler. */
- setup_irq (IRQ_INTCMD(0), timer_action);
-}
-
-static struct v850e_intc_irq_init irq_inits[] = {
- { "IRQ", 0, NUM_CPU_IRQS, 1, 7 },
- { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 },
- { "SER", IRQ_INTSER(0), IRQ_INTSER_NUM, 1, 3 },
- { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 1, 4 },
- { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 1, 5 },
- { 0 }
-};
-#define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1)
-
-static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
-
-/* Initialize MA chip interrupts. */
-void __init teg_init_irqs (void)
-{
- v850e_intc_init_irq_types (irq_inits, hw_itypes);
-}
-
-/* Called before configuring an on-chip UART. */
-void teg_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
-{
- /* Enable UART I/O pins instead of external interrupt pins, and
- UART interrupts instead of external pin interrupts. */
- TEG_ISS |= 0x4E;
-}
diff --git a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c
deleted file mode 100644
index d810c93fe66..00000000000
--- a/arch/v850/kernel/time.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * linux/arch/v850/kernel/time.c -- Arch-dependent timer functions
- *
- * Copyright (C) 1991, 1992, 1995, 2001, 2002 Linus Torvalds
- *
- * This file contains the v850-specific time handling details.
- * Most of the stuff is located in the machine specific files.
- *
- * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
- * "A Kernel Model for Precision Timekeeping" by Dave Mills
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/timex.h>
-#include <linux/profile.h>
-
-#include <asm/io.h>
-
-#include "mach.h"
-
-#define TICK_SIZE (tick_nsec / 1000)
-
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-static irqreturn_t timer_interrupt (int irq, void *dummy, struct pt_regs *regs)
-{
-#if 0
- /* last time the cmos clock got updated */
- static long last_rtc_update=0;
-#endif
-
- /* may need to kick the hardware timer */
- if (mach_tick)
- mach_tick ();
-
- do_timer (1);
-#ifndef CONFIG_SMP
- update_process_times(user_mode(regs));
-#endif
- profile_tick(CPU_PROFILING, regs);
-#if 0
- /*
- * If we have an externally synchronized Linux clock, then update
- * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
- * called as close as possible to 500 ms before the new second starts.
- */
- if (ntp_synced() &&
- xtime.tv_sec > last_rtc_update + 660 &&
- (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
- (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
- if (set_rtc_mmss (xtime.tv_sec) == 0)
- last_rtc_update = xtime.tv_sec;
- else
- last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
- }
-#ifdef CONFIG_HEARTBEAT
- /* use power LED as a heartbeat instead -- much more useful
- for debugging -- based on the version for PReP by Cort */
- /* acts like an actual heart beat -- ie thump-thump-pause... */
- if (mach_heartbeat) {
- static unsigned cnt = 0, period = 0, dist = 0;
-
- if (cnt == 0 || cnt == dist)
- mach_heartbeat ( 1 );
- else if (cnt == 7 || cnt == dist+7)
- mach_heartbeat ( 0 );
-
- if (++cnt > period) {
- cnt = 0;
- /* The hyperbolic function below modifies the heartbeat period
- * length in dependency of the current (5min) load. It goes
- * through the points f(0)=126, f(1)=86, f(5)=51,
- * f(inf)->30. */
- period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
- dist = period / 4;
- }
- }
-#endif /* CONFIG_HEARTBEAT */
-#endif /* 0 */
-
- return IRQ_HANDLED;
-}
-
-static int timer_dev_id;
-static struct irqaction timer_irqaction = {
- .handler = timer_interrupt,
- .flags = IRQF_DISABLED,
- .mask = CPU_MASK_NONE,
- .name = "timer",
- .dev_id = &timer_dev_id,
-};
-
-void time_init (void)
-{
- mach_gettimeofday (&xtime);
- mach_sched_init (&timer_irqaction);
-}
diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
deleted file mode 100644
index 8d386a5dbc4..00000000000
--- a/arch/v850/kernel/v850_ksyms.c
+++ /dev/null
@@ -1,51 +0,0 @@
-#include <linux/module.h>
-#include <linux/linkage.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-#include <linux/in6.h>
-#include <linux/interrupt.h>
-
-#include <asm/pgalloc.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/checksum.h>
-#include <asm/current.h>
-
-
-extern void *trap_table;
-EXPORT_SYMBOL (trap_table);
-
-/* platform dependent support */
-EXPORT_SYMBOL (kernel_thread);
-EXPORT_SYMBOL (__bug);
-
-/* Networking helper routines. */
-EXPORT_SYMBOL (csum_partial_copy_nocheck);
-EXPORT_SYMBOL (csum_partial_copy_from_user);
-EXPORT_SYMBOL (ip_compute_csum);
-EXPORT_SYMBOL (ip_fast_csum);
-
-/* string / mem functions */
-EXPORT_SYMBOL (memset);
-EXPORT_SYMBOL (memcpy);
-EXPORT_SYMBOL (memmove);
-
-/*
- * libgcc functions - functions that are used internally by the
- * compiler... (prototypes are not correct though, but that
- * doesn't really matter since they're not versioned).
- */
-extern void __ashldi3 (void);
-extern void __ashrdi3 (void);
-extern void __lshrdi3 (void);
-extern void __muldi3 (void);
-extern void __negdi2 (void);
-
-EXPORT_SYMBOL (__ashldi3);
-EXPORT_SYMBOL (__ashrdi3);
-EXPORT_SYMBOL (__lshrdi3);
-EXPORT_SYMBOL (__muldi3);
-EXPORT_SYMBOL (__negdi2);
diff --git a/arch/v850/kernel/v850e2_cache.c b/arch/v850/kernel/v850e2_cache.c
deleted file mode 100644
index 4570312c689..00000000000
--- a/arch/v850/kernel/v850e2_cache.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * arch/v850/kernel/v850e2_cache.c -- Cache control for V850E2 cache
- * memories
- *
- * Copyright (C) 2003 NEC Electronics Corporation
- * Copyright (C) 2003 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/mm.h>
-
-#include <asm/v850e2_cache.h>
-
-/* Cache operations we can do. The encoding corresponds directly to the
- value we need to write into the COPR register. */
-enum cache_op {
- OP_SYNC_IF_DIRTY = V850E2_CACHE_COPR_CFC(0), /* 000 */
- OP_SYNC_IF_VALID = V850E2_CACHE_COPR_CFC(1), /* 001 */
- OP_SYNC_IF_VALID_AND_CLEAR = V850E2_CACHE_COPR_CFC(3), /* 011 */
- OP_WAY_CLEAR = V850E2_CACHE_COPR_CFC(4), /* 100 */
- OP_FILL = V850E2_CACHE_COPR_CFC(5), /* 101 */
- OP_CLEAR = V850E2_CACHE_COPR_CFC(6), /* 110 */
- OP_CREATE_DIRTY = V850E2_CACHE_COPR_CFC(7) /* 111 */
-};
-
-/* Which cache to use. This encoding also corresponds directly to the
- value we need to write into the COPR register. */
-enum cache {
- ICACHE = 0,
- DCACHE = V850E2_CACHE_COPR_LBSL
-};
-
-/* Returns ADDR rounded down to the beginning of its cache-line. */
-#define CACHE_LINE_ADDR(addr) \
- ((addr) & ~(V850E2_CACHE_LINE_SIZE - 1))
-/* Returns END_ADDR rounded up to the `limit' of its cache-line. */
-#define CACHE_LINE_END_ADDR(end_addr) \
- CACHE_LINE_ADDR(end_addr + (V850E2_CACHE_LINE_SIZE - 1))
-
-
-/* Low-level cache ops. */
-
-/* Apply cache-op OP to all entries in CACHE. */
-static inline void cache_op_all (enum cache_op op, enum cache cache)
-{
- int cmd = op | cache | V850E2_CACHE_COPR_WSLE | V850E2_CACHE_COPR_STRT;
-
- if (op != OP_WAY_CLEAR) {
- /* The WAY_CLEAR operation does the whole way, but other
- ops take begin-index and count params; we just indicate
- the entire cache. */
- V850E2_CACHE_CADL = 0;
- V850E2_CACHE_CADH = 0;
- V850E2_CACHE_CCNT = V850E2_CACHE_WAY_SIZE - 1;
- }
-
- V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(0); /* way 0 */
- V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(1); /* way 1 */
- V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(2); /* way 2 */
- V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(3); /* way 3 */
-}
-
-/* Apply cache-op OP to all entries in CACHE covering addresses ADDR
- through ADDR+LEN. */
-static inline void cache_op_range (enum cache_op op, u32 addr, u32 len,
- enum cache cache)
-{
- u32 start = CACHE_LINE_ADDR (addr);
- u32 end = CACHE_LINE_END_ADDR (addr + len);
- u32 num_lines = (end - start) >> V850E2_CACHE_LINE_SIZE_BITS;
-
- V850E2_CACHE_CADL = start & 0xFFFF;
- V850E2_CACHE_CADH = start >> 16;
- V850E2_CACHE_CCNT = num_lines - 1;
-
- V850E2_CACHE_COPR = op | cache | V850E2_CACHE_COPR_STRT;
-}
-
-
-/* High-level ops. */
-
-static void cache_exec_after_store_all (void)
-{
- cache_op_all (OP_SYNC_IF_DIRTY, DCACHE);
- cache_op_all (OP_WAY_CLEAR, ICACHE);
-}
-
-static void cache_exec_after_store_range (u32 start, u32 len)
-{
- cache_op_range (OP_SYNC_IF_DIRTY, start, len, DCACHE);
- cache_op_range (OP_CLEAR, start, len, ICACHE);
-}
-
-
-/* Exported functions. */
-
-void flush_icache (void)
-{
- cache_exec_after_store_all ();
-}
-
-void flush_icache_range (unsigned long start, unsigned long end)
-{
- cache_exec_after_store_range (start, end - start);
-}
-
-void flush_icache_page (struct vm_area_struct *vma, struct page *page)
-{
- cache_exec_after_store_range (page_to_virt (page), PAGE_SIZE);
-}
-
-void flush_icache_user_range (struct vm_area_struct *vma, struct page *page,
- unsigned long addr, int len)
-{
- cache_exec_after_store_range (addr, len);
-}
-
-void flush_cache_sigtramp (unsigned long addr)
-{
- /* For the exact size, see signal.c, but 16 bytes should be enough. */
- cache_exec_after_store_range (addr, 16);
-}
diff --git a/arch/v850/kernel/v850e_cache.c b/arch/v850/kernel/v850e_cache.c
deleted file mode 100644
index ea3e51cfb25..00000000000
--- a/arch/v850/kernel/v850e_cache.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * arch/v850/kernel/v850e_cache.c -- Cache control for V850E cache memories
- *
- * Copyright (C) 2003 NEC Electronics Corporation
- * Copyright (C) 2003 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-/* This file implements cache control for the rather simple cache used on
- some V850E CPUs, specifically the NB85E/TEG CPU-core and the V850E/ME2
- CPU. V850E2 processors have their own (better) cache
- implementation. */
-
-#include <asm/entry.h>
-#include <asm/cacheflush.h>
-#include <asm/v850e_cache.h>
-
-#define WAIT_UNTIL_CLEAR(value) while (value) {}
-
-/* Set caching params via the BHC and DCC registers. */
-void v850e_cache_enable (u16 bhc, u16 icc, u16 dcc)
-{
- unsigned long *r0_ram = (unsigned long *)R0_RAM_ADDR;
- register u16 bhc_val asm ("r6") = bhc;
-
- /* Read the instruction cache control register (ICC) and confirm
- that bits 0 and 1 (TCLR0, TCLR1) are all cleared. */
- WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
- V850E_CACHE_ICC = icc;
-
-#ifdef V850E_CACHE_DCC
- /* Configure data-cache. */
- V850E_CACHE_DCC = dcc;
-#endif /* V850E_CACHE_DCC */
-
- /* Configure caching for various memory regions by writing the BHC
- register. The documentation says that an instruction _cannot_
- enable/disable caching for the memory region in which the
- instruction itself exists; to work around this, we store
- appropriate instructions into the on-chip RAM area (which is never
- cached), and briefly jump there to do the work. */
-#ifdef V850E_CACHE_WRITE_IBS
- *r0_ram++ = 0xf0720760; /* st.h r0, 0xfffff072[r0] */
-#endif
- *r0_ram++ = 0xf06a3760; /* st.h r6, 0xfffff06a[r0] */
- *r0_ram = 0x5640006b; /* jmp [r11] */
-
- asm ("mov hilo(1f), r11; jmp [%1]; 1:;"
- :: "r" (bhc_val), "r" (R0_RAM_ADDR) : "r11");
-}
-
-static void clear_icache (void)
-{
- /* 1. Read the instruction cache control register (ICC) and confirm
- that bits 0 and 1 (TCLR0, TCLR1) are all cleared. */
- WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
-
- /* 2. Read the ICC register and confirm that bit 12 (LOCK0) is
- cleared. Bit 13 of the ICC register is always cleared. */
- WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x1000);
-
- /* 3. Set the TCLR0 and TCLR1 bits of the ICC register as follows,
- when clearing way 0 and way 1 at the same time:
- (a) Set the TCLR0 and TCLR1 bits.
- (b) Read the TCLR0 and TCLR1 bits to confirm that these bits
- are cleared.
- (c) Perform (a) and (b) above again. */
- V850E_CACHE_ICC |= 0x3;
- WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
-
-#ifdef V850E_CACHE_REPEAT_ICC_WRITE
- /* Do it again. */
- V850E_CACHE_ICC |= 0x3;
- WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
-#endif
-}
-
-#ifdef V850E_CACHE_DCC
-/* Flush or clear (or both) the data cache, depending on the value of FLAGS;
- the procedure is the same for both, just the control bits used differ (and
- both may be performed simultaneously). */
-static void dcache_op (unsigned short flags)
-{
- /* 1. Read the data cache control register (DCC) and confirm that bits
- 0, 1, 4, and 5 (DC00, DC01, DC04, DC05) are all cleared. */
- WAIT_UNTIL_CLEAR (V850E_CACHE_DCC & 0x33);
-
- /* 2. Clear DCC register bit 12 (DC12), bit 13 (DC13), or both
- depending on the way for which tags are to be cleared. */
- V850E_CACHE_DCC &= ~0xC000;
-
- /* 3. Set DCC register bit 0 (DC00), bit 1 (DC01) or both depending on
- the way for which tags are to be cleared.
- ...
- Set DCC register bit 4 (DC04), bit 5 (DC05), or both depending
- on the way to be data flushed. */
- V850E_CACHE_DCC |= flags;
-
- /* 4. Read DCC register bit DC00, DC01 [DC04, DC05], or both depending
- on the way for which tags were cleared [flushed] and confirm
- that that bit is cleared. */
- WAIT_UNTIL_CLEAR (V850E_CACHE_DCC & flags);
-}
-#endif /* V850E_CACHE_DCC */
-
-/* Flushes the contents of the dcache to memory. */
-static inline void flush_dcache (void)
-{
-#ifdef V850E_CACHE_DCC
- /* We only need to do something if in write-back mode. */
- if (V850E_CACHE_DCC & 0x0400)
- dcache_op (0x30);
-#endif /* V850E_CACHE_DCC */
-}
-
-/* Flushes the contents of the dcache to memory, and then clears it. */
-static inline void clear_dcache (void)
-{
-#ifdef V850E_CACHE_DCC
- /* We only need to do something if the dcache is enabled. */
- if (V850E_CACHE_DCC & 0x0C00)
- dcache_op (0x33);
-#endif /* V850E_CACHE_DCC */
-}
-
-/* Clears the dcache without flushing to memory first. */
-static inline void clear_dcache_no_flush (void)
-{
-#ifdef V850E_CACHE_DCC
- /* We only need to do something if the dcache is enabled. */
- if (V850E_CACHE_DCC & 0x0C00)
- dcache_op (0x3);
-#endif /* V850E_CACHE_DCC */
-}
-
-static inline void cache_exec_after_store (void)
-{
- flush_dcache ();
- clear_icache ();
-}
-
-
-/* Exported functions. */
-
-void flush_icache (void)
-{
- cache_exec_after_store ();
-}
-
-void flush_icache_range (unsigned long start, unsigned long end)
-{
- cache_exec_after_store ();
-}
-
-void flush_icache_page (struct vm_area_struct *vma, struct page *page)
-{
- cache_exec_after_store ();
-}
-
-void flush_icache_user_range (struct vm_area_struct *vma, struct page *page,
- unsigned long adr, int len)
-{
- cache_exec_after_store ();
-}
-
-void flush_cache_sigtramp (unsigned long addr)
-{
- cache_exec_after_store ();
-}
diff --git a/arch/v850/kernel/v850e_intc.c b/arch/v850/kernel/v850e_intc.c
deleted file mode 100644
index 8d39a52ee6d..00000000000
--- a/arch/v850/kernel/v850e_intc.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * arch/v850/kernel/v850e_intc.c -- V850E interrupt controller (INTC)
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/v850e_intc.h>
-
-static void irq_nop (unsigned irq) { }
-
-static unsigned v850e_intc_irq_startup (unsigned irq)
-{
- v850e_intc_clear_pending_irq (irq);
- v850e_intc_enable_irq (irq);
- return 0;
-}
-
-static void v850e_intc_end_irq (unsigned irq)
-{
- unsigned long psw, temp;
-
- /* Clear the highest-level bit in the In-service priority register
- (ISPR), to allow this interrupt (or another of the same or
- lesser priority) to happen again.
-
- The `reti' instruction normally does this automatically when the
- PSW bits EP and NP are zero, but we can't always rely on reti
- being used consistently to return after an interrupt (another
- process can be scheduled, for instance, which can delay the
- associated reti for a long time, or this process may be being
- single-stepped, which uses the `dbret' instruction to return
- from the kernel).
-
- We also set the PSW EP bit, which prevents reti from also
- trying to modify the ISPR itself. */
-
- /* Get PSW and disable interrupts. */
- asm volatile ("stsr psw, %0; di" : "=r" (psw));
- /* We don't want to do anything for NMIs (they don't use the ISPR). */
- if (! (psw & 0xC0)) {
- /* Transition to `trap' state, so that an eventual real
- reti instruction won't modify the ISPR. */
- psw |= 0x40;
- /* Fake an interrupt return, which automatically clears the
- appropriate bit in the ISPR. */
- asm volatile ("mov hilo(1f), %0;"
- "ldsr %0, eipc; ldsr %1, eipsw;"
- "reti;"
- "1:"
- : "=&r" (temp) : "r" (psw));
- }
-}
-
-/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
- INITS (which is terminated by an entry with the name field == 0). */
-void __init v850e_intc_init_irq_types (struct v850e_intc_irq_init *inits,
- struct hw_interrupt_type *hw_irq_types)
-{
- struct v850e_intc_irq_init *init;
- for (init = inits; init->name; init++) {
- unsigned i;
- struct hw_interrupt_type *hwit = hw_irq_types++;
-
- hwit->typename = init->name;
-
- hwit->startup = v850e_intc_irq_startup;
- hwit->shutdown = v850e_intc_disable_irq;
- hwit->enable = v850e_intc_enable_irq;
- hwit->disable = v850e_intc_disable_irq;
- hwit->ack = irq_nop;
- hwit->end = v850e_intc_end_irq;
-
- /* Initialize kernel IRQ infrastructure for this interrupt. */
- init_irq_handlers(init->base, init->num, init->interval, hwit);
-
- /* Set the interrupt priorities. */
- for (i = 0; i < init->num; i++) {
- unsigned irq = init->base + i * init->interval;
-
- /* If the interrupt is currently enabled (all
- interrupts are initially disabled), then
- assume whoever enabled it has set things up
- properly, and avoid messing with it. */
- if (! v850e_intc_irq_enabled (irq))
- /* This write also (1) disables the
- interrupt, and (2) clears any pending
- interrupts. */
- V850E_INTC_IC (irq)
- = (V850E_INTC_IC_PR (init->priority)
- | V850E_INTC_IC_MK);
- }
- }
-}
diff --git a/arch/v850/kernel/v850e_timer_d.c b/arch/v850/kernel/v850e_timer_d.c
deleted file mode 100644
index d2a4ece2574..00000000000
--- a/arch/v850/kernel/v850e_timer_d.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * include/asm-v850/v850e_timer_d.c -- `Timer D' component often used
- * with V850E CPUs
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-
-#include <asm/v850e_utils.h>
-#include <asm/v850e_timer_d.h>
-
-/* Start interval timer TIMER (0-3). The timer will issue the
- corresponding INTCMD interrupt RATE times per second.
- This function does not enable the interrupt. */
-void v850e_timer_d_configure (unsigned timer, unsigned rate)
-{
- unsigned divlog2, count;
-
- /* Calculate params for timer. */
- if (! calc_counter_params (
- V850E_TIMER_D_BASE_FREQ, rate,
- V850E_TIMER_D_TMCD_CS_MIN, V850E_TIMER_D_TMCD_CS_MAX, 16,
- &divlog2, &count))
- printk (KERN_WARNING
- "Cannot find interval timer %d setting suitable"
- " for rate of %dHz.\n"
- "Using rate of %dHz instead.\n",
- timer, rate,
- (V850E_TIMER_D_BASE_FREQ >> divlog2) >> 16);
-
- /* Do the actual hardware timer initialization: */
-
- /* Enable timer. */
- V850E_TIMER_D_TMCD(timer) = V850E_TIMER_D_TMCD_CAE;
- /* Set clock divider. */
- V850E_TIMER_D_TMCD(timer)
- = V850E_TIMER_D_TMCD_CAE
- | V850E_TIMER_D_TMCD_CS(divlog2);
- /* Set timer compare register. */
- V850E_TIMER_D_CMD(timer) = count;
- /* Start counting. */
- V850E_TIMER_D_TMCD(timer)
- = V850E_TIMER_D_TMCD_CAE
- | V850E_TIMER_D_TMCD_CS(divlog2)
- | V850E_TIMER_D_TMCD_CE;
-}
diff --git a/arch/v850/kernel/v850e_utils.c b/arch/v850/kernel/v850e_utils.c
deleted file mode 100644
index e6807ef8dee..00000000000
--- a/arch/v850/kernel/v850e_utils.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * include/asm-v850/v850e_utils.h -- Utility functions associated with
- * V850E CPUs
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <asm/v850e_utils.h>
-
-/* Calculate counter clock-divider and count values to attain the
- desired frequency RATE from the base frequency BASE_FREQ. The
- counter is expected to have a clock-divider, which can divide the
- system cpu clock by a power of two value from MIN_DIVLOG2 to
- MAX_DIV_LOG2, and a word-size of COUNTER_SIZE bits (the counter
- counts up and resets whenever it's equal to the compare register,
- generating an interrupt or whatever when it does so). The returned
- values are: *DIVLOG2 -- log2 of the desired clock divider and *COUNT
- -- the counter compare value to use. Returns true if it was possible
- to find a reasonable value, otherwise false (and the other return
- values will be set to be as good as possible). */
-int calc_counter_params (unsigned long base_freq,
- unsigned long rate,
- unsigned min_divlog2, unsigned max_divlog2,
- unsigned counter_size,
- unsigned *divlog2, unsigned *count)
-{
- unsigned _divlog2;
- int ok = 0;
-
- /* Find the lowest clock divider setting that can represent RATE. */
- for (_divlog2 = min_divlog2; _divlog2 <= max_divlog2; _divlog2++) {
- /* Minimum interrupt rate possible using this divider. */
- unsigned min_int_rate
- = (base_freq >> _divlog2) >> counter_size;
-
- if (min_int_rate <= rate) {
- /* This setting is the highest resolution
- setting that's slow enough enough to attain
- RATE interrupts per second, so use it. */
- ok = 1;
- break;
- }
- }
-
- if (_divlog2 > max_divlog2)
- /* Can't find correct setting. */
- _divlog2 = max_divlog2;
-
- if (divlog2)
- *divlog2 = _divlog2;
- if (count)
- *count = ((base_freq >> _divlog2) + rate/2) / rate;
-
- return ok;
-}
diff --git a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S
deleted file mode 100644
index d08cd1d27f2..00000000000
--- a/arch/v850/kernel/vmlinux.lds.S
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * arch/v850/vmlinux.lds.S -- kernel linker script for v850 platforms
- *
- * Copyright (C) 2002,03,04,05 NEC Electronics Corporation
- * Copyright (C) 2002,03,04,05 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-
-#define VMLINUX_SYMBOL(_sym_) _##_sym_
-#include <asm-generic/vmlinux.lds.h>
-
-/* For most platforms, this will define useful things like RAM addr/size. */
-#include <asm/machdep.h>
-
-
-/* The following macros contain the usual definitions for various data areas.
- The prefix `RAMK_' is used to indicate macros suitable for kernels loaded
- into RAM, and similarly `ROMK_' for ROM-resident kernels. Note that all
- symbols are prefixed with an extra `_' for compatibility with the v850
- toolchain. */
-
-
-/* Interrupt vectors. */
-#define INTV_CONTENTS \
- . = ALIGN (0x10) ; \
- __intv_start = . ; \
- *(.intv.reset) /* Reset vector */ \
- . = __intv_start + 0x10 ; \
- *(.intv.common) /* Vectors common to all v850e proc */\
- . = __intv_start + 0x80 ; \
- *(.intv.mach) /* Machine-specific int. vectors. */ \
- __intv_end = . ;
-
-#define RODATA_CONTENTS \
- . = ALIGN (16) ; \
- *(.rodata) *(.rodata.*) \
- *(__vermagic) /* Kernel version magic */ \
- *(.rodata1) \
- /* PCI quirks */ \
- ___start_pci_fixups_early = . ; \
- *(.pci_fixup_early) \
- ___end_pci_fixups_early = . ; \
- ___start_pci_fixups_header = . ; \
- *(.pci_fixup_header) \
- ___end_pci_fixups_header = . ; \
- ___start_pci_fixups_final = . ; \
- *(.pci_fixup_final) \
- ___end_pci_fixups_final = . ; \
- ___start_pci_fixups_enable = . ; \
- *(.pci_fixup_enable) \
- ___end_pci_fixups_enable = . ; \
- /* Kernel symbol table: Normal symbols */ \
- ___start___ksymtab = .; \
- *(__ksymtab) \
- ___stop___ksymtab = .; \
- /* Kernel symbol table: GPL-only symbols */ \
- ___start___ksymtab_gpl = .; \
- *(__ksymtab_gpl) \
- ___stop___ksymtab_gpl = .; \
- /* Kernel symbol table: GPL-future symbols */ \
- ___start___ksymtab_gpl_future = .; \
- *(__ksymtab_gpl_future) \
- ___stop___ksymtab_gpl_future = .; \
- /* Kernel symbol table: strings */ \
- *(__ksymtab_strings) \
- /* Kernel symbol table: Normal symbols */ \
- ___start___kcrctab = .; \
- *(__kcrctab) \
- ___stop___kcrctab = .; \
- /* Kernel symbol table: GPL-only symbols */ \
- ___start___kcrctab_gpl = .; \
- *(__kcrctab_gpl) \
- ___stop___kcrctab_gpl = .; \
- /* Kernel symbol table: GPL-future symbols */ \
- ___start___kcrctab_gpl_future = .; \
- *(__kcrctab_gpl_future) \
- ___stop___kcrctab_gpl_future = .; \
- /* Built-in module parameters */ \
- . = ALIGN (4) ; \
- ___start___param = .; \
- *(__param) \
- ___stop___param = .;
-
-
-/* Kernel text segment, and some constant data areas. */
-#define TEXT_CONTENTS \
- _text = .; \
- __stext = . ; \
- TEXT_TEXT \
- SCHED_TEXT \
- *(.exit.text) /* 2.5 convention */ \
- *(.text.exit) /* 2.4 convention */ \
- *(.text.lock) \
- *(.exitcall.exit) \
- __real_etext = . ; /* There may be data after here. */ \
- RODATA_CONTENTS \
- . = ALIGN (4) ; \
- *(.call_table_data) \
- *(.call_table_text) \
- . = ALIGN (16) ; /* Exception table. */ \
- ___start___ex_table = . ; \
- *(__ex_table) \
- ___stop___ex_table = . ; \
- . = ALIGN (4) ; \
- __etext = . ;
-
-/* Kernel data segment. */
-#define DATA_CONTENTS \
- __sdata = . ; \
- DATA_DATA \
- EXIT_DATA /* 2.5 convention */ \
- *(.data.exit) /* 2.4 convention */ \
- . = ALIGN (16) ; \
- *(.data.cacheline_aligned) \
- . = ALIGN (0x2000) ; \
- *(.data.init_task) \
- . = ALIGN (0x2000) ; \
- __edata = . ;
-
-/* Kernel BSS segment. */
-#define BSS_CONTENTS \
- __sbss = . ; \
- *(.bss) \
- *(COMMON) \
- . = ALIGN (4) ; \
- __init_stack_end = . ; \
- __ebss = . ;
-
-/* `initcall' tables. */
-#define INITCALL_CONTENTS \
- . = ALIGN (16) ; \
- ___setup_start = . ; \
- *(.init.setup) /* 2.5 convention */ \
- *(.setup.init) /* 2.4 convention */ \
- ___setup_end = . ; \
- ___initcall_start = . ; \
- *(.initcall.init) \
- INITCALLS \
- . = ALIGN (4) ; \
- ___initcall_end = . ; \
- ___con_initcall_start = .; \
- *(.con_initcall.init) \
- ___con_initcall_end = .;
-
-/* Contents of `init' section for a kernel that's loaded into RAM. */
-#define RAMK_INIT_CONTENTS \
- RAMK_INIT_CONTENTS_NO_END \
- __init_end = . ;
-/* Same as RAMK_INIT_CONTENTS, but doesn't define the `__init_end' symbol. */
-#define RAMK_INIT_CONTENTS_NO_END \
- . = ALIGN (4096) ; \
- __init_start = . ; \
- __sinittext = .; \
- INIT_TEXT /* 2.5 convention */ \
- __einittext = .; \
- INIT_DATA \
- *(.text.init) /* 2.4 convention */ \
- *(.data.init) \
- INITCALL_CONTENTS \
- INITRAMFS_CONTENTS
-
-/* The contents of `init' section for a ROM-resident kernel which
- should go into RAM. */
-#define ROMK_INIT_RAM_CONTENTS \
- . = ALIGN (4096) ; \
- __init_start = . ; \
- INIT_DATA /* 2.5 convention */ \
- *(.data.init) /* 2.4 convention */ \
- __init_end = . ; \
- . = ALIGN (4096) ;
-
-/* The contents of `init' section for a ROM-resident kernel which
- should go into ROM. */
-#define ROMK_INIT_ROM_CONTENTS \
- _sinittext = .; \
- INIT_TEXT /* 2.5 convention */ \
- _einittext = .; \
- *(.text.init) /* 2.4 convention */ \
- INITCALL_CONTENTS \
- INITRAMFS_CONTENTS
-
-/* A root filesystem image, for kernels with an embedded root filesystem. */
-#define ROOT_FS_CONTENTS \
- __root_fs_image_start = . ; \
- *(.root) \
- __root_fs_image_end = . ;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-/* The initramfs archive. */
-#define INITRAMFS_CONTENTS \
- . = ALIGN (4) ; \
- ___initramfs_start = . ; \
- *(.init.ramfs) \
- ___initramfs_end = . ;
-#endif
-
-/* Where the initial bootmap (bitmap for the boot-time memory allocator)
- should be place. */
-#define BOOTMAP_CONTENTS \
- . = ALIGN (4096) ; \
- __bootmap = . ; \
- . = . + 4096 ; /* enough for 128MB. */
-
-/* The contents of a `typical' kram area for a kernel in RAM. */
-#define RAMK_KRAM_CONTENTS \
- __kram_start = . ; \
- TEXT_CONTENTS \
- DATA_CONTENTS \
- BSS_CONTENTS \
- RAMK_INIT_CONTENTS \
- __kram_end = . ; \
- BOOTMAP_CONTENTS
-
-
-/* Define output sections normally used for a ROM-resident kernel.
- ROM and RAM should be appropriate memory areas to use for kernel
- ROM and RAM data. This assumes that ROM starts at 0 (and thus can
- hold the interrupt vectors). */
-#define ROMK_SECTIONS(ROM, RAM) \
- .rom : { \
- INTV_CONTENTS \
- TEXT_CONTENTS \
- ROMK_INIT_ROM_CONTENTS \
- ROOT_FS_CONTENTS \
- } > ROM \
- \
- __rom_copy_src_start = . ; \
- \
- .data : { \
- __kram_start = . ; \
- __rom_copy_dst_start = . ; \
- DATA_CONTENTS \
- ROMK_INIT_RAM_CONTENTS \
- __rom_copy_dst_end = . ; \
- } > RAM AT> ROM \
- \
- .bss ALIGN (4) : { \
- BSS_CONTENTS \
- __kram_end = . ; \
- BOOTMAP_CONTENTS \
- } > RAM
-
-
-/* The 32-bit variable `jiffies' is just the lower 32-bits of `jiffies_64'. */
-_jiffies = _jiffies_64 ;
-
-
-/* Include an appropriate platform-dependent linker-script (which
- usually should use the above macros to do most of the work). */
-
-#ifdef CONFIG_V850E_SIM
-# include "sim.ld"
-#endif
-
-#ifdef CONFIG_V850E2_SIM85E2
-# include "sim85e2.ld"
-#endif
-
-#ifdef CONFIG_V850E2_FPGA85E2C
-# include "fpga85e2c.ld"
-#endif
-
-#ifdef CONFIG_V850E2_ANNA
-# ifdef CONFIG_ROM_KERNEL
-# include "anna-rom.ld"
-# else
-# include "anna.ld"
-# endif
-#endif
-
-#ifdef CONFIG_V850E_AS85EP1
-# ifdef CONFIG_ROM_KERNEL
-# include "as85ep1-rom.ld"
-# else
-# include "as85ep1.ld"
-# endif
-#endif
-
-#ifdef CONFIG_RTE_CB_MA1
-# ifdef CONFIG_ROM_KERNEL
-# include "rte_ma1_cb-rom.ld"
-# else
-# include "rte_ma1_cb.ld"
-# endif
-#endif
-
-#ifdef CONFIG_RTE_CB_NB85E
-# ifdef CONFIG_ROM_KERNEL
-# include "rte_nb85e_cb-rom.ld"
-# elif defined(CONFIG_RTE_CB_MULTI)
-# include "rte_nb85e_cb-multi.ld"
-# else
-# include "rte_nb85e_cb.ld"
-# endif
-#endif
-
-#ifdef CONFIG_RTE_CB_ME2
-# include "rte_me2_cb.ld"
-#endif
-
diff --git a/arch/v850/lib/Makefile b/arch/v850/lib/Makefile
deleted file mode 100644
index 1c78b728a11..00000000000
--- a/arch/v850/lib/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# arch/v850/lib/Makefile
-#
-
-lib-y = ashrdi3.o ashldi3.o lshrdi3.o muldi3.o negdi2.o \
- checksum.o memcpy.o memset.o
diff --git a/arch/v850/lib/ashldi3.c b/arch/v850/lib/ashldi3.c
deleted file mode 100644
index 9e792d53f0e..00000000000
--- a/arch/v850/lib/ashldi3.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* ashldi3.c extracted from gcc-2.95.2/libgcc2.c which is: */
-/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC 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, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#define BITS_PER_UNIT 8
-
-typedef int SItype __attribute__ ((mode (SI)));
-typedef unsigned int USItype __attribute__ ((mode (SI)));
-typedef int DItype __attribute__ ((mode (DI)));
-typedef int word_type __attribute__ ((mode (__word__)));
-
-struct DIstruct {SItype high, low;};
-
-typedef union
-{
- struct DIstruct s;
- DItype ll;
-} DIunion;
-
-DItype
-__ashldi3 (DItype u, word_type b)
-{
- DIunion w;
- word_type bm;
- DIunion uu;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- w.s.low = 0;
- w.s.high = (USItype)uu.s.low << -bm;
- }
- else
- {
- USItype carries = (USItype)uu.s.low >> bm;
- w.s.low = (USItype)uu.s.low << b;
- w.s.high = ((USItype)uu.s.high << b) | carries;
- }
-
- return w.ll;
-}
diff --git a/arch/v850/lib/ashrdi3.c b/arch/v850/lib/ashrdi3.c
deleted file mode 100644
index 78efb65e315..00000000000
--- a/arch/v850/lib/ashrdi3.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC 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, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#define BITS_PER_UNIT 8
-
-typedef int SItype __attribute__ ((mode (SI)));
-typedef unsigned int USItype __attribute__ ((mode (SI)));
-typedef int DItype __attribute__ ((mode (DI)));
-typedef int word_type __attribute__ ((mode (__word__)));
-
-struct DIstruct {SItype high, low;};
-
-typedef union
-{
- struct DIstruct s;
- DItype ll;
-} DIunion;
-
-DItype
-__ashrdi3 (DItype u, word_type b)
-{
- DIunion w;
- word_type bm;
- DIunion uu;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- /* w.s.high = 1..1 or 0..0 */
- w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
- w.s.low = uu.s.high >> -bm;
- }
- else
- {
- USItype carries = (USItype)uu.s.high << bm;
- w.s.high = uu.s.high >> b;
- w.s.low = ((USItype)uu.s.low >> b) | carries;
- }
-
- return w.ll;
-}
diff --git a/arch/v850/lib/checksum.c b/arch/v850/lib/checksum.c
deleted file mode 100644
index 042158dfe17..00000000000
--- a/arch/v850/lib/checksum.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * MIPS specific IP/TCP/UDP checksumming routines
- *
- * Authors: Ralf Baechle, <ralf@waldorf-gmbh.de>
- * Lots of code moved from tcp.c and ip.c; see those files
- * for more names.
- *
- * 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.
- *
- * $Id: checksum.c,v 1.1 2002/09/28 14:58:40 gerg Exp $
- */
-#include <net/checksum.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <asm/byteorder.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-static inline unsigned short from32to16 (unsigned long sum)
-{
- unsigned int result;
- /*
- %0 %1
- hsw %1, %0 H L L H
- add %1, %0 H L H+L+C H+L
- */
- asm ("hsw %1, %0; add %1, %0" : "=&r" (result) : "r" (sum));
- return result >> 16;
-}
-
-static inline unsigned int do_csum(const unsigned char * buff, int len)
-{
- int odd, count;
- unsigned int result = 0;
-
- if (len <= 0)
- goto out;
- odd = 1 & (unsigned long) buff;
- if (odd) {
- result = be16_to_cpu(*buff);
- len--;
- buff++;
- }
- count = len >> 1; /* nr of 16-bit words.. */
- if (count) {
- if (2 & (unsigned long) buff) {
- result += *(unsigned short *) buff;
- count--;
- len -= 2;
- buff += 2;
- }
- count >>= 1; /* nr of 32-bit words.. */
- if (count) {
- unsigned int carry = 0;
- do {
- unsigned int w = *(unsigned int *) buff;
- count--;
- buff += 4;
- result += carry;
- result += w;
- carry = (w > result);
- } while (count);
- result += carry;
- result = (result & 0xffff) + (result >> 16);
- }
- if (len & 2) {
- result += *(unsigned short *) buff;
- buff += 2;
- }
- }
- if (len & 1)
- result += le16_to_cpu(*buff);
- result = from32to16(result);
- if (odd)
- result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
-out:
- return result;
-}
-
-/*
- * This is a version of ip_compute_csum() optimized for IP headers,
- * which always checksum on 4 octet boundaries.
- */
-__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
- return (__force __sum16)~do_csum(iph,ihl*4);
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-__sum16 ip_compute_csum(const void *buff, int len)
-{
- return (__force __sum16)~do_csum(buff,len);
-}
-
-/*
- * computes a partial checksum, e.g. for TCP/UDP fragments
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum)
-{
- unsigned int result = do_csum(buff, len);
-
- /* add in old sum, and carry.. */
- result += (__force u32)sum;
- if ((__force u32)sum > result)
- result += 1;
- return (__force __wsum)result;
-}
-
-EXPORT_SYMBOL(csum_partial);
-
-/*
- * copy while checksumming, otherwise like csum_partial
- */
-__wsum csum_partial_copy_nocheck(const void *src, void *dst,
- int len, __wsum sum)
-{
- /*
- * It's 2:30 am and I don't feel like doing it real ...
- * This is lots slower than the real thing (tm)
- */
- sum = csum_partial(src, len, sum);
- memcpy(dst, src, len);
-
- return sum;
-}
-
-/*
- * Copy from userspace and compute checksum. If we catch an exception
- * then zero the rest of the buffer.
- */
-__wsum csum_partial_copy_from_user (const void *src,
- void *dst,
- int len, __wsum sum,
- int *err_ptr)
-{
- int missing;
-
- missing = copy_from_user(dst, src, len);
- if (missing) {
- memset(dst + len - missing, 0, missing);
- *err_ptr = -EFAULT;
- }
-
- return csum_partial(dst, len, sum);
-}
diff --git a/arch/v850/lib/lshrdi3.c b/arch/v850/lib/lshrdi3.c
deleted file mode 100644
index 93b1cb6fdee..00000000000
--- a/arch/v850/lib/lshrdi3.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC 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, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#define BITS_PER_UNIT 8
-
-typedef int SItype __attribute__ ((mode (SI)));
-typedef unsigned int USItype __attribute__ ((mode (SI)));
-typedef int DItype __attribute__ ((mode (DI)));
-typedef int word_type __attribute__ ((mode (__word__)));
-
-struct DIstruct {SItype high, low;};
-
-typedef union
-{
- struct DIstruct s;
- DItype ll;
-} DIunion;
-
-DItype
-__lshrdi3 (DItype u, word_type b)
-{
- DIunion w;
- word_type bm;
- DIunion uu;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- w.s.high = 0;
- w.s.low = (USItype)uu.s.high >> -bm;
- }
- else
- {
- USItype carries = (USItype)uu.s.high << bm;
- w.s.high = (USItype)uu.s.high >> b;
- w.s.low = ((USItype)uu.s.low >> b) | carries;
- }
-
- return w.ll;
-}
diff --git a/arch/v850/lib/memcpy.c b/arch/v850/lib/memcpy.c
deleted file mode 100644
index 492847b3e61..00000000000
--- a/arch/v850/lib/memcpy.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * arch/v850/lib/memcpy.c -- Memory copying
- *
- * Copyright (C) 2001,02 NEC Corporation
- * Copyright (C) 2001,02 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/types.h>
-#include <asm/string.h>
-
-#define CHUNK_SIZE 32 /* bytes */
-#define CHUNK_ALIGNED(addr) (((unsigned long)addr & 0x3) == 0)
-
-/* Note that this macro uses 8 call-clobbered registers (not including
- R1), which are few enough so that the following functions don't need
- to spill anything to memory. It also uses R1, which is nominally
- reserved for the assembler, but here it should be OK. */
-#define COPY_CHUNK(src, dst) \
- asm ("mov %0, ep;" \
- "sld.w 0[ep], r1; sld.w 4[ep], r12;" \
- "sld.w 8[ep], r13; sld.w 12[ep], r14;" \
- "sld.w 16[ep], r15; sld.w 20[ep], r17;" \
- "sld.w 24[ep], r18; sld.w 28[ep], r19;" \
- "mov %1, ep;" \
- "sst.w r1, 0[ep]; sst.w r12, 4[ep];" \
- "sst.w r13, 8[ep]; sst.w r14, 12[ep];" \
- "sst.w r15, 16[ep]; sst.w r17, 20[ep];" \
- "sst.w r18, 24[ep]; sst.w r19, 28[ep]" \
- :: "r" (src), "r" (dst) \
- : "r1", "r12", "r13", "r14", "r15", \
- "r17", "r18", "r19", "ep", "memory");
-
-void *memcpy (void *dst, const void *src, __kernel_size_t size)
-{
- char *_dst = dst;
- const char *_src = src;
-
- if (size >= CHUNK_SIZE && CHUNK_ALIGNED(_src) && CHUNK_ALIGNED(_dst)) {
- /* Copy large blocks efficiently. */
- unsigned count;
- for (count = size / CHUNK_SIZE; count; count--) {
- COPY_CHUNK (_src, _dst);
- _src += CHUNK_SIZE;
- _dst += CHUNK_SIZE;
- }
- size %= CHUNK_SIZE;
- }
-
- if (size > 0)
- do
- *_dst++ = *_src++;
- while (--size);
-
- return dst;
-}
-
-void *memmove (void *dst, const void *src, __kernel_size_t size)
-{
- if ((unsigned long)dst < (unsigned long)src
- || (unsigned long)src + size < (unsigned long)dst)
- return memcpy (dst, src, size);
- else {
- char *_dst = dst + size;
- const char *_src = src + size;
-
- if (size >= CHUNK_SIZE
- && CHUNK_ALIGNED (_src) && CHUNK_ALIGNED (_dst))
- {
- /* Copy large blocks efficiently. */
- unsigned count;
- for (count = size / CHUNK_SIZE; count; count--) {
- _src -= CHUNK_SIZE;
- _dst -= CHUNK_SIZE;
- COPY_CHUNK (_src, _dst);
- }
- size %= CHUNK_SIZE;
- }
-
- if (size > 0)
- do
- *--_dst = *--_src;
- while (--size);
-
- return _dst;
- }
-}
diff --git a/arch/v850/lib/memset.c b/arch/v850/lib/memset.c
deleted file mode 100644
index d1b2ad821b1..00000000000
--- a/arch/v850/lib/memset.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * arch/v850/lib/memset.c -- Memory initialization
- *
- * Copyright (C) 2001,02,04 NEC Corporation
- * Copyright (C) 2001,02,04 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/types.h>
-
-void *memset (void *dst, int val, __kernel_size_t count)
-{
- if (count) {
- register unsigned loop;
- register void *ptr asm ("ep") = dst;
-
- /* replicate VAL into a long. */
- val &= 0xff;
- val |= val << 8;
- val |= val << 16;
-
- /* copy initial unaligned bytes. */
- if ((long)ptr & 1) {
- *(char *)ptr = val;
- ptr = (void *)((char *)ptr + 1);
- count--;
- }
- if (count > 2 && ((long)ptr & 2)) {
- *(short *)ptr = val;
- ptr = (void *)((short *)ptr + 1);
- count -= 2;
- }
-
- /* 32-byte copying loop. */
- for (loop = count / 32; loop; loop--) {
- asm ("sst.w %0, 0[ep]; sst.w %0, 4[ep];"
- "sst.w %0, 8[ep]; sst.w %0, 12[ep];"
- "sst.w %0, 16[ep]; sst.w %0, 20[ep];"
- "sst.w %0, 24[ep]; sst.w %0, 28[ep]"
- :: "r" (val) : "memory");
- ptr += 32;
- }
- count %= 32;
-
- /* long copying loop. */
- for (loop = count / 4; loop; loop--) {
- *(long *)ptr = val;
- ptr = (void *)((long *)ptr + 1);
- }
- count %= 4;
-
- /* finish up with any trailing bytes. */
- if (count & 2) {
- *(short *)ptr = val;
- ptr = (void *)((short *)ptr + 1);
- }
- if (count & 1) {
- *(char *)ptr = val;
- }
- }
-
- return dst;
-}
diff --git a/arch/v850/lib/muldi3.c b/arch/v850/lib/muldi3.c
deleted file mode 100644
index 277ca25c82c..00000000000
--- a/arch/v850/lib/muldi3.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
- gcc-2.7.2.3/longlong.h which is: */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 2001 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC 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, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#define umul_ppmm(w1, w0, u, v) \
- __asm__ ("mulu %3, %0, %1" \
- : "=r" ((USItype)(w0)), \
- "=r" ((USItype)(w1)) \
- : "%0" ((USItype)(u)), \
- "r" ((USItype)(v)))
-
-#define __umulsidi3(u, v) \
- ({DIunion __w; \
- umul_ppmm (__w.s.high, __w.s.low, u, v); \
- __w.ll; })
-
-typedef int SItype __attribute__ ((mode (SI)));
-typedef unsigned int USItype __attribute__ ((mode (SI)));
-typedef int DItype __attribute__ ((mode (DI)));
-typedef int word_type __attribute__ ((mode (__word__)));
-
-struct DIstruct {SItype high, low;};
-
-typedef union
-{
- struct DIstruct s;
- DItype ll;
-} DIunion;
-
-DItype
-__muldi3 (DItype u, DItype v)
-{
- DIunion w;
- DIunion uu, vv;
-
- uu.ll = u,
- vv.ll = v;
-
- w.ll = __umulsidi3 (uu.s.low, vv.s.low);
- w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
- + (USItype) uu.s.high * (USItype) vv.s.low);
-
- return w.ll;
-}
diff --git a/arch/v850/lib/negdi2.c b/arch/v850/lib/negdi2.c
deleted file mode 100644
index 571e04fc619..00000000000
--- a/arch/v850/lib/negdi2.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * arch/v850/lib/negdi2.c -- 64-bit negation
- *
- * Copyright (C) 2001 NEC Corporation
- * Copyright (C) 2001 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-typedef int DItype __attribute__ ((mode (DI)));
-
-DItype __negdi2 (DItype x)
-{
- __asm__ __volatile__
- ("not r6, r10;"
- "add 1, r10;"
- "setf c, r6;"
- "not r7, r11;"
- "add r6, r11"
- ::: "r6", "r7", "r10", "r11");
-}
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 03980cb0429..e3cba0b4560 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -21,12 +21,15 @@ config X86
select HAVE_UNSTABLE_SCHED_CLOCK
select HAVE_IDE
select HAVE_OPROFILE
+ select HAVE_IOREMAP_PROT
select HAVE_KPROBES
+ select ARCH_WANT_OPTIONAL_GPIOLIB if !X86_RDC321X
select HAVE_KRETPROBES
select HAVE_DYNAMIC_FTRACE
select HAVE_FTRACE
select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
select HAVE_ARCH_KGDB if !X86_VOYAGER
+ select HAVE_EFFICIENT_UNALIGNED_ACCESS
config ARCH_DEFCONFIG
string
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index 54b8c02c71e..2c518fbc52e 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -414,4 +414,4 @@ config X86_MINIMUM_CPU_FAMILY
config X86_DEBUGCTLMSR
def_bool y
- depends on !(M586MMX || M586TSC || M586 || M486 || M386)
+ depends on !(MK6 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386)
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 3ee338c7d1d..aaf5a2131ef 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -182,8 +182,6 @@ static unsigned outcnt;
static int fill_inbuf(void);
static void flush_window(void);
static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
/*
* This is set up by the setup-routine at boot-time
@@ -196,9 +194,6 @@ extern int input_len;
static long bytes_out;
-static void *malloc(int size);
-static void free(void *where);
-
static void *memset(void *s, int c, unsigned n);
static void *memcpy(void *dest, const void *src, unsigned n);
@@ -220,40 +215,6 @@ static int lines, cols;
#include "../../../../lib/inflate.c"
-static void *malloc(int size)
-{
- void *p;
-
- if (size < 0)
- error("Malloc error");
- if (free_mem_ptr <= 0)
- error("Memory error");
-
- free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
- p = (void *)free_mem_ptr;
- free_mem_ptr += size;
-
- if (free_mem_ptr >= free_mem_end_ptr)
- error("Out of memory");
-
- return p;
-}
-
-static void free(void *where)
-{ /* Don't care */
-}
-
-static void gzip_mark(void **ptr)
-{
- *ptr = (void *) free_mem_ptr;
-}
-
-static void gzip_release(void **ptr)
-{
- free_mem_ptr = (memptr) *ptr;
-}
-
static void scroll(void)
{
int i;
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 23d146ce676..ffc1bb4fed7 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -15,6 +15,16 @@
#include <asm/irqflags.h>
#include <linux/linkage.h>
+/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
+#include <linux/elf-em.h>
+#define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE)
+#define __AUDIT_ARCH_LE 0x40000000
+
+#ifndef CONFIG_AUDITSYSCALL
+#define sysexit_audit int_ret_from_sys_call
+#define sysretl_audit int_ret_from_sys_call
+#endif
+
#define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8)
.macro IA32_ARG_FIXUP noebp=0
@@ -148,13 +158,15 @@ ENTRY(ia32_sysenter_target)
ja ia32_badsys
sysenter_do_call:
IA32_ARG_FIXUP 1
+sysenter_dispatch:
call *ia32_sys_call_table(,%rax,8)
movq %rax,RAX-ARGOFFSET(%rsp)
GET_THREAD_INFO(%r10)
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
testl $_TIF_ALLWORK_MASK,TI_flags(%r10)
- jnz int_ret_from_sys_call
+ jnz sysexit_audit
+sysexit_from_sys_call:
andl $~TS_COMPAT,TI_status(%r10)
/* clear IF, that popfq doesn't enable interrupts early */
andl $~0x200,EFLAGS-R11(%rsp)
@@ -170,9 +182,63 @@ sysenter_do_call:
TRACE_IRQS_ON
ENABLE_INTERRUPTS_SYSEXIT32
-sysenter_tracesys:
+#ifdef CONFIG_AUDITSYSCALL
+ .macro auditsys_entry_common
+ movl %esi,%r9d /* 6th arg: 4th syscall arg */
+ movl %edx,%r8d /* 5th arg: 3rd syscall arg */
+ /* (already in %ecx) 4th arg: 2nd syscall arg */
+ movl %ebx,%edx /* 3rd arg: 1st syscall arg */
+ movl %eax,%esi /* 2nd arg: syscall number */
+ movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */
+ call audit_syscall_entry
+ movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */
+ cmpl $(IA32_NR_syscalls-1),%eax
+ ja ia32_badsys
+ movl %ebx,%edi /* reload 1st syscall arg */
+ movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */
+ movl RDX-ARGOFFSET(%rsp),%edx /* reload 3rd syscall arg */
+ movl RSI-ARGOFFSET(%rsp),%ecx /* reload 4th syscall arg */
+ movl RDI-ARGOFFSET(%rsp),%r8d /* reload 5th syscall arg */
+ .endm
+
+ .macro auditsys_exit exit,ebpsave=RBP
+ testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
+ jnz int_ret_from_sys_call
+ TRACE_IRQS_ON
+ sti
+ movl %eax,%esi /* second arg, syscall return value */
+ cmpl $0,%eax /* is it < 0? */
+ setl %al /* 1 if so, 0 if not */
+ movzbl %al,%edi /* zero-extend that into %edi */
+ inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
+ call audit_syscall_exit
+ GET_THREAD_INFO(%r10)
+ movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall return value */
+ movl \ebpsave-ARGOFFSET(%rsp),%ebp /* reload user register value */
+ movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
+ cli
+ TRACE_IRQS_OFF
+ testl %edi,TI_flags(%r10)
+ jnz int_with_check
+ jmp \exit
+ .endm
+
+sysenter_auditsys:
CFI_RESTORE_STATE
+ auditsys_entry_common
+ movl %ebp,%r9d /* reload 6th syscall arg */
+ jmp sysenter_dispatch
+
+sysexit_audit:
+ auditsys_exit sysexit_from_sys_call
+#endif
+
+sysenter_tracesys:
xchgl %r9d,%ebp
+#ifdef CONFIG_AUDITSYSCALL
+ testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
+ jz sysenter_auditsys
+#endif
SAVE_REST
CLEAR_RREGS
movq %r9,R9(%rsp)
@@ -252,13 +318,15 @@ cstar_do_call:
cmpl $IA32_NR_syscalls-1,%eax
ja ia32_badsys
IA32_ARG_FIXUP 1
+cstar_dispatch:
call *ia32_sys_call_table(,%rax,8)
movq %rax,RAX-ARGOFFSET(%rsp)
GET_THREAD_INFO(%r10)
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
testl $_TIF_ALLWORK_MASK,TI_flags(%r10)
- jnz int_ret_from_sys_call
+ jnz sysretl_audit
+sysretl_from_sys_call:
andl $~TS_COMPAT,TI_status(%r10)
RESTORE_ARGS 1,-ARG_SKIP,1,1,1
movl RIP-ARGOFFSET(%rsp),%ecx
@@ -270,8 +338,23 @@ cstar_do_call:
CFI_RESTORE rsp
USERGS_SYSRET32
-cstar_tracesys:
+#ifdef CONFIG_AUDITSYSCALL
+cstar_auditsys:
CFI_RESTORE_STATE
+ movl %r9d,R9-ARGOFFSET(%rsp) /* register to be clobbered by call */
+ auditsys_entry_common
+ movl R9-ARGOFFSET(%rsp),%r9d /* reload 6th syscall arg */
+ jmp cstar_dispatch
+
+sysretl_audit:
+ auditsys_exit sysretl_from_sys_call, RCX /* user %ebp in RCX slot */
+#endif
+
+cstar_tracesys:
+#ifdef CONFIG_AUDITSYSCALL
+ testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
+ jz cstar_auditsys
+#endif
xchgl %r9d,%ebp
SAVE_REST
CLEAR_RREGS
@@ -743,4 +826,10 @@ ia32_sys_call_table:
.quad sys32_fallocate
.quad compat_sys_timerfd_settime /* 325 */
.quad compat_sys_timerfd_gettime
+ .quad compat_sys_signalfd4
+ .quad sys_eventfd2
+ .quad sys_epoll_create1
+ .quad sys_dup3 /* 330 */
+ .quad sys_pipe2
+ .quad sys_inotify_init1
ia32_syscall_end:
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
index f00afdf61e6..d3c64088b98 100644
--- a/arch/x86/ia32/sys_ia32.c
+++ b/arch/x86/ia32/sys_ia32.c
@@ -238,7 +238,7 @@ asmlinkage long sys32_pipe(int __user *fd)
int retval;
int fds[2];
- retval = do_pipe(fds);
+ retval = do_pipe_flags(fds, 0);
if (retval)
goto out;
if (copy_to_user(fd, fds, sizeof(fds)))
diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
index c2502eb9aa8..9220cf46aa1 100644
--- a/arch/x86/kernel/acpi/cstate.c
+++ b/arch/x86/kernel/acpi/cstate.c
@@ -73,6 +73,7 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
struct cpuinfo_x86 *c = &cpu_data(cpu);
cpumask_t saved_mask;
+ cpumask_of_cpu_ptr(new_mask, cpu);
int retval;
unsigned int eax, ebx, ecx, edx;
unsigned int edx_part;
@@ -91,7 +92,7 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
/* Make sure we are running on right CPU */
saved_mask = current->cpus_allowed;
- retval = set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ retval = set_cpus_allowed_ptr(current, new_mask);
if (retval)
return -1;
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index a3ddad18aaa..fa2161d5003 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -150,6 +150,10 @@ static int __init acpi_sleep_setup(char *str)
acpi_realmode_flags |= 2;
if (strncmp(str, "s3_beep", 7) == 0)
acpi_realmode_flags |= 4;
+#ifdef CONFIG_HIBERNATION
+ if (strncmp(str, "s4_nohwsig", 10) == 0)
+ acpi_no_s4_hw_signature();
+#endif
if (strncmp(str, "old_ordering", 12) == 0)
acpi_old_suspend_ordering();
str = strchr(str, ',');
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index bf9b441331e..9ee24e6bc4b 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -219,7 +219,6 @@
#include <linux/time.h>
#include <linux/sched.h>
#include <linux/pm.h>
-#include <linux/pm_legacy.h>
#include <linux/capability.h>
#include <linux/device.h>
#include <linux/kernel.h>
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
index b0c8208df9f..ff2fff56f0a 100644
--- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -200,10 +200,12 @@ static void drv_read(struct drv_cmd *cmd)
static void drv_write(struct drv_cmd *cmd)
{
cpumask_t saved_mask = current->cpus_allowed;
+ cpumask_of_cpu_ptr_declare(cpu_mask);
unsigned int i;
- for_each_cpu_mask(i, cmd->mask) {
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(i));
+ for_each_cpu_mask_nr(i, cmd->mask) {
+ cpumask_of_cpu_ptr_next(cpu_mask, i);
+ set_cpus_allowed_ptr(current, cpu_mask);
do_drv_write(cmd);
}
@@ -267,11 +269,12 @@ static unsigned int get_measured_perf(unsigned int cpu)
} aperf_cur, mperf_cur;
cpumask_t saved_mask;
+ cpumask_of_cpu_ptr(cpu_mask, cpu);
unsigned int perf_percent;
unsigned int retval;
saved_mask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ set_cpus_allowed_ptr(current, cpu_mask);
if (get_cpu() != cpu) {
/* We were not able to run on requested processor */
put_cpu();
@@ -337,6 +340,7 @@ static unsigned int get_measured_perf(unsigned int cpu)
static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
{
+ cpumask_of_cpu_ptr(cpu_mask, cpu);
struct acpi_cpufreq_data *data = per_cpu(drv_data, cpu);
unsigned int freq;
unsigned int cached_freq;
@@ -349,7 +353,7 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
}
cached_freq = data->freq_table[data->acpi_data->state].frequency;
- freq = extract_freq(get_cur_val(&cpumask_of_cpu(cpu)), data);
+ freq = extract_freq(get_cur_val(cpu_mask), data);
if (freq != cached_freq) {
/*
* The dreaded BIOS frequency change behind our back.
@@ -451,7 +455,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
freqs.old = perf->states[perf->state].core_frequency * 1000;
freqs.new = data->freq_table[next_state].frequency;
- for_each_cpu_mask(i, cmd.mask) {
+ for_each_cpu_mask_nr(i, cmd.mask) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
@@ -466,7 +470,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
}
}
- for_each_cpu_mask(i, cmd.mask) {
+ for_each_cpu_mask_nr(i, cmd.mask) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
index 199e4e05e5d..f1685fb91fb 100644
--- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
+++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
@@ -122,7 +122,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
return 0;
/* notifiers */
- for_each_cpu_mask(i, policy->cpus) {
+ for_each_cpu_mask_nr(i, policy->cpus) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
@@ -130,11 +130,11 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
/* run on each logical CPU, see section 13.15.3 of IA32 Intel Architecture Software
* Developer's Manual, Volume 3
*/
- for_each_cpu_mask(i, policy->cpus)
+ for_each_cpu_mask_nr(i, policy->cpus)
cpufreq_p4_setdc(i, p4clockmod_table[newstate].index);
/* notifiers */
- for_each_cpu_mask(i, policy->cpus) {
+ for_each_cpu_mask_nr(i, policy->cpus) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
index 206791eb46e..53c7b693697 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
@@ -479,11 +479,12 @@ static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvi
static int check_supported_cpu(unsigned int cpu)
{
cpumask_t oldmask;
+ cpumask_of_cpu_ptr(cpu_mask, cpu);
u32 eax, ebx, ecx, edx;
unsigned int rc = 0;
oldmask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ set_cpus_allowed_ptr(current, cpu_mask);
if (smp_processor_id() != cpu) {
printk(KERN_ERR PFX "limiting to cpu %u failed\n", cpu);
@@ -966,7 +967,7 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, unsigned i
freqs.old = find_khz_freq_from_fid(data->currfid);
freqs.new = find_khz_freq_from_fid(fid);
- for_each_cpu_mask(i, *(data->available_cores)) {
+ for_each_cpu_mask_nr(i, *(data->available_cores)) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
@@ -974,7 +975,7 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, unsigned i
res = transition_fid_vid(data, fid, vid);
freqs.new = find_khz_freq_from_fid(data->currfid);
- for_each_cpu_mask(i, *(data->available_cores)) {
+ for_each_cpu_mask_nr(i, *(data->available_cores)) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
@@ -997,7 +998,7 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned i
freqs.old = find_khz_freq_from_pstate(data->powernow_table, data->currpstate);
freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate);
- for_each_cpu_mask(i, *(data->available_cores)) {
+ for_each_cpu_mask_nr(i, *(data->available_cores)) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
@@ -1005,7 +1006,7 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned i
res = transition_pstate(data, pstate);
freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate);
- for_each_cpu_mask(i, *(data->available_cores)) {
+ for_each_cpu_mask_nr(i, *(data->available_cores)) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
@@ -1016,6 +1017,7 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned i
static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relation)
{
cpumask_t oldmask;
+ cpumask_of_cpu_ptr(cpu_mask, pol->cpu);
struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
u32 checkfid;
u32 checkvid;
@@ -1030,7 +1032,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
/* only run on specific CPU from here on */
oldmask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(pol->cpu));
+ set_cpus_allowed_ptr(current, cpu_mask);
if (smp_processor_id() != pol->cpu) {
printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
@@ -1105,6 +1107,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
{
struct powernow_k8_data *data;
cpumask_t oldmask;
+ cpumask_of_cpu_ptr_declare(newmask);
int rc;
if (!cpu_online(pol->cpu))
@@ -1156,7 +1159,8 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
/* only run on specific CPU from here on */
oldmask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(pol->cpu));
+ cpumask_of_cpu_ptr_next(newmask, pol->cpu);
+ set_cpus_allowed_ptr(current, newmask);
if (smp_processor_id() != pol->cpu) {
printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
@@ -1178,7 +1182,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
set_cpus_allowed_ptr(current, &oldmask);
if (cpu_family == CPU_HW_PSTATE)
- pol->cpus = cpumask_of_cpu(pol->cpu);
+ pol->cpus = *newmask;
else
pol->cpus = per_cpu(cpu_core_map, pol->cpu);
data->available_cores = &(pol->cpus);
@@ -1244,6 +1248,7 @@ static unsigned int powernowk8_get (unsigned int cpu)
{
struct powernow_k8_data *data;
cpumask_t oldmask = current->cpus_allowed;
+ cpumask_of_cpu_ptr(newmask, cpu);
unsigned int khz = 0;
unsigned int first;
@@ -1253,7 +1258,7 @@ static unsigned int powernowk8_get (unsigned int cpu)
if (!data)
return -EINVAL;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ set_cpus_allowed_ptr(current, newmask);
if (smp_processor_id() != cpu) {
printk(KERN_ERR PFX
"limiting to CPU %d failed in powernowk8_get\n", cpu);
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
index 908dd347c67..ca2ac13b7af 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -28,7 +28,8 @@
#define PFX "speedstep-centrino: "
#define MAINTAINER "cpufreq@lists.linux.org.uk"
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg)
+#define dprintk(msg...) \
+ cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg)
#define INTEL_MSR_RANGE (0xffff)
@@ -66,11 +67,12 @@ struct cpu_model
struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */
};
-static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x);
+static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c,
+ const struct cpu_id *x);
/* Operating points for current CPU */
-static struct cpu_model *centrino_model[NR_CPUS];
-static const struct cpu_id *centrino_cpu[NR_CPUS];
+static DEFINE_PER_CPU(struct cpu_model *, centrino_model);
+static DEFINE_PER_CPU(const struct cpu_id *, centrino_cpu);
static struct cpufreq_driver centrino_driver;
@@ -255,7 +257,7 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
return -ENOENT;
}
- centrino_model[policy->cpu] = model;
+ per_cpu(centrino_model, policy->cpu) = model;
dprintk("found \"%s\": max frequency: %dkHz\n",
model->model_name, model->max_freq);
@@ -264,10 +266,14 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
}
#else
-static inline int centrino_cpu_init_table(struct cpufreq_policy *policy) { return -ENODEV; }
+static inline int centrino_cpu_init_table(struct cpufreq_policy *policy)
+{
+ return -ENODEV;
+}
#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */
-static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x)
+static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c,
+ const struct cpu_id *x)
{
if ((c->x86 == x->x86) &&
(c->x86_model == x->x86_model) &&
@@ -286,23 +292,28 @@ static unsigned extract_clock(unsigned msr, unsigned int cpu, int failsafe)
* for centrino, as some DSDTs are buggy.
* Ideally, this can be done using the acpi_data structure.
*/
- if ((centrino_cpu[cpu] == &cpu_ids[CPU_BANIAS]) ||
- (centrino_cpu[cpu] == &cpu_ids[CPU_DOTHAN_A1]) ||
- (centrino_cpu[cpu] == &cpu_ids[CPU_DOTHAN_B0])) {
+ if ((per_cpu(centrino_cpu, cpu) == &cpu_ids[CPU_BANIAS]) ||
+ (per_cpu(centrino_cpu, cpu) == &cpu_ids[CPU_DOTHAN_A1]) ||
+ (per_cpu(centrino_cpu, cpu) == &cpu_ids[CPU_DOTHAN_B0])) {
msr = (msr >> 8) & 0xff;
return msr * 100000;
}
- if ((!centrino_model[cpu]) || (!centrino_model[cpu]->op_points))
+ if ((!per_cpu(centrino_model, cpu)) ||
+ (!per_cpu(centrino_model, cpu)->op_points))
return 0;
msr &= 0xffff;
- for (i=0;centrino_model[cpu]->op_points[i].frequency != CPUFREQ_TABLE_END; i++) {
- if (msr == centrino_model[cpu]->op_points[i].index)
- return centrino_model[cpu]->op_points[i].frequency;
+ for (i = 0;
+ per_cpu(centrino_model, cpu)->op_points[i].frequency
+ != CPUFREQ_TABLE_END;
+ i++) {
+ if (msr == per_cpu(centrino_model, cpu)->op_points[i].index)
+ return per_cpu(centrino_model, cpu)->
+ op_points[i].frequency;
}
if (failsafe)
- return centrino_model[cpu]->op_points[i-1].frequency;
+ return per_cpu(centrino_model, cpu)->op_points[i-1].frequency;
else
return 0;
}
@@ -313,9 +324,10 @@ static unsigned int get_cur_freq(unsigned int cpu)
unsigned l, h;
unsigned clock_freq;
cpumask_t saved_mask;
+ cpumask_of_cpu_ptr(new_mask, cpu);
saved_mask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ set_cpus_allowed_ptr(current, new_mask);
if (smp_processor_id() != cpu)
return 0;
@@ -347,7 +359,8 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
int i;
/* Only Intel makes Enhanced Speedstep-capable CPUs */
- if (cpu->x86_vendor != X86_VENDOR_INTEL || !cpu_has(cpu, X86_FEATURE_EST))
+ if (cpu->x86_vendor != X86_VENDOR_INTEL ||
+ !cpu_has(cpu, X86_FEATURE_EST))
return -ENODEV;
if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC))
@@ -361,9 +374,9 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
break;
if (i != N_IDS)
- centrino_cpu[policy->cpu] = &cpu_ids[i];
+ per_cpu(centrino_cpu, policy->cpu) = &cpu_ids[i];
- if (!centrino_cpu[policy->cpu]) {
+ if (!per_cpu(centrino_cpu, policy->cpu)) {
dprintk("found unsupported CPU with "
"Enhanced SpeedStep: send /proc/cpuinfo to "
MAINTAINER "\n");
@@ -386,23 +399,26 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
/* check to see if it stuck */
rdmsr(MSR_IA32_MISC_ENABLE, l, h);
if (!(l & (1<<16))) {
- printk(KERN_INFO PFX "couldn't enable Enhanced SpeedStep\n");
+ printk(KERN_INFO PFX
+ "couldn't enable Enhanced SpeedStep\n");
return -ENODEV;
}
}
freq = get_cur_freq(policy->cpu);
-
- policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */
+ policy->cpuinfo.transition_latency = 10000;
+ /* 10uS transition latency */
policy->cur = freq;
dprintk("centrino_cpu_init: cur=%dkHz\n", policy->cur);
- ret = cpufreq_frequency_table_cpuinfo(policy, centrino_model[policy->cpu]->op_points);
+ ret = cpufreq_frequency_table_cpuinfo(policy,
+ per_cpu(centrino_model, policy->cpu)->op_points);
if (ret)
return (ret);
- cpufreq_frequency_table_get_attr(centrino_model[policy->cpu]->op_points, policy->cpu);
+ cpufreq_frequency_table_get_attr(
+ per_cpu(centrino_model, policy->cpu)->op_points, policy->cpu);
return 0;
}
@@ -411,12 +427,12 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
{
unsigned int cpu = policy->cpu;
- if (!centrino_model[cpu])
+ if (!per_cpu(centrino_model, cpu))
return -ENODEV;
cpufreq_frequency_table_put_attr(cpu);
- centrino_model[cpu] = NULL;
+ per_cpu(centrino_model, cpu) = NULL;
return 0;
}
@@ -430,17 +446,26 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
*/
static int centrino_verify (struct cpufreq_policy *policy)
{
- return cpufreq_frequency_table_verify(policy, centrino_model[policy->cpu]->op_points);
+ return cpufreq_frequency_table_verify(policy,
+ per_cpu(centrino_model, policy->cpu)->op_points);
}
/**
* centrino_setpolicy - set a new CPUFreq policy
* @policy: new policy
* @target_freq: the target frequency
- * @relation: how that frequency relates to achieved frequency (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
+ * @relation: how that frequency relates to achieved frequency
+ * (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
*
* Sets a new CPUFreq policy.
*/
+struct allmasks {
+ cpumask_t online_policy_cpus;
+ cpumask_t saved_mask;
+ cpumask_t set_mask;
+ cpumask_t covered_cpus;
+};
+
static int centrino_target (struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
@@ -448,48 +473,55 @@ static int centrino_target (struct cpufreq_policy *policy,
unsigned int newstate = 0;
unsigned int msr, oldmsr = 0, h = 0, cpu = policy->cpu;
struct cpufreq_freqs freqs;
- cpumask_t online_policy_cpus;
- cpumask_t saved_mask;
- cpumask_t set_mask;
- cpumask_t covered_cpus;
int retval = 0;
unsigned int j, k, first_cpu, tmp;
-
- if (unlikely(centrino_model[cpu] == NULL))
- return -ENODEV;
+ CPUMASK_ALLOC(allmasks);
+ CPUMASK_PTR(online_policy_cpus, allmasks);
+ CPUMASK_PTR(saved_mask, allmasks);
+ CPUMASK_PTR(set_mask, allmasks);
+ CPUMASK_PTR(covered_cpus, allmasks);
+
+ if (unlikely(allmasks == NULL))
+ return -ENOMEM;
+
+ if (unlikely(per_cpu(centrino_model, cpu) == NULL)) {
+ retval = -ENODEV;
+ goto out;
+ }
if (unlikely(cpufreq_frequency_table_target(policy,
- centrino_model[cpu]->op_points,
+ per_cpu(centrino_model, cpu)->op_points,
target_freq,
relation,
&newstate))) {
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
}
#ifdef CONFIG_HOTPLUG_CPU
/* cpufreq holds the hotplug lock, so we are safe from here on */
- cpus_and(online_policy_cpus, cpu_online_map, policy->cpus);
+ cpus_and(*online_policy_cpus, cpu_online_map, policy->cpus);
#else
- online_policy_cpus = policy->cpus;
+ *online_policy_cpus = policy->cpus;
#endif
- saved_mask = current->cpus_allowed;
+ *saved_mask = current->cpus_allowed;
first_cpu = 1;
- cpus_clear(covered_cpus);
- for_each_cpu_mask(j, online_policy_cpus) {
+ cpus_clear(*covered_cpus);
+ for_each_cpu_mask_nr(j, *online_policy_cpus) {
/*
* Support for SMP systems.
* Make sure we are running on CPU that wants to change freq
*/
- cpus_clear(set_mask);
+ cpus_clear(*set_mask);
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
- cpus_or(set_mask, set_mask, online_policy_cpus);
+ cpus_or(*set_mask, *set_mask, *online_policy_cpus);
else
- cpu_set(j, set_mask);
+ cpu_set(j, *set_mask);
- set_cpus_allowed_ptr(current, &set_mask);
+ set_cpus_allowed_ptr(current, set_mask);
preempt_disable();
- if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) {
+ if (unlikely(!cpu_isset(smp_processor_id(), *set_mask))) {
dprintk("couldn't limit to CPUs in this domain\n");
retval = -EAGAIN;
if (first_cpu) {
@@ -500,7 +532,7 @@ static int centrino_target (struct cpufreq_policy *policy,
break;
}
- msr = centrino_model[cpu]->op_points[newstate].index;
+ msr = per_cpu(centrino_model, cpu)->op_points[newstate].index;
if (first_cpu) {
rdmsr(MSR_IA32_PERF_CTL, oldmsr, h);
@@ -517,7 +549,7 @@ static int centrino_target (struct cpufreq_policy *policy,
dprintk("target=%dkHz old=%d new=%d msr=%04x\n",
target_freq, freqs.old, freqs.new, msr);
- for_each_cpu_mask(k, online_policy_cpus) {
+ for_each_cpu_mask_nr(k, *online_policy_cpus) {
freqs.cpu = k;
cpufreq_notify_transition(&freqs,
CPUFREQ_PRECHANGE);
@@ -536,11 +568,11 @@ static int centrino_target (struct cpufreq_policy *policy,
break;
}
- cpu_set(j, covered_cpus);
+ cpu_set(j, *covered_cpus);
preempt_enable();
}
- for_each_cpu_mask(k, online_policy_cpus) {
+ for_each_cpu_mask_nr(k, *online_policy_cpus) {
freqs.cpu = k;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
@@ -553,10 +585,12 @@ static int centrino_target (struct cpufreq_policy *policy,
* Best effort undo..
*/
- if (!cpus_empty(covered_cpus)) {
- for_each_cpu_mask(j, covered_cpus) {
- set_cpus_allowed_ptr(current,
- &cpumask_of_cpu(j));
+ if (!cpus_empty(*covered_cpus)) {
+ cpumask_of_cpu_ptr_declare(new_mask);
+
+ for_each_cpu_mask_nr(j, *covered_cpus) {
+ cpumask_of_cpu_ptr_next(new_mask, j);
+ set_cpus_allowed_ptr(current, new_mask);
wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
}
}
@@ -564,19 +598,22 @@ static int centrino_target (struct cpufreq_policy *policy,
tmp = freqs.new;
freqs.new = freqs.old;
freqs.old = tmp;
- for_each_cpu_mask(j, online_policy_cpus) {
+ for_each_cpu_mask_nr(j, *online_policy_cpus) {
freqs.cpu = j;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
}
- set_cpus_allowed_ptr(current, &saved_mask);
- return 0;
+ set_cpus_allowed_ptr(current, saved_mask);
+ retval = 0;
+ goto out;
migrate_end:
preempt_enable();
- set_cpus_allowed_ptr(current, &saved_mask);
- return 0;
+ set_cpus_allowed_ptr(current, saved_mask);
+out:
+ CPUMASK_FREE(allmasks);
+ return retval;
}
static struct freq_attr* centrino_attr[] = {
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
index 1b50244b1fd..2f3728dc24f 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
@@ -244,7 +244,8 @@ static unsigned int _speedstep_get(const cpumask_t *cpus)
static unsigned int speedstep_get(unsigned int cpu)
{
- return _speedstep_get(&cpumask_of_cpu(cpu));
+ cpumask_of_cpu_ptr(newmask, cpu);
+ return _speedstep_get(newmask);
}
/**
@@ -279,7 +280,7 @@ static int speedstep_target (struct cpufreq_policy *policy,
cpus_allowed = current->cpus_allowed;
- for_each_cpu_mask(i, policy->cpus) {
+ for_each_cpu_mask_nr(i, policy->cpus) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
@@ -292,7 +293,7 @@ static int speedstep_target (struct cpufreq_policy *policy,
/* allow to be run on all CPUs */
set_cpus_allowed_ptr(current, &cpus_allowed);
- for_each_cpu_mask(i, policy->cpus) {
+ for_each_cpu_mask_nr(i, policy->cpus) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index ff517f0b8cc..650d40f7912 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -489,7 +489,7 @@ static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index)
int sibling;
this_leaf = CPUID4_INFO_IDX(cpu, index);
- for_each_cpu_mask(sibling, this_leaf->shared_cpu_map) {
+ for_each_cpu_mask_nr(sibling, this_leaf->shared_cpu_map) {
sibling_leaf = CPUID4_INFO_IDX(sibling, index);
cpu_clear(cpu, sibling_leaf->shared_cpu_map);
}
@@ -516,6 +516,7 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu)
unsigned long j;
int retval;
cpumask_t oldmask;
+ cpumask_of_cpu_ptr(newmask, cpu);
if (num_cache_leaves == 0)
return -ENOENT;
@@ -526,7 +527,7 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu)
return -ENOMEM;
oldmask = current->cpus_allowed;
- retval = set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ retval = set_cpus_allowed_ptr(current, newmask);
if (retval)
goto out;
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c
index c4a7ec31394..65a339678ec 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_64.c
@@ -580,7 +580,7 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize,
char __user *buf = ubuf;
int i, err;
- cpu_tsc = kmalloc(NR_CPUS * sizeof(long), GFP_KERNEL);
+ cpu_tsc = kmalloc(nr_cpu_ids * sizeof(long), GFP_KERNEL);
if (!cpu_tsc)
return -ENOMEM;
@@ -762,10 +762,14 @@ DEFINE_PER_CPU(struct sys_device, device_mce);
/* Why are there no generic functions for this? */
#define ACCESSOR(name, var, start) \
- static ssize_t show_ ## name(struct sys_device *s, char *buf) { \
+ static ssize_t show_ ## name(struct sys_device *s, \
+ struct sysdev_attribute *attr, \
+ char *buf) { \
return sprintf(buf, "%lx\n", (unsigned long)var); \
} \
- static ssize_t set_ ## name(struct sys_device *s,const char *buf,size_t siz) { \
+ static ssize_t set_ ## name(struct sys_device *s, \
+ struct sysdev_attribute *attr, \
+ const char *buf, size_t siz) { \
char *end; \
unsigned long new = simple_strtoul(buf, &end, 0); \
if (end == buf) return -EINVAL; \
@@ -786,14 +790,16 @@ ACCESSOR(bank3ctl,bank[3],mce_restart())
ACCESSOR(bank4ctl,bank[4],mce_restart())
ACCESSOR(bank5ctl,bank[5],mce_restart())
-static ssize_t show_trigger(struct sys_device *s, char *buf)
+static ssize_t show_trigger(struct sys_device *s, struct sysdev_attribute *attr,
+ char *buf)
{
strcpy(buf, trigger);
strcat(buf, "\n");
return strlen(trigger) + 1;
}
-static ssize_t set_trigger(struct sys_device *s,const char *buf,size_t siz)
+static ssize_t set_trigger(struct sys_device *s, struct sysdev_attribute *attr,
+ const char *buf,size_t siz)
{
char *p;
int len;
@@ -806,12 +812,12 @@ static ssize_t set_trigger(struct sys_device *s,const char *buf,size_t siz)
}
static SYSDEV_ATTR(trigger, 0644, show_trigger, set_trigger);
-ACCESSOR(tolerant,tolerant,)
+static SYSDEV_INT_ATTR(tolerant, 0644, tolerant);
ACCESSOR(check_interval,check_interval,mce_restart())
static struct sysdev_attribute *mce_attributes[] = {
&attr_bank0ctl, &attr_bank1ctl, &attr_bank2ctl,
&attr_bank3ctl, &attr_bank4ctl, &attr_bank5ctl,
- &attr_tolerant, &attr_check_interval, &attr_trigger,
+ &attr_tolerant.attr, &attr_check_interval, &attr_trigger,
NULL
};
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
index 7c9a813e119..88736cadbaa 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
@@ -527,7 +527,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
if (err)
goto out_free;
- for_each_cpu_mask(i, b->cpus) {
+ for_each_cpu_mask_nr(i, b->cpus) {
if (i == cpu)
continue;
@@ -617,7 +617,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank)
#endif
/* remove all sibling symlinks before unregistering */
- for_each_cpu_mask(i, b->cpus) {
+ for_each_cpu_mask_nr(i, b->cpus) {
if (i == cpu)
continue;
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index 1f4cc48c14c..d5ae2243f0b 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -35,6 +35,7 @@ atomic_t therm_throt_en = ATOMIC_INIT(0);
#define define_therm_throt_sysdev_show_func(name) \
static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev, \
+ struct sysdev_attribute *attr, \
char *buf) \
{ \
unsigned int cpu = dev->id; \
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index 0d0d9057e7c..a26c480b949 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -160,7 +160,7 @@ static void *c_start(struct seq_file *m, loff_t *pos)
{
if (*pos == 0) /* just in case, cpu 0 is not the first */
*pos = first_cpu(cpu_online_map);
- if ((*pos) < NR_CPUS && cpu_online(*pos))
+ if ((*pos) < nr_cpu_ids && cpu_online(*pos))
return &cpu_data(*pos);
return NULL;
}
diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c
index 2de5fa2bbf7..14b11b3be31 100644
--- a/arch/x86/kernel/cpuid.c
+++ b/arch/x86/kernel/cpuid.c
@@ -141,8 +141,8 @@ static __cpuinit int cpuid_device_create(int cpu)
{
struct device *dev;
- dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu),
- "cpu%d", cpu);
+ dev = device_create_drvdata(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu),
+ NULL, "cpu%d", cpu);
return IS_ERR(dev) ? PTR_ERR(dev) : 0;
}
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index cdfd94cc6b1..109792bc7cf 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -54,6 +54,16 @@
#include <asm/ftrace.h>
#include <asm/irq_vectors.h>
+/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
+#include <linux/elf-em.h>
+#define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE)
+#define __AUDIT_ARCH_LE 0x40000000
+
+#ifndef CONFIG_AUDITSYSCALL
+#define sysenter_audit syscall_trace_entry
+#define sysexit_audit syscall_exit_work
+#endif
+
/*
* We use macros for low-level operations which need to be overridden
* for paravirtualization. The following will never clobber any registers:
@@ -333,7 +343,8 @@ sysenter_past_esp:
/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
- jnz syscall_trace_entry
+ jnz sysenter_audit
+sysenter_do_call:
cmpl $(nr_syscalls), %eax
jae syscall_badsys
call *sys_call_table(,%eax,4)
@@ -343,7 +354,8 @@ sysenter_past_esp:
TRACE_IRQS_OFF
movl TI_flags(%ebp), %ecx
testw $_TIF_ALLWORK_MASK, %cx
- jne syscall_exit_work
+ jne sysexit_audit
+sysenter_exit:
/* if something modifies registers it must also disable sysexit */
movl PT_EIP(%esp), %edx
movl PT_OLDESP(%esp), %ecx
@@ -351,6 +363,45 @@ sysenter_past_esp:
TRACE_IRQS_ON
1: mov PT_FS(%esp), %fs
ENABLE_INTERRUPTS_SYSEXIT
+
+#ifdef CONFIG_AUDITSYSCALL
+sysenter_audit:
+ testw $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+ jnz syscall_trace_entry
+ addl $4,%esp
+ CFI_ADJUST_CFA_OFFSET -4
+ /* %esi already in 8(%esp) 6th arg: 4th syscall arg */
+ /* %edx already in 4(%esp) 5th arg: 3rd syscall arg */
+ /* %ecx already in 0(%esp) 4th arg: 2nd syscall arg */
+ movl %ebx,%ecx /* 3rd arg: 1st syscall arg */
+ movl %eax,%edx /* 2nd arg: syscall number */
+ movl $AUDIT_ARCH_I386,%eax /* 1st arg: audit arch */
+ call audit_syscall_entry
+ pushl %ebx
+ CFI_ADJUST_CFA_OFFSET 4
+ movl PT_EAX(%esp),%eax /* reload syscall number */
+ jmp sysenter_do_call
+
+sysexit_audit:
+ testw $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %cx
+ jne syscall_exit_work
+ TRACE_IRQS_ON
+ ENABLE_INTERRUPTS(CLBR_ANY)
+ movl %eax,%edx /* second arg, syscall return value */
+ cmpl $0,%eax /* is it < 0? */
+ setl %al /* 1 if so, 0 if not */
+ movzbl %al,%eax /* zero-extend that */
+ inc %eax /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
+ call audit_syscall_exit
+ DISABLE_INTERRUPTS(CLBR_ANY)
+ TRACE_IRQS_OFF
+ movl TI_flags(%ebp), %ecx
+ testw $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %cx
+ jne syscall_exit_work
+ movl PT_EAX(%esp),%eax /* reload syscall return value */
+ jmp sysenter_exit
+#endif
+
CFI_ENDPROC
.pushsection .fixup,"ax"
2: movl $0,PT_FS(%esp)
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 8410e26f418..89434d43960 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -53,6 +53,12 @@
#include <asm/paravirt.h>
#include <asm/ftrace.h>
+/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
+#include <linux/elf-em.h>
+#define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+#define __AUDIT_ARCH_64BIT 0x80000000
+#define __AUDIT_ARCH_LE 0x40000000
+
.code64
#ifdef CONFIG_FTRACE
@@ -351,6 +357,7 @@ ENTRY(system_call_after_swapgs)
GET_THREAD_INFO(%rcx)
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%rcx)
jnz tracesys
+system_call_fastpath:
cmpq $__NR_syscall_max,%rax
ja badsys
movq %r10,%rcx
@@ -402,16 +409,16 @@ sysret_careful:
sysret_signal:
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_NONE)
- testl $_TIF_DO_NOTIFY_MASK,%edx
- jz 1f
-
- /* Really a signal */
+#ifdef CONFIG_AUDITSYSCALL
+ bt $TIF_SYSCALL_AUDIT,%edx
+ jc sysret_audit
+#endif
/* edx: work flags (arg3) */
leaq do_notify_resume(%rip),%rax
leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
xorl %esi,%esi # oldset -> arg2
call ptregscall_common
-1: movl $_TIF_WORK_MASK,%edi
+ movl $_TIF_WORK_MASK,%edi
/* Use IRET because user could have changed frame. This
works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
DISABLE_INTERRUPTS(CLBR_NONE)
@@ -422,8 +429,45 @@ badsys:
movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
jmp ret_from_sys_call
+#ifdef CONFIG_AUDITSYSCALL
+ /*
+ * Fast path for syscall audit without full syscall trace.
+ * We just call audit_syscall_entry() directly, and then
+ * jump back to the normal fast path.
+ */
+auditsys:
+ movq %r10,%r9 /* 6th arg: 4th syscall arg */
+ movq %rdx,%r8 /* 5th arg: 3rd syscall arg */
+ movq %rsi,%rcx /* 4th arg: 2nd syscall arg */
+ movq %rdi,%rdx /* 3rd arg: 1st syscall arg */
+ movq %rax,%rsi /* 2nd arg: syscall number */
+ movl $AUDIT_ARCH_X86_64,%edi /* 1st arg: audit arch */
+ call audit_syscall_entry
+ LOAD_ARGS 0 /* reload call-clobbered registers */
+ jmp system_call_fastpath
+
+ /*
+ * Return fast path for syscall audit. Call audit_syscall_exit()
+ * directly and then jump back to the fast path with TIF_SYSCALL_AUDIT
+ * masked off.
+ */
+sysret_audit:
+ movq %rax,%rsi /* second arg, syscall return value */
+ cmpq $0,%rax /* is it < 0? */
+ setl %al /* 1 if so, 0 if not */
+ movzbl %al,%edi /* zero-extend that into %edi */
+ inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
+ call audit_syscall_exit
+ movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
+ jmp sysret_check
+#endif /* CONFIG_AUDITSYSCALL */
+
/* Do syscall tracing */
tracesys:
+#ifdef CONFIG_AUDITSYSCALL
+ testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
+ jz auditsys
+#endif
SAVE_REST
movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
FIXUP_TOP_OF_STACK %rdi
@@ -448,6 +492,7 @@ tracesys:
* Has correct top of stack, but partial stack frame.
*/
.globl int_ret_from_sys_call
+ .globl int_with_check
int_ret_from_sys_call:
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c
index 1a9c68845ee..786548a62d3 100644
--- a/arch/x86/kernel/genapic_flat_64.c
+++ b/arch/x86/kernel/genapic_flat_64.c
@@ -168,7 +168,7 @@ static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask)
* May as well be the first.
*/
cpu = first_cpu(cpumask);
- if ((unsigned)cpu < NR_CPUS)
+ if ((unsigned)cpu < nr_cpu_ids)
return per_cpu(x86_cpu_to_apicid, cpu);
else
return BAD_APICID;
diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c
index 3c392934069..2cfcbded888 100644
--- a/arch/x86/kernel/genx2apic_uv_x.c
+++ b/arch/x86/kernel/genx2apic_uv_x.c
@@ -98,7 +98,7 @@ static void uv_send_IPI_mask(cpumask_t mask, int vector)
{
unsigned int cpu;
- for (cpu = 0; cpu < NR_CPUS; ++cpu)
+ for_each_possible_cpu(cpu)
if (cpu_isset(cpu, mask))
uv_send_IPI_one(cpu, vector);
}
@@ -132,7 +132,7 @@ static unsigned int uv_cpu_mask_to_apicid(cpumask_t cpumask)
* May as well be the first.
*/
cpu = first_cpu(cpumask);
- if ((unsigned)cpu < NR_CPUS)
+ if ((unsigned)cpu < nr_cpu_ids)
return per_cpu(x86_cpu_to_apicid, cpu);
else
return BAD_APICID;
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 0ea6a19bfdf..ad2b15a1334 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -468,7 +468,7 @@ void hpet_disable(void)
#define RTC_NUM_INTS 1
static unsigned long hpet_rtc_flags;
-static unsigned long hpet_prev_update_sec;
+static int hpet_prev_update_sec;
static struct rtc_time hpet_alarm_time;
static unsigned long hpet_pie_count;
static unsigned long hpet_t1_cmp;
@@ -575,6 +575,9 @@ int hpet_set_rtc_irq_bit(unsigned long bit_mask)
hpet_rtc_flags |= bit_mask;
+ if ((bit_mask & RTC_UIE) && !(oldbits & RTC_UIE))
+ hpet_prev_update_sec = -1;
+
if (!oldbits)
hpet_rtc_timer_init();
@@ -652,7 +655,7 @@ static void hpet_rtc_timer_reinit(void)
if (hpet_rtc_flags & RTC_PIE)
hpet_pie_count += lost_ints;
if (printk_ratelimit())
- printk(KERN_WARNING "rtc: lost %d interrupts\n",
+ printk(KERN_WARNING "hpet1: lost %d rtc interrupts\n",
lost_ints);
}
}
@@ -670,7 +673,8 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
if (hpet_rtc_flags & RTC_UIE &&
curr_time.tm_sec != hpet_prev_update_sec) {
- rtc_int_flag = RTC_UF;
+ if (hpet_prev_update_sec >= 0)
+ rtc_int_flag = RTC_UF;
hpet_prev_update_sec = curr_time.tm_sec;
}
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
index 64a46affd85..8269434d170 100644
--- a/arch/x86/kernel/io_apic_64.c
+++ b/arch/x86/kernel/io_apic_64.c
@@ -732,7 +732,7 @@ static int __assign_irq_vector(int irq, cpumask_t mask)
return 0;
}
- for_each_cpu_mask(cpu, mask) {
+ for_each_cpu_mask_nr(cpu, mask) {
cpumask_t domain, new_mask;
int new_cpu;
int vector, offset;
@@ -753,7 +753,7 @@ next:
continue;
if (vector == IA32_SYSCALL_VECTOR)
goto next;
- for_each_cpu_mask(new_cpu, new_mask)
+ for_each_cpu_mask_nr(new_cpu, new_mask)
if (per_cpu(vector_irq, new_cpu)[vector] != -1)
goto next;
/* Found one! */
@@ -763,7 +763,7 @@ next:
cfg->move_in_progress = 1;
cfg->old_domain = cfg->domain;
}
- for_each_cpu_mask(new_cpu, new_mask)
+ for_each_cpu_mask_nr(new_cpu, new_mask)
per_cpu(vector_irq, new_cpu)[vector] = irq;
cfg->vector = vector;
cfg->domain = domain;
@@ -795,7 +795,7 @@ static void __clear_irq_vector(int irq)
vector = cfg->vector;
cpus_and(mask, cfg->domain, cpu_online_map);
- for_each_cpu_mask(cpu, mask)
+ for_each_cpu_mask_nr(cpu, mask)
per_cpu(vector_irq, cpu)[vector] = -1;
cfg->vector = 0;
@@ -1373,12 +1373,10 @@ static unsigned int startup_ioapic_irq(unsigned int irq)
static int ioapic_retrigger_irq(unsigned int irq)
{
struct irq_cfg *cfg = &irq_cfg[irq];
- cpumask_t mask;
unsigned long flags;
spin_lock_irqsave(&vector_lock, flags);
- mask = cpumask_of_cpu(first_cpu(cfg->domain));
- send_IPI_mask(mask, cfg->vector);
+ send_IPI_mask(cpumask_of_cpu(first_cpu(cfg->domain)), cfg->vector);
spin_unlock_irqrestore(&vector_lock, flags);
return 1;
diff --git a/arch/x86/kernel/irqinit_64.c b/arch/x86/kernel/irqinit_64.c
index 0373e88de95..1f26fd9ec4f 100644
--- a/arch/x86/kernel/irqinit_64.c
+++ b/arch/x86/kernel/irqinit_64.c
@@ -43,10 +43,11 @@
#define BUILD_IRQ(nr) \
asmlinkage void IRQ_NAME(nr); \
- asm("\n.p2align\n" \
+ asm("\n.text\n.p2align\n" \
"IRQ" #nr "_interrupt:\n\t" \
"push $~(" #nr ") ; " \
- "jmp common_interrupt");
+ "jmp common_interrupt\n" \
+ ".previous");
#define BI(x,y) \
BUILD_IRQ(x##y)
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index 43c019f85f0..6c27679ec6a 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -431,7 +431,6 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
regs->ip = (unsigned long)p->ainsn.insn;
}
-/* Called with kretprobe_lock held */
void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
struct pt_regs *regs)
{
@@ -682,8 +681,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
INIT_HLIST_HEAD(&empty_rp);
- spin_lock_irqsave(&kretprobe_lock, flags);
- head = kretprobe_inst_table_head(current);
+ kretprobe_hash_lock(current, &head, &flags);
/* fixup registers */
#ifdef CONFIG_X86_64
regs->cs = __KERNEL_CS;
@@ -732,7 +730,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
kretprobe_assert(ri, orig_ret_address, trampoline_address);
- spin_unlock_irqrestore(&kretprobe_lock, flags);
+ kretprobe_hash_unlock(current, &flags);
hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
hlist_del(&ri->hlist);
diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index a8449571858..3fee2aa50f3 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -62,12 +62,12 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
if (reload) {
#ifdef CONFIG_SMP
- cpumask_t mask;
+ cpumask_of_cpu_ptr_declare(mask);
preempt_disable();
load_LDT(pc);
- mask = cpumask_of_cpu(smp_processor_id());
- if (!cpus_equal(current->mm->cpu_vm_mask, mask))
+ cpumask_of_cpu_ptr_next(mask, smp_processor_id());
+ if (!cpus_equal(current->mm->cpu_vm_mask, *mask))
smp_call_function(flush_ldt, current->mm, 1);
preempt_enable();
#else
diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
index 56b933119a0..6994c751590 100644
--- a/arch/x86/kernel/microcode.c
+++ b/arch/x86/kernel/microcode.c
@@ -388,6 +388,7 @@ static int do_microcode_update (void)
void *new_mc = NULL;
int cpu;
cpumask_t old;
+ cpumask_of_cpu_ptr_declare(newmask);
old = current->cpus_allowed;
@@ -404,7 +405,8 @@ static int do_microcode_update (void)
if (!uci->valid)
continue;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ cpumask_of_cpu_ptr_next(newmask, cpu);
+ set_cpus_allowed_ptr(current, newmask);
error = get_maching_microcode(new_mc, cpu);
if (error < 0)
goto out;
@@ -574,6 +576,7 @@ static int apply_microcode_check_cpu(int cpu)
struct cpuinfo_x86 *c = &cpu_data(cpu);
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
cpumask_t old;
+ cpumask_of_cpu_ptr(newmask, cpu);
unsigned int val[2];
int err = 0;
@@ -582,7 +585,7 @@ static int apply_microcode_check_cpu(int cpu)
return 0;
old = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ set_cpus_allowed_ptr(current, newmask);
/* Check if the microcode we have in memory matches the CPU */
if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
@@ -620,11 +623,12 @@ static int apply_microcode_check_cpu(int cpu)
static void microcode_init_cpu(int cpu, int resume)
{
cpumask_t old;
+ cpumask_of_cpu_ptr(newmask, cpu);
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
old = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ set_cpus_allowed_ptr(current, newmask);
mutex_lock(&microcode_mutex);
collect_cpu_info(cpu);
if (uci->valid && system_state == SYSTEM_RUNNING && !resume)
@@ -644,7 +648,9 @@ static void microcode_fini_cpu(int cpu)
mutex_unlock(&microcode_mutex);
}
-static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
+static ssize_t reload_store(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ const char *buf, size_t sz)
{
struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
char *end;
@@ -656,11 +662,12 @@ static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
return -EINVAL;
if (val == 1) {
cpumask_t old;
+ cpumask_of_cpu_ptr(newmask, cpu);
old = current->cpus_allowed;
get_online_cpus();
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ set_cpus_allowed_ptr(current, newmask);
mutex_lock(&microcode_mutex);
if (uci->valid)
@@ -674,14 +681,16 @@ static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
return sz;
}
-static ssize_t version_show(struct sys_device *dev, char *buf)
+static ssize_t version_show(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
return sprintf(buf, "0x%x\n", uci->rev);
}
-static ssize_t pf_show(struct sys_device *dev, char *buf)
+static ssize_t pf_show(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
diff --git a/arch/x86/kernel/module_64.c b/arch/x86/kernel/module_64.c
index 0e867676b5a..6ba87830d4b 100644
--- a/arch/x86/kernel/module_64.c
+++ b/arch/x86/kernel/module_64.c
@@ -22,6 +22,7 @@
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/bug.h>
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
index a153b3905f6..9fd80955244 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -149,8 +149,8 @@ static int __cpuinit msr_device_create(int cpu)
{
struct device *dev;
- dev = device_create(msr_class, NULL, MKDEV(MSR_MAJOR, cpu),
- "msr%d", cpu);
+ dev = device_create_drvdata(msr_class, NULL, MKDEV(MSR_MAJOR, cpu),
+ NULL, "msr%d", cpu);
return IS_ERR(dev) ? PTR_ERR(dev) : 0;
}
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 097d8a6797f..94da4d52d79 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -443,7 +443,7 @@ struct pv_mmu_ops pv_mmu_ops = {
#endif /* PAGETABLE_LEVELS >= 3 */
.pte_val = native_pte_val,
- .pte_flags = native_pte_val,
+ .pte_flags = native_pte_flags,
.pgd_val = native_pgd_val,
.make_pte = native_make_pte,
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 151f2d171f7..19e7fc7c2c4 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -29,6 +29,7 @@
#include <linux/mm.h>
#include <linux/spinlock.h>
#include <linux/string.h>
+#include <linux/crash_dump.h>
#include <linux/dma-mapping.h>
#include <linux/bitops.h>
#include <linux/pci_ids.h>
@@ -167,6 +168,8 @@ static void calgary_dump_error_regs(struct iommu_table *tbl);
static void calioc2_handle_quirks(struct iommu_table *tbl, struct pci_dev *dev);
static void calioc2_tce_cache_blast(struct iommu_table *tbl);
static void calioc2_dump_error_regs(struct iommu_table *tbl);
+static void calgary_init_bitmap_from_tce_table(struct iommu_table *tbl);
+static void get_tce_space_from_tar(void);
static struct cal_chipset_ops calgary_chip_ops = {
.handle_quirks = calgary_handle_quirks,
@@ -830,7 +833,11 @@ static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar)
tbl = pci_iommu(dev->bus);
tbl->it_base = (unsigned long)bus_info[dev->bus->number].tce_space;
- tce_free(tbl, 0, tbl->it_size);
+
+ if (is_kdump_kernel())
+ calgary_init_bitmap_from_tce_table(tbl);
+ else
+ tce_free(tbl, 0, tbl->it_size);
if (is_calgary(dev->device))
tbl->chip_ops = &calgary_chip_ops;
@@ -1209,6 +1216,10 @@ static int __init calgary_init(void)
if (ret)
return ret;
+ /* Purely for kdump kernel case */
+ if (is_kdump_kernel())
+ get_tce_space_from_tar();
+
do {
dev = pci_get_device(PCI_VENDOR_ID_IBM, PCI_ANY_ID, dev);
if (!dev)
@@ -1339,6 +1350,61 @@ static int __init calgary_bus_has_devices(int bus, unsigned short pci_dev)
return (val != 0xffffffff);
}
+/*
+ * calgary_init_bitmap_from_tce_table():
+ * Funtion for kdump case. In the second/kdump kernel initialize
+ * the bitmap based on the tce table entries obtained from first kernel
+ */
+static void calgary_init_bitmap_from_tce_table(struct iommu_table *tbl)
+{
+ u64 *tp;
+ unsigned int index;
+ tp = ((u64 *)tbl->it_base);
+ for (index = 0 ; index < tbl->it_size; index++) {
+ if (*tp != 0x0)
+ set_bit(index, tbl->it_map);
+ tp++;
+ }
+}
+
+/*
+ * get_tce_space_from_tar():
+ * Function for kdump case. Get the tce tables from first kernel
+ * by reading the contents of the base adress register of calgary iommu
+ */
+static void get_tce_space_from_tar()
+{
+ int bus;
+ void __iomem *target;
+ unsigned long tce_space;
+
+ for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
+ struct calgary_bus_info *info = &bus_info[bus];
+ unsigned short pci_device;
+ u32 val;
+
+ val = read_pci_config(bus, 0, 0, 0);
+ pci_device = (val & 0xFFFF0000) >> 16;
+
+ if (!is_cal_pci_dev(pci_device))
+ continue;
+ if (info->translation_disabled)
+ continue;
+
+ if (calgary_bus_has_devices(bus, pci_device) ||
+ translate_empty_slots) {
+ target = calgary_reg(bus_info[bus].bbar,
+ tar_offset(bus));
+ tce_space = be64_to_cpu(readq(target));
+ tce_space = tce_space & TAR_SW_BITS;
+
+ tce_space = tce_space & (~specified_table_size);
+ info->tce_space = (u64 *)__va(tce_space);
+ }
+ }
+ return;
+}
+
void __init detect_calgary(void)
{
int bus;
@@ -1394,7 +1460,8 @@ void __init detect_calgary(void)
return;
}
- specified_table_size = determine_tce_table_size(max_pfn * PAGE_SIZE);
+ specified_table_size = determine_tce_table_size((is_kdump_kernel() ?
+ saved_max_pfn : max_pfn) * PAGE_SIZE);
for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
struct calgary_bus_info *info = &bus_info[bus];
@@ -1412,10 +1479,16 @@ void __init detect_calgary(void)
if (calgary_bus_has_devices(bus, pci_device) ||
translate_empty_slots) {
- tbl = alloc_tce_table();
- if (!tbl)
- goto cleanup;
- info->tce_space = tbl;
+ /*
+ * If it is kdump kernel, find and use tce tables
+ * from first kernel, else allocate tce tables here
+ */
+ if (!is_kdump_kernel()) {
+ tbl = alloc_tce_table();
+ if (!tbl)
+ goto cleanup;
+ info->tce_space = tbl;
+ }
calgary_found = 1;
}
}
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index a4213c00dff..cbecb05551b 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -314,8 +314,7 @@ int dma_supported(struct device *dev, u64 mask)
{
#ifdef CONFIG_PCI
if (mask > 0xffffffff && forbid_dac > 0) {
- printk(KERN_INFO "PCI: Disallowing DAC for device %s\n",
- dev->bus_id);
+ dev_info(dev, "PCI: Disallowing DAC for device\n");
return 0;
}
#endif
@@ -342,8 +341,7 @@ int dma_supported(struct device *dev, u64 mask)
type. Normally this doesn't make any difference, but gives
more gentle handling of IOMMU overflow. */
if (iommu_sac_force && (mask >= DMA_40BIT_MASK)) {
- printk(KERN_INFO "%s: Force SAC with mask %Lx\n",
- dev->bus_id, mask);
+ dev_info(dev, "Force SAC with mask %Lx\n", mask);
return 0;
}
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index be60961f869..df5f142657d 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -198,9 +198,7 @@ static void iommu_full(struct device *dev, size_t size, int dir)
* out. Hopefully no network devices use single mappings that big.
*/
- printk(KERN_ERR
- "PCI-DMA: Out of IOMMU space for %lu bytes at device %s\n",
- size, dev->bus_id);
+ dev_err(dev, "PCI-DMA: Out of IOMMU space for %lu bytes\n", size);
if (size > PAGE_SIZE*EMERGENCY_PAGES) {
if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL)
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 0c3927accb0..53bc653ed5c 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -128,7 +128,7 @@ void cpu_idle(void)
/* endless idle loop with no priority at all */
while (1) {
- tick_nohz_stop_sched_tick();
+ tick_nohz_stop_sched_tick(1);
while (!need_resched()) {
check_pgt_cache();
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index e8a8e1b9981..3fb62a7d9a1 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -120,7 +120,7 @@ void cpu_idle(void)
current_thread_info()->status |= TS_POLLING;
/* endless idle loop with no priority at all */
while (1) {
- tick_nohz_stop_sched_tick();
+ tick_nohz_stop_sched_tick(1);
while (!need_resched()) {
rmb();
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 9dcf39c0297..06a9f643817 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -411,24 +411,28 @@ void native_machine_shutdown(void)
{
/* Stop the cpus and apics */
#ifdef CONFIG_SMP
- int reboot_cpu_id;
/* The boot cpu is always logical cpu 0 */
- reboot_cpu_id = 0;
+ int reboot_cpu_id = 0;
+ cpumask_of_cpu_ptr(newmask, reboot_cpu_id);
#ifdef CONFIG_X86_32
/* See if there has been given a command line override */
if ((reboot_cpu != -1) && (reboot_cpu < NR_CPUS) &&
- cpu_online(reboot_cpu))
+ cpu_online(reboot_cpu)) {
reboot_cpu_id = reboot_cpu;
+ cpumask_of_cpu_ptr_next(newmask, reboot_cpu_id);
+ }
#endif
/* Make certain the cpu I'm about to reboot on is online */
- if (!cpu_online(reboot_cpu_id))
+ if (!cpu_online(reboot_cpu_id)) {
reboot_cpu_id = smp_processor_id();
+ cpumask_of_cpu_ptr_next(newmask, reboot_cpu_id);
+ }
/* Make certain I only run on the appropriate processor */
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(reboot_cpu_id));
+ set_cpus_allowed_ptr(current, newmask);
/* O.K Now that I'm on the appropriate processor,
* stop all of the others.
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index ec952aa5394..b520dae02bf 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -597,11 +597,11 @@ void __init setup_arch(char **cmdline_p)
memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
visws_early_detect();
pre_setup_arch_hook();
- early_cpu_init();
#else
printk(KERN_INFO "Command line: %s\n", boot_command_line);
#endif
+ early_cpu_init();
early_ioremap_init();
ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev);
@@ -665,9 +665,6 @@ void __init setup_arch(char **cmdline_p)
bss_resource.start = virt_to_phys(&__bss_start);
bss_resource.end = virt_to_phys(&__bss_stop)-1;
-#ifdef CONFIG_X86_64
- early_cpu_init();
-#endif
strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line;
@@ -680,7 +677,7 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_X86_LOCAL_APIC
disable_apic = 1;
#endif
- clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
+ setup_clear_cpu_cap(X86_FEATURE_APIC);
}
#ifdef CONFIG_PCI
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c
index 07faaa5109c..6fb5bcdd893 100644
--- a/arch/x86/kernel/signal_32.c
+++ b/arch/x86/kernel/signal_32.c
@@ -661,8 +661,5 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs);
- if (thread_info_flags & _TIF_HRTICK_RESCHED)
- hrtick_resched();
-
clear_thread_flag(TIF_IRET);
}
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
index bf87684474f..b45ef8ddd65 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -53,6 +53,59 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
return do_sigaltstack(uss, uoss, regs->sp);
}
+/*
+ * Signal frame handlers.
+ */
+
+static inline int save_i387(struct _fpstate __user *buf)
+{
+ struct task_struct *tsk = current;
+ int err = 0;
+
+ BUILD_BUG_ON(sizeof(struct user_i387_struct) !=
+ sizeof(tsk->thread.xstate->fxsave));
+
+ if ((unsigned long)buf % 16)
+ printk("save_i387: bad fpstate %p\n", buf);
+
+ if (!used_math())
+ return 0;
+ clear_used_math(); /* trigger finit */
+ if (task_thread_info(tsk)->status & TS_USEDFPU) {
+ err = save_i387_checking((struct i387_fxsave_struct __user *)
+ buf);
+ if (err)
+ return err;
+ task_thread_info(tsk)->status &= ~TS_USEDFPU;
+ stts();
+ } else {
+ if (__copy_to_user(buf, &tsk->thread.xstate->fxsave,
+ sizeof(struct i387_fxsave_struct)))
+ return -1;
+ }
+ return 1;
+}
+
+/*
+ * This restores directly out of user space. Exceptions are handled.
+ */
+static inline int restore_i387(struct _fpstate __user *buf)
+{
+ struct task_struct *tsk = current;
+ int err;
+
+ if (!used_math()) {
+ err = init_fpu(tsk);
+ if (err)
+ return err;
+ }
+
+ if (!(task_thread_info(current)->status & TS_USEDFPU)) {
+ clts();
+ task_thread_info(current)->status |= TS_USEDFPU;
+ }
+ return restore_fpu_checking((__force struct i387_fxsave_struct *)buf);
+}
/*
* Do a signal return; undo the signal stack.
@@ -496,9 +549,6 @@ void do_notify_resume(struct pt_regs *regs, void *unused,
/* deal with pending signal delivery */
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs);
-
- if (thread_info_flags & _TIF_HRTICK_RESCHED)
- hrtick_resched();
}
void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 4b53a647bc0..332512767f4 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -438,7 +438,7 @@ void __cpuinit set_cpu_sibling_map(int cpu)
cpu_set(cpu, cpu_sibling_setup_map);
if (smp_num_siblings > 1) {
- for_each_cpu_mask(i, cpu_sibling_setup_map) {
+ for_each_cpu_mask_nr(i, cpu_sibling_setup_map) {
if (c->phys_proc_id == cpu_data(i).phys_proc_id &&
c->cpu_core_id == cpu_data(i).cpu_core_id) {
cpu_set(i, per_cpu(cpu_sibling_map, cpu));
@@ -461,7 +461,7 @@ void __cpuinit set_cpu_sibling_map(int cpu)
return;
}
- for_each_cpu_mask(i, cpu_sibling_setup_map) {
+ for_each_cpu_mask_nr(i, cpu_sibling_setup_map) {
if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
cpu_set(i, c->llc_shared_map);
@@ -1219,7 +1219,7 @@ static void remove_siblinginfo(int cpu)
int sibling;
struct cpuinfo_x86 *c = &cpu_data(cpu);
- for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) {
+ for_each_cpu_mask_nr(sibling, per_cpu(cpu_core_map, cpu)) {
cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
/*/
* last thread sibling in this cpu core going down
@@ -1228,7 +1228,7 @@ static void remove_siblinginfo(int cpu)
cpu_data(sibling).booted_cores--;
}
- for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu))
+ for_each_cpu_mask_nr(sibling, per_cpu(cpu_sibling_map, cpu))
cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
cpus_clear(per_cpu(cpu_sibling_map, cpu));
cpus_clear(per_cpu(cpu_core_map, cpu));
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
index adff5562f5f..d44395ff34c 100644
--- a/arch/x86/kernel/syscall_table_32.S
+++ b/arch/x86/kernel/syscall_table_32.S
@@ -326,3 +326,9 @@ ENTRY(sys_call_table)
.long sys_fallocate
.long sys_timerfd_settime /* 325 */
.long sys_timerfd_gettime
+ .long sys_signalfd4
+ .long sys_eventfd2
+ .long sys_epoll_create1
+ .long sys_dup3 /* 330 */
+ .long sys_pipe2
+ .long sys_inotify_init1
diff --git a/arch/x86/mach-es7000/es7000plat.c b/arch/x86/mach-es7000/es7000plat.c
index 4354ce80488..50189af14b8 100644
--- a/arch/x86/mach-es7000/es7000plat.c
+++ b/arch/x86/mach-es7000/es7000plat.c
@@ -130,10 +130,10 @@ parse_unisys_oem (char *oemptr)
mip_addr = val;
mip = (struct mip_reg *)val;
mip_reg = __va(mip);
- Dprintk("es7000_mipcfg: host_reg = 0x%lx \n",
- (unsigned long)host_reg);
- Dprintk("es7000_mipcfg: mip_reg = 0x%lx \n",
- (unsigned long)mip_reg);
+ pr_debug("es7000_mipcfg: host_reg = 0x%lx \n",
+ (unsigned long)host_reg);
+ pr_debug("es7000_mipcfg: mip_reg = 0x%lx \n",
+ (unsigned long)mip_reg);
success++;
break;
case MIP_PSAI_REG:
diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/discontig_32.c
index 5dfef9fa061..62fa440678d 100644
--- a/arch/x86/mm/discontig_32.c
+++ b/arch/x86/mm/discontig_32.c
@@ -42,7 +42,6 @@
struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
EXPORT_SYMBOL(node_data);
-static bootmem_data_t node0_bdata;
/*
* numa interface - we expect the numa architecture specific code to have
@@ -385,7 +384,7 @@ void __init initmem_init(unsigned long start_pfn,
for_each_online_node(nid)
memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
- NODE_DATA(0)->bdata = &node0_bdata;
+ NODE_DATA(0)->bdata = &bootmem_node_data[0];
setup_bootmem_allocator();
}
diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c
index 0bb0caed897..a20d1fa64b4 100644
--- a/arch/x86/mm/dump_pagetables.c
+++ b/arch/x86/mm/dump_pagetables.c
@@ -148,8 +148,8 @@ static void note_page(struct seq_file *m, struct pg_state *st,
* we have now. "break" is either changing perms, levels or
* address space marker.
*/
- prot = pgprot_val(new_prot) & ~(PTE_MASK);
- cur = pgprot_val(st->current_prot) & ~(PTE_MASK);
+ prot = pgprot_val(new_prot) & ~(PTE_PFN_MASK);
+ cur = pgprot_val(st->current_prot) & ~(PTE_PFN_MASK);
if (!st->level) {
/* First entry */
@@ -221,7 +221,7 @@ static void walk_pmd_level(struct seq_file *m, struct pg_state *st, pud_t addr,
for (i = 0; i < PTRS_PER_PMD; i++) {
st->current_address = normalize_addr(P + i * PMD_LEVEL_MULT);
if (!pmd_none(*start)) {
- pgprotval_t prot = pmd_val(*start) & ~PTE_MASK;
+ pgprotval_t prot = pmd_val(*start) & PTE_FLAGS_MASK;
if (pmd_large(*start) || !pmd_present(*start))
note_page(m, st, __pgprot(prot), 3);
@@ -253,7 +253,7 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st, pgd_t addr,
for (i = 0; i < PTRS_PER_PUD; i++) {
st->current_address = normalize_addr(P + i * PUD_LEVEL_MULT);
if (!pud_none(*start)) {
- pgprotval_t prot = pud_val(*start) & ~PTE_MASK;
+ pgprotval_t prot = pud_val(*start) & PTE_FLAGS_MASK;
if (pud_large(*start) || !pud_present(*start))
note_page(m, st, __pgprot(prot), 2);
@@ -288,7 +288,7 @@ static void walk_pgd_level(struct seq_file *m)
for (i = 0; i < PTRS_PER_PGD; i++) {
st.current_address = normalize_addr(i * PGD_LEVEL_MULT);
if (!pgd_none(*start)) {
- pgprotval_t prot = pgd_val(*start) & ~PTE_MASK;
+ pgprotval_t prot = pgd_val(*start) & PTE_FLAGS_MASK;
if (pgd_large(*start) || !pgd_present(*start))
note_page(m, &st, __pgprot(prot), 1);
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index 0b3d567e686..8f307d914c2 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -124,7 +124,8 @@ int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
return 1;
}
-pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+ unsigned long addr, unsigned long sz)
{
pgd_t *pgd;
pud_t *pud;
@@ -133,9 +134,14 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
pgd = pgd_offset(mm, addr);
pud = pud_alloc(mm, pgd, addr);
if (pud) {
- if (pud_none(*pud))
- huge_pmd_share(mm, addr, pud);
- pte = (pte_t *) pmd_alloc(mm, pud, addr);
+ if (sz == PUD_SIZE) {
+ pte = (pte_t *)pud;
+ } else {
+ BUG_ON(sz != PMD_SIZE);
+ if (pud_none(*pud))
+ huge_pmd_share(mm, addr, pud);
+ pte = (pte_t *) pmd_alloc(mm, pud, addr);
+ }
}
BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte));
@@ -151,8 +157,11 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
pgd = pgd_offset(mm, addr);
if (pgd_present(*pgd)) {
pud = pud_offset(pgd, addr);
- if (pud_present(*pud))
+ if (pud_present(*pud)) {
+ if (pud_large(*pud))
+ return (pte_t *)pud;
pmd = pmd_offset(pud, addr);
+ }
}
return (pte_t *) pmd;
}
@@ -188,6 +197,11 @@ int pmd_huge(pmd_t pmd)
return 0;
}
+int pud_huge(pud_t pud)
+{
+ return 0;
+}
+
struct page *
follow_huge_pmd(struct mm_struct *mm, unsigned long address,
pmd_t *pmd, int write)
@@ -208,6 +222,11 @@ int pmd_huge(pmd_t pmd)
return !!(pmd_val(pmd) & _PAGE_PSE);
}
+int pud_huge(pud_t pud)
+{
+ return !!(pud_val(pud) & _PAGE_PSE);
+}
+
struct page *
follow_huge_pmd(struct mm_struct *mm, unsigned long address,
pmd_t *pmd, int write)
@@ -216,9 +235,22 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
page = pte_page(*(pte_t *)pmd);
if (page)
- page += ((address & ~HPAGE_MASK) >> PAGE_SHIFT);
+ page += ((address & ~PMD_MASK) >> PAGE_SHIFT);
+ return page;
+}
+
+struct page *
+follow_huge_pud(struct mm_struct *mm, unsigned long address,
+ pud_t *pud, int write)
+{
+ struct page *page;
+
+ page = pte_page(*(pte_t *)pud);
+ if (page)
+ page += ((address & ~PUD_MASK) >> PAGE_SHIFT);
return page;
}
+
#endif
/* x86_64 also uses this file */
@@ -228,6 +260,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
unsigned long addr, unsigned long len,
unsigned long pgoff, unsigned long flags)
{
+ struct hstate *h = hstate_file(file);
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
unsigned long start_addr;
@@ -240,7 +273,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
}
full_search:
- addr = ALIGN(start_addr, HPAGE_SIZE);
+ addr = ALIGN(start_addr, huge_page_size(h));
for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
/* At this point: (!vma || addr < vma->vm_end). */
@@ -262,7 +295,7 @@ full_search:
}
if (addr + mm->cached_hole_size < vma->vm_start)
mm->cached_hole_size = vma->vm_start - addr;
- addr = ALIGN(vma->vm_end, HPAGE_SIZE);
+ addr = ALIGN(vma->vm_end, huge_page_size(h));
}
}
@@ -270,6 +303,7 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
unsigned long addr0, unsigned long len,
unsigned long pgoff, unsigned long flags)
{
+ struct hstate *h = hstate_file(file);
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma, *prev_vma;
unsigned long base = mm->mmap_base, addr = addr0;
@@ -290,7 +324,7 @@ try_again:
goto fail;
/* either no address requested or cant fit in requested address hole */
- addr = (mm->free_area_cache - len) & HPAGE_MASK;
+ addr = (mm->free_area_cache - len) & huge_page_mask(h);
do {
/*
* Lookup failure means no vma is above this address,
@@ -321,7 +355,7 @@ try_again:
largest_hole = vma->vm_start - addr;
/* try just below the current vma->vm_start */
- addr = (vma->vm_start - len) & HPAGE_MASK;
+ addr = (vma->vm_start - len) & huge_page_mask(h);
} while (len <= vma->vm_start);
fail:
@@ -359,22 +393,23 @@ unsigned long
hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
unsigned long len, unsigned long pgoff, unsigned long flags)
{
+ struct hstate *h = hstate_file(file);
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
- if (len & ~HPAGE_MASK)
+ if (len & ~huge_page_mask(h))
return -EINVAL;
if (len > TASK_SIZE)
return -ENOMEM;
if (flags & MAP_FIXED) {
- if (prepare_hugepage_range(addr, len))
+ if (prepare_hugepage_range(file, addr, len))
return -EINVAL;
return addr;
}
if (addr) {
- addr = ALIGN(addr, HPAGE_SIZE);
+ addr = ALIGN(addr, huge_page_size(h));
vma = find_vma(mm, addr);
if (TASK_SIZE - len >= addr &&
(!vma || addr + len <= vma->vm_start))
@@ -390,3 +425,20 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
#endif /*HAVE_ARCH_HUGETLB_UNMAPPED_AREA*/
+#ifdef CONFIG_X86_64
+static __init int setup_hugepagesz(char *opt)
+{
+ unsigned long ps = memparse(opt, &opt);
+ if (ps == PMD_SIZE) {
+ hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
+ } else if (ps == PUD_SIZE && cpu_has_gbpages) {
+ hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
+ } else {
+ printk(KERN_ERR "hugepagesz: Unsupported page size %lu M\n",
+ ps >> 20);
+ return 0;
+ }
+ return 1;
+}
+__setup("hugepagesz=", setup_hugepagesz);
+#endif
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 24c1d3c3018..016f335bbee 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -330,6 +330,14 @@ static void __iomem *ioremap_default(resource_size_t phys_addr,
return (void __iomem *)ret;
}
+void __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size,
+ unsigned long prot_val)
+{
+ return __ioremap_caller(phys_addr, size, (prot_val & _PAGE_CACHE_MASK),
+ __builtin_return_address(0));
+}
+EXPORT_SYMBOL(ioremap_prot);
+
/**
* iounmap - Free a IO remapping
* @addr: virtual address from ioremap_*
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index 9782f42dd31..a4dd793d600 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -23,8 +23,6 @@
struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
EXPORT_SYMBOL(node_data);
-static bootmem_data_t plat_node_bdata[MAX_NUMNODES];
-
struct memnode memnode;
s16 apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
@@ -198,7 +196,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start,
nodedata_phys + pgdat_size - 1);
memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t));
- NODE_DATA(nodeid)->bdata = &plat_node_bdata[nodeid];
+ NODE_DATA(nodeid)->bdata = &bootmem_node_data[nodeid];
NODE_DATA(nodeid)->node_start_pfn = start_pfn;
NODE_DATA(nodeid)->node_spanned_pages = last_pfn - start_pfn;
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
index 7f3329b55d2..3f90289410e 100644
--- a/arch/x86/oprofile/nmi_int.c
+++ b/arch/x86/oprofile/nmi_int.c
@@ -369,20 +369,34 @@ static int __init ppro_init(char **cpu_type)
{
__u8 cpu_model = boot_cpu_data.x86_model;
- if (cpu_model == 14)
+ switch (cpu_model) {
+ case 0 ... 2:
+ *cpu_type = "i386/ppro";
+ break;
+ case 3 ... 5:
+ *cpu_type = "i386/pii";
+ break;
+ case 6 ... 8:
+ *cpu_type = "i386/piii";
+ break;
+ case 9:
+ *cpu_type = "i386/p6_mobile";
+ break;
+ case 10 ... 13:
+ *cpu_type = "i386/p6";
+ break;
+ case 14:
*cpu_type = "i386/core";
- else if (cpu_model == 15 || cpu_model == 23)
+ break;
+ case 15: case 23:
+ *cpu_type = "i386/core_2";
+ break;
+ case 26:
*cpu_type = "i386/core_2";
- else if (cpu_model > 0xd)
+ break;
+ default:
+ /* Unknown */
return 0;
- else if (cpu_model == 9) {
- *cpu_type = "i386/p6_mobile";
- } else if (cpu_model > 5) {
- *cpu_type = "i386/piii";
- } else if (cpu_model > 2) {
- *cpu_type = "i386/pii";
- } else {
- *cpu_type = "i386/ppro";
}
model = &op_ppro_spec;
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 2aafb67dc5f..a09505806b8 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -280,6 +280,7 @@ static void pci_track_mmap_page_range(struct vm_area_struct *vma)
static struct vm_operations_struct pci_mmap_ops = {
.open = pci_track_mmap_page_range,
.close = pci_unmap_page_range,
+ .access = generic_access_phys,
};
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 194bbd6e324..9ff6e3cbf08 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1435,7 +1435,7 @@ static unsigned long m2p(phys_addr_t maddr)
{
phys_addr_t paddr;
- maddr &= PTE_MASK;
+ maddr &= PTE_PFN_MASK;
paddr = mfn_to_pfn(maddr >> PAGE_SHIFT) << PAGE_SHIFT;
return paddr;
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index a44d56e38bd..aa37469da69 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -343,8 +343,8 @@ void xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
static pteval_t pte_mfn_to_pfn(pteval_t val)
{
if (val & _PAGE_PRESENT) {
- unsigned long mfn = (val & PTE_MASK) >> PAGE_SHIFT;
- pteval_t flags = val & ~PTE_MASK;
+ unsigned long mfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
+ pteval_t flags = val & PTE_FLAGS_MASK;
val = ((pteval_t)mfn_to_pfn(mfn) << PAGE_SHIFT) | flags;
}
@@ -354,8 +354,8 @@ static pteval_t pte_mfn_to_pfn(pteval_t val)
static pteval_t pte_pfn_to_mfn(pteval_t val)
{
if (val & _PAGE_PRESENT) {
- unsigned long pfn = (val & PTE_MASK) >> PAGE_SHIFT;
- pteval_t flags = val & ~PTE_MASK;
+ unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
+ pteval_t flags = val & PTE_FLAGS_MASK;
val = ((pteval_t)pfn_to_mfn(pfn) << PAGE_SHIFT) | flags;
}
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index e693812ac59..d8faf79a0a1 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -367,7 +367,7 @@ static void xen_send_IPI_mask(cpumask_t mask, enum ipi_vector vector)
cpus_and(mask, mask, cpu_online_map);
- for_each_cpu_mask(cpu, mask)
+ for_each_cpu_mask_nr(cpu, mask)
xen_send_IPI_one(cpu, vector);
}
@@ -378,7 +378,7 @@ static void xen_smp_send_call_function_ipi(cpumask_t mask)
xen_send_IPI_mask(mask, XEN_CALL_FUNCTION_VECTOR);
/* Make sure other vcpus get a chance to run if they need to. */
- for_each_cpu_mask(cpu, mask) {
+ for_each_cpu_mask_nr(cpu, mask) {
if (xen_vcpu_stolen(cpu)) {
HYPERVISOR_sched_op(SCHEDOP_yield, 0);
break;
diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S
index 4038cbfe333..7f58304fafb 100644
--- a/arch/x86/xen/xen-asm_64.S
+++ b/arch/x86/xen/xen-asm_64.S
@@ -173,7 +173,7 @@ ENTRY(xen_sysexit)
pushq $__USER32_CS
pushq %rdx
- pushq $VGCF_in_syscall
+ pushq $0
1: jmp hypercall_iret
ENDPATCH(xen_sysexit)
RELOC(xen_sysexit, 1b+1)
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 9fc8551a1cf..02e417d3d8e 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -194,8 +194,8 @@ config HOTPLUG
plugged into slots found on all modern laptop computers. Another
example, used on modern desktops as well as laptops, is USB.
- Enable HOTPLUG and KMOD, and build a modular kernel. Get agent
- software (at <http://linux-hotplug.sourceforge.net/>) and install it.
+ Enable HOTPLUG and build a modular kernel. Get agent software
+ (from <http://linux-hotplug.sourceforge.net/>) and install it.
Then your kernel will automatically call out to a user mode "policy
agent" (/sbin/hotplug) to load modules and set up software needed
to use devices as you hotplug them.
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 5e6d75c9f92..a00359e8f7a 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -16,6 +16,7 @@
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/screen_info.h>
#include <linux/bootmem.h>
diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c
index f3e16efcd47..ac15ecbdf91 100644
--- a/arch/xtensa/kernel/syscall.c
+++ b/arch/xtensa/kernel/syscall.c
@@ -49,7 +49,7 @@ asmlinkage long xtensa_pipe(int __user *userfds)
int fd[2];
int error;
- error = do_pipe(fd);
+ error = do_pipe_flags(fd, 0);
if (!error) {
if (copy_to_user(userfds, fd, 2 * sizeof(int)))
error = -EFAULT;
diff --git a/block/bsg.c b/block/bsg.c
index 5fb9b0bdbe8..5a68b09a69b 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -1044,7 +1044,8 @@ int bsg_register_queue(struct request_queue *q, struct device *parent,
bcd->release = release;
kref_init(&bcd->ref);
dev = MKDEV(bsg_major, bcd->minor);
- class_dev = device_create(bsg_class, parent, dev, "%s", devname);
+ class_dev = device_create_drvdata(bsg_class, parent, dev, NULL,
+ "%s", devname);
if (IS_ERR(class_dev)) {
ret = PTR_ERR(class_dev);
goto put_dev;
diff --git a/block/genhd.c b/block/genhd.c
index 9074f384b09..c13cc77291a 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -183,6 +183,7 @@ static int exact_lock(dev_t devt, void *data)
void add_disk(struct gendisk *disk)
{
struct backing_dev_info *bdi;
+ int retval;
disk->flags |= GENHD_FL_UP;
blk_register_region(MKDEV(disk->major, disk->first_minor),
@@ -193,7 +194,8 @@ void add_disk(struct gendisk *disk)
bdi = &disk->queue->backing_dev_info;
bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor));
- sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi");
+ retval = sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi");
+ WARN_ON(retval);
}
EXPORT_SYMBOL(add_disk);
@@ -225,89 +227,111 @@ struct gendisk *get_gendisk(dev_t devt, int *part)
}
/*
- * print a full list of all partitions - intended for places where the root
- * filesystem can't be mounted and thus to give the victim some idea of what
- * went wrong
+ * print a partitions - intended for places where the root filesystem can't be
+ * mounted and thus to give the victim some idea of what went wrong
*/
-void __init printk_all_partitions(void)
+static int printk_partition(struct device *dev, void *data)
{
- struct device *dev;
struct gendisk *sgp;
char buf[BDEVNAME_SIZE];
int n;
- mutex_lock(&block_class_lock);
- /* For each block device... */
- list_for_each_entry(dev, &block_class.devices, node) {
- if (dev->type != &disk_type)
- continue;
- sgp = dev_to_disk(dev);
- /*
- * Don't show empty devices or things that have been surpressed
- */
- if (get_capacity(sgp) == 0 ||
- (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO))
- continue;
+ if (dev->type != &disk_type)
+ goto exit;
- /*
- * Note, unlike /proc/partitions, I am showing the numbers in
- * hex - the same format as the root= option takes.
- */
- printk("%02x%02x %10llu %s",
- sgp->major, sgp->first_minor,
- (unsigned long long)get_capacity(sgp) >> 1,
- disk_name(sgp, 0, buf));
- if (sgp->driverfs_dev != NULL &&
- sgp->driverfs_dev->driver != NULL)
- printk(" driver: %s\n",
- sgp->driverfs_dev->driver->name);
- else
- printk(" (driver?)\n");
-
- /* now show the partitions */
- for (n = 0; n < sgp->minors - 1; ++n) {
- if (sgp->part[n] == NULL)
- continue;
- if (sgp->part[n]->nr_sects == 0)
- continue;
- printk(" %02x%02x %10llu %s\n",
- sgp->major, n + 1 + sgp->first_minor,
- (unsigned long long)sgp->part[n]->nr_sects >> 1,
- disk_name(sgp, n + 1, buf));
- }
+ sgp = dev_to_disk(dev);
+ /*
+ * Don't show empty devices or things that have been surpressed
+ */
+ if (get_capacity(sgp) == 0 ||
+ (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO))
+ goto exit;
+
+ /*
+ * Note, unlike /proc/partitions, I am showing the numbers in
+ * hex - the same format as the root= option takes.
+ */
+ printk("%02x%02x %10llu %s",
+ sgp->major, sgp->first_minor,
+ (unsigned long long)get_capacity(sgp) >> 1,
+ disk_name(sgp, 0, buf));
+ if (sgp->driverfs_dev != NULL &&
+ sgp->driverfs_dev->driver != NULL)
+ printk(" driver: %s\n",
+ sgp->driverfs_dev->driver->name);
+ else
+ printk(" (driver?)\n");
+
+ /* now show the partitions */
+ for (n = 0; n < sgp->minors - 1; ++n) {
+ if (sgp->part[n] == NULL)
+ goto exit;
+ if (sgp->part[n]->nr_sects == 0)
+ goto exit;
+ printk(" %02x%02x %10llu %s\n",
+ sgp->major, n + 1 + sgp->first_minor,
+ (unsigned long long)sgp->part[n]->nr_sects >> 1,
+ disk_name(sgp, n + 1, buf));
}
+exit:
+ return 0;
+}
+/*
+ * print a full list of all partitions - intended for places where the root
+ * filesystem can't be mounted and thus to give the victim some idea of what
+ * went wrong
+ */
+void __init printk_all_partitions(void)
+{
+ mutex_lock(&block_class_lock);
+ class_for_each_device(&block_class, NULL, NULL, printk_partition);
mutex_unlock(&block_class_lock);
}
#ifdef CONFIG_PROC_FS
/* iterator */
+static int find_start(struct device *dev, void *data)
+{
+ loff_t k = *(loff_t *)data;
+
+ if (dev->type != &disk_type)
+ return 0;
+ if (!k--)
+ return 1;
+ return 0;
+}
+
static void *part_start(struct seq_file *part, loff_t *pos)
{
- loff_t k = *pos;
struct device *dev;
+ loff_t n = *pos;
+
+ if (!n)
+ seq_puts(part, "major minor #blocks name\n\n");
mutex_lock(&block_class_lock);
- list_for_each_entry(dev, &block_class.devices, node) {
- if (dev->type != &disk_type)
- continue;
- if (!k--)
- return dev_to_disk(dev);
- }
+ dev = class_find_device(&block_class, NULL, (void *)pos, find_start);
+ if (dev)
+ return dev_to_disk(dev);
return NULL;
}
+static int find_next(struct device *dev, void *data)
+{
+ if (dev->type == &disk_type)
+ return 1;
+ return 0;
+}
+
static void *part_next(struct seq_file *part, void *v, loff_t *pos)
{
struct gendisk *gp = v;
struct device *dev;
++*pos;
- list_for_each_entry(dev, &gp->dev.node, node) {
- if (&dev->node == &block_class.devices)
- return NULL;
- if (dev->type == &disk_type)
- return dev_to_disk(dev);
- }
+ dev = class_find_device(&block_class, &gp->dev, NULL, find_next);
+ if (dev)
+ return dev_to_disk(dev);
return NULL;
}
@@ -322,9 +346,6 @@ static int show_partition(struct seq_file *part, void *v)
int n;
char buf[BDEVNAME_SIZE];
- if (&sgp->dev.node == block_class.devices.next)
- seq_puts(part, "major minor #blocks name\n\n");
-
/* Don't show non-partitionable removeable devices or empty devices */
if (!get_capacity(sgp) ||
(sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE)))
@@ -370,7 +391,10 @@ static struct kobject *base_probe(dev_t devt, int *part, void *data)
static int __init genhd_device_init(void)
{
- int error = class_register(&block_class);
+ int error;
+
+ block_class.dev_kobj = sysfs_dev_block_kobj;
+ error = class_register(&block_class);
if (unlikely(error))
return error;
bdev_map = kobj_map_init(base_probe, &block_class_lock);
@@ -532,6 +556,7 @@ static struct device_type disk_type = {
.release = disk_release,
};
+#ifdef CONFIG_PROC_FS
/*
* aggregate disk stat collector. Uses the same stats that the sysfs
* entries do, above, but makes them available through one seq_file.
@@ -542,16 +567,12 @@ static struct device_type disk_type = {
static void *diskstats_start(struct seq_file *part, loff_t *pos)
{
- loff_t k = *pos;
struct device *dev;
mutex_lock(&block_class_lock);
- list_for_each_entry(dev, &block_class.devices, node) {
- if (dev->type != &disk_type)
- continue;
- if (!k--)
- return dev_to_disk(dev);
- }
+ dev = class_find_device(&block_class, NULL, (void *)pos, find_start);
+ if (dev)
+ return dev_to_disk(dev);
return NULL;
}
@@ -561,12 +582,9 @@ static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos)
struct device *dev;
++*pos;
- list_for_each_entry(dev, &gp->dev.node, node) {
- if (&dev->node == &block_class.devices)
- return NULL;
- if (dev->type == &disk_type)
- return dev_to_disk(dev);
- }
+ dev = class_find_device(&block_class, &gp->dev, NULL, find_next);
+ if (dev)
+ return dev_to_disk(dev);
return NULL;
}
@@ -641,6 +659,7 @@ const struct seq_operations diskstats_op = {
.stop = diskstats_stop,
.show = diskstats_show
};
+#endif /* CONFIG_PROC_FS */
static void media_change_notify_thread(struct work_struct *work)
{
@@ -665,24 +684,38 @@ void genhd_media_change_notify(struct gendisk *disk)
EXPORT_SYMBOL_GPL(genhd_media_change_notify);
#endif /* 0 */
+struct find_block {
+ const char *name;
+ int part;
+};
+
+static int match_id(struct device *dev, void *data)
+{
+ struct find_block *find = data;
+
+ if (dev->type != &disk_type)
+ return 0;
+ if (strcmp(dev->bus_id, find->name) == 0) {
+ struct gendisk *disk = dev_to_disk(dev);
+ if (find->part < disk->minors)
+ return 1;
+ }
+ return 0;
+}
+
dev_t blk_lookup_devt(const char *name, int part)
{
struct device *dev;
dev_t devt = MKDEV(0, 0);
+ struct find_block find;
mutex_lock(&block_class_lock);
- list_for_each_entry(dev, &block_class.devices, node) {
- if (dev->type != &disk_type)
- continue;
- if (strcmp(dev->bus_id, name) == 0) {
- struct gendisk *disk = dev_to_disk(dev);
-
- if (part < disk->minors)
- devt = MKDEV(MAJOR(dev->devt),
- MINOR(dev->devt) + part);
- break;
- }
- }
+ find.name = name;
+ find.part = part;
+ dev = class_find_device(&block_class, NULL, (void *)&find, match_id);
+ if (dev)
+ devt = MKDEV(MAJOR(dev->devt),
+ MINOR(dev->devt) + part);
mutex_unlock(&block_class_lock);
return devt;
diff --git a/block/ioctl.c b/block/ioctl.c
index 52d6385216a..77185e5c026 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -17,6 +17,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
long long start, length;
int part;
int i;
+ int err;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
@@ -61,9 +62,9 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
}
}
/* all seems OK */
- add_partition(disk, part, start, length, ADDPART_FLAG_NONE);
+ err = add_partition(disk, part, start, length, ADDPART_FLAG_NONE);
mutex_unlock(&bdev->bd_mutex);
- return 0;
+ return err;
case BLKPG_DEL_PARTITION:
if (!disk->part[part-1])
return -ENXIO;
diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c
index a5eda80e842..ddccfb01c41 100644
--- a/crypto/async_tx/async_memcpy.c
+++ b/crypto/async_tx/async_memcpy.c
@@ -73,15 +73,7 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
pr_debug("%s: (sync) len: %zu\n", __func__, len);
/* wait for any prerequisite operations */
- if (depend_tx) {
- /* if ack is already set then we cannot be sure
- * we are referring to the correct operation
- */
- BUG_ON(async_tx_test_ack(depend_tx));
- if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
- panic("%s: DMA_ERROR waiting for depend_tx\n",
- __func__);
- }
+ async_tx_quiesce(&depend_tx);
dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
src_buf = kmap_atomic(src, KM_USER1) + src_offset;
@@ -91,7 +83,7 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
kunmap_atomic(dest_buf, KM_USER0);
kunmap_atomic(src_buf, KM_USER1);
- async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+ async_tx_sync_epilog(cb_fn, cb_param);
}
return tx;
diff --git a/crypto/async_tx/async_memset.c b/crypto/async_tx/async_memset.c
index f5ff3906b03..5b5eb99bb24 100644
--- a/crypto/async_tx/async_memset.c
+++ b/crypto/async_tx/async_memset.c
@@ -72,19 +72,11 @@ async_memset(struct page *dest, int val, unsigned int offset,
dest_buf = (void *) (((char *) page_address(dest)) + offset);
/* wait for any prerequisite operations */
- if (depend_tx) {
- /* if ack is already set then we cannot be sure
- * we are referring to the correct operation
- */
- BUG_ON(depend_tx->ack);
- if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
- panic("%s: DMA_ERROR waiting for depend_tx\n",
- __func__);
- }
+ async_tx_quiesce(&depend_tx);
memset(dest_buf, val, len);
- async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+ async_tx_sync_epilog(cb_fn, cb_param);
}
return tx;
diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c
index 095c798d317..85eaf7b1c53 100644
--- a/crypto/async_tx/async_tx.c
+++ b/crypto/async_tx/async_tx.c
@@ -295,7 +295,7 @@ dma_channel_add_remove(struct dma_client *client,
case DMA_RESOURCE_REMOVED:
found = 0;
spin_lock_irqsave(&async_tx_lock, flags);
- list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+ list_for_each_entry(ref, &async_tx_master_list, node)
if (ref->chan == chan) {
/* permit backing devices to go away */
dma_chan_put(ref->chan);
@@ -608,23 +608,34 @@ async_trigger_callback(enum async_tx_flags flags,
pr_debug("%s: (sync)\n", __func__);
/* wait for any prerequisite operations */
- if (depend_tx) {
- /* if ack is already set then we cannot be sure
- * we are referring to the correct operation
- */
- BUG_ON(async_tx_test_ack(depend_tx));
- if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
- panic("%s: DMA_ERROR waiting for depend_tx\n",
- __func__);
- }
+ async_tx_quiesce(&depend_tx);
- async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+ async_tx_sync_epilog(cb_fn, cb_param);
}
return tx;
}
EXPORT_SYMBOL_GPL(async_trigger_callback);
+/**
+ * async_tx_quiesce - ensure tx is complete and freeable upon return
+ * @tx - transaction to quiesce
+ */
+void async_tx_quiesce(struct dma_async_tx_descriptor **tx)
+{
+ if (*tx) {
+ /* if ack is already set then we cannot be sure
+ * we are referring to the correct operation
+ */
+ BUG_ON(async_tx_test_ack(*tx));
+ if (dma_wait_for_async_tx(*tx) == DMA_ERROR)
+ panic("DMA_ERROR waiting for transaction\n");
+ async_tx_ack(*tx);
+ *tx = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(async_tx_quiesce);
+
module_init(async_tx_init);
module_exit(async_tx_exit);
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
index 3a0dddca5a1..65974c6d3d7 100644
--- a/crypto/async_tx/async_xor.c
+++ b/crypto/async_tx/async_xor.c
@@ -35,74 +35,121 @@
* when CONFIG_DMA_ENGINE=n
*/
static __always_inline struct dma_async_tx_descriptor *
-do_async_xor(struct dma_device *device,
- struct dma_chan *chan, struct page *dest, struct page **src_list,
- unsigned int offset, unsigned int src_cnt, size_t len,
- enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
- dma_async_tx_callback cb_fn, void *cb_param)
+do_async_xor(struct dma_chan *chan, struct page *dest, struct page **src_list,
+ unsigned int offset, int src_cnt, size_t len,
+ enum async_tx_flags flags,
+ struct dma_async_tx_descriptor *depend_tx,
+ dma_async_tx_callback cb_fn, void *cb_param)
{
- dma_addr_t dma_dest;
+ struct dma_device *dma = chan->device;
dma_addr_t *dma_src = (dma_addr_t *) src_list;
- struct dma_async_tx_descriptor *tx;
+ struct dma_async_tx_descriptor *tx = NULL;
+ int src_off = 0;
int i;
- unsigned long dma_prep_flags = cb_fn ? DMA_PREP_INTERRUPT : 0;
-
- pr_debug("%s: len: %zu\n", __func__, len);
-
- dma_dest = dma_map_page(device->dev, dest, offset, len,
- DMA_FROM_DEVICE);
+ dma_async_tx_callback _cb_fn;
+ void *_cb_param;
+ enum async_tx_flags async_flags;
+ enum dma_ctrl_flags dma_flags;
+ int xor_src_cnt;
+ dma_addr_t dma_dest;
+ dma_dest = dma_map_page(dma->dev, dest, offset, len, DMA_FROM_DEVICE);
for (i = 0; i < src_cnt; i++)
- dma_src[i] = dma_map_page(device->dev, src_list[i], offset,
+ dma_src[i] = dma_map_page(dma->dev, src_list[i], offset,
len, DMA_TO_DEVICE);
- /* Since we have clobbered the src_list we are committed
- * to doing this asynchronously. Drivers force forward progress
- * in case they can not provide a descriptor
- */
- tx = device->device_prep_dma_xor(chan, dma_dest, dma_src, src_cnt, len,
- dma_prep_flags);
- if (!tx) {
- if (depend_tx)
- dma_wait_for_async_tx(depend_tx);
-
- while (!tx)
- tx = device->device_prep_dma_xor(chan, dma_dest,
- dma_src, src_cnt, len,
- dma_prep_flags);
- }
+ while (src_cnt) {
+ async_flags = flags;
+ dma_flags = 0;
+ xor_src_cnt = min(src_cnt, dma->max_xor);
+ /* if we are submitting additional xors, leave the chain open,
+ * clear the callback parameters, and leave the destination
+ * buffer mapped
+ */
+ if (src_cnt > xor_src_cnt) {
+ async_flags &= ~ASYNC_TX_ACK;
+ dma_flags = DMA_COMPL_SKIP_DEST_UNMAP;
+ _cb_fn = NULL;
+ _cb_param = NULL;
+ } else {
+ _cb_fn = cb_fn;
+ _cb_param = cb_param;
+ }
+ if (_cb_fn)
+ dma_flags |= DMA_PREP_INTERRUPT;
- async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+ /* Since we have clobbered the src_list we are committed
+ * to doing this asynchronously. Drivers force forward progress
+ * in case they can not provide a descriptor
+ */
+ tx = dma->device_prep_dma_xor(chan, dma_dest, &dma_src[src_off],
+ xor_src_cnt, len, dma_flags);
+
+ if (unlikely(!tx))
+ async_tx_quiesce(&depend_tx);
+
+ /* spin wait for the preceeding transactions to complete */
+ while (unlikely(!tx)) {
+ dma_async_issue_pending(chan);
+ tx = dma->device_prep_dma_xor(chan, dma_dest,
+ &dma_src[src_off],
+ xor_src_cnt, len,
+ dma_flags);
+ }
+
+ async_tx_submit(chan, tx, async_flags, depend_tx, _cb_fn,
+ _cb_param);
+
+ depend_tx = tx;
+ flags |= ASYNC_TX_DEP_ACK;
+
+ if (src_cnt > xor_src_cnt) {
+ /* drop completed sources */
+ src_cnt -= xor_src_cnt;
+ src_off += xor_src_cnt;
+
+ /* use the intermediate result a source */
+ dma_src[--src_off] = dma_dest;
+ src_cnt++;
+ } else
+ break;
+ }
return tx;
}
static void
do_sync_xor(struct page *dest, struct page **src_list, unsigned int offset,
- unsigned int src_cnt, size_t len, enum async_tx_flags flags,
- struct dma_async_tx_descriptor *depend_tx,
- dma_async_tx_callback cb_fn, void *cb_param)
+ int src_cnt, size_t len, enum async_tx_flags flags,
+ dma_async_tx_callback cb_fn, void *cb_param)
{
- void *_dest;
int i;
-
- pr_debug("%s: len: %zu\n", __func__, len);
+ int xor_src_cnt;
+ int src_off = 0;
+ void *dest_buf;
+ void **srcs = (void **) src_list;
/* reuse the 'src_list' array to convert to buffer pointers */
for (i = 0; i < src_cnt; i++)
- src_list[i] = (struct page *)
- (page_address(src_list[i]) + offset);
+ srcs[i] = page_address(src_list[i]) + offset;
/* set destination address */
- _dest = page_address(dest) + offset;
+ dest_buf = page_address(dest) + offset;
if (flags & ASYNC_TX_XOR_ZERO_DST)
- memset(_dest, 0, len);
+ memset(dest_buf, 0, len);
- xor_blocks(src_cnt, len, _dest,
- (void **) src_list);
+ while (src_cnt > 0) {
+ /* process up to 'MAX_XOR_BLOCKS' sources */
+ xor_src_cnt = min(src_cnt, MAX_XOR_BLOCKS);
+ xor_blocks(xor_src_cnt, len, dest_buf, &srcs[src_off]);
- async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+ /* drop completed sources */
+ src_cnt -= xor_src_cnt;
+ src_off += xor_src_cnt;
+ }
+
+ async_tx_sync_epilog(cb_fn, cb_param);
}
/**
@@ -132,106 +179,34 @@ async_xor(struct page *dest, struct page **src_list, unsigned int offset,
struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_XOR,
&dest, 1, src_list,
src_cnt, len);
- struct dma_device *device = chan ? chan->device : NULL;
- struct dma_async_tx_descriptor *tx = NULL;
- dma_async_tx_callback _cb_fn;
- void *_cb_param;
- unsigned long local_flags;
- int xor_src_cnt;
- int i = 0, src_off = 0;
-
BUG_ON(src_cnt <= 1);
- while (src_cnt) {
- local_flags = flags;
- if (device) { /* run the xor asynchronously */
- xor_src_cnt = min(src_cnt, device->max_xor);
- /* if we are submitting additional xors
- * only set the callback on the last transaction
- */
- if (src_cnt > xor_src_cnt) {
- local_flags &= ~ASYNC_TX_ACK;
- _cb_fn = NULL;
- _cb_param = NULL;
- } else {
- _cb_fn = cb_fn;
- _cb_param = cb_param;
- }
-
- tx = do_async_xor(device, chan, dest,
- &src_list[src_off], offset,
- xor_src_cnt, len, local_flags,
- depend_tx, _cb_fn, _cb_param);
- } else { /* run the xor synchronously */
- /* in the sync case the dest is an implied source
- * (assumes the dest is at the src_off index)
- */
- if (flags & ASYNC_TX_XOR_DROP_DST) {
- src_cnt--;
- src_off++;
- }
-
- /* process up to 'MAX_XOR_BLOCKS' sources */
- xor_src_cnt = min(src_cnt, MAX_XOR_BLOCKS);
-
- /* if we are submitting additional xors
- * only set the callback on the last transaction
- */
- if (src_cnt > xor_src_cnt) {
- local_flags &= ~ASYNC_TX_ACK;
- _cb_fn = NULL;
- _cb_param = NULL;
- } else {
- _cb_fn = cb_fn;
- _cb_param = cb_param;
- }
-
- /* wait for any prerequisite operations */
- if (depend_tx) {
- /* if ack is already set then we cannot be sure
- * we are referring to the correct operation
- */
- BUG_ON(async_tx_test_ack(depend_tx));
- if (dma_wait_for_async_tx(depend_tx) ==
- DMA_ERROR)
- panic("%s: DMA_ERROR waiting for "
- "depend_tx\n",
- __func__);
- }
-
- do_sync_xor(dest, &src_list[src_off], offset,
- xor_src_cnt, len, local_flags, depend_tx,
- _cb_fn, _cb_param);
- }
+ if (chan) {
+ /* run the xor asynchronously */
+ pr_debug("%s (async): len: %zu\n", __func__, len);
- /* the previous tx is hidden from the client,
- * so ack it
- */
- if (i && depend_tx)
- async_tx_ack(depend_tx);
+ return do_async_xor(chan, dest, src_list, offset, src_cnt, len,
+ flags, depend_tx, cb_fn, cb_param);
+ } else {
+ /* run the xor synchronously */
+ pr_debug("%s (sync): len: %zu\n", __func__, len);
- depend_tx = tx;
+ /* in the sync case the dest is an implied source
+ * (assumes the dest is the first source)
+ */
+ if (flags & ASYNC_TX_XOR_DROP_DST) {
+ src_cnt--;
+ src_list++;
+ }
- if (src_cnt > xor_src_cnt) {
- /* drop completed sources */
- src_cnt -= xor_src_cnt;
- src_off += xor_src_cnt;
+ /* wait for any prerequisite operations */
+ async_tx_quiesce(&depend_tx);
- /* unconditionally preserve the destination */
- flags &= ~ASYNC_TX_XOR_ZERO_DST;
+ do_sync_xor(dest, src_list, offset, src_cnt, len,
+ flags, cb_fn, cb_param);
- /* use the intermediate result a source, but remember
- * it's dropped, because it's implied, in the sync case
- */
- src_list[--src_off] = dest;
- src_cnt++;
- flags |= ASYNC_TX_XOR_DROP_DST;
- } else
- src_cnt = 0;
- i++;
+ return NULL;
}
-
- return tx;
}
EXPORT_SYMBOL_GPL(async_xor);
@@ -285,11 +260,11 @@ async_xor_zero_sum(struct page *dest, struct page **src_list,
tx = device->device_prep_dma_zero_sum(chan, dma_src, src_cnt,
len, result,
dma_prep_flags);
- if (!tx) {
- if (depend_tx)
- dma_wait_for_async_tx(depend_tx);
+ if (unlikely(!tx)) {
+ async_tx_quiesce(&depend_tx);
while (!tx)
+ dma_async_issue_pending(chan);
tx = device->device_prep_dma_zero_sum(chan,
dma_src, src_cnt, len, result,
dma_prep_flags);
@@ -307,18 +282,11 @@ async_xor_zero_sum(struct page *dest, struct page **src_list,
tx = async_xor(dest, src_list, offset, src_cnt, len, xor_flags,
depend_tx, NULL, NULL);
- if (tx) {
- if (dma_wait_for_async_tx(tx) == DMA_ERROR)
- panic("%s: DMA_ERROR waiting for tx\n",
- __func__);
- async_tx_ack(tx);
- }
+ async_tx_quiesce(&tx);
*result = page_is_zero(dest, offset, len) ? 0 : 1;
- tx = NULL;
-
- async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+ async_tx_sync_epilog(cb_fn, cb_param);
}
return tx;
diff --git a/drivers/Makefile b/drivers/Makefile
index 808e0ae66aa..54ec5e718c0 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -5,7 +5,7 @@
# Rewritten to use lists instead of if-statements.
#
-obj-$(CONFIG_HAVE_GPIO_LIB) += gpio/
+obj-y += gpio/
obj-$(CONFIG_PCI) += pci/
obj-$(CONFIG_PARISC) += parisc/
obj-$(CONFIG_RAPIDIO) += rapidio/
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 55c17afbe66..2655bc1b4ee 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -263,22 +263,22 @@ static int acpi_fan_add(struct acpi_device *device)
goto end;
}
- printk(KERN_INFO PREFIX
- "%s is registered as cooling_device%d\n",
- device->dev.bus_id, cdev->id);
+ dev_info(&device->dev, "registered as cooling_device%d\n", cdev->id);
acpi_driver_data(device) = cdev;
result = sysfs_create_link(&device->dev.kobj,
&cdev->device.kobj,
"thermal_cooling");
if (result)
- printk(KERN_ERR PREFIX "Create sysfs link\n");
+ dev_err(&device->dev, "Failed to create sysfs link "
+ "'thermal_cooling'\n");
result = sysfs_create_link(&cdev->device.kobj,
&device->dev.kobj,
"device");
if (result)
- printk(KERN_ERR PREFIX "Create sysfs link\n");
+ dev_err(&device->dev, "Failed to create sysfs link "
+ "'device'\n");
result = acpi_fan_add_fs(device);
if (result)
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 2f173e83f8a..084109507c9 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -146,8 +146,7 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
acpi_status status;
if (dev->archdata.acpi_handle) {
- printk(KERN_WARNING PREFIX
- "Drivers changed 'acpi_handle' for %s\n", dev->bus_id);
+ dev_warn(dev, "Drivers changed 'acpi_handle'\n");
return -EINVAL;
}
get_device(dev);
@@ -195,8 +194,7 @@ static int acpi_unbind_one(struct device *dev)
/* acpi_bind_one increase refcnt by one */
put_device(dev);
} else {
- printk(KERN_ERR PREFIX
- "Oops, 'acpi_handle' corrupt for %s\n", dev->bus_id);
+ dev_err(dev, "Oops, 'acpi_handle' corrupt\n");
}
return 0;
}
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c
index cffef1bcbdb..549db42f16c 100644
--- a/drivers/acpi/namespace/nsnames.c
+++ b/drivers/acpi/namespace/nsnames.c
@@ -137,6 +137,10 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
/* Calculate required buffer size based on depth below root */
size = acpi_ns_get_pathname_length(node);
+ if (!size) {
+ ACPI_ERROR((AE_INFO, "Invalid node failure"));
+ return_PTR(NULL);
+ }
/* Allocate a buffer to be returned to caller */
@@ -229,6 +233,10 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle,
/* Determine size required for the caller buffer */
required_size = acpi_ns_get_pathname_length(node);
+ if (!required_size) {
+ ACPI_ERROR((AE_INFO, "Invalid node failure"));
+ return_ACPI_STATUS(AE_ERROR);
+ }
/* Validate/Allocate/Clear caller buffer */
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 233c40c5168..89f3b2abfdc 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -113,20 +113,23 @@ acpi_pci_link_check_possible(struct acpi_resource *resource, void *context)
switch (resource->type) {
case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+ case ACPI_RESOURCE_TYPE_END_TAG:
return AE_OK;
case ACPI_RESOURCE_TYPE_IRQ:
{
struct acpi_resource_irq *p = &resource->data.irq;
if (!p || !p->interrupt_count) {
- printk(KERN_WARNING PREFIX "Blank IRQ resource\n");
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Blank _PRS IRQ resource\n"));
return AE_OK;
}
for (i = 0;
(i < p->interrupt_count
&& i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
if (!p->interrupts[i]) {
- printk(KERN_WARNING PREFIX "Invalid IRQ %d\n",
- p->interrupts[i]);
+ printk(KERN_WARNING PREFIX
+ "Invalid _PRS IRQ %d\n",
+ p->interrupts[i]);
continue;
}
link->irq.possible[i] = p->interrupts[i];
@@ -143,15 +146,16 @@ acpi_pci_link_check_possible(struct acpi_resource *resource, void *context)
&resource->data.extended_irq;
if (!p || !p->interrupt_count) {
printk(KERN_WARNING PREFIX
- "Blank EXT IRQ resource\n");
+ "Blank _PRS EXT IRQ resource\n");
return AE_OK;
}
for (i = 0;
(i < p->interrupt_count
&& i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
if (!p->interrupts[i]) {
- printk(KERN_WARNING PREFIX "Invalid IRQ %d\n",
- p->interrupts[i]);
+ printk(KERN_WARNING PREFIX
+ "Invalid _PRS IRQ %d\n",
+ p->interrupts[i]);
continue;
}
link->irq.possible[i] = p->interrupts[i];
@@ -163,7 +167,8 @@ acpi_pci_link_check_possible(struct acpi_resource *resource, void *context)
break;
}
default:
- printk(KERN_ERR PREFIX "Resource is not an IRQ entry\n");
+ printk(KERN_ERR PREFIX "_PRS resource type 0x%x isn't an IRQ\n",
+ resource->type);
return AE_OK;
}
@@ -199,6 +204,9 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context)
switch (resource->type) {
+ case ACPI_RESOURCE_TYPE_START_DEPENDENT:
+ case ACPI_RESOURCE_TYPE_END_TAG:
+ return AE_OK;
case ACPI_RESOURCE_TYPE_IRQ:
{
struct acpi_resource_irq *p = &resource->data.irq;
@@ -208,7 +216,7 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context)
* particularly those those w/ _STA disabled
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Blank IRQ resource\n"));
+ "Blank _CRS IRQ resource\n"));
return AE_OK;
}
*irq = p->interrupts[0];
@@ -224,7 +232,7 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context)
* return at least 1 IRQ
*/
printk(KERN_WARNING PREFIX
- "Blank EXT IRQ resource\n");
+ "Blank _CRS EXT IRQ resource\n");
return AE_OK;
}
*irq = p->interrupts[0];
@@ -232,10 +240,11 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context)
}
break;
default:
- printk(KERN_ERR PREFIX "Resource %d isn't an IRQ\n", resource->type);
- case ACPI_RESOURCE_TYPE_END_TAG:
+ printk(KERN_ERR PREFIX "_CRS resource type 0x%x isn't an IRQ\n",
+ resource->type);
return AE_OK;
}
+
return AE_CTRL_TERMINATE;
}
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c
index b9ab030a52d..dd376f7ad09 100644
--- a/drivers/acpi/pci_slot.c
+++ b/drivers/acpi/pci_slot.c
@@ -6,8 +6,8 @@
* Thanks to Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> for code
* review and fixes.
*
- * Copyright (C) 2007 Alex Chiang <achiang@hp.com>
- * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2007-2008 Hewlett-Packard Development Company, L.P.
+ * Alex Chiang <achiang@hp.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -158,6 +158,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
if (IS_ERR(pci_slot)) {
err("pci_create_slot returned %ld\n", PTR_ERR(pci_slot));
kfree(slot);
+ return AE_OK;
}
slot->root_handle = parent_context->root_handle;
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index ec0f2d581ec..e36422a7122 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -714,9 +714,8 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
goto end;
}
- printk(KERN_INFO PREFIX
- "%s is registered as cooling_device%d\n",
- device->dev.bus_id, pr->cdev->id);
+ dev_info(&device->dev, "registered as cooling_device%d\n",
+ pr->cdev->id);
result = sysfs_create_link(&device->dev.kobj,
&pr->cdev->device.kobj,
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 0622ace0522..a2c3f9cfa54 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -827,6 +827,7 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr)
static int acpi_processor_get_throttling(struct acpi_processor *pr)
{
cpumask_t saved_mask;
+ cpumask_of_cpu_ptr_declare(new_mask);
int ret;
if (!pr)
@@ -838,7 +839,8 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
* Migrate task to the cpu pointed by pr.
*/
saved_mask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
+ cpumask_of_cpu_ptr_next(new_mask, pr->id);
+ set_cpus_allowed_ptr(current, new_mask);
ret = pr->throttling.acpi_processor_get_throttling(pr);
/* restore the previous state */
set_cpus_allowed_ptr(current, &saved_mask);
@@ -987,6 +989,7 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
{
cpumask_t saved_mask;
+ cpumask_of_cpu_ptr_declare(new_mask);
int ret = 0;
unsigned int i;
struct acpi_processor *match_pr;
@@ -1013,7 +1016,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* affected cpu in order to get one proper T-state.
* The notifier event is THROTTLING_PRECHANGE.
*/
- for_each_cpu_mask(i, online_throttling_cpus) {
+ for_each_cpu_mask_nr(i, online_throttling_cpus) {
t_state.cpu = i;
acpi_processor_throttling_notifier(THROTTLING_PRECHANGE,
&t_state);
@@ -1025,7 +1028,8 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* it can be called only for the cpu pointed by pr.
*/
if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
+ cpumask_of_cpu_ptr_next(new_mask, pr->id);
+ set_cpus_allowed_ptr(current, new_mask);
ret = p_throttling->acpi_processor_set_throttling(pr,
t_state.target_state);
} else {
@@ -1034,7 +1038,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* it is necessary to set T-state for every affected
* cpus.
*/
- for_each_cpu_mask(i, online_throttling_cpus) {
+ for_each_cpu_mask_nr(i, online_throttling_cpus) {
match_pr = per_cpu(processors, i);
/*
* If the pointer is invalid, we will report the
@@ -1056,7 +1060,8 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
continue;
}
t_state.cpu = i;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(i));
+ cpumask_of_cpu_ptr_next(new_mask, i);
+ set_cpus_allowed_ptr(current, new_mask);
ret = match_pr->throttling.
acpi_processor_set_throttling(
match_pr, t_state.target_state);
@@ -1068,7 +1073,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* affected cpu to update the T-states.
* The notifier event is THROTTLING_POSTCHANGE
*/
- for_each_cpu_mask(i, online_throttling_cpus) {
+ for_each_cpu_mask_nr(i, online_throttling_cpus) {
t_state.cpu = i;
acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
&t_state);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index f3132aa47a6..f6f52c1a2ab 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -471,7 +471,7 @@ static int acpi_device_register(struct acpi_device *device,
device->dev.release = &acpi_device_release;
result = device_add(&device->dev);
if(result) {
- printk(KERN_ERR PREFIX "Error adding device %s", device->dev.bus_id);
+ dev_err(&device->dev, "Error adding device\n");
goto end;
}
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 0489a7d1d42..d13194a031b 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -280,9 +280,36 @@ static struct platform_suspend_ops acpi_suspend_ops_old = {
.end = acpi_pm_end,
.recover = acpi_pm_finish,
};
+
+static int __init init_old_suspend_ordering(const struct dmi_system_id *d)
+{
+ old_suspend_ordering = true;
+ return 0;
+}
+
+static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
+ {
+ .callback = init_old_suspend_ordering,
+ .ident = "Abit KN9 (nForce4 variant)",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"),
+ DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"),
+ },
+ },
+ {},
+};
#endif /* CONFIG_SUSPEND */
#ifdef CONFIG_HIBERNATION
+static unsigned long s4_hardware_signature;
+static struct acpi_table_facs *facs;
+static bool nosigcheck;
+
+void __init acpi_no_s4_hw_signature(void)
+{
+ nosigcheck = true;
+}
+
static int acpi_hibernation_begin(void)
{
acpi_target_sleep_state = ACPI_STATE_S4;
@@ -316,6 +343,12 @@ static void acpi_hibernation_leave(void)
acpi_enable();
/* Reprogram control registers and execute _BFS */
acpi_leave_sleep_state_prep(ACPI_STATE_S4);
+ /* Check the hardware signature */
+ if (facs && s4_hardware_signature != facs->hardware_signature) {
+ printk(KERN_EMERG "ACPI: Hardware changed while hibernated, "
+ "cannot resume!\n");
+ panic("ACPI S4 hardware signature mismatch");
+ }
}
static void acpi_pm_enable_gpes(void)
@@ -516,6 +549,8 @@ int __init acpi_sleep_init(void)
u8 type_a, type_b;
#ifdef CONFIG_SUSPEND
int i = 0;
+
+ dmi_check_system(acpisleep_dmi_table);
#endif
if (acpi_disabled)
@@ -544,6 +579,13 @@ int __init acpi_sleep_init(void)
&acpi_hibernation_ops_old : &acpi_hibernation_ops);
sleep_states[ACPI_STATE_S4] = 1;
printk(" S4");
+ if (!nosigcheck) {
+ acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
+ (struct acpi_table_header **)&facs);
+ if (facs)
+ s4_hardware_signature =
+ facs->hardware_signature;
+ }
}
#endif
status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index d8e3f153b29..91dec448b3e 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -26,6 +26,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/init.h>
+#include <linux/string.h>
#include <asm/uaccess.h>
#include <acpi/acpi_drivers.h>
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c
index ccb5b64bbef..a4a41ba2484 100644
--- a/drivers/acpi/tables/tbfadt.c
+++ b/drivers/acpi/tables/tbfadt.c
@@ -124,7 +124,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
static void inline
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
- u8 byte_width, u64 address)
+ u8 bit_width, u64 address)
{
/*
@@ -136,7 +136,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
/* All other fields are byte-wide */
generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO;
- generic_address->bit_width = byte_width << 3;
+ generic_address->bit_width = bit_width;
generic_address->bit_offset = 0;
generic_address->access_width = 0;
}
@@ -343,11 +343,9 @@ static void acpi_tb_convert_fadt(void)
*
* The PM event blocks are split into two register blocks, first is the
* PM Status Register block, followed immediately by the PM Enable Register
- * block. Each is of length (xpm1x_event_block.bit_width/2)
+ * block. Each is of length (pm1_event_length/2)
*/
- WARN_ON(ACPI_MOD_16(acpi_gbl_FADT.xpm1a_event_block.bit_width));
- pm1_register_length = (u8) ACPI_DIV_16(acpi_gbl_FADT
- .xpm1a_event_block.bit_width);
+ pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length);
/* The PM1A register block is required */
@@ -362,17 +360,14 @@ static void acpi_tb_convert_fadt(void)
/* The PM1B register block is optional, ignore if not present */
if (acpi_gbl_FADT.xpm1b_event_block.address) {
- WARN_ON(ACPI_MOD_16(acpi_gbl_FADT.xpm1b_event_block.bit_width));
- pm1_register_length = (u8) ACPI_DIV_16(acpi_gbl_FADT
- .xpm1b_event_block
- .bit_width);
acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
pm1_register_length,
(acpi_gbl_FADT.xpm1b_event_block.
address + pm1_register_length));
/* Don't forget to copy space_id of the GAS */
acpi_gbl_xpm1b_enable.space_id =
- acpi_gbl_FADT.xpm1b_event_block.space_id;
+ acpi_gbl_FADT.xpm1a_event_block.space_id;
+
}
}
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 84c795fb9b1..912703691d3 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -769,6 +769,47 @@ static void acpi_thermal_run(unsigned long data)
acpi_os_execute(OSL_GPE_HANDLER, acpi_thermal_check, (void *)data);
}
+static void acpi_thermal_active_off(void *data)
+{
+ int result = 0;
+ struct acpi_thermal *tz = data;
+ int i = 0;
+ int j = 0;
+ struct acpi_thermal_active *active = NULL;
+
+ if (!tz) {
+ printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
+ return;
+ }
+
+ result = acpi_thermal_get_temperature(tz);
+ if (result)
+ return;
+
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+ active = &(tz->trips.active[i]);
+ if (!active || !active->flags.valid)
+ break;
+ if (tz->temperature >= active->temperature) {
+ /*
+ * If the thermal temperature is greater than the
+ * active threshod, unnecessary to turn off the
+ * the active cooling device.
+ */
+ continue;
+ }
+ /*
+ * Below Threshold?
+ * ----------------
+ * Turn OFF all cooling devices associated with this
+ * threshold.
+ */
+ for (j = 0; j < active->devices.count; j++)
+ result = acpi_bus_set_power(active->devices.handles[j],
+ ACPI_STATE_D3);
+ }
+}
+
static void acpi_thermal_check(void *data)
{
int result = 0;
@@ -1179,8 +1220,8 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
tz->tz_enabled = 1;
- printk(KERN_INFO PREFIX "%s is registered as thermal_zone%d\n",
- tz->device->dev.bus_id, tz->thermal_zone->id);
+ dev_info(&tz->device->dev, "registered as thermal_zone%d\n",
+ tz->thermal_zone->id);
return 0;
}
@@ -1624,6 +1665,8 @@ static int acpi_thermal_add(struct acpi_device *device)
init_timer(&tz->timer);
+ acpi_thermal_active_off(tz);
+
acpi_thermal_check(tz);
status = acpi_install_notify_handler(device->handle,
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
index 3dfb8a442b2..e7bf34a7b1d 100644
--- a/drivers/acpi/utilities/utalloc.c
+++ b/drivers/acpi/utilities/utalloc.c
@@ -242,6 +242,10 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
{
acpi_status status = AE_OK;
+ if (!required_length) {
+ WARN_ON(1);
+ return AE_ERROR;
+ }
switch (buffer->length) {
case ACPI_NO_BUFFER:
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 64c889331f3..e8a51a1700f 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -741,7 +741,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
max_level = acpi_video_init_brightness(device);
- if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
+ if (device->cap._BCL && device->cap._BCM && max_level > 0) {
int result;
static int count = 0;
char *name;
@@ -753,7 +753,17 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
device->backlight = backlight_device_register(name,
NULL, device, &acpi_backlight_ops);
device->backlight->props.max_brightness = device->brightness->count-3;
- device->backlight->props.brightness = acpi_video_get_brightness(device->backlight);
+ /*
+ * If there exists the _BQC object, the _BQC object will be
+ * called to get the current backlight brightness. Otherwise
+ * the brightness will be set to the maximum.
+ */
+ if (device->cap._BQC)
+ device->backlight->props.brightness =
+ acpi_video_get_brightness(device->backlight);
+ else
+ device->backlight->props.brightness =
+ device->backlight->props.max_brightness;
backlight_update_status(device->backlight);
kfree(name);
@@ -762,9 +772,8 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
if (IS_ERR(device->cdev))
return;
- printk(KERN_INFO PREFIX
- "%s is registered as cooling_device%d\n",
- device->dev->dev.bus_id, device->cdev->id);
+ dev_info(&device->dev->dev, "registered as cooling_device%d\n",
+ device->cdev->id);
result = sysfs_create_link(&device->dev->dev.kobj,
&device->cdev->device.kobj,
"thermal_cooling");
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index dc7596f028b..ef3e5522e1a 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1273,7 +1273,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
u32 em_ctl;
u32 message[] = {0, 0};
- unsigned int flags;
+ unsigned long flags;
int pmp;
struct ahci_em_priv *emp;
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index d5c1bbfbe79..73338d231db 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -2562,7 +2562,8 @@ fore200e_load_and_start_fw(struct fore200e* fore200e)
const struct firmware *firmware;
struct device *device;
struct fw_header *fw_header;
- u32 *fw_data, fw_size;
+ const __le32 *fw_data;
+ u32 fw_size;
u32 __iomem *load_addr;
char buf[48];
int err = -ENODEV;
@@ -2582,7 +2583,7 @@ fore200e_load_and_start_fw(struct fore200e* fore200e)
return err;
}
- fw_data = (u32 *) firmware->data;
+ fw_data = (__le32 *) firmware->data;
fw_size = firmware->size / sizeof(u32);
fw_header = (struct fw_header *) firmware->data;
load_addr = fore200e->virt_base + le32_to_cpu(fw_header->load_offset);
@@ -3199,6 +3200,14 @@ static const struct fore200e_bus fore200e_bus[] = {
{}
};
-#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
+#ifdef CONFIG_PCI
+#ifdef __LITTLE_ENDIAN__
+MODULE_FIRMWARE("pca200e.bin");
+#else
+MODULE_FIRMWARE("pca200e_ecd.bin2");
+#endif
+#endif /* CONFIG_PCI */
+#ifdef CONFIG_SBUS
+MODULE_FIRMWARE("sba200e_ecd.bin2");
#endif
diff --git a/drivers/auxdisplay/cfag12864b.c b/drivers/auxdisplay/cfag12864b.c
index 683509f013a..eacb175f6bd 100644
--- a/drivers/auxdisplay/cfag12864b.c
+++ b/drivers/auxdisplay/cfag12864b.c
@@ -336,16 +336,9 @@ static int __init cfag12864b_init(void)
"ks0108 is not initialized\n");
goto none;
}
+ BUILD_BUG_ON(PAGE_SIZE < CFAG12864B_SIZE);
- if (PAGE_SIZE < CFAG12864B_SIZE) {
- printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
- "page size (%i) < cfag12864b size (%i)\n",
- (unsigned int)PAGE_SIZE, CFAG12864B_SIZE);
- ret = -ENOMEM;
- goto none;
- }
-
- cfag12864b_buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
+ cfag12864b_buffer = (unsigned char *) get_zeroed_page(GFP_KERNEL);
if (cfag12864b_buffer == NULL) {
printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
"can't get a free page\n");
@@ -367,8 +360,6 @@ static int __init cfag12864b_init(void)
if (cfag12864b_workqueue == NULL)
goto cachealloced;
- memset(cfag12864b_buffer, 0, CFAG12864B_SIZE);
-
cfag12864b_clear();
cfag12864b_on();
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index d47482fa1d2..6318f6b5736 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -27,8 +27,9 @@ config PREVENT_FIRMWARE_BUILD
If unsure say Y here.
config FW_LOADER
- tristate "Userspace firmware loading support"
+ tristate "Userspace firmware loading support" if EMBEDDED
depends on HOTPLUG
+ default y
---help---
This option is provided for the case where no in-kernel-tree modules
require userspace firmware loading support, but a module built outside
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 2c9ae43e221..31dc0cd84af 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -36,6 +36,33 @@ struct driver_private {
};
#define to_driver(obj) container_of(obj, struct driver_private, kobj)
+
+/**
+ * struct class_private - structure to hold the private to the driver core portions of the class structure.
+ *
+ * @class_subsys - the struct kset that defines this class. This is the main kobject
+ * @class_devices - list of devices associated with this class
+ * @class_interfaces - list of class_interfaces associated with this class
+ * @class_dirs - "glue" directory for virtual devices associated with this class
+ * @class_mutex - mutex to protect the children, devices, and interfaces lists.
+ * @class - pointer back to the struct class that this structure is associated
+ * with.
+ *
+ * This structure is the one that is the actual kobject allowing struct
+ * class to be statically allocated safely. Nothing outside of the driver
+ * core should ever touch these fields.
+ */
+struct class_private {
+ struct kset class_subsys;
+ struct list_head class_devices;
+ struct list_head class_interfaces;
+ struct kset class_dirs;
+ struct mutex class_mutex;
+ struct class *class;
+};
+#define to_class(obj) \
+ container_of(obj, struct class_private, class_subsys.kobj)
+
/* initialisation functions */
extern int devices_init(void);
extern int buses_init(void);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index e085af0ff94..839d27cecb3 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -18,20 +18,20 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/genhd.h>
+#include <linux/mutex.h>
#include "base.h"
#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
-#define to_class(obj) container_of(obj, struct class, subsys.kobj)
static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
struct class_attribute *class_attr = to_class_attr(attr);
- struct class *dc = to_class(kobj);
+ struct class_private *cp = to_class(kobj);
ssize_t ret = -EIO;
if (class_attr->show)
- ret = class_attr->show(dc, buf);
+ ret = class_attr->show(cp->class, buf);
return ret;
}
@@ -39,17 +39,18 @@ static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr,
const char *buf, size_t count)
{
struct class_attribute *class_attr = to_class_attr(attr);
- struct class *dc = to_class(kobj);
+ struct class_private *cp = to_class(kobj);
ssize_t ret = -EIO;
if (class_attr->store)
- ret = class_attr->store(dc, buf, count);
+ ret = class_attr->store(cp->class, buf, count);
return ret;
}
static void class_release(struct kobject *kobj)
{
- struct class *class = to_class(kobj);
+ struct class_private *cp = to_class(kobj);
+ struct class *class = cp->class;
pr_debug("class '%s': release.\n", class->name);
@@ -70,7 +71,7 @@ static struct kobj_type class_ktype = {
.release = class_release,
};
-/* Hotplug events for classes go to the class_obj subsys */
+/* Hotplug events for classes go to the class class_subsys */
static struct kset *class_kset;
@@ -78,7 +79,8 @@ int class_create_file(struct class *cls, const struct class_attribute *attr)
{
int error;
if (cls)
- error = sysfs_create_file(&cls->subsys.kobj, &attr->attr);
+ error = sysfs_create_file(&cls->p->class_subsys.kobj,
+ &attr->attr);
else
error = -EINVAL;
return error;
@@ -87,21 +89,20 @@ int class_create_file(struct class *cls, const struct class_attribute *attr)
void class_remove_file(struct class *cls, const struct class_attribute *attr)
{
if (cls)
- sysfs_remove_file(&cls->subsys.kobj, &attr->attr);
+ sysfs_remove_file(&cls->p->class_subsys.kobj, &attr->attr);
}
static struct class *class_get(struct class *cls)
{
if (cls)
- return container_of(kset_get(&cls->subsys),
- struct class, subsys);
- return NULL;
+ kset_get(&cls->p->class_subsys);
+ return cls;
}
static void class_put(struct class *cls)
{
if (cls)
- kset_put(&cls->subsys);
+ kset_put(&cls->p->class_subsys);
}
static int add_class_attrs(struct class *cls)
@@ -134,42 +135,57 @@ static void remove_class_attrs(struct class *cls)
}
}
-int class_register(struct class *cls)
+int __class_register(struct class *cls, struct lock_class_key *key)
{
+ struct class_private *cp;
int error;
pr_debug("device class '%s': registering\n", cls->name);
- INIT_LIST_HEAD(&cls->devices);
- INIT_LIST_HEAD(&cls->interfaces);
- kset_init(&cls->class_dirs);
- init_MUTEX(&cls->sem);
- error = kobject_set_name(&cls->subsys.kobj, "%s", cls->name);
- if (error)
+ cp = kzalloc(sizeof(*cp), GFP_KERNEL);
+ if (!cp)
+ return -ENOMEM;
+ INIT_LIST_HEAD(&cp->class_devices);
+ INIT_LIST_HEAD(&cp->class_interfaces);
+ kset_init(&cp->class_dirs);
+ __mutex_init(&cp->class_mutex, "struct class mutex", key);
+ error = kobject_set_name(&cp->class_subsys.kobj, "%s", cls->name);
+ if (error) {
+ kfree(cp);
return error;
+ }
+
+ /* set the default /sys/dev directory for devices of this class */
+ if (!cls->dev_kobj)
+ cls->dev_kobj = sysfs_dev_char_kobj;
#if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK)
/* let the block class directory show up in the root of sysfs */
if (cls != &block_class)
- cls->subsys.kobj.kset = class_kset;
+ cp->class_subsys.kobj.kset = class_kset;
#else
- cls->subsys.kobj.kset = class_kset;
+ cp->class_subsys.kobj.kset = class_kset;
#endif
- cls->subsys.kobj.ktype = &class_ktype;
+ cp->class_subsys.kobj.ktype = &class_ktype;
+ cp->class = cls;
+ cls->p = cp;
- error = kset_register(&cls->subsys);
- if (!error) {
- error = add_class_attrs(class_get(cls));
- class_put(cls);
+ error = kset_register(&cp->class_subsys);
+ if (error) {
+ kfree(cp);
+ return error;
}
+ error = add_class_attrs(class_get(cls));
+ class_put(cls);
return error;
}
+EXPORT_SYMBOL_GPL(__class_register);
void class_unregister(struct class *cls)
{
pr_debug("device class '%s': unregistering\n", cls->name);
remove_class_attrs(cls);
- kset_unregister(&cls->subsys);
+ kset_unregister(&cls->p->class_subsys);
}
static void class_create_release(struct class *cls)
@@ -189,7 +205,8 @@ static void class_create_release(struct class *cls)
* Note, the pointer created here is to be destroyed when finished by
* making a call to class_destroy().
*/
-struct class *class_create(struct module *owner, const char *name)
+struct class *__class_create(struct module *owner, const char *name,
+ struct lock_class_key *key)
{
struct class *cls;
int retval;
@@ -204,7 +221,7 @@ struct class *class_create(struct module *owner, const char *name)
cls->owner = owner;
cls->class_release = class_create_release;
- retval = class_register(cls);
+ retval = __class_register(cls, key);
if (retval)
goto error;
@@ -214,6 +231,7 @@ error:
kfree(cls);
return ERR_PTR(retval);
}
+EXPORT_SYMBOL_GPL(__class_create);
/**
* class_destroy - destroys a struct class structure
@@ -252,39 +270,44 @@ char *make_class_name(const char *name, struct kobject *kobj)
/**
* class_for_each_device - device iterator
* @class: the class we're iterating
+ * @start: the device to start with in the list, if any.
* @data: data for the callback
* @fn: function to be called for each device
*
* Iterate over @class's list of devices, and call @fn for each,
- * passing it @data.
+ * passing it @data. If @start is set, the list iteration will start
+ * there, otherwise if it is NULL, the iteration starts at the
+ * beginning of the list.
*
* We check the return of @fn each time. If it returns anything
* other than 0, we break out and return that value.
*
- * Note, we hold class->sem in this function, so it can not be
+ * Note, we hold class->class_mutex in this function, so it can not be
* re-acquired in @fn, otherwise it will self-deadlocking. For
* example, calls to add or remove class members would be verboten.
*/
-int class_for_each_device(struct class *class, void *data,
- int (*fn)(struct device *, void *))
+int class_for_each_device(struct class *class, struct device *start,
+ void *data, int (*fn)(struct device *, void *))
{
struct device *dev;
int error = 0;
if (!class)
return -EINVAL;
- down(&class->sem);
- list_for_each_entry(dev, &class->devices, node) {
+ mutex_lock(&class->p->class_mutex);
+ list_for_each_entry(dev, &class->p->class_devices, node) {
+ if (start) {
+ if (start == dev)
+ start = NULL;
+ continue;
+ }
dev = get_device(dev);
- if (dev) {
- error = fn(dev, data);
- put_device(dev);
- } else
- error = -ENODEV;
+ error = fn(dev, data);
+ put_device(dev);
if (error)
break;
}
- up(&class->sem);
+ mutex_unlock(&class->p->class_mutex);
return error;
}
@@ -293,6 +316,7 @@ EXPORT_SYMBOL_GPL(class_for_each_device);
/**
* class_find_device - device iterator for locating a particular device
* @class: the class we're iterating
+ * @start: Device to begin with
* @data: data for the match function
* @match: function to check device
*
@@ -306,12 +330,13 @@ EXPORT_SYMBOL_GPL(class_for_each_device);
*
* Note, you will need to drop the reference with put_device() after use.
*
- * We hold class->sem in this function, so it can not be
+ * We hold class->class_mutex in this function, so it can not be
* re-acquired in @match, otherwise it will self-deadlocking. For
* example, calls to add or remove class members would be verboten.
*/
-struct device *class_find_device(struct class *class, void *data,
- int (*match)(struct device *, void *))
+struct device *class_find_device(struct class *class, struct device *start,
+ void *data,
+ int (*match)(struct device *, void *))
{
struct device *dev;
int found = 0;
@@ -319,19 +344,21 @@ struct device *class_find_device(struct class *class, void *data,
if (!class)
return NULL;
- down(&class->sem);
- list_for_each_entry(dev, &class->devices, node) {
+ mutex_lock(&class->p->class_mutex);
+ list_for_each_entry(dev, &class->p->class_devices, node) {
+ if (start) {
+ if (start == dev)
+ start = NULL;
+ continue;
+ }
dev = get_device(dev);
- if (dev) {
- if (match(dev, data)) {
- found = 1;
- break;
- } else
- put_device(dev);
- } else
+ if (match(dev, data)) {
+ found = 1;
break;
+ } else
+ put_device(dev);
}
- up(&class->sem);
+ mutex_unlock(&class->p->class_mutex);
return found ? dev : NULL;
}
@@ -349,13 +376,13 @@ int class_interface_register(struct class_interface *class_intf)
if (!parent)
return -EINVAL;
- down(&parent->sem);
- list_add_tail(&class_intf->node, &parent->interfaces);
+ mutex_lock(&parent->p->class_mutex);
+ list_add_tail(&class_intf->node, &parent->p->class_interfaces);
if (class_intf->add_dev) {
- list_for_each_entry(dev, &parent->devices, node)
+ list_for_each_entry(dev, &parent->p->class_devices, node)
class_intf->add_dev(dev, class_intf);
}
- up(&parent->sem);
+ mutex_unlock(&parent->p->class_mutex);
return 0;
}
@@ -368,13 +395,13 @@ void class_interface_unregister(struct class_interface *class_intf)
if (!parent)
return;
- down(&parent->sem);
+ mutex_lock(&parent->p->class_mutex);
list_del_init(&class_intf->node);
if (class_intf->remove_dev) {
- list_for_each_entry(dev, &parent->devices, node)
+ list_for_each_entry(dev, &parent->p->class_devices, node)
class_intf->remove_dev(dev, class_intf);
}
- up(&parent->sem);
+ mutex_unlock(&parent->p->class_mutex);
class_put(parent);
}
@@ -389,9 +416,7 @@ int __init classes_init(void)
EXPORT_SYMBOL_GPL(class_create_file);
EXPORT_SYMBOL_GPL(class_remove_file);
-EXPORT_SYMBOL_GPL(class_register);
EXPORT_SYMBOL_GPL(class_unregister);
-EXPORT_SYMBOL_GPL(class_create);
EXPORT_SYMBOL_GPL(class_destroy);
EXPORT_SYMBOL_GPL(class_interface_register);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index ee0a51a3a41..7d5c63c81a5 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -21,12 +21,16 @@
#include <linux/genhd.h>
#include <linux/kallsyms.h>
#include <linux/semaphore.h>
+#include <linux/mutex.h>
#include "base.h"
#include "power/power.h"
int (*platform_notify)(struct device *dev) = NULL;
int (*platform_notify_remove)(struct device *dev) = NULL;
+static struct kobject *dev_kobj;
+struct kobject *sysfs_dev_char_kobj;
+struct kobject *sysfs_dev_block_kobj;
#ifdef CONFIG_BLOCK
static inline int device_is_not_partition(struct device *dev)
@@ -548,7 +552,7 @@ static struct kobject *get_device_parent(struct device *dev,
{
/* class devices without a parent live in /sys/class/<classname>/ */
if (dev->class && (!parent || parent->class != dev->class))
- return &dev->class->subsys.kobj;
+ return &dev->class->p->class_subsys.kobj;
/* all other devices keep their parent */
else if (parent)
return &parent->kobj;
@@ -594,13 +598,13 @@ static struct kobject *get_device_parent(struct device *dev,
parent_kobj = &parent->kobj;
/* find our class-directory at the parent and reference it */
- spin_lock(&dev->class->class_dirs.list_lock);
- list_for_each_entry(k, &dev->class->class_dirs.list, entry)
+ spin_lock(&dev->class->p->class_dirs.list_lock);
+ list_for_each_entry(k, &dev->class->p->class_dirs.list, entry)
if (k->parent == parent_kobj) {
kobj = kobject_get(k);
break;
}
- spin_unlock(&dev->class->class_dirs.list_lock);
+ spin_unlock(&dev->class->p->class_dirs.list_lock);
if (kobj)
return kobj;
@@ -608,7 +612,7 @@ static struct kobject *get_device_parent(struct device *dev,
k = kobject_create();
if (!k)
return NULL;
- k->kset = &dev->class->class_dirs;
+ k->kset = &dev->class->p->class_dirs;
retval = kobject_add(k, parent_kobj, "%s", dev->class->name);
if (retval < 0) {
kobject_put(k);
@@ -627,7 +631,7 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
{
/* see if we live in a "glue" directory */
if (!glue_dir || !dev->class ||
- glue_dir->kset != &dev->class->class_dirs)
+ glue_dir->kset != &dev->class->p->class_dirs)
return;
kobject_put(glue_dir);
@@ -654,17 +658,18 @@ static int device_add_class_symlinks(struct device *dev)
if (!dev->class)
return 0;
- error = sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj,
+ error = sysfs_create_link(&dev->kobj,
+ &dev->class->p->class_subsys.kobj,
"subsystem");
if (error)
goto out;
#ifdef CONFIG_SYSFS_DEPRECATED
/* stacked class devices need a symlink in the class directory */
- if (dev->kobj.parent != &dev->class->subsys.kobj &&
+ if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
device_is_not_partition(dev)) {
- error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
- dev->bus_id);
+ error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
+ &dev->kobj, dev->bus_id);
if (error)
goto out_subsys;
}
@@ -701,13 +706,14 @@ out_device:
if (dev->parent && device_is_not_partition(dev))
sysfs_remove_link(&dev->kobj, "device");
out_busid:
- if (dev->kobj.parent != &dev->class->subsys.kobj &&
+ if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
device_is_not_partition(dev))
- sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
+ sysfs_remove_link(&dev->class->p->class_subsys.kobj,
+ dev->bus_id);
#else
/* link in the class directory pointing to the device */
- error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
- dev->bus_id);
+ error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
+ &dev->kobj, dev->bus_id);
if (error)
goto out_subsys;
@@ -720,7 +726,7 @@ out_busid:
return 0;
out_busid:
- sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
+ sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id);
#endif
out_subsys:
@@ -746,14 +752,15 @@ static void device_remove_class_symlinks(struct device *dev)
sysfs_remove_link(&dev->kobj, "device");
}
- if (dev->kobj.parent != &dev->class->subsys.kobj &&
+ if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
device_is_not_partition(dev))
- sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
+ sysfs_remove_link(&dev->class->p->class_subsys.kobj,
+ dev->bus_id);
#else
if (dev->parent && device_is_not_partition(dev))
sysfs_remove_link(&dev->kobj, "device");
- sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
+ sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id);
#endif
sysfs_remove_link(&dev->kobj, "subsystem");
@@ -776,6 +783,54 @@ int dev_set_name(struct device *dev, const char *fmt, ...)
EXPORT_SYMBOL_GPL(dev_set_name);
/**
+ * device_to_dev_kobj - select a /sys/dev/ directory for the device
+ * @dev: device
+ *
+ * By default we select char/ for new entries. Setting class->dev_obj
+ * to NULL prevents an entry from being created. class->dev_kobj must
+ * be set (or cleared) before any devices are registered to the class
+ * otherwise device_create_sys_dev_entry() and
+ * device_remove_sys_dev_entry() will disagree about the the presence
+ * of the link.
+ */
+static struct kobject *device_to_dev_kobj(struct device *dev)
+{
+ struct kobject *kobj;
+
+ if (dev->class)
+ kobj = dev->class->dev_kobj;
+ else
+ kobj = sysfs_dev_char_kobj;
+
+ return kobj;
+}
+
+static int device_create_sys_dev_entry(struct device *dev)
+{
+ struct kobject *kobj = device_to_dev_kobj(dev);
+ int error = 0;
+ char devt_str[15];
+
+ if (kobj) {
+ format_dev_t(devt_str, dev->devt);
+ error = sysfs_create_link(kobj, &dev->kobj, devt_str);
+ }
+
+ return error;
+}
+
+static void device_remove_sys_dev_entry(struct device *dev)
+{
+ struct kobject *kobj = device_to_dev_kobj(dev);
+ char devt_str[15];
+
+ if (kobj) {
+ format_dev_t(devt_str, dev->devt);
+ sysfs_remove_link(kobj, devt_str);
+ }
+}
+
+/**
* device_add - add device to device hierarchy.
* @dev: device.
*
@@ -829,6 +884,10 @@ int device_add(struct device *dev)
error = device_create_file(dev, &devt_attr);
if (error)
goto ueventattrError;
+
+ error = device_create_sys_dev_entry(dev);
+ if (error)
+ goto devtattrError;
}
error = device_add_class_symlinks(dev);
@@ -849,15 +908,16 @@ int device_add(struct device *dev)
klist_add_tail(&dev->knode_parent, &parent->klist_children);
if (dev->class) {
- down(&dev->class->sem);
+ mutex_lock(&dev->class->p->class_mutex);
/* tie the class to the device */
- list_add_tail(&dev->node, &dev->class->devices);
+ list_add_tail(&dev->node, &dev->class->p->class_devices);
/* notify any interfaces that the device is here */
- list_for_each_entry(class_intf, &dev->class->interfaces, node)
+ list_for_each_entry(class_intf,
+ &dev->class->p->class_interfaces, node)
if (class_intf->add_dev)
class_intf->add_dev(dev, class_intf);
- up(&dev->class->sem);
+ mutex_unlock(&dev->class->p->class_mutex);
}
Done:
put_device(dev);
@@ -873,6 +933,9 @@ int device_add(struct device *dev)
device_remove_class_symlinks(dev);
SymlinkError:
if (MAJOR(dev->devt))
+ device_remove_sys_dev_entry(dev);
+ devtattrError:
+ if (MAJOR(dev->devt))
device_remove_file(dev, &devt_attr);
ueventattrError:
device_remove_file(dev, &uevent_attr);
@@ -948,19 +1011,22 @@ void device_del(struct device *dev)
device_pm_remove(dev);
if (parent)
klist_del(&dev->knode_parent);
- if (MAJOR(dev->devt))
+ if (MAJOR(dev->devt)) {
+ device_remove_sys_dev_entry(dev);
device_remove_file(dev, &devt_attr);
+ }
if (dev->class) {
device_remove_class_symlinks(dev);
- down(&dev->class->sem);
+ mutex_lock(&dev->class->p->class_mutex);
/* notify any interfaces that the device is now gone */
- list_for_each_entry(class_intf, &dev->class->interfaces, node)
+ list_for_each_entry(class_intf,
+ &dev->class->p->class_interfaces, node)
if (class_intf->remove_dev)
class_intf->remove_dev(dev, class_intf);
/* remove the device from the class list */
list_del_init(&dev->node);
- up(&dev->class->sem);
+ mutex_unlock(&dev->class->p->class_mutex);
}
device_remove_file(dev, &uevent_attr);
device_remove_attrs(dev);
@@ -1074,7 +1140,25 @@ int __init devices_init(void)
devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
if (!devices_kset)
return -ENOMEM;
+ dev_kobj = kobject_create_and_add("dev", NULL);
+ if (!dev_kobj)
+ goto dev_kobj_err;
+ sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);
+ if (!sysfs_dev_block_kobj)
+ goto block_kobj_err;
+ sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);
+ if (!sysfs_dev_char_kobj)
+ goto char_kobj_err;
+
return 0;
+
+ char_kobj_err:
+ kobject_put(sysfs_dev_block_kobj);
+ block_kobj_err:
+ kobject_put(dev_kobj);
+ dev_kobj_err:
+ kset_unregister(devices_kset);
+ return -ENOMEM;
}
EXPORT_SYMBOL_GPL(device_for_each_child);
@@ -1158,48 +1242,11 @@ error:
EXPORT_SYMBOL_GPL(device_create_vargs);
/**
- * device_create_drvdata - creates a device and registers it with sysfs
- * @class: pointer to the struct class that this device should be registered to
- * @parent: pointer to the parent struct device of this new device, if any
- * @devt: the dev_t for the char device to be added
- * @drvdata: the data to be added to the device for callbacks
- * @fmt: string for the device's name
- *
- * This function can be used by char device classes. A struct device
- * will be created in sysfs, registered to the specified class.
- *
- * A "dev" file will be created, showing the dev_t for the device, if
- * the dev_t is not 0,0.
- * If a pointer to a parent struct device is passed in, the newly created
- * struct device will be a child of that device in sysfs.
- * The pointer to the struct device will be returned from the call.
- * Any further sysfs files that might be required can be created using this
- * pointer.
- *
- * Note: the struct class passed to this function must have previously
- * been created with a call to class_create().
- */
-struct device *device_create_drvdata(struct class *class,
- struct device *parent,
- dev_t devt,
- void *drvdata,
- const char *fmt, ...)
-{
- va_list vargs;
- struct device *dev;
-
- va_start(vargs, fmt);
- dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
- va_end(vargs);
- return dev;
-}
-EXPORT_SYMBOL_GPL(device_create_drvdata);
-
-/**
* device_create - creates a device and registers it with sysfs
* @class: pointer to the struct class that this device should be registered to
* @parent: pointer to the parent struct device of this new device, if any
* @devt: the dev_t for the char device to be added
+ * @drvdata: the data to be added to the device for callbacks
* @fmt: string for the device's name
*
* This function can be used by char device classes. A struct device
@@ -1217,13 +1264,13 @@ EXPORT_SYMBOL_GPL(device_create_drvdata);
* been created with a call to class_create().
*/
struct device *device_create(struct class *class, struct device *parent,
- dev_t devt, const char *fmt, ...)
+ dev_t devt, void *drvdata, const char *fmt, ...)
{
va_list vargs;
struct device *dev;
va_start(vargs, fmt);
- dev = device_create_vargs(class, parent, devt, NULL, fmt, vargs);
+ dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
va_end(vargs);
return dev;
}
@@ -1248,7 +1295,7 @@ void device_destroy(struct class *class, dev_t devt)
{
struct device *dev;
- dev = class_find_device(class, &devt, __match_devt);
+ dev = class_find_device(class, NULL, &devt, __match_devt);
if (dev) {
put_device(dev);
device_unregister(dev);
@@ -1298,8 +1345,9 @@ int device_rename(struct device *dev, char *new_name)
if (old_class_name) {
new_class_name = make_class_name(dev->class->name, &dev->kobj);
if (new_class_name) {
- error = sysfs_create_link(&dev->parent->kobj,
- &dev->kobj, new_class_name);
+ error = sysfs_create_link_nowarn(&dev->parent->kobj,
+ &dev->kobj,
+ new_class_name);
if (error)
goto out;
sysfs_remove_link(&dev->parent->kobj, old_class_name);
@@ -1307,11 +1355,12 @@ int device_rename(struct device *dev, char *new_name)
}
#else
if (dev->class) {
- error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
- dev->bus_id);
+ error = sysfs_create_link_nowarn(&dev->class->p->class_subsys.kobj,
+ &dev->kobj, dev->bus_id);
if (error)
goto out;
- sysfs_remove_link(&dev->class->subsys.kobj, old_device_name);
+ sysfs_remove_link(&dev->class->p->class_subsys.kobj,
+ old_device_name);
}
#endif
@@ -1447,4 +1496,7 @@ void device_shutdown(void)
dev->driver->shutdown(dev);
}
}
+ kobject_put(sysfs_dev_char_kobj);
+ kobject_put(sysfs_dev_block_kobj);
+ kobject_put(dev_kobj);
}
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index e38dfed41d8..64f5d54f7ed 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -21,15 +21,16 @@ EXPORT_SYMBOL(cpu_sysdev_class);
static DEFINE_PER_CPU(struct sys_device *, cpu_sys_devices);
#ifdef CONFIG_HOTPLUG_CPU
-static ssize_t show_online(struct sys_device *dev, char *buf)
+static ssize_t show_online(struct sys_device *dev, struct sysdev_attribute *attr,
+ char *buf)
{
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id));
}
-static ssize_t __ref store_online(struct sys_device *dev, const char *buf,
- size_t count)
+static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribute *attr,
+ const char *buf, size_t count)
{
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
ssize_t ret;
@@ -80,7 +81,8 @@ static inline void register_cpu_control(struct cpu *cpu)
#ifdef CONFIG_KEXEC
#include <linux/kexec.h>
-static ssize_t show_crash_notes(struct sys_device *dev, char *buf)
+static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute *attr,
+ char *buf)
{
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
ssize_t rc;
@@ -119,14 +121,14 @@ static ssize_t print_cpus_##type(struct sysdev_class *class, char *buf) \
{ \
return print_cpus_map(buf, &cpu_##type##_map); \
} \
-struct sysdev_class_attribute attr_##type##_map = \
+static struct sysdev_class_attribute attr_##type##_map = \
_SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL)
print_cpus_func(online);
print_cpus_func(possible);
print_cpus_func(present);
-struct sysdev_class_attribute *cpu_state_attr[] = {
+static struct sysdev_class_attribute *cpu_state_attr[] = {
&attr_online_map,
&attr_possible_map,
&attr_present_map,
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index b0be1d18fee..c9c92b00fd5 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -184,7 +184,7 @@ firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
struct device *dev = to_dev(kobj);
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
struct firmware *fw;
- ssize_t ret_count = count;
+ ssize_t ret_count;
mutex_lock(&fw_lock);
fw = fw_priv->fw;
@@ -192,14 +192,8 @@ firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
ret_count = -ENODEV;
goto out;
}
- if (offset > fw->size) {
- ret_count = 0;
- goto out;
- }
- if (offset + ret_count > fw->size)
- ret_count = fw->size - offset;
-
- memcpy(buffer, fw->data + offset, ret_count);
+ ret_count = memory_read_from_buffer(buffer, count, &offset,
+ fw->data, fw->size);
out:
mutex_unlock(&fw_lock);
return ret_count;
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 937e8258981..855ed1a9f97 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -92,7 +92,8 @@ unregister_memory(struct memory_block *memory, struct mem_section *section)
* uses.
*/
-static ssize_t show_mem_phys_index(struct sys_device *dev, char *buf)
+static ssize_t show_mem_phys_index(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct memory_block *mem =
container_of(dev, struct memory_block, sysdev);
@@ -100,9 +101,25 @@ static ssize_t show_mem_phys_index(struct sys_device *dev, char *buf)
}
/*
+ * Show whether the section of memory is likely to be hot-removable
+ */
+static ssize_t show_mem_removable(struct sys_device *dev, char *buf)
+{
+ unsigned long start_pfn;
+ int ret;
+ struct memory_block *mem =
+ container_of(dev, struct memory_block, sysdev);
+
+ start_pfn = section_nr_to_pfn(mem->phys_index);
+ ret = is_mem_section_removable(start_pfn, PAGES_PER_SECTION);
+ return sprintf(buf, "%d\n", ret);
+}
+
+/*
* online, offline, going offline, etc.
*/
-static ssize_t show_mem_state(struct sys_device *dev, char *buf)
+static ssize_t show_mem_state(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct memory_block *mem =
container_of(dev, struct memory_block, sysdev);
@@ -217,7 +234,8 @@ out:
}
static ssize_t
-store_mem_state(struct sys_device *dev, const char *buf, size_t count)
+store_mem_state(struct sys_device *dev,
+ struct sysdev_attribute *attr, const char *buf, size_t count)
{
struct memory_block *mem;
unsigned int phys_section_nr;
@@ -248,7 +266,8 @@ out:
* s.t. if I offline all of these sections I can then
* remove the physical device?
*/
-static ssize_t show_phys_device(struct sys_device *dev, char *buf)
+static ssize_t show_phys_device(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct memory_block *mem =
container_of(dev, struct memory_block, sysdev);
@@ -258,6 +277,7 @@ static ssize_t show_phys_device(struct sys_device *dev, char *buf)
static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL);
static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state);
static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL);
+static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL);
#define mem_create_simple_file(mem, attr_name) \
sysdev_create_file(&mem->sysdev, &attr_##attr_name)
@@ -346,6 +366,8 @@ static int add_memory_block(unsigned long node_id, struct mem_section *section,
ret = mem_create_simple_file(mem, state);
if (!ret)
ret = mem_create_simple_file(mem, phys_device);
+ if (!ret)
+ ret = mem_create_simple_file(mem, removable);
return ret;
}
@@ -390,6 +412,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
mem_remove_simple_file(mem, phys_index);
mem_remove_simple_file(mem, state);
mem_remove_simple_file(mem, phys_device);
+ mem_remove_simple_file(mem, removable);
unregister_memory(mem, section);
return 0;
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 0f867a08333..5116b78c632 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -36,11 +36,13 @@ static ssize_t node_read_cpumap(struct sys_device *dev, int type, char *buf)
return len;
}
-static inline ssize_t node_read_cpumask(struct sys_device *dev, char *buf)
+static inline ssize_t node_read_cpumask(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
return node_read_cpumap(dev, 0, buf);
}
-static inline ssize_t node_read_cpulist(struct sys_device *dev, char *buf)
+static inline ssize_t node_read_cpulist(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
return node_read_cpumap(dev, 1, buf);
}
@@ -49,7 +51,8 @@ static SYSDEV_ATTR(cpumap, S_IRUGO, node_read_cpumask, NULL);
static SYSDEV_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL);
#define K(x) ((x) << (PAGE_SHIFT - 10))
-static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
+static ssize_t node_read_meminfo(struct sys_device * dev,
+ struct sysdev_attribute *attr, char * buf)
{
int n;
int nid = dev->id;
@@ -112,7 +115,8 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
#undef K
static SYSDEV_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL);
-static ssize_t node_read_numastat(struct sys_device * dev, char * buf)
+static ssize_t node_read_numastat(struct sys_device * dev,
+ struct sysdev_attribute *attr, char * buf)
{
return sprintf(buf,
"numa_hit %lu\n"
@@ -130,7 +134,8 @@ static ssize_t node_read_numastat(struct sys_device * dev, char * buf)
}
static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL);
-static ssize_t node_read_distance(struct sys_device * dev, char * buf)
+static ssize_t node_read_distance(struct sys_device * dev,
+ struct sysdev_attribute *attr, char * buf)
{
int nid = dev->id;
int len = 0;
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
index 9b1b20b59e0..2aa6e8fc4de 100644
--- a/drivers/base/power/trace.c
+++ b/drivers/base/power/trace.c
@@ -194,7 +194,7 @@ static int show_dev_hash(unsigned int value)
struct device * dev = to_device(entry);
unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH);
if (hash == value) {
- printk(" hash matches device %s\n", dev->bus_id);
+ dev_info(dev, "hash matches\n");
match++;
}
entry = entry->prev;
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 358bb0be3c0..40fc14f0354 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -36,7 +36,7 @@ sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer)
struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr);
if (sysdev_attr->show)
- return sysdev_attr->show(sysdev, buffer);
+ return sysdev_attr->show(sysdev, sysdev_attr, buffer);
return -EIO;
}
@@ -49,7 +49,7 @@ sysdev_store(struct kobject * kobj, struct attribute * attr,
struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr);
if (sysdev_attr->store)
- return sysdev_attr->store(sysdev, buffer, count);
+ return sysdev_attr->store(sysdev, sysdev_attr, buffer, count);
return -EIO;
}
@@ -130,8 +130,8 @@ static struct kset *system_kset;
int sysdev_class_register(struct sysdev_class * cls)
{
- pr_debug("Registering sysdev class '%s'\n",
- kobject_name(&cls->kset.kobj));
+ pr_debug("Registering sysdev class '%s'\n", cls->name);
+
INIT_LIST_HEAD(&cls->drivers);
memset(&cls->kset.kobj, 0x00, sizeof(struct kobject));
cls->kset.kobj.parent = &system_kset->kobj;
@@ -241,7 +241,8 @@ int sysdev_register(struct sys_device * sysdev)
if (!cls)
return -EINVAL;
- pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj));
+ pr_debug("Registering sys device of class '%s'\n",
+ kobject_name(&cls->kset.kobj));
/* initialize the kobject to 0, in case it had previously been used */
memset(&sysdev->kobj, 0x00, sizeof(struct kobject));
@@ -257,6 +258,9 @@ int sysdev_register(struct sys_device * sysdev)
if (!error) {
struct sysdev_driver * drv;
+ pr_debug("Registering sys device '%s'\n",
+ kobject_name(&sysdev->kobj));
+
mutex_lock(&sysdev_drivers_lock);
/* Generic notification is implicit, because it's that
* code that should have called us.
@@ -269,6 +273,7 @@ int sysdev_register(struct sys_device * sysdev)
}
mutex_unlock(&sysdev_drivers_lock);
}
+
kobject_uevent(&sysdev->kobj, KOBJ_ADD);
return error;
}
@@ -474,3 +479,52 @@ int __init system_bus_init(void)
EXPORT_SYMBOL_GPL(sysdev_register);
EXPORT_SYMBOL_GPL(sysdev_unregister);
+
+#define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr)
+
+ssize_t sysdev_store_ulong(struct sys_device *sysdev,
+ struct sysdev_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct sysdev_ext_attribute *ea = to_ext_attr(attr);
+ char *end;
+ unsigned long new = simple_strtoul(buf, &end, 0);
+ if (end == buf)
+ return -EINVAL;
+ *(unsigned long *)(ea->var) = new;
+ return end - buf;
+}
+EXPORT_SYMBOL_GPL(sysdev_store_ulong);
+
+ssize_t sysdev_show_ulong(struct sys_device *sysdev,
+ struct sysdev_attribute *attr,
+ char *buf)
+{
+ struct sysdev_ext_attribute *ea = to_ext_attr(attr);
+ return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var));
+}
+EXPORT_SYMBOL_GPL(sysdev_show_ulong);
+
+ssize_t sysdev_store_int(struct sys_device *sysdev,
+ struct sysdev_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct sysdev_ext_attribute *ea = to_ext_attr(attr);
+ char *end;
+ long new = simple_strtol(buf, &end, 0);
+ if (end == buf || new > INT_MAX || new < INT_MIN)
+ return -EINVAL;
+ *(int *)(ea->var) = new;
+ return end - buf;
+}
+EXPORT_SYMBOL_GPL(sysdev_store_int);
+
+ssize_t sysdev_show_int(struct sys_device *sysdev,
+ struct sysdev_attribute *attr,
+ char *buf)
+{
+ struct sysdev_ext_attribute *ea = to_ext_attr(attr);
+ return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var));
+}
+EXPORT_SYMBOL_GPL(sysdev_show_int);
+
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 3f6d9b0a6ab..199cd97e32e 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -34,7 +34,8 @@
static SYSDEV_ATTR(_name, 0444, show_##_name, NULL)
#define define_id_show_func(name) \
-static ssize_t show_##name(struct sys_device *dev, char *buf) \
+static ssize_t show_##name(struct sys_device *dev, \
+ struct sysdev_attribute *attr, char *buf) \
{ \
unsigned int cpu = dev->id; \
return sprintf(buf, "%d\n", topology_##name(cpu)); \
@@ -59,14 +60,17 @@ static ssize_t show_cpumap(int type, cpumask_t *mask, char *buf)
#ifdef arch_provides_topology_pointers
#define define_siblings_show_map(name) \
-static ssize_t show_##name(struct sys_device *dev, char *buf) \
+static ssize_t show_##name(struct sys_device *dev, \
+ struct sysdev_attribute *attr, char *buf) \
{ \
unsigned int cpu = dev->id; \
return show_cpumap(0, &(topology_##name(cpu)), buf); \
}
#define define_siblings_show_list(name) \
-static ssize_t show_##name##_list(struct sys_device *dev, char *buf) \
+static ssize_t show_##name##_list(struct sys_device *dev, \
+ struct sysdev_attribute *attr, \
+ char *buf) \
{ \
unsigned int cpu = dev->id; \
return show_cpumap(1, &(topology_##name(cpu)), buf); \
@@ -74,7 +78,8 @@ static ssize_t show_##name##_list(struct sys_device *dev, char *buf) \
#else
#define define_siblings_show_map(name) \
-static ssize_t show_##name(struct sys_device *dev, char *buf) \
+static ssize_t show_##name(struct sys_device *dev, \
+ struct sysdev_attribute *attr, char *buf) \
{ \
unsigned int cpu = dev->id; \
cpumask_t mask = topology_##name(cpu); \
@@ -82,7 +87,9 @@ static ssize_t show_##name(struct sys_device *dev, char *buf) \
}
#define define_siblings_show_list(name) \
-static ssize_t show_##name##_list(struct sys_device *dev, char *buf) \
+static ssize_t show_##name##_list(struct sys_device *dev, \
+ struct sysdev_attribute *attr, \
+ char *buf) \
{ \
unsigned int cpu = dev->id; \
cpumask_t mask = topology_##name(cpu); \
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index d1de68a3192..181ebb85f0b 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -6,6 +6,7 @@
#include <linux/hdreg.h>
#include <linux/blkdev.h>
+#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/smp_lock.h>
#include "aoe.h"
@@ -36,7 +37,7 @@ struct ErrMsg {
static struct ErrMsg emsgs[NMSG];
static int emsgs_head_idx, emsgs_tail_idx;
-static struct semaphore emsgs_sema;
+static struct completion emsgs_comp;
static spinlock_t emsgs_lock;
static int nblocked_emsgs_readers;
static struct class *aoe_class;
@@ -141,7 +142,7 @@ bail: spin_unlock_irqrestore(&emsgs_lock, flags);
spin_unlock_irqrestore(&emsgs_lock, flags);
if (nblocked_emsgs_readers)
- up(&emsgs_sema);
+ complete(&emsgs_comp);
}
static ssize_t
@@ -221,7 +222,7 @@ aoechr_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off)
spin_unlock_irqrestore(&emsgs_lock, flags);
- n = down_interruptible(&emsgs_sema);
+ n = wait_for_completion_interruptible(&emsgs_comp);
spin_lock_irqsave(&emsgs_lock, flags);
@@ -269,7 +270,7 @@ aoechr_init(void)
printk(KERN_ERR "aoe: can't register char device\n");
return n;
}
- sema_init(&emsgs_sema, 0);
+ init_completion(&emsgs_comp);
spin_lock_init(&emsgs_lock);
aoe_class = class_create(THIS_MODULE, "aoe");
if (IS_ERR(aoe_class)) {
@@ -277,8 +278,9 @@ aoechr_init(void)
return PTR_ERR(aoe_class);
}
for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
- device_create(aoe_class, NULL,
- MKDEV(AOE_MAJOR, chardevs[i].minor), chardevs[i].name);
+ device_create_drvdata(aoe_class, NULL,
+ MKDEV(AOE_MAJOR, chardevs[i].minor),
+ NULL, chardevs[i].name);
return 0;
}
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index 9d92636350e..d731ca42f80 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -686,8 +686,9 @@ static int __init pg_init(void)
for (unit = 0; unit < PG_UNITS; unit++) {
struct pg *dev = &devices[unit];
if (dev->present)
- device_create(pg_class, NULL, MKDEV(major, unit),
- "pg%u", unit);
+ device_create_drvdata(pg_class, NULL,
+ MKDEV(major, unit), NULL,
+ "pg%u", unit);
}
err = 0;
goto out;
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 5c74c3574a5..673b8b2fd33 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -979,10 +979,12 @@ static int __init pt_init(void)
for (unit = 0; unit < PT_UNITS; unit++)
if (pt[unit].present) {
- device_create(pt_class, NULL, MKDEV(major, unit),
- "pt%d", unit);
- device_create(pt_class, NULL, MKDEV(major, unit + 128),
- "pt%dn", unit);
+ device_create_drvdata(pt_class, NULL,
+ MKDEV(major, unit), NULL,
+ "pt%d", unit);
+ device_create_drvdata(pt_class, NULL,
+ MKDEV(major, unit + 128), NULL,
+ "pt%dn", unit);
}
goto out;
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 45bee918c46..158eed4d516 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -303,7 +303,9 @@ static struct kobj_type kobj_pkt_type_wqueue = {
static void pkt_sysfs_dev_new(struct pktcdvd_device *pd)
{
if (class_pktcdvd) {
- pd->dev = device_create(class_pktcdvd, NULL, pd->pkt_dev, "%s", pd->name);
+ pd->dev = device_create_drvdata(class_pktcdvd, NULL,
+ pd->pkt_dev, NULL,
+ "%s", pd->name);
if (IS_ERR(pd->dev))
pd->dev = NULL;
}
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index dd7ea203f94..42251095134 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -196,6 +196,7 @@ static int virtblk_probe(struct virtio_device *vdev)
int err;
u64 cap;
u32 v;
+ u32 blk_size;
if (index_to_minor(index) >= 1 << MINORBITS)
return -ENOSPC;
@@ -290,6 +291,13 @@ static int virtblk_probe(struct virtio_device *vdev)
if (!err)
blk_queue_max_hw_segments(vblk->disk->queue, v);
+ /* Host can optionally specify the block size of the device */
+ err = virtio_config_val(vdev, VIRTIO_BLK_F_BLK_SIZE,
+ offsetof(struct virtio_blk_config, blk_size),
+ &blk_size);
+ if (!err)
+ blk_queue_hardsect_size(vblk->disk->queue, blk_size);
+
add_disk(vblk->disk);
return 0;
@@ -330,7 +338,7 @@ static struct virtio_device_id id_table[] = {
static unsigned int features[] = {
VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX,
- VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO,
+ VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
};
static struct virtio_driver virtio_blk = {
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 650e6b44ce6..d0ac944e169 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -36,6 +36,14 @@ config VT
If unsure, say Y, or else you won't be able to do much with your new
shiny Linux system :-)
+config CONSOLE_TRANSLATIONS
+ depends on VT
+ default y
+ bool "Enable character translations in console" if EMBEDDED
+ ---help---
+ This enables support for font mapping and Unicode translation
+ on virtual consoles.
+
config VT_CONSOLE
bool "Support for console on virtual terminal" if EMBEDDED
depends on VT
@@ -300,16 +308,6 @@ config SPECIALIX
and compile this driver as kernel loadable module which will be
called specialix.
-config SPECIALIX_RTSCTS
- bool "Specialix DTR/RTS pin is RTS"
- depends on SPECIALIX
- help
- The Specialix IO8+ card can only support either RTS or DTR. If you
- say N here, the driver will use the pin as "DTR" when the tty is in
- software handshake mode. If you say Y here or hardware handshake is
- on, it will always be RTS. Read the file
- <file:Documentation/specialix.txt> for more information.
-
config SX
tristate "Specialix SX (and SI) card support"
depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
@@ -588,11 +586,14 @@ config HVC_DRIVER
It will automatically be selected if one of the back-end console drivers
is selected.
+config HVC_IRQ
+ bool
config HVC_CONSOLE
bool "pSeries Hypervisor Virtual Console support"
depends on PPC_PSERIES
select HVC_DRIVER
+ select HVC_IRQ
help
pSeries machines when partitioned support a hypervisor virtual
console. This driver allows each pSeries partition to have a console
@@ -603,6 +604,7 @@ config HVC_ISERIES
depends on PPC_ISERIES
default y
select HVC_DRIVER
+ select HVC_IRQ
help
iSeries machines support a hypervisor virtual console.
@@ -624,13 +626,18 @@ config HVC_XEN
bool "Xen Hypervisor Console support"
depends on XEN
select HVC_DRIVER
+ select HVC_IRQ
default y
help
Xen virtual console device driver
config VIRTIO_CONSOLE
- bool
+ tristate "Virtio console"
+ depends on VIRTIO
select HVC_DRIVER
+ help
+ Virtio console for use with lguest and other hypervisors.
+
config HVCS
tristate "IBM Hypervisor Virtual Console Server support"
@@ -867,13 +874,6 @@ config DS1302
endif # RTC_LIB
-config COBALT_LCD
- bool "Support for Cobalt LCD"
- depends on MIPS_COBALT
- help
- This option enables support for the LCD display and buttons found
- on Cobalt systems through a misc device.
-
config DTLK
tristate "Double Talk PC internal speech card support"
depends on ISA
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 0e0d12a0646..8a161c30e1d 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -7,13 +7,13 @@
#
FONTMAPFILE = cp437.uni
-obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o
+obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o
obj-$(CONFIG_LEGACY_PTYS) += pty.o
obj-$(CONFIG_UNIX98_PTYS) += pty.o
obj-y += misc.o
-obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o \
- consolemap_deftbl.o selection.o keyboard.o
+obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o
+obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o
obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o
obj-$(CONFIG_AUDIT) += tty_audit.o
obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
@@ -48,6 +48,7 @@ obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o
obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o
obj-$(CONFIG_HVC_BEAT) += hvc_beat.o
obj-$(CONFIG_HVC_DRIVER) += hvc_console.o
+obj-$(CONFIG_HVC_IRQ) += hvc_irq.o
obj-$(CONFIG_HVC_XEN) += hvc_xen.o
obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o
obj-$(CONFIG_RAW_DRIVER) += raw.o
@@ -63,7 +64,6 @@ obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o
obj-$(CONFIG_BFIN_OTP) += bfin-otp.o
obj-$(CONFIG_PRINTER) += lp.o
-obj-$(CONFIG_TIPAR) += tipar.o
obj-$(CONFIG_APM_EMULATION) += apm-emulation.o
@@ -88,7 +88,6 @@ obj-$(CONFIG_TOSHIBA) += toshiba.o
obj-$(CONFIG_I8K) += i8k.o
obj-$(CONFIG_DS1620) += ds1620.o
obj-$(CONFIG_HW_RANDOM) += hw_random/
-obj-$(CONFIG_COBALT_LCD) += lcd.o
obj-$(CONFIG_PPDEV) += ppdev.o
obj-$(CONFIG_NWBUTTON) += nwbutton.o
obj-$(CONFIG_NWFLASH) += nwflash.o
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 37457e5a4f2..3530ff417a5 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -1248,7 +1248,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file,
/*
* rs_break() --- routine which turns the break handling on or off
*/
-static void rs_break(struct tty_struct *tty, int break_state)
+static int rs_break(struct tty_struct *tty, int break_state)
{
struct async_struct * info = (struct async_struct *)tty->driver_data;
unsigned long flags;
@@ -1263,6 +1263,7 @@ static void rs_break(struct tty_struct *tty, int break_state)
custom.adkcon = AC_UARTBRK;
mb();
local_irq_restore(flags);
+ return 0;
}
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index e991dc85f2f..fe6d774fe2e 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -3700,14 +3700,15 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
/*
* cy_break() --- routine which turns the break handling on or off
*/
-static void cy_break(struct tty_struct *tty, int break_state)
+static int cy_break(struct tty_struct *tty, int break_state)
{
struct cyclades_port *info = tty->driver_data;
struct cyclades_card *card;
unsigned long flags;
+ int retval = 0;
if (serial_paranoia_check(info, tty->name, "cy_break"))
- return;
+ return -EINVAL;
card = info->card;
@@ -3736,8 +3737,6 @@ static void cy_break(struct tty_struct *tty, int break_state)
}
}
} else {
- int retval;
-
if (break_state == -1) {
retval = cyz_issue_cmd(card,
info->line - card->first_line,
@@ -3758,6 +3757,7 @@ static void cy_break(struct tty_struct *tty, int break_state)
}
}
spin_unlock_irqrestore(&card->card_lock, flags);
+ return retval;
} /* cy_break */
static int get_mon_info(struct cyclades_port *info,
diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c
index fada6ddefba..c5e67a62395 100644
--- a/drivers/char/ds1302.c
+++ b/drivers/char/ds1302.c
@@ -20,10 +20,11 @@
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/bcd.h>
+#include <linux/smp_lock.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
-#include <asm/uaccess.h>
#include <asm/system.h>
-#include <asm/io.h>
#include <asm/rtc.h>
#if defined(CONFIG_M32R)
#include <asm/m32r.h>
@@ -153,9 +154,7 @@ static unsigned char days_in_mo[] =
/* ioctl that supports RTC_RD_TIME and RTC_SET_TIME (read and set time/date). */
-static int
-rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned long flags;
@@ -165,7 +164,9 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
struct rtc_time rtc_tm;
memset(&rtc_tm, 0, sizeof (struct rtc_time));
+ lock_kernel();
get_rtc_time(&rtc_tm);
+ unlock_kernel();
if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)))
return -EFAULT;
return 0;
@@ -217,6 +218,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
BIN_TO_BCD(mon);
BIN_TO_BCD(yrs);
+ lock_kernel();
local_irq_save(flags);
CMOS_WRITE(yrs, RTC_YEAR);
CMOS_WRITE(mon, RTC_MONTH);
@@ -225,6 +227,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
CMOS_WRITE(min, RTC_MINUTES);
CMOS_WRITE(sec, RTC_SECONDS);
local_irq_restore(flags);
+ unlock_kernel();
/* Notice that at this point, the RTC is updated but
* the kernel is still running with the old time.
@@ -244,8 +247,10 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if(copy_from_user(&tcs_val, (int*)arg, sizeof(int)))
return -EFAULT;
+ lock_kernel();
tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F);
ds1302_writereg(RTC_TRICKLECHARGER, tcs_val);
+ unlock_kernel();
return 0;
}
default:
@@ -282,7 +287,7 @@ get_rtc_status(char *buf)
static const struct file_operations rtc_fops = {
.owner = THIS_MODULE,
- .ioctl = rtc_ioctl,
+ .unlocked_ioctl = rtc_ioctl,
};
/* Probe for the chip by writing something to its RAM and try reading it back. */
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index b9a30c30e2b..19b88504e96 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -36,10 +36,10 @@
#include <linux/smp_lock.h>
#include <linux/firmware.h>
#include <linux/platform_device.h>
+#include <linux/uaccess.h> /* For put_user and get_user */
#include <asm/atarihw.h>
#include <asm/traps.h>
-#include <asm/uaccess.h> /* For put_user and get_user */
#include <asm/dsp56k.h>
@@ -303,8 +303,8 @@ static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t co
}
}
-static int dsp56k_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long dsp56k_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
int dev = iminor(inode) & 0x0f;
void __user *argp = (void __user *)arg;
@@ -331,8 +331,9 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
if (len > DSP56K_MAX_BINARY_LENGTH) {
return -EINVAL;
}
-
+ lock_kernel();
r = dsp56k_upload(bin, len);
+ unlock_kernel();
if (r < 0) {
return r;
}
@@ -342,12 +343,16 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
case DSP56K_SET_TX_WSIZE:
if (arg > 4 || arg < 1)
return -EINVAL;
+ lock_kernel();
dsp56k.tx_wsize = (int) arg;
+ unlock_kernel();
break;
case DSP56K_SET_RX_WSIZE:
if (arg > 4 || arg < 1)
return -EINVAL;
+ lock_kernel();
dsp56k.rx_wsize = (int) arg;
+ unlock_kernel();
break;
case DSP56K_HOST_FLAGS:
{
@@ -359,6 +364,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
if(get_user(out, &hf->out) < 0)
return -EFAULT;
+ lock_kernel();
if ((dir & 0x1) && (out & 0x1))
dsp56k_host_interface.icr |= DSP56K_ICR_HF0;
else if (dir & 0x1)
@@ -373,14 +379,16 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2;
if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4;
if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8;
-
+ unlock_kernel();
return put_user(status, &hf->status);
}
case DSP56K_HOST_CMD:
if (arg > 31 || arg < 0)
return -EINVAL;
+ lock_kernel();
dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) |
DSP56K_CVR_HC);
+ unlock_kernel();
break;
default:
return -EINVAL;
@@ -472,7 +480,7 @@ static const struct file_operations dsp56k_fops = {
.owner = THIS_MODULE,
.read = dsp56k_read,
.write = dsp56k_write,
- .ioctl = dsp56k_ioctl,
+ .unlocked_ioctl = dsp56k_ioctl,
.open = dsp56k_open,
.release = dsp56k_release,
};
@@ -500,7 +508,8 @@ static int __init dsp56k_init_driver(void)
err = PTR_ERR(dsp56k_class);
goto out_chrdev;
}
- device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), "dsp56k");
+ device_create_drvdata(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0),
+ NULL, "dsp56k");
printk(banner);
goto out;
diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c
index d57ca3e4e53..67fbd7aab5d 100644
--- a/drivers/char/efirtc.c
+++ b/drivers/char/efirtc.c
@@ -37,8 +37,9 @@
#include <linux/rtc.h>
#include <linux/proc_fs.h>
#include <linux/efi.h>
+#include <linux/smp_lock.h>
+#include <linux/uaccess.h>
-#include <asm/uaccess.h>
#include <asm/system.h>
#define EFI_RTC_VERSION "0.4"
@@ -51,8 +52,8 @@
static DEFINE_SPINLOCK(efi_rtc_lock);
-static int efi_rtc_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
+static long efi_rtc_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg);
#define is_leap(year) \
((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
@@ -146,9 +147,8 @@ convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime)
}
}
-static int
-efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+static long efi_rtc_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
efi_status_t status;
@@ -175,13 +175,13 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return -EINVAL;
case RTC_RD_TIME:
-
+ lock_kernel();
spin_lock_irqsave(&efi_rtc_lock, flags);
status = efi.get_time(&eft, &cap);
spin_unlock_irqrestore(&efi_rtc_lock,flags);
-
+ unlock_kernel();
if (status != EFI_SUCCESS) {
/* should never happen */
printk(KERN_ERR "efitime: can't read time\n");
@@ -203,11 +203,13 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
convert_to_efi_time(&wtime, &eft);
+ lock_kernel();
spin_lock_irqsave(&efi_rtc_lock, flags);
status = efi.set_time(&eft);
spin_unlock_irqrestore(&efi_rtc_lock,flags);
+ unlock_kernel();
return status == EFI_SUCCESS ? 0 : -EINVAL;
@@ -223,6 +225,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
convert_to_efi_time(&wtime, &eft);
+ lock_kernel();
spin_lock_irqsave(&efi_rtc_lock, flags);
/*
* XXX Fixme:
@@ -233,16 +236,19 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
status = efi.set_wakeup_time((efi_bool_t)enabled, &eft);
spin_unlock_irqrestore(&efi_rtc_lock,flags);
+ unlock_kernel();
return status == EFI_SUCCESS ? 0 : -EINVAL;
case RTC_WKALM_RD:
+ lock_kernel();
spin_lock_irqsave(&efi_rtc_lock, flags);
status = efi.get_wakeup_time((efi_bool_t *)&enabled, (efi_bool_t *)&pending, &eft);
spin_unlock_irqrestore(&efi_rtc_lock,flags);
+ unlock_kernel();
if (status != EFI_SUCCESS) return -EINVAL;
@@ -256,7 +262,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return copy_to_user(&ewp->time, &wtime,
sizeof(struct rtc_time)) ? -EFAULT : 0;
}
- return -EINVAL;
+ return -ENOTTY;
}
/*
@@ -265,8 +271,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
* up things on a close.
*/
-static int
-efi_rtc_open(struct inode *inode, struct file *file)
+static int efi_rtc_open(struct inode *inode, struct file *file)
{
/*
* nothing special to do here
@@ -277,8 +282,7 @@ efi_rtc_open(struct inode *inode, struct file *file)
return 0;
}
-static int
-efi_rtc_close(struct inode *inode, struct file *file)
+static int efi_rtc_close(struct inode *inode, struct file *file)
{
return 0;
}
@@ -289,13 +293,12 @@ efi_rtc_close(struct inode *inode, struct file *file)
static const struct file_operations efi_rtc_fops = {
.owner = THIS_MODULE,
- .ioctl = efi_rtc_ioctl,
+ .unlocked_ioctl = efi_rtc_ioctl,
.open = efi_rtc_open,
.release = efi_rtc_close,
};
-static struct miscdevice efi_rtc_dev=
-{
+static struct miscdevice efi_rtc_dev= {
EFI_RTC_MINOR,
"efirtc",
&efi_rtc_fops
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index ac9995f6578..456e4ede049 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -184,9 +184,8 @@ static void pc_stop(struct tty_struct *);
static void pc_start(struct tty_struct *);
static void pc_throttle(struct tty_struct *tty);
static void pc_unthrottle(struct tty_struct *tty);
-static void digi_send_break(struct channel *ch, int msec);
+static int pc_send_break(struct tty_struct *tty, int msec);
static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
-static void epca_setup(char *, int *);
static int pc_write(struct tty_struct *, const unsigned char *, int);
static int pc_init(void);
@@ -1040,6 +1039,7 @@ static const struct tty_operations pc_ops = {
.throttle = pc_throttle,
.unthrottle = pc_unthrottle,
.hangup = pc_hangup,
+ .break_ctl = pc_send_break
};
static int info_open(struct tty_struct *tty, struct file *filp)
@@ -1132,7 +1132,7 @@ static int __init pc_init(void)
pc_driver->init_termios.c_lflag = 0;
pc_driver->init_termios.c_ispeed = 9600;
pc_driver->init_termios.c_ospeed = 9600;
- pc_driver->flags = TTY_DRIVER_REAL_RAW;
+ pc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK;
tty_set_operations(pc_driver, &pc_ops);
pc_info->owner = THIS_MODULE;
@@ -2177,7 +2177,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
digiflow_t dflow;
- int retval;
unsigned long flags;
unsigned int mflag, mstat;
unsigned char startc, stopc;
@@ -2189,37 +2188,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file,
bc = ch->brdchan;
else
return -EINVAL;
- /*
- * For POSIX compliance we need to add more ioctls. See tty_ioctl.c in
- * /usr/src/linux/drivers/char for a good example. In particular think
- * about adding TCSETAF, TCSETAW, TCSETA, TCSETSF, TCSETSW, TCSETS.
- */
switch (cmd) {
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- /* Setup an event to indicate when the transmit
- buffer empties */
- spin_lock_irqsave(&epca_lock, flags);
- setup_empty_event(tty, ch);
- spin_unlock_irqrestore(&epca_lock, flags);
- tty_wait_until_sent(tty, 0);
- if (!arg)
- digi_send_break(ch, HZ / 4); /* 1/4 second */
- return 0;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- /* Setup an event to indicate when the transmit buffer
- empties */
- spin_lock_irqsave(&epca_lock, flags);
- setup_empty_event(tty, ch);
- spin_unlock_irqrestore(&epca_lock, flags);
- tty_wait_until_sent(tty, 0);
- digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4);
- return 0;
case TIOCMODG:
mflag = pc_tiocmget(tty, file);
if (put_user(mflag, (unsigned long __user *)argp))
@@ -2505,10 +2474,14 @@ static void pc_unthrottle(struct tty_struct *tty)
}
}
-static void digi_send_break(struct channel *ch, int msec)
+static int pc_send_break(struct tty_struct *tty, int msec)
{
+ struct channel *ch = (struct channel *) tty->driver_data;
unsigned long flags;
+ if (msec == -1)
+ return -EOPNOTSUPP;
+
spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
/*
@@ -2521,6 +2494,7 @@ static void digi_send_break(struct channel *ch, int msec)
fepcmd(ch, SENDBREAK, msec, 0, 10, 0);
memoff(ch);
spin_unlock_irqrestore(&epca_lock, flags);
+ return 0;
}
/* Caller MUST hold the lock */
@@ -2538,7 +2512,8 @@ static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
memoff(ch);
}
-static void epca_setup(char *str, int *ints)
+#ifndef MODULE
+static void __init epca_setup(char *str, int *ints)
{
struct board_info board;
int index, loop, last;
@@ -2792,6 +2767,17 @@ static void epca_setup(char *str, int *ints)
num_cards++;
}
+static int __init epca_real_setup(char *str)
+{
+ int ints[11];
+
+ epca_setup(get_options(str, 11, ints), ints);
+ return 1;
+}
+
+__setup("digiepca", epca_real_setup);
+#endif
+
enum epic_board_types {
brd_xr = 0,
brd_xem,
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 2eaf09f93e3..7f077c0097f 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -1725,13 +1725,13 @@ static int esp_tiocmset(struct tty_struct *tty, struct file *file,
/*
* rs_break() --- routine which turns the break handling on or off
*/
-static void esp_break(struct tty_struct *tty, int break_state)
+static int esp_break(struct tty_struct *tty, int break_state)
{
struct esp_struct *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "esp_break"))
- return;
+ return -EINVAL;
if (break_state == -1) {
spin_lock_irqsave(&info->lock, flags);
@@ -1747,6 +1747,7 @@ static void esp_break(struct tty_struct *tty, int break_state)
serial_out(info, UART_ESI_CMD2, 0x00);
spin_unlock_irqrestore(&info->lock, flags);
}
+ return 0;
}
static int rs_ioctl(struct tty_struct *tty, struct file *file,
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index fb0a85a1eb3..b3f5dbc6d88 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -623,6 +623,7 @@ static inline int hpet_tpcheck(struct hpet_task *tp)
return -ENXIO;
}
+#if 0
int hpet_unregister(struct hpet_task *tp)
{
struct hpet_dev *devp;
@@ -652,6 +653,7 @@ int hpet_unregister(struct hpet_task *tp)
return 0;
}
+#endif /* 0 */
static ctl_table hpet_table[] = {
{
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 2f9759d625c..02aac104842 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -27,7 +27,6 @@
#include <linux/init.h>
#include <linux/kbd_kern.h>
#include <linux/kernel.h>
-#include <linux/kref.h>
#include <linux/kthread.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -75,23 +74,6 @@ static int hvc_init(void);
static int sysrq_pressed;
#endif
-struct hvc_struct {
- spinlock_t lock;
- int index;
- struct tty_struct *tty;
- unsigned int count;
- int do_wakeup;
- char *outbuf;
- int outbuf_size;
- int n_outbuf;
- uint32_t vtermno;
- struct hv_ops *ops;
- int irq_requested;
- int irq;
- struct list_head next;
- struct kref kref; /* ref count & hvc_struct lifetime */
-};
-
/* dynamic list of hvc_struct instances */
static LIST_HEAD(hvc_structs);
@@ -298,27 +280,15 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops)
return 0;
}
+EXPORT_SYMBOL_GPL(hvc_instantiate);
/* Wake the sleeping khvcd */
-static void hvc_kick(void)
+void hvc_kick(void)
{
hvc_kicked = 1;
wake_up_process(hvc_task);
}
-
-static int hvc_poll(struct hvc_struct *hp);
-
-/*
- * NOTE: This API isn't used if the console adapter doesn't support interrupts.
- * In this case the console is poll driven.
- */
-static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance)
-{
- /* if hvc_poll request a repoll, then kick the hvcd thread */
- if (hvc_poll(dev_instance))
- hvc_kick();
- return IRQ_HANDLED;
-}
+EXPORT_SYMBOL_GPL(hvc_kick);
static void hvc_unthrottle(struct tty_struct *tty)
{
@@ -333,7 +303,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
{
struct hvc_struct *hp;
unsigned long flags;
- int irq = 0;
int rc = 0;
/* Auto increments kref reference if found. */
@@ -352,18 +321,15 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */
hp->tty = tty;
- /* Save for request_irq outside of spin_lock. */
- irq = hp->irq;
- if (irq)
- hp->irq_requested = 1;
+
+ if (hp->ops->notifier_add)
+ rc = hp->ops->notifier_add(hp, hp->data);
spin_unlock_irqrestore(&hp->lock, flags);
- /* check error, fallback to non-irq */
- if (irq)
- rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, "hvc_console", hp);
+
/*
- * If the request_irq() fails and we return an error. The tty layer
+ * If the notifier fails we return an error. The tty layer
* will call hvc_close() after a failed open but we don't want to clean
* up there so we'll clean up here and clear out the previously set
* tty fields and return the kref reference.
@@ -371,7 +337,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
if (rc) {
spin_lock_irqsave(&hp->lock, flags);
hp->tty = NULL;
- hp->irq_requested = 0;
spin_unlock_irqrestore(&hp->lock, flags);
tty->driver_data = NULL;
kref_put(&hp->kref, destroy_hvc_struct);
@@ -386,7 +351,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
static void hvc_close(struct tty_struct *tty, struct file * filp)
{
struct hvc_struct *hp;
- int irq = 0;
unsigned long flags;
if (tty_hung_up_p(filp))
@@ -404,9 +368,8 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
spin_lock_irqsave(&hp->lock, flags);
if (--hp->count == 0) {
- if (hp->irq_requested)
- irq = hp->irq;
- hp->irq_requested = 0;
+ if (hp->ops->notifier_del)
+ hp->ops->notifier_del(hp, hp->data);
/* We are done with the tty pointer now. */
hp->tty = NULL;
@@ -418,10 +381,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
* waking periodically to check chars_in_buffer().
*/
tty_wait_until_sent(tty, HVC_CLOSE_WAIT);
-
- if (irq)
- free_irq(irq, hp);
-
} else {
if (hp->count < 0)
printk(KERN_ERR "hvc_close %X: oops, count is %d\n",
@@ -436,7 +395,6 @@ static void hvc_hangup(struct tty_struct *tty)
{
struct hvc_struct *hp = tty->driver_data;
unsigned long flags;
- int irq = 0;
int temp_open_count;
if (!hp)
@@ -458,13 +416,12 @@ static void hvc_hangup(struct tty_struct *tty)
hp->count = 0;
hp->n_outbuf = 0;
hp->tty = NULL;
- if (hp->irq_requested)
- /* Saved for use outside of spin_lock. */
- irq = hp->irq;
- hp->irq_requested = 0;
+
+ if (hp->ops->notifier_del)
+ hp->ops->notifier_del(hp, hp->data);
+
spin_unlock_irqrestore(&hp->lock, flags);
- if (irq)
- free_irq(irq, hp);
+
while(temp_open_count) {
--temp_open_count;
kref_put(&hp->kref, destroy_hvc_struct);
@@ -575,7 +532,7 @@ static u32 timeout = MIN_TIMEOUT;
#define HVC_POLL_READ 0x00000001
#define HVC_POLL_WRITE 0x00000002
-static int hvc_poll(struct hvc_struct *hp)
+int hvc_poll(struct hvc_struct *hp)
{
struct tty_struct *tty;
int i, n, poll_mask = 0;
@@ -602,10 +559,10 @@ static int hvc_poll(struct hvc_struct *hp)
if (test_bit(TTY_THROTTLED, &tty->flags))
goto throttled;
- /* If we aren't interrupt driven and aren't throttled, we always
+ /* If we aren't notifier driven and aren't throttled, we always
* request a reschedule
*/
- if (hp->irq == 0)
+ if (!hp->irq_requested)
poll_mask |= HVC_POLL_READ;
/* Read data if any */
@@ -674,6 +631,7 @@ static int hvc_poll(struct hvc_struct *hp)
return poll_mask;
}
+EXPORT_SYMBOL_GPL(hvc_poll);
/*
* This kthread is either polling or interrupt driven. This is determined by
@@ -733,7 +691,7 @@ static const struct tty_operations hvc_ops = {
.chars_in_buffer = hvc_chars_in_buffer,
};
-struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
+struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data,
struct hv_ops *ops, int outbuf_size)
{
struct hvc_struct *hp;
@@ -754,7 +712,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
memset(hp, 0x00, sizeof(*hp));
hp->vtermno = vtermno;
- hp->irq = irq;
+ hp->data = data;
hp->ops = ops;
hp->outbuf_size = outbuf_size;
hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))];
@@ -784,6 +742,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
return hp;
}
+EXPORT_SYMBOL_GPL(hvc_alloc);
int __devexit hvc_remove(struct hvc_struct *hp)
{
diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h
index 42ffb17e15d..d9ce1091562 100644
--- a/drivers/char/hvc_console.h
+++ b/drivers/char/hvc_console.h
@@ -26,6 +26,7 @@
#ifndef HVC_CONSOLE_H
#define HVC_CONSOLE_H
+#include <linux/kref.h>
/*
* This is the max number of console adapters that can/will be found as
@@ -42,24 +43,50 @@
*/
#define HVC_ALLOC_TTY_ADAPTERS 8
+struct hvc_struct {
+ spinlock_t lock;
+ int index;
+ struct tty_struct *tty;
+ unsigned int count;
+ int do_wakeup;
+ char *outbuf;
+ int outbuf_size;
+ int n_outbuf;
+ uint32_t vtermno;
+ struct hv_ops *ops;
+ int irq_requested;
+ int data;
+ struct list_head next;
+ struct kref kref; /* ref count & hvc_struct lifetime */
+};
/* implemented by a low level driver */
struct hv_ops {
int (*get_chars)(uint32_t vtermno, char *buf, int count);
int (*put_chars)(uint32_t vtermno, const char *buf, int count);
-};
-struct hvc_struct;
+ /* Callbacks for notification. Called in open and close */
+ int (*notifier_add)(struct hvc_struct *hp, int irq);
+ void (*notifier_del)(struct hvc_struct *hp, int irq);
+};
/* Register a vterm and a slot index for use as a console (console_init) */
extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops);
/* register a vterm for hvc tty operation (module_init or hotplug add) */
-extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq,
+extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int data,
struct hv_ops *ops, int outbuf_size);
-/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */
+/* remove a vterm from hvc tty operation (module_exit or hotplug remove) */
extern int __devexit hvc_remove(struct hvc_struct *hp);
+/* data available */
+int hvc_poll(struct hvc_struct *hp);
+void hvc_kick(void);
+
+/* default notifier for irq based notification */
+extern int notifier_add_irq(struct hvc_struct *hp, int data);
+extern void notifier_del_irq(struct hvc_struct *hp, int data);
+
#if defined(CONFIG_XMON) && defined(CONFIG_SMP)
#include <asm/xmon.h>
diff --git a/drivers/char/hvc_irq.c b/drivers/char/hvc_irq.c
new file mode 100644
index 00000000000..73a59cdb894
--- /dev/null
+++ b/drivers/char/hvc_irq.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright IBM Corp. 2001,2008
+ *
+ * This file contains the IRQ specific code for hvc_console
+ *
+ */
+
+#include <linux/interrupt.h>
+
+#include "hvc_console.h"
+
+static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance)
+{
+ /* if hvc_poll request a repoll, then kick the hvcd thread */
+ if (hvc_poll(dev_instance))
+ hvc_kick();
+ return IRQ_HANDLED;
+}
+
+/*
+ * For IRQ based systems these callbacks can be used
+ */
+int notifier_add_irq(struct hvc_struct *hp, int irq)
+{
+ int rc;
+
+ if (!irq) {
+ hp->irq_requested = 0;
+ return 0;
+ }
+ rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED,
+ "hvc_console", hp);
+ if (!rc)
+ hp->irq_requested = 1;
+ return rc;
+}
+
+void notifier_del_irq(struct hvc_struct *hp, int irq)
+{
+ if (!irq)
+ return;
+ free_irq(irq, hp);
+ hp->irq_requested = 0;
+}
diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c
index a08f8f981c1..b71c610fe5a 100644
--- a/drivers/char/hvc_iseries.c
+++ b/drivers/char/hvc_iseries.c
@@ -200,6 +200,8 @@ done:
static struct hv_ops hvc_get_put_ops = {
.get_chars = get_chars,
.put_chars = put_chars,
+ .notifier_add = notifier_add_irq,
+ .notifier_del = notifier_del_irq,
};
static int __devinit hvc_vio_probe(struct vio_dev *vdev,
diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c
index 79711aa4b41..93f3840c168 100644
--- a/drivers/char/hvc_vio.c
+++ b/drivers/char/hvc_vio.c
@@ -80,6 +80,8 @@ static int filtered_get_chars(uint32_t vtermno, char *buf, int count)
static struct hv_ops hvc_get_put_ops = {
.get_chars = filtered_get_chars,
.put_chars = hvc_put_chars,
+ .notifier_add = notifier_add_irq,
+ .notifier_del = notifier_del_irq,
};
static int __devinit hvc_vio_probe(struct vio_dev *vdev,
diff --git a/drivers/char/hvc_xen.c b/drivers/char/hvc_xen.c
index db2ae421627..6b70aa66a58 100644
--- a/drivers/char/hvc_xen.c
+++ b/drivers/char/hvc_xen.c
@@ -100,6 +100,8 @@ static int read_console(uint32_t vtermno, char *buf, int len)
static struct hv_ops hvc_ops = {
.get_chars = read_console,
.put_chars = write_console,
+ .notifier_add = notifier_add_irq,
+ .notifier_del = notifier_del_irq,
};
static int __init xen_init(void)
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 5dc74404058..689f9dcd3b8 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -203,7 +203,7 @@ static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *);
static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *);
-static int ip2_ipl_ioctl(struct inode *, struct file *, UINT, ULONG);
+static long ip2_ipl_ioctl(struct file *, UINT, ULONG);
static int ip2_ipl_open(struct inode *, struct file *);
static int DumpTraceBuffer(char __user *, int);
@@ -236,7 +236,7 @@ static const struct file_operations ip2_ipl = {
.owner = THIS_MODULE,
.read = ip2_ipl_read,
.write = ip2_ipl_write,
- .ioctl = ip2_ipl_ioctl,
+ .unlocked_ioctl = ip2_ipl_ioctl,
.open = ip2_ipl_open,
};
@@ -718,12 +718,12 @@ ip2_loadmain(int *iop, int *irqp)
}
if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
- device_create(ip2_class, NULL,
- MKDEV(IP2_IPL_MAJOR, 4 * i),
- "ipl%d", i);
- device_create(ip2_class, NULL,
- MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
- "stat%d", i);
+ device_create_drvdata(ip2_class, NULL,
+ MKDEV(IP2_IPL_MAJOR, 4 * i),
+ NULL, "ipl%d", i);
+ device_create_drvdata(ip2_class, NULL,
+ MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
+ NULL, "stat%d", i);
for ( box = 0; box < ABS_MAX_BOXES; ++box )
{
@@ -2845,10 +2845,10 @@ ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t
/* */
/* */
/******************************************************************************/
-static int
-ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg )
+static long
+ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
{
- unsigned int iplminor = iminor(pInode);
+ unsigned int iplminor = iminor(pFile->f_path.dentry->d_inode);
int rc = 0;
void __user *argp = (void __user *)arg;
ULONG __user *pIndex = argp;
@@ -2859,6 +2859,8 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg )
printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg );
#endif
+ lock_kernel();
+
switch ( iplminor ) {
case 0: // IPL device
rc = -EINVAL;
@@ -2919,6 +2921,7 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg )
rc = -ENODEV;
break;
}
+ unlock_kernel();
return rc;
}
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index c11a4048345..64e1c169e82 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -871,7 +871,7 @@ static void ipmi_new_smi(int if_num, struct device *device)
entry->dev = dev;
mutex_lock(&reg_list_mutex);
- device_create(ipmi_class, device, dev, "ipmi%d", if_num);
+ device_create_drvdata(ipmi_class, device, dev, NULL, "ipmi%d", if_num);
list_add(&entry->link, &reg_list);
mutex_unlock(&reg_list_mutex);
}
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index d4281df10c2..8f7cc190b62 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -1181,14 +1181,17 @@ static int isicom_chars_in_buffer(struct tty_struct *tty)
}
/* ioctl et all */
-static inline void isicom_send_break(struct isi_port *port,
- unsigned long length)
+static int isicom_send_break(struct tty_struct *tty, int length)
{
+ struct isi_port *port = tty->driver_data;
struct isi_board *card = port->card;
unsigned long base = card->base;
+ if (length == -1)
+ return -EOPNOTSUPP;
+
if (!lock_card(card))
- return;
+ return -EINVAL;
outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
outw((length & 0xff) << 8 | 0x00, base);
@@ -1196,6 +1199,7 @@ static inline void isicom_send_break(struct isi_port *port,
InterruptTheCard(base);
unlock_card(card);
+ return 0;
}
static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
@@ -1305,28 +1309,11 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
{
struct isi_port *port = tty->driver_data;
void __user *argp = (void __user *)arg;
- int retval;
if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
return -ENODEV;
switch (cmd) {
- case TCSBRK:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- if (!arg)
- isicom_send_break(port, HZ/4);
- return 0;
-
- case TCSBRKP:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
- return 0;
case TIOCGSERIAL:
return isicom_get_serial_info(port, argp);
@@ -1459,6 +1446,7 @@ static const struct tty_operations isicom_ops = {
.flush_buffer = isicom_flush_buffer,
.tiocmget = isicom_tiocmget,
.tiocmset = isicom_tiocmset,
+ .break_ctl = isicom_send_break,
};
static int __devinit reset_card(struct pci_dev *pdev,
@@ -1832,7 +1820,7 @@ static int __init isicom_init(void)
isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
CLOCAL;
isicom_normal->flags = TTY_DRIVER_REAL_RAW |
- TTY_DRIVER_DYNAMIC_DEV;
+ TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK;
tty_set_operations(isicom_normal, &isicom_ops);
retval = tty_register_driver(isicom_normal);
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 7930fba4baf..843a2afaf20 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -609,7 +609,7 @@ static void stli_unthrottle(struct tty_struct *tty);
static void stli_stop(struct tty_struct *tty);
static void stli_start(struct tty_struct *tty);
static void stli_flushbuffer(struct tty_struct *tty);
-static void stli_breakctl(struct tty_struct *tty, int state);
+static int stli_breakctl(struct tty_struct *tty, int state);
static void stli_waituntilsent(struct tty_struct *tty, int timeout);
static void stli_sendxchar(struct tty_struct *tty, char ch);
static void stli_hangup(struct tty_struct *tty);
@@ -925,8 +925,7 @@ static void stli_close(struct tty_struct *tty, struct file *filp)
clear_bit(ST_TXBUSY, &portp->state);
clear_bit(ST_RXSTOP, &portp->state);
set_bit(TTY_IO_ERROR, &tty->flags);
- if (tty->ldisc.ops->flush_buffer)
- (tty->ldisc.ops->flush_buffer)(tty);
+ tty_ldisc_flush(tty);
set_bit(ST_DOFLUSHRX, &portp->state);
stli_flushbuffer(tty);
@@ -1909,7 +1908,7 @@ static void stli_flushbuffer(struct tty_struct *tty)
/*****************************************************************************/
-static void stli_breakctl(struct tty_struct *tty, int state)
+static int stli_breakctl(struct tty_struct *tty, int state)
{
struct stlibrd *brdp;
struct stliport *portp;
@@ -1917,15 +1916,16 @@ static void stli_breakctl(struct tty_struct *tty, int state)
portp = tty->driver_data;
if (portp == NULL)
- return;
+ return -EINVAL;
if (portp->brdnr >= stli_nrbrds)
- return;
+ return -EINVAL;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
- return;
+ return -EINVAL;
arg = (state == -1) ? BREAKON : BREAKOFF;
stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0);
+ return 0;
}
/*****************************************************************************/
@@ -4599,8 +4599,9 @@ static int __init istallion_module_init(void)
istallion_class = class_create(THIS_MODULE, "staliomem");
for (i = 0; i < 4; i++)
- device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
- "staliomem%d", i);
+ device_create_drvdata(istallion_class, NULL,
+ MKDEV(STL_SIOMEMMAJOR, i),
+ NULL, "staliomem%d", i);
return 0;
err_deinit:
diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c
deleted file mode 100644
index 1c29b20e4f4..00000000000
--- a/drivers/char/lcd.c
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * LCD, LED and Button interface for Cobalt
- *
- * 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.
- *
- * Copyright (C) 1996, 1997 by Andrew Bose
- *
- * Linux kernel version history:
- * March 2001: Ported from 2.0.34 by Liam Davies
- *
- */
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/mc146818rtc.h>
-#include <linux/netdevice.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include "lcd.h"
-
-static int lcd_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
-
-static unsigned int lcd_present = 1;
-
-/* used in arch/mips/cobalt/reset.c */
-int led_state = 0;
-
-#if defined(CONFIG_TULIP) && 0
-
-#define MAX_INTERFACES 8
-static linkcheck_func_t linkcheck_callbacks[MAX_INTERFACES];
-static void *linkcheck_cookies[MAX_INTERFACES];
-
-int lcd_register_linkcheck_func(int iface_num, void *func, void *cookie)
-{
- if (iface_num < 0 ||
- iface_num >= MAX_INTERFACES ||
- linkcheck_callbacks[iface_num] != NULL)
- return -1;
- linkcheck_callbacks[iface_num] = (linkcheck_func_t) func;
- linkcheck_cookies[iface_num] = cookie;
- return 0;
-}
-#endif
-
-static int lcd_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct lcd_display button_display;
- unsigned long address, a;
-
- switch (cmd) {
- case LCD_On:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x0F);
- break;
-
- case LCD_Off:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x08);
- break;
-
- case LCD_Reset:
- udelay(150);
- LCDWriteInst(0x3F);
- udelay(150);
- LCDWriteInst(0x3F);
- udelay(150);
- LCDWriteInst(0x3F);
- udelay(150);
- LCDWriteInst(0x3F);
- udelay(150);
- LCDWriteInst(0x01);
- udelay(150);
- LCDWriteInst(0x06);
- break;
-
- case LCD_Clear:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x01);
- break;
-
- case LCD_Cursor_Left:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x10);
- break;
-
- case LCD_Cursor_Right:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x14);
- break;
-
- case LCD_Cursor_Off:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x0C);
- break;
-
- case LCD_Cursor_On:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x0F);
- break;
-
- case LCD_Blink_Off:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x0E);
- break;
-
- case LCD_Get_Cursor_Pos:{
- struct lcd_display display;
-
- udelay(150);
- BusyCheck();
- display.cursor_address = (LCDReadInst);
- display.cursor_address =
- (display.cursor_address & 0x07F);
- if (copy_to_user
- ((struct lcd_display *) arg, &display,
- sizeof(struct lcd_display)))
- return -EFAULT;
-
- break;
- }
-
-
- case LCD_Set_Cursor_Pos:{
- struct lcd_display display;
-
- if (copy_from_user
- (&display, (struct lcd_display *) arg,
- sizeof(struct lcd_display)))
- return -EFAULT;
-
- a = (display.cursor_address | kLCD_Addr);
-
- udelay(150);
- BusyCheck();
- LCDWriteInst(a);
-
- break;
- }
-
- case LCD_Get_Cursor:{
- struct lcd_display display;
-
- udelay(150);
- BusyCheck();
- display.character = LCDReadData;
-
- if (copy_to_user
- ((struct lcd_display *) arg, &display,
- sizeof(struct lcd_display)))
- return -EFAULT;
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x10);
-
- break;
- }
-
- case LCD_Set_Cursor:{
- struct lcd_display display;
-
- if (copy_from_user
- (&display, (struct lcd_display *) arg,
- sizeof(struct lcd_display)))
- return -EFAULT;
-
- udelay(150);
- BusyCheck();
- LCDWriteData(display.character);
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x10);
-
- break;
- }
-
-
- case LCD_Disp_Left:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x18);
- break;
-
- case LCD_Disp_Right:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x1C);
- break;
-
- case LCD_Home:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x02);
- break;
-
- case LCD_Write:{
- struct lcd_display display;
- unsigned int index;
-
-
- if (copy_from_user
- (&display, (struct lcd_display *) arg,
- sizeof(struct lcd_display)))
- return -EFAULT;
-
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x80);
- udelay(150);
- BusyCheck();
-
- for (index = 0; index < (display.size1); index++) {
- udelay(150);
- BusyCheck();
- LCDWriteData(display.line1[index]);
- BusyCheck();
- }
-
- udelay(150);
- BusyCheck();
- LCDWriteInst(0xC0);
- udelay(150);
- BusyCheck();
- for (index = 0; index < (display.size2); index++) {
- udelay(150);
- BusyCheck();
- LCDWriteData(display.line2[index]);
- }
-
- break;
- }
-
- case LCD_Read:{
- struct lcd_display display;
-
- BusyCheck();
- for (address = kDD_R00; address <= kDD_R01;
- address++) {
- a = (address | kLCD_Addr);
-
- udelay(150);
- BusyCheck();
- LCDWriteInst(a);
- udelay(150);
- BusyCheck();
- display.line1[address] = LCDReadData;
- }
-
- display.line1[0x27] = '\0';
-
- for (address = kDD_R10; address <= kDD_R11;
- address++) {
- a = (address | kLCD_Addr);
-
- udelay(150);
- BusyCheck();
- LCDWriteInst(a);
-
- udelay(150);
- BusyCheck();
- display.line2[address - 0x40] =
- LCDReadData;
- }
-
- display.line2[0x27] = '\0';
-
- if (copy_to_user
- ((struct lcd_display *) arg, &display,
- sizeof(struct lcd_display)))
- return -EFAULT;
- break;
- }
-
-// set all GPIO leds to led_display.leds
-
- case LED_Set:{
- struct lcd_display led_display;
-
-
- if (copy_from_user
- (&led_display, (struct lcd_display *) arg,
- sizeof(struct lcd_display)))
- return -EFAULT;
-
- led_state = led_display.leds;
- LEDSet(led_state);
-
- break;
- }
-
-
-// set only bit led_display.leds
-
- case LED_Bit_Set:{
- unsigned int i;
- int bit = 1;
- struct lcd_display led_display;
-
-
- if (copy_from_user
- (&led_display, (struct lcd_display *) arg,
- sizeof(struct lcd_display)))
- return -EFAULT;
-
- for (i = 0; i < (int) led_display.leds; i++) {
- bit = 2 * bit;
- }
-
- led_state = led_state | bit;
- LEDSet(led_state);
- break;
- }
-
-// clear only bit led_display.leds
-
- case LED_Bit_Clear:{
- unsigned int i;
- int bit = 1;
- struct lcd_display led_display;
-
-
- if (copy_from_user
- (&led_display, (struct lcd_display *) arg,
- sizeof(struct lcd_display)))
- return -EFAULT;
-
- for (i = 0; i < (int) led_display.leds; i++) {
- bit = 2 * bit;
- }
-
- led_state = led_state & ~bit;
- LEDSet(led_state);
- break;
- }
-
-
- case BUTTON_Read:{
- button_display.buttons = GPIRead;
- if (copy_to_user
- ((struct lcd_display *) arg, &button_display,
- sizeof(struct lcd_display)))
- return -EFAULT;
- break;
- }
-
- case LINK_Check:{
- button_display.buttons =
- *((volatile unsigned long *) (0xB0100060));
- if (copy_to_user
- ((struct lcd_display *) arg, &button_display,
- sizeof(struct lcd_display)))
- return -EFAULT;
- break;
- }
-
- case LINK_Check_2:{
- int iface_num;
-
- /* panel-utils should pass in the desired interface status is wanted for
- * in "buttons" of the structure. We will set this to non-zero if the
- * link is in fact up for the requested interface. --DaveM
- */
- if (copy_from_user
- (&button_display, (struct lcd_display *) arg,
- sizeof(button_display)))
- return -EFAULT;
- iface_num = button_display.buttons;
-#if defined(CONFIG_TULIP) && 0
- if (iface_num >= 0 &&
- iface_num < MAX_INTERFACES &&
- linkcheck_callbacks[iface_num] != NULL) {
- button_display.buttons =
- linkcheck_callbacks[iface_num]
- (linkcheck_cookies[iface_num]);
- } else
-#endif
- button_display.buttons = 0;
-
- if (__copy_to_user
- ((struct lcd_display *) arg, &button_display,
- sizeof(struct lcd_display)))
- return -EFAULT;
- break;
- }
-
- default:
- return -EINVAL;
-
- }
-
- return 0;
-
-}
-
-static int lcd_open(struct inode *inode, struct file *file)
-{
- cycle_kernel_lock();
-
- if (!lcd_present)
- return -ENXIO;
- else
- return 0;
-}
-
-/* Only RESET or NEXT counts as button pressed */
-
-static inline int button_pressed(void)
-{
- unsigned long buttons = GPIRead;
-
- if ((buttons == BUTTON_Next) || (buttons == BUTTON_Next_B)
- || (buttons == BUTTON_Reset_B))
- return buttons;
- return 0;
-}
-
-/* LED daemon sits on this and we wake him up once a key is pressed. */
-
-static int lcd_waiters = 0;
-
-static ssize_t lcd_read(struct file *file, char *buf,
- size_t count, loff_t *ofs)
-{
- long buttons_now;
-
- if (lcd_waiters > 0)
- return -EINVAL;
-
- lcd_waiters++;
- while (((buttons_now = (long) button_pressed()) == 0) &&
- !(signal_pending(current))) {
- msleep_interruptible(2000);
- }
- lcd_waiters--;
-
- if (signal_pending(current))
- return -ERESTARTSYS;
- return buttons_now;
-}
-
-/*
- * The various file operations we support.
- */
-
-static const struct file_operations lcd_fops = {
- .read = lcd_read,
- .ioctl = lcd_ioctl,
- .open = lcd_open,
-};
-
-static struct miscdevice lcd_dev = {
- MISC_DYNAMIC_MINOR,
- "lcd",
- &lcd_fops
-};
-
-static int lcd_init(void)
-{
- int ret;
- unsigned long data;
-
- pr_info("%s\n", LCD_DRIVER);
- ret = misc_register(&lcd_dev);
- if (ret) {
- printk(KERN_WARNING LCD "Unable to register misc device.\n");
- return ret;
- }
-
- /* Check region? Naaah! Just snarf it up. */
-/* request_region(RTC_PORT(0), RTC_IO_EXTENT, "lcd");*/
-
- udelay(150);
- data = LCDReadData;
- if ((data & 0x000000FF) == (0x00)) {
- lcd_present = 0;
- pr_info(LCD "LCD Not Present\n");
- } else {
- lcd_present = 1;
- WRITE_GAL(kGal_DevBank2PReg, kGal_DevBank2Cfg);
- WRITE_GAL(kGal_DevBank3PReg, kGal_DevBank3Cfg);
- }
-
- return 0;
-}
-
-static void __exit lcd_exit(void)
-{
- misc_deregister(&lcd_dev);
-}
-
-module_init(lcd_init);
-module_exit(lcd_exit);
-
-MODULE_AUTHOR("Andrew Bose");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/lcd.h b/drivers/char/lcd.h
deleted file mode 100644
index 290b3ff23b0..00000000000
--- a/drivers/char/lcd.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * LED, LCD and Button panel driver for Cobalt
- *
- * 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.
- *
- * Copyright (C) 1996, 1997 by Andrew Bose
- *
- * Linux kernel version history:
- * March 2001: Ported from 2.0.34 by Liam Davies
- *
- */
-
-// function headers
-
-#define LCD_CHARS_PER_LINE 40
-#define MAX_IDLE_TIME 120
-
-struct lcd_display {
- unsigned buttons;
- int size1;
- int size2;
- unsigned char line1[LCD_CHARS_PER_LINE];
- unsigned char line2[LCD_CHARS_PER_LINE];
- unsigned char cursor_address;
- unsigned char character;
- unsigned char leds;
- unsigned char *RomImage;
-};
-
-
-
-#define LCD_DRIVER "Cobalt LCD Driver v2.10"
-
-#define LCD "lcd: "
-
-#define kLCD_IR 0x0F000000
-#define kLCD_DR 0x0F000010
-#define kGPI 0x0D000000
-#define kLED 0x0C000000
-
-#define kDD_R00 0x00
-#define kDD_R01 0x27
-#define kDD_R10 0x40
-#define kDD_R11 0x67
-
-#define kLCD_Addr 0x00000080
-
-#define LCDTimeoutValue 0xfff
-
-
-// Macros
-
-#define LCDWriteData(x) outl((x << 24), kLCD_DR)
-#define LCDWriteInst(x) outl((x << 24), kLCD_IR)
-
-#define LCDReadData (inl(kLCD_DR) >> 24)
-#define LCDReadInst (inl(kLCD_IR) >> 24)
-
-#define GPIRead (inl(kGPI) >> 24)
-
-#define LEDSet(x) outb((char)x, kLED)
-
-#define WRITE_GAL(x,y) outl(y, 0x04000000 | (x))
-#define BusyCheck() while ((LCDReadInst & 0x80) == 0x80)
-
-
-
-/*
- * Function command codes for io_ctl.
- */
-#define LCD_On 1
-#define LCD_Off 2
-#define LCD_Clear 3
-#define LCD_Reset 4
-#define LCD_Cursor_Left 5
-#define LCD_Cursor_Right 6
-#define LCD_Disp_Left 7
-#define LCD_Disp_Right 8
-#define LCD_Get_Cursor 9
-#define LCD_Set_Cursor 10
-#define LCD_Home 11
-#define LCD_Read 12
-#define LCD_Write 13
-#define LCD_Cursor_Off 14
-#define LCD_Cursor_On 15
-#define LCD_Get_Cursor_Pos 16
-#define LCD_Set_Cursor_Pos 17
-#define LCD_Blink_Off 18
-
-#define LED_Set 40
-#define LED_Bit_Set 41
-#define LED_Bit_Clear 42
-
-
-// Button defs
-#define BUTTON_Read 50
-
-
-// Ethernet LINK check hackaroo
-#define LINK_Check 90
-#define LINK_Check_2 91
-
-// Button patterns _B - single layer lcd boards
-
-#define BUTTON_NONE 0x3F
-#define BUTTON_NONE_B 0xFE
-
-#define BUTTON_Left 0x3B
-#define BUTTON_Left_B 0xFA
-
-#define BUTTON_Right 0x37
-#define BUTTON_Right_B 0xDE
-
-#define BUTTON_Up 0x2F
-#define BUTTON_Up_B 0xF6
-
-#define BUTTON_Down 0x1F
-#define BUTTON_Down_B 0xEE
-
-#define BUTTON_Next 0x3D
-#define BUTTON_Next_B 0x7E
-
-#define BUTTON_Enter 0x3E
-#define BUTTON_Enter_B 0xBE
-
-#define BUTTON_Reset_B 0xFC
-
-
-// debounce constants
-
-#define BUTTON_SENSE 160000
-#define BUTTON_DEBOUNCE 5000
-
-
-// Galileo register stuff
-
-#define kGal_DevBank2Cfg 0x1466DB33
-#define kGal_DevBank2PReg 0x464
-#define kGal_DevBank3Cfg 0x146FDFFB
-#define kGal_DevBank3PReg 0x468
-
-// Network
-
-#define kIPADDR 1
-#define kNETMASK 2
-#define kGATEWAY 3
-#define kDNS 4
-
-#define kClassA 5
-#define kClassB 6
-#define kClassC 7
-
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 71abb4c33aa..3f2719b9f77 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -813,7 +813,8 @@ static int lp_register(int nr, struct parport *port)
if (reset)
lp_reset(nr);
- device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), "lp%d", nr);
+ device_create_drvdata(lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL,
+ "lp%d", nr);
printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name,
(port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index b6772d65754..672b08e694d 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -327,7 +327,10 @@ static void mmap_mem_close(struct vm_area_struct *vma)
static struct vm_operations_struct mmap_mem_ops = {
.open = mmap_mem_open,
- .close = mmap_mem_close
+ .close = mmap_mem_close,
+#ifdef CONFIG_HAVE_IOREMAP_PROT
+ .access = generic_access_phys
+#endif
};
static int mmap_mem(struct file * file, struct vm_area_struct * vma)
@@ -989,9 +992,9 @@ static int __init chr_dev_init(void)
mem_class = class_create(THIS_MODULE, "mem");
for (i = 0; i < ARRAY_SIZE(devlist); i++)
- device_create(mem_class, NULL,
- MKDEV(MEM_MAJOR, devlist[i].minor),
- devlist[i].name);
+ device_create_drvdata(mem_class, NULL,
+ MKDEV(MEM_MAJOR, devlist[i].minor),
+ NULL, devlist[i].name);
return 0;
}
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 6e1563c3d30..999aa779c08 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -217,8 +217,8 @@ int misc_register(struct miscdevice * misc)
misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
dev = MKDEV(MISC_MAJOR, misc->minor);
- misc->this_device = device_create(misc_class, misc->parent, dev,
- "%s", misc->name);
+ misc->this_device = device_create_drvdata(misc_class, misc->parent,
+ dev, NULL, "%s", misc->name);
if (IS_ERR(misc->this_device)) {
err = PTR_ERR(misc->this_device);
goto out;
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 2bba250ffc8..d3d7864e0c1 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -374,12 +374,13 @@ copy:
return ret;
}
-static void moxa_break_ctl(struct tty_struct *tty, int state)
+static int moxa_break_ctl(struct tty_struct *tty, int state)
{
struct moxa_port *port = tty->driver_data;
moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak,
Magic_code);
+ return 0;
}
static const struct tty_operations moxa_ops = {
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index fe2a95b5d3c..30f095a8c2d 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -193,25 +193,23 @@ mspec_close(struct vm_area_struct *vma)
}
/*
- * mspec_nopfn
+ * mspec_fault
*
* Creates a mspec page and maps it to user space.
*/
-static unsigned long
-mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
+static int
+mspec_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
unsigned long paddr, maddr;
unsigned long pfn;
- int index;
+ pgoff_t index = vmf->pgoff;
struct vma_data *vdata = vma->vm_private_data;
- BUG_ON(address < vdata->vm_start || address >= vdata->vm_end);
- index = (address - vdata->vm_start) >> PAGE_SHIFT;
maddr = (volatile unsigned long) vdata->maddr[index];
if (maddr == 0) {
maddr = uncached_alloc_page(numa_node_id(), 1);
if (maddr == 0)
- return NOPFN_OOM;
+ return VM_FAULT_OOM;
spin_lock(&vdata->lock);
if (vdata->maddr[index] == 0) {
@@ -231,13 +229,20 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
pfn = paddr >> PAGE_SHIFT;
- return pfn;
+ /*
+ * vm_insert_pfn can fail with -EBUSY, but in that case it will
+ * be because another thread has installed the pte first, so it
+ * is no problem.
+ */
+ vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
+
+ return VM_FAULT_NOPAGE;
}
static struct vm_operations_struct mspec_vm_ops = {
.open = mspec_open,
.close = mspec_close,
- .nopfn = mspec_nopfn
+ .fault = mspec_fault,
};
/*
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index 50243fcd87e..4f8d67fed29 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -86,8 +86,8 @@ module_param(mwave_uart_io, int, 0);
static int mwave_open(struct inode *inode, struct file *file);
static int mwave_close(struct inode *inode, struct file *file);
-static int mwave_ioctl(struct inode *inode, struct file *filp,
- unsigned int iocmd, unsigned long ioarg);
+static long mwave_ioctl(struct file *filp, unsigned int iocmd,
+ unsigned long ioarg);
MWAVE_DEVICE_DATA mwave_s_mdd;
@@ -119,16 +119,16 @@ static int mwave_close(struct inode *inode, struct file *file)
return retval;
}
-static int mwave_ioctl(struct inode *inode, struct file *file,
- unsigned int iocmd, unsigned long ioarg)
+static long mwave_ioctl(struct file *file, unsigned int iocmd,
+ unsigned long ioarg)
{
unsigned int retval = 0;
pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
void __user *arg = (void __user *)ioarg;
- PRINTK_5(TRACE_MWAVE,
- "mwavedd::mwave_ioctl, entry inode %p file %p cmd %x arg %x\n",
- inode, file, iocmd, (int) ioarg);
+ PRINTK_4(TRACE_MWAVE,
+ "mwavedd::mwave_ioctl, entry file %p cmd %x arg %x\n",
+ file, iocmd, (int) ioarg);
switch (iocmd) {
@@ -136,7 +136,9 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
PRINTK_1(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
" calling tp3780I_ResetDSP\n");
+ lock_kernel();
retval = tp3780I_ResetDSP(&pDrvData->rBDData);
+ unlock_kernel();
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
" retval %x from tp3780I_ResetDSP\n",
@@ -147,7 +149,9 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
PRINTK_1(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
" calling tp3780I_StartDSP\n");
+ lock_kernel();
retval = tp3780I_StartDSP(&pDrvData->rBDData);
+ unlock_kernel();
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
" retval %x from tp3780I_StartDSP\n",
@@ -161,8 +165,10 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
"mwavedd::mwave_ioctl,"
" IOCTL_MW_DSP_ABILITIES calling"
" tp3780I_QueryAbilities\n");
+ lock_kernel();
retval = tp3780I_QueryAbilities(&pDrvData->rBDData,
&rAbilities);
+ unlock_kernel();
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
" retval %x from tp3780I_QueryAbilities\n",
@@ -193,11 +199,13 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
"mwavedd::mwave_ioctl IOCTL_MW_READ_DATA,"
" size %lx, ioarg %lx pusBuffer %p\n",
rReadData.ulDataLength, ioarg, pusBuffer);
+ lock_kernel();
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
iocmd,
pusBuffer,
rReadData.ulDataLength,
rReadData.usDspAddress);
+ unlock_kernel();
}
break;
@@ -215,10 +223,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
" size %lx, ioarg %lx pusBuffer %p\n",
rReadData.ulDataLength / 2, ioarg,
pusBuffer);
+ lock_kernel();
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
iocmd, pusBuffer,
rReadData.ulDataLength / 2,
rReadData.usDspAddress);
+ unlock_kernel();
}
break;
@@ -236,10 +246,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
" size %lx, ioarg %lx pusBuffer %p\n",
rWriteData.ulDataLength, ioarg,
pusBuffer);
+ lock_kernel();
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
iocmd, pusBuffer,
rWriteData.ulDataLength,
rWriteData.usDspAddress);
+ unlock_kernel();
}
break;
@@ -257,10 +269,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
" size %lx, ioarg %lx pusBuffer %p\n",
rWriteData.ulDataLength, ioarg,
pusBuffer);
+ lock_kernel();
retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData,
iocmd, pusBuffer,
rWriteData.ulDataLength,
rWriteData.usDspAddress);
+ unlock_kernel();
}
break;
@@ -281,8 +295,10 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
ipcnum);
return -EINVAL;
}
+ lock_kernel();
pDrvData->IPCs[ipcnum].bIsHere = FALSE;
pDrvData->IPCs[ipcnum].bIsEnabled = TRUE;
+ unlock_kernel();
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
@@ -307,6 +323,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
}
+ lock_kernel();
if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
DECLARE_WAITQUEUE(wait, current);
@@ -347,6 +364,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
" processing\n",
ipcnum);
}
+ unlock_kernel();
}
break;
@@ -365,19 +383,18 @@ static int mwave_ioctl(struct inode *inode, struct file *file,
ipcnum);
return -EINVAL;
}
+ lock_kernel();
if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
pDrvData->IPCs[ipcnum].bIsEnabled = FALSE;
if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) {
wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue);
}
}
+ unlock_kernel();
}
break;
default:
- PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl:"
- " Error: Unrecognized iocmd %x\n",
- iocmd);
return -ENOTTY;
break;
} /* switch */
@@ -460,7 +477,7 @@ static const struct file_operations mwave_fops = {
.owner = THIS_MODULE,
.read = mwave_read,
.write = mwave_write,
- .ioctl = mwave_ioctl,
+ .unlocked_ioctl = mwave_ioctl,
.open = mwave_open,
.release = mwave_close
};
diff --git a/drivers/char/mwave/mwavedd.h b/drivers/char/mwave/mwavedd.h
index 8eca61e0a19..7e0d530e2e0 100644
--- a/drivers/char/mwave/mwavedd.h
+++ b/drivers/char/mwave/mwavedd.h
@@ -147,4 +147,6 @@ typedef struct _MWAVE_DEVICE_DATA {
} MWAVE_DEVICE_DATA, *pMWAVE_DEVICE_DATA;
+extern MWAVE_DEVICE_DATA mwave_s_mdd;
+
#endif
diff --git a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c
index f282976daaa..c6896970806 100644
--- a/drivers/char/mwave/tp3780i.c
+++ b/drivers/char/mwave/tp3780i.c
@@ -57,8 +57,6 @@
#include "3780i.h"
#include "mwavepub.h"
-extern MWAVE_DEVICE_DATA mwave_s_mdd;
-
static unsigned short s_ausThinkpadIrqToField[16] =
{ 0xFFFF, 0xFFFF, 0xFFFF, 0x0001, 0x0002, 0x0003, 0xFFFF, 0x0004,
0xFFFF, 0xFFFF, 0x0005, 0x0006, 0xFFFF, 0xFFFF, 0xFFFF, 0x0007 };
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 6307e301bd2..e30575e8764 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -16,7 +16,6 @@
* Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox
* <alan@redhat.com>. The original 1.8 code is available on www.moxa.com.
* - Fixed x86_64 cleanness
- * - Fixed sleep with spinlock held in mxser_send_break
*/
#include <linux/module.h>
@@ -47,20 +46,14 @@
#include "mxser.h"
-#define MXSER_VERSION "2.0.3" /* 1.11 */
+#define MXSER_VERSION "2.0.4" /* 1.12 */
#define MXSERMAJOR 174
-#define MXSERCUMAJOR 175
#define MXSER_BOARDS 4 /* Max. boards */
#define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */
#define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD)
#define MXSER_ISR_PASS_LIMIT 100
-#define MXSER_ERR_IOADDR -1
-#define MXSER_ERR_IRQ -2
-#define MXSER_ERR_IRQ_CONFLIT -3
-#define MXSER_ERR_VECTOR -4
-
/*CheckIsMoxaMust return value*/
#define MOXA_OTHER_UART 0x00
#define MOXA_MUST_MU150_HWID 0x01
@@ -71,12 +64,13 @@
#define UART_MCR_AFE 0x20
#define UART_LSR_SPECIAL 0x1E
+#define PCI_DEVICE_ID_POS104UL 0x1044
#define PCI_DEVICE_ID_CB108 0x1080
+#define PCI_DEVICE_ID_CP102UF 0x1023
#define PCI_DEVICE_ID_CB114 0x1142
#define PCI_DEVICE_ID_CP114UL 0x1143
#define PCI_DEVICE_ID_CB134I 0x1341
#define PCI_DEVICE_ID_CP138U 0x1380
-#define PCI_DEVICE_ID_POS104UL 0x1044
#define C168_ASIC_ID 1
@@ -142,7 +136,8 @@ static const struct mxser_cardinfo mxser_cards[] = {
{ "CB-134I series", 4, },
{ "CP-138U series", 8, },
{ "POS-104UL series", 4, },
- { "CP-114UL series", 4, }
+ { "CP-114UL series", 4, },
+/*30*/ { "CP-102UF series", 2, }
};
/* driver_data correspond to the lines in the structure above
@@ -172,18 +167,20 @@ static struct pci_device_id mxser_pcibrds[] = {
{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U), .driver_data = 27 },
{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 28 },
{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL), .driver_data = 29 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF), .driver_data = 30 },
{ }
};
MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
-static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 };
+static unsigned long ioaddr[MXSER_BOARDS];
static int ttymajor = MXSERMAJOR;
/* Variables for insmod */
MODULE_AUTHOR("Casper Yang");
MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver");
-module_param_array(ioaddr, int, NULL, 0);
+module_param_array(ioaddr, ulong, NULL, 0);
+MODULE_PARM_DESC(ioaddr, "ISA io addresses to look for a moxa board");
module_param(ttymajor, int, 0);
MODULE_LICENSE("GPL");
@@ -193,7 +190,6 @@ struct mxser_log {
unsigned long txcnt[MXSER_PORTS];
};
-
struct mxser_mon {
unsigned long rxcnt;
unsigned long txcnt;
@@ -284,19 +280,9 @@ struct mxser_mstatus {
int dcd;
};
-static struct mxser_mstatus GMStatus[MXSER_PORTS];
-
-static int mxserBoardCAP[MXSER_BOARDS] = {
- 0, 0, 0, 0
- /* 0x180, 0x280, 0x200, 0x320 */
-};
-
static struct mxser_board mxser_boards[MXSER_BOARDS];
static struct tty_driver *mxvar_sdriver;
static struct mxser_log mxvar_log;
-static int mxvar_diagflag;
-static unsigned char mxser_msr[MXSER_PORTS + 1];
-static struct mxser_mon_ext mon_data_ext;
static int mxser_set_baud_method[MXSER_PORTS + 1];
static void mxser_enable_must_enchance_mode(unsigned long baseio)
@@ -540,6 +526,7 @@ static void process_txrx_fifo(struct mxser_port *info)
static unsigned char mxser_get_msr(int baseaddr, int mode, int port)
{
+ static unsigned char mxser_msr[MXSER_PORTS + 1];
unsigned char status = 0;
status = inb(baseaddr + UART_MSR);
@@ -1316,13 +1303,9 @@ static void mxser_flush_chars(struct tty_struct *tty)
struct mxser_port *info = tty->driver_data;
unsigned long flags;
- if (info->xmit_cnt <= 0 ||
- tty->stopped ||
- !info->port.xmit_buf ||
- (tty->hw_stopped &&
- (info->type != PORT_16550A) &&
- (!info->board->chip_flag)
- ))
+ if (info->xmit_cnt <= 0 || tty->stopped || !info->port.xmit_buf ||
+ (tty->hw_stopped && info->type != PORT_16550A &&
+ !info->board->chip_flag))
return;
spin_lock_irqsave(&info->slock, flags);
@@ -1340,9 +1323,7 @@ static int mxser_write_room(struct tty_struct *tty)
int ret;
ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
- if (ret < 0)
- ret = 0;
- return ret;
+ return ret < 0 ? 0 : ret;
}
static int mxser_chars_in_buffer(struct tty_struct *tty)
@@ -1414,7 +1395,6 @@ static int mxser_set_serial_info(struct mxser_port *info,
info->port.closing_wait = new_serial.closing_wait * HZ / 100;
info->port.tty->low_latency =
(info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
- info->port.tty->low_latency = 0;
if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
(new_serial.baud_base != info->baud_base ||
new_serial.custom_divisor !=
@@ -1464,27 +1444,6 @@ static int mxser_get_lsr_info(struct mxser_port *info,
return put_user(result, value);
}
-/*
- * This routine sends a break character out the serial port.
- */
-static void mxser_send_break(struct mxser_port *info, int duration)
-{
- unsigned long flags;
-
- if (!info->ioaddr)
- return;
- set_current_state(TASK_INTERRUPTIBLE);
- spin_lock_irqsave(&info->slock, flags);
- outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC,
- info->ioaddr + UART_LCR);
- spin_unlock_irqrestore(&info->slock, flags);
- schedule_timeout(duration);
- spin_lock_irqsave(&info->slock, flags);
- outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
- info->ioaddr + UART_LCR);
- spin_unlock_irqrestore(&info->slock, flags);
-}
-
static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
{
struct mxser_port *info = tty->driver_data;
@@ -1653,6 +1612,8 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
switch (cmd) {
case MOXA_GET_MAJOR:
+ printk(KERN_WARNING "mxser: '%s' uses deprecated ioctl %x, fix "
+ "your userspace\n", current->comm, cmd);
return put_user(ttymajor, (int __user *)argp);
case MOXA_CHKPORTENABLE:
@@ -1670,62 +1631,60 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
ret = -EFAULT;
unlock_kernel();
return ret;
- case MOXA_GETMSTATUS:
+ case MOXA_GETMSTATUS: {
+ struct mxser_mstatus ms, __user *msu = argp;
lock_kernel();
for (i = 0; i < MXSER_BOARDS; i++)
for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
port = &mxser_boards[i].ports[j];
+ memset(&ms, 0, sizeof(ms));
- GMStatus[i].ri = 0;
- if (!port->ioaddr) {
- GMStatus[i].dcd = 0;
- GMStatus[i].dsr = 0;
- GMStatus[i].cts = 0;
- continue;
- }
+ if (!port->ioaddr)
+ goto copy;
if (!port->port.tty || !port->port.tty->termios)
- GMStatus[i].cflag =
- port->normal_termios.c_cflag;
+ ms.cflag = port->normal_termios.c_cflag;
else
- GMStatus[i].cflag =
- port->port.tty->termios->c_cflag;
+ ms.cflag = port->port.tty->termios->c_cflag;
status = inb(port->ioaddr + UART_MSR);
- if (status & 0x80 /*UART_MSR_DCD */ )
- GMStatus[i].dcd = 1;
- else
- GMStatus[i].dcd = 0;
-
- if (status & 0x20 /*UART_MSR_DSR */ )
- GMStatus[i].dsr = 1;
- else
- GMStatus[i].dsr = 0;
-
-
- if (status & 0x10 /*UART_MSR_CTS */ )
- GMStatus[i].cts = 1;
- else
- GMStatus[i].cts = 0;
+ if (status & UART_MSR_DCD)
+ ms.dcd = 1;
+ if (status & UART_MSR_DSR)
+ ms.dsr = 1;
+ if (status & UART_MSR_CTS)
+ ms.cts = 1;
+ copy:
+ if (copy_to_user(msu, &ms, sizeof(ms))) {
+ unlock_kernel();
+ return -EFAULT;
+ }
+ msu++;
}
unlock_kernel();
- if (copy_to_user(argp, GMStatus,
- sizeof(struct mxser_mstatus) * MXSER_PORTS))
- return -EFAULT;
return 0;
+ }
case MOXA_ASPP_MON_EXT: {
- int p, shiftbit;
- unsigned long opmode;
- unsigned cflag, iflag;
+ struct mxser_mon_ext *me; /* it's 2k, stack unfriendly */
+ unsigned int cflag, iflag, p;
+ u8 opmode;
+
+ me = kzalloc(sizeof(*me), GFP_KERNEL);
+ if (!me)
+ return -ENOMEM;
lock_kernel();
- for (i = 0; i < MXSER_BOARDS; i++) {
- for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
+ for (i = 0, p = 0; i < MXSER_BOARDS; i++) {
+ for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) {
+ if (p >= ARRAY_SIZE(me->rx_cnt)) {
+ i = MXSER_BOARDS;
+ break;
+ }
port = &mxser_boards[i].ports[j];
if (!port->ioaddr)
continue;
- status = mxser_get_msr(port->ioaddr, 0, i);
+ status = mxser_get_msr(port->ioaddr, 0, p);
if (status & UART_MSR_TERI)
port->icount.rng++;
@@ -1737,16 +1696,13 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
port->icount.cts++;
port->mon_data.modem_status = status;
- mon_data_ext.rx_cnt[i] = port->mon_data.rxcnt;
- mon_data_ext.tx_cnt[i] = port->mon_data.txcnt;
- mon_data_ext.up_rxcnt[i] =
- port->mon_data.up_rxcnt;
- mon_data_ext.up_txcnt[i] =
- port->mon_data.up_txcnt;
- mon_data_ext.modem_status[i] =
+ me->rx_cnt[p] = port->mon_data.rxcnt;
+ me->tx_cnt[p] = port->mon_data.txcnt;
+ me->up_rxcnt[p] = port->mon_data.up_rxcnt;
+ me->up_txcnt[p] = port->mon_data.up_txcnt;
+ me->modem_status[p] =
port->mon_data.modem_status;
- mon_data_ext.baudrate[i] =
- tty_get_baud_rate(port->port.tty);
+ me->baudrate[p] = tty_get_baud_rate(port->port.tty);
if (!port->port.tty || !port->port.tty->termios) {
cflag = port->normal_termios.c_cflag;
@@ -1756,40 +1712,31 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
iflag = port->port.tty->termios->c_iflag;
}
- mon_data_ext.databits[i] = cflag & CSIZE;
-
- mon_data_ext.stopbits[i] = cflag & CSTOPB;
-
- mon_data_ext.parity[i] =
- cflag & (PARENB | PARODD | CMSPAR);
-
- mon_data_ext.flowctrl[i] = 0x00;
+ me->databits[p] = cflag & CSIZE;
+ me->stopbits[p] = cflag & CSTOPB;
+ me->parity[p] = cflag & (PARENB | PARODD |
+ CMSPAR);
if (cflag & CRTSCTS)
- mon_data_ext.flowctrl[i] |= 0x03;
+ me->flowctrl[p] |= 0x03;
if (iflag & (IXON | IXOFF))
- mon_data_ext.flowctrl[i] |= 0x0C;
+ me->flowctrl[p] |= 0x0C;
if (port->type == PORT_16550A)
- mon_data_ext.fifo[i] = 1;
- else
- mon_data_ext.fifo[i] = 0;
+ me->fifo[p] = 1;
- p = i % 4;
- shiftbit = p * 2;
- opmode = inb(port->opmode_ioaddr) >> shiftbit;
+ opmode = inb(port->opmode_ioaddr) >>
+ ((p % 4) * 2);
opmode &= OP_MODE_MASK;
-
- mon_data_ext.iftype[i] = opmode;
-
+ me->iftype[p] = opmode;
}
}
unlock_kernel();
- if (copy_to_user(argp, &mon_data_ext,
- sizeof(mon_data_ext)))
- return -EFAULT;
- return 0;
+ if (copy_to_user(argp, me, sizeof(*me)))
+ ret = -EFAULT;
+ kfree(me);
+ return ret;
}
default:
return -ENOIOCTLCMD;
@@ -1823,7 +1770,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
{
struct mxser_port *info = tty->driver_data;
struct async_icount cnow;
- struct serial_icounter_struct __user *p_cuser;
unsigned long flags;
void __user *argp = (void __user *)arg;
int retval;
@@ -1872,21 +1818,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
return -EIO;
switch (cmd) {
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- if (!arg)
- mxser_send_break(info, HZ / 4); /* 1/4 second */
- return 0;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
- return 0;
case TIOCGSERIAL:
lock_kernel();
retval = mxser_get_serial_info(info, argp);
@@ -1918,30 +1849,26 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
* NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted.
*/
- case TIOCGICOUNT:
+ case TIOCGICOUNT: {
+ struct serial_icounter_struct icnt = { 0 };
spin_lock_irqsave(&info->slock, flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->slock, flags);
- p_cuser = argp;
- if (put_user(cnow.frame, &p_cuser->frame))
- return -EFAULT;
- if (put_user(cnow.brk, &p_cuser->brk))
- return -EFAULT;
- if (put_user(cnow.overrun, &p_cuser->overrun))
- return -EFAULT;
- if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
- return -EFAULT;
- if (put_user(cnow.parity, &p_cuser->parity))
- return -EFAULT;
- if (put_user(cnow.rx, &p_cuser->rx))
- return -EFAULT;
- if (put_user(cnow.tx, &p_cuser->tx))
- return -EFAULT;
- put_user(cnow.cts, &p_cuser->cts);
- put_user(cnow.dsr, &p_cuser->dsr);
- put_user(cnow.rng, &p_cuser->rng);
- put_user(cnow.dcd, &p_cuser->dcd);
- return 0;
+
+ icnt.frame = cnow.frame;
+ icnt.brk = cnow.brk;
+ icnt.overrun = cnow.overrun;
+ icnt.buf_overrun = cnow.buf_overrun;
+ icnt.parity = cnow.parity;
+ icnt.rx = cnow.rx;
+ icnt.tx = cnow.tx;
+ icnt.cts = cnow.cts;
+ icnt.dsr = cnow.dsr;
+ icnt.rng = cnow.rng;
+ icnt.dcd = cnow.dcd;
+
+ return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0;
+ }
case MOXA_HighSpeedOn:
return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
case MOXA_SDS_RSTICOUNTER:
@@ -2219,7 +2146,7 @@ static void mxser_hangup(struct tty_struct *tty)
/*
* mxser_rs_break() --- routine which turns the break handling on or off
*/
-static void mxser_rs_break(struct tty_struct *tty, int break_state)
+static int mxser_rs_break(struct tty_struct *tty, int break_state)
{
struct mxser_port *info = tty->driver_data;
unsigned long flags;
@@ -2232,6 +2159,7 @@ static void mxser_rs_break(struct tty_struct *tty, int break_state)
outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
info->ioaddr + UART_LCR);
spin_unlock_irqrestore(&info->slock, flags);
+ return 0;
}
static void mxser_receive_chars(struct mxser_port *port, int *status)
@@ -2536,7 +2464,8 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
unsigned int i;
int retval;
- printk(KERN_INFO "max. baud rate = %d bps.\n", brd->ports[0].max_baud);
+ printk(KERN_INFO "mxser: max. baud rate = %d bps\n",
+ brd->ports[0].max_baud);
for (i = 0; i < brd->info->nports; i++) {
info = &brd->ports[i];
@@ -2619,28 +2548,32 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
irq = regs[9] & 0xF000;
irq = irq | (irq >> 4);
if (irq != (regs[9] & 0xFF00))
- return MXSER_ERR_IRQ_CONFLIT;
+ goto err_irqconflict;
} else if (brd->info->nports == 4) {
irq = regs[9] & 0xF000;
irq = irq | (irq >> 4);
irq = irq | (irq >> 8);
if (irq != regs[9])
- return MXSER_ERR_IRQ_CONFLIT;
+ goto err_irqconflict;
} else if (brd->info->nports == 8) {
irq = regs[9] & 0xF000;
irq = irq | (irq >> 4);
irq = irq | (irq >> 8);
if ((irq != regs[9]) || (irq != regs[10]))
- return MXSER_ERR_IRQ_CONFLIT;
+ goto err_irqconflict;
}
- if (!irq)
- return MXSER_ERR_IRQ;
+ if (!irq) {
+ printk(KERN_ERR "mxser: interrupt number unset\n");
+ return -EIO;
+ }
brd->irq = ((int)(irq & 0xF000) >> 12);
for (i = 0; i < 8; i++)
brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8;
- if ((regs[12] & 0x80) == 0)
- return MXSER_ERR_VECTOR;
+ if ((regs[12] & 0x80) == 0) {
+ printk(KERN_ERR "mxser: invalid interrupt vector\n");
+ return -EIO;
+ }
brd->vector = (int)regs[11]; /* interrupt vector */
if (id == 1)
brd->vector_mask = 0x00FF;
@@ -2667,13 +2600,26 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
else
brd->uart_type = PORT_16450;
if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports,
- "mxser(IO)"))
- return MXSER_ERR_IOADDR;
+ "mxser(IO)")) {
+ printk(KERN_ERR "mxser: can't request ports I/O region: "
+ "0x%.8lx-0x%.8lx\n",
+ brd->ports[0].ioaddr, brd->ports[0].ioaddr +
+ 8 * brd->info->nports - 1);
+ return -EIO;
+ }
if (!request_region(brd->vector, 1, "mxser(vector)")) {
release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
- return MXSER_ERR_VECTOR;
+ printk(KERN_ERR "mxser: can't request interrupt vector region: "
+ "0x%.8lx-0x%.8lx\n",
+ brd->ports[0].ioaddr, brd->ports[0].ioaddr +
+ 8 * brd->info->nports - 1);
+ return -EIO;
}
return brd->info->nports;
+
+err_irqconflict:
+ printk(KERN_ERR "mxser: invalid interrupt number\n");
+ return -EIO;
}
static int __devinit mxser_probe(struct pci_dev *pdev,
@@ -2690,20 +2636,20 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
break;
if (i >= MXSER_BOARDS) {
- printk(KERN_ERR "Too many Smartio/Industio family boards found "
- "(maximum %d), board not configured\n", MXSER_BOARDS);
+ dev_err(&pdev->dev, "too many boards found (maximum %d), board "
+ "not configured\n", MXSER_BOARDS);
goto err;
}
brd = &mxser_boards[i];
brd->idx = i * MXSER_PORTS_PER_BOARD;
- printk(KERN_INFO "Found MOXA %s board (BusNo=%d, DevNo=%d)\n",
+ dev_info(&pdev->dev, "found MOXA %s board (BusNo=%d, DevNo=%d)\n",
mxser_cards[ent->driver_data].name,
pdev->bus->number, PCI_SLOT(pdev->devfn));
retval = pci_enable_device(pdev);
if (retval) {
- printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n");
+ dev_err(&pdev->dev, "PCI enable failed\n");
goto err;
}
@@ -2805,11 +2751,8 @@ static struct pci_driver mxser_driver = {
static int __init mxser_module_init(void)
{
struct mxser_board *brd;
- unsigned long cap;
- unsigned int i, m, isaloop;
- int retval, b;
-
- pr_debug("Loading module mxser ...\n");
+ unsigned int b, i, m;
+ int retval;
mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1);
if (!mxvar_sdriver)
@@ -2839,74 +2782,43 @@ static int __init mxser_module_init(void)
goto err_put;
}
- mxvar_diagflag = 0;
-
- m = 0;
/* Start finding ISA boards here */
- for (isaloop = 0; isaloop < 2; isaloop++)
- for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) {
- if (!isaloop)
- cap = mxserBoardCAP[b]; /* predefined */
- else
- cap = ioaddr[b]; /* module param */
+ for (m = 0, b = 0; b < MXSER_BOARDS; b++) {
+ if (!ioaddr[b])
+ continue;
+
+ brd = &mxser_boards[m];
+ retval = mxser_get_ISA_conf(!ioaddr[b], brd);
+ if (retval <= 0) {
+ brd->info = NULL;
+ continue;
+ }
- if (!cap)
- continue;
+ printk(KERN_INFO "mxser: found MOXA %s board (CAP=0x%lx)\n",
+ brd->info->name, ioaddr[b]);
- brd = &mxser_boards[m];
- retval = mxser_get_ISA_conf(cap, brd);
-
- if (retval != 0)
- printk(KERN_INFO "Found MOXA %s board "
- "(CAP=0x%x)\n",
- brd->info->name, ioaddr[b]);
-
- if (retval <= 0) {
- if (retval == MXSER_ERR_IRQ)
- printk(KERN_ERR "Invalid interrupt "
- "number, board not "
- "configured\n");
- else if (retval == MXSER_ERR_IRQ_CONFLIT)
- printk(KERN_ERR "Invalid interrupt "
- "number, board not "
- "configured\n");
- else if (retval == MXSER_ERR_VECTOR)
- printk(KERN_ERR "Invalid interrupt "
- "vector, board not "
- "configured\n");
- else if (retval == MXSER_ERR_IOADDR)
- printk(KERN_ERR "Invalid I/O address, "
- "board not configured\n");
-
- brd->info = NULL;
- continue;
- }
-
- /* mxser_initbrd will hook ISR. */
- if (mxser_initbrd(brd, NULL) < 0) {
- brd->info = NULL;
- continue;
- }
+ /* mxser_initbrd will hook ISR. */
+ if (mxser_initbrd(brd, NULL) < 0) {
+ brd->info = NULL;
+ continue;
+ }
- brd->idx = m * MXSER_PORTS_PER_BOARD;
- for (i = 0; i < brd->info->nports; i++)
- tty_register_device(mxvar_sdriver, brd->idx + i,
- NULL);
+ brd->idx = m * MXSER_PORTS_PER_BOARD;
+ for (i = 0; i < brd->info->nports; i++)
+ tty_register_device(mxvar_sdriver, brd->idx + i, NULL);
- m++;
- }
+ m++;
+ }
retval = pci_register_driver(&mxser_driver);
if (retval) {
- printk(KERN_ERR "Can't register pci driver\n");
+ printk(KERN_ERR "mxser: can't register pci driver\n");
if (!m) {
retval = -ENODEV;
goto err_unr;
} /* else: we have some ISA cards under control */
}
- pr_debug("Done.\n");
-
return 0;
err_unr:
tty_unregister_driver(mxvar_sdriver);
@@ -2919,8 +2831,6 @@ static void __exit mxser_module_exit(void)
{
unsigned int i, j;
- pr_debug("Unloading module mxser ...\n");
-
pci_unregister_driver(&mxser_driver);
for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */
@@ -2934,8 +2844,6 @@ static void __exit mxser_module_exit(void)
for (i = 0; i < MXSER_BOARDS; i++)
if (mxser_boards[i].info != NULL)
mxser_release_res(&mxser_boards[i], NULL, 1);
-
- pr_debug("Done.\n");
}
module_init(mxser_module_init);
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index ed4e03333ab..69ec6399c71 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -677,6 +677,10 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
/* Allocate transmit buffer */
/* sleep until transmit buffer available */
while (!(tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list))) {
+ if (file->f_flags & O_NONBLOCK) {
+ error = -EAGAIN;
+ break;
+ }
schedule();
n_hdlc = tty2n_hdlc (tty);
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index a22662b6a1a..39f6357e3b5 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -107,7 +107,6 @@
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c
index ba012c2bdf7..f9f72a21129 100644
--- a/drivers/char/nwflash.c
+++ b/drivers/char/nwflash.c
@@ -122,35 +122,20 @@ static int flash_ioctl(struct inode *inodep, struct file *filep, unsigned int cm
static ssize_t flash_read(struct file *file, char __user *buf, size_t size,
loff_t *ppos)
{
- unsigned long p = *ppos;
- unsigned int count = size;
- int ret = 0;
+ ssize_t ret;
if (flashdebug)
printk(KERN_DEBUG "flash_read: flash_read: offset=0x%lX, "
"buffer=%p, count=0x%X.\n", p, buf, count);
+ /*
+ * We now lock against reads and writes. --rmk
+ */
+ if (mutex_lock_interruptible(&nwflash_mutex))
+ return -ERESTARTSYS;
- if (count)
- ret = -ENXIO;
-
- if (p < gbFlashSize) {
- if (count > gbFlashSize - p)
- count = gbFlashSize - p;
+ ret = simple_read_from_buffer(buf, size, ppos, FLASH_BASE, gbFlashSize);
+ mutex_unlock(&nwflash_mutex);
- /*
- * We now lock against reads and writes. --rmk
- */
- if (mutex_lock_interruptible(&nwflash_mutex))
- return -ERESTARTSYS;
-
- ret = copy_to_user(buf, (void *)(FLASH_BASE + p), count);
- if (ret == 0) {
- ret = count;
- *ppos += count;
- } else
- ret = -EFAULT;
- mutex_unlock(&nwflash_mutex);
- }
return ret;
}
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index e4a4fbd37d7..f070ae7bd91 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -1896,7 +1896,7 @@ static int cm4000_probe(struct pcmcia_device *link)
return ret;
}
- device_create(cmm_class, NULL, MKDEV(major, i), "cmm%d", i);
+ device_create_drvdata(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i);
return 0;
}
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 6181f8a9b0b..0b5934bef7a 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -653,7 +653,8 @@ static int reader_probe(struct pcmcia_device *link)
return ret;
}
- device_create(cmx_class, NULL, MKDEV(major, i), "cmx%d", i);
+ device_create_drvdata(cmx_class, NULL, MKDEV(major, i), NULL,
+ "cmx%d", i);
return 0;
}
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index b694d430f10..d1fceabe3ae 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -2230,7 +2230,7 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
* Arguments: tty pointer to tty instance data
* break_state -1=set break condition, 0=clear
*/
-static void mgslpc_break(struct tty_struct *tty, int break_state)
+static int mgslpc_break(struct tty_struct *tty, int break_state)
{
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
unsigned long flags;
@@ -2240,7 +2240,7 @@ static void mgslpc_break(struct tty_struct *tty, int break_state)
__FILE__,__LINE__, info->device_name, break_state);
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_break"))
- return;
+ return -EINVAL;
spin_lock_irqsave(&info->lock,flags);
if (break_state == -1)
@@ -2248,6 +2248,7 @@ static void mgslpc_break(struct tty_struct *tty, int break_state)
else
clear_reg_bits(info, CHA+DAFO, BIT6);
spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
}
/* Service an IOCTL request
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index f6e6acadd9a..bee39fdfba7 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -67,7 +67,7 @@
#include <linux/major.h>
#include <linux/ppdev.h>
#include <linux/smp_lock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#define PP_VERSION "ppdev: user-space parallel port driver"
#define CHRDEV "ppdev"
@@ -328,10 +328,9 @@ static enum ieee1284_phase init_phase (int mode)
return IEEE1284_PH_FWD_IDLE;
}
-static int pp_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- unsigned int minor = iminor(inode);
+ unsigned int minor = iminor(file->f_path.dentry->d_inode);
struct pp_struct *pp = file->private_data;
struct parport * port;
void __user *argp = (void __user *)arg;
@@ -634,6 +633,15 @@ static int pp_ioctl(struct inode *inode, struct file *file,
return 0;
}
+static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ long ret;
+ lock_kernel();
+ ret = pp_do_ioctl(file, cmd, arg);
+ unlock_kernel();
+ return ret;
+}
+
static int pp_open (struct inode * inode, struct file * file)
{
unsigned int minor = iminor(inode);
@@ -745,15 +753,16 @@ static const struct file_operations pp_fops = {
.read = pp_read,
.write = pp_write,
.poll = pp_poll,
- .ioctl = pp_ioctl,
+ .unlocked_ioctl = pp_ioctl,
.open = pp_open,
.release = pp_release,
};
static void pp_attach(struct parport *port)
{
- device_create(ppdev_class, port->dev, MKDEV(PP_MAJOR, port->number),
- "parport%d", port->number);
+ device_create_drvdata(ppdev_class, port->dev,
+ MKDEV(PP_MAJOR, port->number),
+ NULL, "parport%d", port->number);
}
static void pp_detach(struct parport *port)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 0cf98bd4f2d..e0d0e371909 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -236,6 +236,7 @@
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/interrupt.h>
+#include <linux/mm.h>
#include <linux/spinlock.h>
#include <linux/percpu.h>
#include <linux/cryptohash.h>
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 505fcbe884a..47b8cf281d4 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -131,8 +131,8 @@ raw_ioctl(struct inode *inode, struct file *filp,
static void bind_device(struct raw_config_request *rq)
{
device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
- device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
- "raw%d", rq->raw_minor);
+ device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
+ NULL, "raw%d", rq->raw_minor);
}
/*
@@ -283,7 +283,8 @@ static int __init raw_init(void)
ret = PTR_ERR(raw_class);
goto error_region;
}
- device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), "rawctl");
+ device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL,
+ "rawctl");
return 0;
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index 0cdfee15291..a8f68a3f14d 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -179,7 +179,7 @@ static int rio_set_real_termios(void *ptr);
static void rio_hungup(void *ptr);
static void rio_close(void *ptr);
static int rio_chars_in_buffer(void *ptr);
-static int rio_fw_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
+static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
static int rio_init_drivers(void);
static void my_hd(void *addr, int len);
@@ -240,7 +240,7 @@ static struct real_driver rio_real_driver = {
static const struct file_operations rio_fw_fops = {
.owner = THIS_MODULE,
- .ioctl = rio_fw_ioctl,
+ .unlocked_ioctl = rio_fw_ioctl,
};
static struct miscdevice rio_fw_device = {
@@ -560,13 +560,15 @@ static void rio_close(void *ptr)
-static int rio_fw_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int rc = 0;
func_enter();
/* The "dev" argument isn't used. */
+ lock_kernel();
rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN));
+ unlock_kernel();
func_exit();
return rc;
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 724b2b20f4b..2c6c8f33d6b 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -1250,11 +1250,15 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file,
return 0;
}
-static void rc_send_break(struct riscom_port *port, unsigned long length)
+static int rc_send_break(struct tty_struct *tty, int length)
{
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
struct riscom_board *bp = port_Board(port);
unsigned long flags;
+ if (length == 0 || length == -1)
+ return -EOPNOTSUPP;
+
spin_lock_irqsave(&riscom_lock, flags);
port->break_length = RISCOM_TPS / HZ * length;
@@ -1268,6 +1272,7 @@ static void rc_send_break(struct riscom_port *port, unsigned long length)
rc_wait_CCR(bp);
spin_unlock_irqrestore(&riscom_lock, flags);
+ return 0;
}
static int rc_set_serial_info(struct riscom_port *port,
@@ -1342,27 +1347,12 @@ static int rc_ioctl(struct tty_struct *tty, struct file *filp,
{
struct riscom_port *port = (struct riscom_port *)tty->driver_data;
void __user *argp = (void __user *)arg;
- int retval = 0;
+ int retval;
if (rc_paranoia_check(port, tty->name, "rc_ioctl"))
return -ENODEV;
switch (cmd) {
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- if (!arg)
- rc_send_break(port, HZ/4); /* 1/4 second */
- break;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- rc_send_break(port, arg ? arg*(HZ/10) : HZ/4);
- break;
case TIOCGSERIAL:
lock_kernel();
retval = rc_get_serial_info(port, argp);
@@ -1517,6 +1507,7 @@ static const struct tty_operations riscom_ops = {
.hangup = rc_hangup,
.tiocmget = rc_tiocmget,
.tiocmset = rc_tiocmset,
+ .break_ctl = rc_send_break,
};
static int __init rc_init_drivers(void)
@@ -1538,7 +1529,7 @@ static int __init rc_init_drivers(void)
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
riscom_driver->init_termios.c_ispeed = 9600;
riscom_driver->init_termios.c_ospeed = 9600;
- riscom_driver->flags = TTY_DRIVER_REAL_RAW;
+ riscom_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK;
tty_set_operations(riscom_driver, &riscom_ops);
error = tty_register_driver(riscom_driver);
if (error != 0) {
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index e670eae2f51..584d791e84a 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -1236,13 +1236,13 @@ static void rp_set_termios(struct tty_struct *tty,
}
}
-static void rp_break(struct tty_struct *tty, int break_state)
+static int rp_break(struct tty_struct *tty, int break_state)
{
struct r_port *info = (struct r_port *) tty->driver_data;
unsigned long flags;
if (rocket_paranoia_check(info, "rp_break"))
- return;
+ return -EINVAL;
spin_lock_irqsave(&info->slock, flags);
if (break_state == -1)
@@ -1250,6 +1250,7 @@ static void rp_break(struct tty_struct *tty, int break_state)
else
sClrBreak(&info->channel);
spin_unlock_irqrestore(&info->slock, flags);
+ return 0;
}
/*
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index fa92a8af5a5..dbefbb30ed4 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -78,9 +78,10 @@
#include <linux/wait.h>
#include <linux/bcd.h>
#include <linux/delay.h>
+#include <linux/smp_lock.h>
+#include <linux/uaccess.h>
#include <asm/current.h>
-#include <asm/uaccess.h>
#include <asm/system.h>
#ifdef CONFIG_X86
@@ -120,8 +121,6 @@ static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
return 0;
}
#endif
-#else
-extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
#endif
/*
@@ -144,8 +143,7 @@ static DEFINE_TIMER(rtc_irq_timer, rtc_dropped_irq, 0, 0);
static ssize_t rtc_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos);
-static int rtc_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
+static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
#ifdef RTC_IRQ
static unsigned int rtc_poll(struct file *file, poll_table *wait);
@@ -719,10 +717,13 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
&wtime, sizeof wtime) ? -EFAULT : 0;
}
-static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- return rtc_do_ioctl(cmd, arg, 0);
+ long ret;
+ lock_kernel();
+ ret = rtc_do_ioctl(cmd, arg, 0);
+ unlock_kernel();
+ return ret;
}
/*
@@ -915,7 +916,7 @@ static const struct file_operations rtc_fops = {
#ifdef RTC_IRQ
.poll = rtc_poll,
#endif
- .ioctl = rtc_ioctl,
+ .unlocked_ioctl = rtc_ioctl,
.open = rtc_open,
.release = rtc_release,
.fasync = rtc_fasync,
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 0b799ac1b04..3ce60df14c0 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -444,7 +444,8 @@ scdrv_init(void)
continue;
}
- device_create(snsc_class, NULL, dev, "%s", devname);
+ device_create_drvdata(snsc_class, NULL, dev, NULL,
+ "%s", devname);
ia64_sn_irtr_intr_enable(scd->scd_nasid,
0 /*ignored */ ,
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 037dc47e4cb..242fd46fda2 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -77,7 +77,7 @@
#include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/ioport.h>
@@ -92,7 +92,7 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/init.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "specialix_io8.h"
#include "cd1865.h"
@@ -110,9 +110,10 @@
static int sx_debug;
static int sx_rxfifo = SPECIALIX_RXFIFO;
+static int sx_rtscts;
#ifdef DEBUG
-#define dprintk(f, str...) if (sx_debug & f) printk (str)
+#define dprintk(f, str...) if (sx_debug & f) printk(str)
#else
#define dprintk(f, str...) /* nothing */
#endif
@@ -131,10 +132,8 @@ static int sx_rxfifo = SPECIALIX_RXFIFO;
#define SX_DEBUG_FIFO 0x0800
-#define func_enter() dprintk (SX_DEBUG_FLOW, "io8: enter %s\n",__func__)
-#define func_exit() dprintk (SX_DEBUG_FLOW, "io8: exit %s\n", __func__)
-
-#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
+#define func_enter() dprintk(SX_DEBUG_FLOW, "io8: enter %s\n", __func__)
+#define func_exit() dprintk(SX_DEBUG_FLOW, "io8: exit %s\n", __func__)
/* Configurable options: */
@@ -142,17 +141,6 @@ static int sx_rxfifo = SPECIALIX_RXFIFO;
/* Am I paranoid or not ? ;-) */
#define SPECIALIX_PARANOIA_CHECK
-/* Do I trust the IRQ from the card? (enabeling it doesn't seem to help)
- When the IRQ routine leaves the chip in a state that is keeps on
- requiring attention, the timer doesn't help either. */
-#undef SPECIALIX_TIMER
-
-#ifdef SPECIALIX_TIMER
-static int sx_poll = HZ;
-#endif
-
-
-
/*
* The following defines are mostly for testing purposes. But if you need
* some nice reporting in your syslog, you can define them also.
@@ -162,16 +150,6 @@ static int sx_poll = HZ;
-#ifdef CONFIG_SPECIALIX_RTSCTS
-#define SX_CRTSCTS(bla) 1
-#else
-#define SX_CRTSCTS(tty) C_CRTSCTS(tty)
-#endif
-
-
-/* Used to be outb (0xff, 0x80); */
-#define short_pause() udelay (1)
-
#define SPECIALIX_LEGAL_FLAGS \
(ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \
@@ -190,21 +168,14 @@ static struct specialix_board sx_board[SX_NBOARD] = {
static struct specialix_port sx_port[SX_NBOARD * SX_NPORT];
-#ifdef SPECIALIX_TIMER
-static struct timer_list missed_irq_timer;
-static irqreturn_t sx_interrupt(int irq, void * dev_id);
-#endif
-
-
-
-static inline int sx_paranoia_check(struct specialix_port const * port,
+static int sx_paranoia_check(struct specialix_port const *port,
char *name, const char *routine)
{
#ifdef SPECIALIX_PARANOIA_CHECK
- static const char *badmagic =
- KERN_ERR "sx: Warning: bad specialix port magic number for device %s in %s\n";
- static const char *badinfo =
- KERN_ERR "sx: Warning: null specialix port for device %s in %s\n";
+ static const char *badmagic = KERN_ERR
+ "sx: Warning: bad specialix port magic number for device %s in %s\n";
+ static const char *badinfo = KERN_ERR
+ "sx: Warning: null specialix port for device %s in %s\n";
if (!port) {
printk(badinfo, name, routine);
@@ -226,66 +197,69 @@ static inline int sx_paranoia_check(struct specialix_port const * port,
*/
/* Get board number from pointer */
-static inline int board_No (struct specialix_board * bp)
+static inline int board_No(struct specialix_board *bp)
{
return bp - sx_board;
}
/* Get port number from pointer */
-static inline int port_No (struct specialix_port const * port)
+static inline int port_No(struct specialix_port const *port)
{
return SX_PORT(port - sx_port);
}
/* Get pointer to board from pointer to port */
-static inline struct specialix_board * port_Board(struct specialix_port const * port)
+static inline struct specialix_board *port_Board(
+ struct specialix_port const *port)
{
return &sx_board[SX_BOARD(port - sx_port)];
}
/* Input Byte from CL CD186x register */
-static inline unsigned char sx_in(struct specialix_board * bp, unsigned short reg)
+static inline unsigned char sx_in(struct specialix_board *bp,
+ unsigned short reg)
{
bp->reg = reg | 0x80;
- outb (reg | 0x80, bp->base + SX_ADDR_REG);
- return inb (bp->base + SX_DATA_REG);
+ outb(reg | 0x80, bp->base + SX_ADDR_REG);
+ return inb(bp->base + SX_DATA_REG);
}
/* Output Byte to CL CD186x register */
-static inline void sx_out(struct specialix_board * bp, unsigned short reg,
+static inline void sx_out(struct specialix_board *bp, unsigned short reg,
unsigned char val)
{
bp->reg = reg | 0x80;
- outb (reg | 0x80, bp->base + SX_ADDR_REG);
- outb (val, bp->base + SX_DATA_REG);
+ outb(reg | 0x80, bp->base + SX_ADDR_REG);
+ outb(val, bp->base + SX_DATA_REG);
}
/* Input Byte from CL CD186x register */
-static inline unsigned char sx_in_off(struct specialix_board * bp, unsigned short reg)
+static inline unsigned char sx_in_off(struct specialix_board *bp,
+ unsigned short reg)
{
bp->reg = reg;
- outb (reg, bp->base + SX_ADDR_REG);
- return inb (bp->base + SX_DATA_REG);
+ outb(reg, bp->base + SX_ADDR_REG);
+ return inb(bp->base + SX_DATA_REG);
}
/* Output Byte to CL CD186x register */
-static inline void sx_out_off(struct specialix_board * bp, unsigned short reg,
- unsigned char val)
+static inline void sx_out_off(struct specialix_board *bp,
+ unsigned short reg, unsigned char val)
{
bp->reg = reg;
- outb (reg, bp->base + SX_ADDR_REG);
- outb (val, bp->base + SX_DATA_REG);
+ outb(reg, bp->base + SX_ADDR_REG);
+ outb(val, bp->base + SX_DATA_REG);
}
/* Wait for Channel Command Register ready */
-static inline void sx_wait_CCR(struct specialix_board * bp)
+static void sx_wait_CCR(struct specialix_board *bp)
{
unsigned long delay, flags;
unsigned char ccr;
@@ -296,7 +270,7 @@ static inline void sx_wait_CCR(struct specialix_board * bp)
spin_unlock_irqrestore(&bp->lock, flags);
if (!ccr)
return;
- udelay (1);
+ udelay(1);
}
printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
@@ -304,7 +278,7 @@ static inline void sx_wait_CCR(struct specialix_board * bp)
/* Wait for Channel Command Register ready */
-static inline void sx_wait_CCR_off(struct specialix_board * bp)
+static void sx_wait_CCR_off(struct specialix_board *bp)
{
unsigned long delay;
unsigned char crr;
@@ -316,7 +290,7 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp)
spin_unlock_irqrestore(&bp->lock, flags);
if (!crr)
return;
- udelay (1);
+ udelay(1);
}
printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
@@ -327,7 +301,7 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp)
* specialix IO8+ IO range functions.
*/
-static inline int sx_request_io_range(struct specialix_board * bp)
+static int sx_request_io_range(struct specialix_board *bp)
{
return request_region(bp->base,
bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE,
@@ -335,15 +309,15 @@ static inline int sx_request_io_range(struct specialix_board * bp)
}
-static inline void sx_release_io_range(struct specialix_board * bp)
+static void sx_release_io_range(struct specialix_board *bp)
{
- release_region(bp->base,
- bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE);
+ release_region(bp->base, bp->flags & SX_BOARD_IS_PCI ?
+ SX_PCI_IO_SPACE : SX_IO_SPACE);
}
/* Set the IRQ using the RTS lines that run to the PAL on the board.... */
-static int sx_set_irq ( struct specialix_board *bp)
+static int sx_set_irq(struct specialix_board *bp)
{
int virq;
int i;
@@ -353,15 +327,24 @@ static int sx_set_irq ( struct specialix_board *bp)
return 1;
switch (bp->irq) {
/* In the same order as in the docs... */
- case 15: virq = 0;break;
- case 12: virq = 1;break;
- case 11: virq = 2;break;
- case 9: virq = 3;break;
- default: printk (KERN_ERR "Speclialix: cannot set irq to %d.\n", bp->irq);
- return 0;
+ case 15:
+ virq = 0;
+ break;
+ case 12:
+ virq = 1;
+ break;
+ case 11:
+ virq = 2;
+ break;
+ case 9:
+ virq = 3;
+ break;
+ default:printk(KERN_ERR
+ "Speclialix: cannot set irq to %d.\n", bp->irq);
+ return 0;
}
spin_lock_irqsave(&bp->lock, flags);
- for (i=0;i<2;i++) {
+ for (i = 0; i < 2; i++) {
sx_out(bp, CD186x_CAR, i);
sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0);
}
@@ -371,7 +354,7 @@ static int sx_set_irq ( struct specialix_board *bp)
/* Reset and setup CD186x chip */
-static int sx_init_CD186x(struct specialix_board * bp)
+static int sx_init_CD186x(struct specialix_board *bp)
{
unsigned long flags;
int scaler;
@@ -390,7 +373,7 @@ static int sx_init_CD186x(struct specialix_board * bp)
sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT); /* Prio for transmitter intr */
sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */
/* Set RegAckEn */
- sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN);
+ sx_out_off(bp, CD186x_SRCR, sx_in(bp, CD186x_SRCR) | SRCR_REGACKEN);
/* Setting up prescaler. We need 4 ticks per 1 ms */
scaler = SX_OSCFREQ/SPECIALIX_TPS;
@@ -399,9 +382,9 @@ static int sx_init_CD186x(struct specialix_board * bp)
sx_out_off(bp, CD186x_PPRL, scaler & 0xff);
spin_unlock_irqrestore(&bp->lock, flags);
- if (!sx_set_irq (bp)) {
+ if (!sx_set_irq(bp)) {
/* Figure out how to pass this along... */
- printk (KERN_ERR "Cannot set irq to %d.\n", bp->irq);
+ printk(KERN_ERR "Cannot set irq to %d.\n", bp->irq);
rv = 0;
}
@@ -410,16 +393,16 @@ static int sx_init_CD186x(struct specialix_board * bp)
}
-static int read_cross_byte (struct specialix_board *bp, int reg, int bit)
+static int read_cross_byte(struct specialix_board *bp, int reg, int bit)
{
int i;
int t;
unsigned long flags;
spin_lock_irqsave(&bp->lock, flags);
- for (i=0, t=0;i<8;i++) {
- sx_out_off (bp, CD186x_CAR, i);
- if (sx_in_off (bp, reg) & bit)
+ for (i = 0, t = 0; i < 8; i++) {
+ sx_out_off(bp, CD186x_CAR, i);
+ if (sx_in_off(bp, reg) & bit)
t |= 1 << i;
}
spin_unlock_irqrestore(&bp->lock, flags);
@@ -428,37 +411,10 @@ static int read_cross_byte (struct specialix_board *bp, int reg, int bit)
}
-#ifdef SPECIALIX_TIMER
-void missed_irq (unsigned long data)
-{
- unsigned char irq;
- unsigned long flags;
- struct specialix_board *bp = (struct specialix_board *)data;
-
- spin_lock_irqsave(&bp->lock, flags);
- irq = sx_in ((struct specialix_board *)data, CD186x_SRSR) &
- (SRSR_RREQint |
- SRSR_TREQint |
- SRSR_MREQint);
- spin_unlock_irqrestore(&bp->lock, flags);
- if (irq) {
- printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
- sx_interrupt (-1, bp);
- }
- mod_timer(&missed_irq_timer, jiffies + sx_poll);
-}
-#endif
-
-
-
/* Main probing routine, also sets irq. */
static int sx_probe(struct specialix_board *bp)
{
unsigned char val1, val2;
-#if 0
- int irqs = 0;
- int retries;
-#endif
int rev;
int chip;
@@ -471,17 +427,18 @@ static int sx_probe(struct specialix_board *bp)
/* Are the I/O ports here ? */
sx_out_off(bp, CD186x_PPRL, 0x5a);
- short_pause ();
+ udelay(1);
val1 = sx_in_off(bp, CD186x_PPRL);
sx_out_off(bp, CD186x_PPRL, 0xa5);
- short_pause ();
+ udelay(1);
val2 = sx_in_off(bp, CD186x_PPRL);
- if ((val1 != 0x5a) || (val2 != 0xa5)) {
- printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n",
- board_No(bp), bp->base);
+ if (val1 != 0x5a || val2 != 0xa5) {
+ printk(KERN_INFO
+ "sx%d: specialix IO8+ Board at 0x%03x not found.\n",
+ board_No(bp), bp->base);
sx_release_io_range(bp);
func_exit();
return 1;
@@ -489,10 +446,11 @@ static int sx_probe(struct specialix_board *bp)
/* Check the DSR lines that Specialix uses as board
identification */
- val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR);
- val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS);
- dprintk (SX_DEBUG_INIT, "sx%d: DSR lines are: %02x, rts lines are: %02x\n",
- board_No(bp), val1, val2);
+ val1 = read_cross_byte(bp, CD186x_MSVR, MSVR_DSR);
+ val2 = read_cross_byte(bp, CD186x_MSVR, MSVR_RTS);
+ dprintk(SX_DEBUG_INIT,
+ "sx%d: DSR lines are: %02x, rts lines are: %02x\n",
+ board_No(bp), val1, val2);
/* They managed to switch the bit order between the docs and
the IO8+ card. The new PCI card now conforms to old docs.
@@ -500,7 +458,8 @@ static int sx_probe(struct specialix_board *bp)
old card. */
val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2;
if (val1 != val2) {
- printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
+ printk(KERN_INFO
+ "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
board_No(bp), val2, bp->base, val1);
sx_release_io_range(bp);
func_exit();
@@ -508,47 +467,6 @@ static int sx_probe(struct specialix_board *bp)
}
-#if 0
- /* It's time to find IRQ for this board */
- for (retries = 0; retries < 5 && irqs <= 0; retries++) {
- irqs = probe_irq_on();
- sx_init_CD186x(bp); /* Reset CD186x chip */
- sx_out(bp, CD186x_CAR, 2); /* Select port 2 */
- sx_wait_CCR(bp);
- sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */
- sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */
- msleep(50);
- irqs = probe_irq_off(irqs);
-
- dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR));
- dprintk (SX_DEBUG_INIT, "TRAR = %02x, ", sx_in(bp, CD186x_TRAR));
- dprintk (SX_DEBUG_INIT, "GIVR = %02x, ", sx_in(bp, CD186x_GIVR));
- dprintk (SX_DEBUG_INIT, "GICR = %02x, ", sx_in(bp, CD186x_GICR));
- dprintk (SX_DEBUG_INIT, "\n");
-
- /* Reset CD186x again */
- if (!sx_init_CD186x(bp)) {
- /* Hmmm. This is dead code anyway. */
- }
-
- dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n",
- val1, val2, val3);
-
- }
-
-#if 0
- if (irqs <= 0) {
- printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n",
- board_No(bp), bp->base);
- sx_release_io_range(bp);
- func_exit();
- return 1;
- }
-#endif
- printk (KERN_INFO "Started with irq=%d, but now have irq=%d.\n", bp->irq, irqs);
- if (irqs > 0)
- bp->irq = irqs;
-#endif
/* Reset CD186x again */
if (!sx_init_CD186x(bp)) {
sx_release_io_range(bp);
@@ -560,7 +478,7 @@ static int sx_probe(struct specialix_board *bp)
bp->flags |= SX_BOARD_PRESENT;
/* Chip revcode pkgtype
- GFRCR SRCR bit 7
+ GFRCR SRCR bit 7
CD180 rev B 0x81 0
CD180 rev C 0x82 0
CD1864 rev A 0x82 1
@@ -570,24 +488,32 @@ static int sx_probe(struct specialix_board *bp)
*/
switch (sx_in_off(bp, CD186x_GFRCR)) {
- case 0x82:chip = 1864;rev='A';break;
- case 0x83:chip = 1865;rev='A';break;
- case 0x84:chip = 1865;rev='B';break;
- case 0x85:chip = 1865;rev='C';break; /* Does not exist at this time */
- default:chip=-1;rev='x';
+ case 0x82:
+ chip = 1864;
+ rev = 'A';
+ break;
+ case 0x83:
+ chip = 1865;
+ rev = 'A';
+ break;
+ case 0x84:
+ chip = 1865;
+ rev = 'B';
+ break;
+ case 0x85:
+ chip = 1865;
+ rev = 'C';
+ break; /* Does not exist at this time */
+ default:
+ chip = -1;
+ rev = 'x';
}
- dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) );
-
-#ifdef SPECIALIX_TIMER
- setup_timer(&missed_irq_timer, missed_irq, (unsigned long)bp);
- mod_timer(&missed_irq_timer, jiffies + sx_poll);
-#endif
+ dprintk(SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR));
- printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
- board_No(bp),
- bp->base, bp->irq,
- chip, rev);
+ printk(KERN_INFO
+ "sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
+ board_No(bp), bp->base, bp->irq, chip, rev);
func_exit();
return 0;
@@ -598,20 +524,22 @@ static int sx_probe(struct specialix_board *bp)
* Interrupt processing routines.
* */
-static inline struct specialix_port * sx_get_port(struct specialix_board * bp,
- unsigned char const * what)
+static struct specialix_port *sx_get_port(struct specialix_board *bp,
+ unsigned char const *what)
{
unsigned char channel;
- struct specialix_port * port = NULL;
+ struct specialix_port *port = NULL;
channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF;
- dprintk (SX_DEBUG_CHAN, "channel: %d\n", channel);
+ dprintk(SX_DEBUG_CHAN, "channel: %d\n", channel);
if (channel < CD186x_NCH) {
port = &sx_port[board_No(bp) * SX_NPORT + channel];
- dprintk (SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n",board_No(bp) * SX_NPORT + channel, port, port->port.flags & ASYNC_INITIALIZED);
+ dprintk(SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n",
+ board_No(bp) * SX_NPORT + channel, port,
+ port->port.flags & ASYNC_INITIALIZED);
if (port->port.flags & ASYNC_INITIALIZED) {
- dprintk (SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
+ dprintk(SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
func_exit();
return port;
}
@@ -622,7 +550,7 @@ static inline struct specialix_port * sx_get_port(struct specialix_board * bp,
}
-static inline void sx_receive_exc(struct specialix_board * bp)
+static void sx_receive_exc(struct specialix_board *bp)
{
struct specialix_port *port;
struct tty_struct *tty;
@@ -633,7 +561,7 @@ static inline void sx_receive_exc(struct specialix_board * bp)
port = sx_get_port(bp, "Receive");
if (!port) {
- dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
+ dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n");
func_exit();
return;
}
@@ -641,19 +569,21 @@ static inline void sx_receive_exc(struct specialix_board * bp)
status = sx_in(bp, CD186x_RCSR);
- dprintk (SX_DEBUG_RX, "status: 0x%x\n", status);
+ dprintk(SX_DEBUG_RX, "status: 0x%x\n", status);
if (status & RCSR_OE) {
port->overrun++;
- dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Overrun. Total %ld overruns.\n",
- board_No(bp), port_No(port), port->overrun);
+ dprintk(SX_DEBUG_FIFO,
+ "sx%d: port %d: Overrun. Total %ld overruns.\n",
+ board_No(bp), port_No(port), port->overrun);
}
status &= port->mark_mask;
/* This flip buffer check needs to be below the reading of the
status register to reset the chip's IRQ.... */
if (tty_buffer_request_room(tty, 1) == 0) {
- dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Working around flip buffer overflow.\n",
- board_No(bp), port_No(port));
+ dprintk(SX_DEBUG_FIFO,
+ "sx%d: port %d: Working around flip buffer overflow.\n",
+ board_No(bp), port_No(port));
func_exit();
return;
}
@@ -664,8 +594,9 @@ static inline void sx_receive_exc(struct specialix_board * bp)
return;
}
if (status & RCSR_TOUT) {
- printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
- board_No(bp), port_No(port));
+ printk(KERN_INFO
+ "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
+ board_No(bp), port_No(port));
func_exit();
return;
@@ -688,13 +619,13 @@ static inline void sx_receive_exc(struct specialix_board * bp)
else
flag = TTY_NORMAL;
- if(tty_insert_flip_char(tty, ch, flag))
+ if (tty_insert_flip_char(tty, ch, flag))
tty_flip_buffer_push(tty);
func_exit();
}
-static inline void sx_receive(struct specialix_board * bp)
+static void sx_receive(struct specialix_board *bp)
{
struct specialix_port *port;
struct tty_struct *tty;
@@ -702,15 +633,16 @@ static inline void sx_receive(struct specialix_board * bp)
func_enter();
- if (!(port = sx_get_port(bp, "Receive"))) {
- dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
+ port = sx_get_port(bp, "Receive");
+ if (port == NULL) {
+ dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n");
func_exit();
return;
}
tty = port->port.tty;
count = sx_in(bp, CD186x_RDCR);
- dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
+ dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
port->hits[count > 8 ? 9 : count]++;
tty_buffer_request_room(tty, count);
@@ -722,18 +654,19 @@ static inline void sx_receive(struct specialix_board * bp)
}
-static inline void sx_transmit(struct specialix_board * bp)
+static void sx_transmit(struct specialix_board *bp)
{
struct specialix_port *port;
struct tty_struct *tty;
unsigned char count;
func_enter();
- if (!(port = sx_get_port(bp, "Transmit"))) {
+ port = sx_get_port(bp, "Transmit");
+ if (port == NULL) {
func_exit();
return;
}
- dprintk (SX_DEBUG_TX, "port: %p\n", port);
+ dprintk(SX_DEBUG_TX, "port: %p\n", port);
tty = port->port.tty;
if (port->IER & IER_TXEMPTY) {
@@ -765,7 +698,8 @@ static inline void sx_transmit(struct specialix_board * bp)
sx_out(bp, CD186x_TDR, CD186x_C_ESC);
sx_out(bp, CD186x_TDR, CD186x_C_DELAY);
sx_out(bp, CD186x_TDR, count);
- if (!(port->break_length -= count))
+ port->break_length -= count;
+ if (port->break_length == 0)
port->break_length--;
} else {
sx_out(bp, CD186x_TDR, CD186x_C_ESC);
@@ -794,36 +728,36 @@ static inline void sx_transmit(struct specialix_board * bp)
sx_out(bp, CD186x_IER, port->IER);
}
if (port->xmit_cnt <= port->wakeup_chars)
- tty_wakeup(tty);
+ tty_wakeup(tty);
func_exit();
}
-static inline void sx_check_modem(struct specialix_board * bp)
+static void sx_check_modem(struct specialix_board *bp)
{
struct specialix_port *port;
struct tty_struct *tty;
unsigned char mcr;
int msvr_cd;
- dprintk (SX_DEBUG_SIGNALS, "Modem intr. ");
- if (!(port = sx_get_port(bp, "Modem")))
+ dprintk(SX_DEBUG_SIGNALS, "Modem intr. ");
+ port = sx_get_port(bp, "Modem");
+ if (port == NULL)
return;
tty = port->port.tty;
mcr = sx_in(bp, CD186x_MCR);
- printk ("mcr = %02x.\n", mcr);
if ((mcr & MCR_CDCHG)) {
- dprintk (SX_DEBUG_SIGNALS, "CD just changed... ");
+ dprintk(SX_DEBUG_SIGNALS, "CD just changed... ");
msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD;
if (msvr_cd) {
- dprintk (SX_DEBUG_SIGNALS, "Waking up guys in open.\n");
+ dprintk(SX_DEBUG_SIGNALS, "Waking up guys in open.\n");
wake_up_interruptible(&port->port.open_wait);
} else {
- dprintk (SX_DEBUG_SIGNALS, "Sending HUP.\n");
+ dprintk(SX_DEBUG_SIGNALS, "Sending HUP.\n");
tty_hangup(tty);
}
}
@@ -874,9 +808,12 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id)
spin_lock_irqsave(&bp->lock, flags);
- dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
+ dprintk(SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__,
+ port_No(sx_get_port(bp, "INT")),
+ SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
if (!(bp->flags & SX_BOARD_ACTIVE)) {
- dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", bp->irq);
+ dprintk(SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n",
+ bp->irq);
spin_unlock_irqrestore(&bp->lock, flags);
func_exit();
return IRQ_NONE;
@@ -884,10 +821,11 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id)
saved_reg = bp->reg;
- while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) &
- (SRSR_RREQint |
- SRSR_TREQint |
- SRSR_MREQint)))) {
+ while (++loop < 16) {
+ status = sx_in(bp, CD186x_SRSR) &
+ (SRSR_RREQint | SRSR_TREQint | SRSR_MREQint);
+ if (status == 0)
+ break;
if (status & SRSR_RREQint) {
ack = sx_in(bp, CD186x_RRAR);
@@ -896,8 +834,9 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id)
else if (ack == (SX_ID | GIVR_IT_REXC))
sx_receive_exc(bp);
else
- printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
- board_No(bp), status, ack);
+ printk(KERN_ERR
+ "sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
+ board_No(bp), status, ack);
} else if (status & SRSR_TREQint) {
ack = sx_in(bp, CD186x_TRAR);
@@ -906,14 +845,16 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id)
sx_transmit(bp);
else
printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n",
- board_No(bp), status, ack, port_No (sx_get_port (bp, "Int")));
+ board_No(bp), status, ack,
+ port_No(sx_get_port(bp, "Int")));
} else if (status & SRSR_MREQint) {
ack = sx_in(bp, CD186x_MRAR);
if (ack == (SX_ID | GIVR_IT_MODEM))
sx_check_modem(bp);
else
- printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
+ printk(KERN_ERR
+ "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
board_No(bp), status, ack);
}
@@ -921,7 +862,7 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id)
sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */
}
bp->reg = saved_reg;
- outb (bp->reg, bp->base + SX_ADDR_REG);
+ outb(bp->reg, bp->base + SX_ADDR_REG);
spin_unlock_irqrestore(&bp->lock, flags);
func_exit();
return IRQ_HANDLED;
@@ -932,36 +873,26 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id)
* Routines for open & close processing.
*/
-static void turn_ints_off (struct specialix_board *bp)
+static void turn_ints_off(struct specialix_board *bp)
{
unsigned long flags;
func_enter();
- if (bp->flags & SX_BOARD_IS_PCI) {
- /* This was intended for enabeling the interrupt on the
- * PCI card. However it seems that it's already enabled
- * and as PCI interrupts can be shared, there is no real
- * reason to have to turn it off. */
- }
-
spin_lock_irqsave(&bp->lock, flags);
- (void) sx_in_off (bp, 0); /* Turn off interrupts. */
+ (void) sx_in_off(bp, 0); /* Turn off interrupts. */
spin_unlock_irqrestore(&bp->lock, flags);
func_exit();
}
-static void turn_ints_on (struct specialix_board *bp)
+static void turn_ints_on(struct specialix_board *bp)
{
unsigned long flags;
func_enter();
- if (bp->flags & SX_BOARD_IS_PCI) {
- /* play with the PCI chip. See comment above. */
- }
spin_lock_irqsave(&bp->lock, flags);
- (void) sx_in (bp, 0); /* Turn ON interrupts. */
+ (void) sx_in(bp, 0); /* Turn ON interrupts. */
spin_unlock_irqrestore(&bp->lock, flags);
func_exit();
@@ -969,7 +900,7 @@ static void turn_ints_on (struct specialix_board *bp)
/* Called with disabled interrupts */
-static inline int sx_setup_board(struct specialix_board * bp)
+static int sx_setup_board(struct specialix_board *bp)
{
int error;
@@ -977,14 +908,16 @@ static inline int sx_setup_board(struct specialix_board * bp)
return 0;
if (bp->flags & SX_BOARD_IS_PCI)
- error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp);
+ error = request_irq(bp->irq, sx_interrupt,
+ IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp);
else
- error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED, "specialix IO8+", bp);
+ error = request_irq(bp->irq, sx_interrupt,
+ IRQF_DISABLED, "specialix IO8+", bp);
if (error)
return error;
- turn_ints_on (bp);
+ turn_ints_on(bp);
bp->flags |= SX_BOARD_ACTIVE;
return 0;
@@ -992,7 +925,7 @@ static inline int sx_setup_board(struct specialix_board * bp)
/* Called with disabled interrupts */
-static inline void sx_shutdown_board(struct specialix_board *bp)
+static void sx_shutdown_board(struct specialix_board *bp)
{
func_enter();
@@ -1003,22 +936,26 @@ static inline void sx_shutdown_board(struct specialix_board *bp)
bp->flags &= ~SX_BOARD_ACTIVE;
- dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
- bp->irq, board_No (bp));
+ dprintk(SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
+ bp->irq, board_No(bp));
free_irq(bp->irq, bp);
-
- turn_ints_off (bp);
-
-
+ turn_ints_off(bp);
func_exit();
}
+static unsigned int sx_crtscts(struct tty_struct *tty)
+{
+ if (sx_rtscts)
+ return C_CRTSCTS(tty);
+ return 1;
+}
/*
* Setting up port characteristics.
* Must be called with disabled interrupts
*/
-static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port)
+static void sx_change_speed(struct specialix_board *bp,
+ struct specialix_port *port)
{
struct tty_struct *tty;
unsigned long baud;
@@ -1030,7 +967,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
func_enter();
- if (!(tty = port->port.tty) || !tty->termios) {
+ tty = port->port.tty;
+ if (!tty || !tty->termios) {
func_exit();
return;
}
@@ -1043,12 +981,12 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
/* The Specialix board doens't implement the RTS lines.
They are used to set the IRQ level. Don't touch them. */
- if (SX_CRTSCTS(tty))
+ if (sx_crtscts(tty))
port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
else
port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
spin_unlock_irqrestore(&bp->lock, flags);
- dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
+ dprintk(SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
baud = tty_get_baud_rate(tty);
if (baud == 38400) {
@@ -1060,21 +998,19 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
if (!baud) {
/* Drop DTR & exit */
- dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n");
- if (!SX_CRTSCTS (tty)) {
- port -> MSVR &= ~ MSVR_DTR;
+ dprintk(SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n");
+ if (!sx_crtscts(tty)) {
+ port->MSVR &= ~MSVR_DTR;
spin_lock_irqsave(&bp->lock, flags);
- sx_out(bp, CD186x_MSVR, port->MSVR );
+ sx_out(bp, CD186x_MSVR, port->MSVR);
spin_unlock_irqrestore(&bp->lock, flags);
- }
- else
- dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
+ } else
+ dprintk(SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
return;
} else {
/* Set DTR on */
- if (!SX_CRTSCTS (tty)) {
- port ->MSVR |= MSVR_DTR;
- }
+ if (!sx_crtscts(tty))
+ port->MSVR |= MSVR_DTR;
}
/*
@@ -1083,28 +1019,27 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
/* Set baud rate for port */
tmp = port->custom_divisor ;
- if ( tmp )
- printk (KERN_INFO "sx%d: Using custom baud rate divisor %ld. \n"
- "This is an untested option, please be carefull.\n",
- port_No (port), tmp);
+ if (tmp)
+ printk(KERN_INFO
+ "sx%d: Using custom baud rate divisor %ld. \n"
+ "This is an untested option, please be careful.\n",
+ port_No(port), tmp);
else
- tmp = (((SX_OSCFREQ + baud/2) / baud +
- CD186x_TPC/2) / CD186x_TPC);
+ tmp = (((SX_OSCFREQ + baud/2) / baud + CD186x_TPC/2) /
+ CD186x_TPC);
- if ((tmp < 0x10) && time_before(again, jiffies)) {
+ if (tmp < 0x10 && time_before(again, jiffies)) {
again = jiffies + HZ * 60;
/* Page 48 of version 2.0 of the CL-CD1865 databook */
if (tmp >= 12) {
- printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
- "Performance degradation is possible.\n"
- "Read specialix.txt for more info.\n",
- port_No (port), tmp);
+ printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
+ "Performance degradation is possible.\n"
+ "Read specialix.txt for more info.\n",
+ port_No(port), tmp);
} else {
- printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
- "Warning: overstressing Cirrus chip. "
- "This might not work.\n"
- "Read specialix.txt for more info.\n",
- port_No (port), tmp);
+ printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
+ "Warning: overstressing Cirrus chip. This might not work.\n"
+ "Read specialix.txt for more info.\n", port_No(port), tmp);
}
}
spin_lock_irqsave(&bp->lock, flags);
@@ -1114,7 +1049,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
sx_out(bp, CD186x_TBPRL, tmp & 0xff);
spin_unlock_irqrestore(&bp->lock, flags);
if (port->custom_divisor)
- baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor;
+ baud = (SX_OSCFREQ + port->custom_divisor/2) /
+ port->custom_divisor;
baud = (baud + 5) / 10; /* Estimated CPS */
/* Two timer ticks seems enough to wakeup something like SLIP driver */
@@ -1129,16 +1065,16 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
sx_out(bp, CD186x_RTPR, tmp);
spin_unlock_irqrestore(&bp->lock, flags);
switch (C_CSIZE(tty)) {
- case CS5:
+ case CS5:
cor1 |= COR1_5BITS;
break;
- case CS6:
+ case CS6:
cor1 |= COR1_6BITS;
break;
- case CS7:
+ case CS7:
cor1 |= COR1_7BITS;
break;
- case CS8:
+ case CS8:
cor1 |= COR1_8BITS;
break;
}
@@ -1175,7 +1111,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
spin_lock_irqsave(&bp->lock, flags);
- tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR));
+ tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) &
+ (MSVR_CTS|MSVR_DSR));
spin_unlock_irqrestore(&bp->lock, flags);
#else
port->COR2 |= COR2_CTSAE;
@@ -1219,7 +1156,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
/* Setting up modem option registers */
- dprintk (SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", mcor1, mcor2);
+ dprintk(SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n",
+ mcor1, mcor2);
sx_out(bp, CD186x_MCOR1, mcor1);
sx_out(bp, CD186x_MCOR2, mcor2);
spin_unlock_irqrestore(&bp->lock, flags);
@@ -1238,7 +1176,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
/* Must be called with interrupts enabled */
-static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port)
+static int sx_setup_port(struct specialix_board *bp,
+ struct specialix_port *port)
{
unsigned long flags;
@@ -1253,7 +1192,8 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port
/* We may sleep in get_zeroed_page() */
unsigned long tmp;
- if (!(tmp = get_zeroed_page(GFP_KERNEL))) {
+ tmp = get_zeroed_page(GFP_KERNEL);
+ if (tmp == 0L) {
func_exit();
return -ENOMEM;
}
@@ -1284,7 +1224,8 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port
/* Must be called with interrupts disabled */
-static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *port)
+static void sx_shutdown_port(struct specialix_board *bp,
+ struct specialix_port *port)
{
struct tty_struct *tty;
int i;
@@ -1298,11 +1239,11 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *
}
if (sx_debug & SX_DEBUG_FIFO) {
- dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ",
- board_No(bp), port_No(port), port->overrun);
- for (i = 0; i < 10; i++) {
+ dprintk(SX_DEBUG_FIFO,
+ "sx%d: port %d: %ld overruns, FIFO hits [ ",
+ board_No(bp), port_No(port), port->overrun);
+ for (i = 0; i < 10; i++)
dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]);
- }
dprintk(SX_DEBUG_FIFO, "].\n");
}
@@ -1315,7 +1256,8 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *
spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
- if (!(tty = port->port.tty) || C_HUPCL(tty)) {
+ tty = port->port.tty;
+ if (tty == NULL || C_HUPCL(tty)) {
/* Drop DTR */
sx_out(bp, CD186x_MSVDTR, 0);
}
@@ -1338,8 +1280,8 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *
}
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
- struct specialix_port *port)
+static int block_til_ready(struct tty_struct *tty, struct file *filp,
+ struct specialix_port *port)
{
DECLARE_WAITQUEUE(wait, current);
struct specialix_board *bp = port_Board(port);
@@ -1389,23 +1331,22 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
retval = 0;
add_wait_queue(&port->port.open_wait, &wait);
spin_lock_irqsave(&port->lock, flags);
- if (!tty_hung_up_p(filp)) {
+ if (!tty_hung_up_p(filp))
port->port.count--;
- }
spin_unlock_irqrestore(&port->lock, flags);
port->port.blocked_open++;
while (1) {
spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
CD = sx_in(bp, CD186x_MSVR) & MSVR_CD;
- if (SX_CRTSCTS (tty)) {
+ if (sx_crtscts(tty)) {
/* Activate RTS */
port->MSVR |= MSVR_DTR; /* WTF? */
- sx_out (bp, CD186x_MSVR, port->MSVR);
+ sx_out(bp, CD186x_MSVR, port->MSVR);
} else {
/* Activate DTR */
port->MSVR |= MSVR_DTR;
- sx_out (bp, CD186x_MSVR, port->MSVR);
+ sx_out(bp, CD186x_MSVR, port->MSVR);
}
spin_unlock_irqrestore(&bp->lock, flags);
set_current_state(TASK_INTERRUPTIBLE);
@@ -1430,9 +1371,8 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
set_current_state(TASK_RUNNING);
remove_wait_queue(&port->port.open_wait, &wait);
spin_lock_irqsave(&port->lock, flags);
- if (!tty_hung_up_p(filp)) {
+ if (!tty_hung_up_p(filp))
port->port.count++;
- }
port->port.blocked_open--;
spin_unlock_irqrestore(&port->lock, flags);
if (retval) {
@@ -1446,12 +1386,12 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
}
-static int sx_open(struct tty_struct * tty, struct file * filp)
+static int sx_open(struct tty_struct *tty, struct file *filp)
{
int board;
int error;
- struct specialix_port * port;
- struct specialix_board * bp;
+ struct specialix_port *port;
+ struct specialix_board *bp;
int i;
unsigned long flags;
@@ -1468,17 +1408,19 @@ static int sx_open(struct tty_struct * tty, struct file * filp)
port = sx_port + board * SX_NPORT + SX_PORT(tty->index);
port->overrun = 0;
for (i = 0; i < 10; i++)
- port->hits[i]=0;
+ port->hits[i] = 0;
- dprintk (SX_DEBUG_OPEN, "Board = %d, bp = %p, port = %p, portno = %d.\n",
- board, bp, port, SX_PORT(tty->index));
+ dprintk(SX_DEBUG_OPEN,
+ "Board = %d, bp = %p, port = %p, portno = %d.\n",
+ board, bp, port, SX_PORT(tty->index));
if (sx_paranoia_check(port, tty->name, "sx_open")) {
func_enter();
return -ENODEV;
}
- if ((error = sx_setup_board(bp))) {
+ error = sx_setup_board(bp);
+ if (error) {
func_exit();
return error;
}
@@ -1490,12 +1432,14 @@ static int sx_open(struct tty_struct * tty, struct file * filp)
port->port.tty = tty;
spin_unlock_irqrestore(&bp->lock, flags);
- if ((error = sx_setup_port(bp, port))) {
+ error = sx_setup_port(bp, port);
+ if (error) {
func_enter();
return error;
}
- if ((error = block_til_ready(tty, filp, port))) {
+ error = block_til_ready(tty, filp, port);
+ if (error) {
func_enter();
return error;
}
@@ -1508,7 +1452,7 @@ static void sx_flush_buffer(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
unsigned long flags;
- struct specialix_board * bp;
+ struct specialix_board *bp;
func_enter();
@@ -1526,9 +1470,9 @@ static void sx_flush_buffer(struct tty_struct *tty)
func_exit();
}
-static void sx_close(struct tty_struct * tty, struct file * filp)
+static void sx_close(struct tty_struct *tty, struct file *filp)
{
- struct specialix_port *port = (struct specialix_port *) tty->driver_data;
+ struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
unsigned long flags;
unsigned long timeout;
@@ -1547,7 +1491,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
}
bp = port_Board(port);
- if ((tty->count == 1) && (port->port.count != 1)) {
+ if (tty->count == 1 && port->port.count != 1) {
printk(KERN_ERR "sx%d: sx_close: bad port count;"
" tty->count is 1, port count is %d\n",
board_No(bp), port->port.count);
@@ -1570,17 +1514,16 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
*/
tty->closing = 1;
spin_unlock_irqrestore(&port->lock, flags);
- dprintk (SX_DEBUG_OPEN, "Closing\n");
- if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) {
+ dprintk(SX_DEBUG_OPEN, "Closing\n");
+ if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, port->port.closing_wait);
- }
/*
* At this point we stop accepting input. To do this, we
* disable the receive line status interrupts, and tell the
* interrupt driver to stop checking the data ready bit in the
* line status register.
*/
- dprintk (SX_DEBUG_OPEN, "Closed\n");
+ dprintk(SX_DEBUG_OPEN, "Closed\n");
port->IER &= ~IER_RXD;
if (port->port.flags & ASYNC_INITIALIZED) {
port->IER &= ~IER_TXRDY;
@@ -1595,11 +1538,11 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
* important if there is a transmit FIFO!
*/
timeout = jiffies+HZ;
- while(port->IER & IER_TXEMPTY) {
- set_current_state (TASK_INTERRUPTIBLE);
+ while (port->IER & IER_TXEMPTY) {
+ set_current_state(TASK_INTERRUPTIBLE);
msleep_interruptible(jiffies_to_msecs(port->timeout));
if (time_after(jiffies, timeout)) {
- printk (KERN_INFO "Timeout waiting for close\n");
+ printk(KERN_INFO "Timeout waiting for close\n");
break;
}
}
@@ -1607,13 +1550,15 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
}
if (--bp->count < 0) {
- printk(KERN_ERR "sx%d: sx_shutdown_port: bad board count: %d port: %d\n",
- board_No(bp), bp->count, tty->index);
+ printk(KERN_ERR
+ "sx%d: sx_shutdown_port: bad board count: %d port: %d\n",
+ board_No(bp), bp->count, tty->index);
bp->count = 0;
}
if (--port->port.count < 0) {
- printk(KERN_ERR "sx%d: sx_close: bad port count for tty%d: %d\n",
- board_No(bp), port_No(port), port->port.count);
+ printk(KERN_ERR
+ "sx%d: sx_close: bad port count for tty%d: %d\n",
+ board_No(bp), port_No(port), port->port.count);
port->port.count = 0;
}
@@ -1625,9 +1570,9 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
port->port.tty = NULL;
spin_unlock_irqrestore(&port->lock, flags);
if (port->port.blocked_open) {
- if (port->port.close_delay) {
- msleep_interruptible(jiffies_to_msecs(port->port.close_delay));
- }
+ if (port->port.close_delay)
+ msleep_interruptible(
+ jiffies_to_msecs(port->port.close_delay));
wake_up_interruptible(&port->port.open_wait);
}
port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
@@ -1637,8 +1582,8 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
}
-static int sx_write(struct tty_struct * tty,
- const unsigned char *buf, int count)
+static int sx_write(struct tty_struct *tty,
+ const unsigned char *buf, int count)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
@@ -1690,11 +1635,11 @@ static int sx_write(struct tty_struct * tty,
}
-static int sx_put_char(struct tty_struct * tty, unsigned char ch)
+static int sx_put_char(struct tty_struct *tty, unsigned char ch)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
unsigned long flags;
- struct specialix_board * bp;
+ struct specialix_board *bp;
func_enter();
@@ -1702,7 +1647,7 @@ static int sx_put_char(struct tty_struct * tty, unsigned char ch)
func_exit();
return 0;
}
- dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
+ dprintk(SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
if (!port->xmit_buf) {
func_exit();
return 0;
@@ -1710,14 +1655,15 @@ static int sx_put_char(struct tty_struct * tty, unsigned char ch)
bp = port_Board(port);
spin_lock_irqsave(&port->lock, flags);
- dprintk (SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", port->xmit_cnt, port->xmit_buf);
- if ((port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) || (!port->xmit_buf)) {
+ dprintk(SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n",
+ port->xmit_cnt, port->xmit_buf);
+ if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1 || !port->xmit_buf) {
spin_unlock_irqrestore(&port->lock, flags);
- dprintk (SX_DEBUG_TX, "Exit size\n");
+ dprintk(SX_DEBUG_TX, "Exit size\n");
func_exit();
return 0;
}
- dprintk (SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
+ dprintk(SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
port->xmit_buf[port->xmit_head++] = ch;
port->xmit_head &= SERIAL_XMIT_SIZE - 1;
port->xmit_cnt++;
@@ -1728,11 +1674,11 @@ static int sx_put_char(struct tty_struct * tty, unsigned char ch)
}
-static void sx_flush_chars(struct tty_struct * tty)
+static void sx_flush_chars(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
unsigned long flags;
- struct specialix_board * bp = port_Board(port);
+ struct specialix_board *bp = port_Board(port);
func_enter();
@@ -1755,7 +1701,7 @@ static void sx_flush_chars(struct tty_struct * tty)
}
-static int sx_write_room(struct tty_struct * tty)
+static int sx_write_room(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
int ret;
@@ -1790,12 +1736,10 @@ static int sx_chars_in_buffer(struct tty_struct *tty)
return port->xmit_cnt;
}
-
-
static int sx_tiocmget(struct tty_struct *tty, struct file *file)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
- struct specialix_board * bp;
+ struct specialix_board *bp;
unsigned char status;
unsigned int result;
unsigned long flags;
@@ -1808,25 +1752,23 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file)
}
bp = port_Board(port);
- spin_lock_irqsave (&bp->lock, flags);
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
status = sx_in(bp, CD186x_MSVR);
spin_unlock_irqrestore(&bp->lock, flags);
- dprintk (SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n",
- port_No(port), status, sx_in (bp, CD186x_CAR));
- dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
- if (SX_CRTSCTS(port->port.tty)) {
- result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */
- | ((status & MSVR_DTR) ? TIOCM_RTS : 0)
- | ((status & MSVR_CD) ? TIOCM_CAR : 0)
- |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
- | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
+ dprintk(SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n",
+ port_No(port), status, sx_in(bp, CD186x_CAR));
+ dprintk(SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
+ if (sx_crtscts(port->port.tty)) {
+ result = TIOCM_DTR | TIOCM_DSR
+ | ((status & MSVR_DTR) ? TIOCM_RTS : 0)
+ | ((status & MSVR_CD) ? TIOCM_CAR : 0)
+ | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
} else {
- result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */
- | ((status & MSVR_DTR) ? TIOCM_DTR : 0)
- | ((status & MSVR_CD) ? TIOCM_CAR : 0)
- |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
- | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
+ result = TIOCM_RTS | TIOCM_DSR
+ | ((status & MSVR_DTR) ? TIOCM_DTR : 0)
+ | ((status & MSVR_CD) ? TIOCM_CAR : 0)
+ | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
}
func_exit();
@@ -1852,24 +1794,14 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file,
bp = port_Board(port);
spin_lock_irqsave(&port->lock, flags);
- /* if (set & TIOCM_RTS)
- port->MSVR |= MSVR_RTS; */
- /* if (set & TIOCM_DTR)
- port->MSVR |= MSVR_DTR; */
-
- if (SX_CRTSCTS(port->port.tty)) {
+ if (sx_crtscts(port->port.tty)) {
if (set & TIOCM_RTS)
port->MSVR |= MSVR_DTR;
} else {
if (set & TIOCM_DTR)
port->MSVR |= MSVR_DTR;
}
-
- /* if (clear & TIOCM_RTS)
- port->MSVR &= ~MSVR_RTS; */
- /* if (clear & TIOCM_DTR)
- port->MSVR &= ~MSVR_DTR; */
- if (SX_CRTSCTS(port->port.tty)) {
+ if (sx_crtscts(port->port.tty)) {
if (clear & TIOCM_RTS)
port->MSVR &= ~MSVR_DTR;
} else {
@@ -1886,14 +1818,17 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file,
}
-static inline void sx_send_break(struct specialix_port * port, unsigned long length)
+static int sx_send_break(struct tty_struct *tty, int length)
{
+ struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp = port_Board(port);
unsigned long flags;
func_enter();
+ if (length == 0 || length == -1)
+ return -EOPNOTSUPP;
- spin_lock_irqsave (&port->lock, flags);
+ spin_lock_irqsave(&port->lock, flags);
port->break_length = SPECIALIX_TPS / HZ * length;
port->COR2 |= COR2_ETC;
port->IER |= IER_TXRDY;
@@ -1902,7 +1837,7 @@ static inline void sx_send_break(struct specialix_port * port, unsigned long len
sx_out(bp, CD186x_COR2, port->COR2);
sx_out(bp, CD186x_IER, port->IER);
spin_unlock_irqrestore(&bp->lock, flags);
- spin_unlock_irqrestore (&port->lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);
sx_wait_CCR(bp);
spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CCR, CCR_CORCHG2);
@@ -1910,11 +1845,12 @@ static inline void sx_send_break(struct specialix_port * port, unsigned long len
sx_wait_CCR(bp);
func_exit();
+ return 0;
}
-static inline int sx_set_serial_info(struct specialix_port * port,
- struct serial_struct __user * newinfo)
+static int sx_set_serial_info(struct specialix_port *port,
+ struct serial_struct __user *newinfo)
{
struct serial_struct tmp;
struct specialix_board *bp = port_Board(port);
@@ -1943,25 +1879,25 @@ static inline int sx_set_serial_info(struct specialix_port * port,
return -EPERM;
}
port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
- (tmp.flags & ASYNC_USR_MASK));
+ (tmp.flags & ASYNC_USR_MASK));
port->custom_divisor = tmp.custom_divisor;
} else {
port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
- (tmp.flags & ASYNC_FLAGS));
+ (tmp.flags & ASYNC_FLAGS));
port->port.close_delay = tmp.close_delay;
port->port.closing_wait = tmp.closing_wait;
port->custom_divisor = tmp.custom_divisor;
}
- if (change_speed) {
+ if (change_speed)
sx_change_speed(bp, port);
- }
+
func_exit();
unlock_kernel();
return 0;
}
-static inline int sx_get_serial_info(struct specialix_port * port,
+static int sx_get_serial_info(struct specialix_port *port,
struct serial_struct __user *retinfo)
{
struct serial_struct tmp;
@@ -1992,11 +1928,10 @@ static inline int sx_get_serial_info(struct specialix_port * port,
}
-static int sx_ioctl(struct tty_struct * tty, struct file * filp,
- unsigned int cmd, unsigned long arg)
+static int sx_ioctl(struct tty_struct *tty, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
- int retval;
void __user *argp = (void __user *)arg;
func_enter();
@@ -2007,34 +1942,14 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp,
}
switch (cmd) {
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- retval = tty_check_change(tty);
- if (retval) {
- func_exit();
- return retval;
- }
- tty_wait_until_sent(tty, 0);
- if (!arg)
- sx_send_break(port, HZ/4); /* 1/4 second */
- return 0;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- retval = tty_check_change(tty);
- if (retval) {
- func_exit();
- return retval;
- }
- tty_wait_until_sent(tty, 0);
- sx_send_break(port, arg ? arg*(HZ/10) : HZ/4);
+ case TIOCGSERIAL:
func_exit();
- return 0;
- case TIOCGSERIAL:
- func_exit();
return sx_get_serial_info(port, argp);
- case TIOCSSERIAL:
- func_exit();
+ case TIOCSSERIAL:
+ func_exit();
return sx_set_serial_info(port, argp);
- default:
- func_exit();
+ default:
+ func_exit();
return -ENOIOCTLCMD;
}
func_exit();
@@ -2042,7 +1957,7 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp,
}
-static void sx_throttle(struct tty_struct * tty)
+static void sx_throttle(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
@@ -2058,15 +1973,16 @@ static void sx_throttle(struct tty_struct * tty)
bp = port_Board(port);
/* Use DTR instead of RTS ! */
- if (SX_CRTSCTS (tty))
+ if (sx_crtscts(tty))
port->MSVR &= ~MSVR_DTR;
else {
/* Auch!!! I think the system shouldn't call this then. */
/* Or maybe we're supposed (allowed?) to do our side of hw
handshake anyway, even when hardware handshake is off.
When you see this in your logs, please report.... */
- printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n",
- port_No (port));
+ printk(KERN_ERR
+ "sx%d: Need to throttle, but can't (hardware hs is off)\n",
+ port_No(port));
}
spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
@@ -2086,7 +2002,7 @@ static void sx_throttle(struct tty_struct * tty)
}
-static void sx_unthrottle(struct tty_struct * tty)
+static void sx_unthrottle(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
@@ -2103,9 +2019,9 @@ static void sx_unthrottle(struct tty_struct * tty)
spin_lock_irqsave(&port->lock, flags);
/* XXXX Use DTR INSTEAD???? */
- if (SX_CRTSCTS(tty)) {
+ if (sx_crtscts(tty))
port->MSVR |= MSVR_DTR;
- } /* Else clause: see remark in "sx_throttle"... */
+ /* Else clause: see remark in "sx_throttle"... */
spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
spin_unlock_irqrestore(&bp->lock, flags);
@@ -2127,7 +2043,7 @@ static void sx_unthrottle(struct tty_struct * tty)
}
-static void sx_stop(struct tty_struct * tty)
+static void sx_stop(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
@@ -2154,7 +2070,7 @@ static void sx_stop(struct tty_struct * tty)
}
-static void sx_start(struct tty_struct * tty)
+static void sx_start(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
@@ -2182,7 +2098,7 @@ static void sx_start(struct tty_struct * tty)
func_exit();
}
-static void sx_hangup(struct tty_struct * tty)
+static void sx_hangup(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
@@ -2201,8 +2117,9 @@ static void sx_hangup(struct tty_struct * tty)
spin_lock_irqsave(&port->lock, flags);
bp->count -= port->port.count;
if (bp->count < 0) {
- printk(KERN_ERR "sx%d: sx_hangup: bad board count: %d port: %d\n",
- board_No(bp), bp->count, tty->index);
+ printk(KERN_ERR
+ "sx%d: sx_hangup: bad board count: %d port: %d\n",
+ board_No(bp), bp->count, tty->index);
bp->count = 0;
}
port->port.count = 0;
@@ -2215,11 +2132,12 @@ static void sx_hangup(struct tty_struct * tty)
}
-static void sx_set_termios(struct tty_struct * tty, struct ktermios * old_termios)
+static void sx_set_termios(struct tty_struct *tty,
+ struct ktermios *old_termios)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
unsigned long flags;
- struct specialix_board * bp;
+ struct specialix_board *bp;
if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
return;
@@ -2254,6 +2172,7 @@ static const struct tty_operations sx_ops = {
.hangup = sx_hangup,
.tiocmget = sx_tiocmget,
.tiocmset = sx_tiocmset,
+ .break_ctl = sx_send_break,
};
static int sx_init_drivers(void)
@@ -2280,13 +2199,16 @@ static int sx_init_drivers(void)
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
specialix_driver->init_termios.c_ispeed = 9600;
specialix_driver->init_termios.c_ospeed = 9600;
- specialix_driver->flags = TTY_DRIVER_REAL_RAW;
+ specialix_driver->flags = TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_HARDWARE_BREAK;
tty_set_operations(specialix_driver, &sx_ops);
- if ((error = tty_register_driver(specialix_driver))) {
+ error = tty_register_driver(specialix_driver);
+ if (error) {
put_tty_driver(specialix_driver);
- printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n",
- error);
+ printk(KERN_ERR
+ "sx: Couldn't register specialix IO8+ driver, error = %d\n",
+ error);
func_exit();
return 1;
}
@@ -2322,11 +2244,11 @@ static int __init specialix_init(void)
printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n");
printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n");
-#ifdef CONFIG_SPECIALIX_RTSCTS
- printk (KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
-#else
- printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
-#endif
+ if (sx_rtscts)
+ printk(KERN_INFO
+ "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
+ else
+ printk(KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
for (i = 0; i < SX_NBOARD; i++)
spin_lock_init(&sx_board[i].lock);
@@ -2344,27 +2266,27 @@ static int __init specialix_init(void)
{
struct pci_dev *pdev = NULL;
- i=0;
+ i = 0;
while (i < SX_NBOARD) {
if (sx_board[i].flags & SX_BOARD_PRESENT) {
i++;
continue;
}
- pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
- PCI_DEVICE_ID_SPECIALIX_IO8,
- pdev);
- if (!pdev) break;
+ pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX,
+ PCI_DEVICE_ID_SPECIALIX_IO8, pdev);
+ if (!pdev)
+ break;
if (pci_enable_device(pdev))
continue;
sx_board[i].irq = pdev->irq;
- sx_board[i].base = pci_resource_start (pdev, 2);
+ sx_board[i].base = pci_resource_start(pdev, 2);
sx_board[i].flags |= SX_BOARD_IS_PCI;
if (!sx_probe(&sx_board[i]))
- found ++;
+ found++;
}
/* May exit pci_get sequence early with lots of boards */
if (pdev != NULL)
@@ -2384,16 +2306,13 @@ static int __init specialix_init(void)
}
static int iobase[SX_NBOARD] = {0,};
-
-static int irq [SX_NBOARD] = {0,};
+static int irq[SX_NBOARD] = {0,};
module_param_array(iobase, int, NULL, 0);
module_param_array(irq, int, NULL, 0);
module_param(sx_debug, int, 0);
+module_param(sx_rtscts, int, 0);
module_param(sx_rxfifo, int, 0);
-#ifdef SPECIALIX_TIMER
-module_param(sx_poll, int, 0);
-#endif
/*
* You can setup up to 4 boards.
@@ -2411,10 +2330,10 @@ static int __init specialix_init_module(void)
func_enter();
if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
- for(i = 0; i < SX_NBOARD; i++) {
+ for (i = 0; i < SX_NBOARD; i++) {
sx_board[i].base = iobase[i];
sx_board[i].irq = irq[i];
- sx_board[i].count= 0;
+ sx_board[i].count = 0;
}
}
@@ -2433,10 +2352,6 @@ static void __exit specialix_exit_module(void)
for (i = 0; i < SX_NBOARD; i++)
if (sx_board[i].flags & SX_BOARD_PRESENT)
sx_release_io_range(&sx_board[i]);
-#ifdef SPECIALIX_TIMER
- del_timer_sync(&missed_irq_timer);
-#endif
-
func_exit();
}
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 0243efb0be9..19db1eb87c2 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -1025,7 +1025,7 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count
/*****************************************************************************/
-static void stl_putchar(struct tty_struct *tty, unsigned char ch)
+static int stl_putchar(struct tty_struct *tty, unsigned char ch)
{
struct stlport *portp;
unsigned int len;
@@ -1034,12 +1034,12 @@ static void stl_putchar(struct tty_struct *tty, unsigned char ch)
pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
if (tty == NULL)
- return;
+ return -EINVAL;
portp = tty->driver_data;
if (portp == NULL)
- return;
+ return -EINVAL;
if (portp->tx.buf == NULL)
- return;
+ return -EINVAL;
head = portp->tx.head;
tail = portp->tx.tail;
@@ -1053,6 +1053,7 @@ static void stl_putchar(struct tty_struct *tty, unsigned char ch)
head = portp->tx.buf;
}
portp->tx.head = head;
+ return 0;
}
/*****************************************************************************/
@@ -1255,7 +1256,6 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file,
static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
{
struct stlport *portp;
- unsigned int ival;
int rc;
void __user *argp = (void __user *)arg;
@@ -1460,19 +1460,20 @@ static void stl_hangup(struct tty_struct *tty)
/*****************************************************************************/
-static void stl_breakctl(struct tty_struct *tty, int state)
+static int stl_breakctl(struct tty_struct *tty, int state)
{
struct stlport *portp;
pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
if (tty == NULL)
- return;
+ return -EINVAL;
portp = tty->driver_data;
if (portp == NULL)
- return;
+ return -EINVAL;
stl_sendbreak(portp, ((state == -1) ? 1 : 2));
+ return 0;
}
/*****************************************************************************/
@@ -4753,8 +4754,8 @@ static int __init stallion_module_init(void)
if (IS_ERR(stallion_class))
printk("STALLION: failed to create class\n");
for (i = 0; i < 4; i++)
- device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
- "staliomem%d", i);
+ device_create_drvdata(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
+ NULL, "staliomem%d", i);
return 0;
err_unrtty:
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index d5cffcd6a57..c385206f9db 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -286,8 +286,8 @@ static void sx_close(void *ptr);
static int sx_chars_in_buffer(void *ptr);
static int sx_init_board(struct sx_board *board);
static int sx_init_portstructs(int nboards, int nports);
-static int sx_fw_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
+static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg);
static int sx_init_drivers(void);
static struct tty_driver *sx_driver;
@@ -396,7 +396,7 @@ static struct real_driver sx_real_driver = {
static const struct file_operations sx_fw_fops = {
.owner = THIS_MODULE,
- .ioctl = sx_fw_ioctl,
+ .unlocked_ioctl = sx_fw_ioctl,
};
static struct miscdevice sx_fw_device = {
@@ -1686,10 +1686,10 @@ static int do_memtest_w(struct sx_board *board, int min, int max)
}
#endif
-static int sx_fw_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
{
- int rc = 0;
+ long rc = 0;
int __user *descr = (int __user *)arg;
int i;
static struct sx_board *board = NULL;
@@ -1699,13 +1699,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
func_enter();
-#if 0
- /* Removed superuser check: Sysops can use the permissions on the device
- file to restrict access. Recommendation: Root only. (root.root 600) */
- if (!capable(CAP_SYS_ADMIN)) {
+ if (!capable(CAP_SYS_RAWIO))
return -EPERM;
- }
-#endif
+
+ lock_kernel();
sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
@@ -1720,19 +1717,23 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
for (i = 0; i < SX_NBOARDS; i++)
sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
+ unlock_kernel();
return -EIO;
}
switch (cmd) {
case SXIO_SET_BOARD:
sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg);
+ rc = -EIO;
if (arg >= SX_NBOARDS)
- return -EIO;
+ break;
sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n");
if (!(boards[arg].flags & SX_BOARD_PRESENT))
- return -EIO;
+ break;
sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n");
board = &boards[arg];
+ rc = 0;
+ /* FIXME: And this does ... nothing?? */
break;
case SXIO_GET_TYPE:
rc = -ENOENT; /* If we manage to miss one, return error. */
@@ -1746,7 +1747,7 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
rc = SX_TYPE_SI;
if (IS_EISA_BOARD(board))
rc = SX_TYPE_SI;
- sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %d\n", rc);
+ sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc);
break;
case SXIO_DO_RAMTEST:
if (sx_initialized) /* Already initialized: better not ramtest the board. */
@@ -1760,19 +1761,26 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
rc = do_memtest(board, 0, 0x7ff8);
/* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */
}
- sx_dprintk(SX_DEBUG_FIRMWARE, "returning memtest result= %d\n",
- rc);
+ sx_dprintk(SX_DEBUG_FIRMWARE,
+ "returning memtest result= %ld\n", rc);
break;
case SXIO_DOWNLOAD:
- if (sx_initialized) /* Already initialized */
- return -EEXIST;
- if (!sx_reset(board))
- return -EIO;
+ if (sx_initialized) {/* Already initialized */
+ rc = -EEXIST;
+ break;
+ }
+ if (!sx_reset(board)) {
+ rc = -EIO;
+ break;
+ }
sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER);
- if (!tmp)
- return -ENOMEM;
+ if (!tmp) {
+ rc = -ENOMEM;
+ break;
+ }
+ /* FIXME: check returns */
get_user(nbytes, descr++);
get_user(offset, descr++);
get_user(data, descr++);
@@ -1782,7 +1790,8 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
(i + SX_CHUNK_SIZE > nbytes) ?
nbytes - i : SX_CHUNK_SIZE)) {
kfree(tmp);
- return -EFAULT;
+ rc = -EFAULT;
+ break;
}
memcpy_toio(board->base2 + offset + i, tmp,
(i + SX_CHUNK_SIZE > nbytes) ?
@@ -1798,13 +1807,17 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
rc = sx_nports;
break;
case SXIO_INIT:
- if (sx_initialized) /* Already initialized */
- return -EEXIST;
+ if (sx_initialized) { /* Already initialized */
+ rc = -EEXIST;
+ break;
+ }
/* This is not allowed until all boards are initialized... */
for (i = 0; i < SX_NBOARDS; i++) {
if ((boards[i].flags & SX_BOARD_PRESENT) &&
- !(boards[i].flags & SX_BOARD_INITIALIZED))
- return -EIO;
+ !(boards[i].flags & SX_BOARD_INITIALIZED)) {
+ rc = -EIO;
+ break;
+ }
}
for (i = 0; i < SX_NBOARDS; i++)
if (!(boards[i].flags & SX_BOARD_PRESENT))
@@ -1832,15 +1845,15 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
rc = sx_nports;
break;
default:
- printk(KERN_WARNING "Unknown ioctl on firmware device (%x).\n",
- cmd);
+ rc = -ENOTTY;
break;
}
+ unlock_kernel();
func_exit();
return rc;
}
-static void sx_break(struct tty_struct *tty, int flag)
+static int sx_break(struct tty_struct *tty, int flag)
{
struct sx_port *port = tty->driver_data;
int rv;
@@ -1857,6 +1870,7 @@ static void sx_break(struct tty_struct *tty, int flag)
read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
unlock_kernel();
func_exit();
+ return 0;
}
static int sx_tiocmget(struct tty_struct *tty, struct file *file)
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 527d220aa4a..ef6706f0906 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -2897,9 +2897,9 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
*
* Arguments: tty pointer to tty instance data
* break_state -1=set break condition, 0=clear
- * Return Value: None
+ * Return Value: error code
*/
-static void mgsl_break(struct tty_struct *tty, int break_state)
+static int mgsl_break(struct tty_struct *tty, int break_state)
{
struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
unsigned long flags;
@@ -2909,7 +2909,7 @@ static void mgsl_break(struct tty_struct *tty, int break_state)
__FILE__,__LINE__, info->device_name, break_state);
if (mgsl_paranoia_check(info, tty->name, "mgsl_break"))
- return;
+ return -EINVAL;
spin_lock_irqsave(&info->irq_spinlock,flags);
if (break_state == -1)
@@ -2917,6 +2917,7 @@ static void mgsl_break(struct tty_struct *tty, int break_state)
else
usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) & ~BIT7));
spin_unlock_irqrestore(&info->irq_spinlock,flags);
+ return 0;
} /* end of mgsl_break() */
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 2c3e43bb2cc..3e9058993e4 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -165,7 +165,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v
static int chars_in_buffer(struct tty_struct *tty);
static void throttle(struct tty_struct * tty);
static void unthrottle(struct tty_struct * tty);
-static void set_break(struct tty_struct *tty, int break_state);
+static int set_break(struct tty_struct *tty, int break_state);
/*
* generic HDLC support and callbacks
@@ -214,6 +214,7 @@ struct slgt_desc
char *buf; /* virtual address of data buffer */
unsigned int pdesc; /* physical address of this descriptor */
dma_addr_t buf_dma_addr;
+ unsigned short buf_count;
};
#define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b))
@@ -302,7 +303,7 @@ struct slgt_info {
u32 idle_mode;
u32 max_frame_size; /* as set by device config */
- unsigned int raw_rx_size;
+ unsigned int rbuf_fill_level;
unsigned int if_mode;
/* device status */
@@ -466,6 +467,7 @@ static void tx_start(struct slgt_info *info);
static void tx_stop(struct slgt_info *info);
static void tx_set_idle(struct slgt_info *info);
static unsigned int free_tbuf_count(struct slgt_info *info);
+static unsigned int tbuf_bytes(struct slgt_info *info);
static void reset_tbufs(struct slgt_info *info);
static void tdma_reset(struct slgt_info *info);
static void tdma_start(struct slgt_info *info);
@@ -513,7 +515,7 @@ static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr);
static int tiocmget(struct tty_struct *tty, struct file *file);
static int tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
-static void set_break(struct tty_struct *tty, int break_state);
+static int set_break(struct tty_struct *tty, int break_state);
static int get_interface(struct slgt_info *info, int __user *if_mode);
static int set_interface(struct slgt_info *info, int if_mode);
static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
@@ -849,6 +851,7 @@ static int write(struct tty_struct *tty,
int ret = 0;
struct slgt_info *info = tty->driver_data;
unsigned long flags;
+ unsigned int bufs_needed;
if (sanity_check(info, tty->name, "write"))
goto cleanup;
@@ -865,25 +868,16 @@ static int write(struct tty_struct *tty,
if (!count)
goto cleanup;
- if (info->params.mode == MGSL_MODE_RAW ||
- info->params.mode == MGSL_MODE_MONOSYNC ||
- info->params.mode == MGSL_MODE_BISYNC) {
- unsigned int bufs_needed = (count/DMABUFSIZE);
- unsigned int bufs_free = free_tbuf_count(info);
- if (count % DMABUFSIZE)
- ++bufs_needed;
- if (bufs_needed > bufs_free)
- goto cleanup;
- } else {
- if (info->tx_active)
- goto cleanup;
- if (info->tx_count) {
- /* send accumulated data from send_char() calls */
- /* as frame and wait before accepting more data. */
- tx_load(info, info->tx_buf, info->tx_count);
- goto start;
- }
+ if (!info->tx_active && info->tx_count) {
+ /* send accumulated data from send_char() */
+ tx_load(info, info->tx_buf, info->tx_count);
+ goto start;
}
+ bufs_needed = (count/DMABUFSIZE);
+ if (count % DMABUFSIZE)
+ ++bufs_needed;
+ if (bufs_needed > free_tbuf_count(info))
+ goto cleanup;
ret = info->tx_count = count;
tx_load(info, buf, count);
@@ -1396,10 +1390,12 @@ done:
static int chars_in_buffer(struct tty_struct *tty)
{
struct slgt_info *info = tty->driver_data;
+ int count;
if (sanity_check(info, tty->name, "chars_in_buffer"))
return 0;
- DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, info->tx_count));
- return info->tx_count;
+ count = tbuf_bytes(info);
+ DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, count));
+ return count;
}
/*
@@ -1452,14 +1448,14 @@ static void unthrottle(struct tty_struct * tty)
* set or clear transmit break condition
* break_state -1=set break condition, 0=clear
*/
-static void set_break(struct tty_struct *tty, int break_state)
+static int set_break(struct tty_struct *tty, int break_state)
{
struct slgt_info *info = tty->driver_data;
unsigned short value;
unsigned long flags;
if (sanity_check(info, tty->name, "set_break"))
- return;
+ return -EINVAL;
DBGINFO(("%s set_break(%d)\n", info->device_name, break_state));
spin_lock_irqsave(&info->lock,flags);
@@ -1470,6 +1466,7 @@ static void set_break(struct tty_struct *tty, int break_state)
value &= ~BIT6;
wr_reg16(info, TCR, value);
spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
}
#if SYNCLINK_GENERIC_HDLC
@@ -2679,8 +2676,31 @@ static int tx_abort(struct slgt_info *info)
static int rx_enable(struct slgt_info *info, int enable)
{
unsigned long flags;
- DBGINFO(("%s rx_enable(%d)\n", info->device_name, enable));
+ unsigned int rbuf_fill_level;
+ DBGINFO(("%s rx_enable(%08x)\n", info->device_name, enable));
spin_lock_irqsave(&info->lock,flags);
+ /*
+ * enable[31..16] = receive DMA buffer fill level
+ * 0 = noop (leave fill level unchanged)
+ * fill level must be multiple of 4 and <= buffer size
+ */
+ rbuf_fill_level = ((unsigned int)enable) >> 16;
+ if (rbuf_fill_level) {
+ if ((rbuf_fill_level > DMABUFSIZE) || (rbuf_fill_level % 4)) {
+ spin_unlock_irqrestore(&info->lock, flags);
+ return -EINVAL;
+ }
+ info->rbuf_fill_level = rbuf_fill_level;
+ rx_stop(info); /* restart receiver to use new fill level */
+ }
+
+ /*
+ * enable[1..0] = receiver enable command
+ * 0 = disable
+ * 1 = enable
+ * 2 = enable or force hunt mode if already enabled
+ */
+ enable &= 3;
if (enable) {
if (!info->rx_enabled)
rx_start(info);
@@ -3447,7 +3467,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev
info->magic = MGSL_MAGIC;
INIT_WORK(&info->task, bh_handler);
info->max_frame_size = 4096;
- info->raw_rx_size = DMABUFSIZE;
+ info->rbuf_fill_level = DMABUFSIZE;
info->port.close_delay = 5*HZ/10;
info->port.closing_wait = 30*HZ;
init_waitqueue_head(&info->status_event_wait_q);
@@ -3934,15 +3954,7 @@ static void tdma_start(struct slgt_info *info)
/* set 1st descriptor address */
wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
- switch(info->params.mode) {
- case MGSL_MODE_RAW:
- case MGSL_MODE_MONOSYNC:
- case MGSL_MODE_BISYNC:
- wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */
- break;
- default:
- wr_reg32(info, TDCSR, BIT0); /* DMA enable */
- }
+ wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */
}
static void tx_stop(struct slgt_info *info)
@@ -4145,7 +4157,7 @@ static void sync_mode(struct slgt_info *info)
* 01 enable
* 00 auto-CTS enable
*/
- val = 0;
+ val = BIT2;
switch(info->params.mode) {
case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
@@ -4418,6 +4430,8 @@ static void msc_set_vcr(struct slgt_info *info)
break;
}
+ if (info->if_mode & MGSL_INTERFACE_MSB_FIRST)
+ val |= BIT4;
if (info->signals & SerialSignal_DTR)
val |= BIT3;
if (info->signals & SerialSignal_RTS)
@@ -4456,16 +4470,7 @@ static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last
while(!done) {
/* reset current buffer for reuse */
info->rbufs[i].status = 0;
- switch(info->params.mode) {
- case MGSL_MODE_RAW:
- case MGSL_MODE_MONOSYNC:
- case MGSL_MODE_BISYNC:
- set_desc_count(info->rbufs[i], info->raw_rx_size);
- break;
- default:
- set_desc_count(info->rbufs[i], DMABUFSIZE);
- }
-
+ set_desc_count(info->rbufs[i], info->rbuf_fill_level);
if (i == last)
done = 1;
if (++i == info->rbuf_count)
@@ -4572,7 +4577,7 @@ check_again:
DBGBH(("%s rx frame status=%04X size=%d\n",
info->device_name, status, framesize));
- DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx");
+ DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, info->rbuf_fill_level), "rx");
if (framesize) {
if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) {
@@ -4592,7 +4597,7 @@ check_again:
info->icount.rxok++;
while(copy_count) {
- int partial_count = min(copy_count, DMABUFSIZE);
+ int partial_count = min_t(int, copy_count, info->rbuf_fill_level);
memcpy(p, info->rbufs[i].buf, partial_count);
p += partial_count;
copy_count -= partial_count;
@@ -4684,6 +4689,56 @@ static unsigned int free_tbuf_count(struct slgt_info *info)
}
/*
+ * return number of bytes in unsent transmit DMA buffers
+ * and the serial controller tx FIFO
+ */
+static unsigned int tbuf_bytes(struct slgt_info *info)
+{
+ unsigned int total_count = 0;
+ unsigned int i = info->tbuf_current;
+ unsigned int reg_value;
+ unsigned int count;
+ unsigned int active_buf_count = 0;
+
+ /*
+ * Add descriptor counts for all tx DMA buffers.
+ * If count is zero (cleared by DMA controller after read),
+ * the buffer is complete or is actively being read from.
+ *
+ * Record buf_count of last buffer with zero count starting
+ * from current ring position. buf_count is mirror
+ * copy of count and is not cleared by serial controller.
+ * If DMA controller is active, that buffer is actively
+ * being read so add to total.
+ */
+ do {
+ count = desc_count(info->tbufs[i]);
+ if (count)
+ total_count += count;
+ else if (!total_count)
+ active_buf_count = info->tbufs[i].buf_count;
+ if (++i == info->tbuf_count)
+ i = 0;
+ } while (i != info->tbuf_current);
+
+ /* read tx DMA status register */
+ reg_value = rd_reg32(info, TDCSR);
+
+ /* if tx DMA active, last zero count buffer is in use */
+ if (reg_value & BIT0)
+ total_count += active_buf_count;
+
+ /* add tx FIFO count = reg_value[15..8] */
+ total_count += (reg_value >> 8) & 0xff;
+
+ /* if transmitter active add one byte for shift register */
+ if (info->tx_active)
+ total_count++;
+
+ return total_count;
+}
+
+/*
* load transmit DMA buffer(s) with data
*/
static void tx_load(struct slgt_info *info, const char *buf, unsigned int size)
@@ -4721,6 +4776,7 @@ static void tx_load(struct slgt_info *info, const char *buf, unsigned int size)
set_desc_eof(*d, 0);
set_desc_count(*d, count);
+ d->buf_count = count;
}
info->tbuf_current = i;
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 5768c413634..c0490cbd0db 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -527,7 +527,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v
static int chars_in_buffer(struct tty_struct *tty);
static void throttle(struct tty_struct * tty);
static void unthrottle(struct tty_struct * tty);
-static void set_break(struct tty_struct *tty, int break_state);
+static int set_break(struct tty_struct *tty, int break_state);
#if SYNCLINK_GENERIC_HDLC
#define dev_to_port(D) (dev_to_hdlc(D)->priv)
@@ -552,7 +552,7 @@ static int wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr);
static int tiocmget(struct tty_struct *tty, struct file *file);
static int tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
-static void set_break(struct tty_struct *tty, int break_state);
+static int set_break(struct tty_struct *tty, int break_state);
static void add_device(SLMP_INFO *info);
static void device_init(int adapter_num, struct pci_dev *pdev);
@@ -1587,7 +1587,7 @@ static void unthrottle(struct tty_struct * tty)
/* set or clear transmit break condition
* break_state -1=set break condition, 0=clear
*/
-static void set_break(struct tty_struct *tty, int break_state)
+static int set_break(struct tty_struct *tty, int break_state)
{
unsigned char RegValue;
SLMP_INFO * info = (SLMP_INFO *)tty->driver_data;
@@ -1598,7 +1598,7 @@ static void set_break(struct tty_struct *tty, int break_state)
__FILE__,__LINE__, info->device_name, break_state);
if (sanity_check(info, tty->name, "set_break"))
- return;
+ return -EINVAL;
spin_lock_irqsave(&info->lock,flags);
RegValue = read_reg(info, CTL);
@@ -1608,6 +1608,7 @@ static void set_break(struct tty_struct *tty, int break_state)
RegValue &= ~BIT3;
write_reg(info, CTL, RegValue);
spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
}
#if SYNCLINK_GENERIC_HDLC
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 82f6a8c8633..e1b46bc7e43 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -656,558 +656,6 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
/**
- * tty_set_termios_ldisc - set ldisc field
- * @tty: tty structure
- * @num: line discipline number
- *
- * This is probably overkill for real world processors but
- * they are not on hot paths so a little discipline won't do
- * any harm.
- *
- * Locking: takes termios_mutex
- */
-
-static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
-{
- mutex_lock(&tty->termios_mutex);
- tty->termios->c_line = num;
- mutex_unlock(&tty->termios_mutex);
-}
-
-/*
- * This guards the refcounted line discipline lists. The lock
- * must be taken with irqs off because there are hangup path
- * callers who will do ldisc lookups and cannot sleep.
- */
-
-static DEFINE_SPINLOCK(tty_ldisc_lock);
-static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
-/* Line disc dispatch table */
-static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
-
-/**
- * tty_register_ldisc - install a line discipline
- * @disc: ldisc number
- * @new_ldisc: pointer to the ldisc object
- *
- * Installs a new line discipline into the kernel. The discipline
- * is set up as unreferenced and then made available to the kernel
- * from this point onwards.
- *
- * Locking:
- * takes tty_ldisc_lock to guard against ldisc races
- */
-
-int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
-{
- unsigned long flags;
- int ret = 0;
-
- if (disc < N_TTY || disc >= NR_LDISCS)
- return -EINVAL;
-
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- tty_ldiscs[disc] = new_ldisc;
- new_ldisc->num = disc;
- new_ldisc->refcount = 0;
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL(tty_register_ldisc);
-
-/**
- * tty_unregister_ldisc - unload a line discipline
- * @disc: ldisc number
- * @new_ldisc: pointer to the ldisc object
- *
- * Remove a line discipline from the kernel providing it is not
- * currently in use.
- *
- * Locking:
- * takes tty_ldisc_lock to guard against ldisc races
- */
-
-int tty_unregister_ldisc(int disc)
-{
- unsigned long flags;
- int ret = 0;
-
- if (disc < N_TTY || disc >= NR_LDISCS)
- return -EINVAL;
-
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- if (tty_ldiscs[disc]->refcount)
- ret = -EBUSY;
- else
- tty_ldiscs[disc] = NULL;
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL(tty_unregister_ldisc);
-
-
-/**
- * tty_ldisc_try_get - try and reference an ldisc
- * @disc: ldisc number
- * @ld: tty ldisc structure to complete
- *
- * Attempt to open and lock a line discipline into place. Return
- * the line discipline refcounted and assigned in ld. On an error
- * report the error code back
- */
-
-static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld)
-{
- unsigned long flags;
- struct tty_ldisc_ops *ldops;
- int err = -EINVAL;
-
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- ld->ops = NULL;
- ldops = tty_ldiscs[disc];
- /* Check the entry is defined */
- if (ldops) {
- /* If the module is being unloaded we can't use it */
- if (!try_module_get(ldops->owner))
- err = -EAGAIN;
- else {
- /* lock it */
- ldops->refcount++;
- ld->ops = ldops;
- err = 0;
- }
- }
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
- return err;
-}
-
-/**
- * tty_ldisc_get - take a reference to an ldisc
- * @disc: ldisc number
- * @ld: tty line discipline structure to use
- *
- * Takes a reference to a line discipline. Deals with refcounts and
- * module locking counts. Returns NULL if the discipline is not available.
- * Returns a pointer to the discipline and bumps the ref count if it is
- * available
- *
- * Locking:
- * takes tty_ldisc_lock to guard against ldisc races
- */
-
-static int tty_ldisc_get(int disc, struct tty_ldisc *ld)
-{
- int err;
-
- if (disc < N_TTY || disc >= NR_LDISCS)
- return -EINVAL;
- err = tty_ldisc_try_get(disc, ld);
- if (err == -EAGAIN) {
- request_module("tty-ldisc-%d", disc);
- err = tty_ldisc_try_get(disc, ld);
- }
- return err;
-}
-
-/**
- * tty_ldisc_put - drop ldisc reference
- * @disc: ldisc number
- *
- * Drop a reference to a line discipline. Manage refcounts and
- * module usage counts
- *
- * Locking:
- * takes tty_ldisc_lock to guard against ldisc races
- */
-
-static void tty_ldisc_put(struct tty_ldisc_ops *ld)
-{
- unsigned long flags;
- int disc = ld->num;
-
- BUG_ON(disc < N_TTY || disc >= NR_LDISCS);
-
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- ld = tty_ldiscs[disc];
- BUG_ON(ld->refcount == 0);
- ld->refcount--;
- module_put(ld->owner);
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-}
-
-static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
-{
- return (*pos < NR_LDISCS) ? pos : NULL;
-}
-
-static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos)
-{
- (*pos)++;
- return (*pos < NR_LDISCS) ? pos : NULL;
-}
-
-static void tty_ldiscs_seq_stop(struct seq_file *m, void *v)
-{
-}
-
-static int tty_ldiscs_seq_show(struct seq_file *m, void *v)
-{
- int i = *(loff_t *)v;
- struct tty_ldisc ld;
-
- if (tty_ldisc_get(i, &ld) < 0)
- return 0;
- seq_printf(m, "%-10s %2d\n", ld.ops->name ? ld.ops->name : "???", i);
- tty_ldisc_put(ld.ops);
- return 0;
-}
-
-static const struct seq_operations tty_ldiscs_seq_ops = {
- .start = tty_ldiscs_seq_start,
- .next = tty_ldiscs_seq_next,
- .stop = tty_ldiscs_seq_stop,
- .show = tty_ldiscs_seq_show,
-};
-
-static int proc_tty_ldiscs_open(struct inode *inode, struct file *file)
-{
- return seq_open(file, &tty_ldiscs_seq_ops);
-}
-
-const struct file_operations tty_ldiscs_proc_fops = {
- .owner = THIS_MODULE,
- .open = proc_tty_ldiscs_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
-/**
- * tty_ldisc_assign - set ldisc on a tty
- * @tty: tty to assign
- * @ld: line discipline
- *
- * Install an instance of a line discipline into a tty structure. The
- * ldisc must have a reference count above zero to ensure it remains/
- * The tty instance refcount starts at zero.
- *
- * Locking:
- * Caller must hold references
- */
-
-static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
-{
- ld->refcount = 0;
- tty->ldisc = *ld;
-}
-
-/**
- * tty_ldisc_try - internal helper
- * @tty: the tty
- *
- * Make a single attempt to grab and bump the refcount on
- * the tty ldisc. Return 0 on failure or 1 on success. This is
- * used to implement both the waiting and non waiting versions
- * of tty_ldisc_ref
- *
- * Locking: takes tty_ldisc_lock
- */
-
-static int tty_ldisc_try(struct tty_struct *tty)
-{
- unsigned long flags;
- struct tty_ldisc *ld;
- int ret = 0;
-
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- ld = &tty->ldisc;
- if (test_bit(TTY_LDISC, &tty->flags)) {
- ld->refcount++;
- ret = 1;
- }
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
- return ret;
-}
-
-/**
- * tty_ldisc_ref_wait - wait for the tty ldisc
- * @tty: tty device
- *
- * Dereference the line discipline for the terminal and take a
- * reference to it. If the line discipline is in flux then
- * wait patiently until it changes.
- *
- * Note: Must not be called from an IRQ/timer context. The caller
- * must also be careful not to hold other locks that will deadlock
- * against a discipline change, such as an existing ldisc reference
- * (which we check for)
- *
- * Locking: call functions take tty_ldisc_lock
- */
-
-struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
-{
- /* wait_event is a macro */
- wait_event(tty_ldisc_wait, tty_ldisc_try(tty));
- if (tty->ldisc.refcount == 0)
- printk(KERN_ERR "tty_ldisc_ref_wait\n");
- return &tty->ldisc;
-}
-
-EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
-
-/**
- * tty_ldisc_ref - get the tty ldisc
- * @tty: tty device
- *
- * Dereference the line discipline for the terminal and take a
- * reference to it. If the line discipline is in flux then
- * return NULL. Can be called from IRQ and timer functions.
- *
- * Locking: called functions take tty_ldisc_lock
- */
-
-struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
-{
- if (tty_ldisc_try(tty))
- return &tty->ldisc;
- return NULL;
-}
-
-EXPORT_SYMBOL_GPL(tty_ldisc_ref);
-
-/**
- * tty_ldisc_deref - free a tty ldisc reference
- * @ld: reference to free up
- *
- * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
- * be called in IRQ context.
- *
- * Locking: takes tty_ldisc_lock
- */
-
-void tty_ldisc_deref(struct tty_ldisc *ld)
-{
- unsigned long flags;
-
- BUG_ON(ld == NULL);
-
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- if (ld->refcount == 0)
- printk(KERN_ERR "tty_ldisc_deref: no references.\n");
- else
- ld->refcount--;
- if (ld->refcount == 0)
- wake_up(&tty_ldisc_wait);
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-}
-
-EXPORT_SYMBOL_GPL(tty_ldisc_deref);
-
-/**
- * tty_ldisc_enable - allow ldisc use
- * @tty: terminal to activate ldisc on
- *
- * Set the TTY_LDISC flag when the line discipline can be called
- * again. Do necessary wakeups for existing sleepers.
- *
- * Note: nobody should set this bit except via this function. Clearing
- * directly is allowed.
- */
-
-static void tty_ldisc_enable(struct tty_struct *tty)
-{
- set_bit(TTY_LDISC, &tty->flags);
- wake_up(&tty_ldisc_wait);
-}
-
-/**
- * tty_ldisc_restore - helper for tty ldisc change
- * @tty: tty to recover
- * @old: previous ldisc
- *
- * Restore the previous line discipline or N_TTY when a line discipline
- * change fails due to an open error
- */
-
-static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
-{
- char buf[64];
- struct tty_ldisc new_ldisc;
-
- /* There is an outstanding reference here so this is safe */
- tty_ldisc_get(old->ops->num, old);
- tty_ldisc_assign(tty, old);
- tty_set_termios_ldisc(tty, old->ops->num);
- if (old->ops->open && (old->ops->open(tty) < 0)) {
- tty_ldisc_put(old->ops);
- /* This driver is always present */
- if (tty_ldisc_get(N_TTY, &new_ldisc) < 0)
- panic("n_tty: get");
- tty_ldisc_assign(tty, &new_ldisc);
- tty_set_termios_ldisc(tty, N_TTY);
- if (new_ldisc.ops->open) {
- int r = new_ldisc.ops->open(tty);
- if (r < 0)
- panic("Couldn't open N_TTY ldisc for "
- "%s --- error %d.",
- tty_name(tty, buf), r);
- }
- }
-}
-
-/**
- * tty_set_ldisc - set line discipline
- * @tty: the terminal to set
- * @ldisc: the line discipline
- *
- * Set the discipline of a tty line. Must be called from a process
- * context.
- *
- * Locking: takes tty_ldisc_lock.
- * called functions take termios_mutex
- */
-
-static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
-{
- int retval;
- struct tty_ldisc o_ldisc, new_ldisc;
- int work;
- unsigned long flags;
- struct tty_struct *o_tty;
-
-restart:
- /* This is a bit ugly for now but means we can break the 'ldisc
- is part of the tty struct' assumption later */
- retval = tty_ldisc_get(ldisc, &new_ldisc);
- if (retval)
- return retval;
-
- /*
- * Problem: What do we do if this blocks ?
- */
-
- tty_wait_until_sent(tty, 0);
-
- if (tty->ldisc.ops->num == ldisc) {
- tty_ldisc_put(new_ldisc.ops);
- return 0;
- }
-
- /*
- * No more input please, we are switching. The new ldisc
- * will update this value in the ldisc open function
- */
-
- tty->receive_room = 0;
-
- o_ldisc = tty->ldisc;
- o_tty = tty->link;
-
- /*
- * Make sure we don't change while someone holds a
- * reference to the line discipline. The TTY_LDISC bit
- * prevents anyone taking a reference once it is clear.
- * We need the lock to avoid racing reference takers.
- */
-
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) {
- if (tty->ldisc.refcount) {
- /* Free the new ldisc we grabbed. Must drop the lock
- first. */
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
- tty_ldisc_put(o_ldisc.ops);
- /*
- * There are several reasons we may be busy, including
- * random momentary I/O traffic. We must therefore
- * retry. We could distinguish between blocking ops
- * and retries if we made tty_ldisc_wait() smarter.
- * That is up for discussion.
- */
- if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
- return -ERESTARTSYS;
- goto restart;
- }
- if (o_tty && o_tty->ldisc.refcount) {
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
- tty_ldisc_put(o_tty->ldisc.ops);
- if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0)
- return -ERESTARTSYS;
- goto restart;
- }
- }
- /*
- * If the TTY_LDISC bit is set, then we are racing against
- * another ldisc change
- */
- if (!test_bit(TTY_LDISC, &tty->flags)) {
- struct tty_ldisc *ld;
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
- tty_ldisc_put(new_ldisc.ops);
- ld = tty_ldisc_ref_wait(tty);
- tty_ldisc_deref(ld);
- goto restart;
- }
-
- clear_bit(TTY_LDISC, &tty->flags);
- if (o_tty)
- clear_bit(TTY_LDISC, &o_tty->flags);
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-
- /*
- * From this point on we know nobody has an ldisc
- * usage reference, nor can they obtain one until
- * we say so later on.
- */
-
- work = cancel_delayed_work(&tty->buf.work);
- /*
- * Wait for ->hangup_work and ->buf.work handlers to terminate
- * MUST NOT hold locks here.
- */
- flush_scheduled_work();
- /* Shutdown the current discipline. */
- if (o_ldisc.ops->close)
- (o_ldisc.ops->close)(tty);
-
- /* Now set up the new line discipline. */
- tty_ldisc_assign(tty, &new_ldisc);
- tty_set_termios_ldisc(tty, ldisc);
- if (new_ldisc.ops->open)
- retval = (new_ldisc.ops->open)(tty);
- if (retval < 0) {
- tty_ldisc_put(new_ldisc.ops);
- tty_ldisc_restore(tty, &o_ldisc);
- }
- /* At this point we hold a reference to the new ldisc and a
- a reference to the old ldisc. If we ended up flipping back
- to the existing ldisc we have two references to it */
-
- if (tty->ldisc.ops->num != o_ldisc.ops->num && tty->ops->set_ldisc)
- tty->ops->set_ldisc(tty);
-
- tty_ldisc_put(o_ldisc.ops);
-
- /*
- * Allow ldisc referencing to occur as soon as the driver
- * ldisc callback completes.
- */
-
- tty_ldisc_enable(tty);
- if (o_tty)
- tty_ldisc_enable(o_tty);
-
- /* Restart it in case no characters kick it off. Safe if
- already running */
- if (work)
- schedule_delayed_work(&tty->buf.work, 1);
- return retval;
-}
-
-/**
* get_tty_driver - find device of a tty
* @dev_t: device identifier
* @index: returns the index of the tty
@@ -1467,7 +915,7 @@ static void tty_reset_termios(struct tty_struct *tty)
* do_tty_hangup - actual handler for hangup events
* @work: tty device
*
-k * This can be called by the "eventd" kernel thread. That is process
+ * This can be called by the "eventd" kernel thread. That is process
* synchronous but doesn't hold any locks, so we need to make sure we
* have the appropriate locks for what we're doing.
*
@@ -1671,19 +1119,6 @@ int tty_hung_up_p(struct file *filp)
EXPORT_SYMBOL(tty_hung_up_p);
-/**
- * is_tty - checker whether file is a TTY
- * @filp: file handle that may be a tty
- *
- * Check if the file handle is a tty handle.
- */
-
-int is_tty(struct file *filp)
-{
- return filp->f_op->read == tty_read
- || filp->f_op->read == hung_up_tty_read;
-}
-
static void session_clear_tty(struct pid *session)
{
struct task_struct *p;
@@ -2193,7 +1628,6 @@ static int init_dev(struct tty_driver *driver, int idx,
struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc;
struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
int retval = 0;
- struct tty_ldisc *ld;
/* check whether we're reopening an existing tty */
if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
@@ -2342,25 +1776,12 @@ static int init_dev(struct tty_driver *driver, int idx,
* If we fail here just call release_tty to clean up. No need
* to decrement the use counts, as release_tty doesn't care.
*/
-
- ld = &tty->ldisc;
- if (ld->ops->open) {
- retval = (ld->ops->open)(tty);
- if (retval)
- goto release_mem_out;
- }
- if (o_tty && o_tty->ldisc.ops->open) {
- retval = (o_tty->ldisc.ops->open)(o_tty);
- if (retval) {
- if (ld->ops->close)
- (ld->ops->close)(tty);
- goto release_mem_out;
- }
- tty_ldisc_enable(o_tty);
- }
- tty_ldisc_enable(tty);
- goto success;
+ retval = tty_ldisc_setup(tty, o_tty);
+
+ if (retval)
+ goto release_mem_out;
+ goto success;
/*
* This fast open can be used if the tty is already open.
@@ -2498,12 +1919,10 @@ static void release_tty(struct tty_struct *tty, int idx)
static void release_dev(struct file *filp)
{
struct tty_struct *tty, *o_tty;
- struct tty_ldisc ld;
int pty_master, tty_closing, o_tty_closing, do_sleep;
int devpts;
int idx;
char buf[64];
- unsigned long flags;
tty = (struct tty_struct *)filp->private_data;
if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode,
@@ -2705,56 +2124,9 @@ static void release_dev(struct file *filp)
printk(KERN_DEBUG "freeing tty structure...");
#endif
/*
- * Prevent flush_to_ldisc() from rescheduling the work for later. Then
- * kill any delayed work. As this is the final close it does not
- * race with the set_ldisc code path.
+ * Ask the line discipline code to release its structures
*/
- clear_bit(TTY_LDISC, &tty->flags);
- cancel_delayed_work(&tty->buf.work);
-
- /*
- * Wait for ->hangup_work and ->buf.work handlers to terminate
- */
-
- flush_scheduled_work();
-
- /*
- * Wait for any short term users (we know they are just driver
- * side waiters as the file is closing so user count on the file
- * side is zero.
- */
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- while (tty->ldisc.refcount) {
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
- wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0);
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- }
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
- /*
- * Shutdown the current line discipline, and reset it to N_TTY.
- *
- * FIXME: this MUST get fixed for the new reflocking
- */
- if (tty->ldisc.ops->close)
- (tty->ldisc.ops->close)(tty);
- tty_ldisc_put(tty->ldisc.ops);
-
- /*
- * Switch the line discipline back
- */
- WARN_ON(tty_ldisc_get(N_TTY, &ld));
- tty_ldisc_assign(tty, &ld);
- tty_set_termios_ldisc(tty, N_TTY);
- if (o_tty) {
- /* FIXME: could o_tty be in setldisc here ? */
- clear_bit(TTY_LDISC, &o_tty->flags);
- if (o_tty->ldisc.ops->close)
- (o_tty->ldisc.ops->close)(o_tty);
- tty_ldisc_put(o_tty->ldisc.ops);
- WARN_ON(tty_ldisc_get(N_TTY, &ld));
- tty_ldisc_assign(o_tty, &ld);
- tty_set_termios_ldisc(o_tty, N_TTY);
- }
+ tty_ldisc_release(tty, o_tty);
/*
* The release_tty function takes care of the details of clearing
* the slots and preserving the termios structure.
@@ -3464,16 +2836,29 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
static int send_break(struct tty_struct *tty, unsigned int duration)
{
- if (tty_write_lock(tty, 0) < 0)
- return -EINTR;
- tty->ops->break_ctl(tty, -1);
- if (!signal_pending(current))
- msleep_interruptible(duration);
- tty->ops->break_ctl(tty, 0);
- tty_write_unlock(tty);
- if (signal_pending(current))
- return -EINTR;
- return 0;
+ int retval;
+
+ if (tty->ops->break_ctl == NULL)
+ return 0;
+
+ if (tty->driver->flags & TTY_DRIVER_HARDWARE_BREAK)
+ retval = tty->ops->break_ctl(tty, duration);
+ else {
+ /* Do the work ourselves */
+ if (tty_write_lock(tty, 0) < 0)
+ return -EINTR;
+ retval = tty->ops->break_ctl(tty, -1);
+ if (retval)
+ goto out;
+ if (!signal_pending(current))
+ msleep_interruptible(duration);
+ retval = tty->ops->break_ctl(tty, 0);
+out:
+ tty_write_unlock(tty);
+ if (signal_pending(current))
+ retval = -EINTR;
+ }
+ return retval;
}
/**
@@ -3564,36 +2949,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
tty->driver->subtype == PTY_TYPE_MASTER)
real_tty = tty->link;
- /*
- * Break handling by driver
- */
-
- retval = -EINVAL;
-
- if (!tty->ops->break_ctl) {
- switch (cmd) {
- case TIOCSBRK:
- case TIOCCBRK:
- if (tty->ops->ioctl)
- retval = tty->ops->ioctl(tty, file, cmd, arg);
- if (retval != -EINVAL && retval != -ENOIOCTLCMD)
- printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
- return retval;
-
- /* These two ioctl's always return success; even if */
- /* the driver doesn't support them. */
- case TCSBRK:
- case TCSBRKP:
- if (!tty->ops->ioctl)
- return 0;
- retval = tty->ops->ioctl(tty, file, cmd, arg);
- if (retval != -EINVAL && retval != -ENOIOCTLCMD)
- printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
- if (retval == -ENOIOCTLCMD)
- retval = 0;
- return retval;
- }
- }
/*
* Factor out some common prep work
@@ -3615,6 +2970,9 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
}
+ /*
+ * Now do the stuff.
+ */
switch (cmd) {
case TIOCSTI:
return tiocsti(tty, p);
@@ -3658,12 +3016,11 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
*/
case TIOCSBRK: /* Turn break on, unconditionally */
if (tty->ops->break_ctl)
- tty->ops->break_ctl(tty, -1);
+ return tty->ops->break_ctl(tty, -1);
return 0;
-
case TIOCCBRK: /* Turn break off, unconditionally */
if (tty->ops->break_ctl)
- tty->ops->break_ctl(tty, 0);
+ return tty->ops->break_ctl(tty, 0);
return 0;
case TCSBRK: /* SVID version: non-zero arg --> no break */
/* non-zero arg means wait for all output data
@@ -3962,12 +3319,9 @@ EXPORT_SYMBOL(tty_flip_buffer_push);
static void initialize_tty_struct(struct tty_struct *tty)
{
- struct tty_ldisc ld;
memset(tty, 0, sizeof(struct tty_struct));
tty->magic = TTY_MAGIC;
- if (tty_ldisc_get(N_TTY, &ld) < 0)
- panic("n_tty: init_tty");
- tty_ldisc_assign(tty, &ld);
+ tty_ldisc_init(tty);
tty->session = NULL;
tty->pgrp = NULL;
tty->overrun_time = jiffies;
@@ -4045,7 +3399,7 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index,
else
tty_line_name(driver, index, name);
- return device_create(tty_class, device, dev, name);
+ return device_create_drvdata(tty_class, device, dev, NULL, name);
}
/**
@@ -4226,7 +3580,6 @@ void proc_clear_tty(struct task_struct *p)
p->signal->tty = NULL;
spin_unlock_irq(&p->sighand->siglock);
}
-EXPORT_SYMBOL(proc_clear_tty);
/* Called under the sighand lock */
@@ -4280,7 +3633,7 @@ void __init console_init(void)
initcall_t *call;
/* Setup the default TTY line discipline. */
- (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
+ tty_ldisc_begin();
/*
* set up the console device so that later boot sequences can
@@ -4323,20 +3676,22 @@ static int __init tty_init(void)
if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
panic("Couldn't register /dev/tty driver\n");
- device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), "tty");
+ device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL,
+ "tty");
cdev_init(&console_cdev, &console_fops);
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
panic("Couldn't register /dev/console driver\n");
- device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), "console");
+ device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL,
+ "console");
#ifdef CONFIG_UNIX98_PTYS
cdev_init(&ptmx_cdev, &ptmx_fops);
if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
panic("Couldn't register /dev/ptmx driver\n");
- device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), "ptmx");
+ device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
#endif
#ifdef CONFIG_VT
@@ -4344,7 +3699,7 @@ static int __init tty_init(void)
if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
panic("Couldn't register /dev/tty0 driver\n");
- device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), "tty0");
+ device_create_drvdata(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
vty_init();
#endif
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
new file mode 100644
index 00000000000..241cbdea65a
--- /dev/null
+++ b/drivers/char/tty_ldisc.c
@@ -0,0 +1,714 @@
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/fcntl.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/devpts_fs.h>
+#include <linux/file.h>
+#include <linux/fdtable.h>
+#include <linux/console.h>
+#include <linux/timer.h>
+#include <linux/ctype.h>
+#include <linux/kd.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+
+#include <linux/uaccess.h>
+#include <asm/system.h>
+
+#include <linux/kbd_kern.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+
+#include <linux/kmod.h>
+#include <linux/nsproxy.h>
+
+/*
+ * This guards the refcounted line discipline lists. The lock
+ * must be taken with irqs off because there are hangup path
+ * callers who will do ldisc lookups and cannot sleep.
+ */
+
+static DEFINE_SPINLOCK(tty_ldisc_lock);
+static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
+/* Line disc dispatch table */
+static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
+
+/**
+ * tty_register_ldisc - install a line discipline
+ * @disc: ldisc number
+ * @new_ldisc: pointer to the ldisc object
+ *
+ * Installs a new line discipline into the kernel. The discipline
+ * is set up as unreferenced and then made available to the kernel
+ * from this point onwards.
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
+int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (disc < N_TTY || disc >= NR_LDISCS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ tty_ldiscs[disc] = new_ldisc;
+ new_ldisc->num = disc;
+ new_ldisc->refcount = 0;
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(tty_register_ldisc);
+
+/**
+ * tty_unregister_ldisc - unload a line discipline
+ * @disc: ldisc number
+ * @new_ldisc: pointer to the ldisc object
+ *
+ * Remove a line discipline from the kernel providing it is not
+ * currently in use.
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
+int tty_unregister_ldisc(int disc)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (disc < N_TTY || disc >= NR_LDISCS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ if (tty_ldiscs[disc]->refcount)
+ ret = -EBUSY;
+ else
+ tty_ldiscs[disc] = NULL;
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(tty_unregister_ldisc);
+
+
+/**
+ * tty_ldisc_try_get - try and reference an ldisc
+ * @disc: ldisc number
+ * @ld: tty ldisc structure to complete
+ *
+ * Attempt to open and lock a line discipline into place. Return
+ * the line discipline refcounted and assigned in ld. On an error
+ * report the error code back
+ */
+
+static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld)
+{
+ unsigned long flags;
+ struct tty_ldisc_ops *ldops;
+ int err = -EINVAL;
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ ld->ops = NULL;
+ ldops = tty_ldiscs[disc];
+ /* Check the entry is defined */
+ if (ldops) {
+ /* If the module is being unloaded we can't use it */
+ if (!try_module_get(ldops->owner))
+ err = -EAGAIN;
+ else {
+ /* lock it */
+ ldops->refcount++;
+ ld->ops = ldops;
+ err = 0;
+ }
+ }
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ return err;
+}
+
+/**
+ * tty_ldisc_get - take a reference to an ldisc
+ * @disc: ldisc number
+ * @ld: tty line discipline structure to use
+ *
+ * Takes a reference to a line discipline. Deals with refcounts and
+ * module locking counts. Returns NULL if the discipline is not available.
+ * Returns a pointer to the discipline and bumps the ref count if it is
+ * available
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
+static int tty_ldisc_get(int disc, struct tty_ldisc *ld)
+{
+ int err;
+
+ if (disc < N_TTY || disc >= NR_LDISCS)
+ return -EINVAL;
+ err = tty_ldisc_try_get(disc, ld);
+ if (err == -EAGAIN) {
+ request_module("tty-ldisc-%d", disc);
+ err = tty_ldisc_try_get(disc, ld);
+ }
+ return err;
+}
+
+/**
+ * tty_ldisc_put - drop ldisc reference
+ * @disc: ldisc number
+ *
+ * Drop a reference to a line discipline. Manage refcounts and
+ * module usage counts
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
+static void tty_ldisc_put(struct tty_ldisc_ops *ld)
+{
+ unsigned long flags;
+ int disc = ld->num;
+
+ BUG_ON(disc < N_TTY || disc >= NR_LDISCS);
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ ld = tty_ldiscs[disc];
+ BUG_ON(ld->refcount == 0);
+ ld->refcount--;
+ module_put(ld->owner);
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+}
+
+static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
+{
+ return (*pos < NR_LDISCS) ? pos : NULL;
+}
+
+static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return (*pos < NR_LDISCS) ? pos : NULL;
+}
+
+static void tty_ldiscs_seq_stop(struct seq_file *m, void *v)
+{
+}
+
+static int tty_ldiscs_seq_show(struct seq_file *m, void *v)
+{
+ int i = *(loff_t *)v;
+ struct tty_ldisc ld;
+
+ if (tty_ldisc_get(i, &ld) < 0)
+ return 0;
+ seq_printf(m, "%-10s %2d\n", ld.ops->name ? ld.ops->name : "???", i);
+ tty_ldisc_put(ld.ops);
+ return 0;
+}
+
+static const struct seq_operations tty_ldiscs_seq_ops = {
+ .start = tty_ldiscs_seq_start,
+ .next = tty_ldiscs_seq_next,
+ .stop = tty_ldiscs_seq_stop,
+ .show = tty_ldiscs_seq_show,
+};
+
+static int proc_tty_ldiscs_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &tty_ldiscs_seq_ops);
+}
+
+const struct file_operations tty_ldiscs_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = proc_tty_ldiscs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+/**
+ * tty_ldisc_assign - set ldisc on a tty
+ * @tty: tty to assign
+ * @ld: line discipline
+ *
+ * Install an instance of a line discipline into a tty structure. The
+ * ldisc must have a reference count above zero to ensure it remains/
+ * The tty instance refcount starts at zero.
+ *
+ * Locking:
+ * Caller must hold references
+ */
+
+static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
+{
+ ld->refcount = 0;
+ tty->ldisc = *ld;
+}
+
+/**
+ * tty_ldisc_try - internal helper
+ * @tty: the tty
+ *
+ * Make a single attempt to grab and bump the refcount on
+ * the tty ldisc. Return 0 on failure or 1 on success. This is
+ * used to implement both the waiting and non waiting versions
+ * of tty_ldisc_ref
+ *
+ * Locking: takes tty_ldisc_lock
+ */
+
+static int tty_ldisc_try(struct tty_struct *tty)
+{
+ unsigned long flags;
+ struct tty_ldisc *ld;
+ int ret = 0;
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ ld = &tty->ldisc;
+ if (test_bit(TTY_LDISC, &tty->flags)) {
+ ld->refcount++;
+ ret = 1;
+ }
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ return ret;
+}
+
+/**
+ * tty_ldisc_ref_wait - wait for the tty ldisc
+ * @tty: tty device
+ *
+ * Dereference the line discipline for the terminal and take a
+ * reference to it. If the line discipline is in flux then
+ * wait patiently until it changes.
+ *
+ * Note: Must not be called from an IRQ/timer context. The caller
+ * must also be careful not to hold other locks that will deadlock
+ * against a discipline change, such as an existing ldisc reference
+ * (which we check for)
+ *
+ * Locking: call functions take tty_ldisc_lock
+ */
+
+struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
+{
+ /* wait_event is a macro */
+ wait_event(tty_ldisc_wait, tty_ldisc_try(tty));
+ if (tty->ldisc.refcount == 0)
+ printk(KERN_ERR "tty_ldisc_ref_wait\n");
+ return &tty->ldisc;
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
+
+/**
+ * tty_ldisc_ref - get the tty ldisc
+ * @tty: tty device
+ *
+ * Dereference the line discipline for the terminal and take a
+ * reference to it. If the line discipline is in flux then
+ * return NULL. Can be called from IRQ and timer functions.
+ *
+ * Locking: called functions take tty_ldisc_lock
+ */
+
+struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
+{
+ if (tty_ldisc_try(tty))
+ return &tty->ldisc;
+ return NULL;
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_ref);
+
+/**
+ * tty_ldisc_deref - free a tty ldisc reference
+ * @ld: reference to free up
+ *
+ * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
+ * be called in IRQ context.
+ *
+ * Locking: takes tty_ldisc_lock
+ */
+
+void tty_ldisc_deref(struct tty_ldisc *ld)
+{
+ unsigned long flags;
+
+ BUG_ON(ld == NULL);
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ if (ld->refcount == 0)
+ printk(KERN_ERR "tty_ldisc_deref: no references.\n");
+ else
+ ld->refcount--;
+ if (ld->refcount == 0)
+ wake_up(&tty_ldisc_wait);
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_deref);
+
+/**
+ * tty_ldisc_enable - allow ldisc use
+ * @tty: terminal to activate ldisc on
+ *
+ * Set the TTY_LDISC flag when the line discipline can be called
+ * again. Do necessary wakeups for existing sleepers.
+ *
+ * Note: nobody should set this bit except via this function. Clearing
+ * directly is allowed.
+ */
+
+void tty_ldisc_enable(struct tty_struct *tty)
+{
+ set_bit(TTY_LDISC, &tty->flags);
+ wake_up(&tty_ldisc_wait);
+}
+
+/**
+ * tty_set_termios_ldisc - set ldisc field
+ * @tty: tty structure
+ * @num: line discipline number
+ *
+ * This is probably overkill for real world processors but
+ * they are not on hot paths so a little discipline won't do
+ * any harm.
+ *
+ * Locking: takes termios_mutex
+ */
+
+static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
+{
+ mutex_lock(&tty->termios_mutex);
+ tty->termios->c_line = num;
+ mutex_unlock(&tty->termios_mutex);
+}
+
+
+/**
+ * tty_ldisc_restore - helper for tty ldisc change
+ * @tty: tty to recover
+ * @old: previous ldisc
+ *
+ * Restore the previous line discipline or N_TTY when a line discipline
+ * change fails due to an open error
+ */
+
+static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
+{
+ char buf[64];
+ struct tty_ldisc new_ldisc;
+
+ /* There is an outstanding reference here so this is safe */
+ tty_ldisc_get(old->ops->num, old);
+ tty_ldisc_assign(tty, old);
+ tty_set_termios_ldisc(tty, old->ops->num);
+ if (old->ops->open && (old->ops->open(tty) < 0)) {
+ tty_ldisc_put(old->ops);
+ /* This driver is always present */
+ if (tty_ldisc_get(N_TTY, &new_ldisc) < 0)
+ panic("n_tty: get");
+ tty_ldisc_assign(tty, &new_ldisc);
+ tty_set_termios_ldisc(tty, N_TTY);
+ if (new_ldisc.ops->open) {
+ int r = new_ldisc.ops->open(tty);
+ if (r < 0)
+ panic("Couldn't open N_TTY ldisc for "
+ "%s --- error %d.",
+ tty_name(tty, buf), r);
+ }
+ }
+}
+
+/**
+ * tty_set_ldisc - set line discipline
+ * @tty: the terminal to set
+ * @ldisc: the line discipline
+ *
+ * Set the discipline of a tty line. Must be called from a process
+ * context.
+ *
+ * Locking: takes tty_ldisc_lock.
+ * called functions take termios_mutex
+ */
+
+int tty_set_ldisc(struct tty_struct *tty, int ldisc)
+{
+ int retval;
+ struct tty_ldisc o_ldisc, new_ldisc;
+ int work;
+ unsigned long flags;
+ struct tty_struct *o_tty;
+
+restart:
+ /* This is a bit ugly for now but means we can break the 'ldisc
+ is part of the tty struct' assumption later */
+ retval = tty_ldisc_get(ldisc, &new_ldisc);
+ if (retval)
+ return retval;
+
+ /*
+ * Problem: What do we do if this blocks ?
+ */
+
+ tty_wait_until_sent(tty, 0);
+
+ if (tty->ldisc.ops->num == ldisc) {
+ tty_ldisc_put(new_ldisc.ops);
+ return 0;
+ }
+
+ /*
+ * No more input please, we are switching. The new ldisc
+ * will update this value in the ldisc open function
+ */
+
+ tty->receive_room = 0;
+
+ o_ldisc = tty->ldisc;
+ o_tty = tty->link;
+
+ /*
+ * Make sure we don't change while someone holds a
+ * reference to the line discipline. The TTY_LDISC bit
+ * prevents anyone taking a reference once it is clear.
+ * We need the lock to avoid racing reference takers.
+ */
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) {
+ if (tty->ldisc.refcount) {
+ /* Free the new ldisc we grabbed. Must drop the lock
+ first. */
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ tty_ldisc_put(o_ldisc.ops);
+ /*
+ * There are several reasons we may be busy, including
+ * random momentary I/O traffic. We must therefore
+ * retry. We could distinguish between blocking ops
+ * and retries if we made tty_ldisc_wait() smarter.
+ * That is up for discussion.
+ */
+ if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
+ return -ERESTARTSYS;
+ goto restart;
+ }
+ if (o_tty && o_tty->ldisc.refcount) {
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ tty_ldisc_put(o_tty->ldisc.ops);
+ if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0)
+ return -ERESTARTSYS;
+ goto restart;
+ }
+ }
+ /*
+ * If the TTY_LDISC bit is set, then we are racing against
+ * another ldisc change
+ */
+ if (!test_bit(TTY_LDISC, &tty->flags)) {
+ struct tty_ldisc *ld;
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ tty_ldisc_put(new_ldisc.ops);
+ ld = tty_ldisc_ref_wait(tty);
+ tty_ldisc_deref(ld);
+ goto restart;
+ }
+
+ clear_bit(TTY_LDISC, &tty->flags);
+ if (o_tty)
+ clear_bit(TTY_LDISC, &o_tty->flags);
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+ /*
+ * From this point on we know nobody has an ldisc
+ * usage reference, nor can they obtain one until
+ * we say so later on.
+ */
+
+ work = cancel_delayed_work(&tty->buf.work);
+ /*
+ * Wait for ->hangup_work and ->buf.work handlers to terminate
+ * MUST NOT hold locks here.
+ */
+ flush_scheduled_work();
+ /* Shutdown the current discipline. */
+ if (o_ldisc.ops->close)
+ (o_ldisc.ops->close)(tty);
+
+ /* Now set up the new line discipline. */
+ tty_ldisc_assign(tty, &new_ldisc);
+ tty_set_termios_ldisc(tty, ldisc);
+ if (new_ldisc.ops->open)
+ retval = (new_ldisc.ops->open)(tty);
+ if (retval < 0) {
+ tty_ldisc_put(new_ldisc.ops);
+ tty_ldisc_restore(tty, &o_ldisc);
+ }
+ /* At this point we hold a reference to the new ldisc and a
+ a reference to the old ldisc. If we ended up flipping back
+ to the existing ldisc we have two references to it */
+
+ if (tty->ldisc.ops->num != o_ldisc.ops->num && tty->ops->set_ldisc)
+ tty->ops->set_ldisc(tty);
+
+ tty_ldisc_put(o_ldisc.ops);
+
+ /*
+ * Allow ldisc referencing to occur as soon as the driver
+ * ldisc callback completes.
+ */
+
+ tty_ldisc_enable(tty);
+ if (o_tty)
+ tty_ldisc_enable(o_tty);
+
+ /* Restart it in case no characters kick it off. Safe if
+ already running */
+ if (work)
+ schedule_delayed_work(&tty->buf.work, 1);
+ return retval;
+}
+
+
+/**
+ * tty_ldisc_setup - open line discipline
+ * @tty: tty being shut down
+ * @o_tty: pair tty for pty/tty pairs
+ *
+ * Called during the initial open of a tty/pty pair in order to set up the
+ * line discplines and bind them to the tty.
+ */
+
+int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
+{
+ struct tty_ldisc *ld = &tty->ldisc;
+ int retval;
+
+ if (ld->ops->open) {
+ retval = (ld->ops->open)(tty);
+ if (retval)
+ return retval;
+ }
+ if (o_tty && o_tty->ldisc.ops->open) {
+ retval = (o_tty->ldisc.ops->open)(o_tty);
+ if (retval) {
+ if (ld->ops->close)
+ (ld->ops->close)(tty);
+ return retval;
+ }
+ tty_ldisc_enable(o_tty);
+ }
+ tty_ldisc_enable(tty);
+ return 0;
+}
+
+/**
+ * tty_ldisc_release - release line discipline
+ * @tty: tty being shut down
+ * @o_tty: pair tty for pty/tty pairs
+ *
+ * Called during the final close of a tty/pty pair in order to shut down the
+ * line discpline layer.
+ */
+
+void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
+{
+ unsigned long flags;
+ struct tty_ldisc ld;
+ /*
+ * Prevent flush_to_ldisc() from rescheduling the work for later. Then
+ * kill any delayed work. As this is the final close it does not
+ * race with the set_ldisc code path.
+ */
+ clear_bit(TTY_LDISC, &tty->flags);
+ cancel_delayed_work(&tty->buf.work);
+
+ /*
+ * Wait for ->hangup_work and ->buf.work handlers to terminate
+ */
+
+ flush_scheduled_work();
+
+ /*
+ * Wait for any short term users (we know they are just driver
+ * side waiters as the file is closing so user count on the file
+ * side is zero.
+ */
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ while (tty->ldisc.refcount) {
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0);
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ }
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ /*
+ * Shutdown the current line discipline, and reset it to N_TTY.
+ *
+ * FIXME: this MUST get fixed for the new reflocking
+ */
+ if (tty->ldisc.ops->close)
+ (tty->ldisc.ops->close)(tty);
+ tty_ldisc_put(tty->ldisc.ops);
+
+ /*
+ * Switch the line discipline back
+ */
+ WARN_ON(tty_ldisc_get(N_TTY, &ld));
+ tty_ldisc_assign(tty, &ld);
+ tty_set_termios_ldisc(tty, N_TTY);
+ if (o_tty) {
+ /* FIXME: could o_tty be in setldisc here ? */
+ clear_bit(TTY_LDISC, &o_tty->flags);
+ if (o_tty->ldisc.ops->close)
+ (o_tty->ldisc.ops->close)(o_tty);
+ tty_ldisc_put(o_tty->ldisc.ops);
+ WARN_ON(tty_ldisc_get(N_TTY, &ld));
+ tty_ldisc_assign(o_tty, &ld);
+ tty_set_termios_ldisc(o_tty, N_TTY);
+ }
+}
+
+/**
+ * tty_ldisc_init - ldisc setup for new tty
+ * @tty: tty being allocated
+ *
+ * Set up the line discipline objects for a newly allocated tty. Note that
+ * the tty structure is not completely set up when this call is made.
+ */
+
+void tty_ldisc_init(struct tty_struct *tty)
+{
+ struct tty_ldisc ld;
+ if (tty_ldisc_get(N_TTY, &ld) < 0)
+ panic("n_tty: init_tty");
+ tty_ldisc_assign(tty, &ld);
+}
+
+void tty_ldisc_begin(void)
+{
+ /* Setup the default TTY line discipline. */
+ (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
+}
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index eebfad2777d..c2ae52dd53d 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -481,10 +481,10 @@ static struct class *vc_class;
void vcs_make_sysfs(struct tty_struct *tty)
{
- device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
- "vcs%u", tty->index + 1);
- device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
- "vcsa%u", tty->index + 1);
+ device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
+ NULL, "vcs%u", tty->index + 1);
+ device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
+ NULL, "vcsa%u", tty->index + 1);
}
void vcs_remove_sysfs(struct tty_struct *tty)
@@ -499,7 +499,7 @@ int __init vcs_init(void)
panic("unable to get major %d for vcs device", VCS_MAJOR);
vc_class = class_create(THIS_MODULE, "vc");
- device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), "vcs");
- device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), "vcsa");
+ device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
+ device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
return 0;
}
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index e5da98d8f9c..7a70a40ad63 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -886,10 +886,10 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
state[i].cur_part = 0;
for (j = 0; j < MAX_PARTITIONS; ++j)
state[i].part_stat_rwi[j] = VIOT_IDLE;
- device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i),
- "iseries!vt%d", i);
- device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
- "iseries!nvt%d", i);
+ device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i),
+ NULL, "iseries!vt%d", i);
+ device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
+ NULL, "iseries!nvt%d", i);
printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries "
"resource %10.10s type %4.4s, model %3.3s\n",
i, viotape_unitinfo[i].rsrcname,
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index dc17fe3a88b..d0f4eb6fdb7 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -46,6 +46,9 @@ static char *in, *inbuf;
/* The operations for our console. */
static struct hv_ops virtio_cons;
+/* The hvc device */
+static struct hvc_struct *hvc;
+
/*D:310 The put_chars() callback is pretty straightforward.
*
* We turn the characters into a scatter-gather list, add it to the output
@@ -134,6 +137,27 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int))
return hvc_instantiate(0, 0, &virtio_cons);
}
+/*
+ * we support only one console, the hvc struct is a global var
+ * There is no need to do anything
+ */
+static int notifier_add_vio(struct hvc_struct *hp, int data)
+{
+ hp->irq_requested = 1;
+ return 0;
+}
+
+static void notifier_del_vio(struct hvc_struct *hp, int data)
+{
+ hp->irq_requested = 0;
+}
+
+static void hvc_handle_input(struct virtqueue *vq)
+{
+ if (hvc_poll(hvc))
+ hvc_kick();
+}
+
/*D:370 Once we're further in boot, we get probed like any other virtio device.
* At this stage we set up the output virtqueue.
*
@@ -144,7 +168,6 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int))
static int __devinit virtcons_probe(struct virtio_device *dev)
{
int err;
- struct hvc_struct *hvc;
vdev = dev;
@@ -158,7 +181,7 @@ static int __devinit virtcons_probe(struct virtio_device *dev)
/* Find the input queue. */
/* FIXME: This is why we want to wean off hvc: we do nothing
* when input comes in. */
- in_vq = vdev->config->find_vq(vdev, 0, NULL);
+ in_vq = vdev->config->find_vq(vdev, 0, hvc_handle_input);
if (IS_ERR(in_vq)) {
err = PTR_ERR(in_vq);
goto free;
@@ -173,15 +196,18 @@ static int __devinit virtcons_probe(struct virtio_device *dev)
/* Start using the new console output. */
virtio_cons.get_chars = get_chars;
virtio_cons.put_chars = put_chars;
+ virtio_cons.notifier_add = notifier_add_vio;
+ virtio_cons.notifier_del = notifier_del_vio;
/* The first argument of hvc_alloc() is the virtual console number, so
- * we use zero. The second argument is the interrupt number; we
- * currently leave this as zero: it would be better not to use the
- * hvc mechanism and fix this (FIXME!).
+ * we use zero. The second argument is the parameter for the
+ * notification mechanism (like irq number). We currently leave this
+ * as zero, virtqueues have implicit notifications.
*
* The third argument is a "struct hv_ops" containing the put_chars()
- * and get_chars() pointers. The final argument is the output buffer
- * size: we can do any size, so we put PAGE_SIZE here. */
+ * get_chars(), notifier_add() and notifier_del() pointers.
+ * The final argument is the output buffer size: we can do any size,
+ * so we put PAGE_SIZE here. */
hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE);
if (IS_ERR(hvc)) {
err = PTR_ERR(hvc);
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index f17ac043b55..69c5afe97f1 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -85,7 +85,7 @@ static irqreturn_t scc_rx_int(int irq, void *data);
static irqreturn_t scc_stat_int(int irq, void *data);
static irqreturn_t scc_spcond_int(int irq, void *data);
static void scc_setsignals(struct scc_port *port, int dtr, int rts);
-static void scc_break_ctl(struct tty_struct *tty, int break_state);
+static int scc_break_ctl(struct tty_struct *tty, int break_state);
static struct tty_driver *scc_driver;
@@ -942,7 +942,7 @@ static int scc_ioctl(struct tty_struct *tty, struct file *file,
}
-static void scc_break_ctl(struct tty_struct *tty, int break_state)
+static int scc_break_ctl(struct tty_struct *tty, int break_state)
{
struct scc_port *port = (struct scc_port *)tty->driver_data;
unsigned long flags;
@@ -952,6 +952,7 @@ static void scc_break_ctl(struct tty_struct *tty, int break_state)
SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK,
break_state ? TCR_SEND_BREAK : 0);
local_irq_restore(flags);
+ return 0;
}
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 935f1c207a1..82a51f38a54 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -261,7 +261,7 @@ static void notify_update(struct vc_data *vc)
#ifdef VT_BUF_VRAM_ONLY
#define DO_UPDATE(vc) 0
#else
-#define DO_UPDATE(vc) CON_IS_VISIBLE(vc)
+#define DO_UPDATE(vc) (CON_IS_VISIBLE(vc) && !console_blanked)
#endif
static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewed)
@@ -2211,7 +2211,7 @@ rescan_last_byte:
c = 0xfffd;
tc = c;
} else { /* no utf or alternate charset mode */
- tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c];
+ tc = vc_translate(vc, c);
}
param.c = tc;
@@ -2749,8 +2749,8 @@ static int con_open(struct tty_struct *tty, struct file *filp)
tty->termios->c_iflag |= IUTF8;
else
tty->termios->c_iflag &= ~IUTF8;
- release_console_sem();
vcs_make_sysfs(tty);
+ release_console_sem();
return ret;
}
}
@@ -2775,8 +2775,8 @@ static void con_close(struct tty_struct *tty, struct file *filp)
if (vc)
vc->vc_tty = NULL;
tty->driver_data = NULL;
- release_console_sem();
vcs_remove_sysfs(tty);
+ release_console_sem();
mutex_unlock(&tty_mutex);
/*
* tty_mutex is released, but we still hold BKL, so there is
@@ -3425,9 +3425,10 @@ int register_con_driver(const struct consw *csw, int first, int last)
if (retval)
goto err;
- con_driver->dev = device_create(vtconsole_class, NULL,
- MKDEV(0, con_driver->node),
- "vtcon%i", con_driver->node);
+ con_driver->dev = device_create_drvdata(vtconsole_class, NULL,
+ MKDEV(0, con_driver->node),
+ NULL, "vtcon%i",
+ con_driver->node);
if (IS_ERR(con_driver->dev)) {
printk(KERN_WARNING "Unable to create device for %s; "
@@ -3535,9 +3536,10 @@ static int __init vtconsole_class_init(void)
struct con_driver *con = &registered_con_driver[i];
if (con->con && !con->dev) {
- con->dev = device_create(vtconsole_class, NULL,
- MKDEV(0, con->node),
- "vtcon%i", con->node);
+ con->dev = device_create_drvdata(vtconsole_class, NULL,
+ MKDEV(0, con->node),
+ NULL, "vtcon%i",
+ con->node);
if (IS_ERR(con->dev)) {
printk(KERN_WARNING "Unable to create "
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 1e1b81e57cd..8bfee5fb722 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -87,7 +87,6 @@
#include <linux/mutex.h>
#include <linux/smp_lock.h>
#include <linux/sysctl.h>
-#include <linux/version.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/platform_device.h>
@@ -658,8 +657,9 @@ static int __devinit hwicap_setup(struct device *dev, int id,
dev_err(dev, "cdev_add() failed\n");
goto failed3;
}
- /* devfs_mk_cdev(devt, S_IFCHR|S_IRUGO|S_IWUGO, DRIVER_NAME); */
- device_create(icap_class, dev, devt, "%s%d", DRIVER_NAME, id);
+
+ device_create_drvdata(icap_class, dev, devt, NULL,
+ "%s%d", DRIVER_NAME, id);
return 0; /* success */
failed3:
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index ee1df0d45e8..8d6a3ff0267 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -589,7 +589,7 @@ static ssize_t show_cpus(cpumask_t mask, char *buf)
ssize_t i = 0;
unsigned int cpu;
- for_each_cpu_mask(cpu, mask) {
+ for_each_cpu_mask_nr(cpu, mask) {
if (i)
i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), " ");
i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), "%u", cpu);
@@ -835,7 +835,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
}
#endif
- for_each_cpu_mask(j, policy->cpus) {
+ for_each_cpu_mask_nr(j, policy->cpus) {
if (cpu == j)
continue;
@@ -898,14 +898,14 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
}
spin_lock_irqsave(&cpufreq_driver_lock, flags);
- for_each_cpu_mask(j, policy->cpus) {
+ for_each_cpu_mask_nr(j, policy->cpus) {
per_cpu(cpufreq_cpu_data, j) = policy;
per_cpu(policy_cpu, j) = policy->cpu;
}
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
/* symlink affected CPUs */
- for_each_cpu_mask(j, policy->cpus) {
+ for_each_cpu_mask_nr(j, policy->cpus) {
if (j == cpu)
continue;
if (!cpu_online(j))
@@ -945,7 +945,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
err_out_unregister:
spin_lock_irqsave(&cpufreq_driver_lock, flags);
- for_each_cpu_mask(j, policy->cpus)
+ for_each_cpu_mask_nr(j, policy->cpus)
per_cpu(cpufreq_cpu_data, j) = NULL;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
@@ -1028,7 +1028,7 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
* the sysfs links afterwards.
*/
if (unlikely(cpus_weight(data->cpus) > 1)) {
- for_each_cpu_mask(j, data->cpus) {
+ for_each_cpu_mask_nr(j, data->cpus) {
if (j == cpu)
continue;
per_cpu(cpufreq_cpu_data, j) = NULL;
@@ -1038,7 +1038,7 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
if (unlikely(cpus_weight(data->cpus) > 1)) {
- for_each_cpu_mask(j, data->cpus) {
+ for_each_cpu_mask_nr(j, data->cpus) {
if (j == cpu)
continue;
dprintk("removing link for cpu %u\n", j);
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 5d3a04ba6ad..fe565ee4375 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -497,7 +497,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
return rc;
}
- for_each_cpu_mask(j, policy->cpus) {
+ for_each_cpu_mask_nr(j, policy->cpus) {
struct cpu_dbs_info_s *j_dbs_info;
j_dbs_info = &per_cpu(cpu_dbs_info, j);
j_dbs_info->cur_policy = policy;
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index d2af20dda38..33855cb3cf1 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -367,7 +367,7 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
/* Get Idle Time */
idle_ticks = UINT_MAX;
- for_each_cpu_mask(j, policy->cpus) {
+ for_each_cpu_mask_nr(j, policy->cpus) {
cputime64_t total_idle_ticks;
unsigned int tmp_idle_ticks;
struct cpu_dbs_info_s *j_dbs_info;
@@ -521,7 +521,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
return rc;
}
- for_each_cpu_mask(j, policy->cpus) {
+ for_each_cpu_mask_nr(j, policy->cpus) {
struct cpu_dbs_info_s *j_dbs_info;
j_dbs_info = &per_cpu(cpu_dbs_info, j);
j_dbs_info->cur_policy = policy;
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index cb2ac01a41a..32244aa7cc0 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -30,16 +30,18 @@
/**
* A few values needed by the userspace governor
*/
-static unsigned int cpu_max_freq[NR_CPUS];
-static unsigned int cpu_min_freq[NR_CPUS];
-static unsigned int cpu_cur_freq[NR_CPUS]; /* current CPU freq */
-static unsigned int cpu_set_freq[NR_CPUS]; /* CPU freq desired by userspace */
-static unsigned int cpu_is_managed[NR_CPUS];
+static DEFINE_PER_CPU(unsigned int, cpu_max_freq);
+static DEFINE_PER_CPU(unsigned int, cpu_min_freq);
+static DEFINE_PER_CPU(unsigned int, cpu_cur_freq); /* current CPU freq */
+static DEFINE_PER_CPU(unsigned int, cpu_set_freq); /* CPU freq desired by
+ userspace */
+static DEFINE_PER_CPU(unsigned int, cpu_is_managed);
static DEFINE_MUTEX (userspace_mutex);
static int cpus_using_userspace_governor;
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg)
+#define dprintk(msg...) \
+ cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg)
/* keep track of frequency transitions */
static int
@@ -48,12 +50,12 @@ userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
{
struct cpufreq_freqs *freq = data;
- if (!cpu_is_managed[freq->cpu])
+ if (!per_cpu(cpu_is_managed, freq->cpu))
return 0;
dprintk("saving cpu_cur_freq of cpu %u to be %u kHz\n",
freq->cpu, freq->new);
- cpu_cur_freq[freq->cpu] = freq->new;
+ per_cpu(cpu_cur_freq, freq->cpu) = freq->new;
return 0;
}
@@ -77,15 +79,15 @@ static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
dprintk("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
mutex_lock(&userspace_mutex);
- if (!cpu_is_managed[policy->cpu])
+ if (!per_cpu(cpu_is_managed, policy->cpu))
goto err;
- cpu_set_freq[policy->cpu] = freq;
+ per_cpu(cpu_set_freq, policy->cpu) = freq;
- if (freq < cpu_min_freq[policy->cpu])
- freq = cpu_min_freq[policy->cpu];
- if (freq > cpu_max_freq[policy->cpu])
- freq = cpu_max_freq[policy->cpu];
+ if (freq < per_cpu(cpu_min_freq, policy->cpu))
+ freq = per_cpu(cpu_min_freq, policy->cpu);
+ if (freq > per_cpu(cpu_max_freq, policy->cpu))
+ freq = per_cpu(cpu_max_freq, policy->cpu);
/*
* We're safe from concurrent calls to ->target() here
@@ -104,7 +106,7 @@ static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
static ssize_t show_speed(struct cpufreq_policy *policy, char *buf)
{
- return sprintf(buf, "%u\n", cpu_cur_freq[policy->cpu]);
+ return sprintf(buf, "%u\n", per_cpu(cpu_cur_freq, policy->cpu));
}
static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
@@ -127,12 +129,17 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
}
cpus_using_userspace_governor++;
- cpu_is_managed[cpu] = 1;
- cpu_min_freq[cpu] = policy->min;
- cpu_max_freq[cpu] = policy->max;
- cpu_cur_freq[cpu] = policy->cur;
- cpu_set_freq[cpu] = policy->cur;
- dprintk("managing cpu %u started (%u - %u kHz, currently %u kHz)\n", cpu, cpu_min_freq[cpu], cpu_max_freq[cpu], cpu_cur_freq[cpu]);
+ per_cpu(cpu_is_managed, cpu) = 1;
+ per_cpu(cpu_min_freq, cpu) = policy->min;
+ per_cpu(cpu_max_freq, cpu) = policy->max;
+ per_cpu(cpu_cur_freq, cpu) = policy->cur;
+ per_cpu(cpu_set_freq, cpu) = policy->cur;
+ dprintk("managing cpu %u started "
+ "(%u - %u kHz, currently %u kHz)\n",
+ cpu,
+ per_cpu(cpu_min_freq, cpu),
+ per_cpu(cpu_max_freq, cpu),
+ per_cpu(cpu_cur_freq, cpu));
mutex_unlock(&userspace_mutex);
break;
@@ -145,34 +152,34 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
CPUFREQ_TRANSITION_NOTIFIER);
}
- cpu_is_managed[cpu] = 0;
- cpu_min_freq[cpu] = 0;
- cpu_max_freq[cpu] = 0;
- cpu_set_freq[cpu] = 0;
+ per_cpu(cpu_is_managed, cpu) = 0;
+ per_cpu(cpu_min_freq, cpu) = 0;
+ per_cpu(cpu_max_freq, cpu) = 0;
+ per_cpu(cpu_set_freq, cpu) = 0;
dprintk("managing cpu %u stopped\n", cpu);
mutex_unlock(&userspace_mutex);
break;
case CPUFREQ_GOV_LIMITS:
mutex_lock(&userspace_mutex);
- dprintk("limit event for cpu %u: %u - %u kHz,"
+ dprintk("limit event for cpu %u: %u - %u kHz, "
"currently %u kHz, last set to %u kHz\n",
cpu, policy->min, policy->max,
- cpu_cur_freq[cpu], cpu_set_freq[cpu]);
- if (policy->max < cpu_set_freq[cpu]) {
+ per_cpu(cpu_cur_freq, cpu),
+ per_cpu(cpu_set_freq, cpu));
+ if (policy->max < per_cpu(cpu_set_freq, cpu)) {
__cpufreq_driver_target(policy, policy->max,
CPUFREQ_RELATION_H);
- }
- else if (policy->min > cpu_set_freq[cpu]) {
+ } else if (policy->min > per_cpu(cpu_set_freq, cpu)) {
__cpufreq_driver_target(policy, policy->min,
CPUFREQ_RELATION_L);
- }
- else {
- __cpufreq_driver_target(policy, cpu_set_freq[cpu],
+ } else {
+ __cpufreq_driver_target(policy,
+ per_cpu(cpu_set_freq, cpu),
CPUFREQ_RELATION_L);
}
- cpu_min_freq[cpu] = policy->min;
- cpu_max_freq[cpu] = policy->max;
- cpu_cur_freq[cpu] = policy->cur;
+ per_cpu(cpu_min_freq, cpu) = policy->min;
+ per_cpu(cpu_max_freq, cpu) = policy->max;
+ per_cpu(cpu_cur_freq, cpu) = policy->cur;
mutex_unlock(&userspace_mutex);
break;
}
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index e949618b9be..31a0e0b455b 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -21,7 +21,8 @@ static int __init cpuidle_sysfs_setup(char *unused)
}
__setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup);
-static ssize_t show_available_governors(struct sys_device *dev, char *buf)
+static ssize_t show_available_governors(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
ssize_t i = 0;
struct cpuidle_governor *tmp;
@@ -39,7 +40,8 @@ out:
return i;
}
-static ssize_t show_current_driver(struct sys_device *dev, char *buf)
+static ssize_t show_current_driver(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
ssize_t ret;
@@ -53,7 +55,8 @@ static ssize_t show_current_driver(struct sys_device *dev, char *buf)
return ret;
}
-static ssize_t show_current_governor(struct sys_device *dev, char *buf)
+static ssize_t show_current_governor(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
ssize_t ret;
@@ -68,6 +71,7 @@ static ssize_t show_current_governor(struct sys_device *dev, char *buf)
}
static ssize_t store_current_governor(struct sys_device *dev,
+ struct sysdev_attribute *attr,
const char *buf, size_t count)
{
char gov_name[CPUIDLE_NAME_LEN];
diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c
index bf5b92f86df..ec249d2db63 100644
--- a/drivers/dca/dca-core.c
+++ b/drivers/dca/dca-core.c
@@ -28,13 +28,29 @@
#include <linux/device.h>
#include <linux/dca.h>
-MODULE_LICENSE("GPL");
+#define DCA_VERSION "1.4"
-/* For now we're assuming a single, global, DCA provider for the system. */
+MODULE_VERSION(DCA_VERSION);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Intel Corporation");
static DEFINE_SPINLOCK(dca_lock);
-static struct dca_provider *global_dca = NULL;
+static LIST_HEAD(dca_providers);
+
+static struct dca_provider *dca_find_provider_by_dev(struct device *dev)
+{
+ struct dca_provider *dca, *ret = NULL;
+
+ list_for_each_entry(dca, &dca_providers, node) {
+ if ((!dev) || (dca->ops->dev_managed(dca, dev))) {
+ ret = dca;
+ break;
+ }
+ }
+
+ return ret;
+}
/**
* dca_add_requester - add a dca client to the list
@@ -42,25 +58,39 @@ static struct dca_provider *global_dca = NULL;
*/
int dca_add_requester(struct device *dev)
{
- int err, slot;
+ struct dca_provider *dca;
+ int err, slot = -ENODEV;
- if (!global_dca)
- return -ENODEV;
+ if (!dev)
+ return -EFAULT;
spin_lock(&dca_lock);
- slot = global_dca->ops->add_requester(global_dca, dev);
- spin_unlock(&dca_lock);
- if (slot < 0)
+
+ /* check if the requester has not been added already */
+ dca = dca_find_provider_by_dev(dev);
+ if (dca) {
+ spin_unlock(&dca_lock);
+ return -EEXIST;
+ }
+
+ list_for_each_entry(dca, &dca_providers, node) {
+ slot = dca->ops->add_requester(dca, dev);
+ if (slot >= 0)
+ break;
+ }
+ if (slot < 0) {
+ spin_unlock(&dca_lock);
return slot;
+ }
- err = dca_sysfs_add_req(global_dca, dev, slot);
+ err = dca_sysfs_add_req(dca, dev, slot);
if (err) {
- spin_lock(&dca_lock);
- global_dca->ops->remove_requester(global_dca, dev);
+ dca->ops->remove_requester(dca, dev);
spin_unlock(&dca_lock);
return err;
}
+ spin_unlock(&dca_lock);
return 0;
}
EXPORT_SYMBOL_GPL(dca_add_requester);
@@ -71,30 +101,78 @@ EXPORT_SYMBOL_GPL(dca_add_requester);
*/
int dca_remove_requester(struct device *dev)
{
+ struct dca_provider *dca;
int slot;
- if (!global_dca)
- return -ENODEV;
+
+ if (!dev)
+ return -EFAULT;
spin_lock(&dca_lock);
- slot = global_dca->ops->remove_requester(global_dca, dev);
- spin_unlock(&dca_lock);
- if (slot < 0)
+ dca = dca_find_provider_by_dev(dev);
+ if (!dca) {
+ spin_unlock(&dca_lock);
+ return -ENODEV;
+ }
+ slot = dca->ops->remove_requester(dca, dev);
+ if (slot < 0) {
+ spin_unlock(&dca_lock);
return slot;
+ }
- dca_sysfs_remove_req(global_dca, slot);
+ dca_sysfs_remove_req(dca, slot);
+
+ spin_unlock(&dca_lock);
return 0;
}
EXPORT_SYMBOL_GPL(dca_remove_requester);
/**
- * dca_get_tag - return the dca tag for the given cpu
+ * dca_common_get_tag - return the dca tag (serves both new and old api)
+ * @dev - the device that wants dca service
* @cpu - the cpuid as returned by get_cpu()
*/
-u8 dca_get_tag(int cpu)
+u8 dca_common_get_tag(struct device *dev, int cpu)
{
- if (!global_dca)
+ struct dca_provider *dca;
+ u8 tag;
+
+ spin_lock(&dca_lock);
+
+ dca = dca_find_provider_by_dev(dev);
+ if (!dca) {
+ spin_unlock(&dca_lock);
return -ENODEV;
- return global_dca->ops->get_tag(global_dca, cpu);
+ }
+ tag = dca->ops->get_tag(dca, dev, cpu);
+
+ spin_unlock(&dca_lock);
+ return tag;
+}
+
+/**
+ * dca3_get_tag - return the dca tag to the requester device
+ * for the given cpu (new api)
+ * @dev - the device that wants dca service
+ * @cpu - the cpuid as returned by get_cpu()
+ */
+u8 dca3_get_tag(struct device *dev, int cpu)
+{
+ if (!dev)
+ return -EFAULT;
+
+ return dca_common_get_tag(dev, cpu);
+}
+EXPORT_SYMBOL_GPL(dca3_get_tag);
+
+/**
+ * dca_get_tag - return the dca tag for the given cpu (old api)
+ * @cpu - the cpuid as returned by get_cpu()
+ */
+u8 dca_get_tag(int cpu)
+{
+ struct device *dev = NULL;
+
+ return dca_common_get_tag(dev, cpu);
}
EXPORT_SYMBOL_GPL(dca_get_tag);
@@ -140,12 +218,10 @@ int register_dca_provider(struct dca_provider *dca, struct device *dev)
{
int err;
- if (global_dca)
- return -EEXIST;
err = dca_sysfs_add_provider(dca, dev);
if (err)
return err;
- global_dca = dca;
+ list_add(&dca->node, &dca_providers);
blocking_notifier_call_chain(&dca_provider_chain,
DCA_PROVIDER_ADD, NULL);
return 0;
@@ -158,11 +234,9 @@ EXPORT_SYMBOL_GPL(register_dca_provider);
*/
void unregister_dca_provider(struct dca_provider *dca)
{
- if (!global_dca)
- return;
blocking_notifier_call_chain(&dca_provider_chain,
DCA_PROVIDER_REMOVE, NULL);
- global_dca = NULL;
+ list_del(&dca->node);
dca_sysfs_remove_provider(dca);
}
EXPORT_SYMBOL_GPL(unregister_dca_provider);
@@ -187,6 +261,7 @@ EXPORT_SYMBOL_GPL(dca_unregister_notify);
static int __init dca_init(void)
{
+ printk(KERN_ERR "dca service started, version %s\n", DCA_VERSION);
return dca_sysfs_init();
}
diff --git a/drivers/dca/dca-sysfs.c b/drivers/dca/dca-sysfs.c
index 011328faa5f..7af4b403bd2 100644
--- a/drivers/dca/dca-sysfs.c
+++ b/drivers/dca/dca-sysfs.c
@@ -13,9 +13,11 @@ static spinlock_t dca_idr_lock;
int dca_sysfs_add_req(struct dca_provider *dca, struct device *dev, int slot)
{
struct device *cd;
+ static int req_count;
- cd = device_create(dca_class, dca->cd, MKDEV(0, slot + 1),
- "requester%d", slot);
+ cd = device_create_drvdata(dca_class, dca->cd,
+ MKDEV(0, slot + 1), NULL,
+ "requester%d", req_count++);
if (IS_ERR(cd))
return PTR_ERR(cd);
return 0;
@@ -46,7 +48,8 @@ idr_try_again:
return err;
}
- cd = device_create(dca_class, dev, MKDEV(0, 0), "dca%d", dca->id);
+ cd = device_create_drvdata(dca_class, dev, MKDEV(0, 0), NULL,
+ "dca%d", dca->id);
if (IS_ERR(cd)) {
spin_lock(&dca_idr_lock);
idr_remove(&dca_idr, dca->id);
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 6239c3df30a..cd303901eb5 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -4,13 +4,14 @@
menuconfig DMADEVICES
bool "DMA Engine support"
- depends on (PCI && X86) || ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX || PPC
- depends on !HIGHMEM64G
+ depends on !HIGHMEM64G && HAS_DMA
help
DMA engines can do asynchronous data transfers without
involving the host CPU. Currently, this framework can be
used to offload memory copies in the network stack and
- RAID operations in the MD driver.
+ RAID operations in the MD driver. This menu only presents
+ DMA Device drivers supported by the configured arch, it may
+ be empty in some cases.
if DMADEVICES
@@ -37,6 +38,15 @@ config INTEL_IOP_ADMA
help
Enable support for the Intel(R) IOP Series RAID engines.
+config DW_DMAC
+ tristate "Synopsys DesignWare AHB DMA support"
+ depends on AVR32
+ select DMA_ENGINE
+ default y if CPU_AT32AP7000
+ help
+ Support the Synopsys DesignWare AHB DMA controller. This
+ can be integrated in chips such as the Atmel AT32ap7000.
+
config FSL_DMA
bool "Freescale MPC85xx/MPC83xx DMA support"
depends on PPC
@@ -46,6 +56,14 @@ config FSL_DMA
MPC8560/40, MPC8555, MPC8548 and MPC8641 processors.
The MPC8349, MPC8360 is also supported.
+config MV_XOR
+ bool "Marvell XOR engine support"
+ depends on PLAT_ORION
+ select ASYNC_CORE
+ select DMA_ENGINE
+ ---help---
+ Enable support for the Marvell XOR engine.
+
config DMA_ENGINE
bool
@@ -55,10 +73,19 @@ comment "DMA Clients"
config NET_DMA
bool "Network: TCP receive copy offload"
depends on DMA_ENGINE && NET
+ default (INTEL_IOATDMA || FSL_DMA)
help
This enables the use of DMA engines in the network stack to
offload receive copy-to-user operations, freeing CPU cycles.
- Since this is the main user of the DMA engine, it should be enabled;
- say Y here.
+
+ Say Y here if you enabled INTEL_IOATDMA or FSL_DMA, otherwise
+ say N.
+
+config DMATEST
+ tristate "DMA Test client"
+ depends on DMA_ENGINE
+ help
+ Simple DMA test client. Say N unless you're debugging a
+ DMA Device driver.
endif
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index c8036d94590..14f59527d4f 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -1,6 +1,9 @@
obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
obj-$(CONFIG_NET_DMA) += iovlock.o
+obj-$(CONFIG_DMATEST) += dmatest.o
obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
ioatdma-objs := ioat.o ioat_dma.o ioat_dca.o
obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
obj-$(CONFIG_FSL_DMA) += fsldma.o
+obj-$(CONFIG_MV_XOR) += mv_xor.o
+obj-$(CONFIG_DW_DMAC) += dw_dmac.o
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 97b329e7679..dc003a3a787 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -169,12 +169,18 @@ static void dma_client_chan_alloc(struct dma_client *client)
enum dma_state_client ack;
/* Find a channel */
- list_for_each_entry(device, &dma_device_list, global_node)
+ list_for_each_entry(device, &dma_device_list, global_node) {
+ /* Does the client require a specific DMA controller? */
+ if (client->slave && client->slave->dma_dev
+ && client->slave->dma_dev != device->dev)
+ continue;
+
list_for_each_entry(chan, &device->channels, device_node) {
if (!dma_chan_satisfies_mask(chan, client->cap_mask))
continue;
- desc = chan->device->device_alloc_chan_resources(chan);
+ desc = chan->device->device_alloc_chan_resources(
+ chan, client);
if (desc >= 0) {
ack = client->event_callback(client,
chan,
@@ -183,12 +189,14 @@ static void dma_client_chan_alloc(struct dma_client *client)
/* we are done once this client rejects
* an available resource
*/
- if (ack == DMA_ACK)
+ if (ack == DMA_ACK) {
dma_chan_get(chan);
- else if (ack == DMA_NAK)
+ chan->client_count++;
+ } else if (ack == DMA_NAK)
return;
}
}
+ }
}
enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie)
@@ -272,8 +280,10 @@ static void dma_clients_notify_removed(struct dma_chan *chan)
/* client was holding resources for this channel so
* free it
*/
- if (ack == DMA_ACK)
+ if (ack == DMA_ACK) {
dma_chan_put(chan);
+ chan->client_count--;
+ }
}
mutex_unlock(&dma_list_mutex);
@@ -285,6 +295,10 @@ static void dma_clients_notify_removed(struct dma_chan *chan)
*/
void dma_async_client_register(struct dma_client *client)
{
+ /* validate client data */
+ BUG_ON(dma_has_cap(DMA_SLAVE, client->cap_mask) &&
+ !client->slave);
+
mutex_lock(&dma_list_mutex);
list_add_tail(&client->global_node, &dma_client_list);
mutex_unlock(&dma_list_mutex);
@@ -313,8 +327,10 @@ void dma_async_client_unregister(struct dma_client *client)
ack = client->event_callback(client, chan,
DMA_RESOURCE_REMOVED);
- if (ack == DMA_ACK)
+ if (ack == DMA_ACK) {
dma_chan_put(chan);
+ chan->client_count--;
+ }
}
list_del(&client->global_node);
@@ -359,6 +375,10 @@ int dma_async_device_register(struct dma_device *device)
!device->device_prep_dma_memset);
BUG_ON(dma_has_cap(DMA_INTERRUPT, device->cap_mask) &&
!device->device_prep_dma_interrupt);
+ BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
+ !device->device_prep_slave_sg);
+ BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
+ !device->device_terminate_all);
BUG_ON(!device->device_alloc_chan_resources);
BUG_ON(!device->device_free_chan_resources);
@@ -378,7 +398,7 @@ int dma_async_device_register(struct dma_device *device)
chan->chan_id = chancnt++;
chan->dev.class = &dma_devclass;
- chan->dev.parent = NULL;
+ chan->dev.parent = device->dev;
snprintf(chan->dev.bus_id, BUS_ID_SIZE, "dma%dchan%d",
device->dev_id, chan->chan_id);
@@ -394,6 +414,7 @@ int dma_async_device_register(struct dma_device *device)
kref_get(&device->refcount);
kref_get(&device->refcount);
kref_init(&chan->refcount);
+ chan->client_count = 0;
chan->slow_ref = 0;
INIT_RCU_HEAD(&chan->rcu);
}
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
new file mode 100644
index 00000000000..a08d1970474
--- /dev/null
+++ b/drivers/dma/dmatest.c
@@ -0,0 +1,444 @@
+/*
+ * DMA Engine test module
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * 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/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/init.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/random.h>
+#include <linux/wait.h>
+
+static unsigned int test_buf_size = 16384;
+module_param(test_buf_size, uint, S_IRUGO);
+MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer");
+
+static char test_channel[BUS_ID_SIZE];
+module_param_string(channel, test_channel, sizeof(test_channel), S_IRUGO);
+MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)");
+
+static char test_device[BUS_ID_SIZE];
+module_param_string(device, test_device, sizeof(test_device), S_IRUGO);
+MODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)");
+
+static unsigned int threads_per_chan = 1;
+module_param(threads_per_chan, uint, S_IRUGO);
+MODULE_PARM_DESC(threads_per_chan,
+ "Number of threads to start per channel (default: 1)");
+
+static unsigned int max_channels;
+module_param(max_channels, uint, S_IRUGO);
+MODULE_PARM_DESC(nr_channels,
+ "Maximum number of channels to use (default: all)");
+
+/*
+ * Initialization patterns. All bytes in the source buffer has bit 7
+ * set, all bytes in the destination buffer has bit 7 cleared.
+ *
+ * Bit 6 is set for all bytes which are to be copied by the DMA
+ * engine. Bit 5 is set for all bytes which are to be overwritten by
+ * the DMA engine.
+ *
+ * The remaining bits are the inverse of a counter which increments by
+ * one for each byte address.
+ */
+#define PATTERN_SRC 0x80
+#define PATTERN_DST 0x00
+#define PATTERN_COPY 0x40
+#define PATTERN_OVERWRITE 0x20
+#define PATTERN_COUNT_MASK 0x1f
+
+struct dmatest_thread {
+ struct list_head node;
+ struct task_struct *task;
+ struct dma_chan *chan;
+ u8 *srcbuf;
+ u8 *dstbuf;
+};
+
+struct dmatest_chan {
+ struct list_head node;
+ struct dma_chan *chan;
+ struct list_head threads;
+};
+
+/*
+ * These are protected by dma_list_mutex since they're only used by
+ * the DMA client event callback
+ */
+static LIST_HEAD(dmatest_channels);
+static unsigned int nr_channels;
+
+static bool dmatest_match_channel(struct dma_chan *chan)
+{
+ if (test_channel[0] == '\0')
+ return true;
+ return strcmp(chan->dev.bus_id, test_channel) == 0;
+}
+
+static bool dmatest_match_device(struct dma_device *device)
+{
+ if (test_device[0] == '\0')
+ return true;
+ return strcmp(device->dev->bus_id, test_device) == 0;
+}
+
+static unsigned long dmatest_random(void)
+{
+ unsigned long buf;
+
+ get_random_bytes(&buf, sizeof(buf));
+ return buf;
+}
+
+static void dmatest_init_srcbuf(u8 *buf, unsigned int start, unsigned int len)
+{
+ unsigned int i;
+
+ for (i = 0; i < start; i++)
+ buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
+ for ( ; i < start + len; i++)
+ buf[i] = PATTERN_SRC | PATTERN_COPY
+ | (~i & PATTERN_COUNT_MASK);;
+ for ( ; i < test_buf_size; i++)
+ buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
+}
+
+static void dmatest_init_dstbuf(u8 *buf, unsigned int start, unsigned int len)
+{
+ unsigned int i;
+
+ for (i = 0; i < start; i++)
+ buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK);
+ for ( ; i < start + len; i++)
+ buf[i] = PATTERN_DST | PATTERN_OVERWRITE
+ | (~i & PATTERN_COUNT_MASK);
+ for ( ; i < test_buf_size; i++)
+ buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK);
+}
+
+static void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index,
+ unsigned int counter, bool is_srcbuf)
+{
+ u8 diff = actual ^ pattern;
+ u8 expected = pattern | (~counter & PATTERN_COUNT_MASK);
+ const char *thread_name = current->comm;
+
+ if (is_srcbuf)
+ pr_warning("%s: srcbuf[0x%x] overwritten!"
+ " Expected %02x, got %02x\n",
+ thread_name, index, expected, actual);
+ else if ((pattern & PATTERN_COPY)
+ && (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
+ pr_warning("%s: dstbuf[0x%x] not copied!"
+ " Expected %02x, got %02x\n",
+ thread_name, index, expected, actual);
+ else if (diff & PATTERN_SRC)
+ pr_warning("%s: dstbuf[0x%x] was copied!"
+ " Expected %02x, got %02x\n",
+ thread_name, index, expected, actual);
+ else
+ pr_warning("%s: dstbuf[0x%x] mismatch!"
+ " Expected %02x, got %02x\n",
+ thread_name, index, expected, actual);
+}
+
+static unsigned int dmatest_verify(u8 *buf, unsigned int start,
+ unsigned int end, unsigned int counter, u8 pattern,
+ bool is_srcbuf)
+{
+ unsigned int i;
+ unsigned int error_count = 0;
+ u8 actual;
+
+ for (i = start; i < end; i++) {
+ actual = buf[i];
+ if (actual != (pattern | (~counter & PATTERN_COUNT_MASK))) {
+ if (error_count < 32)
+ dmatest_mismatch(actual, pattern, i, counter,
+ is_srcbuf);
+ error_count++;
+ }
+ counter++;
+ }
+
+ if (error_count > 32)
+ pr_warning("%s: %u errors suppressed\n",
+ current->comm, error_count - 32);
+
+ return error_count;
+}
+
+/*
+ * This function repeatedly tests DMA transfers of various lengths and
+ * offsets until it is told to exit by kthread_stop(). There may be
+ * multiple threads running this function in parallel for a single
+ * channel, and there may be multiple channels being tested in
+ * parallel.
+ *
+ * Before each test, the source and destination buffer is initialized
+ * with a known pattern. This pattern is different depending on
+ * whether it's in an area which is supposed to be copied or
+ * overwritten, and different in the source and destination buffers.
+ * So if the DMA engine doesn't copy exactly what we tell it to copy,
+ * we'll notice.
+ */
+static int dmatest_func(void *data)
+{
+ struct dmatest_thread *thread = data;
+ struct dma_chan *chan;
+ const char *thread_name;
+ unsigned int src_off, dst_off, len;
+ unsigned int error_count;
+ unsigned int failed_tests = 0;
+ unsigned int total_tests = 0;
+ dma_cookie_t cookie;
+ enum dma_status status;
+ int ret;
+
+ thread_name = current->comm;
+
+ ret = -ENOMEM;
+ thread->srcbuf = kmalloc(test_buf_size, GFP_KERNEL);
+ if (!thread->srcbuf)
+ goto err_srcbuf;
+ thread->dstbuf = kmalloc(test_buf_size, GFP_KERNEL);
+ if (!thread->dstbuf)
+ goto err_dstbuf;
+
+ smp_rmb();
+ chan = thread->chan;
+ dma_chan_get(chan);
+
+ while (!kthread_should_stop()) {
+ total_tests++;
+
+ len = dmatest_random() % test_buf_size + 1;
+ src_off = dmatest_random() % (test_buf_size - len + 1);
+ dst_off = dmatest_random() % (test_buf_size - len + 1);
+
+ dmatest_init_srcbuf(thread->srcbuf, src_off, len);
+ dmatest_init_dstbuf(thread->dstbuf, dst_off, len);
+
+ cookie = dma_async_memcpy_buf_to_buf(chan,
+ thread->dstbuf + dst_off,
+ thread->srcbuf + src_off,
+ len);
+ if (dma_submit_error(cookie)) {
+ pr_warning("%s: #%u: submit error %d with src_off=0x%x "
+ "dst_off=0x%x len=0x%x\n",
+ thread_name, total_tests - 1, cookie,
+ src_off, dst_off, len);
+ msleep(100);
+ failed_tests++;
+ continue;
+ }
+ dma_async_memcpy_issue_pending(chan);
+
+ do {
+ msleep(1);
+ status = dma_async_memcpy_complete(
+ chan, cookie, NULL, NULL);
+ } while (status == DMA_IN_PROGRESS);
+
+ if (status == DMA_ERROR) {
+ pr_warning("%s: #%u: error during copy\n",
+ thread_name, total_tests - 1);
+ failed_tests++;
+ continue;
+ }
+
+ error_count = 0;
+
+ pr_debug("%s: verifying source buffer...\n", thread_name);
+ error_count += dmatest_verify(thread->srcbuf, 0, src_off,
+ 0, PATTERN_SRC, true);
+ error_count += dmatest_verify(thread->srcbuf, src_off,
+ src_off + len, src_off,
+ PATTERN_SRC | PATTERN_COPY, true);
+ error_count += dmatest_verify(thread->srcbuf, src_off + len,
+ test_buf_size, src_off + len,
+ PATTERN_SRC, true);
+
+ pr_debug("%s: verifying dest buffer...\n",
+ thread->task->comm);
+ error_count += dmatest_verify(thread->dstbuf, 0, dst_off,
+ 0, PATTERN_DST, false);
+ error_count += dmatest_verify(thread->dstbuf, dst_off,
+ dst_off + len, src_off,
+ PATTERN_SRC | PATTERN_COPY, false);
+ error_count += dmatest_verify(thread->dstbuf, dst_off + len,
+ test_buf_size, dst_off + len,
+ PATTERN_DST, false);
+
+ if (error_count) {
+ pr_warning("%s: #%u: %u errors with "
+ "src_off=0x%x dst_off=0x%x len=0x%x\n",
+ thread_name, total_tests - 1, error_count,
+ src_off, dst_off, len);
+ failed_tests++;
+ } else {
+ pr_debug("%s: #%u: No errors with "
+ "src_off=0x%x dst_off=0x%x len=0x%x\n",
+ thread_name, total_tests - 1,
+ src_off, dst_off, len);
+ }
+ }
+
+ ret = 0;
+ dma_chan_put(chan);
+ kfree(thread->dstbuf);
+err_dstbuf:
+ kfree(thread->srcbuf);
+err_srcbuf:
+ pr_notice("%s: terminating after %u tests, %u failures (status %d)\n",
+ thread_name, total_tests, failed_tests, ret);
+ return ret;
+}
+
+static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
+{
+ struct dmatest_thread *thread;
+ struct dmatest_thread *_thread;
+ int ret;
+
+ list_for_each_entry_safe(thread, _thread, &dtc->threads, node) {
+ ret = kthread_stop(thread->task);
+ pr_debug("dmatest: thread %s exited with status %d\n",
+ thread->task->comm, ret);
+ list_del(&thread->node);
+ kfree(thread);
+ }
+ kfree(dtc);
+}
+
+static enum dma_state_client dmatest_add_channel(struct dma_chan *chan)
+{
+ struct dmatest_chan *dtc;
+ struct dmatest_thread *thread;
+ unsigned int i;
+
+ dtc = kmalloc(sizeof(struct dmatest_chan), GFP_ATOMIC);
+ if (!dtc) {
+ pr_warning("dmatest: No memory for %s\n", chan->dev.bus_id);
+ return DMA_NAK;
+ }
+
+ dtc->chan = chan;
+ INIT_LIST_HEAD(&dtc->threads);
+
+ for (i = 0; i < threads_per_chan; i++) {
+ thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL);
+ if (!thread) {
+ pr_warning("dmatest: No memory for %s-test%u\n",
+ chan->dev.bus_id, i);
+ break;
+ }
+ thread->chan = dtc->chan;
+ smp_wmb();
+ thread->task = kthread_run(dmatest_func, thread, "%s-test%u",
+ chan->dev.bus_id, i);
+ if (IS_ERR(thread->task)) {
+ pr_warning("dmatest: Failed to run thread %s-test%u\n",
+ chan->dev.bus_id, i);
+ kfree(thread);
+ break;
+ }
+
+ /* srcbuf and dstbuf are allocated by the thread itself */
+
+ list_add_tail(&thread->node, &dtc->threads);
+ }
+
+ pr_info("dmatest: Started %u threads using %s\n", i, chan->dev.bus_id);
+
+ list_add_tail(&dtc->node, &dmatest_channels);
+ nr_channels++;
+
+ return DMA_ACK;
+}
+
+static enum dma_state_client dmatest_remove_channel(struct dma_chan *chan)
+{
+ struct dmatest_chan *dtc, *_dtc;
+
+ list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) {
+ if (dtc->chan == chan) {
+ list_del(&dtc->node);
+ dmatest_cleanup_channel(dtc);
+ pr_debug("dmatest: lost channel %s\n",
+ chan->dev.bus_id);
+ return DMA_ACK;
+ }
+ }
+
+ return DMA_DUP;
+}
+
+/*
+ * Start testing threads as new channels are assigned to us, and kill
+ * them when the channels go away.
+ *
+ * When we unregister the client, all channels are removed so this
+ * will also take care of cleaning things up when the module is
+ * unloaded.
+ */
+static enum dma_state_client
+dmatest_event(struct dma_client *client, struct dma_chan *chan,
+ enum dma_state state)
+{
+ enum dma_state_client ack = DMA_NAK;
+
+ switch (state) {
+ case DMA_RESOURCE_AVAILABLE:
+ if (!dmatest_match_channel(chan)
+ || !dmatest_match_device(chan->device))
+ ack = DMA_DUP;
+ else if (max_channels && nr_channels >= max_channels)
+ ack = DMA_NAK;
+ else
+ ack = dmatest_add_channel(chan);
+ break;
+
+ case DMA_RESOURCE_REMOVED:
+ ack = dmatest_remove_channel(chan);
+ break;
+
+ default:
+ pr_info("dmatest: Unhandled event %u (%s)\n",
+ state, chan->dev.bus_id);
+ break;
+ }
+
+ return ack;
+}
+
+static struct dma_client dmatest_client = {
+ .event_callback = dmatest_event,
+};
+
+static int __init dmatest_init(void)
+{
+ dma_cap_set(DMA_MEMCPY, dmatest_client.cap_mask);
+ dma_async_client_register(&dmatest_client);
+ dma_async_client_chan_request(&dmatest_client);
+
+ return 0;
+}
+module_init(dmatest_init);
+
+static void __exit dmatest_exit(void)
+{
+ dma_async_client_unregister(&dmatest_client);
+}
+module_exit(dmatest_exit);
+
+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
new file mode 100644
index 00000000000..94df9177124
--- /dev/null
+++ b/drivers/dma/dw_dmac.c
@@ -0,0 +1,1122 @@
+/*
+ * Driver for the Synopsys DesignWare DMA Controller (aka DMACA on
+ * AVR32 systems.)
+ *
+ * Copyright (C) 2007-2008 Atmel Corporation
+ *
+ * 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/clk.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "dw_dmac_regs.h"
+
+/*
+ * This supports the Synopsys "DesignWare AHB Central DMA Controller",
+ * (DW_ahb_dmac) which is used with various AMBA 2.0 systems (not all
+ * of which use ARM any more). See the "Databook" from Synopsys for
+ * information beyond what licensees probably provide.
+ *
+ * The driver has currently been tested only with the Atmel AT32AP7000,
+ * which does not support descriptor writeback.
+ */
+
+/* NOTE: DMS+SMS is system-specific. We should get this information
+ * from the platform code somehow.
+ */
+#define DWC_DEFAULT_CTLLO (DWC_CTLL_DST_MSIZE(0) \
+ | DWC_CTLL_SRC_MSIZE(0) \
+ | DWC_CTLL_DMS(0) \
+ | DWC_CTLL_SMS(1) \
+ | DWC_CTLL_LLP_D_EN \
+ | DWC_CTLL_LLP_S_EN)
+
+/*
+ * This is configuration-dependent and usually a funny size like 4095.
+ * Let's round it down to the nearest power of two.
+ *
+ * Note that this is a transfer count, i.e. if we transfer 32-bit
+ * words, we can do 8192 bytes per descriptor.
+ *
+ * This parameter is also system-specific.
+ */
+#define DWC_MAX_COUNT 2048U
+
+/*
+ * Number of descriptors to allocate for each channel. This should be
+ * made configurable somehow; preferably, the clients (at least the
+ * ones using slave transfers) should be able to give us a hint.
+ */
+#define NR_DESCS_PER_CHANNEL 64
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Because we're not relying on writeback from the controller (it may not
+ * even be configured into the core!) we don't need to use dma_pool. These
+ * descriptors -- and associated data -- are cacheable. We do need to make
+ * sure their dcache entries are written back before handing them off to
+ * the controller, though.
+ */
+
+static struct dw_desc *dwc_first_active(struct dw_dma_chan *dwc)
+{
+ return list_entry(dwc->active_list.next, struct dw_desc, desc_node);
+}
+
+static struct dw_desc *dwc_first_queued(struct dw_dma_chan *dwc)
+{
+ return list_entry(dwc->queue.next, struct dw_desc, desc_node);
+}
+
+static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc)
+{
+ struct dw_desc *desc, *_desc;
+ struct dw_desc *ret = NULL;
+ unsigned int i = 0;
+
+ spin_lock_bh(&dwc->lock);
+ list_for_each_entry_safe(desc, _desc, &dwc->free_list, desc_node) {
+ if (async_tx_test_ack(&desc->txd)) {
+ list_del(&desc->desc_node);
+ ret = desc;
+ break;
+ }
+ dev_dbg(&dwc->chan.dev, "desc %p not ACKed\n", desc);
+ i++;
+ }
+ spin_unlock_bh(&dwc->lock);
+
+ dev_vdbg(&dwc->chan.dev, "scanned %u descriptors on freelist\n", i);
+
+ return ret;
+}
+
+static void dwc_sync_desc_for_cpu(struct dw_dma_chan *dwc, struct dw_desc *desc)
+{
+ struct dw_desc *child;
+
+ list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+ dma_sync_single_for_cpu(dwc->chan.dev.parent,
+ child->txd.phys, sizeof(child->lli),
+ DMA_TO_DEVICE);
+ dma_sync_single_for_cpu(dwc->chan.dev.parent,
+ desc->txd.phys, sizeof(desc->lli),
+ DMA_TO_DEVICE);
+}
+
+/*
+ * Move a descriptor, including any children, to the free list.
+ * `desc' must not be on any lists.
+ */
+static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc)
+{
+ if (desc) {
+ struct dw_desc *child;
+
+ dwc_sync_desc_for_cpu(dwc, desc);
+
+ spin_lock_bh(&dwc->lock);
+ list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+ dev_vdbg(&dwc->chan.dev,
+ "moving child desc %p to freelist\n",
+ child);
+ list_splice_init(&desc->txd.tx_list, &dwc->free_list);
+ dev_vdbg(&dwc->chan.dev, "moving desc %p to freelist\n", desc);
+ list_add(&desc->desc_node, &dwc->free_list);
+ spin_unlock_bh(&dwc->lock);
+ }
+}
+
+/* Called with dwc->lock held and bh disabled */
+static dma_cookie_t
+dwc_assign_cookie(struct dw_dma_chan *dwc, struct dw_desc *desc)
+{
+ dma_cookie_t cookie = dwc->chan.cookie;
+
+ if (++cookie < 0)
+ cookie = 1;
+
+ dwc->chan.cookie = cookie;
+ desc->txd.cookie = cookie;
+
+ return cookie;
+}
+
+/*----------------------------------------------------------------------*/
+
+/* Called with dwc->lock held and bh disabled */
+static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first)
+{
+ struct dw_dma *dw = to_dw_dma(dwc->chan.device);
+
+ /* ASSERT: channel is idle */
+ if (dma_readl(dw, CH_EN) & dwc->mask) {
+ dev_err(&dwc->chan.dev,
+ "BUG: Attempted to start non-idle channel\n");
+ dev_err(&dwc->chan.dev,
+ " SAR: 0x%x DAR: 0x%x LLP: 0x%x CTL: 0x%x:%08x\n",
+ channel_readl(dwc, SAR),
+ channel_readl(dwc, DAR),
+ channel_readl(dwc, LLP),
+ channel_readl(dwc, CTL_HI),
+ channel_readl(dwc, CTL_LO));
+
+ /* The tasklet will hopefully advance the queue... */
+ return;
+ }
+
+ channel_writel(dwc, LLP, first->txd.phys);
+ channel_writel(dwc, CTL_LO,
+ DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN);
+ channel_writel(dwc, CTL_HI, 0);
+ channel_set_bit(dw, CH_EN, dwc->mask);
+}
+
+/*----------------------------------------------------------------------*/
+
+static void
+dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc)
+{
+ dma_async_tx_callback callback;
+ void *param;
+ struct dma_async_tx_descriptor *txd = &desc->txd;
+
+ dev_vdbg(&dwc->chan.dev, "descriptor %u complete\n", txd->cookie);
+
+ dwc->completed = txd->cookie;
+ callback = txd->callback;
+ param = txd->callback_param;
+
+ dwc_sync_desc_for_cpu(dwc, desc);
+ list_splice_init(&txd->tx_list, &dwc->free_list);
+ list_move(&desc->desc_node, &dwc->free_list);
+
+ /*
+ * We use dma_unmap_page() regardless of how the buffers were
+ * mapped before they were submitted...
+ */
+ if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP))
+ dma_unmap_page(dwc->chan.dev.parent, desc->lli.dar, desc->len,
+ DMA_FROM_DEVICE);
+ if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP))
+ dma_unmap_page(dwc->chan.dev.parent, desc->lli.sar, desc->len,
+ DMA_TO_DEVICE);
+
+ /*
+ * The API requires that no submissions are done from a
+ * callback, so we don't need to drop the lock here
+ */
+ if (callback)
+ callback(param);
+}
+
+static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc)
+{
+ struct dw_desc *desc, *_desc;
+ LIST_HEAD(list);
+
+ if (dma_readl(dw, CH_EN) & dwc->mask) {
+ dev_err(&dwc->chan.dev,
+ "BUG: XFER bit set, but channel not idle!\n");
+
+ /* Try to continue after resetting the channel... */
+ channel_clear_bit(dw, CH_EN, dwc->mask);
+ while (dma_readl(dw, CH_EN) & dwc->mask)
+ cpu_relax();
+ }
+
+ /*
+ * Submit queued descriptors ASAP, i.e. before we go through
+ * the completed ones.
+ */
+ if (!list_empty(&dwc->queue))
+ dwc_dostart(dwc, dwc_first_queued(dwc));
+ list_splice_init(&dwc->active_list, &list);
+ list_splice_init(&dwc->queue, &dwc->active_list);
+
+ list_for_each_entry_safe(desc, _desc, &list, desc_node)
+ dwc_descriptor_complete(dwc, desc);
+}
+
+static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
+{
+ dma_addr_t llp;
+ struct dw_desc *desc, *_desc;
+ struct dw_desc *child;
+ u32 status_xfer;
+
+ /*
+ * Clear block interrupt flag before scanning so that we don't
+ * miss any, and read LLP before RAW_XFER to ensure it is
+ * valid if we decide to scan the list.
+ */
+ dma_writel(dw, CLEAR.BLOCK, dwc->mask);
+ llp = channel_readl(dwc, LLP);
+ status_xfer = dma_readl(dw, RAW.XFER);
+
+ if (status_xfer & dwc->mask) {
+ /* Everything we've submitted is done */
+ dma_writel(dw, CLEAR.XFER, dwc->mask);
+ dwc_complete_all(dw, dwc);
+ return;
+ }
+
+ dev_vdbg(&dwc->chan.dev, "scan_descriptors: llp=0x%x\n", llp);
+
+ list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) {
+ if (desc->lli.llp == llp)
+ /* This one is currently in progress */
+ return;
+
+ list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+ if (child->lli.llp == llp)
+ /* Currently in progress */
+ return;
+
+ /*
+ * No descriptors so far seem to be in progress, i.e.
+ * this one must be done.
+ */
+ dwc_descriptor_complete(dwc, desc);
+ }
+
+ dev_err(&dwc->chan.dev,
+ "BUG: All descriptors done, but channel not idle!\n");
+
+ /* Try to continue after resetting the channel... */
+ channel_clear_bit(dw, CH_EN, dwc->mask);
+ while (dma_readl(dw, CH_EN) & dwc->mask)
+ cpu_relax();
+
+ if (!list_empty(&dwc->queue)) {
+ dwc_dostart(dwc, dwc_first_queued(dwc));
+ list_splice_init(&dwc->queue, &dwc->active_list);
+ }
+}
+
+static void dwc_dump_lli(struct dw_dma_chan *dwc, struct dw_lli *lli)
+{
+ dev_printk(KERN_CRIT, &dwc->chan.dev,
+ " desc: s0x%x d0x%x l0x%x c0x%x:%x\n",
+ lli->sar, lli->dar, lli->llp,
+ lli->ctlhi, lli->ctllo);
+}
+
+static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc)
+{
+ struct dw_desc *bad_desc;
+ struct dw_desc *child;
+
+ dwc_scan_descriptors(dw, dwc);
+
+ /*
+ * The descriptor currently at the head of the active list is
+ * borked. Since we don't have any way to report errors, we'll
+ * just have to scream loudly and try to carry on.
+ */
+ bad_desc = dwc_first_active(dwc);
+ list_del_init(&bad_desc->desc_node);
+ list_splice_init(&dwc->queue, dwc->active_list.prev);
+
+ /* Clear the error flag and try to restart the controller */
+ dma_writel(dw, CLEAR.ERROR, dwc->mask);
+ if (!list_empty(&dwc->active_list))
+ dwc_dostart(dwc, dwc_first_active(dwc));
+
+ /*
+ * KERN_CRITICAL may seem harsh, but since this only happens
+ * when someone submits a bad physical address in a
+ * descriptor, we should consider ourselves lucky that the
+ * controller flagged an error instead of scribbling over
+ * random memory locations.
+ */
+ dev_printk(KERN_CRIT, &dwc->chan.dev,
+ "Bad descriptor submitted for DMA!\n");
+ dev_printk(KERN_CRIT, &dwc->chan.dev,
+ " cookie: %d\n", bad_desc->txd.cookie);
+ dwc_dump_lli(dwc, &bad_desc->lli);
+ list_for_each_entry(child, &bad_desc->txd.tx_list, desc_node)
+ dwc_dump_lli(dwc, &child->lli);
+
+ /* Pretend the descriptor completed successfully */
+ dwc_descriptor_complete(dwc, bad_desc);
+}
+
+static void dw_dma_tasklet(unsigned long data)
+{
+ struct dw_dma *dw = (struct dw_dma *)data;
+ struct dw_dma_chan *dwc;
+ u32 status_block;
+ u32 status_xfer;
+ u32 status_err;
+ int i;
+
+ status_block = dma_readl(dw, RAW.BLOCK);
+ status_xfer = dma_readl(dw, RAW.BLOCK);
+ status_err = dma_readl(dw, RAW.ERROR);
+
+ dev_vdbg(dw->dma.dev, "tasklet: status_block=%x status_err=%x\n",
+ status_block, status_err);
+
+ for (i = 0; i < dw->dma.chancnt; i++) {
+ dwc = &dw->chan[i];
+ spin_lock(&dwc->lock);
+ if (status_err & (1 << i))
+ dwc_handle_error(dw, dwc);
+ else if ((status_block | status_xfer) & (1 << i))
+ dwc_scan_descriptors(dw, dwc);
+ spin_unlock(&dwc->lock);
+ }
+
+ /*
+ * Re-enable interrupts. Block Complete interrupts are only
+ * enabled if the INT_EN bit in the descriptor is set. This
+ * will trigger a scan before the whole list is done.
+ */
+ channel_set_bit(dw, MASK.XFER, dw->all_chan_mask);
+ channel_set_bit(dw, MASK.BLOCK, dw->all_chan_mask);
+ channel_set_bit(dw, MASK.ERROR, dw->all_chan_mask);
+}
+
+static irqreturn_t dw_dma_interrupt(int irq, void *dev_id)
+{
+ struct dw_dma *dw = dev_id;
+ u32 status;
+
+ dev_vdbg(dw->dma.dev, "interrupt: status=0x%x\n",
+ dma_readl(dw, STATUS_INT));
+
+ /*
+ * Just disable the interrupts. We'll turn them back on in the
+ * softirq handler.
+ */
+ channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask);
+
+ status = dma_readl(dw, STATUS_INT);
+ if (status) {
+ dev_err(dw->dma.dev,
+ "BUG: Unexpected interrupts pending: 0x%x\n",
+ status);
+
+ /* Try to recover */
+ channel_clear_bit(dw, MASK.XFER, (1 << 8) - 1);
+ channel_clear_bit(dw, MASK.BLOCK, (1 << 8) - 1);
+ channel_clear_bit(dw, MASK.SRC_TRAN, (1 << 8) - 1);
+ channel_clear_bit(dw, MASK.DST_TRAN, (1 << 8) - 1);
+ channel_clear_bit(dw, MASK.ERROR, (1 << 8) - 1);
+ }
+
+ tasklet_schedule(&dw->tasklet);
+
+ return IRQ_HANDLED;
+}
+
+/*----------------------------------------------------------------------*/
+
+static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct dw_desc *desc = txd_to_dw_desc(tx);
+ struct dw_dma_chan *dwc = to_dw_dma_chan(tx->chan);
+ dma_cookie_t cookie;
+
+ spin_lock_bh(&dwc->lock);
+ cookie = dwc_assign_cookie(dwc, desc);
+
+ /*
+ * REVISIT: We should attempt to chain as many descriptors as
+ * possible, perhaps even appending to those already submitted
+ * for DMA. But this is hard to do in a race-free manner.
+ */
+ if (list_empty(&dwc->active_list)) {
+ dev_vdbg(&tx->chan->dev, "tx_submit: started %u\n",
+ desc->txd.cookie);
+ dwc_dostart(dwc, desc);
+ list_add_tail(&desc->desc_node, &dwc->active_list);
+ } else {
+ dev_vdbg(&tx->chan->dev, "tx_submit: queued %u\n",
+ desc->txd.cookie);
+
+ list_add_tail(&desc->desc_node, &dwc->queue);
+ }
+
+ spin_unlock_bh(&dwc->lock);
+
+ return cookie;
+}
+
+static struct dma_async_tx_descriptor *
+dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+ size_t len, unsigned long flags)
+{
+ struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+ struct dw_desc *desc;
+ struct dw_desc *first;
+ struct dw_desc *prev;
+ size_t xfer_count;
+ size_t offset;
+ unsigned int src_width;
+ unsigned int dst_width;
+ u32 ctllo;
+
+ dev_vdbg(&chan->dev, "prep_dma_memcpy d0x%x s0x%x l0x%zx f0x%lx\n",
+ dest, src, len, flags);
+
+ if (unlikely(!len)) {
+ dev_dbg(&chan->dev, "prep_dma_memcpy: length is zero!\n");
+ return NULL;
+ }
+
+ /*
+ * We can be a lot more clever here, but this should take care
+ * of the most common optimization.
+ */
+ if (!((src | dest | len) & 3))
+ src_width = dst_width = 2;
+ else if (!((src | dest | len) & 1))
+ src_width = dst_width = 1;
+ else
+ src_width = dst_width = 0;
+
+ ctllo = DWC_DEFAULT_CTLLO
+ | DWC_CTLL_DST_WIDTH(dst_width)
+ | DWC_CTLL_SRC_WIDTH(src_width)
+ | DWC_CTLL_DST_INC
+ | DWC_CTLL_SRC_INC
+ | DWC_CTLL_FC_M2M;
+ prev = first = NULL;
+
+ for (offset = 0; offset < len; offset += xfer_count << src_width) {
+ xfer_count = min_t(size_t, (len - offset) >> src_width,
+ DWC_MAX_COUNT);
+
+ desc = dwc_desc_get(dwc);
+ if (!desc)
+ goto err_desc_get;
+
+ desc->lli.sar = src + offset;
+ desc->lli.dar = dest + offset;
+ desc->lli.ctllo = ctllo;
+ desc->lli.ctlhi = xfer_count;
+
+ if (!first) {
+ first = desc;
+ } else {
+ prev->lli.llp = desc->txd.phys;
+ dma_sync_single_for_device(chan->dev.parent,
+ prev->txd.phys, sizeof(prev->lli),
+ DMA_TO_DEVICE);
+ list_add_tail(&desc->desc_node,
+ &first->txd.tx_list);
+ }
+ prev = desc;
+ }
+
+
+ if (flags & DMA_PREP_INTERRUPT)
+ /* Trigger interrupt after last block */
+ prev->lli.ctllo |= DWC_CTLL_INT_EN;
+
+ prev->lli.llp = 0;
+ dma_sync_single_for_device(chan->dev.parent,
+ prev->txd.phys, sizeof(prev->lli),
+ DMA_TO_DEVICE);
+
+ first->txd.flags = flags;
+ first->len = len;
+
+ return &first->txd;
+
+err_desc_get:
+ dwc_desc_put(dwc, first);
+ return NULL;
+}
+
+static struct dma_async_tx_descriptor *
+dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_data_direction direction,
+ unsigned long flags)
+{
+ struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+ struct dw_dma_slave *dws = dwc->dws;
+ struct dw_desc *prev;
+ struct dw_desc *first;
+ u32 ctllo;
+ dma_addr_t reg;
+ unsigned int reg_width;
+ unsigned int mem_width;
+ unsigned int i;
+ struct scatterlist *sg;
+ size_t total_len = 0;
+
+ dev_vdbg(&chan->dev, "prep_dma_slave\n");
+
+ if (unlikely(!dws || !sg_len))
+ return NULL;
+
+ reg_width = dws->slave.reg_width;
+ prev = first = NULL;
+
+ sg_len = dma_map_sg(chan->dev.parent, sgl, sg_len, direction);
+
+ switch (direction) {
+ case DMA_TO_DEVICE:
+ ctllo = (DWC_DEFAULT_CTLLO
+ | DWC_CTLL_DST_WIDTH(reg_width)
+ | DWC_CTLL_DST_FIX
+ | DWC_CTLL_SRC_INC
+ | DWC_CTLL_FC_M2P);
+ reg = dws->slave.tx_reg;
+ for_each_sg(sgl, sg, sg_len, i) {
+ struct dw_desc *desc;
+ u32 len;
+ u32 mem;
+
+ desc = dwc_desc_get(dwc);
+ if (!desc) {
+ dev_err(&chan->dev,
+ "not enough descriptors available\n");
+ goto err_desc_get;
+ }
+
+ mem = sg_phys(sg);
+ len = sg_dma_len(sg);
+ mem_width = 2;
+ if (unlikely(mem & 3 || len & 3))
+ mem_width = 0;
+
+ desc->lli.sar = mem;
+ desc->lli.dar = reg;
+ desc->lli.ctllo = ctllo | DWC_CTLL_SRC_WIDTH(mem_width);
+ desc->lli.ctlhi = len >> mem_width;
+
+ if (!first) {
+ first = desc;
+ } else {
+ prev->lli.llp = desc->txd.phys;
+ dma_sync_single_for_device(chan->dev.parent,
+ prev->txd.phys,
+ sizeof(prev->lli),
+ DMA_TO_DEVICE);
+ list_add_tail(&desc->desc_node,
+ &first->txd.tx_list);
+ }
+ prev = desc;
+ total_len += len;
+ }
+ break;
+ case DMA_FROM_DEVICE:
+ ctllo = (DWC_DEFAULT_CTLLO
+ | DWC_CTLL_SRC_WIDTH(reg_width)
+ | DWC_CTLL_DST_INC
+ | DWC_CTLL_SRC_FIX
+ | DWC_CTLL_FC_P2M);
+
+ reg = dws->slave.rx_reg;
+ for_each_sg(sgl, sg, sg_len, i) {
+ struct dw_desc *desc;
+ u32 len;
+ u32 mem;
+
+ desc = dwc_desc_get(dwc);
+ if (!desc) {
+ dev_err(&chan->dev,
+ "not enough descriptors available\n");
+ goto err_desc_get;
+ }
+
+ mem = sg_phys(sg);
+ len = sg_dma_len(sg);
+ mem_width = 2;
+ if (unlikely(mem & 3 || len & 3))
+ mem_width = 0;
+
+ desc->lli.sar = reg;
+ desc->lli.dar = mem;
+ desc->lli.ctllo = ctllo | DWC_CTLL_DST_WIDTH(mem_width);
+ desc->lli.ctlhi = len >> reg_width;
+
+ if (!first) {
+ first = desc;
+ } else {
+ prev->lli.llp = desc->txd.phys;
+ dma_sync_single_for_device(chan->dev.parent,
+ prev->txd.phys,
+ sizeof(prev->lli),
+ DMA_TO_DEVICE);
+ list_add_tail(&desc->desc_node,
+ &first->txd.tx_list);
+ }
+ prev = desc;
+ total_len += len;
+ }
+ break;
+ default:
+ return NULL;
+ }
+
+ if (flags & DMA_PREP_INTERRUPT)
+ /* Trigger interrupt after last block */
+ prev->lli.ctllo |= DWC_CTLL_INT_EN;
+
+ prev->lli.llp = 0;
+ dma_sync_single_for_device(chan->dev.parent,
+ prev->txd.phys, sizeof(prev->lli),
+ DMA_TO_DEVICE);
+
+ first->len = total_len;
+
+ return &first->txd;
+
+err_desc_get:
+ dwc_desc_put(dwc, first);
+ return NULL;
+}
+
+static void dwc_terminate_all(struct dma_chan *chan)
+{
+ struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+ struct dw_dma *dw = to_dw_dma(chan->device);
+ struct dw_desc *desc, *_desc;
+ LIST_HEAD(list);
+
+ /*
+ * This is only called when something went wrong elsewhere, so
+ * we don't really care about the data. Just disable the
+ * channel. We still have to poll the channel enable bit due
+ * to AHB/HSB limitations.
+ */
+ spin_lock_bh(&dwc->lock);
+
+ channel_clear_bit(dw, CH_EN, dwc->mask);
+
+ while (dma_readl(dw, CH_EN) & dwc->mask)
+ cpu_relax();
+
+ /* active_list entries will end up before queued entries */
+ list_splice_init(&dwc->queue, &list);
+ list_splice_init(&dwc->active_list, &list);
+
+ spin_unlock_bh(&dwc->lock);
+
+ /* Flush all pending and queued descriptors */
+ list_for_each_entry_safe(desc, _desc, &list, desc_node)
+ dwc_descriptor_complete(dwc, desc);
+}
+
+static enum dma_status
+dwc_is_tx_complete(struct dma_chan *chan,
+ dma_cookie_t cookie,
+ dma_cookie_t *done, dma_cookie_t *used)
+{
+ struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+ dma_cookie_t last_used;
+ dma_cookie_t last_complete;
+ int ret;
+
+ last_complete = dwc->completed;
+ last_used = chan->cookie;
+
+ ret = dma_async_is_complete(cookie, last_complete, last_used);
+ if (ret != DMA_SUCCESS) {
+ dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
+
+ last_complete = dwc->completed;
+ last_used = chan->cookie;
+
+ ret = dma_async_is_complete(cookie, last_complete, last_used);
+ }
+
+ if (done)
+ *done = last_complete;
+ if (used)
+ *used = last_used;
+
+ return ret;
+}
+
+static void dwc_issue_pending(struct dma_chan *chan)
+{
+ struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+
+ spin_lock_bh(&dwc->lock);
+ if (!list_empty(&dwc->queue))
+ dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
+ spin_unlock_bh(&dwc->lock);
+}
+
+static int dwc_alloc_chan_resources(struct dma_chan *chan,
+ struct dma_client *client)
+{
+ struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+ struct dw_dma *dw = to_dw_dma(chan->device);
+ struct dw_desc *desc;
+ struct dma_slave *slave;
+ struct dw_dma_slave *dws;
+ int i;
+ u32 cfghi;
+ u32 cfglo;
+
+ dev_vdbg(&chan->dev, "alloc_chan_resources\n");
+
+ /* Channels doing slave DMA can only handle one client. */
+ if (dwc->dws || client->slave) {
+ if (chan->client_count)
+ return -EBUSY;
+ }
+
+ /* ASSERT: channel is idle */
+ if (dma_readl(dw, CH_EN) & dwc->mask) {
+ dev_dbg(&chan->dev, "DMA channel not idle?\n");
+ return -EIO;
+ }
+
+ dwc->completed = chan->cookie = 1;
+
+ cfghi = DWC_CFGH_FIFO_MODE;
+ cfglo = 0;
+
+ slave = client->slave;
+ if (slave) {
+ /*
+ * We need controller-specific data to set up slave
+ * transfers.
+ */
+ BUG_ON(!slave->dma_dev || slave->dma_dev != dw->dma.dev);
+
+ dws = container_of(slave, struct dw_dma_slave, slave);
+
+ dwc->dws = dws;
+ cfghi = dws->cfg_hi;
+ cfglo = dws->cfg_lo;
+ } else {
+ dwc->dws = NULL;
+ }
+
+ channel_writel(dwc, CFG_LO, cfglo);
+ channel_writel(dwc, CFG_HI, cfghi);
+
+ /*
+ * NOTE: some controllers may have additional features that we
+ * need to initialize here, like "scatter-gather" (which
+ * doesn't mean what you think it means), and status writeback.
+ */
+
+ spin_lock_bh(&dwc->lock);
+ i = dwc->descs_allocated;
+ while (dwc->descs_allocated < NR_DESCS_PER_CHANNEL) {
+ spin_unlock_bh(&dwc->lock);
+
+ desc = kzalloc(sizeof(struct dw_desc), GFP_KERNEL);
+ if (!desc) {
+ dev_info(&chan->dev,
+ "only allocated %d descriptors\n", i);
+ spin_lock_bh(&dwc->lock);
+ break;
+ }
+
+ dma_async_tx_descriptor_init(&desc->txd, chan);
+ desc->txd.tx_submit = dwc_tx_submit;
+ desc->txd.flags = DMA_CTRL_ACK;
+ INIT_LIST_HEAD(&desc->txd.tx_list);
+ desc->txd.phys = dma_map_single(chan->dev.parent, &desc->lli,
+ sizeof(desc->lli), DMA_TO_DEVICE);
+ dwc_desc_put(dwc, desc);
+
+ spin_lock_bh(&dwc->lock);
+ i = ++dwc->descs_allocated;
+ }
+
+ /* Enable interrupts */
+ channel_set_bit(dw, MASK.XFER, dwc->mask);
+ channel_set_bit(dw, MASK.BLOCK, dwc->mask);
+ channel_set_bit(dw, MASK.ERROR, dwc->mask);
+
+ spin_unlock_bh(&dwc->lock);
+
+ dev_dbg(&chan->dev,
+ "alloc_chan_resources allocated %d descriptors\n", i);
+
+ return i;
+}
+
+static void dwc_free_chan_resources(struct dma_chan *chan)
+{
+ struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+ struct dw_dma *dw = to_dw_dma(chan->device);
+ struct dw_desc *desc, *_desc;
+ LIST_HEAD(list);
+
+ dev_dbg(&chan->dev, "free_chan_resources (descs allocated=%u)\n",
+ dwc->descs_allocated);
+
+ /* ASSERT: channel is idle */
+ BUG_ON(!list_empty(&dwc->active_list));
+ BUG_ON(!list_empty(&dwc->queue));
+ BUG_ON(dma_readl(to_dw_dma(chan->device), CH_EN) & dwc->mask);
+
+ spin_lock_bh(&dwc->lock);
+ list_splice_init(&dwc->free_list, &list);
+ dwc->descs_allocated = 0;
+ dwc->dws = NULL;
+
+ /* Disable interrupts */
+ channel_clear_bit(dw, MASK.XFER, dwc->mask);
+ channel_clear_bit(dw, MASK.BLOCK, dwc->mask);
+ channel_clear_bit(dw, MASK.ERROR, dwc->mask);
+
+ spin_unlock_bh(&dwc->lock);
+
+ list_for_each_entry_safe(desc, _desc, &list, desc_node) {
+ dev_vdbg(&chan->dev, " freeing descriptor %p\n", desc);
+ dma_unmap_single(chan->dev.parent, desc->txd.phys,
+ sizeof(desc->lli), DMA_TO_DEVICE);
+ kfree(desc);
+ }
+
+ dev_vdbg(&chan->dev, "free_chan_resources done\n");
+}
+
+/*----------------------------------------------------------------------*/
+
+static void dw_dma_off(struct dw_dma *dw)
+{
+ dma_writel(dw, CFG, 0);
+
+ channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.SRC_TRAN, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.DST_TRAN, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask);
+
+ while (dma_readl(dw, CFG) & DW_CFG_DMA_EN)
+ cpu_relax();
+}
+
+static int __init dw_probe(struct platform_device *pdev)
+{
+ struct dw_dma_platform_data *pdata;
+ struct resource *io;
+ struct dw_dma *dw;
+ size_t size;
+ int irq;
+ int err;
+ int i;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata || pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS)
+ return -EINVAL;
+
+ io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!io)
+ return -EINVAL;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ size = sizeof(struct dw_dma);
+ size += pdata->nr_channels * sizeof(struct dw_dma_chan);
+ dw = kzalloc(size, GFP_KERNEL);
+ if (!dw)
+ return -ENOMEM;
+
+ if (!request_mem_region(io->start, DW_REGLEN, pdev->dev.driver->name)) {
+ err = -EBUSY;
+ goto err_kfree;
+ }
+
+ memset(dw, 0, sizeof *dw);
+
+ dw->regs = ioremap(io->start, DW_REGLEN);
+ if (!dw->regs) {
+ err = -ENOMEM;
+ goto err_release_r;
+ }
+
+ dw->clk = clk_get(&pdev->dev, "hclk");
+ if (IS_ERR(dw->clk)) {
+ err = PTR_ERR(dw->clk);
+ goto err_clk;
+ }
+ clk_enable(dw->clk);
+
+ /* force dma off, just in case */
+ dw_dma_off(dw);
+
+ err = request_irq(irq, dw_dma_interrupt, 0, "dw_dmac", dw);
+ if (err)
+ goto err_irq;
+
+ platform_set_drvdata(pdev, dw);
+
+ tasklet_init(&dw->tasklet, dw_dma_tasklet, (unsigned long)dw);
+
+ dw->all_chan_mask = (1 << pdata->nr_channels) - 1;
+
+ INIT_LIST_HEAD(&dw->dma.channels);
+ for (i = 0; i < pdata->nr_channels; i++, dw->dma.chancnt++) {
+ struct dw_dma_chan *dwc = &dw->chan[i];
+
+ dwc->chan.device = &dw->dma;
+ dwc->chan.cookie = dwc->completed = 1;
+ dwc->chan.chan_id = i;
+ list_add_tail(&dwc->chan.device_node, &dw->dma.channels);
+
+ dwc->ch_regs = &__dw_regs(dw)->CHAN[i];
+ spin_lock_init(&dwc->lock);
+ dwc->mask = 1 << i;
+
+ INIT_LIST_HEAD(&dwc->active_list);
+ INIT_LIST_HEAD(&dwc->queue);
+ INIT_LIST_HEAD(&dwc->free_list);
+
+ channel_clear_bit(dw, CH_EN, dwc->mask);
+ }
+
+ /* Clear/disable all interrupts on all channels. */
+ dma_writel(dw, CLEAR.XFER, dw->all_chan_mask);
+ dma_writel(dw, CLEAR.BLOCK, dw->all_chan_mask);
+ dma_writel(dw, CLEAR.SRC_TRAN, dw->all_chan_mask);
+ dma_writel(dw, CLEAR.DST_TRAN, dw->all_chan_mask);
+ dma_writel(dw, CLEAR.ERROR, dw->all_chan_mask);
+
+ channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.SRC_TRAN, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.DST_TRAN, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask);
+
+ dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask);
+ dma_cap_set(DMA_SLAVE, dw->dma.cap_mask);
+ dw->dma.dev = &pdev->dev;
+ dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources;
+ dw->dma.device_free_chan_resources = dwc_free_chan_resources;
+
+ dw->dma.device_prep_dma_memcpy = dwc_prep_dma_memcpy;
+
+ dw->dma.device_prep_slave_sg = dwc_prep_slave_sg;
+ dw->dma.device_terminate_all = dwc_terminate_all;
+
+ dw->dma.device_is_tx_complete = dwc_is_tx_complete;
+ dw->dma.device_issue_pending = dwc_issue_pending;
+
+ dma_writel(dw, CFG, DW_CFG_DMA_EN);
+
+ printk(KERN_INFO "%s: DesignWare DMA Controller, %d channels\n",
+ pdev->dev.bus_id, dw->dma.chancnt);
+
+ dma_async_device_register(&dw->dma);
+
+ return 0;
+
+err_irq:
+ clk_disable(dw->clk);
+ clk_put(dw->clk);
+err_clk:
+ iounmap(dw->regs);
+ dw->regs = NULL;
+err_release_r:
+ release_resource(io);
+err_kfree:
+ kfree(dw);
+ return err;
+}
+
+static int __exit dw_remove(struct platform_device *pdev)
+{
+ struct dw_dma *dw = platform_get_drvdata(pdev);
+ struct dw_dma_chan *dwc, *_dwc;
+ struct resource *io;
+
+ dw_dma_off(dw);
+ dma_async_device_unregister(&dw->dma);
+
+ free_irq(platform_get_irq(pdev, 0), dw);
+ tasklet_kill(&dw->tasklet);
+
+ list_for_each_entry_safe(dwc, _dwc, &dw->dma.channels,
+ chan.device_node) {
+ list_del(&dwc->chan.device_node);
+ channel_clear_bit(dw, CH_EN, dwc->mask);
+ }
+
+ clk_disable(dw->clk);
+ clk_put(dw->clk);
+
+ iounmap(dw->regs);
+ dw->regs = NULL;
+
+ io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(io->start, DW_REGLEN);
+
+ kfree(dw);
+
+ return 0;
+}
+
+static void dw_shutdown(struct platform_device *pdev)
+{
+ struct dw_dma *dw = platform_get_drvdata(pdev);
+
+ dw_dma_off(platform_get_drvdata(pdev));
+ clk_disable(dw->clk);
+}
+
+static int dw_suspend_late(struct platform_device *pdev, pm_message_t mesg)
+{
+ struct dw_dma *dw = platform_get_drvdata(pdev);
+
+ dw_dma_off(platform_get_drvdata(pdev));
+ clk_disable(dw->clk);
+ return 0;
+}
+
+static int dw_resume_early(struct platform_device *pdev)
+{
+ struct dw_dma *dw = platform_get_drvdata(pdev);
+
+ clk_enable(dw->clk);
+ dma_writel(dw, CFG, DW_CFG_DMA_EN);
+ return 0;
+
+}
+
+static struct platform_driver dw_driver = {
+ .remove = __exit_p(dw_remove),
+ .shutdown = dw_shutdown,
+ .suspend_late = dw_suspend_late,
+ .resume_early = dw_resume_early,
+ .driver = {
+ .name = "dw_dmac",
+ },
+};
+
+static int __init dw_init(void)
+{
+ return platform_driver_probe(&dw_driver, dw_probe);
+}
+module_init(dw_init);
+
+static void __exit dw_exit(void)
+{
+ platform_driver_unregister(&dw_driver);
+}
+module_exit(dw_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller driver");
+MODULE_AUTHOR("Haavard Skinnemoen <haavard.skinnemoen@atmel.com>");
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
new file mode 100644
index 00000000000..00fdd187bb0
--- /dev/null
+++ b/drivers/dma/dw_dmac_regs.h
@@ -0,0 +1,225 @@
+/*
+ * Driver for the Synopsys DesignWare AHB DMA Controller
+ *
+ * Copyright (C) 2005-2007 Atmel Corporation
+ *
+ * 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/dw_dmac.h>
+
+#define DW_DMA_MAX_NR_CHANNELS 8
+
+/*
+ * Redefine this macro to handle differences between 32- and 64-bit
+ * addressing, big vs. little endian, etc.
+ */
+#define DW_REG(name) u32 name; u32 __pad_##name
+
+/* Hardware register definitions. */
+struct dw_dma_chan_regs {
+ DW_REG(SAR); /* Source Address Register */
+ DW_REG(DAR); /* Destination Address Register */
+ DW_REG(LLP); /* Linked List Pointer */
+ u32 CTL_LO; /* Control Register Low */
+ u32 CTL_HI; /* Control Register High */
+ DW_REG(SSTAT);
+ DW_REG(DSTAT);
+ DW_REG(SSTATAR);
+ DW_REG(DSTATAR);
+ u32 CFG_LO; /* Configuration Register Low */
+ u32 CFG_HI; /* Configuration Register High */
+ DW_REG(SGR);
+ DW_REG(DSR);
+};
+
+struct dw_dma_irq_regs {
+ DW_REG(XFER);
+ DW_REG(BLOCK);
+ DW_REG(SRC_TRAN);
+ DW_REG(DST_TRAN);
+ DW_REG(ERROR);
+};
+
+struct dw_dma_regs {
+ /* per-channel registers */
+ struct dw_dma_chan_regs CHAN[DW_DMA_MAX_NR_CHANNELS];
+
+ /* irq handling */
+ struct dw_dma_irq_regs RAW; /* r */
+ struct dw_dma_irq_regs STATUS; /* r (raw & mask) */
+ struct dw_dma_irq_regs MASK; /* rw (set = irq enabled) */
+ struct dw_dma_irq_regs CLEAR; /* w (ack, affects "raw") */
+
+ DW_REG(STATUS_INT); /* r */
+
+ /* software handshaking */
+ DW_REG(REQ_SRC);
+ DW_REG(REQ_DST);
+ DW_REG(SGL_REQ_SRC);
+ DW_REG(SGL_REQ_DST);
+ DW_REG(LAST_SRC);
+ DW_REG(LAST_DST);
+
+ /* miscellaneous */
+ DW_REG(CFG);
+ DW_REG(CH_EN);
+ DW_REG(ID);
+ DW_REG(TEST);
+
+ /* optional encoded params, 0x3c8..0x3 */
+};
+
+/* Bitfields in CTL_LO */
+#define DWC_CTLL_INT_EN (1 << 0) /* irqs enabled? */
+#define DWC_CTLL_DST_WIDTH(n) ((n)<<1) /* bytes per element */
+#define DWC_CTLL_SRC_WIDTH(n) ((n)<<4)
+#define DWC_CTLL_DST_INC (0<<7) /* DAR update/not */
+#define DWC_CTLL_DST_DEC (1<<7)
+#define DWC_CTLL_DST_FIX (2<<7)
+#define DWC_CTLL_SRC_INC (0<<7) /* SAR update/not */
+#define DWC_CTLL_SRC_DEC (1<<9)
+#define DWC_CTLL_SRC_FIX (2<<9)
+#define DWC_CTLL_DST_MSIZE(n) ((n)<<11) /* burst, #elements */
+#define DWC_CTLL_SRC_MSIZE(n) ((n)<<14)
+#define DWC_CTLL_S_GATH_EN (1 << 17) /* src gather, !FIX */
+#define DWC_CTLL_D_SCAT_EN (1 << 18) /* dst scatter, !FIX */
+#define DWC_CTLL_FC_M2M (0 << 20) /* mem-to-mem */
+#define DWC_CTLL_FC_M2P (1 << 20) /* mem-to-periph */
+#define DWC_CTLL_FC_P2M (2 << 20) /* periph-to-mem */
+#define DWC_CTLL_FC_P2P (3 << 20) /* periph-to-periph */
+/* plus 4 transfer types for peripheral-as-flow-controller */
+#define DWC_CTLL_DMS(n) ((n)<<23) /* dst master select */
+#define DWC_CTLL_SMS(n) ((n)<<25) /* src master select */
+#define DWC_CTLL_LLP_D_EN (1 << 27) /* dest block chain */
+#define DWC_CTLL_LLP_S_EN (1 << 28) /* src block chain */
+
+/* Bitfields in CTL_HI */
+#define DWC_CTLH_DONE 0x00001000
+#define DWC_CTLH_BLOCK_TS_MASK 0x00000fff
+
+/* Bitfields in CFG_LO. Platform-configurable bits are in <linux/dw_dmac.h> */
+#define DWC_CFGL_CH_SUSP (1 << 8) /* pause xfer */
+#define DWC_CFGL_FIFO_EMPTY (1 << 9) /* pause xfer */
+#define DWC_CFGL_HS_DST (1 << 10) /* handshake w/dst */
+#define DWC_CFGL_HS_SRC (1 << 11) /* handshake w/src */
+#define DWC_CFGL_MAX_BURST(x) ((x) << 20)
+#define DWC_CFGL_RELOAD_SAR (1 << 30)
+#define DWC_CFGL_RELOAD_DAR (1 << 31)
+
+/* Bitfields in CFG_HI. Platform-configurable bits are in <linux/dw_dmac.h> */
+#define DWC_CFGH_DS_UPD_EN (1 << 5)
+#define DWC_CFGH_SS_UPD_EN (1 << 6)
+
+/* Bitfields in SGR */
+#define DWC_SGR_SGI(x) ((x) << 0)
+#define DWC_SGR_SGC(x) ((x) << 20)
+
+/* Bitfields in DSR */
+#define DWC_DSR_DSI(x) ((x) << 0)
+#define DWC_DSR_DSC(x) ((x) << 20)
+
+/* Bitfields in CFG */
+#define DW_CFG_DMA_EN (1 << 0)
+
+#define DW_REGLEN 0x400
+
+struct dw_dma_chan {
+ struct dma_chan chan;
+ void __iomem *ch_regs;
+ u8 mask;
+
+ spinlock_t lock;
+
+ /* these other elements are all protected by lock */
+ dma_cookie_t completed;
+ struct list_head active_list;
+ struct list_head queue;
+ struct list_head free_list;
+
+ struct dw_dma_slave *dws;
+
+ unsigned int descs_allocated;
+};
+
+static inline struct dw_dma_chan_regs __iomem *
+__dwc_regs(struct dw_dma_chan *dwc)
+{
+ return dwc->ch_regs;
+}
+
+#define channel_readl(dwc, name) \
+ __raw_readl(&(__dwc_regs(dwc)->name))
+#define channel_writel(dwc, name, val) \
+ __raw_writel((val), &(__dwc_regs(dwc)->name))
+
+static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan)
+{
+ return container_of(chan, struct dw_dma_chan, chan);
+}
+
+
+struct dw_dma {
+ struct dma_device dma;
+ void __iomem *regs;
+ struct tasklet_struct tasklet;
+ struct clk *clk;
+
+ u8 all_chan_mask;
+
+ struct dw_dma_chan chan[0];
+};
+
+static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw)
+{
+ return dw->regs;
+}
+
+#define dma_readl(dw, name) \
+ __raw_readl(&(__dw_regs(dw)->name))
+#define dma_writel(dw, name, val) \
+ __raw_writel((val), &(__dw_regs(dw)->name))
+
+#define channel_set_bit(dw, reg, mask) \
+ dma_writel(dw, reg, ((mask) << 8) | (mask))
+#define channel_clear_bit(dw, reg, mask) \
+ dma_writel(dw, reg, ((mask) << 8) | 0)
+
+static inline struct dw_dma *to_dw_dma(struct dma_device *ddev)
+{
+ return container_of(ddev, struct dw_dma, dma);
+}
+
+/* LLI == Linked List Item; a.k.a. DMA block descriptor */
+struct dw_lli {
+ /* values that are not changed by hardware */
+ dma_addr_t sar;
+ dma_addr_t dar;
+ dma_addr_t llp; /* chain to next lli */
+ u32 ctllo;
+ /* values that may get written back: */
+ u32 ctlhi;
+ /* sstat and dstat can snapshot peripheral register state.
+ * silicon config may discard either or both...
+ */
+ u32 sstat;
+ u32 dstat;
+};
+
+struct dw_desc {
+ /* FIRST values the hardware uses */
+ struct dw_lli lli;
+
+ /* THEN values for driver housekeeping */
+ struct list_head desc_node;
+ struct dma_async_tx_descriptor txd;
+ size_t len;
+};
+
+static inline struct dw_desc *
+txd_to_dw_desc(struct dma_async_tx_descriptor *txd)
+{
+ return container_of(txd, struct dw_desc, txd);
+}
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 054eabffc18..c0059ca5834 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -366,7 +366,8 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
*
* Return - The number of descriptors allocated.
*/
-static int fsl_dma_alloc_chan_resources(struct dma_chan *chan)
+static int fsl_dma_alloc_chan_resources(struct dma_chan *chan,
+ struct dma_client *client)
{
struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
LIST_HEAD(tmp_list);
@@ -809,8 +810,7 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
if (!src) {
dev_err(fsl_chan->dev,
"selftest: Cannot alloc memory for test!\n");
- err = -ENOMEM;
- goto out;
+ return -ENOMEM;
}
dest = src + test_size;
@@ -820,7 +820,7 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
chan = &fsl_chan->common;
- if (fsl_dma_alloc_chan_resources(chan) < 1) {
+ if (fsl_dma_alloc_chan_resources(chan, NULL) < 1) {
dev_err(fsl_chan->dev,
"selftest: Cannot alloc resources for DMA\n");
err = -ENODEV;
@@ -842,13 +842,13 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
if (fsl_dma_is_complete(chan, cookie, NULL, NULL) != DMA_SUCCESS) {
dev_err(fsl_chan->dev, "selftest: Time out!\n");
err = -ENODEV;
- goto out;
+ goto free_resources;
}
/* Test free and re-alloc channel resources */
fsl_dma_free_chan_resources(chan);
- if (fsl_dma_alloc_chan_resources(chan) < 1) {
+ if (fsl_dma_alloc_chan_resources(chan, NULL) < 1) {
dev_err(fsl_chan->dev,
"selftest: Cannot alloc resources for DMA\n");
err = -ENODEV;
@@ -927,8 +927,7 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
if (!new_fsl_chan) {
dev_err(&dev->dev, "No free memory for allocating "
"dma channels!\n");
- err = -ENOMEM;
- goto err;
+ return -ENOMEM;
}
/* get dma channel register base */
@@ -936,7 +935,7 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
if (err) {
dev_err(&dev->dev, "Can't get %s property 'reg'\n",
dev->node->full_name);
- goto err;
+ goto err_no_reg;
}
new_fsl_chan->feature = *(u32 *)match->data;
@@ -958,7 +957,7 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
dev_err(&dev->dev, "There is no %d channel!\n",
new_fsl_chan->id);
err = -EINVAL;
- goto err;
+ goto err_no_chan;
}
fdev->chan[new_fsl_chan->id] = new_fsl_chan;
tasklet_init(&new_fsl_chan->tasklet, dma_do_tasklet,
@@ -997,23 +996,26 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
if (err) {
dev_err(&dev->dev, "DMA channel %s request_irq error "
"with return %d\n", dev->node->full_name, err);
- goto err;
+ goto err_no_irq;
}
}
err = fsl_dma_self_test(new_fsl_chan);
if (err)
- goto err;
+ goto err_self_test;
dev_info(&dev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id,
match->compatible, new_fsl_chan->irq);
return 0;
-err:
- dma_halt(new_fsl_chan);
- iounmap(new_fsl_chan->reg_base);
+
+err_self_test:
free_irq(new_fsl_chan->irq, new_fsl_chan);
+err_no_irq:
list_del(&new_fsl_chan->common.device_node);
+err_no_chan:
+ iounmap(new_fsl_chan->reg_base);
+err_no_reg:
kfree(new_fsl_chan);
return err;
}
@@ -1054,8 +1056,7 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
fdev = kzalloc(sizeof(struct fsl_dma_device), GFP_KERNEL);
if (!fdev) {
dev_err(&dev->dev, "No enough memory for 'priv'\n");
- err = -ENOMEM;
- goto err;
+ return -ENOMEM;
}
fdev->dev = &dev->dev;
INIT_LIST_HEAD(&fdev->common.channels);
@@ -1065,7 +1066,7 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
if (err) {
dev_err(&dev->dev, "Can't get %s property 'reg'\n",
dev->node->full_name);
- goto err;
+ goto err_no_reg;
}
dev_info(&dev->dev, "Probe the Freescale DMA driver for %s "
@@ -1103,6 +1104,7 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
err:
iounmap(fdev->reg_base);
+err_no_reg:
kfree(fdev);
return err;
}
diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c
index 16e0fd8facf..9b16a3af9a0 100644
--- a/drivers/dma/ioat.c
+++ b/drivers/dma/ioat.c
@@ -47,6 +47,16 @@ static struct pci_device_id ioat_pci_tbl[] = {
/* I/OAT v2 platforms */
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB) },
+
+ /* I/OAT v3 platforms */
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG1) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG2) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG5) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG6) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG7) },
{ 0, }
};
@@ -83,6 +93,11 @@ static int ioat_setup_functionality(struct pci_dev *pdev, void __iomem *iobase)
if (device->dma && ioat_dca_enabled)
device->dca = ioat2_dca_init(pdev, iobase);
break;
+ case IOAT_VER_3_0:
+ device->dma = ioat_dma_probe(pdev, iobase);
+ if (device->dma && ioat_dca_enabled)
+ device->dca = ioat3_dca_init(pdev, iobase);
+ break;
default:
err = -ENODEV;
break;
diff --git a/drivers/dma/ioat_dca.c b/drivers/dma/ioat_dca.c
index 9e922760b7f..6cf622da028 100644
--- a/drivers/dma/ioat_dca.c
+++ b/drivers/dma/ioat_dca.c
@@ -37,12 +37,18 @@
#include "ioatdma_registers.h"
/*
- * Bit 16 of a tag map entry is the "valid" bit, if it is set then bits 0:15
+ * Bit 7 of a tag map entry is the "valid" bit, if it is set then bits 0:6
* contain the bit number of the APIC ID to map into the DCA tag. If the valid
* bit is not set, then the value must be 0 or 1 and defines the bit in the tag.
*/
#define DCA_TAG_MAP_VALID 0x80
+#define DCA3_TAG_MAP_BIT_TO_INV 0x80
+#define DCA3_TAG_MAP_BIT_TO_SEL 0x40
+#define DCA3_TAG_MAP_LITERAL_VAL 0x1
+
+#define DCA_TAG_MAP_MASK 0xDF
+
/*
* "Legacy" DCA systems do not implement the DCA register set in the
* I/OAT device. Software needs direct support for their tag mappings.
@@ -95,6 +101,7 @@ struct ioat_dca_slot {
};
#define IOAT_DCA_MAX_REQ 6
+#define IOAT3_DCA_MAX_REQ 2
struct ioat_dca_priv {
void __iomem *iobase;
@@ -171,7 +178,9 @@ static int ioat_dca_remove_requester(struct dca_provider *dca,
return -ENODEV;
}
-static u8 ioat_dca_get_tag(struct dca_provider *dca, int cpu)
+static u8 ioat_dca_get_tag(struct dca_provider *dca,
+ struct device *dev,
+ int cpu)
{
struct ioat_dca_priv *ioatdca = dca_priv(dca);
int i, apic_id, bit, value;
@@ -193,10 +202,26 @@ static u8 ioat_dca_get_tag(struct dca_provider *dca, int cpu)
return tag;
}
+static int ioat_dca_dev_managed(struct dca_provider *dca,
+ struct device *dev)
+{
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ struct pci_dev *pdev;
+ int i;
+
+ pdev = to_pci_dev(dev);
+ for (i = 0; i < ioatdca->max_requesters; i++) {
+ if (ioatdca->req_slots[i].pdev == pdev)
+ return 1;
+ }
+ return 0;
+}
+
static struct dca_ops ioat_dca_ops = {
.add_requester = ioat_dca_add_requester,
.remove_requester = ioat_dca_remove_requester,
.get_tag = ioat_dca_get_tag,
+ .dev_managed = ioat_dca_dev_managed,
};
@@ -207,6 +232,8 @@ struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase)
u8 *tag_map = NULL;
int i;
int err;
+ u8 version;
+ u8 max_requesters;
if (!system_has_dca_enabled(pdev))
return NULL;
@@ -237,15 +264,20 @@ struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase)
if (tag_map == NULL)
return NULL;
+ version = readb(iobase + IOAT_VER_OFFSET);
+ if (version == IOAT_VER_3_0)
+ max_requesters = IOAT3_DCA_MAX_REQ;
+ else
+ max_requesters = IOAT_DCA_MAX_REQ;
+
dca = alloc_dca_provider(&ioat_dca_ops,
sizeof(*ioatdca) +
- (sizeof(struct ioat_dca_slot) * IOAT_DCA_MAX_REQ));
+ (sizeof(struct ioat_dca_slot) * max_requesters));
if (!dca)
return NULL;
ioatdca = dca_priv(dca);
- ioatdca->max_requesters = IOAT_DCA_MAX_REQ;
-
+ ioatdca->max_requesters = max_requesters;
ioatdca->dca_base = iobase + 0x54;
/* copy over the APIC ID to DCA tag mapping */
@@ -323,11 +355,13 @@ static int ioat2_dca_remove_requester(struct dca_provider *dca,
return -ENODEV;
}
-static u8 ioat2_dca_get_tag(struct dca_provider *dca, int cpu)
+static u8 ioat2_dca_get_tag(struct dca_provider *dca,
+ struct device *dev,
+ int cpu)
{
u8 tag;
- tag = ioat_dca_get_tag(dca, cpu);
+ tag = ioat_dca_get_tag(dca, dev, cpu);
tag = (~tag) & 0x1F;
return tag;
}
@@ -336,6 +370,7 @@ static struct dca_ops ioat2_dca_ops = {
.add_requester = ioat2_dca_add_requester,
.remove_requester = ioat2_dca_remove_requester,
.get_tag = ioat2_dca_get_tag,
+ .dev_managed = ioat_dca_dev_managed,
};
static int ioat2_dca_count_dca_slots(void __iomem *iobase, u16 dca_offset)
@@ -425,3 +460,198 @@ struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase)
return dca;
}
+
+static int ioat3_dca_add_requester(struct dca_provider *dca, struct device *dev)
+{
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ struct pci_dev *pdev;
+ int i;
+ u16 id;
+ u16 global_req_table;
+
+ /* This implementation only supports PCI-Express */
+ if (dev->bus != &pci_bus_type)
+ return -ENODEV;
+ pdev = to_pci_dev(dev);
+ id = dcaid_from_pcidev(pdev);
+
+ if (ioatdca->requester_count == ioatdca->max_requesters)
+ return -ENODEV;
+
+ for (i = 0; i < ioatdca->max_requesters; i++) {
+ if (ioatdca->req_slots[i].pdev == NULL) {
+ /* found an empty slot */
+ ioatdca->requester_count++;
+ ioatdca->req_slots[i].pdev = pdev;
+ ioatdca->req_slots[i].rid = id;
+ global_req_table =
+ readw(ioatdca->dca_base + IOAT3_DCA_GREQID_OFFSET);
+ writel(id | IOAT_DCA_GREQID_VALID,
+ ioatdca->iobase + global_req_table + (i * 4));
+ return i;
+ }
+ }
+ /* Error, ioatdma->requester_count is out of whack */
+ return -EFAULT;
+}
+
+static int ioat3_dca_remove_requester(struct dca_provider *dca,
+ struct device *dev)
+{
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ struct pci_dev *pdev;
+ int i;
+ u16 global_req_table;
+
+ /* This implementation only supports PCI-Express */
+ if (dev->bus != &pci_bus_type)
+ return -ENODEV;
+ pdev = to_pci_dev(dev);
+
+ for (i = 0; i < ioatdca->max_requesters; i++) {
+ if (ioatdca->req_slots[i].pdev == pdev) {
+ global_req_table =
+ readw(ioatdca->dca_base + IOAT3_DCA_GREQID_OFFSET);
+ writel(0, ioatdca->iobase + global_req_table + (i * 4));
+ ioatdca->req_slots[i].pdev = NULL;
+ ioatdca->req_slots[i].rid = 0;
+ ioatdca->requester_count--;
+ return i;
+ }
+ }
+ return -ENODEV;
+}
+
+static u8 ioat3_dca_get_tag(struct dca_provider *dca,
+ struct device *dev,
+ int cpu)
+{
+ u8 tag;
+
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ int i, apic_id, bit, value;
+ u8 entry;
+
+ tag = 0;
+ apic_id = cpu_physical_id(cpu);
+
+ for (i = 0; i < IOAT_TAG_MAP_LEN; i++) {
+ entry = ioatdca->tag_map[i];
+ if (entry & DCA3_TAG_MAP_BIT_TO_SEL) {
+ bit = entry &
+ ~(DCA3_TAG_MAP_BIT_TO_SEL | DCA3_TAG_MAP_BIT_TO_INV);
+ value = (apic_id & (1 << bit)) ? 1 : 0;
+ } else if (entry & DCA3_TAG_MAP_BIT_TO_INV) {
+ bit = entry & ~DCA3_TAG_MAP_BIT_TO_INV;
+ value = (apic_id & (1 << bit)) ? 0 : 1;
+ } else {
+ value = (entry & DCA3_TAG_MAP_LITERAL_VAL) ? 1 : 0;
+ }
+ tag |= (value << i);
+ }
+
+ return tag;
+}
+
+static struct dca_ops ioat3_dca_ops = {
+ .add_requester = ioat3_dca_add_requester,
+ .remove_requester = ioat3_dca_remove_requester,
+ .get_tag = ioat3_dca_get_tag,
+ .dev_managed = ioat_dca_dev_managed,
+};
+
+static int ioat3_dca_count_dca_slots(void *iobase, u16 dca_offset)
+{
+ int slots = 0;
+ u32 req;
+ u16 global_req_table;
+
+ global_req_table = readw(iobase + dca_offset + IOAT3_DCA_GREQID_OFFSET);
+ if (global_req_table == 0)
+ return 0;
+
+ do {
+ req = readl(iobase + global_req_table + (slots * sizeof(u32)));
+ slots++;
+ } while ((req & IOAT_DCA_GREQID_LASTID) == 0);
+
+ return slots;
+}
+
+struct dca_provider *ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase)
+{
+ struct dca_provider *dca;
+ struct ioat_dca_priv *ioatdca;
+ int slots;
+ int i;
+ int err;
+ u16 dca_offset;
+ u16 csi_fsb_control;
+ u16 pcie_control;
+ u8 bit;
+
+ union {
+ u64 full;
+ struct {
+ u32 low;
+ u32 high;
+ };
+ } tag_map;
+
+ if (!system_has_dca_enabled(pdev))
+ return NULL;
+
+ dca_offset = readw(iobase + IOAT_DCAOFFSET_OFFSET);
+ if (dca_offset == 0)
+ return NULL;
+
+ slots = ioat3_dca_count_dca_slots(iobase, dca_offset);
+ if (slots == 0)
+ return NULL;
+
+ dca = alloc_dca_provider(&ioat3_dca_ops,
+ sizeof(*ioatdca)
+ + (sizeof(struct ioat_dca_slot) * slots));
+ if (!dca)
+ return NULL;
+
+ ioatdca = dca_priv(dca);
+ ioatdca->iobase = iobase;
+ ioatdca->dca_base = iobase + dca_offset;
+ ioatdca->max_requesters = slots;
+
+ /* some bios might not know to turn these on */
+ csi_fsb_control = readw(ioatdca->dca_base + IOAT3_CSI_CONTROL_OFFSET);
+ if ((csi_fsb_control & IOAT3_CSI_CONTROL_PREFETCH) == 0) {
+ csi_fsb_control |= IOAT3_CSI_CONTROL_PREFETCH;
+ writew(csi_fsb_control,
+ ioatdca->dca_base + IOAT3_CSI_CONTROL_OFFSET);
+ }
+ pcie_control = readw(ioatdca->dca_base + IOAT3_PCI_CONTROL_OFFSET);
+ if ((pcie_control & IOAT3_PCI_CONTROL_MEMWR) == 0) {
+ pcie_control |= IOAT3_PCI_CONTROL_MEMWR;
+ writew(pcie_control,
+ ioatdca->dca_base + IOAT3_PCI_CONTROL_OFFSET);
+ }
+
+
+ /* TODO version, compatibility and configuration checks */
+
+ /* copy out the APIC to DCA tag map */
+ tag_map.low =
+ readl(ioatdca->dca_base + IOAT3_APICID_TAG_MAP_OFFSET_LOW);
+ tag_map.high =
+ readl(ioatdca->dca_base + IOAT3_APICID_TAG_MAP_OFFSET_HIGH);
+ for (i = 0; i < 8; i++) {
+ bit = tag_map.full >> (8 * i);
+ ioatdca->tag_map[i] = bit & DCA_TAG_MAP_MASK;
+ }
+
+ err = register_dca_provider(dca, &pdev->dev);
+ if (err) {
+ free_dca_provider(dca);
+ return NULL;
+ }
+
+ return dca;
+}
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
index 318e8a22d81..a52156e5688 100644
--- a/drivers/dma/ioat_dma.c
+++ b/drivers/dma/ioat_dma.c
@@ -32,6 +32,7 @@
#include <linux/dmaengine.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
+#include <linux/workqueue.h>
#include "ioatdma.h"
#include "ioatdma_registers.h"
#include "ioatdma_hw.h"
@@ -41,11 +42,23 @@
#define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)
#define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx)
+#define chan_num(ch) ((int)((ch)->reg_base - (ch)->device->reg_base) / 0x80)
static int ioat_pending_level = 4;
module_param(ioat_pending_level, int, 0644);
MODULE_PARM_DESC(ioat_pending_level,
"high-water mark for pushing ioat descriptors (default: 4)");
+#define RESET_DELAY msecs_to_jiffies(100)
+#define WATCHDOG_DELAY round_jiffies(msecs_to_jiffies(2000))
+static void ioat_dma_chan_reset_part2(struct work_struct *work);
+static void ioat_dma_chan_watchdog(struct work_struct *work);
+
+/*
+ * workaround for IOAT ver.3.0 null descriptor issue
+ * (channel returns error when size is 0)
+ */
+#define NULL_DESC_BUFFER_SIZE 1
+
/* internal functions */
static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan);
static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan);
@@ -122,6 +135,38 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
int i;
struct ioat_dma_chan *ioat_chan;
+ /*
+ * IOAT ver.3 workarounds
+ */
+ if (device->version == IOAT_VER_3_0) {
+ u32 chan_err_mask;
+ u16 dev_id;
+ u32 dmauncerrsts;
+
+ /*
+ * Write CHANERRMSK_INT with 3E07h to mask out the errors
+ * that can cause stability issues for IOAT ver.3
+ */
+ chan_err_mask = 0x3E07;
+ pci_write_config_dword(device->pdev,
+ IOAT_PCI_CHANERRMASK_INT_OFFSET,
+ chan_err_mask);
+
+ /*
+ * Clear DMAUNCERRSTS Cfg-Reg Parity Error status bit
+ * (workaround for spurious config parity error after restart)
+ */
+ pci_read_config_word(device->pdev,
+ IOAT_PCI_DEVICE_ID_OFFSET,
+ &dev_id);
+ if (dev_id == PCI_DEVICE_ID_INTEL_IOAT_TBG0) {
+ dmauncerrsts = 0x10;
+ pci_write_config_dword(device->pdev,
+ IOAT_PCI_DMAUNCERRSTS_OFFSET,
+ dmauncerrsts);
+ }
+ }
+
device->common.chancnt = readb(device->reg_base + IOAT_CHANCNT_OFFSET);
xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET);
xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
@@ -137,6 +182,7 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
ioat_chan->reg_base = device->reg_base + (0x80 * (i + 1));
ioat_chan->xfercap = xfercap;
ioat_chan->desccount = 0;
+ INIT_DELAYED_WORK(&ioat_chan->work, ioat_dma_chan_reset_part2);
if (ioat_chan->device->version != IOAT_VER_1_2) {
writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE
| IOAT_DMA_DCA_ANY_CPU,
@@ -175,7 +221,7 @@ static void ioat1_dma_memcpy_issue_pending(struct dma_chan *chan)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
- if (ioat_chan->pending != 0) {
+ if (ioat_chan->pending > 0) {
spin_lock_bh(&ioat_chan->desc_lock);
__ioat1_dma_memcpy_issue_pending(ioat_chan);
spin_unlock_bh(&ioat_chan->desc_lock);
@@ -194,13 +240,228 @@ static void ioat2_dma_memcpy_issue_pending(struct dma_chan *chan)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
- if (ioat_chan->pending != 0) {
+ if (ioat_chan->pending > 0) {
spin_lock_bh(&ioat_chan->desc_lock);
__ioat2_dma_memcpy_issue_pending(ioat_chan);
spin_unlock_bh(&ioat_chan->desc_lock);
}
}
+
+/**
+ * ioat_dma_chan_reset_part2 - reinit the channel after a reset
+ */
+static void ioat_dma_chan_reset_part2(struct work_struct *work)
+{
+ struct ioat_dma_chan *ioat_chan =
+ container_of(work, struct ioat_dma_chan, work.work);
+ struct ioat_desc_sw *desc;
+
+ spin_lock_bh(&ioat_chan->cleanup_lock);
+ spin_lock_bh(&ioat_chan->desc_lock);
+
+ ioat_chan->completion_virt->low = 0;
+ ioat_chan->completion_virt->high = 0;
+ ioat_chan->pending = 0;
+
+ /*
+ * count the descriptors waiting, and be sure to do it
+ * right for both the CB1 line and the CB2 ring
+ */
+ ioat_chan->dmacount = 0;
+ if (ioat_chan->used_desc.prev) {
+ desc = to_ioat_desc(ioat_chan->used_desc.prev);
+ do {
+ ioat_chan->dmacount++;
+ desc = to_ioat_desc(desc->node.next);
+ } while (&desc->node != ioat_chan->used_desc.next);
+ }
+
+ /*
+ * write the new starting descriptor address
+ * this puts channel engine into ARMED state
+ */
+ desc = to_ioat_desc(ioat_chan->used_desc.prev);
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
+ ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_LOW);
+ writel(((u64) desc->async_tx.phys) >> 32,
+ ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_HIGH);
+
+ writeb(IOAT_CHANCMD_START, ioat_chan->reg_base
+ + IOAT_CHANCMD_OFFSET(ioat_chan->device->version));
+ break;
+ case IOAT_VER_2_0:
+ writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
+ ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_LOW);
+ writel(((u64) desc->async_tx.phys) >> 32,
+ ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_HIGH);
+
+ /* tell the engine to go with what's left to be done */
+ writew(ioat_chan->dmacount,
+ ioat_chan->reg_base + IOAT_CHAN_DMACOUNT_OFFSET);
+
+ break;
+ }
+ dev_err(&ioat_chan->device->pdev->dev,
+ "chan%d reset - %d descs waiting, %d total desc\n",
+ chan_num(ioat_chan), ioat_chan->dmacount, ioat_chan->desccount);
+
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ spin_unlock_bh(&ioat_chan->cleanup_lock);
+}
+
+/**
+ * ioat_dma_reset_channel - restart a channel
+ * @ioat_chan: IOAT DMA channel handle
+ */
+static void ioat_dma_reset_channel(struct ioat_dma_chan *ioat_chan)
+{
+ u32 chansts, chanerr;
+
+ if (!ioat_chan->used_desc.prev)
+ return;
+
+ chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
+ chansts = (ioat_chan->completion_virt->low
+ & IOAT_CHANSTS_DMA_TRANSFER_STATUS);
+ if (chanerr) {
+ dev_err(&ioat_chan->device->pdev->dev,
+ "chan%d, CHANSTS = 0x%08x CHANERR = 0x%04x, clearing\n",
+ chan_num(ioat_chan), chansts, chanerr);
+ writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
+ }
+
+ /*
+ * whack it upside the head with a reset
+ * and wait for things to settle out.
+ * force the pending count to a really big negative
+ * to make sure no one forces an issue_pending
+ * while we're waiting.
+ */
+
+ spin_lock_bh(&ioat_chan->desc_lock);
+ ioat_chan->pending = INT_MIN;
+ writeb(IOAT_CHANCMD_RESET,
+ ioat_chan->reg_base
+ + IOAT_CHANCMD_OFFSET(ioat_chan->device->version));
+ spin_unlock_bh(&ioat_chan->desc_lock);
+
+ /* schedule the 2nd half instead of sleeping a long time */
+ schedule_delayed_work(&ioat_chan->work, RESET_DELAY);
+}
+
+/**
+ * ioat_dma_chan_watchdog - watch for stuck channels
+ */
+static void ioat_dma_chan_watchdog(struct work_struct *work)
+{
+ struct ioatdma_device *device =
+ container_of(work, struct ioatdma_device, work.work);
+ struct ioat_dma_chan *ioat_chan;
+ int i;
+
+ union {
+ u64 full;
+ struct {
+ u32 low;
+ u32 high;
+ };
+ } completion_hw;
+ unsigned long compl_desc_addr_hw;
+
+ for (i = 0; i < device->common.chancnt; i++) {
+ ioat_chan = ioat_lookup_chan_by_index(device, i);
+
+ if (ioat_chan->device->version == IOAT_VER_1_2
+ /* have we started processing anything yet */
+ && ioat_chan->last_completion
+ /* have we completed any since last watchdog cycle? */
+ && (ioat_chan->last_completion ==
+ ioat_chan->watchdog_completion)
+ /* has TCP stuck on one cookie since last watchdog? */
+ && (ioat_chan->watchdog_tcp_cookie ==
+ ioat_chan->watchdog_last_tcp_cookie)
+ && (ioat_chan->watchdog_tcp_cookie !=
+ ioat_chan->completed_cookie)
+ /* is there something in the chain to be processed? */
+ /* CB1 chain always has at least the last one processed */
+ && (ioat_chan->used_desc.prev != ioat_chan->used_desc.next)
+ && ioat_chan->pending == 0) {
+
+ /*
+ * check CHANSTS register for completed
+ * descriptor address.
+ * if it is different than completion writeback,
+ * it is not zero
+ * and it has changed since the last watchdog
+ * we can assume that channel
+ * is still working correctly
+ * and the problem is in completion writeback.
+ * update completion writeback
+ * with actual CHANSTS value
+ * else
+ * try resetting the channel
+ */
+
+ completion_hw.low = readl(ioat_chan->reg_base +
+ IOAT_CHANSTS_OFFSET_LOW(ioat_chan->device->version));
+ completion_hw.high = readl(ioat_chan->reg_base +
+ IOAT_CHANSTS_OFFSET_HIGH(ioat_chan->device->version));
+#if (BITS_PER_LONG == 64)
+ compl_desc_addr_hw =
+ completion_hw.full
+ & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR;
+#else
+ compl_desc_addr_hw =
+ completion_hw.low & IOAT_LOW_COMPLETION_MASK;
+#endif
+
+ if ((compl_desc_addr_hw != 0)
+ && (compl_desc_addr_hw != ioat_chan->watchdog_completion)
+ && (compl_desc_addr_hw != ioat_chan->last_compl_desc_addr_hw)) {
+ ioat_chan->last_compl_desc_addr_hw = compl_desc_addr_hw;
+ ioat_chan->completion_virt->low = completion_hw.low;
+ ioat_chan->completion_virt->high = completion_hw.high;
+ } else {
+ ioat_dma_reset_channel(ioat_chan);
+ ioat_chan->watchdog_completion = 0;
+ ioat_chan->last_compl_desc_addr_hw = 0;
+ }
+
+ /*
+ * for version 2.0 if there are descriptors yet to be processed
+ * and the last completed hasn't changed since the last watchdog
+ * if they haven't hit the pending level
+ * issue the pending to push them through
+ * else
+ * try resetting the channel
+ */
+ } else if (ioat_chan->device->version == IOAT_VER_2_0
+ && ioat_chan->used_desc.prev
+ && ioat_chan->last_completion
+ && ioat_chan->last_completion == ioat_chan->watchdog_completion) {
+
+ if (ioat_chan->pending < ioat_pending_level)
+ ioat2_dma_memcpy_issue_pending(&ioat_chan->common);
+ else {
+ ioat_dma_reset_channel(ioat_chan);
+ ioat_chan->watchdog_completion = 0;
+ }
+ } else {
+ ioat_chan->last_compl_desc_addr_hw = 0;
+ ioat_chan->watchdog_completion
+ = ioat_chan->last_completion;
+ }
+
+ ioat_chan->watchdog_last_tcp_cookie =
+ ioat_chan->watchdog_tcp_cookie;
+ }
+
+ schedule_delayed_work(&device->work, WATCHDOG_DELAY);
+}
+
static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
@@ -250,6 +511,13 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
prev = new;
} while (len && (new = ioat1_dma_get_next_descriptor(ioat_chan)));
+ if (!new) {
+ dev_err(&ioat_chan->device->pdev->dev,
+ "tx submit failed\n");
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ return -ENOMEM;
+ }
+
hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
if (new->async_tx.callback) {
hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN;
@@ -335,7 +603,14 @@ static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)
desc_count++;
} while (len && (new = ioat2_dma_get_next_descriptor(ioat_chan)));
- hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
+ if (!new) {
+ dev_err(&ioat_chan->device->pdev->dev,
+ "tx submit failed\n");
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ return -ENOMEM;
+ }
+
+ hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
if (new->async_tx.callback) {
hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN;
if (first != new) {
@@ -406,6 +681,7 @@ static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
desc_sw->async_tx.tx_submit = ioat1_tx_submit;
break;
case IOAT_VER_2_0:
+ case IOAT_VER_3_0:
desc_sw->async_tx.tx_submit = ioat2_tx_submit;
break;
}
@@ -452,7 +728,8 @@ static void ioat2_dma_massage_chan_desc(struct ioat_dma_chan *ioat_chan)
* ioat_dma_alloc_chan_resources - returns the number of allocated descriptors
* @chan: the channel to be filled out
*/
-static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
+static int ioat_dma_alloc_chan_resources(struct dma_chan *chan,
+ struct dma_client *client)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
struct ioat_desc_sw *desc;
@@ -555,6 +832,7 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan)
}
break;
case IOAT_VER_2_0:
+ case IOAT_VER_3_0:
list_for_each_entry_safe(desc, _desc,
ioat_chan->free_desc.next, node) {
list_del(&desc->node);
@@ -585,6 +863,10 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan)
ioat_chan->last_completion = ioat_chan->completion_addr = 0;
ioat_chan->pending = 0;
ioat_chan->dmacount = 0;
+ ioat_chan->watchdog_completion = 0;
+ ioat_chan->last_compl_desc_addr_hw = 0;
+ ioat_chan->watchdog_tcp_cookie =
+ ioat_chan->watchdog_last_tcp_cookie = 0;
}
/**
@@ -640,7 +922,8 @@ ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
/* set up the noop descriptor */
noop_desc = to_ioat_desc(ioat_chan->used_desc.next);
- noop_desc->hw->size = 0;
+ /* set size to non-zero value (channel returns error when size is 0) */
+ noop_desc->hw->size = NULL_DESC_BUFFER_SIZE;
noop_desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL;
noop_desc->hw->src_addr = 0;
noop_desc->hw->dst_addr = 0;
@@ -690,6 +973,7 @@ static struct ioat_desc_sw *ioat_dma_get_next_descriptor(
return ioat1_dma_get_next_descriptor(ioat_chan);
break;
case IOAT_VER_2_0:
+ case IOAT_VER_3_0:
return ioat2_dma_get_next_descriptor(ioat_chan);
break;
}
@@ -716,8 +1000,12 @@ static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy(
new->src = dma_src;
new->async_tx.flags = flags;
return &new->async_tx;
- } else
+ } else {
+ dev_err(&ioat_chan->device->pdev->dev,
+ "chan%d - get_next_desc failed: %d descs waiting, %d total desc\n",
+ chan_num(ioat_chan), ioat_chan->dmacount, ioat_chan->desccount);
return NULL;
+ }
}
static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(
@@ -744,8 +1032,13 @@ static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(
new->src = dma_src;
new->async_tx.flags = flags;
return &new->async_tx;
- } else
+ } else {
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ dev_err(&ioat_chan->device->pdev->dev,
+ "chan%d - get_next_desc failed: %d descs waiting, %d total desc\n",
+ chan_num(ioat_chan), ioat_chan->dmacount, ioat_chan->desccount);
return NULL;
+ }
}
static void ioat_dma_cleanup_tasklet(unsigned long data)
@@ -756,6 +1049,27 @@ static void ioat_dma_cleanup_tasklet(unsigned long data)
chan->reg_base + IOAT_CHANCTRL_OFFSET);
}
+static void
+ioat_dma_unmap(struct ioat_dma_chan *ioat_chan, struct ioat_desc_sw *desc)
+{
+ /*
+ * yes we are unmapping both _page and _single
+ * alloc'd regions with unmap_page. Is this
+ * *really* that bad?
+ */
+ if (!(desc->async_tx.flags & DMA_COMPL_SKIP_DEST_UNMAP))
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, dst),
+ pci_unmap_len(desc, len),
+ PCI_DMA_FROMDEVICE);
+
+ if (!(desc->async_tx.flags & DMA_COMPL_SKIP_SRC_UNMAP))
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, src),
+ pci_unmap_len(desc, len),
+ PCI_DMA_TODEVICE);
+}
+
/**
* ioat_dma_memcpy_cleanup - cleanup up finished descriptors
* @chan: ioat channel to be cleaned up
@@ -799,11 +1113,27 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
if (phys_complete == ioat_chan->last_completion) {
spin_unlock_bh(&ioat_chan->cleanup_lock);
+ /*
+ * perhaps we're stuck so hard that the watchdog can't go off?
+ * try to catch it after 2 seconds
+ */
+ if (ioat_chan->device->version != IOAT_VER_3_0) {
+ if (time_after(jiffies,
+ ioat_chan->last_completion_time + HZ*WATCHDOG_DELAY)) {
+ ioat_dma_chan_watchdog(&(ioat_chan->device->work.work));
+ ioat_chan->last_completion_time = jiffies;
+ }
+ }
return;
}
+ ioat_chan->last_completion_time = jiffies;
cookie = 0;
- spin_lock_bh(&ioat_chan->desc_lock);
+ if (!spin_trylock_bh(&ioat_chan->desc_lock)) {
+ spin_unlock_bh(&ioat_chan->cleanup_lock);
+ return;
+ }
+
switch (ioat_chan->device->version) {
case IOAT_VER_1_2:
list_for_each_entry_safe(desc, _desc,
@@ -816,21 +1146,7 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
*/
if (desc->async_tx.cookie) {
cookie = desc->async_tx.cookie;
-
- /*
- * yes we are unmapping both _page and _single
- * alloc'd regions with unmap_page. Is this
- * *really* that bad?
- */
- pci_unmap_page(ioat_chan->device->pdev,
- pci_unmap_addr(desc, dst),
- pci_unmap_len(desc, len),
- PCI_DMA_FROMDEVICE);
- pci_unmap_page(ioat_chan->device->pdev,
- pci_unmap_addr(desc, src),
- pci_unmap_len(desc, len),
- PCI_DMA_TODEVICE);
-
+ ioat_dma_unmap(ioat_chan, desc);
if (desc->async_tx.callback) {
desc->async_tx.callback(desc->async_tx.callback_param);
desc->async_tx.callback = NULL;
@@ -862,6 +1178,7 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
}
break;
case IOAT_VER_2_0:
+ case IOAT_VER_3_0:
/* has some other thread has already cleaned up? */
if (ioat_chan->used_desc.prev == NULL)
break;
@@ -889,16 +1206,7 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
if (desc->async_tx.cookie) {
cookie = desc->async_tx.cookie;
desc->async_tx.cookie = 0;
-
- pci_unmap_page(ioat_chan->device->pdev,
- pci_unmap_addr(desc, dst),
- pci_unmap_len(desc, len),
- PCI_DMA_FROMDEVICE);
- pci_unmap_page(ioat_chan->device->pdev,
- pci_unmap_addr(desc, src),
- pci_unmap_len(desc, len),
- PCI_DMA_TODEVICE);
-
+ ioat_dma_unmap(ioat_chan, desc);
if (desc->async_tx.callback) {
desc->async_tx.callback(desc->async_tx.callback_param);
desc->async_tx.callback = NULL;
@@ -943,6 +1251,7 @@ static enum dma_status ioat_dma_is_complete(struct dma_chan *chan,
last_used = chan->cookie;
last_complete = ioat_chan->completed_cookie;
+ ioat_chan->watchdog_tcp_cookie = cookie;
if (done)
*done = last_complete;
@@ -973,10 +1282,19 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan)
spin_lock_bh(&ioat_chan->desc_lock);
desc = ioat_dma_get_next_descriptor(ioat_chan);
+
+ if (!desc) {
+ dev_err(&ioat_chan->device->pdev->dev,
+ "Unable to start null desc - get next desc failed\n");
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ return;
+ }
+
desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL
| IOAT_DMA_DESCRIPTOR_CTL_INT_GN
| IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
- desc->hw->size = 0;
+ /* set size to non-zero value (channel returns error when size is 0) */
+ desc->hw->size = NULL_DESC_BUFFER_SIZE;
desc->hw->src_addr = 0;
desc->hw->dst_addr = 0;
async_tx_ack(&desc->async_tx);
@@ -994,6 +1312,7 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan)
+ IOAT_CHANCMD_OFFSET(ioat_chan->device->version));
break;
case IOAT_VER_2_0:
+ case IOAT_VER_3_0:
writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_LOW);
writel(((u64) desc->async_tx.phys) >> 32,
@@ -1049,7 +1368,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
dma_chan = container_of(device->common.channels.next,
struct dma_chan,
device_node);
- if (device->common.device_alloc_chan_resources(dma_chan) < 1) {
+ if (device->common.device_alloc_chan_resources(dma_chan, NULL) < 1) {
dev_err(&device->pdev->dev,
"selftest cannot allocate chan resource\n");
err = -ENODEV;
@@ -1312,6 +1631,7 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
ioat1_dma_memcpy_issue_pending;
break;
case IOAT_VER_2_0:
+ case IOAT_VER_3_0:
device->common.device_prep_dma_memcpy = ioat2_dma_prep_memcpy;
device->common.device_issue_pending =
ioat2_dma_memcpy_issue_pending;
@@ -1331,8 +1651,16 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
if (err)
goto err_self_test;
+ ioat_set_tcp_copy_break(device);
+
dma_async_device_register(&device->common);
+ if (device->version != IOAT_VER_3_0) {
+ INIT_DELAYED_WORK(&device->work, ioat_dma_chan_watchdog);
+ schedule_delayed_work(&device->work,
+ WATCHDOG_DELAY);
+ }
+
return device;
err_self_test:
@@ -1365,6 +1693,10 @@ void ioat_dma_remove(struct ioatdma_device *device)
pci_release_regions(device->pdev);
pci_disable_device(device->pdev);
+ if (device->version != IOAT_VER_3_0) {
+ cancel_delayed_work(&device->work);
+ }
+
list_for_each_entry_safe(chan, _chan,
&device->common.channels, device_node) {
ioat_chan = to_ioat_chan(chan);
diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h
index f2c7fedbf00..a3306d0e137 100644
--- a/drivers/dma/ioatdma.h
+++ b/drivers/dma/ioatdma.h
@@ -27,8 +27,9 @@
#include <linux/dmapool.h>
#include <linux/cache.h>
#include <linux/pci_ids.h>
+#include <net/tcp.h>
-#define IOAT_DMA_VERSION "2.04"
+#define IOAT_DMA_VERSION "3.30"
enum ioat_interrupt {
none = 0,
@@ -40,6 +41,7 @@ enum ioat_interrupt {
#define IOAT_LOW_COMPLETION_MASK 0xffffffc0
#define IOAT_DMA_DCA_ANY_CPU ~0
+#define IOAT_WATCHDOG_PERIOD (2 * HZ)
/**
@@ -62,6 +64,7 @@ struct ioatdma_device {
struct dma_device common;
u8 version;
enum ioat_interrupt irq_mode;
+ struct delayed_work work;
struct msix_entry msix_entries[4];
struct ioat_dma_chan *idx[4];
};
@@ -75,6 +78,7 @@ struct ioat_dma_chan {
dma_cookie_t completed_cookie;
unsigned long last_completion;
+ unsigned long last_completion_time;
size_t xfercap; /* XFERCAP register value expanded out */
@@ -82,6 +86,10 @@ struct ioat_dma_chan {
spinlock_t desc_lock;
struct list_head free_desc;
struct list_head used_desc;
+ unsigned long watchdog_completion;
+ int watchdog_tcp_cookie;
+ u32 watchdog_last_tcp_cookie;
+ struct delayed_work work;
int pending;
int dmacount;
@@ -98,6 +106,7 @@ struct ioat_dma_chan {
u32 high;
};
} *completion_virt;
+ unsigned long last_compl_desc_addr_hw;
struct tasklet_struct cleanup_task;
};
@@ -121,17 +130,34 @@ struct ioat_desc_sw {
struct dma_async_tx_descriptor async_tx;
};
+static inline void ioat_set_tcp_copy_break(struct ioatdma_device *dev)
+{
+ #ifdef CONFIG_NET_DMA
+ switch (dev->version) {
+ case IOAT_VER_1_2:
+ case IOAT_VER_3_0:
+ sysctl_tcp_dma_copybreak = 4096;
+ break;
+ case IOAT_VER_2_0:
+ sysctl_tcp_dma_copybreak = 2048;
+ break;
+ }
+ #endif
+}
+
#if defined(CONFIG_INTEL_IOATDMA) || defined(CONFIG_INTEL_IOATDMA_MODULE)
struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
void __iomem *iobase);
void ioat_dma_remove(struct ioatdma_device *device);
struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase);
struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase);
+struct dca_provider *ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase);
#else
#define ioat_dma_probe(pdev, iobase) NULL
#define ioat_dma_remove(device) do { } while (0)
#define ioat_dca_init(pdev, iobase) NULL
#define ioat2_dca_init(pdev, iobase) NULL
+#define ioat3_dca_init(pdev, iobase) NULL
#endif
#endif /* IOATDMA_H */
diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h
index dd470fa91d8..f1ae2c776f7 100644
--- a/drivers/dma/ioatdma_hw.h
+++ b/drivers/dma/ioatdma_hw.h
@@ -35,6 +35,7 @@
#define IOAT_PCI_SID 0x8086
#define IOAT_VER_1_2 0x12 /* Version 1.2 */
#define IOAT_VER_2_0 0x20 /* Version 2.0 */
+#define IOAT_VER_3_0 0x30 /* Version 3.0 */
struct ioat_dma_descriptor {
uint32_t size;
diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h
index 9832d7ebd93..827cb503cac 100644
--- a/drivers/dma/ioatdma_registers.h
+++ b/drivers/dma/ioatdma_registers.h
@@ -25,6 +25,10 @@
#define IOAT_PCI_DMACTRL_DMA_EN 0x00000001
#define IOAT_PCI_DMACTRL_MSI_EN 0x00000002
+#define IOAT_PCI_DEVICE_ID_OFFSET 0x02
+#define IOAT_PCI_DMAUNCERRSTS_OFFSET 0x148
+#define IOAT_PCI_CHANERRMASK_INT_OFFSET 0x184
+
/* MMIO Device Registers */
#define IOAT_CHANCNT_OFFSET 0x00 /* 8-bit */
@@ -149,7 +153,23 @@
#define IOAT_DCA_GREQID_VALID 0x20000000
#define IOAT_DCA_GREQID_LASTID 0x80000000
+#define IOAT3_CSI_CAPABILITY_OFFSET 0x08
+#define IOAT3_CSI_CAPABILITY_PREFETCH 0x1
+
+#define IOAT3_PCI_CAPABILITY_OFFSET 0x0A
+#define IOAT3_PCI_CAPABILITY_MEMWR 0x1
+
+#define IOAT3_CSI_CONTROL_OFFSET 0x0C
+#define IOAT3_CSI_CONTROL_PREFETCH 0x1
+
+#define IOAT3_PCI_CONTROL_OFFSET 0x0E
+#define IOAT3_PCI_CONTROL_MEMWR 0x1
+
+#define IOAT3_APICID_TAG_MAP_OFFSET 0x10
+#define IOAT3_APICID_TAG_MAP_OFFSET_LOW 0x10
+#define IOAT3_APICID_TAG_MAP_OFFSET_HIGH 0x14
+#define IOAT3_DCA_GREQID_OFFSET 0x02
#define IOAT1_CHAINADDR_OFFSET 0x0C /* 64-bit Descriptor Chain Address Register */
#define IOAT2_CHAINADDR_OFFSET 0x10 /* 64-bit Descriptor Chain Address Register */
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 0ec0f431e6a..85bfeba4d85 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -82,17 +82,24 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
struct device *dev =
&iop_chan->device->pdev->dev;
u32 len = unmap->unmap_len;
- u32 src_cnt = unmap->unmap_src_cnt;
- dma_addr_t addr = iop_desc_get_dest_addr(unmap,
- iop_chan);
-
- dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
- while (src_cnt--) {
- addr = iop_desc_get_src_addr(unmap,
- iop_chan,
- src_cnt);
- dma_unmap_page(dev, addr, len,
- DMA_TO_DEVICE);
+ enum dma_ctrl_flags flags = desc->async_tx.flags;
+ u32 src_cnt;
+ dma_addr_t addr;
+
+ if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+ addr = iop_desc_get_dest_addr(unmap, iop_chan);
+ dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
+ }
+
+ if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+ src_cnt = unmap->unmap_src_cnt;
+ while (src_cnt--) {
+ addr = iop_desc_get_src_addr(unmap,
+ iop_chan,
+ src_cnt);
+ dma_unmap_page(dev, addr, len,
+ DMA_TO_DEVICE);
+ }
}
desc->group_head = NULL;
}
@@ -366,8 +373,8 @@ retry:
if (!retry++)
goto retry;
- /* try to free some slots if the allocation fails */
- tasklet_schedule(&iop_chan->irq_tasklet);
+ /* perform direct reclaim if the allocation fails */
+ __iop_adma_slot_cleanup(iop_chan);
return NULL;
}
@@ -443,8 +450,18 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx)
static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan);
static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan);
-/* returns the number of allocated descriptors */
-static int iop_adma_alloc_chan_resources(struct dma_chan *chan)
+/**
+ * iop_adma_alloc_chan_resources - returns the number of allocated descriptors
+ * @chan - allocate descriptor resources for this channel
+ * @client - current client requesting the channel be ready for requests
+ *
+ * Note: We keep the slots for 1 operation on iop_chan->chain at all times. To
+ * avoid deadlock, via async_xor, num_descs_in_pool must at a minimum be
+ * greater than 2x the number slots needed to satisfy a device->max_xor
+ * request.
+ * */
+static int iop_adma_alloc_chan_resources(struct dma_chan *chan,
+ struct dma_client *client)
{
char *hw_desc;
int idx;
@@ -838,7 +855,7 @@ static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
dma_chan = container_of(device->common.channels.next,
struct dma_chan,
device_node);
- if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
+ if (iop_adma_alloc_chan_resources(dma_chan, NULL) < 1) {
err = -ENODEV;
goto out;
}
@@ -936,7 +953,7 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
dma_chan = container_of(device->common.channels.next,
struct dma_chan,
device_node);
- if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
+ if (iop_adma_alloc_chan_resources(dma_chan, NULL) < 1) {
err = -ENODEV;
goto out;
}
@@ -1387,6 +1404,8 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
spin_unlock_bh(&iop_chan->lock);
}
+MODULE_ALIAS("platform:iop-adma");
+
static struct platform_driver iop_adma_driver = {
.probe = iop_adma_probe,
.remove = iop_adma_remove,
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
new file mode 100644
index 00000000000..a4e4494663b
--- /dev/null
+++ b/drivers/dma/mv_xor.c
@@ -0,0 +1,1375 @@
+/*
+ * offload engine driver for the Marvell XOR engine
+ * Copyright (C) 2007, 2008, Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/async_tx.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/memory.h>
+#include <asm/plat-orion/mv_xor.h>
+#include "mv_xor.h"
+
+static void mv_xor_issue_pending(struct dma_chan *chan);
+
+#define to_mv_xor_chan(chan) \
+ container_of(chan, struct mv_xor_chan, common)
+
+#define to_mv_xor_device(dev) \
+ container_of(dev, struct mv_xor_device, common)
+
+#define to_mv_xor_slot(tx) \
+ container_of(tx, struct mv_xor_desc_slot, async_tx)
+
+static void mv_desc_init(struct mv_xor_desc_slot *desc, unsigned long flags)
+{
+ struct mv_xor_desc *hw_desc = desc->hw_desc;
+
+ hw_desc->status = (1 << 31);
+ hw_desc->phy_next_desc = 0;
+ hw_desc->desc_command = (1 << 31);
+}
+
+static u32 mv_desc_get_dest_addr(struct mv_xor_desc_slot *desc)
+{
+ struct mv_xor_desc *hw_desc = desc->hw_desc;
+ return hw_desc->phy_dest_addr;
+}
+
+static u32 mv_desc_get_src_addr(struct mv_xor_desc_slot *desc,
+ int src_idx)
+{
+ struct mv_xor_desc *hw_desc = desc->hw_desc;
+ return hw_desc->phy_src_addr[src_idx];
+}
+
+
+static void mv_desc_set_byte_count(struct mv_xor_desc_slot *desc,
+ u32 byte_count)
+{
+ struct mv_xor_desc *hw_desc = desc->hw_desc;
+ hw_desc->byte_count = byte_count;
+}
+
+static void mv_desc_set_next_desc(struct mv_xor_desc_slot *desc,
+ u32 next_desc_addr)
+{
+ struct mv_xor_desc *hw_desc = desc->hw_desc;
+ BUG_ON(hw_desc->phy_next_desc);
+ hw_desc->phy_next_desc = next_desc_addr;
+}
+
+static void mv_desc_clear_next_desc(struct mv_xor_desc_slot *desc)
+{
+ struct mv_xor_desc *hw_desc = desc->hw_desc;
+ hw_desc->phy_next_desc = 0;
+}
+
+static void mv_desc_set_block_fill_val(struct mv_xor_desc_slot *desc, u32 val)
+{
+ desc->value = val;
+}
+
+static void mv_desc_set_dest_addr(struct mv_xor_desc_slot *desc,
+ dma_addr_t addr)
+{
+ struct mv_xor_desc *hw_desc = desc->hw_desc;
+ hw_desc->phy_dest_addr = addr;
+}
+
+static int mv_chan_memset_slot_count(size_t len)
+{
+ return 1;
+}
+
+#define mv_chan_memcpy_slot_count(c) mv_chan_memset_slot_count(c)
+
+static void mv_desc_set_src_addr(struct mv_xor_desc_slot *desc,
+ int index, dma_addr_t addr)
+{
+ struct mv_xor_desc *hw_desc = desc->hw_desc;
+ hw_desc->phy_src_addr[index] = addr;
+ if (desc->type == DMA_XOR)
+ hw_desc->desc_command |= (1 << index);
+}
+
+static u32 mv_chan_get_current_desc(struct mv_xor_chan *chan)
+{
+ return __raw_readl(XOR_CURR_DESC(chan));
+}
+
+static void mv_chan_set_next_descriptor(struct mv_xor_chan *chan,
+ u32 next_desc_addr)
+{
+ __raw_writel(next_desc_addr, XOR_NEXT_DESC(chan));
+}
+
+static void mv_chan_set_dest_pointer(struct mv_xor_chan *chan, u32 desc_addr)
+{
+ __raw_writel(desc_addr, XOR_DEST_POINTER(chan));
+}
+
+static void mv_chan_set_block_size(struct mv_xor_chan *chan, u32 block_size)
+{
+ __raw_writel(block_size, XOR_BLOCK_SIZE(chan));
+}
+
+static void mv_chan_set_value(struct mv_xor_chan *chan, u32 value)
+{
+ __raw_writel(value, XOR_INIT_VALUE_LOW(chan));
+ __raw_writel(value, XOR_INIT_VALUE_HIGH(chan));
+}
+
+static void mv_chan_unmask_interrupts(struct mv_xor_chan *chan)
+{
+ u32 val = __raw_readl(XOR_INTR_MASK(chan));
+ val |= XOR_INTR_MASK_VALUE << (chan->idx * 16);
+ __raw_writel(val, XOR_INTR_MASK(chan));
+}
+
+static u32 mv_chan_get_intr_cause(struct mv_xor_chan *chan)
+{
+ u32 intr_cause = __raw_readl(XOR_INTR_CAUSE(chan));
+ intr_cause = (intr_cause >> (chan->idx * 16)) & 0xFFFF;
+ return intr_cause;
+}
+
+static int mv_is_err_intr(u32 intr_cause)
+{
+ if (intr_cause & ((1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)))
+ return 1;
+
+ return 0;
+}
+
+static void mv_xor_device_clear_eoc_cause(struct mv_xor_chan *chan)
+{
+ u32 val = (1 << (1 + (chan->idx * 16)));
+ dev_dbg(chan->device->common.dev, "%s, val 0x%08x\n", __func__, val);
+ __raw_writel(val, XOR_INTR_CAUSE(chan));
+}
+
+static void mv_xor_device_clear_err_status(struct mv_xor_chan *chan)
+{
+ u32 val = 0xFFFF0000 >> (chan->idx * 16);
+ __raw_writel(val, XOR_INTR_CAUSE(chan));
+}
+
+static int mv_can_chain(struct mv_xor_desc_slot *desc)
+{
+ struct mv_xor_desc_slot *chain_old_tail = list_entry(
+ desc->chain_node.prev, struct mv_xor_desc_slot, chain_node);
+
+ if (chain_old_tail->type != desc->type)
+ return 0;
+ if (desc->type == DMA_MEMSET)
+ return 0;
+
+ return 1;
+}
+
+static void mv_set_mode(struct mv_xor_chan *chan,
+ enum dma_transaction_type type)
+{
+ u32 op_mode;
+ u32 config = __raw_readl(XOR_CONFIG(chan));
+
+ switch (type) {
+ case DMA_XOR:
+ op_mode = XOR_OPERATION_MODE_XOR;
+ break;
+ case DMA_MEMCPY:
+ op_mode = XOR_OPERATION_MODE_MEMCPY;
+ break;
+ case DMA_MEMSET:
+ op_mode = XOR_OPERATION_MODE_MEMSET;
+ break;
+ default:
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "error: unsupported operation %d.\n",
+ type);
+ BUG();
+ return;
+ }
+
+ config &= ~0x7;
+ config |= op_mode;
+ __raw_writel(config, XOR_CONFIG(chan));
+ chan->current_type = type;
+}
+
+static void mv_chan_activate(struct mv_xor_chan *chan)
+{
+ u32 activation;
+
+ dev_dbg(chan->device->common.dev, " activate chan.\n");
+ activation = __raw_readl(XOR_ACTIVATION(chan));
+ activation |= 0x1;
+ __raw_writel(activation, XOR_ACTIVATION(chan));
+}
+
+static char mv_chan_is_busy(struct mv_xor_chan *chan)
+{
+ u32 state = __raw_readl(XOR_ACTIVATION(chan));
+
+ state = (state >> 4) & 0x3;
+
+ return (state == 1) ? 1 : 0;
+}
+
+static int mv_chan_xor_slot_count(size_t len, int src_cnt)
+{
+ return 1;
+}
+
+/**
+ * mv_xor_free_slots - flags descriptor slots for reuse
+ * @slot: Slot to free
+ * Caller must hold &mv_chan->lock while calling this function
+ */
+static void mv_xor_free_slots(struct mv_xor_chan *mv_chan,
+ struct mv_xor_desc_slot *slot)
+{
+ dev_dbg(mv_chan->device->common.dev, "%s %d slot %p\n",
+ __func__, __LINE__, slot);
+
+ slot->slots_per_op = 0;
+
+}
+
+/*
+ * mv_xor_start_new_chain - program the engine to operate on new chain headed by
+ * sw_desc
+ * Caller must hold &mv_chan->lock while calling this function
+ */
+static void mv_xor_start_new_chain(struct mv_xor_chan *mv_chan,
+ struct mv_xor_desc_slot *sw_desc)
+{
+ dev_dbg(mv_chan->device->common.dev, "%s %d: sw_desc %p\n",
+ __func__, __LINE__, sw_desc);
+ if (sw_desc->type != mv_chan->current_type)
+ mv_set_mode(mv_chan, sw_desc->type);
+
+ if (sw_desc->type == DMA_MEMSET) {
+ /* for memset requests we need to program the engine, no
+ * descriptors used.
+ */
+ struct mv_xor_desc *hw_desc = sw_desc->hw_desc;
+ mv_chan_set_dest_pointer(mv_chan, hw_desc->phy_dest_addr);
+ mv_chan_set_block_size(mv_chan, sw_desc->unmap_len);
+ mv_chan_set_value(mv_chan, sw_desc->value);
+ } else {
+ /* set the hardware chain */
+ mv_chan_set_next_descriptor(mv_chan, sw_desc->async_tx.phys);
+ }
+ mv_chan->pending += sw_desc->slot_cnt;
+ mv_xor_issue_pending(&mv_chan->common);
+}
+
+static dma_cookie_t
+mv_xor_run_tx_complete_actions(struct mv_xor_desc_slot *desc,
+ struct mv_xor_chan *mv_chan, dma_cookie_t cookie)
+{
+ BUG_ON(desc->async_tx.cookie < 0);
+
+ if (desc->async_tx.cookie > 0) {
+ cookie = desc->async_tx.cookie;
+
+ /* call the callback (must not sleep or submit new
+ * operations to this channel)
+ */
+ if (desc->async_tx.callback)
+ desc->async_tx.callback(
+ desc->async_tx.callback_param);
+
+ /* unmap dma addresses
+ * (unmap_single vs unmap_page?)
+ */
+ if (desc->group_head && desc->unmap_len) {
+ struct mv_xor_desc_slot *unmap = desc->group_head;
+ struct device *dev =
+ &mv_chan->device->pdev->dev;
+ u32 len = unmap->unmap_len;
+ enum dma_ctrl_flags flags = desc->async_tx.flags;
+ u32 src_cnt;
+ dma_addr_t addr;
+
+ if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+ addr = mv_desc_get_dest_addr(unmap);
+ dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
+ }
+
+ if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+ src_cnt = unmap->unmap_src_cnt;
+ while (src_cnt--) {
+ addr = mv_desc_get_src_addr(unmap,
+ src_cnt);
+ dma_unmap_page(dev, addr, len,
+ DMA_TO_DEVICE);
+ }
+ }
+ desc->group_head = NULL;
+ }
+ }
+
+ /* run dependent operations */
+ async_tx_run_dependencies(&desc->async_tx);
+
+ return cookie;
+}
+
+static int
+mv_xor_clean_completed_slots(struct mv_xor_chan *mv_chan)
+{
+ struct mv_xor_desc_slot *iter, *_iter;
+
+ dev_dbg(mv_chan->device->common.dev, "%s %d\n", __func__, __LINE__);
+ list_for_each_entry_safe(iter, _iter, &mv_chan->completed_slots,
+ completed_node) {
+
+ if (async_tx_test_ack(&iter->async_tx)) {
+ list_del(&iter->completed_node);
+ mv_xor_free_slots(mv_chan, iter);
+ }
+ }
+ return 0;
+}
+
+static int
+mv_xor_clean_slot(struct mv_xor_desc_slot *desc,
+ struct mv_xor_chan *mv_chan)
+{
+ dev_dbg(mv_chan->device->common.dev, "%s %d: desc %p flags %d\n",
+ __func__, __LINE__, desc, desc->async_tx.flags);
+ list_del(&desc->chain_node);
+ /* the client is allowed to attach dependent operations
+ * until 'ack' is set
+ */
+ if (!async_tx_test_ack(&desc->async_tx)) {
+ /* move this slot to the completed_slots */
+ list_add_tail(&desc->completed_node, &mv_chan->completed_slots);
+ return 0;
+ }
+
+ mv_xor_free_slots(mv_chan, desc);
+ return 0;
+}
+
+static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
+{
+ struct mv_xor_desc_slot *iter, *_iter;
+ dma_cookie_t cookie = 0;
+ int busy = mv_chan_is_busy(mv_chan);
+ u32 current_desc = mv_chan_get_current_desc(mv_chan);
+ int seen_current = 0;
+
+ dev_dbg(mv_chan->device->common.dev, "%s %d\n", __func__, __LINE__);
+ dev_dbg(mv_chan->device->common.dev, "current_desc %x\n", current_desc);
+ mv_xor_clean_completed_slots(mv_chan);
+
+ /* free completed slots from the chain starting with
+ * the oldest descriptor
+ */
+
+ list_for_each_entry_safe(iter, _iter, &mv_chan->chain,
+ chain_node) {
+ prefetch(_iter);
+ prefetch(&_iter->async_tx);
+
+ /* do not advance past the current descriptor loaded into the
+ * hardware channel, subsequent descriptors are either in
+ * process or have not been submitted
+ */
+ if (seen_current)
+ break;
+
+ /* stop the search if we reach the current descriptor and the
+ * channel is busy
+ */
+ if (iter->async_tx.phys == current_desc) {
+ seen_current = 1;
+ if (busy)
+ break;
+ }
+
+ cookie = mv_xor_run_tx_complete_actions(iter, mv_chan, cookie);
+
+ if (mv_xor_clean_slot(iter, mv_chan))
+ break;
+ }
+
+ if ((busy == 0) && !list_empty(&mv_chan->chain)) {
+ struct mv_xor_desc_slot *chain_head;
+ chain_head = list_entry(mv_chan->chain.next,
+ struct mv_xor_desc_slot,
+ chain_node);
+
+ mv_xor_start_new_chain(mv_chan, chain_head);
+ }
+
+ if (cookie > 0)
+ mv_chan->completed_cookie = cookie;
+}
+
+static void
+mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
+{
+ spin_lock_bh(&mv_chan->lock);
+ __mv_xor_slot_cleanup(mv_chan);
+ spin_unlock_bh(&mv_chan->lock);
+}
+
+static void mv_xor_tasklet(unsigned long data)
+{
+ struct mv_xor_chan *chan = (struct mv_xor_chan *) data;
+ __mv_xor_slot_cleanup(chan);
+}
+
+static struct mv_xor_desc_slot *
+mv_xor_alloc_slots(struct mv_xor_chan *mv_chan, int num_slots,
+ int slots_per_op)
+{
+ struct mv_xor_desc_slot *iter, *_iter, *alloc_start = NULL;
+ LIST_HEAD(chain);
+ int slots_found, retry = 0;
+
+ /* start search from the last allocated descrtiptor
+ * if a contiguous allocation can not be found start searching
+ * from the beginning of the list
+ */
+retry:
+ slots_found = 0;
+ if (retry == 0)
+ iter = mv_chan->last_used;
+ else
+ iter = list_entry(&mv_chan->all_slots,
+ struct mv_xor_desc_slot,
+ slot_node);
+
+ list_for_each_entry_safe_continue(
+ iter, _iter, &mv_chan->all_slots, slot_node) {
+ prefetch(_iter);
+ prefetch(&_iter->async_tx);
+ if (iter->slots_per_op) {
+ /* give up after finding the first busy slot
+ * on the second pass through the list
+ */
+ if (retry)
+ break;
+
+ slots_found = 0;
+ continue;
+ }
+
+ /* start the allocation if the slot is correctly aligned */
+ if (!slots_found++)
+ alloc_start = iter;
+
+ if (slots_found == num_slots) {
+ struct mv_xor_desc_slot *alloc_tail = NULL;
+ struct mv_xor_desc_slot *last_used = NULL;
+ iter = alloc_start;
+ while (num_slots) {
+ int i;
+
+ /* pre-ack all but the last descriptor */
+ async_tx_ack(&iter->async_tx);
+
+ list_add_tail(&iter->chain_node, &chain);
+ alloc_tail = iter;
+ iter->async_tx.cookie = 0;
+ iter->slot_cnt = num_slots;
+ iter->xor_check_result = NULL;
+ for (i = 0; i < slots_per_op; i++) {
+ iter->slots_per_op = slots_per_op - i;
+ last_used = iter;
+ iter = list_entry(iter->slot_node.next,
+ struct mv_xor_desc_slot,
+ slot_node);
+ }
+ num_slots -= slots_per_op;
+ }
+ alloc_tail->group_head = alloc_start;
+ alloc_tail->async_tx.cookie = -EBUSY;
+ list_splice(&chain, &alloc_tail->async_tx.tx_list);
+ mv_chan->last_used = last_used;
+ mv_desc_clear_next_desc(alloc_start);
+ mv_desc_clear_next_desc(alloc_tail);
+ return alloc_tail;
+ }
+ }
+ if (!retry++)
+ goto retry;
+
+ /* try to free some slots if the allocation fails */
+ tasklet_schedule(&mv_chan->irq_tasklet);
+
+ return NULL;
+}
+
+static dma_cookie_t
+mv_desc_assign_cookie(struct mv_xor_chan *mv_chan,
+ struct mv_xor_desc_slot *desc)
+{
+ dma_cookie_t cookie = mv_chan->common.cookie;
+
+ if (++cookie < 0)
+ cookie = 1;
+ mv_chan->common.cookie = desc->async_tx.cookie = cookie;
+ return cookie;
+}
+
+/************************ DMA engine API functions ****************************/
+static dma_cookie_t
+mv_xor_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct mv_xor_desc_slot *sw_desc = to_mv_xor_slot(tx);
+ struct mv_xor_chan *mv_chan = to_mv_xor_chan(tx->chan);
+ struct mv_xor_desc_slot *grp_start, *old_chain_tail;
+ dma_cookie_t cookie;
+ int new_hw_chain = 1;
+
+ dev_dbg(mv_chan->device->common.dev,
+ "%s sw_desc %p: async_tx %p\n",
+ __func__, sw_desc, &sw_desc->async_tx);
+
+ grp_start = sw_desc->group_head;
+
+ spin_lock_bh(&mv_chan->lock);
+ cookie = mv_desc_assign_cookie(mv_chan, sw_desc);
+
+ if (list_empty(&mv_chan->chain))
+ list_splice_init(&sw_desc->async_tx.tx_list, &mv_chan->chain);
+ else {
+ new_hw_chain = 0;
+
+ old_chain_tail = list_entry(mv_chan->chain.prev,
+ struct mv_xor_desc_slot,
+ chain_node);
+ list_splice_init(&grp_start->async_tx.tx_list,
+ &old_chain_tail->chain_node);
+
+ if (!mv_can_chain(grp_start))
+ goto submit_done;
+
+ dev_dbg(mv_chan->device->common.dev, "Append to last desc %x\n",
+ old_chain_tail->async_tx.phys);
+
+ /* fix up the hardware chain */
+ mv_desc_set_next_desc(old_chain_tail, grp_start->async_tx.phys);
+
+ /* if the channel is not busy */
+ if (!mv_chan_is_busy(mv_chan)) {
+ u32 current_desc = mv_chan_get_current_desc(mv_chan);
+ /*
+ * and the curren desc is the end of the chain before
+ * the append, then we need to start the channel
+ */
+ if (current_desc == old_chain_tail->async_tx.phys)
+ new_hw_chain = 1;
+ }
+ }
+
+ if (new_hw_chain)
+ mv_xor_start_new_chain(mv_chan, grp_start);
+
+submit_done:
+ spin_unlock_bh(&mv_chan->lock);
+
+ return cookie;
+}
+
+/* returns the number of allocated descriptors */
+static int mv_xor_alloc_chan_resources(struct dma_chan *chan,
+ struct dma_client *client)
+{
+ char *hw_desc;
+ int idx;
+ struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+ struct mv_xor_desc_slot *slot = NULL;
+ struct mv_xor_platform_data *plat_data =
+ mv_chan->device->pdev->dev.platform_data;
+ int num_descs_in_pool = plat_data->pool_size/MV_XOR_SLOT_SIZE;
+
+ /* Allocate descriptor slots */
+ idx = mv_chan->slots_allocated;
+ while (idx < num_descs_in_pool) {
+ slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+ if (!slot) {
+ printk(KERN_INFO "MV XOR Channel only initialized"
+ " %d descriptor slots", idx);
+ break;
+ }
+ hw_desc = (char *) mv_chan->device->dma_desc_pool_virt;
+ slot->hw_desc = (void *) &hw_desc[idx * MV_XOR_SLOT_SIZE];
+
+ dma_async_tx_descriptor_init(&slot->async_tx, chan);
+ slot->async_tx.tx_submit = mv_xor_tx_submit;
+ INIT_LIST_HEAD(&slot->chain_node);
+ INIT_LIST_HEAD(&slot->slot_node);
+ INIT_LIST_HEAD(&slot->async_tx.tx_list);
+ hw_desc = (char *) mv_chan->device->dma_desc_pool;
+ slot->async_tx.phys =
+ (dma_addr_t) &hw_desc[idx * MV_XOR_SLOT_SIZE];
+ slot->idx = idx++;
+
+ spin_lock_bh(&mv_chan->lock);
+ mv_chan->slots_allocated = idx;
+ list_add_tail(&slot->slot_node, &mv_chan->all_slots);
+ spin_unlock_bh(&mv_chan->lock);
+ }
+
+ if (mv_chan->slots_allocated && !mv_chan->last_used)
+ mv_chan->last_used = list_entry(mv_chan->all_slots.next,
+ struct mv_xor_desc_slot,
+ slot_node);
+
+ dev_dbg(mv_chan->device->common.dev,
+ "allocated %d descriptor slots last_used: %p\n",
+ mv_chan->slots_allocated, mv_chan->last_used);
+
+ return mv_chan->slots_allocated ? : -ENOMEM;
+}
+
+static struct dma_async_tx_descriptor *
+mv_xor_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+ size_t len, unsigned long flags)
+{
+ struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+ struct mv_xor_desc_slot *sw_desc, *grp_start;
+ int slot_cnt;
+
+ dev_dbg(mv_chan->device->common.dev,
+ "%s dest: %x src %x len: %u flags: %ld\n",
+ __func__, dest, src, len, flags);
+ if (unlikely(len < MV_XOR_MIN_BYTE_COUNT))
+ return NULL;
+
+ BUG_ON(unlikely(len > MV_XOR_MAX_BYTE_COUNT));
+
+ spin_lock_bh(&mv_chan->lock);
+ slot_cnt = mv_chan_memcpy_slot_count(len);
+ sw_desc = mv_xor_alloc_slots(mv_chan, slot_cnt, 1);
+ if (sw_desc) {
+ sw_desc->type = DMA_MEMCPY;
+ sw_desc->async_tx.flags = flags;
+ grp_start = sw_desc->group_head;
+ mv_desc_init(grp_start, flags);
+ mv_desc_set_byte_count(grp_start, len);
+ mv_desc_set_dest_addr(sw_desc->group_head, dest);
+ mv_desc_set_src_addr(grp_start, 0, src);
+ sw_desc->unmap_src_cnt = 1;
+ sw_desc->unmap_len = len;
+ }
+ spin_unlock_bh(&mv_chan->lock);
+
+ dev_dbg(mv_chan->device->common.dev,
+ "%s sw_desc %p async_tx %p\n",
+ __func__, sw_desc, sw_desc ? &sw_desc->async_tx : 0);
+
+ return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static struct dma_async_tx_descriptor *
+mv_xor_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value,
+ size_t len, unsigned long flags)
+{
+ struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+ struct mv_xor_desc_slot *sw_desc, *grp_start;
+ int slot_cnt;
+
+ dev_dbg(mv_chan->device->common.dev,
+ "%s dest: %x len: %u flags: %ld\n",
+ __func__, dest, len, flags);
+ if (unlikely(len < MV_XOR_MIN_BYTE_COUNT))
+ return NULL;
+
+ BUG_ON(unlikely(len > MV_XOR_MAX_BYTE_COUNT));
+
+ spin_lock_bh(&mv_chan->lock);
+ slot_cnt = mv_chan_memset_slot_count(len);
+ sw_desc = mv_xor_alloc_slots(mv_chan, slot_cnt, 1);
+ if (sw_desc) {
+ sw_desc->type = DMA_MEMSET;
+ sw_desc->async_tx.flags = flags;
+ grp_start = sw_desc->group_head;
+ mv_desc_init(grp_start, flags);
+ mv_desc_set_byte_count(grp_start, len);
+ mv_desc_set_dest_addr(sw_desc->group_head, dest);
+ mv_desc_set_block_fill_val(grp_start, value);
+ sw_desc->unmap_src_cnt = 1;
+ sw_desc->unmap_len = len;
+ }
+ spin_unlock_bh(&mv_chan->lock);
+ dev_dbg(mv_chan->device->common.dev,
+ "%s sw_desc %p async_tx %p \n",
+ __func__, sw_desc, &sw_desc->async_tx);
+ return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static struct dma_async_tx_descriptor *
+mv_xor_prep_dma_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
+ unsigned int src_cnt, size_t len, unsigned long flags)
+{
+ struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+ struct mv_xor_desc_slot *sw_desc, *grp_start;
+ int slot_cnt;
+
+ if (unlikely(len < MV_XOR_MIN_BYTE_COUNT))
+ return NULL;
+
+ BUG_ON(unlikely(len > MV_XOR_MAX_BYTE_COUNT));
+
+ dev_dbg(mv_chan->device->common.dev,
+ "%s src_cnt: %d len: dest %x %u flags: %ld\n",
+ __func__, src_cnt, len, dest, flags);
+
+ spin_lock_bh(&mv_chan->lock);
+ slot_cnt = mv_chan_xor_slot_count(len, src_cnt);
+ sw_desc = mv_xor_alloc_slots(mv_chan, slot_cnt, 1);
+ if (sw_desc) {
+ sw_desc->type = DMA_XOR;
+ sw_desc->async_tx.flags = flags;
+ grp_start = sw_desc->group_head;
+ mv_desc_init(grp_start, flags);
+ /* the byte count field is the same as in memcpy desc*/
+ mv_desc_set_byte_count(grp_start, len);
+ mv_desc_set_dest_addr(sw_desc->group_head, dest);
+ sw_desc->unmap_src_cnt = src_cnt;
+ sw_desc->unmap_len = len;
+ while (src_cnt--)
+ mv_desc_set_src_addr(grp_start, src_cnt, src[src_cnt]);
+ }
+ spin_unlock_bh(&mv_chan->lock);
+ dev_dbg(mv_chan->device->common.dev,
+ "%s sw_desc %p async_tx %p \n",
+ __func__, sw_desc, &sw_desc->async_tx);
+ return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static void mv_xor_free_chan_resources(struct dma_chan *chan)
+{
+ struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+ struct mv_xor_desc_slot *iter, *_iter;
+ int in_use_descs = 0;
+
+ mv_xor_slot_cleanup(mv_chan);
+
+ spin_lock_bh(&mv_chan->lock);
+ list_for_each_entry_safe(iter, _iter, &mv_chan->chain,
+ chain_node) {
+ in_use_descs++;
+ list_del(&iter->chain_node);
+ }
+ list_for_each_entry_safe(iter, _iter, &mv_chan->completed_slots,
+ completed_node) {
+ in_use_descs++;
+ list_del(&iter->completed_node);
+ }
+ list_for_each_entry_safe_reverse(
+ iter, _iter, &mv_chan->all_slots, slot_node) {
+ list_del(&iter->slot_node);
+ kfree(iter);
+ mv_chan->slots_allocated--;
+ }
+ mv_chan->last_used = NULL;
+
+ dev_dbg(mv_chan->device->common.dev, "%s slots_allocated %d\n",
+ __func__, mv_chan->slots_allocated);
+ spin_unlock_bh(&mv_chan->lock);
+
+ if (in_use_descs)
+ dev_err(mv_chan->device->common.dev,
+ "freeing %d in use descriptors!\n", in_use_descs);
+}
+
+/**
+ * mv_xor_is_complete - poll the status of an XOR transaction
+ * @chan: XOR channel handle
+ * @cookie: XOR transaction identifier
+ */
+static enum dma_status mv_xor_is_complete(struct dma_chan *chan,
+ dma_cookie_t cookie,
+ dma_cookie_t *done,
+ dma_cookie_t *used)
+{
+ struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+ dma_cookie_t last_used;
+ dma_cookie_t last_complete;
+ enum dma_status ret;
+
+ last_used = chan->cookie;
+ last_complete = mv_chan->completed_cookie;
+ mv_chan->is_complete_cookie = cookie;
+ if (done)
+ *done = last_complete;
+ if (used)
+ *used = last_used;
+
+ ret = dma_async_is_complete(cookie, last_complete, last_used);
+ if (ret == DMA_SUCCESS) {
+ mv_xor_clean_completed_slots(mv_chan);
+ return ret;
+ }
+ mv_xor_slot_cleanup(mv_chan);
+
+ last_used = chan->cookie;
+ last_complete = mv_chan->completed_cookie;
+
+ if (done)
+ *done = last_complete;
+ if (used)
+ *used = last_used;
+
+ return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+static void mv_dump_xor_regs(struct mv_xor_chan *chan)
+{
+ u32 val;
+
+ val = __raw_readl(XOR_CONFIG(chan));
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "config 0x%08x.\n", val);
+
+ val = __raw_readl(XOR_ACTIVATION(chan));
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "activation 0x%08x.\n", val);
+
+ val = __raw_readl(XOR_INTR_CAUSE(chan));
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "intr cause 0x%08x.\n", val);
+
+ val = __raw_readl(XOR_INTR_MASK(chan));
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "intr mask 0x%08x.\n", val);
+
+ val = __raw_readl(XOR_ERROR_CAUSE(chan));
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "error cause 0x%08x.\n", val);
+
+ val = __raw_readl(XOR_ERROR_ADDR(chan));
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "error addr 0x%08x.\n", val);
+}
+
+static void mv_xor_err_interrupt_handler(struct mv_xor_chan *chan,
+ u32 intr_cause)
+{
+ if (intr_cause & (1 << 4)) {
+ dev_dbg(chan->device->common.dev,
+ "ignore this error\n");
+ return;
+ }
+
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "error on chan %d. intr cause 0x%08x.\n",
+ chan->idx, intr_cause);
+
+ mv_dump_xor_regs(chan);
+ BUG();
+}
+
+static irqreturn_t mv_xor_interrupt_handler(int irq, void *data)
+{
+ struct mv_xor_chan *chan = data;
+ u32 intr_cause = mv_chan_get_intr_cause(chan);
+
+ dev_dbg(chan->device->common.dev, "intr cause %x\n", intr_cause);
+
+ if (mv_is_err_intr(intr_cause))
+ mv_xor_err_interrupt_handler(chan, intr_cause);
+
+ tasklet_schedule(&chan->irq_tasklet);
+
+ mv_xor_device_clear_eoc_cause(chan);
+
+ return IRQ_HANDLED;
+}
+
+static void mv_xor_issue_pending(struct dma_chan *chan)
+{
+ struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+
+ if (mv_chan->pending >= MV_XOR_THRESHOLD) {
+ mv_chan->pending = 0;
+ mv_chan_activate(mv_chan);
+ }
+}
+
+/*
+ * Perform a transaction to verify the HW works.
+ */
+#define MV_XOR_TEST_SIZE 2000
+
+static int __devinit mv_xor_memcpy_self_test(struct mv_xor_device *device)
+{
+ int i;
+ void *src, *dest;
+ dma_addr_t src_dma, dest_dma;
+ struct dma_chan *dma_chan;
+ dma_cookie_t cookie;
+ struct dma_async_tx_descriptor *tx;
+ int err = 0;
+ struct mv_xor_chan *mv_chan;
+
+ src = kmalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL);
+ if (!src)
+ return -ENOMEM;
+
+ dest = kzalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL);
+ if (!dest) {
+ kfree(src);
+ return -ENOMEM;
+ }
+
+ /* Fill in src buffer */
+ for (i = 0; i < MV_XOR_TEST_SIZE; i++)
+ ((u8 *) src)[i] = (u8)i;
+
+ /* Start copy, using first DMA channel */
+ dma_chan = container_of(device->common.channels.next,
+ struct dma_chan,
+ device_node);
+ if (mv_xor_alloc_chan_resources(dma_chan, NULL) < 1) {
+ err = -ENODEV;
+ goto out;
+ }
+
+ dest_dma = dma_map_single(dma_chan->device->dev, dest,
+ MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
+
+ src_dma = dma_map_single(dma_chan->device->dev, src,
+ MV_XOR_TEST_SIZE, DMA_TO_DEVICE);
+
+ tx = mv_xor_prep_dma_memcpy(dma_chan, dest_dma, src_dma,
+ MV_XOR_TEST_SIZE, 0);
+ cookie = mv_xor_tx_submit(tx);
+ mv_xor_issue_pending(dma_chan);
+ async_tx_ack(tx);
+ msleep(1);
+
+ if (mv_xor_is_complete(dma_chan, cookie, NULL, NULL) !=
+ DMA_SUCCESS) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test copy timed out, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+
+ mv_chan = to_mv_xor_chan(dma_chan);
+ dma_sync_single_for_cpu(&mv_chan->device->pdev->dev, dest_dma,
+ MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
+ if (memcmp(src, dest, MV_XOR_TEST_SIZE)) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test copy failed compare, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+
+free_resources:
+ mv_xor_free_chan_resources(dma_chan);
+out:
+ kfree(src);
+ kfree(dest);
+ return err;
+}
+
+#define MV_XOR_NUM_SRC_TEST 4 /* must be <= 15 */
+static int __devinit
+mv_xor_xor_self_test(struct mv_xor_device *device)
+{
+ int i, src_idx;
+ struct page *dest;
+ struct page *xor_srcs[MV_XOR_NUM_SRC_TEST];
+ dma_addr_t dma_srcs[MV_XOR_NUM_SRC_TEST];
+ dma_addr_t dest_dma;
+ struct dma_async_tx_descriptor *tx;
+ struct dma_chan *dma_chan;
+ dma_cookie_t cookie;
+ u8 cmp_byte = 0;
+ u32 cmp_word;
+ int err = 0;
+ struct mv_xor_chan *mv_chan;
+
+ for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
+ xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
+ if (!xor_srcs[src_idx])
+ while (src_idx--) {
+ __free_page(xor_srcs[src_idx]);
+ return -ENOMEM;
+ }
+ }
+
+ dest = alloc_page(GFP_KERNEL);
+ if (!dest)
+ while (src_idx--) {
+ __free_page(xor_srcs[src_idx]);
+ return -ENOMEM;
+ }
+
+ /* Fill in src buffers */
+ for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
+ u8 *ptr = page_address(xor_srcs[src_idx]);
+ for (i = 0; i < PAGE_SIZE; i++)
+ ptr[i] = (1 << src_idx);
+ }
+
+ for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++)
+ cmp_byte ^= (u8) (1 << src_idx);
+
+ cmp_word = (cmp_byte << 24) | (cmp_byte << 16) |
+ (cmp_byte << 8) | cmp_byte;
+
+ memset(page_address(dest), 0, PAGE_SIZE);
+
+ dma_chan = container_of(device->common.channels.next,
+ struct dma_chan,
+ device_node);
+ if (mv_xor_alloc_chan_resources(dma_chan, NULL) < 1) {
+ err = -ENODEV;
+ goto out;
+ }
+
+ /* test xor */
+ dest_dma = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE,
+ DMA_FROM_DEVICE);
+
+ for (i = 0; i < MV_XOR_NUM_SRC_TEST; i++)
+ dma_srcs[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
+ 0, PAGE_SIZE, DMA_TO_DEVICE);
+
+ tx = mv_xor_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
+ MV_XOR_NUM_SRC_TEST, PAGE_SIZE, 0);
+
+ cookie = mv_xor_tx_submit(tx);
+ mv_xor_issue_pending(dma_chan);
+ async_tx_ack(tx);
+ msleep(8);
+
+ if (mv_xor_is_complete(dma_chan, cookie, NULL, NULL) !=
+ DMA_SUCCESS) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test xor timed out, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+
+ mv_chan = to_mv_xor_chan(dma_chan);
+ dma_sync_single_for_cpu(&mv_chan->device->pdev->dev, dest_dma,
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) {
+ u32 *ptr = page_address(dest);
+ if (ptr[i] != cmp_word) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test xor failed compare, disabling."
+ " index %d, data %x, expected %x\n", i,
+ ptr[i], cmp_word);
+ err = -ENODEV;
+ goto free_resources;
+ }
+ }
+
+free_resources:
+ mv_xor_free_chan_resources(dma_chan);
+out:
+ src_idx = MV_XOR_NUM_SRC_TEST;
+ while (src_idx--)
+ __free_page(xor_srcs[src_idx]);
+ __free_page(dest);
+ return err;
+}
+
+static int __devexit mv_xor_remove(struct platform_device *dev)
+{
+ struct mv_xor_device *device = platform_get_drvdata(dev);
+ struct dma_chan *chan, *_chan;
+ struct mv_xor_chan *mv_chan;
+ struct mv_xor_platform_data *plat_data = dev->dev.platform_data;
+
+ dma_async_device_unregister(&device->common);
+
+ dma_free_coherent(&dev->dev, plat_data->pool_size,
+ device->dma_desc_pool_virt, device->dma_desc_pool);
+
+ list_for_each_entry_safe(chan, _chan, &device->common.channels,
+ device_node) {
+ mv_chan = to_mv_xor_chan(chan);
+ list_del(&chan->device_node);
+ }
+
+ return 0;
+}
+
+static int __devinit mv_xor_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ int irq;
+ struct mv_xor_device *adev;
+ struct mv_xor_chan *mv_chan;
+ struct dma_device *dma_dev;
+ struct mv_xor_platform_data *plat_data = pdev->dev.platform_data;
+
+
+ adev = devm_kzalloc(&pdev->dev, sizeof(*adev), GFP_KERNEL);
+ if (!adev)
+ return -ENOMEM;
+
+ dma_dev = &adev->common;
+
+ /* allocate coherent memory for hardware descriptors
+ * note: writecombine gives slightly better performance, but
+ * requires that we explicitly flush the writes
+ */
+ adev->dma_desc_pool_virt = dma_alloc_writecombine(&pdev->dev,
+ plat_data->pool_size,
+ &adev->dma_desc_pool,
+ GFP_KERNEL);
+ if (!adev->dma_desc_pool_virt)
+ return -ENOMEM;
+
+ adev->id = plat_data->hw_id;
+
+ /* discover transaction capabilites from the platform data */
+ dma_dev->cap_mask = plat_data->cap_mask;
+ adev->pdev = pdev;
+ platform_set_drvdata(pdev, adev);
+
+ adev->shared = platform_get_drvdata(plat_data->shared);
+
+ INIT_LIST_HEAD(&dma_dev->channels);
+
+ /* set base routines */
+ dma_dev->device_alloc_chan_resources = mv_xor_alloc_chan_resources;
+ dma_dev->device_free_chan_resources = mv_xor_free_chan_resources;
+ dma_dev->device_is_tx_complete = mv_xor_is_complete;
+ dma_dev->device_issue_pending = mv_xor_issue_pending;
+ dma_dev->dev = &pdev->dev;
+
+ /* set prep routines based on capability */
+ if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask))
+ dma_dev->device_prep_dma_memcpy = mv_xor_prep_dma_memcpy;
+ if (dma_has_cap(DMA_MEMSET, dma_dev->cap_mask))
+ dma_dev->device_prep_dma_memset = mv_xor_prep_dma_memset;
+ if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
+ dma_dev->max_xor = 8; ;
+ dma_dev->device_prep_dma_xor = mv_xor_prep_dma_xor;
+ }
+
+ mv_chan = devm_kzalloc(&pdev->dev, sizeof(*mv_chan), GFP_KERNEL);
+ if (!mv_chan) {
+ ret = -ENOMEM;
+ goto err_free_dma;
+ }
+ mv_chan->device = adev;
+ mv_chan->idx = plat_data->hw_id;
+ mv_chan->mmr_base = adev->shared->xor_base;
+
+ if (!mv_chan->mmr_base) {
+ ret = -ENOMEM;
+ goto err_free_dma;
+ }
+ tasklet_init(&mv_chan->irq_tasklet, mv_xor_tasklet, (unsigned long)
+ mv_chan);
+
+ /* clear errors before enabling interrupts */
+ mv_xor_device_clear_err_status(mv_chan);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = irq;
+ goto err_free_dma;
+ }
+ ret = devm_request_irq(&pdev->dev, irq,
+ mv_xor_interrupt_handler,
+ 0, dev_name(&pdev->dev), mv_chan);
+ if (ret)
+ goto err_free_dma;
+
+ mv_chan_unmask_interrupts(mv_chan);
+
+ mv_set_mode(mv_chan, DMA_MEMCPY);
+
+ spin_lock_init(&mv_chan->lock);
+ INIT_LIST_HEAD(&mv_chan->chain);
+ INIT_LIST_HEAD(&mv_chan->completed_slots);
+ INIT_LIST_HEAD(&mv_chan->all_slots);
+ INIT_RCU_HEAD(&mv_chan->common.rcu);
+ mv_chan->common.device = dma_dev;
+
+ list_add_tail(&mv_chan->common.device_node, &dma_dev->channels);
+
+ if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
+ ret = mv_xor_memcpy_self_test(adev);
+ dev_dbg(&pdev->dev, "memcpy self test returned %d\n", ret);
+ if (ret)
+ goto err_free_dma;
+ }
+
+ if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
+ ret = mv_xor_xor_self_test(adev);
+ dev_dbg(&pdev->dev, "xor self test returned %d\n", ret);
+ if (ret)
+ goto err_free_dma;
+ }
+
+ dev_printk(KERN_INFO, &pdev->dev, "Marvell XOR: "
+ "( %s%s%s%s)\n",
+ dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "",
+ dma_has_cap(DMA_MEMSET, dma_dev->cap_mask) ? "fill " : "",
+ dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "",
+ dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : "");
+
+ dma_async_device_register(dma_dev);
+ goto out;
+
+ err_free_dma:
+ dma_free_coherent(&adev->pdev->dev, plat_data->pool_size,
+ adev->dma_desc_pool_virt, adev->dma_desc_pool);
+ out:
+ return ret;
+}
+
+static void
+mv_xor_conf_mbus_windows(struct mv_xor_shared_private *msp,
+ struct mbus_dram_target_info *dram)
+{
+ void __iomem *base = msp->xor_base;
+ u32 win_enable = 0;
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ writel(0, base + WINDOW_BASE(i));
+ writel(0, base + WINDOW_SIZE(i));
+ if (i < 4)
+ writel(0, base + WINDOW_REMAP_HIGH(i));
+ }
+
+ for (i = 0; i < dram->num_cs; i++) {
+ struct mbus_dram_window *cs = dram->cs + i;
+
+ writel((cs->base & 0xffff0000) |
+ (cs->mbus_attr << 8) |
+ dram->mbus_dram_target_id, base + WINDOW_BASE(i));
+ writel((cs->size - 1) & 0xffff0000, base + WINDOW_SIZE(i));
+
+ win_enable |= (1 << i);
+ win_enable |= 3 << (16 + (2 * i));
+ }
+
+ writel(win_enable, base + WINDOW_BAR_ENABLE(0));
+ writel(win_enable, base + WINDOW_BAR_ENABLE(1));
+}
+
+static struct platform_driver mv_xor_driver = {
+ .probe = mv_xor_probe,
+ .remove = mv_xor_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = MV_XOR_NAME,
+ },
+};
+
+static int mv_xor_shared_probe(struct platform_device *pdev)
+{
+ struct mv_xor_platform_shared_data *msd = pdev->dev.platform_data;
+ struct mv_xor_shared_private *msp;
+ struct resource *res;
+
+ dev_printk(KERN_NOTICE, &pdev->dev, "Marvell shared XOR driver\n");
+
+ msp = devm_kzalloc(&pdev->dev, sizeof(*msp), GFP_KERNEL);
+ if (!msp)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ msp->xor_base = devm_ioremap(&pdev->dev, res->start,
+ res->end - res->start + 1);
+ if (!msp->xor_base)
+ return -EBUSY;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res)
+ return -ENODEV;
+
+ msp->xor_high_base = devm_ioremap(&pdev->dev, res->start,
+ res->end - res->start + 1);
+ if (!msp->xor_high_base)
+ return -EBUSY;
+
+ platform_set_drvdata(pdev, msp);
+
+ /*
+ * (Re-)program MBUS remapping windows if we are asked to.
+ */
+ if (msd != NULL && msd->dram != NULL)
+ mv_xor_conf_mbus_windows(msp, msd->dram);
+
+ return 0;
+}
+
+static int mv_xor_shared_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver mv_xor_shared_driver = {
+ .probe = mv_xor_shared_probe,
+ .remove = mv_xor_shared_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = MV_XOR_SHARED_NAME,
+ },
+};
+
+
+static int __init mv_xor_init(void)
+{
+ int rc;
+
+ rc = platform_driver_register(&mv_xor_shared_driver);
+ if (!rc) {
+ rc = platform_driver_register(&mv_xor_driver);
+ if (rc)
+ platform_driver_unregister(&mv_xor_shared_driver);
+ }
+ return rc;
+}
+module_init(mv_xor_init);
+
+/* it's currently unsafe to unload this module */
+#if 0
+static void __exit mv_xor_exit(void)
+{
+ platform_driver_unregister(&mv_xor_driver);
+ platform_driver_unregister(&mv_xor_shared_driver);
+ return;
+}
+
+module_exit(mv_xor_exit);
+#endif
+
+MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>");
+MODULE_DESCRIPTION("DMA engine driver for Marvell's XOR engine");
+MODULE_LICENSE("GPL");
diff --git a/drivers/dma/mv_xor.h b/drivers/dma/mv_xor.h
new file mode 100644
index 00000000000..06cafe1ef52
--- /dev/null
+++ b/drivers/dma/mv_xor.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2007, 2008, Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MV_XOR_H
+#define MV_XOR_H
+
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+
+#define USE_TIMER
+#define MV_XOR_SLOT_SIZE 64
+#define MV_XOR_THRESHOLD 1
+
+#define XOR_OPERATION_MODE_XOR 0
+#define XOR_OPERATION_MODE_MEMCPY 2
+#define XOR_OPERATION_MODE_MEMSET 4
+
+#define XOR_CURR_DESC(chan) (chan->mmr_base + 0x210 + (chan->idx * 4))
+#define XOR_NEXT_DESC(chan) (chan->mmr_base + 0x200 + (chan->idx * 4))
+#define XOR_BYTE_COUNT(chan) (chan->mmr_base + 0x220 + (chan->idx * 4))
+#define XOR_DEST_POINTER(chan) (chan->mmr_base + 0x2B0 + (chan->idx * 4))
+#define XOR_BLOCK_SIZE(chan) (chan->mmr_base + 0x2C0 + (chan->idx * 4))
+#define XOR_INIT_VALUE_LOW(chan) (chan->mmr_base + 0x2E0)
+#define XOR_INIT_VALUE_HIGH(chan) (chan->mmr_base + 0x2E4)
+
+#define XOR_CONFIG(chan) (chan->mmr_base + 0x10 + (chan->idx * 4))
+#define XOR_ACTIVATION(chan) (chan->mmr_base + 0x20 + (chan->idx * 4))
+#define XOR_INTR_CAUSE(chan) (chan->mmr_base + 0x30)
+#define XOR_INTR_MASK(chan) (chan->mmr_base + 0x40)
+#define XOR_ERROR_CAUSE(chan) (chan->mmr_base + 0x50)
+#define XOR_ERROR_ADDR(chan) (chan->mmr_base + 0x60)
+#define XOR_INTR_MASK_VALUE 0x3F5
+
+#define WINDOW_BASE(w) (0x250 + ((w) << 2))
+#define WINDOW_SIZE(w) (0x270 + ((w) << 2))
+#define WINDOW_REMAP_HIGH(w) (0x290 + ((w) << 2))
+#define WINDOW_BAR_ENABLE(chan) (0x240 + ((chan) << 2))
+
+struct mv_xor_shared_private {
+ void __iomem *xor_base;
+ void __iomem *xor_high_base;
+};
+
+
+/**
+ * struct mv_xor_device - internal representation of a XOR device
+ * @pdev: Platform device
+ * @id: HW XOR Device selector
+ * @dma_desc_pool: base of DMA descriptor region (DMA address)
+ * @dma_desc_pool_virt: base of DMA descriptor region (CPU address)
+ * @common: embedded struct dma_device
+ */
+struct mv_xor_device {
+ struct platform_device *pdev;
+ int id;
+ dma_addr_t dma_desc_pool;
+ void *dma_desc_pool_virt;
+ struct dma_device common;
+ struct mv_xor_shared_private *shared;
+};
+
+/**
+ * struct mv_xor_chan - internal representation of a XOR channel
+ * @pending: allows batching of hardware operations
+ * @completed_cookie: identifier for the most recently completed operation
+ * @lock: serializes enqueue/dequeue operations to the descriptors pool
+ * @mmr_base: memory mapped register base
+ * @idx: the index of the xor channel
+ * @chain: device chain view of the descriptors
+ * @completed_slots: slots completed by HW but still need to be acked
+ * @device: parent device
+ * @common: common dmaengine channel object members
+ * @last_used: place holder for allocation to continue from where it left off
+ * @all_slots: complete domain of slots usable by the channel
+ * @slots_allocated: records the actual size of the descriptor slot pool
+ * @irq_tasklet: bottom half where mv_xor_slot_cleanup runs
+ */
+struct mv_xor_chan {
+ int pending;
+ dma_cookie_t completed_cookie;
+ spinlock_t lock; /* protects the descriptor slot pool */
+ void __iomem *mmr_base;
+ unsigned int idx;
+ enum dma_transaction_type current_type;
+ struct list_head chain;
+ struct list_head completed_slots;
+ struct mv_xor_device *device;
+ struct dma_chan common;
+ struct mv_xor_desc_slot *last_used;
+ struct list_head all_slots;
+ int slots_allocated;
+ struct tasklet_struct irq_tasklet;
+#ifdef USE_TIMER
+ unsigned long cleanup_time;
+ u32 current_on_last_cleanup;
+ dma_cookie_t is_complete_cookie;
+#endif
+};
+
+/**
+ * struct mv_xor_desc_slot - software descriptor
+ * @slot_node: node on the mv_xor_chan.all_slots list
+ * @chain_node: node on the mv_xor_chan.chain list
+ * @completed_node: node on the mv_xor_chan.completed_slots list
+ * @hw_desc: virtual address of the hardware descriptor chain
+ * @phys: hardware address of the hardware descriptor chain
+ * @group_head: first operation in a transaction
+ * @slot_cnt: total slots used in an transaction (group of operations)
+ * @slots_per_op: number of slots per operation
+ * @idx: pool index
+ * @unmap_src_cnt: number of xor sources
+ * @unmap_len: transaction bytecount
+ * @async_tx: support for the async_tx api
+ * @group_list: list of slots that make up a multi-descriptor transaction
+ * for example transfer lengths larger than the supported hw max
+ * @xor_check_result: result of zero sum
+ * @crc32_result: result crc calculation
+ */
+struct mv_xor_desc_slot {
+ struct list_head slot_node;
+ struct list_head chain_node;
+ struct list_head completed_node;
+ enum dma_transaction_type type;
+ void *hw_desc;
+ struct mv_xor_desc_slot *group_head;
+ u16 slot_cnt;
+ u16 slots_per_op;
+ u16 idx;
+ u16 unmap_src_cnt;
+ u32 value;
+ size_t unmap_len;
+ struct dma_async_tx_descriptor async_tx;
+ union {
+ u32 *xor_check_result;
+ u32 *crc32_result;
+ };
+#ifdef USE_TIMER
+ unsigned long arrival_time;
+ struct timer_list timeout;
+#endif
+};
+
+/* This structure describes XOR descriptor size 64bytes */
+struct mv_xor_desc {
+ u32 status; /* descriptor execution status */
+ u32 crc32_result; /* result of CRC-32 calculation */
+ u32 desc_command; /* type of operation to be carried out */
+ u32 phy_next_desc; /* next descriptor address pointer */
+ u32 byte_count; /* size of src/dst blocks in bytes */
+ u32 phy_dest_addr; /* destination block address */
+ u32 phy_src_addr[8]; /* source block addresses */
+ u32 reserved0;
+ u32 reserved1;
+};
+
+#define to_mv_sw_desc(addr_hw_desc) \
+ container_of(addr_hw_desc, struct mv_xor_desc_slot, hw_desc)
+
+#define mv_hw_desc_slot_idx(hw_desc, idx) \
+ ((void *)(((unsigned long)hw_desc) + ((idx) << 5)))
+
+#define MV_XOR_MIN_BYTE_COUNT (128)
+#define XOR_MAX_BYTE_COUNT ((16 * 1024 * 1024) - 1)
+#define MV_XOR_MAX_BYTE_COUNT XOR_MAX_BYTE_COUNT
+
+
+#endif
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 6e6c3c4aea6..5a11e3cbcae 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -123,6 +123,13 @@ config EDAC_I5000
Support for error detection and correction the Intel
Greekcreek/Blackford chipsets.
+config EDAC_I5100
+ tristate "Intel San Clemente MCH"
+ depends on EDAC_MM_EDAC && X86 && PCI
+ help
+ Support for error detection and correction the Intel
+ San Clemente MCH.
+
config EDAC_MPC85XX
tristate "Freescale MPC85xx"
depends on EDAC_MM_EDAC && FSL_SOC && MPC85xx
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index 83807731d4a..e5e9104b552 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -19,6 +19,7 @@ endif
obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o
obj-$(CONFIG_EDAC_I5000) += i5000_edac.o
+obj-$(CONFIG_EDAC_I5100) += i5100_edac.o
obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o
obj-$(CONFIG_EDAC_E752X) += e752x_edac.o
obj-$(CONFIG_EDAC_I82443BXGX) += i82443bxgx_edac.o
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c
index b54112ffd28..0e024fe2d8c 100644
--- a/drivers/edac/cell_edac.c
+++ b/drivers/edac/cell_edac.c
@@ -33,7 +33,7 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar)
{
struct cell_edac_priv *priv = mci->pvt_info;
struct csrow_info *csrow = &mci->csrows[0];
- unsigned long address, pfn, offset;
+ unsigned long address, pfn, offset, syndrome;
dev_dbg(mci->dev, "ECC CE err on node %d, channel %d, ar = 0x%016lx\n",
priv->node, chan, ar);
@@ -44,10 +44,11 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar)
address = (address << 1) | chan;
pfn = address >> PAGE_SHIFT;
offset = address & ~PAGE_MASK;
+ syndrome = (ar & 0x000000001fe00000ul) >> 21;
/* TODO: Decoding of the error addresss */
edac_mc_handle_ce(mci, csrow->first_page + pfn, offset,
- 0, 0, chan, "");
+ syndrome, 0, chan, "");
}
static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar)
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
index c94a0eb492c..facfdb1fa71 100644
--- a/drivers/edac/e752x_edac.c
+++ b/drivers/edac/e752x_edac.c
@@ -28,6 +28,7 @@
#define E752X_REVISION " Ver: 2.0.2 " __DATE__
#define EDAC_MOD_STR "e752x_edac"
+static int report_non_memory_errors;
static int force_function_unhide;
static int sysbus_parity = -1;
@@ -117,7 +118,7 @@ static struct edac_pci_ctl_info *e752x_pci;
#define E752X_BUF_FERR 0x70 /* Memory buffer first error reg (8b) */
#define E752X_BUF_NERR 0x72 /* Memory buffer next error reg (8b) */
#define E752X_BUF_ERRMASK 0x74 /* Memory buffer error mask reg (8b) */
-#define E752X_BUF_SMICMD 0x7A /* Memory buffer SMI command reg (8b) */
+#define E752X_BUF_SMICMD 0x7A /* Memory buffer SMI cmd reg (8b) */
#define E752X_DRAM_FERR 0x80 /* DRAM first error register (16b) */
#define E752X_DRAM_NERR 0x82 /* DRAM next error register (16b) */
#define E752X_DRAM_ERRMASK 0x84 /* DRAM error mask register (8b) */
@@ -127,7 +128,7 @@ static struct edac_pci_ctl_info *e752x_pci;
/* error address register (32b) */
/*
* 31 Reserved
- * 30:2 CE address (64 byte block 34:6)
+ * 30:2 CE address (64 byte block 34:6
* 1 Reserved
* 0 HiLoCS
*/
@@ -147,11 +148,11 @@ static struct edac_pci_ctl_info *e752x_pci;
* 1 Reserved
* 0 HiLoCS
*/
-#define E752X_DRAM_SCRB_ADD 0xA8 /* DRAM first uncorrectable scrub memory */
+#define E752X_DRAM_SCRB_ADD 0xA8 /* DRAM 1st uncorrectable scrub mem */
/* error address register (32b) */
/*
* 31 Reserved
- * 30:2 CE address (64 byte block 34:6)
+ * 30:2 CE address (64 byte block 34:6
* 1 Reserved
* 0 HiLoCS
*/
@@ -394,9 +395,12 @@ static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error,
struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info;
error_1b = retry_add;
- page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */
- row = pvt->mc_symmetric ? ((page >> 1) & 3) : /* chip select are bits 14 & 13 */
+ page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */
+
+ /* chip select are bits 14 & 13 */
+ row = pvt->mc_symmetric ? ((page >> 1) & 3) :
edac_mc_find_csrow_by_page(mci, page);
+
e752x_mc_printk(mci, KERN_WARNING,
"CE page 0x%lx, row %d : Memory read retry\n",
(long unsigned int)page, row);
@@ -422,12 +426,21 @@ static inline void process_threshold_ce(struct mem_ctl_info *mci, u16 error,
}
static char *global_message[11] = {
- "PCI Express C1", "PCI Express C", "PCI Express B1",
- "PCI Express B", "PCI Express A1", "PCI Express A",
- "DMA Controler", "HUB or NS Interface", "System Bus",
- "DRAM Controler", "Internal Buffer"
+ "PCI Express C1",
+ "PCI Express C",
+ "PCI Express B1",
+ "PCI Express B",
+ "PCI Express A1",
+ "PCI Express A",
+ "DMA Controller",
+ "HUB or NS Interface",
+ "System Bus",
+ "DRAM Controller", /* 9th entry */
+ "Internal Buffer"
};
+#define DRAM_ENTRY 9
+
static char *fatal_message[2] = { "Non-Fatal ", "Fatal " };
static void do_global_error(int fatal, u32 errors)
@@ -435,9 +448,16 @@ static void do_global_error(int fatal, u32 errors)
int i;
for (i = 0; i < 11; i++) {
- if (errors & (1 << i))
- e752x_printk(KERN_WARNING, "%sError %s\n",
- fatal_message[fatal], global_message[i]);
+ if (errors & (1 << i)) {
+ /* If the error is from DRAM Controller OR
+ * we are to report ALL errors, then
+ * report the error
+ */
+ if ((i == DRAM_ENTRY) || report_non_memory_errors)
+ e752x_printk(KERN_WARNING, "%sError %s\n",
+ fatal_message[fatal],
+ global_message[i]);
+ }
}
}
@@ -1021,7 +1041,7 @@ static int e752x_get_devs(struct pci_dev *pdev, int dev_idx,
struct pci_dev *dev;
pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
- pvt->dev_info->err_dev, pvt->bridge_ck);
+ pvt->dev_info->err_dev, pvt->bridge_ck);
if (pvt->bridge_ck == NULL)
pvt->bridge_ck = pci_scan_single_device(pdev->bus,
@@ -1034,8 +1054,9 @@ static int e752x_get_devs(struct pci_dev *pdev, int dev_idx,
return 1;
}
- dev = pci_get_device(PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].ctl_dev,
- NULL);
+ dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ e752x_devs[dev_idx].ctl_dev,
+ NULL);
if (dev == NULL)
goto fail;
@@ -1316,7 +1337,8 @@ MODULE_DESCRIPTION("MC support for Intel e752x/3100 memory controllers");
module_param(force_function_unhide, int, 0444);
MODULE_PARM_DESC(force_function_unhide, "if BIOS sets Dev0:Fun1 up as hidden:"
- " 1=force unhide and hope BIOS doesn't fight driver for Dev0:Fun1 access");
+ " 1=force unhide and hope BIOS doesn't fight driver for "
+ "Dev0:Fun1 access");
module_param(edac_op_state, int, 0444);
MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
@@ -1324,3 +1346,6 @@ MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
module_param(sysbus_parity, int, 0444);
MODULE_PARM_DESC(sysbus_parity, "0=disable system bus parity checking,"
" 1=enable system bus parity checking, default=auto-detect");
+module_param(report_non_memory_errors, int, 0644);
+MODULE_PARM_DESC(report_non_memory_errors, "0=disable non-memory error "
+ "reporting, 1=enable non-memory error reporting");
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 021d1879514..ad218fe4942 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -44,6 +44,25 @@ int edac_mc_get_poll_msec(void)
return edac_mc_poll_msec;
}
+static int edac_set_poll_msec(const char *val, struct kernel_param *kp)
+{
+ long l;
+ int ret;
+
+ if (!val)
+ return -EINVAL;
+
+ ret = strict_strtol(val, 0, &l);
+ if (ret == -EINVAL || ((int)l != l))
+ return -EINVAL;
+ *((int *)kp->arg) = l;
+
+ /* notify edac_mc engine to reset the poll period */
+ edac_mc_reset_delay_period(l);
+
+ return 0;
+}
+
/* Parameter declarations for above */
module_param(edac_mc_panic_on_ue, int, 0644);
MODULE_PARM_DESC(edac_mc_panic_on_ue, "Panic on uncorrected error: 0=off 1=on");
@@ -53,7 +72,8 @@ MODULE_PARM_DESC(edac_mc_log_ue,
module_param(edac_mc_log_ce, int, 0644);
MODULE_PARM_DESC(edac_mc_log_ce,
"Log correctable error to console: 0=off 1=on");
-module_param(edac_mc_poll_msec, int, 0644);
+module_param_call(edac_mc_poll_msec, edac_set_poll_msec, param_get_int,
+ &edac_mc_poll_msec, 0644);
MODULE_PARM_DESC(edac_mc_poll_msec, "Polling period in milliseconds");
/*
@@ -103,16 +123,6 @@ static const char *edac_caps[] = {
-/*
- * /sys/devices/system/edac/mc;
- * data structures and methods
- */
-static ssize_t memctrl_int_show(void *ptr, char *buffer)
-{
- int *value = (int *)ptr;
- return sprintf(buffer, "%u\n", *value);
-}
-
static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count)
{
int *value = (int *)ptr;
@@ -123,23 +133,6 @@ static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count)
return count;
}
-/*
- * mc poll_msec time value
- */
-static ssize_t poll_msec_int_store(void *ptr, const char *buffer, size_t count)
-{
- int *value = (int *)ptr;
-
- if (isdigit(*buffer)) {
- *value = simple_strtoul(buffer, NULL, 0);
-
- /* notify edac_mc engine to reset the poll period */
- edac_mc_reset_delay_period(*value);
- }
-
- return count;
-}
-
/* EDAC sysfs CSROW data structures and methods
*/
@@ -185,7 +178,11 @@ static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data,
static ssize_t channel_dimm_label_show(struct csrow_info *csrow,
char *data, int channel)
{
- return snprintf(data, EDAC_MC_LABEL_LEN, "%s",
+ /* if field has not been initialized, there is nothing to send */
+ if (!csrow->channels[channel].label[0])
+ return 0;
+
+ return snprintf(data, EDAC_MC_LABEL_LEN, "%s\n",
csrow->channels[channel].label);
}
@@ -649,98 +646,10 @@ static struct kobj_type ktype_mci = {
.default_attrs = (struct attribute **)mci_attr,
};
-/* show/store, tables, etc for the MC kset */
-
-
-struct memctrl_dev_attribute {
- struct attribute attr;
- void *value;
- ssize_t(*show) (void *, char *);
- ssize_t(*store) (void *, const char *, size_t);
-};
-
-/* Set of show/store abstract level functions for memory control object */
-static ssize_t memctrl_dev_show(struct kobject *kobj,
- struct attribute *attr, char *buffer)
-{
- struct memctrl_dev_attribute *memctrl_dev;
- memctrl_dev = (struct memctrl_dev_attribute *)attr;
-
- if (memctrl_dev->show)
- return memctrl_dev->show(memctrl_dev->value, buffer);
-
- return -EIO;
-}
-
-static ssize_t memctrl_dev_store(struct kobject *kobj, struct attribute *attr,
- const char *buffer, size_t count)
-{
- struct memctrl_dev_attribute *memctrl_dev;
- memctrl_dev = (struct memctrl_dev_attribute *)attr;
-
- if (memctrl_dev->store)
- return memctrl_dev->store(memctrl_dev->value, buffer, count);
-
- return -EIO;
-}
-
-static struct sysfs_ops memctrlfs_ops = {
- .show = memctrl_dev_show,
- .store = memctrl_dev_store
-};
-
-#define MEMCTRL_ATTR(_name, _mode, _show, _store) \
-static struct memctrl_dev_attribute attr_##_name = { \
- .attr = {.name = __stringify(_name), .mode = _mode }, \
- .value = &_name, \
- .show = _show, \
- .store = _store, \
-};
-
-#define MEMCTRL_STRING_ATTR(_name, _data, _mode, _show, _store) \
-static struct memctrl_dev_attribute attr_##_name = { \
- .attr = {.name = __stringify(_name), .mode = _mode }, \
- .value = _data, \
- .show = _show, \
- .store = _store, \
-};
-
-/* csrow<id> control files */
-MEMCTRL_ATTR(edac_mc_panic_on_ue,
- S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store);
-
-MEMCTRL_ATTR(edac_mc_log_ue,
- S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store);
-
-MEMCTRL_ATTR(edac_mc_log_ce,
- S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store);
-
-MEMCTRL_ATTR(edac_mc_poll_msec,
- S_IRUGO | S_IWUSR, memctrl_int_show, poll_msec_int_store);
-
-/* Base Attributes of the memory ECC object */
-static struct memctrl_dev_attribute *memctrl_attr[] = {
- &attr_edac_mc_panic_on_ue,
- &attr_edac_mc_log_ue,
- &attr_edac_mc_log_ce,
- &attr_edac_mc_poll_msec,
- NULL,
-};
-
-
-/* the ktype for the mc_kset internal kobj */
-static struct kobj_type ktype_mc_set_attribs = {
- .sysfs_ops = &memctrlfs_ops,
- .default_attrs = (struct attribute **)memctrl_attr,
-};
-
/* EDAC memory controller sysfs kset:
* /sys/devices/system/edac/mc
*/
-static struct kset mc_kset = {
- .kobj = {.ktype = &ktype_mc_set_attribs },
-};
-
+static struct kset *mc_kset;
/*
* edac_mc_register_sysfs_main_kobj
@@ -771,7 +680,7 @@ int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci)
}
/* this instance become part of the mc_kset */
- kobj_mci->kset = &mc_kset;
+ kobj_mci->kset = mc_kset;
/* register the mc<id> kobject to the mc_kset */
err = kobject_init_and_add(kobj_mci, &ktype_mci, NULL,
@@ -1001,12 +910,9 @@ int edac_sysfs_setup_mc_kset(void)
}
/* Init the MC's kobject */
- kobject_set_name(&mc_kset.kobj, "mc");
- mc_kset.kobj.parent = &edac_class->kset.kobj;
-
- /* register the mc_kset */
- err = kset_register(&mc_kset);
- if (err) {
+ mc_kset = kset_create_and_add("mc", NULL, &edac_class->kset.kobj);
+ if (!mc_kset) {
+ err = -ENOMEM;
debugf1("%s() Failed to register '.../edac/mc'\n", __func__);
goto fail_out;
}
@@ -1028,6 +934,6 @@ fail_out:
*/
void edac_sysfs_teardown_mc_kset(void)
{
- kset_unregister(&mc_kset);
+ kset_unregister(mc_kset);
}
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
index 2c1fa1bb6df..5c153dccc95 100644
--- a/drivers/edac/edac_pci_sysfs.c
+++ b/drivers/edac/edac_pci_sysfs.c
@@ -28,7 +28,7 @@ static int edac_pci_poll_msec = 1000; /* one second workq period */
static atomic_t pci_parity_count = ATOMIC_INIT(0);
static atomic_t pci_nonparity_count = ATOMIC_INIT(0);
-static struct kobject edac_pci_top_main_kobj;
+static struct kobject *edac_pci_top_main_kobj;
static atomic_t edac_pci_sysfs_refcount = ATOMIC_INIT(0);
/* getter functions for the data variables */
@@ -83,7 +83,7 @@ static void edac_pci_instance_release(struct kobject *kobj)
pci = to_instance(kobj);
/* decrement reference count on top main kobj */
- kobject_put(&edac_pci_top_main_kobj);
+ kobject_put(edac_pci_top_main_kobj);
kfree(pci); /* Free the control struct */
}
@@ -166,7 +166,7 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
* track the number of PCI instances we have, and thus nest
* properly on keeping the module loaded
*/
- main_kobj = kobject_get(&edac_pci_top_main_kobj);
+ main_kobj = kobject_get(edac_pci_top_main_kobj);
if (!main_kobj) {
err = -ENODEV;
goto error_out;
@@ -174,11 +174,11 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
/* And now register this new kobject under the main kobj */
err = kobject_init_and_add(&pci->kobj, &ktype_pci_instance,
- &edac_pci_top_main_kobj, "pci%d", idx);
+ edac_pci_top_main_kobj, "pci%d", idx);
if (err != 0) {
debugf2("%s() failed to register instance pci%d\n",
__func__, idx);
- kobject_put(&edac_pci_top_main_kobj);
+ kobject_put(edac_pci_top_main_kobj);
goto error_out;
}
@@ -316,9 +316,10 @@ static struct edac_pci_dev_attribute *edac_pci_attr[] = {
*/
static void edac_pci_release_main_kobj(struct kobject *kobj)
{
-
debugf0("%s() here to module_put(THIS_MODULE)\n", __func__);
+ kfree(kobj);
+
/* last reference to top EDAC PCI kobject has been removed,
* NOW release our ref count on the core module
*/
@@ -369,8 +370,16 @@ static int edac_pci_main_kobj_setup(void)
goto decrement_count_fail;
}
+ edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);
+ if (!edac_pci_top_main_kobj) {
+ debugf1("Failed to allocate\n");
+ err = -ENOMEM;
+ goto kzalloc_fail;
+ }
+
/* Instanstiate the pci object */
- err = kobject_init_and_add(&edac_pci_top_main_kobj, &ktype_edac_pci_main_kobj,
+ err = kobject_init_and_add(edac_pci_top_main_kobj,
+ &ktype_edac_pci_main_kobj,
&edac_class->kset.kobj, "pci");
if (err) {
debugf1("Failed to register '.../edac/pci'\n");
@@ -381,13 +390,16 @@ static int edac_pci_main_kobj_setup(void)
* for EDAC PCI, then edac_pci_main_kobj_teardown()
* must be used, for resources to be cleaned up properly
*/
- kobject_uevent(&edac_pci_top_main_kobj, KOBJ_ADD);
+ kobject_uevent(edac_pci_top_main_kobj, KOBJ_ADD);
debugf1("Registered '.../edac/pci' kobject\n");
return 0;
/* Error unwind statck */
kobject_init_and_add_fail:
+ kfree(edac_pci_top_main_kobj);
+
+kzalloc_fail:
module_put(THIS_MODULE);
decrement_count_fail:
@@ -414,7 +426,7 @@ static void edac_pci_main_kobj_teardown(void)
if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) {
debugf0("%s() called kobject_put on main kobj\n",
__func__);
- kobject_put(&edac_pci_top_main_kobj);
+ kobject_put(edac_pci_top_main_kobj);
}
}
diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c
new file mode 100644
index 00000000000..22db05a67bf
--- /dev/null
+++ b/drivers/edac/i5100_edac.c
@@ -0,0 +1,981 @@
+/*
+ * Intel 5100 Memory Controllers kernel module
+ *
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * This module is based on the following document:
+ *
+ * Intel 5100X Chipset Memory Controller Hub (MCH) - Datasheet
+ * http://download.intel.com/design/chipsets/datashts/318378.pdf
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include <linux/edac.h>
+#include <linux/delay.h>
+#include <linux/mmzone.h>
+
+#include "edac_core.h"
+
+/* register addresses */
+
+/* device 16, func 1 */
+#define I5100_MC 0x40 /* Memory Control Register */
+#define I5100_MS 0x44 /* Memory Status Register */
+#define I5100_SPDDATA 0x48 /* Serial Presence Detect Status Reg */
+#define I5100_SPDCMD 0x4c /* Serial Presence Detect Command Reg */
+#define I5100_TOLM 0x6c /* Top of Low Memory */
+#define I5100_MIR0 0x80 /* Memory Interleave Range 0 */
+#define I5100_MIR1 0x84 /* Memory Interleave Range 1 */
+#define I5100_AMIR_0 0x8c /* Adjusted Memory Interleave Range 0 */
+#define I5100_AMIR_1 0x90 /* Adjusted Memory Interleave Range 1 */
+#define I5100_FERR_NF_MEM 0xa0 /* MC First Non Fatal Errors */
+#define I5100_FERR_NF_MEM_M16ERR_MASK (1 << 16)
+#define I5100_FERR_NF_MEM_M15ERR_MASK (1 << 15)
+#define I5100_FERR_NF_MEM_M14ERR_MASK (1 << 14)
+#define I5100_FERR_NF_MEM_M12ERR_MASK (1 << 12)
+#define I5100_FERR_NF_MEM_M11ERR_MASK (1 << 11)
+#define I5100_FERR_NF_MEM_M10ERR_MASK (1 << 10)
+#define I5100_FERR_NF_MEM_M6ERR_MASK (1 << 6)
+#define I5100_FERR_NF_MEM_M5ERR_MASK (1 << 5)
+#define I5100_FERR_NF_MEM_M4ERR_MASK (1 << 4)
+#define I5100_FERR_NF_MEM_M1ERR_MASK 1
+#define I5100_FERR_NF_MEM_ANY_MASK \
+ (I5100_FERR_NF_MEM_M16ERR_MASK | \
+ I5100_FERR_NF_MEM_M15ERR_MASK | \
+ I5100_FERR_NF_MEM_M14ERR_MASK | \
+ I5100_FERR_NF_MEM_M12ERR_MASK | \
+ I5100_FERR_NF_MEM_M11ERR_MASK | \
+ I5100_FERR_NF_MEM_M10ERR_MASK | \
+ I5100_FERR_NF_MEM_M6ERR_MASK | \
+ I5100_FERR_NF_MEM_M5ERR_MASK | \
+ I5100_FERR_NF_MEM_M4ERR_MASK | \
+ I5100_FERR_NF_MEM_M1ERR_MASK)
+#define I5100_NERR_NF_MEM 0xa4 /* MC Next Non-Fatal Errors */
+#define I5100_EMASK_MEM 0xa8 /* MC Error Mask Register */
+
+/* device 21 and 22, func 0 */
+#define I5100_MTR_0 0x154 /* Memory Technology Registers 0-3 */
+#define I5100_DMIR 0x15c /* DIMM Interleave Range */
+#define I5100_VALIDLOG 0x18c /* Valid Log Markers */
+#define I5100_NRECMEMA 0x190 /* Non-Recoverable Memory Error Log Reg A */
+#define I5100_NRECMEMB 0x194 /* Non-Recoverable Memory Error Log Reg B */
+#define I5100_REDMEMA 0x198 /* Recoverable Memory Data Error Log Reg A */
+#define I5100_REDMEMB 0x19c /* Recoverable Memory Data Error Log Reg B */
+#define I5100_RECMEMA 0x1a0 /* Recoverable Memory Error Log Reg A */
+#define I5100_RECMEMB 0x1a4 /* Recoverable Memory Error Log Reg B */
+#define I5100_MTR_4 0x1b0 /* Memory Technology Registers 4,5 */
+
+/* bit field accessors */
+
+static inline u32 i5100_mc_errdeten(u32 mc)
+{
+ return mc >> 5 & 1;
+}
+
+static inline u16 i5100_spddata_rdo(u16 a)
+{
+ return a >> 15 & 1;
+}
+
+static inline u16 i5100_spddata_sbe(u16 a)
+{
+ return a >> 13 & 1;
+}
+
+static inline u16 i5100_spddata_busy(u16 a)
+{
+ return a >> 12 & 1;
+}
+
+static inline u16 i5100_spddata_data(u16 a)
+{
+ return a & ((1 << 8) - 1);
+}
+
+static inline u32 i5100_spdcmd_create(u32 dti, u32 ckovrd, u32 sa, u32 ba,
+ u32 data, u32 cmd)
+{
+ return ((dti & ((1 << 4) - 1)) << 28) |
+ ((ckovrd & 1) << 27) |
+ ((sa & ((1 << 3) - 1)) << 24) |
+ ((ba & ((1 << 8) - 1)) << 16) |
+ ((data & ((1 << 8) - 1)) << 8) |
+ (cmd & 1);
+}
+
+static inline u16 i5100_tolm_tolm(u16 a)
+{
+ return a >> 12 & ((1 << 4) - 1);
+}
+
+static inline u16 i5100_mir_limit(u16 a)
+{
+ return a >> 4 & ((1 << 12) - 1);
+}
+
+static inline u16 i5100_mir_way1(u16 a)
+{
+ return a >> 1 & 1;
+}
+
+static inline u16 i5100_mir_way0(u16 a)
+{
+ return a & 1;
+}
+
+static inline u32 i5100_ferr_nf_mem_chan_indx(u32 a)
+{
+ return a >> 28 & 1;
+}
+
+static inline u32 i5100_ferr_nf_mem_any(u32 a)
+{
+ return a & I5100_FERR_NF_MEM_ANY_MASK;
+}
+
+static inline u32 i5100_nerr_nf_mem_any(u32 a)
+{
+ return i5100_ferr_nf_mem_any(a);
+}
+
+static inline u32 i5100_dmir_limit(u32 a)
+{
+ return a >> 16 & ((1 << 11) - 1);
+}
+
+static inline u32 i5100_dmir_rank(u32 a, u32 i)
+{
+ return a >> (4 * i) & ((1 << 2) - 1);
+}
+
+static inline u16 i5100_mtr_present(u16 a)
+{
+ return a >> 10 & 1;
+}
+
+static inline u16 i5100_mtr_ethrottle(u16 a)
+{
+ return a >> 9 & 1;
+}
+
+static inline u16 i5100_mtr_width(u16 a)
+{
+ return a >> 8 & 1;
+}
+
+static inline u16 i5100_mtr_numbank(u16 a)
+{
+ return a >> 6 & 1;
+}
+
+static inline u16 i5100_mtr_numrow(u16 a)
+{
+ return a >> 2 & ((1 << 2) - 1);
+}
+
+static inline u16 i5100_mtr_numcol(u16 a)
+{
+ return a & ((1 << 2) - 1);
+}
+
+
+static inline u32 i5100_validlog_redmemvalid(u32 a)
+{
+ return a >> 2 & 1;
+}
+
+static inline u32 i5100_validlog_recmemvalid(u32 a)
+{
+ return a >> 1 & 1;
+}
+
+static inline u32 i5100_validlog_nrecmemvalid(u32 a)
+{
+ return a & 1;
+}
+
+static inline u32 i5100_nrecmema_merr(u32 a)
+{
+ return a >> 15 & ((1 << 5) - 1);
+}
+
+static inline u32 i5100_nrecmema_bank(u32 a)
+{
+ return a >> 12 & ((1 << 3) - 1);
+}
+
+static inline u32 i5100_nrecmema_rank(u32 a)
+{
+ return a >> 8 & ((1 << 3) - 1);
+}
+
+static inline u32 i5100_nrecmema_dm_buf_id(u32 a)
+{
+ return a & ((1 << 8) - 1);
+}
+
+static inline u32 i5100_nrecmemb_cas(u32 a)
+{
+ return a >> 16 & ((1 << 13) - 1);
+}
+
+static inline u32 i5100_nrecmemb_ras(u32 a)
+{
+ return a & ((1 << 16) - 1);
+}
+
+static inline u32 i5100_redmemb_ecc_locator(u32 a)
+{
+ return a & ((1 << 18) - 1);
+}
+
+static inline u32 i5100_recmema_merr(u32 a)
+{
+ return i5100_nrecmema_merr(a);
+}
+
+static inline u32 i5100_recmema_bank(u32 a)
+{
+ return i5100_nrecmema_bank(a);
+}
+
+static inline u32 i5100_recmema_rank(u32 a)
+{
+ return i5100_nrecmema_rank(a);
+}
+
+static inline u32 i5100_recmema_dm_buf_id(u32 a)
+{
+ return i5100_nrecmema_dm_buf_id(a);
+}
+
+static inline u32 i5100_recmemb_cas(u32 a)
+{
+ return i5100_nrecmemb_cas(a);
+}
+
+static inline u32 i5100_recmemb_ras(u32 a)
+{
+ return i5100_nrecmemb_ras(a);
+}
+
+/* some generic limits */
+#define I5100_MAX_RANKS_PER_CTLR 6
+#define I5100_MAX_CTLRS 2
+#define I5100_MAX_RANKS_PER_DIMM 4
+#define I5100_DIMM_ADDR_LINES (6 - 3) /* 64 bits / 8 bits per byte */
+#define I5100_MAX_DIMM_SLOTS_PER_CTLR 4
+#define I5100_MAX_RANK_INTERLEAVE 4
+#define I5100_MAX_DMIRS 5
+
+struct i5100_priv {
+ /* ranks on each dimm -- 0 maps to not present -- obtained via SPD */
+ int dimm_numrank[I5100_MAX_CTLRS][I5100_MAX_DIMM_SLOTS_PER_CTLR];
+
+ /*
+ * mainboard chip select map -- maps i5100 chip selects to
+ * DIMM slot chip selects. In the case of only 4 ranks per
+ * controller, the mapping is fairly obvious but not unique.
+ * we map -1 -> NC and assume both controllers use the same
+ * map...
+ *
+ */
+ int dimm_csmap[I5100_MAX_DIMM_SLOTS_PER_CTLR][I5100_MAX_RANKS_PER_DIMM];
+
+ /* memory interleave range */
+ struct {
+ u64 limit;
+ unsigned way[2];
+ } mir[I5100_MAX_CTLRS];
+
+ /* adjusted memory interleave range register */
+ unsigned amir[I5100_MAX_CTLRS];
+
+ /* dimm interleave range */
+ struct {
+ unsigned rank[I5100_MAX_RANK_INTERLEAVE];
+ u64 limit;
+ } dmir[I5100_MAX_CTLRS][I5100_MAX_DMIRS];
+
+ /* memory technology registers... */
+ struct {
+ unsigned present; /* 0 or 1 */
+ unsigned ethrottle; /* 0 or 1 */
+ unsigned width; /* 4 or 8 bits */
+ unsigned numbank; /* 2 or 3 lines */
+ unsigned numrow; /* 13 .. 16 lines */
+ unsigned numcol; /* 11 .. 12 lines */
+ } mtr[I5100_MAX_CTLRS][I5100_MAX_RANKS_PER_CTLR];
+
+ u64 tolm; /* top of low memory in bytes */
+ unsigned ranksperctlr; /* number of ranks per controller */
+
+ struct pci_dev *mc; /* device 16 func 1 */
+ struct pci_dev *ch0mm; /* device 21 func 0 */
+ struct pci_dev *ch1mm; /* device 22 func 0 */
+};
+
+/* map a rank/ctlr to a slot number on the mainboard */
+static int i5100_rank_to_slot(const struct mem_ctl_info *mci,
+ int ctlr, int rank)
+{
+ const struct i5100_priv *priv = mci->pvt_info;
+ int i;
+
+ for (i = 0; i < I5100_MAX_DIMM_SLOTS_PER_CTLR; i++) {
+ int j;
+ const int numrank = priv->dimm_numrank[ctlr][i];
+
+ for (j = 0; j < numrank; j++)
+ if (priv->dimm_csmap[i][j] == rank)
+ return i * 2 + ctlr;
+ }
+
+ return -1;
+}
+
+static const char *i5100_err_msg(unsigned err)
+{
+ static const char *merrs[] = {
+ "unknown", /* 0 */
+ "uncorrectable data ECC on replay", /* 1 */
+ "unknown", /* 2 */
+ "unknown", /* 3 */
+ "aliased uncorrectable demand data ECC", /* 4 */
+ "aliased uncorrectable spare-copy data ECC", /* 5 */
+ "aliased uncorrectable patrol data ECC", /* 6 */
+ "unknown", /* 7 */
+ "unknown", /* 8 */
+ "unknown", /* 9 */
+ "non-aliased uncorrectable demand data ECC", /* 10 */
+ "non-aliased uncorrectable spare-copy data ECC", /* 11 */
+ "non-aliased uncorrectable patrol data ECC", /* 12 */
+ "unknown", /* 13 */
+ "correctable demand data ECC", /* 14 */
+ "correctable spare-copy data ECC", /* 15 */
+ "correctable patrol data ECC", /* 16 */
+ "unknown", /* 17 */
+ "SPD protocol error", /* 18 */
+ "unknown", /* 19 */
+ "spare copy initiated", /* 20 */
+ "spare copy completed", /* 21 */
+ };
+ unsigned i;
+
+ for (i = 0; i < ARRAY_SIZE(merrs); i++)
+ if (1 << i & err)
+ return merrs[i];
+
+ return "none";
+}
+
+/* convert csrow index into a rank (per controller -- 0..5) */
+static int i5100_csrow_to_rank(const struct mem_ctl_info *mci, int csrow)
+{
+ const struct i5100_priv *priv = mci->pvt_info;
+
+ return csrow % priv->ranksperctlr;
+}
+
+/* convert csrow index into a controller (0..1) */
+static int i5100_csrow_to_cntlr(const struct mem_ctl_info *mci, int csrow)
+{
+ const struct i5100_priv *priv = mci->pvt_info;
+
+ return csrow / priv->ranksperctlr;
+}
+
+static unsigned i5100_rank_to_csrow(const struct mem_ctl_info *mci,
+ int ctlr, int rank)
+{
+ const struct i5100_priv *priv = mci->pvt_info;
+
+ return ctlr * priv->ranksperctlr + rank;
+}
+
+static void i5100_handle_ce(struct mem_ctl_info *mci,
+ int ctlr,
+ unsigned bank,
+ unsigned rank,
+ unsigned long syndrome,
+ unsigned cas,
+ unsigned ras,
+ const char *msg)
+{
+ const int csrow = i5100_rank_to_csrow(mci, ctlr, rank);
+
+ printk(KERN_ERR
+ "CE ctlr %d, bank %u, rank %u, syndrome 0x%lx, "
+ "cas %u, ras %u, csrow %u, label \"%s\": %s\n",
+ ctlr, bank, rank, syndrome, cas, ras,
+ csrow, mci->csrows[csrow].channels[0].label, msg);
+
+ mci->ce_count++;
+ mci->csrows[csrow].ce_count++;
+ mci->csrows[csrow].channels[0].ce_count++;
+}
+
+static void i5100_handle_ue(struct mem_ctl_info *mci,
+ int ctlr,
+ unsigned bank,
+ unsigned rank,
+ unsigned long syndrome,
+ unsigned cas,
+ unsigned ras,
+ const char *msg)
+{
+ const int csrow = i5100_rank_to_csrow(mci, ctlr, rank);
+
+ printk(KERN_ERR
+ "UE ctlr %d, bank %u, rank %u, syndrome 0x%lx, "
+ "cas %u, ras %u, csrow %u, label \"%s\": %s\n",
+ ctlr, bank, rank, syndrome, cas, ras,
+ csrow, mci->csrows[csrow].channels[0].label, msg);
+
+ mci->ue_count++;
+ mci->csrows[csrow].ue_count++;
+}
+
+static void i5100_read_log(struct mem_ctl_info *mci, int ctlr,
+ u32 ferr, u32 nerr)
+{
+ struct i5100_priv *priv = mci->pvt_info;
+ struct pci_dev *pdev = (ctlr) ? priv->ch1mm : priv->ch0mm;
+ u32 dw;
+ u32 dw2;
+ unsigned syndrome = 0;
+ unsigned ecc_loc = 0;
+ unsigned merr;
+ unsigned bank;
+ unsigned rank;
+ unsigned cas;
+ unsigned ras;
+
+ pci_read_config_dword(pdev, I5100_VALIDLOG, &dw);
+
+ if (i5100_validlog_redmemvalid(dw)) {
+ pci_read_config_dword(pdev, I5100_REDMEMA, &dw2);
+ syndrome = dw2;
+ pci_read_config_dword(pdev, I5100_REDMEMB, &dw2);
+ ecc_loc = i5100_redmemb_ecc_locator(dw2);
+ }
+
+ if (i5100_validlog_recmemvalid(dw)) {
+ const char *msg;
+
+ pci_read_config_dword(pdev, I5100_RECMEMA, &dw2);
+ merr = i5100_recmema_merr(dw2);
+ bank = i5100_recmema_bank(dw2);
+ rank = i5100_recmema_rank(dw2);
+
+ pci_read_config_dword(pdev, I5100_RECMEMB, &dw2);
+ cas = i5100_recmemb_cas(dw2);
+ ras = i5100_recmemb_ras(dw2);
+
+ /* FIXME: not really sure if this is what merr is...
+ */
+ if (!merr)
+ msg = i5100_err_msg(ferr);
+ else
+ msg = i5100_err_msg(nerr);
+
+ i5100_handle_ce(mci, ctlr, bank, rank, syndrome, cas, ras, msg);
+ }
+
+ if (i5100_validlog_nrecmemvalid(dw)) {
+ const char *msg;
+
+ pci_read_config_dword(pdev, I5100_NRECMEMA, &dw2);
+ merr = i5100_nrecmema_merr(dw2);
+ bank = i5100_nrecmema_bank(dw2);
+ rank = i5100_nrecmema_rank(dw2);
+
+ pci_read_config_dword(pdev, I5100_NRECMEMB, &dw2);
+ cas = i5100_nrecmemb_cas(dw2);
+ ras = i5100_nrecmemb_ras(dw2);
+
+ /* FIXME: not really sure if this is what merr is...
+ */
+ if (!merr)
+ msg = i5100_err_msg(ferr);
+ else
+ msg = i5100_err_msg(nerr);
+
+ i5100_handle_ue(mci, ctlr, bank, rank, syndrome, cas, ras, msg);
+ }
+
+ pci_write_config_dword(pdev, I5100_VALIDLOG, dw);
+}
+
+static void i5100_check_error(struct mem_ctl_info *mci)
+{
+ struct i5100_priv *priv = mci->pvt_info;
+ u32 dw;
+
+
+ pci_read_config_dword(priv->mc, I5100_FERR_NF_MEM, &dw);
+ if (i5100_ferr_nf_mem_any(dw)) {
+ u32 dw2;
+
+ pci_read_config_dword(priv->mc, I5100_NERR_NF_MEM, &dw2);
+ if (dw2)
+ pci_write_config_dword(priv->mc, I5100_NERR_NF_MEM,
+ dw2);
+ pci_write_config_dword(priv->mc, I5100_FERR_NF_MEM, dw);
+
+ i5100_read_log(mci, i5100_ferr_nf_mem_chan_indx(dw),
+ i5100_ferr_nf_mem_any(dw),
+ i5100_nerr_nf_mem_any(dw2));
+ }
+}
+
+static struct pci_dev *pci_get_device_func(unsigned vendor,
+ unsigned device,
+ unsigned func)
+{
+ struct pci_dev *ret = NULL;
+
+ while (1) {
+ ret = pci_get_device(vendor, device, ret);
+
+ if (!ret)
+ break;
+
+ if (PCI_FUNC(ret->devfn) == func)
+ break;
+ }
+
+ return ret;
+}
+
+static unsigned long __devinit i5100_npages(struct mem_ctl_info *mci,
+ int csrow)
+{
+ struct i5100_priv *priv = mci->pvt_info;
+ const unsigned ctlr_rank = i5100_csrow_to_rank(mci, csrow);
+ const unsigned ctlr = i5100_csrow_to_cntlr(mci, csrow);
+ unsigned addr_lines;
+
+ /* dimm present? */
+ if (!priv->mtr[ctlr][ctlr_rank].present)
+ return 0ULL;
+
+ addr_lines =
+ I5100_DIMM_ADDR_LINES +
+ priv->mtr[ctlr][ctlr_rank].numcol +
+ priv->mtr[ctlr][ctlr_rank].numrow +
+ priv->mtr[ctlr][ctlr_rank].numbank;
+
+ return (unsigned long)
+ ((unsigned long long) (1ULL << addr_lines) / PAGE_SIZE);
+}
+
+static void __devinit i5100_init_mtr(struct mem_ctl_info *mci)
+{
+ struct i5100_priv *priv = mci->pvt_info;
+ struct pci_dev *mms[2] = { priv->ch0mm, priv->ch1mm };
+ int i;
+
+ for (i = 0; i < I5100_MAX_CTLRS; i++) {
+ int j;
+ struct pci_dev *pdev = mms[i];
+
+ for (j = 0; j < I5100_MAX_RANKS_PER_CTLR; j++) {
+ const unsigned addr =
+ (j < 4) ? I5100_MTR_0 + j * 2 :
+ I5100_MTR_4 + (j - 4) * 2;
+ u16 w;
+
+ pci_read_config_word(pdev, addr, &w);
+
+ priv->mtr[i][j].present = i5100_mtr_present(w);
+ priv->mtr[i][j].ethrottle = i5100_mtr_ethrottle(w);
+ priv->mtr[i][j].width = 4 + 4 * i5100_mtr_width(w);
+ priv->mtr[i][j].numbank = 2 + i5100_mtr_numbank(w);
+ priv->mtr[i][j].numrow = 13 + i5100_mtr_numrow(w);
+ priv->mtr[i][j].numcol = 10 + i5100_mtr_numcol(w);
+ }
+ }
+}
+
+/*
+ * FIXME: make this into a real i2c adapter (so that dimm-decode
+ * will work)?
+ */
+static int i5100_read_spd_byte(const struct mem_ctl_info *mci,
+ u8 ch, u8 slot, u8 addr, u8 *byte)
+{
+ struct i5100_priv *priv = mci->pvt_info;
+ u16 w;
+ unsigned long et;
+
+ pci_read_config_word(priv->mc, I5100_SPDDATA, &w);
+ if (i5100_spddata_busy(w))
+ return -1;
+
+ pci_write_config_dword(priv->mc, I5100_SPDCMD,
+ i5100_spdcmd_create(0xa, 1, ch * 4 + slot, addr,
+ 0, 0));
+
+ /* wait up to 100ms */
+ et = jiffies + HZ / 10;
+ udelay(100);
+ while (1) {
+ pci_read_config_word(priv->mc, I5100_SPDDATA, &w);
+ if (!i5100_spddata_busy(w))
+ break;
+ udelay(100);
+ }
+
+ if (!i5100_spddata_rdo(w) || i5100_spddata_sbe(w))
+ return -1;
+
+ *byte = i5100_spddata_data(w);
+
+ return 0;
+}
+
+/*
+ * fill dimm chip select map
+ *
+ * FIXME:
+ * o only valid for 4 ranks per controller
+ * o not the only way to may chip selects to dimm slots
+ * o investigate if there is some way to obtain this map from the bios
+ */
+static void __devinit i5100_init_dimm_csmap(struct mem_ctl_info *mci)
+{
+ struct i5100_priv *priv = mci->pvt_info;
+ int i;
+
+ WARN_ON(priv->ranksperctlr != 4);
+
+ for (i = 0; i < I5100_MAX_DIMM_SLOTS_PER_CTLR; i++) {
+ int j;
+
+ for (j = 0; j < I5100_MAX_RANKS_PER_DIMM; j++)
+ priv->dimm_csmap[i][j] = -1; /* default NC */
+ }
+
+ /* only 2 chip selects per slot... */
+ priv->dimm_csmap[0][0] = 0;
+ priv->dimm_csmap[0][1] = 3;
+ priv->dimm_csmap[1][0] = 1;
+ priv->dimm_csmap[1][1] = 2;
+ priv->dimm_csmap[2][0] = 2;
+ priv->dimm_csmap[3][0] = 3;
+}
+
+static void __devinit i5100_init_dimm_layout(struct pci_dev *pdev,
+ struct mem_ctl_info *mci)
+{
+ struct i5100_priv *priv = mci->pvt_info;
+ int i;
+
+ for (i = 0; i < I5100_MAX_CTLRS; i++) {
+ int j;
+
+ for (j = 0; j < I5100_MAX_DIMM_SLOTS_PER_CTLR; j++) {
+ u8 rank;
+
+ if (i5100_read_spd_byte(mci, i, j, 5, &rank) < 0)
+ priv->dimm_numrank[i][j] = 0;
+ else
+ priv->dimm_numrank[i][j] = (rank & 3) + 1;
+ }
+ }
+
+ i5100_init_dimm_csmap(mci);
+}
+
+static void __devinit i5100_init_interleaving(struct pci_dev *pdev,
+ struct mem_ctl_info *mci)
+{
+ u16 w;
+ u32 dw;
+ struct i5100_priv *priv = mci->pvt_info;
+ struct pci_dev *mms[2] = { priv->ch0mm, priv->ch1mm };
+ int i;
+
+ pci_read_config_word(pdev, I5100_TOLM, &w);
+ priv->tolm = (u64) i5100_tolm_tolm(w) * 256 * 1024 * 1024;
+
+ pci_read_config_word(pdev, I5100_MIR0, &w);
+ priv->mir[0].limit = (u64) i5100_mir_limit(w) << 28;
+ priv->mir[0].way[1] = i5100_mir_way1(w);
+ priv->mir[0].way[0] = i5100_mir_way0(w);
+
+ pci_read_config_word(pdev, I5100_MIR1, &w);
+ priv->mir[1].limit = (u64) i5100_mir_limit(w) << 28;
+ priv->mir[1].way[1] = i5100_mir_way1(w);
+ priv->mir[1].way[0] = i5100_mir_way0(w);
+
+ pci_read_config_word(pdev, I5100_AMIR_0, &w);
+ priv->amir[0] = w;
+ pci_read_config_word(pdev, I5100_AMIR_1, &w);
+ priv->amir[1] = w;
+
+ for (i = 0; i < I5100_MAX_CTLRS; i++) {
+ int j;
+
+ for (j = 0; j < 5; j++) {
+ int k;
+
+ pci_read_config_dword(mms[i], I5100_DMIR + j * 4, &dw);
+
+ priv->dmir[i][j].limit =
+ (u64) i5100_dmir_limit(dw) << 28;
+ for (k = 0; k < I5100_MAX_RANKS_PER_DIMM; k++)
+ priv->dmir[i][j].rank[k] =
+ i5100_dmir_rank(dw, k);
+ }
+ }
+
+ i5100_init_mtr(mci);
+}
+
+static void __devinit i5100_init_csrows(struct mem_ctl_info *mci)
+{
+ int i;
+ unsigned long total_pages = 0UL;
+ struct i5100_priv *priv = mci->pvt_info;
+
+ for (i = 0; i < mci->nr_csrows; i++) {
+ const unsigned long npages = i5100_npages(mci, i);
+ const unsigned cntlr = i5100_csrow_to_cntlr(mci, i);
+ const unsigned rank = i5100_csrow_to_rank(mci, i);
+
+ if (!npages)
+ continue;
+
+ /*
+ * FIXME: these two are totally bogus -- I don't see how to
+ * map them correctly to this structure...
+ */
+ mci->csrows[i].first_page = total_pages;
+ mci->csrows[i].last_page = total_pages + npages - 1;
+ mci->csrows[i].page_mask = 0UL;
+
+ mci->csrows[i].nr_pages = npages;
+ mci->csrows[i].grain = 32;
+ mci->csrows[i].csrow_idx = i;
+ mci->csrows[i].dtype =
+ (priv->mtr[cntlr][rank].width == 4) ? DEV_X4 : DEV_X8;
+ mci->csrows[i].ue_count = 0;
+ mci->csrows[i].ce_count = 0;
+ mci->csrows[i].mtype = MEM_RDDR2;
+ mci->csrows[i].edac_mode = EDAC_SECDED;
+ mci->csrows[i].mci = mci;
+ mci->csrows[i].nr_channels = 1;
+ mci->csrows[i].channels[0].chan_idx = 0;
+ mci->csrows[i].channels[0].ce_count = 0;
+ mci->csrows[i].channels[0].csrow = mci->csrows + i;
+ snprintf(mci->csrows[i].channels[0].label,
+ sizeof(mci->csrows[i].channels[0].label),
+ "DIMM%u", i5100_rank_to_slot(mci, cntlr, rank));
+
+ total_pages += npages;
+ }
+}
+
+static int __devinit i5100_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int rc;
+ struct mem_ctl_info *mci;
+ struct i5100_priv *priv;
+ struct pci_dev *ch0mm, *ch1mm;
+ int ret = 0;
+ u32 dw;
+ int ranksperch;
+
+ if (PCI_FUNC(pdev->devfn) != 1)
+ return -ENODEV;
+
+ rc = pci_enable_device(pdev);
+ if (rc < 0) {
+ ret = rc;
+ goto bail;
+ }
+
+ /* ECC enabled? */
+ pci_read_config_dword(pdev, I5100_MC, &dw);
+ if (!i5100_mc_errdeten(dw)) {
+ printk(KERN_INFO "i5100_edac: ECC not enabled.\n");
+ ret = -ENODEV;
+ goto bail_pdev;
+ }
+
+ /* figure out how many ranks, from strapped state of 48GB_Mode input */
+ pci_read_config_dword(pdev, I5100_MS, &dw);
+ ranksperch = !!(dw & (1 << 8)) * 2 + 4;
+
+ if (ranksperch != 4) {
+ /* FIXME: get 6 ranks / controller to work - need hw... */
+ printk(KERN_INFO "i5100_edac: unsupported configuration.\n");
+ ret = -ENODEV;
+ goto bail_pdev;
+ }
+
+ /* enable error reporting... */
+ pci_read_config_dword(pdev, I5100_EMASK_MEM, &dw);
+ dw &= ~I5100_FERR_NF_MEM_ANY_MASK;
+ pci_write_config_dword(pdev, I5100_EMASK_MEM, dw);
+
+ /* device 21, func 0, Channel 0 Memory Map, Error Flag/Mask, etc... */
+ ch0mm = pci_get_device_func(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_5100_21, 0);
+ if (!ch0mm) {
+ ret = -ENODEV;
+ goto bail_pdev;
+ }
+
+ rc = pci_enable_device(ch0mm);
+ if (rc < 0) {
+ ret = rc;
+ goto bail_ch0;
+ }
+
+ /* device 22, func 0, Channel 1 Memory Map, Error Flag/Mask, etc... */
+ ch1mm = pci_get_device_func(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_5100_22, 0);
+ if (!ch1mm) {
+ ret = -ENODEV;
+ goto bail_disable_ch0;
+ }
+
+ rc = pci_enable_device(ch1mm);
+ if (rc < 0) {
+ ret = rc;
+ goto bail_ch1;
+ }
+
+ mci = edac_mc_alloc(sizeof(*priv), ranksperch * 2, 1, 0);
+ if (!mci) {
+ ret = -ENOMEM;
+ goto bail_disable_ch1;
+ }
+
+ mci->dev = &pdev->dev;
+
+ priv = mci->pvt_info;
+ priv->ranksperctlr = ranksperch;
+ priv->mc = pdev;
+ priv->ch0mm = ch0mm;
+ priv->ch1mm = ch1mm;
+
+ i5100_init_dimm_layout(pdev, mci);
+ i5100_init_interleaving(pdev, mci);
+
+ mci->mtype_cap = MEM_FLAG_FB_DDR2;
+ mci->edac_ctl_cap = EDAC_FLAG_SECDED;
+ mci->edac_cap = EDAC_FLAG_SECDED;
+ mci->mod_name = "i5100_edac.c";
+ mci->mod_ver = "not versioned";
+ mci->ctl_name = "i5100";
+ mci->dev_name = pci_name(pdev);
+ mci->ctl_page_to_phys = NULL;
+
+ mci->edac_check = i5100_check_error;
+
+ i5100_init_csrows(mci);
+
+ /* this strange construction seems to be in every driver, dunno why */
+ switch (edac_op_state) {
+ case EDAC_OPSTATE_POLL:
+ case EDAC_OPSTATE_NMI:
+ break;
+ default:
+ edac_op_state = EDAC_OPSTATE_POLL;
+ break;
+ }
+
+ if (edac_mc_add_mc(mci)) {
+ ret = -ENODEV;
+ goto bail_mc;
+ }
+
+ return ret;
+
+bail_mc:
+ edac_mc_free(mci);
+
+bail_disable_ch1:
+ pci_disable_device(ch1mm);
+
+bail_ch1:
+ pci_dev_put(ch1mm);
+
+bail_disable_ch0:
+ pci_disable_device(ch0mm);
+
+bail_ch0:
+ pci_dev_put(ch0mm);
+
+bail_pdev:
+ pci_disable_device(pdev);
+
+bail:
+ return ret;
+}
+
+static void __devexit i5100_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+ struct i5100_priv *priv;
+
+ mci = edac_mc_del_mc(&pdev->dev);
+
+ if (!mci)
+ return;
+
+ priv = mci->pvt_info;
+ pci_disable_device(pdev);
+ pci_disable_device(priv->ch0mm);
+ pci_disable_device(priv->ch1mm);
+ pci_dev_put(priv->ch0mm);
+ pci_dev_put(priv->ch1mm);
+
+ edac_mc_free(mci);
+}
+
+static const struct pci_device_id i5100_pci_tbl[] __devinitdata = {
+ /* Device 16, Function 0, Channel 0 Memory Map, Error Flag/Mask, ... */
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5100_16) },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, i5100_pci_tbl);
+
+static struct pci_driver i5100_driver = {
+ .name = KBUILD_BASENAME,
+ .probe = i5100_init_one,
+ .remove = __devexit_p(i5100_remove_one),
+ .id_table = i5100_pci_tbl,
+};
+
+static int __init i5100_init(void)
+{
+ int pci_rc;
+
+ pci_rc = pci_register_driver(&i5100_driver);
+
+ return (pci_rc < 0) ? pci_rc : 0;
+}
+
+static void __exit i5100_exit(void)
+{
+ pci_unregister_driver(&i5100_driver);
+}
+
+module_init(i5100_init);
+module_exit(i5100_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR
+ ("Arthur Jones <ajones@riverbed.com>");
+MODULE_DESCRIPTION("MC Driver for Intel I5100 memory controllers");
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index d49361bfe67..2265d9ca153 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -195,14 +195,15 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int __devinit mpc85xx_pci_err_probe(struct platform_device *pdev)
+static int __devinit mpc85xx_pci_err_probe(struct of_device *op,
+ const struct of_device_id *match)
{
struct edac_pci_ctl_info *pci;
struct mpc85xx_pci_pdata *pdata;
- struct resource *r;
+ struct resource r;
int res = 0;
- if (!devres_open_group(&pdev->dev, mpc85xx_pci_err_probe, GFP_KERNEL))
+ if (!devres_open_group(&op->dev, mpc85xx_pci_err_probe, GFP_KERNEL))
return -ENOMEM;
pci = edac_pci_alloc_ctl_info(sizeof(*pdata), "mpc85xx_pci_err");
@@ -212,34 +213,37 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *pdev)
pdata = pci->pvt_info;
pdata->name = "mpc85xx_pci_err";
pdata->irq = NO_IRQ;
- platform_set_drvdata(pdev, pci);
- pci->dev = &pdev->dev;
+ dev_set_drvdata(&op->dev, pci);
+ pci->dev = &op->dev;
pci->mod_name = EDAC_MOD_STR;
pci->ctl_name = pdata->name;
- pci->dev_name = pdev->dev.bus_id;
+ pci->dev_name = op->dev.bus_id;
if (edac_op_state == EDAC_OPSTATE_POLL)
pci->edac_check = mpc85xx_pci_check;
pdata->edac_idx = edac_pci_idx++;
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!r) {
+ res = of_address_to_resource(op->node, 0, &r);
+ if (res) {
printk(KERN_ERR "%s: Unable to get resource for "
"PCI err regs\n", __func__);
goto err;
}
- if (!devm_request_mem_region(&pdev->dev, r->start,
- r->end - r->start + 1, pdata->name)) {
+ /* we only need the error registers */
+ r.start += 0xe00;
+
+ if (!devm_request_mem_region(&op->dev, r.start,
+ r.end - r.start + 1, pdata->name)) {
printk(KERN_ERR "%s: Error while requesting mem region\n",
__func__);
res = -EBUSY;
goto err;
}
- pdata->pci_vbase = devm_ioremap(&pdev->dev, r->start,
- r->end - r->start + 1);
+ pdata->pci_vbase = devm_ioremap(&op->dev, r.start,
+ r.end - r.start + 1);
if (!pdata->pci_vbase) {
printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__);
res = -ENOMEM;
@@ -266,14 +270,15 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *pdev)
}
if (edac_op_state == EDAC_OPSTATE_INT) {
- pdata->irq = platform_get_irq(pdev, 0);
- res = devm_request_irq(&pdev->dev, pdata->irq,
+ pdata->irq = irq_of_parse_and_map(op->node, 0);
+ res = devm_request_irq(&op->dev, pdata->irq,
mpc85xx_pci_isr, IRQF_DISABLED,
"[EDAC] PCI err", pci);
if (res < 0) {
printk(KERN_ERR
"%s: Unable to requiest irq %d for "
"MPC85xx PCI err\n", __func__, pdata->irq);
+ irq_dispose_mapping(pdata->irq);
res = -ENODEV;
goto err2;
}
@@ -282,23 +287,23 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *pdev)
pdata->irq);
}
- devres_remove_group(&pdev->dev, mpc85xx_pci_err_probe);
+ devres_remove_group(&op->dev, mpc85xx_pci_err_probe);
debugf3("%s(): success\n", __func__);
printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n");
return 0;
err2:
- edac_pci_del_device(&pdev->dev);
+ edac_pci_del_device(&op->dev);
err:
edac_pci_free_ctl_info(pci);
- devres_release_group(&pdev->dev, mpc85xx_pci_err_probe);
+ devres_release_group(&op->dev, mpc85xx_pci_err_probe);
return res;
}
-static int mpc85xx_pci_err_remove(struct platform_device *pdev)
+static int mpc85xx_pci_err_remove(struct of_device *op)
{
- struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev);
+ struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev);
struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
debugf0("%s()\n", __func__);
@@ -318,12 +323,26 @@ static int mpc85xx_pci_err_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_driver mpc85xx_pci_err_driver = {
+static struct of_device_id mpc85xx_pci_err_of_match[] = {
+ {
+ .compatible = "fsl,mpc8540-pcix",
+ },
+ {
+ .compatible = "fsl,mpc8540-pci",
+ },
+ {},
+};
+
+static struct of_platform_driver mpc85xx_pci_err_driver = {
+ .owner = THIS_MODULE,
+ .name = "mpc85xx_pci_err",
+ .match_table = mpc85xx_pci_err_of_match,
.probe = mpc85xx_pci_err_probe,
.remove = __devexit_p(mpc85xx_pci_err_remove),
.driver = {
- .name = "mpc85xx_pci_err",
- }
+ .name = "mpc85xx_pci_err",
+ .owner = THIS_MODULE,
+ },
};
#endif /* CONFIG_PCI */
@@ -1002,7 +1021,7 @@ static int __init mpc85xx_mc_init(void)
printk(KERN_WARNING EDAC_MOD_STR "L2 fails to register\n");
#ifdef CONFIG_PCI
- res = platform_driver_register(&mpc85xx_pci_err_driver);
+ res = of_register_platform_driver(&mpc85xx_pci_err_driver);
if (res)
printk(KERN_WARNING EDAC_MOD_STR "PCI fails to register\n");
#endif
@@ -1025,7 +1044,7 @@ static void __exit mpc85xx_mc_exit(void)
{
mtspr(SPRN_HID1, orig_hid1);
#ifdef CONFIG_PCI
- platform_driver_unregister(&mpc85xx_pci_err_driver);
+ of_unregister_platform_driver(&mpc85xx_pci_err_driver);
#endif
of_unregister_platform_driver(&mpc85xx_l2_err_driver);
of_unregister_platform_driver(&mpc85xx_mc_err_driver);
diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c
index bf071f140a0..083ce8d0c63 100644
--- a/drivers/edac/mv64x60_edac.c
+++ b/drivers/edac/mv64x60_edac.c
@@ -71,6 +71,35 @@ static irqreturn_t mv64x60_pci_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
+/*
+ * Bit 0 of MV64x60_PCIx_ERR_MASK does not exist on the 64360 and because of
+ * errata FEr-#11 and FEr-##16 for the 64460, it should be 0 on that chip as
+ * well. IOW, don't set bit 0.
+ */
+
+/* Erratum FEr PCI-#16: clear bit 0 of PCI SERRn Mask reg. */
+static int __init mv64x60_pci_fixup(struct platform_device *pdev)
+{
+ struct resource *r;
+ void __iomem *pci_serr;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!r) {
+ printk(KERN_ERR "%s: Unable to get resource for "
+ "PCI err regs\n", __func__);
+ return -ENOENT;
+ }
+
+ pci_serr = ioremap(r->start, r->end - r->start + 1);
+ if (!pci_serr)
+ return -ENOMEM;
+
+ out_le32(pci_serr, in_le32(pci_serr) & ~0x1);
+ iounmap(pci_serr);
+
+ return 0;
+}
+
static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev)
{
struct edac_pci_ctl_info *pci;
@@ -128,6 +157,12 @@ static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev)
goto err;
}
+ res = mv64x60_pci_fixup(pdev);
+ if (res < 0) {
+ printk(KERN_ERR "%s: PCI fixup failed\n", __func__);
+ goto err;
+ }
+
out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, 0);
out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, 0);
out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK,
@@ -612,7 +647,7 @@ static void get_total_mem(struct mv64x60_mc_pdata *pdata)
if (!np)
return;
- reg = get_property(np, "reg", NULL);
+ reg = of_get_property(np, "reg", NULL);
pdata->total_mem = reg[1];
}
diff --git a/drivers/eisa/Makefile b/drivers/eisa/Makefile
index 70abf93fe6b..5369ce957c6 100644
--- a/drivers/eisa/Makefile
+++ b/drivers/eisa/Makefile
@@ -9,7 +9,7 @@ obj-${CONFIG_EISA_VIRTUAL_ROOT} += virtual_root.o
# Ugly hack to get DEVICE_NAME_SIZE value...
-DEVICE_NAME_SIZE =$(shell awk '$$1=="\#define" && $$2=="DEVICE_NAME_SIZE" {print $$3-1}' $(srctree)/include/linux/device.h)
+DEVICE_NAME_SIZE = 50
$(obj)/eisa-bus.o: $(obj)/devlist.h
diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
index 65dcf043265..c950bf8606d 100644
--- a/drivers/eisa/eisa-bus.c
+++ b/drivers/eisa/eisa-bus.c
@@ -22,7 +22,7 @@
struct eisa_device_info {
struct eisa_device_id id;
- char name[DEVICE_NAME_SIZE];
+ char name[50];
};
#ifdef CONFIG_EISA_NAMES
@@ -63,7 +63,7 @@ static void __init eisa_name_device (struct eisa_device *edev)
if (!strcmp (edev->id.sig, eisa_table[i].id.sig)) {
strlcpy (edev->pretty_name,
eisa_table[i].name,
- DEVICE_NAME_SIZE);
+ sizeof(edev->pretty_name));
return;
}
}
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
index 25918f7dfd0..c66817e7717 100644
--- a/drivers/firmware/dcdbas.c
+++ b/drivers/firmware/dcdbas.c
@@ -152,20 +152,11 @@ static ssize_t smi_data_read(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t pos, size_t count)
{
- size_t max_read;
ssize_t ret;
mutex_lock(&smi_data_lock);
-
- if (pos >= smi_data_buf_size) {
- ret = 0;
- goto out;
- }
-
- max_read = smi_data_buf_size - pos;
- ret = min(max_read, count);
- memcpy(buf, smi_data_buf + pos, ret);
-out:
+ ret = memory_read_from_buffer(buf, count, &pos, smi_data_buf,
+ smi_data_buf_size);
mutex_unlock(&smi_data_lock);
return ret;
}
@@ -254,6 +245,7 @@ static ssize_t host_control_on_shutdown_store(struct device *dev,
static int smi_request(struct smi_cmd *smi_cmd)
{
cpumask_t old_mask;
+ cpumask_of_cpu_ptr(new_mask, 0);
int ret = 0;
if (smi_cmd->magic != SMI_CMD_MAGIC) {
@@ -264,7 +256,7 @@ static int smi_request(struct smi_cmd *smi_cmd)
/* SMI requires CPU 0 */
old_mask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(0));
+ set_cpus_allowed_ptr(current, new_mask);
if (smp_processor_id() != 0) {
dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
__func__);
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
index 7430e218cda..13946ebd77d 100644
--- a/drivers/firmware/dell_rbu.c
+++ b/drivers/firmware/dell_rbu.c
@@ -507,11 +507,6 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
{
- unsigned char *ptemp = NULL;
- size_t bytes_left = 0;
- size_t data_length = 0;
- ssize_t ret_count = 0;
-
/* check to see if we have something to return */
if ((rbu_data.image_update_buffer == NULL) ||
(rbu_data.bios_image_size == 0)) {
@@ -519,28 +514,11 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
"bios_image_size %lu\n",
rbu_data.image_update_buffer,
rbu_data.bios_image_size);
- ret_count = -ENOMEM;
- goto read_rbu_data_exit;
- }
-
- if (pos > rbu_data.bios_image_size) {
- ret_count = 0;
- goto read_rbu_data_exit;
+ return -ENOMEM;
}
- bytes_left = rbu_data.bios_image_size - pos;
- data_length = min(bytes_left, count);
-
- ptemp = rbu_data.image_update_buffer;
- memcpy(buffer, (ptemp + pos), data_length);
-
- if ((pos + count) > rbu_data.bios_image_size)
- /* this was the last copy */
- ret_count = bytes_left;
- else
- ret_count = count;
- read_rbu_data_exit:
- return ret_count;
+ return memory_read_from_buffer(buffer, count, &pos,
+ rbu_data.image_update_buffer, rbu_data.bios_image_size);
}
static ssize_t read_rbu_data(struct kobject *kobj,
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 008c38ba774..dbd42d6c93a 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -2,15 +2,40 @@
# GPIO infrastructure and expanders
#
-config HAVE_GPIO_LIB
+config ARCH_WANT_OPTIONAL_GPIOLIB
bool
help
+ Select this config option from the architecture Kconfig, if
+ it is possible to use gpiolib on the architecture, but let the
+ user decide whether to actually build it or not.
+ Select this instead of ARCH_REQUIRE_GPIOLIB, if your architecture does
+ not depend on GPIOs being available, but rather let the user
+ decide whether he needs it or not.
+
+config ARCH_REQUIRE_GPIOLIB
+ bool
+ select GPIOLIB
+ help
Platforms select gpiolib if they use this infrastructure
for all their GPIOs, usually starting with ones integrated
into SOC processors.
+ Selecting this from the architecture code will cause the gpiolib
+ code to always get built in.
+
+
+
+menuconfig GPIOLIB
+ bool "GPIO Support"
+ depends on ARCH_WANT_OPTIONAL_GPIOLIB || ARCH_REQUIRE_GPIOLIB
+ select GENERIC_GPIO
+ help
+ This enables GPIO support through the generic GPIO library.
+ You only need to enable this, if you also want to enable
+ one or more of the GPIO expansion card drivers below.
+
+ If unsure, say N.
-menu "GPIO Support"
- depends on HAVE_GPIO_LIB
+if GPIOLIB
config DEBUG_GPIO
bool "Debug GPIO calls"
@@ -23,10 +48,44 @@ config DEBUG_GPIO
slower. The diagnostics help catch the type of setup errors
that are most common when setting up new platforms or boards.
+config GPIO_SYSFS
+ bool "/sys/class/gpio/... (sysfs interface)"
+ depends on SYSFS && EXPERIMENTAL
+ help
+ Say Y here to add a sysfs interface for GPIOs.
+
+ This is mostly useful to work around omissions in a system's
+ kernel support. Those are common in custom and semicustom
+ hardware assembled using standard kernels with a minimum of
+ custom patches. In those cases, userspace code may import
+ a given GPIO from the kernel, if no kernel driver requested it.
+
+ Kernel drivers may also request that a particular GPIO be
+ exported to userspace; this can be useful when debugging.
+
# put expanders in the right section, in alphabetical order
comment "I2C GPIO expanders:"
+config GPIO_MAX732X
+ tristate "MAX7319, MAX7320-7327 I2C Port Expanders"
+ depends on I2C
+ help
+ Say yes here to support the MAX7319, MAX7320-7327 series of I2C
+ Port Expanders. Each IO port on these chips has a fixed role of
+ Input (designated by 'I'), Push-Pull Output ('O'), or Open-Drain
+ Input and Output (designed by 'P'). The combinations are listed
+ below:
+
+ 8 bits: max7319 (8I), max7320 (8O), max7321 (8P),
+ max7322 (4I4O), max7323 (4P4O)
+
+ 16 bits: max7324 (8I8O), max7325 (8P8O),
+ max7326 (4I12O), max7327 (4P12O)
+
+ Board setup code must specify the model to use, and the start
+ number for these GPIOs.
+
config GPIO_PCA953X
tristate "PCA953x, PCA955x, and MAX7310 I/O ports"
depends on I2C
@@ -45,7 +104,7 @@ config GPIO_PCA953X
will be called pca953x.
config GPIO_PCF857X
- tristate "PCF857x, PCA857x, and PCA967x I2C GPIO expanders"
+ tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders"
depends on I2C
help
Say yes here to provide access to most "quasi-bidirectional" I2C
@@ -54,7 +113,8 @@ config GPIO_PCF857X
some of them. Compatible models include:
8 bits: pcf8574, pcf8574a, pca8574, pca8574a,
- pca9670, pca9672, pca9674, pca9674a
+ pca9670, pca9672, pca9674, pca9674a,
+ max7328, max7329
16 bits: pcf8575, pcf8575c, pca8575,
pca9671, pca9673, pca9675
@@ -67,8 +127,32 @@ config GPIO_PCF857X
This driver provides an in-kernel interface to those GPIOs using
platform-neutral GPIO calls.
+comment "PCI GPIO expanders:"
+
+config GPIO_BT8XX
+ tristate "BT8XX GPIO abuser"
+ depends on PCI && VIDEO_BT848=n
+ help
+ The BT8xx frame grabber chip has 24 GPIO pins than can be abused
+ as a cheap PCI GPIO card.
+
+ This chip can be found on Miro, Hauppauge and STB TV-cards.
+
+ The card needs to be physically altered for using it as a
+ GPIO card. For more information on how to build a GPIO card
+ from a BT8xx TV card, see the documentation file at
+ Documentation/bt8xxgpio.txt
+
+ If unsure, say N.
+
comment "SPI GPIO expanders:"
+config GPIO_MAX7301
+ tristate "Maxim MAX7301 GPIO expander"
+ depends on SPI_MASTER
+ help
+ gpio driver for Maxim MAX7301 SPI GPIO expander.
+
config GPIO_MCP23S08
tristate "Microchip MCP23S08 I/O expander"
depends on SPI_MASTER
@@ -76,4 +160,4 @@ config GPIO_MCP23S08
SPI driver for Microchip MCP23S08 I/O expander. This provides
a GPIO interface supporting inputs and outputs.
-endmenu
+endif
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index fdde9923cf3..01b4bbde195 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -2,8 +2,11 @@
ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
-obj-$(CONFIG_HAVE_GPIO_LIB) += gpiolib.o
+obj-$(CONFIG_GPIOLIB) += gpiolib.o
+obj-$(CONFIG_GPIO_MAX7301) += max7301.o
+obj-$(CONFIG_GPIO_MAX732X) += max732x.o
obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o
obj-$(CONFIG_GPIO_PCA953X) += pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
+obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o
diff --git a/drivers/gpio/bt8xxgpio.c b/drivers/gpio/bt8xxgpio.c
new file mode 100644
index 00000000000..7a1168249dd
--- /dev/null
+++ b/drivers/gpio/bt8xxgpio.c
@@ -0,0 +1,348 @@
+/*
+
+ bt8xx GPIO abuser
+
+ Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
+
+ Please do _only_ contact the people listed _above_ with issues related to this driver.
+ All the other people listed below are not related to this driver. Their names
+ are only here, because this driver is derived from the bt848 driver.
+
+
+ Derived from the bt848 driver:
+
+ Copyright (C) 1996,97,98 Ralph Metzler
+ & Marcus Metzler
+ (c) 1999-2002 Gerd Knorr
+
+ some v4l2 code lines are taken from Justin's bttv2 driver which is
+ (c) 2000 Justin Schoeman
+
+ V4L1 removal from:
+ (c) 2005-2006 Nickolay V. Shmyrev
+
+ Fixes to be fully V4L2 compliant by
+ (c) 2006 Mauro Carvalho Chehab
+
+ Cropping and overscan support
+ Copyright (C) 2005, 2006 Michael H. Schimek
+ Sponsored by OPQ Systems AB
+
+ 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.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include <asm/gpio.h>
+
+/* Steal the hardware definitions from the bttv driver. */
+#include "../media/video/bt8xx/bt848.h"
+
+
+#define BT8XXGPIO_NR_GPIOS 24 /* We have 24 GPIO pins */
+
+
+struct bt8xxgpio {
+ spinlock_t lock;
+
+ void __iomem *mmio;
+ struct pci_dev *pdev;
+ struct gpio_chip gpio;
+
+#ifdef CONFIG_PM
+ u32 saved_outen;
+ u32 saved_data;
+#endif
+};
+
+#define bgwrite(dat, adr) writel((dat), bg->mmio+(adr))
+#define bgread(adr) readl(bg->mmio+(adr))
+
+
+static int modparam_gpiobase = -1/* dynamic */;
+module_param_named(gpiobase, modparam_gpiobase, int, 0444);
+MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default.");
+
+
+static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
+{
+ struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
+ unsigned long flags;
+ u32 outen, data;
+
+ spin_lock_irqsave(&bg->lock, flags);
+
+ data = bgread(BT848_GPIO_DATA);
+ data &= ~(1 << nr);
+ bgwrite(data, BT848_GPIO_DATA);
+
+ outen = bgread(BT848_GPIO_OUT_EN);
+ outen &= ~(1 << nr);
+ bgwrite(outen, BT848_GPIO_OUT_EN);
+
+ spin_unlock_irqrestore(&bg->lock, flags);
+
+ return 0;
+}
+
+static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
+{
+ struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&bg->lock, flags);
+ val = bgread(BT848_GPIO_DATA);
+ spin_unlock_irqrestore(&bg->lock, flags);
+
+ return !!(val & (1 << nr));
+}
+
+static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio,
+ unsigned nr, int val)
+{
+ struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
+ unsigned long flags;
+ u32 outen, data;
+
+ spin_lock_irqsave(&bg->lock, flags);
+
+ outen = bgread(BT848_GPIO_OUT_EN);
+ outen |= (1 << nr);
+ bgwrite(outen, BT848_GPIO_OUT_EN);
+
+ data = bgread(BT848_GPIO_DATA);
+ if (val)
+ data |= (1 << nr);
+ else
+ data &= ~(1 << nr);
+ bgwrite(data, BT848_GPIO_DATA);
+
+ spin_unlock_irqrestore(&bg->lock, flags);
+
+ return 0;
+}
+
+static void bt8xxgpio_gpio_set(struct gpio_chip *gpio,
+ unsigned nr, int val)
+{
+ struct bt8xxgpio *bg = container_of(gpio, struct bt8xxgpio, gpio);
+ unsigned long flags;
+ u32 data;
+
+ spin_lock_irqsave(&bg->lock, flags);
+
+ data = bgread(BT848_GPIO_DATA);
+ if (val)
+ data |= (1 << nr);
+ else
+ data &= ~(1 << nr);
+ bgwrite(data, BT848_GPIO_DATA);
+
+ spin_unlock_irqrestore(&bg->lock, flags);
+}
+
+static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg)
+{
+ struct gpio_chip *c = &bg->gpio;
+
+ c->label = bg->pdev->dev.bus_id;
+ c->owner = THIS_MODULE;
+ c->direction_input = bt8xxgpio_gpio_direction_input;
+ c->get = bt8xxgpio_gpio_get;
+ c->direction_output = bt8xxgpio_gpio_direction_output;
+ c->set = bt8xxgpio_gpio_set;
+ c->dbg_show = NULL;
+ c->base = modparam_gpiobase;
+ c->ngpio = BT8XXGPIO_NR_GPIOS;
+ c->can_sleep = 0;
+}
+
+static int bt8xxgpio_probe(struct pci_dev *dev,
+ const struct pci_device_id *pci_id)
+{
+ struct bt8xxgpio *bg;
+ int err;
+
+ bg = kzalloc(sizeof(*bg), GFP_KERNEL);
+ if (!bg)
+ return -ENOMEM;
+
+ bg->pdev = dev;
+ spin_lock_init(&bg->lock);
+
+ err = pci_enable_device(dev);
+ if (err) {
+ printk(KERN_ERR "bt8xxgpio: Can't enable device.\n");
+ goto err_freebg;
+ }
+ if (!request_mem_region(pci_resource_start(dev, 0),
+ pci_resource_len(dev, 0),
+ "bt8xxgpio")) {
+ printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n",
+ (unsigned long long)pci_resource_start(dev, 0));
+ err = -EBUSY;
+ goto err_disable;
+ }
+ pci_set_master(dev);
+ pci_set_drvdata(dev, bg);
+
+ bg->mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
+ if (!bg->mmio) {
+ printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");
+ err = -EIO;
+ goto err_release_mem;
+ }
+
+ /* Disable interrupts */
+ bgwrite(0, BT848_INT_MASK);
+
+ /* gpio init */
+ bgwrite(0, BT848_GPIO_DMA_CTL);
+ bgwrite(0, BT848_GPIO_REG_INP);
+ bgwrite(0, BT848_GPIO_OUT_EN);
+
+ bt8xxgpio_gpio_setup(bg);
+ err = gpiochip_add(&bg->gpio);
+ if (err) {
+ printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n");
+ goto err_release_mem;
+ }
+
+ printk(KERN_INFO "bt8xxgpio: Abusing BT8xx card for GPIOs %d to %d\n",
+ bg->gpio.base, bg->gpio.base + BT8XXGPIO_NR_GPIOS - 1);
+
+ return 0;
+
+err_release_mem:
+ release_mem_region(pci_resource_start(dev, 0),
+ pci_resource_len(dev, 0));
+ pci_set_drvdata(dev, NULL);
+err_disable:
+ pci_disable_device(dev);
+err_freebg:
+ kfree(bg);
+
+ return err;
+}
+
+static void bt8xxgpio_remove(struct pci_dev *pdev)
+{
+ struct bt8xxgpio *bg = pci_get_drvdata(pdev);
+
+ gpiochip_remove(&bg->gpio);
+
+ bgwrite(0, BT848_INT_MASK);
+ bgwrite(~0x0, BT848_INT_STAT);
+ bgwrite(0x0, BT848_GPIO_OUT_EN);
+
+ iounmap(bg->mmio);
+ release_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ pci_disable_device(pdev);
+
+ pci_set_drvdata(pdev, NULL);
+ kfree(bg);
+}
+
+#ifdef CONFIG_PM
+static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct bt8xxgpio *bg = pci_get_drvdata(pdev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&bg->lock, flags);
+
+ bg->saved_outen = bgread(BT848_GPIO_OUT_EN);
+ bg->saved_data = bgread(BT848_GPIO_DATA);
+
+ bgwrite(0, BT848_INT_MASK);
+ bgwrite(~0x0, BT848_INT_STAT);
+ bgwrite(0x0, BT848_GPIO_OUT_EN);
+
+ spin_unlock_irqrestore(&bg->lock, flags);
+
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+static int bt8xxgpio_resume(struct pci_dev *pdev)
+{
+ struct bt8xxgpio *bg = pci_get_drvdata(pdev);
+ unsigned long flags;
+ int err;
+
+ pci_set_power_state(pdev, 0);
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+ pci_restore_state(pdev);
+
+ spin_lock_irqsave(&bg->lock, flags);
+
+ bgwrite(0, BT848_INT_MASK);
+ bgwrite(0, BT848_GPIO_DMA_CTL);
+ bgwrite(0, BT848_GPIO_REG_INP);
+ bgwrite(bg->saved_outen, BT848_GPIO_OUT_EN);
+ bgwrite(bg->saved_data & bg->saved_outen,
+ BT848_GPIO_DATA);
+
+ spin_unlock_irqrestore(&bg->lock, flags);
+
+ return 0;
+}
+#else
+#define bt8xxgpio_suspend NULL
+#define bt8xxgpio_resume NULL
+#endif /* CONFIG_PM */
+
+static struct pci_device_id bt8xxgpio_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
+ { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
+ { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
+ { PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879) },
+ { 0, },
+};
+MODULE_DEVICE_TABLE(pci, bt8xxgpio_pci_tbl);
+
+static struct pci_driver bt8xxgpio_pci_driver = {
+ .name = "bt8xxgpio",
+ .id_table = bt8xxgpio_pci_tbl,
+ .probe = bt8xxgpio_probe,
+ .remove = bt8xxgpio_remove,
+ .suspend = bt8xxgpio_suspend,
+ .resume = bt8xxgpio_resume,
+};
+
+static int bt8xxgpio_init(void)
+{
+ return pci_register_driver(&bt8xxgpio_pci_driver);
+}
+module_init(bt8xxgpio_init)
+
+static void bt8xxgpio_exit(void)
+{
+ pci_unregister_driver(&bt8xxgpio_pci_driver);
+}
+module_exit(bt8xxgpio_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michael Buesch");
+MODULE_DESCRIPTION("Abuse a BT8xx framegrabber card as generic GPIO card");
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index beaf6b3a37d..8d2940517c9 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -2,8 +2,11 @@
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/spinlock.h>
-
-#include <asm/gpio.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/gpio.h>
/* Optional implementation infrastructure for GPIO interfaces.
@@ -44,6 +47,8 @@ struct gpio_desc {
#define FLAG_REQUESTED 0
#define FLAG_IS_OUT 1
#define FLAG_RESERVED 2
+#define FLAG_EXPORT 3 /* protected by sysfs_lock */
+#define FLAG_SYSFS 4 /* exported via /sys/class/gpio/control */
#ifdef CONFIG_DEBUG_FS
const char *label;
@@ -151,6 +156,482 @@ err:
return ret;
}
+#ifdef CONFIG_GPIO_SYSFS
+
+/* lock protects against unexport_gpio() being called while
+ * sysfs files are active.
+ */
+static DEFINE_MUTEX(sysfs_lock);
+
+/*
+ * /sys/class/gpio/gpioN... only for GPIOs that are exported
+ * /direction
+ * * MAY BE OMITTED if kernel won't allow direction changes
+ * * is read/write as "in" or "out"
+ * * may also be written as "high" or "low", initializing
+ * output value as specified ("out" implies "low")
+ * /value
+ * * always readable, subject to hardware behavior
+ * * may be writable, as zero/nonzero
+ *
+ * REVISIT there will likely be an attribute for configuring async
+ * notifications, e.g. to specify polling interval or IRQ trigger type
+ * that would for example trigger a poll() on the "value".
+ */
+
+static ssize_t gpio_direction_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const struct gpio_desc *desc = dev_get_drvdata(dev);
+ ssize_t status;
+
+ mutex_lock(&sysfs_lock);
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags))
+ status = -EIO;
+ else
+ status = sprintf(buf, "%s\n",
+ test_bit(FLAG_IS_OUT, &desc->flags)
+ ? "out" : "in");
+
+ mutex_unlock(&sysfs_lock);
+ return status;
+}
+
+static ssize_t gpio_direction_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ const struct gpio_desc *desc = dev_get_drvdata(dev);
+ unsigned gpio = desc - gpio_desc;
+ ssize_t status;
+
+ mutex_lock(&sysfs_lock);
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags))
+ status = -EIO;
+ else if (sysfs_streq(buf, "high"))
+ status = gpio_direction_output(gpio, 1);
+ else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low"))
+ status = gpio_direction_output(gpio, 0);
+ else if (sysfs_streq(buf, "in"))
+ status = gpio_direction_input(gpio);
+ else
+ status = -EINVAL;
+
+ mutex_unlock(&sysfs_lock);
+ return status ? : size;
+}
+
+static const DEVICE_ATTR(direction, 0644,
+ gpio_direction_show, gpio_direction_store);
+
+static ssize_t gpio_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const struct gpio_desc *desc = dev_get_drvdata(dev);
+ unsigned gpio = desc - gpio_desc;
+ ssize_t status;
+
+ mutex_lock(&sysfs_lock);
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags))
+ status = -EIO;
+ else
+ status = sprintf(buf, "%d\n", gpio_get_value_cansleep(gpio));
+
+ mutex_unlock(&sysfs_lock);
+ return status;
+}
+
+static ssize_t gpio_value_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ const struct gpio_desc *desc = dev_get_drvdata(dev);
+ unsigned gpio = desc - gpio_desc;
+ ssize_t status;
+
+ mutex_lock(&sysfs_lock);
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags))
+ status = -EIO;
+ else if (!test_bit(FLAG_IS_OUT, &desc->flags))
+ status = -EPERM;
+ else {
+ long value;
+
+ status = strict_strtol(buf, 0, &value);
+ if (status == 0) {
+ gpio_set_value_cansleep(gpio, value != 0);
+ status = size;
+ }
+ }
+
+ mutex_unlock(&sysfs_lock);
+ return status;
+}
+
+static /*const*/ DEVICE_ATTR(value, 0644,
+ gpio_value_show, gpio_value_store);
+
+static const struct attribute *gpio_attrs[] = {
+ &dev_attr_direction.attr,
+ &dev_attr_value.attr,
+ NULL,
+};
+
+static const struct attribute_group gpio_attr_group = {
+ .attrs = (struct attribute **) gpio_attrs,
+};
+
+/*
+ * /sys/class/gpio/gpiochipN/
+ * /base ... matching gpio_chip.base (N)
+ * /label ... matching gpio_chip.label
+ * /ngpio ... matching gpio_chip.ngpio
+ */
+
+static ssize_t chip_base_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const struct gpio_chip *chip = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", chip->base);
+}
+static DEVICE_ATTR(base, 0444, chip_base_show, NULL);
+
+static ssize_t chip_label_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const struct gpio_chip *chip = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", chip->label ? : "");
+}
+static DEVICE_ATTR(label, 0444, chip_label_show, NULL);
+
+static ssize_t chip_ngpio_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const struct gpio_chip *chip = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", chip->ngpio);
+}
+static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL);
+
+static const struct attribute *gpiochip_attrs[] = {
+ &dev_attr_base.attr,
+ &dev_attr_label.attr,
+ &dev_attr_ngpio.attr,
+ NULL,
+};
+
+static const struct attribute_group gpiochip_attr_group = {
+ .attrs = (struct attribute **) gpiochip_attrs,
+};
+
+/*
+ * /sys/class/gpio/export ... write-only
+ * integer N ... number of GPIO to export (full access)
+ * /sys/class/gpio/unexport ... write-only
+ * integer N ... number of GPIO to unexport
+ */
+static ssize_t export_store(struct class *class, const char *buf, size_t len)
+{
+ long gpio;
+ int status;
+
+ status = strict_strtol(buf, 0, &gpio);
+ if (status < 0)
+ goto done;
+
+ /* No extra locking here; FLAG_SYSFS just signifies that the
+ * request and export were done by on behalf of userspace, so
+ * they may be undone on its behalf too.
+ */
+
+ status = gpio_request(gpio, "sysfs");
+ if (status < 0)
+ goto done;
+
+ status = gpio_export(gpio, true);
+ if (status < 0)
+ gpio_free(gpio);
+ else
+ set_bit(FLAG_SYSFS, &gpio_desc[gpio].flags);
+
+done:
+ if (status)
+ pr_debug("%s: status %d\n", __func__, status);
+ return status ? : len;
+}
+
+static ssize_t unexport_store(struct class *class, const char *buf, size_t len)
+{
+ long gpio;
+ int status;
+
+ status = strict_strtol(buf, 0, &gpio);
+ if (status < 0)
+ goto done;
+
+ status = -EINVAL;
+
+ /* reject bogus commands (gpio_unexport ignores them) */
+ if (!gpio_is_valid(gpio))
+ goto done;
+
+ /* No extra locking here; FLAG_SYSFS just signifies that the
+ * request and export were done by on behalf of userspace, so
+ * they may be undone on its behalf too.
+ */
+ if (test_and_clear_bit(FLAG_SYSFS, &gpio_desc[gpio].flags)) {
+ status = 0;
+ gpio_free(gpio);
+ }
+done:
+ if (status)
+ pr_debug("%s: status %d\n", __func__, status);
+ return status ? : len;
+}
+
+static struct class_attribute gpio_class_attrs[] = {
+ __ATTR(export, 0200, NULL, export_store),
+ __ATTR(unexport, 0200, NULL, unexport_store),
+ __ATTR_NULL,
+};
+
+static struct class gpio_class = {
+ .name = "gpio",
+ .owner = THIS_MODULE,
+
+ .class_attrs = gpio_class_attrs,
+};
+
+
+/**
+ * gpio_export - export a GPIO through sysfs
+ * @gpio: gpio to make available, already requested
+ * @direction_may_change: true if userspace may change gpio direction
+ * Context: arch_initcall or later
+ *
+ * When drivers want to make a GPIO accessible to userspace after they
+ * have requested it -- perhaps while debugging, or as part of their
+ * public interface -- they may use this routine. If the GPIO can
+ * change direction (some can't) and the caller allows it, userspace
+ * will see "direction" sysfs attribute which may be used to change
+ * the gpio's direction. A "value" attribute will always be provided.
+ *
+ * Returns zero on success, else an error.
+ */
+int gpio_export(unsigned gpio, bool direction_may_change)
+{
+ unsigned long flags;
+ struct gpio_desc *desc;
+ int status = -EINVAL;
+
+ /* can't export until sysfs is available ... */
+ if (!gpio_class.p) {
+ pr_debug("%s: called too early!\n", __func__);
+ return -ENOENT;
+ }
+
+ if (!gpio_is_valid(gpio))
+ goto done;
+
+ mutex_lock(&sysfs_lock);
+
+ spin_lock_irqsave(&gpio_lock, flags);
+ desc = &gpio_desc[gpio];
+ if (test_bit(FLAG_REQUESTED, &desc->flags)
+ && !test_bit(FLAG_EXPORT, &desc->flags)) {
+ status = 0;
+ if (!desc->chip->direction_input
+ || !desc->chip->direction_output)
+ direction_may_change = false;
+ }
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+ if (status == 0) {
+ struct device *dev;
+
+ dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
+ desc, "gpio%d", gpio);
+ if (dev) {
+ if (direction_may_change)
+ status = sysfs_create_group(&dev->kobj,
+ &gpio_attr_group);
+ else
+ status = device_create_file(dev,
+ &dev_attr_value);
+ if (status != 0)
+ device_unregister(dev);
+ } else
+ status = -ENODEV;
+ if (status == 0)
+ set_bit(FLAG_EXPORT, &desc->flags);
+ }
+
+ mutex_unlock(&sysfs_lock);
+
+done:
+ if (status)
+ pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(gpio_export);
+
+static int match_export(struct device *dev, void *data)
+{
+ return dev_get_drvdata(dev) == data;
+}
+
+/**
+ * gpio_unexport - reverse effect of gpio_export()
+ * @gpio: gpio to make unavailable
+ *
+ * This is implicit on gpio_free().
+ */
+void gpio_unexport(unsigned gpio)
+{
+ struct gpio_desc *desc;
+ int status = -EINVAL;
+
+ if (!gpio_is_valid(gpio))
+ goto done;
+
+ mutex_lock(&sysfs_lock);
+
+ desc = &gpio_desc[gpio];
+ if (test_bit(FLAG_EXPORT, &desc->flags)) {
+ struct device *dev = NULL;
+
+ dev = class_find_device(&gpio_class, NULL, desc, match_export);
+ if (dev) {
+ clear_bit(FLAG_EXPORT, &desc->flags);
+ put_device(dev);
+ device_unregister(dev);
+ status = 0;
+ } else
+ status = -ENODEV;
+ }
+
+ mutex_unlock(&sysfs_lock);
+done:
+ if (status)
+ pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
+}
+EXPORT_SYMBOL_GPL(gpio_unexport);
+
+static int gpiochip_export(struct gpio_chip *chip)
+{
+ int status;
+ struct device *dev;
+
+ /* Many systems register gpio chips for SOC support very early,
+ * before driver model support is available. In those cases we
+ * export this later, in gpiolib_sysfs_init() ... here we just
+ * verify that _some_ field of gpio_class got initialized.
+ */
+ if (!gpio_class.p)
+ return 0;
+
+ /* use chip->base for the ID; it's already known to be unique */
+ mutex_lock(&sysfs_lock);
+ dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip,
+ "gpiochip%d", chip->base);
+ if (dev) {
+ status = sysfs_create_group(&dev->kobj,
+ &gpiochip_attr_group);
+ } else
+ status = -ENODEV;
+ chip->exported = (status == 0);
+ mutex_unlock(&sysfs_lock);
+
+ if (status) {
+ unsigned long flags;
+ unsigned gpio;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+ gpio = chip->base;
+ while (gpio_desc[gpio].chip == chip)
+ gpio_desc[gpio++].chip = NULL;
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+ pr_debug("%s: chip %s status %d\n", __func__,
+ chip->label, status);
+ }
+
+ return status;
+}
+
+static void gpiochip_unexport(struct gpio_chip *chip)
+{
+ int status;
+ struct device *dev;
+
+ mutex_lock(&sysfs_lock);
+ dev = class_find_device(&gpio_class, NULL, chip, match_export);
+ if (dev) {
+ put_device(dev);
+ device_unregister(dev);
+ chip->exported = 0;
+ status = 0;
+ } else
+ status = -ENODEV;
+ mutex_unlock(&sysfs_lock);
+
+ if (status)
+ pr_debug("%s: chip %s status %d\n", __func__,
+ chip->label, status);
+}
+
+static int __init gpiolib_sysfs_init(void)
+{
+ int status;
+ unsigned long flags;
+ unsigned gpio;
+
+ status = class_register(&gpio_class);
+ if (status < 0)
+ return status;
+
+ /* Scan and register the gpio_chips which registered very
+ * early (e.g. before the class_register above was called).
+ *
+ * We run before arch_initcall() so chip->dev nodes can have
+ * registered, and so arch_initcall() can always gpio_export().
+ */
+ spin_lock_irqsave(&gpio_lock, flags);
+ for (gpio = 0; gpio < ARCH_NR_GPIOS; gpio++) {
+ struct gpio_chip *chip;
+
+ chip = gpio_desc[gpio].chip;
+ if (!chip || chip->exported)
+ continue;
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ status = gpiochip_export(chip);
+ spin_lock_irqsave(&gpio_lock, flags);
+ }
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+
+ return status;
+}
+postcore_initcall(gpiolib_sysfs_init);
+
+#else
+static inline int gpiochip_export(struct gpio_chip *chip)
+{
+ return 0;
+}
+
+static inline void gpiochip_unexport(struct gpio_chip *chip)
+{
+}
+
+#endif /* CONFIG_GPIO_SYSFS */
+
/**
* gpiochip_add() - register a gpio_chip
* @chip: the chip to register, with chip->base initialized
@@ -160,6 +641,11 @@ err:
* because the chip->base is invalid or already associated with a
* different chip. Otherwise it returns zero as a success code.
*
+ * When gpiochip_add() is called very early during boot, so that GPIOs
+ * can be freely used, the chip->dev device must be registered before
+ * the gpio framework's arch_initcall(). Otherwise sysfs initialization
+ * for GPIOs will fail rudely.
+ *
* If chip->base is negative, this requests dynamic assignment of
* a range of valid GPIOs.
*/
@@ -182,7 +668,7 @@ int gpiochip_add(struct gpio_chip *chip)
base = gpiochip_find_base(chip->ngpio);
if (base < 0) {
status = base;
- goto fail_unlock;
+ goto unlock;
}
chip->base = base;
}
@@ -197,12 +683,23 @@ int gpiochip_add(struct gpio_chip *chip)
if (status == 0) {
for (id = base; id < base + chip->ngpio; id++) {
gpio_desc[id].chip = chip;
- gpio_desc[id].flags = 0;
+
+ /* REVISIT: most hardware initializes GPIOs as
+ * inputs (often with pullups enabled) so power
+ * usage is minimized. Linux code should set the
+ * gpio direction first thing; but until it does,
+ * we may expose the wrong direction in sysfs.
+ */
+ gpio_desc[id].flags = !chip->direction_input
+ ? (1 << FLAG_IS_OUT)
+ : 0;
}
}
-fail_unlock:
+unlock:
spin_unlock_irqrestore(&gpio_lock, flags);
+ if (status == 0)
+ status = gpiochip_export(chip);
fail:
/* failures here can mean systems won't boot... */
if (status)
@@ -239,6 +736,10 @@ int gpiochip_remove(struct gpio_chip *chip)
}
spin_unlock_irqrestore(&gpio_lock, flags);
+
+ if (status == 0)
+ gpiochip_unexport(chip);
+
return status;
}
EXPORT_SYMBOL_GPL(gpiochip_remove);
@@ -296,6 +797,8 @@ void gpio_free(unsigned gpio)
return;
}
+ gpio_unexport(gpio);
+
spin_lock_irqsave(&gpio_lock, flags);
desc = &gpio_desc[gpio];
@@ -534,10 +1037,6 @@ EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);
#ifdef CONFIG_DEBUG_FS
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-
static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{
unsigned i;
@@ -614,17 +1113,28 @@ static int gpiolib_show(struct seq_file *s, void *unused)
/* REVISIT this isn't locked against gpio_chip removal ... */
for (gpio = 0; gpio_is_valid(gpio); gpio++) {
+ struct device *dev;
+
if (chip == gpio_desc[gpio].chip)
continue;
chip = gpio_desc[gpio].chip;
if (!chip)
continue;
- seq_printf(s, "%sGPIOs %d-%d, %s%s:\n",
+ seq_printf(s, "%sGPIOs %d-%d",
started ? "\n" : "",
- chip->base, chip->base + chip->ngpio - 1,
- chip->label ? : "generic",
- chip->can_sleep ? ", can sleep" : "");
+ chip->base, chip->base + chip->ngpio - 1);
+ dev = chip->dev;
+ if (dev)
+ seq_printf(s, ", %s/%s",
+ dev->bus ? dev->bus->name : "no-bus",
+ dev->bus_id);
+ if (chip->label)
+ seq_printf(s, ", %s", chip->label);
+ if (chip->can_sleep)
+ seq_printf(s, ", can sleep");
+ seq_printf(s, ":\n");
+
started = 1;
if (chip->dbg_show)
chip->dbg_show(s, chip);
diff --git a/drivers/gpio/max7301.c b/drivers/gpio/max7301.c
new file mode 100644
index 00000000000..39c795ad831
--- /dev/null
+++ b/drivers/gpio/max7301.c
@@ -0,0 +1,339 @@
+/**
+ * drivers/gpio/max7301.c
+ *
+ * Copyright (C) 2006 Juergen Beisert, Pengutronix
+ * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
+ *
+ * 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.
+ *
+ * The Maxim's MAX7301 device is an SPI driven GPIO expander. There are
+ * 28 GPIOs. 8 of them can trigger an interrupt. See datasheet for more
+ * details
+ * Note:
+ * - DIN must be stable at the rising edge of clock.
+ * - when writing:
+ * - always clock in 16 clocks at once
+ * - at DIN: D15 first, D0 last
+ * - D0..D7 = databyte, D8..D14 = commandbyte
+ * - D15 = low -> write command
+ * - when reading
+ * - always clock in 16 clocks at once
+ * - at DIN: D15 first, D0 last
+ * - D0..D7 = dummy, D8..D14 = register address
+ * - D15 = high -> read command
+ * - raise CS and assert it again
+ * - always clock in 16 clocks at once
+ * - at DOUT: D15 first, D0 last
+ * - D0..D7 contains the data from the first cycle
+ *
+ * The driver exports a standard gpiochip interface
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/max7301.h>
+#include <linux/gpio.h>
+
+#define DRIVER_NAME "max7301"
+
+/*
+ * Pin configurations, see MAX7301 datasheet page 6
+ */
+#define PIN_CONFIG_MASK 0x03
+#define PIN_CONFIG_IN_PULLUP 0x03
+#define PIN_CONFIG_IN_WO_PULLUP 0x02
+#define PIN_CONFIG_OUT 0x01
+
+#define PIN_NUMBER 28
+
+
+/*
+ * Some registers must be read back to modify.
+ * To save time we cache them here in memory
+ */
+struct max7301 {
+ struct mutex lock;
+ u8 port_config[8]; /* field 0 is unused */
+ u32 out_level; /* cached output levels */
+ struct gpio_chip chip;
+ struct spi_device *spi;
+};
+
+/**
+ * max7301_write - Write a new register content
+ * @spi: The SPI device
+ * @reg: Register offset
+ * @val: Value to write
+ *
+ * A write to the MAX7301 means one message with one transfer
+ *
+ * Returns 0 if successful or a negative value on error
+ */
+static int max7301_write(struct spi_device *spi, unsigned int reg, unsigned int val)
+{
+ u16 word = ((reg & 0x7F) << 8) | (val & 0xFF);
+ return spi_write(spi, (const u8 *)&word, sizeof(word));
+}
+
+/**
+ * max7301_read - Read back register content
+ * @spi: The SPI device
+ * @reg: Register offset
+ *
+ * A read from the MAX7301 means two transfers; here, one message each
+ *
+ * Returns positive 8 bit value from device if successful or a
+ * negative value on error
+ */
+static int max7301_read(struct spi_device *spi, unsigned int reg)
+{
+ int ret;
+ u16 word;
+
+ word = 0x8000 | (reg << 8);
+ ret = spi_write(spi, (const u8 *)&word, sizeof(word));
+ if (ret)
+ return ret;
+ /*
+ * This relies on the fact, that a transfer with NULL tx_buf shifts out
+ * zero bytes (=NOOP for MAX7301)
+ */
+ ret = spi_read(spi, (u8 *)&word, sizeof(word));
+ if (ret)
+ return ret;
+ return word & 0xff;
+}
+
+static int max7301_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct max7301 *ts = container_of(chip, struct max7301, chip);
+ u8 *config;
+ int ret;
+
+ /* First 4 pins are unused in the controller */
+ offset += 4;
+
+ config = &ts->port_config[offset >> 2];
+
+ mutex_lock(&ts->lock);
+
+ /* Standard GPIO API doesn't support pull-ups, has to be extended.
+ * Hard-coding no pollup for now. */
+ *config = (*config & ~(3 << (offset & 3))) | (1 << (offset & 3));
+
+ ret = max7301_write(ts->spi, 0x08 + (offset >> 2), *config);
+
+ mutex_unlock(&ts->lock);
+
+ return ret;
+}
+
+static int __max7301_set(struct max7301 *ts, unsigned offset, int value)
+{
+ if (value) {
+ ts->out_level |= 1 << offset;
+ return max7301_write(ts->spi, 0x20 + offset, 0x01);
+ } else {
+ ts->out_level &= ~(1 << offset);
+ return max7301_write(ts->spi, 0x20 + offset, 0x00);
+ }
+}
+
+static int max7301_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ struct max7301 *ts = container_of(chip, struct max7301, chip);
+ u8 *config;
+ int ret;
+
+ /* First 4 pins are unused in the controller */
+ offset += 4;
+
+ config = &ts->port_config[offset >> 2];
+
+ mutex_lock(&ts->lock);
+
+ *config = (*config & ~(3 << (offset & 3))) | (1 << (offset & 3));
+
+ ret = __max7301_set(ts, offset, value);
+
+ if (!ret)
+ ret = max7301_write(ts->spi, 0x08 + (offset >> 2), *config);
+
+ mutex_unlock(&ts->lock);
+
+ return ret;
+}
+
+static int max7301_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct max7301 *ts = container_of(chip, struct max7301, chip);
+ int config, level = -EINVAL;
+
+ /* First 4 pins are unused in the controller */
+ offset += 4;
+
+ mutex_lock(&ts->lock);
+
+ config = (ts->port_config[offset >> 2] >> ((offset & 3) * 2)) & 3;
+
+ switch (config) {
+ case 1:
+ /* Output: return cached level */
+ level = !!(ts->out_level & (1 << offset));
+ break;
+ case 2:
+ case 3:
+ /* Input: read out */
+ level = max7301_read(ts->spi, 0x20 + offset) & 0x01;
+ }
+ mutex_unlock(&ts->lock);
+
+ return level;
+}
+
+static void max7301_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct max7301 *ts = container_of(chip, struct max7301, chip);
+
+ /* First 4 pins are unused in the controller */
+ offset += 4;
+
+ mutex_lock(&ts->lock);
+
+ __max7301_set(ts, offset, value);
+
+ mutex_unlock(&ts->lock);
+}
+
+static int __devinit max7301_probe(struct spi_device *spi)
+{
+ struct max7301 *ts;
+ struct max7301_platform_data *pdata;
+ int i, ret;
+
+ pdata = spi->dev.platform_data;
+ if (!pdata || !pdata->base)
+ return -ENODEV;
+
+ /*
+ * bits_per_word cannot be configured in platform data
+ */
+ spi->bits_per_word = 16;
+
+ ret = spi_setup(spi);
+ if (ret < 0)
+ return ret;
+
+ ts = kzalloc(sizeof(struct max7301), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ mutex_init(&ts->lock);
+
+ dev_set_drvdata(&spi->dev, ts);
+
+ /* Power up the chip and disable IRQ output */
+ max7301_write(spi, 0x04, 0x01);
+
+ ts->spi = spi;
+
+ ts->chip.label = DRIVER_NAME,
+
+ ts->chip.direction_input = max7301_direction_input;
+ ts->chip.get = max7301_get;
+ ts->chip.direction_output = max7301_direction_output;
+ ts->chip.set = max7301_set;
+
+ ts->chip.base = pdata->base;
+ ts->chip.ngpio = PIN_NUMBER;
+ ts->chip.can_sleep = 1;
+ ts->chip.dev = &spi->dev;
+ ts->chip.owner = THIS_MODULE;
+
+ ret = gpiochip_add(&ts->chip);
+ if (ret)
+ goto exit_destroy;
+
+ /*
+ * tristate all pins in hardware and cache the
+ * register values for later use.
+ */
+ for (i = 1; i < 8; i++) {
+ int j;
+ /* 0xAA means input with internal pullup disabled */
+ max7301_write(spi, 0x08 + i, 0xAA);
+ ts->port_config[i] = 0xAA;
+ for (j = 0; j < 4; j++) {
+ int idx = ts->chip.base + (i - 1) * 4 + j;
+ ret = gpio_direction_input(idx);
+ if (ret)
+ goto exit_remove;
+ gpio_free(idx);
+ }
+ }
+ return ret;
+
+exit_remove:
+ gpiochip_remove(&ts->chip);
+exit_destroy:
+ dev_set_drvdata(&spi->dev, NULL);
+ mutex_destroy(&ts->lock);
+ kfree(ts);
+ return ret;
+}
+
+static int max7301_remove(struct spi_device *spi)
+{
+ struct max7301 *ts;
+ int ret;
+
+ ts = dev_get_drvdata(&spi->dev);
+ if (ts == NULL)
+ return -ENODEV;
+
+ dev_set_drvdata(&spi->dev, NULL);
+
+ /* Power down the chip and disable IRQ output */
+ max7301_write(spi, 0x04, 0x00);
+
+ ret = gpiochip_remove(&ts->chip);
+ if (!ret) {
+ mutex_destroy(&ts->lock);
+ kfree(ts);
+ } else
+ dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
+ ret);
+
+ return ret;
+}
+
+static struct spi_driver max7301_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = max7301_probe,
+ .remove = __devexit_p(max7301_remove),
+};
+
+static int __init max7301_init(void)
+{
+ return spi_register_driver(&max7301_driver);
+}
+
+static void __exit max7301_exit(void)
+{
+ spi_unregister_driver(&max7301_driver);
+}
+
+module_init(max7301_init);
+module_exit(max7301_exit);
+
+MODULE_AUTHOR("Juergen Beisert");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MAX7301 SPI based GPIO-Expander");
diff --git a/drivers/gpio/max732x.c b/drivers/gpio/max732x.c
new file mode 100644
index 00000000000..b51c8135ca2
--- /dev/null
+++ b/drivers/gpio/max732x.c
@@ -0,0 +1,385 @@
+/*
+ * max732x.c - I2C Port Expander with 8/16 I/O
+ *
+ * Copyright (C) 2007 Marvell International Ltd.
+ * Copyright (C) 2008 Jack Ren <jack.ren@marvell.com>
+ * Copyright (C) 2008 Eric Miao <eric.miao@marvell.com>
+ *
+ * Derived from drivers/gpio/pca953x.c
+ *
+ * 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; version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/gpio.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c/max732x.h>
+
+
+/*
+ * Each port of MAX732x (including MAX7319) falls into one of the
+ * following three types:
+ *
+ * - Push Pull Output
+ * - Input
+ * - Open Drain I/O
+ *
+ * designated by 'O', 'I' and 'P' individually according to MAXIM's
+ * datasheets.
+ *
+ * There are two groups of I/O ports, each group usually includes
+ * up to 8 I/O ports, and is accessed by a specific I2C address:
+ *
+ * - Group A : by I2C address 0b'110xxxx
+ * - Group B : by I2C address 0b'101xxxx
+ *
+ * where 'xxxx' is decided by the connections of pin AD2/AD0. The
+ * address used also affects the initial state of output signals.
+ *
+ * Within each group of ports, there are five known combinations of
+ * I/O ports: 4I4O, 4P4O, 8I, 8P, 8O, see the definitions below for
+ * the detailed organization of these ports.
+ *
+ * GPIO numbers start from 'gpio_base + 0' to 'gpio_base + 8/16',
+ * and GPIOs from GROUP_A are numbered before those from GROUP_B
+ * (if there are two groups).
+ *
+ * NOTE: MAX7328/MAX7329 are drop-in replacements for PCF8574/a, so
+ * they are not supported by this driver.
+ */
+
+#define PORT_NONE 0x0 /* '/' No Port */
+#define PORT_OUTPUT 0x1 /* 'O' Push-Pull, Output Only */
+#define PORT_INPUT 0x2 /* 'I' Input Only */
+#define PORT_OPENDRAIN 0x3 /* 'P' Open-Drain, I/O */
+
+#define IO_4I4O 0x5AA5 /* O7 O6 I5 I4 I3 I2 O1 O0 */
+#define IO_4P4O 0x5FF5 /* O7 O6 P5 P4 P3 P2 O1 O0 */
+#define IO_8I 0xAAAA /* I7 I6 I5 I4 I3 I2 I1 I0 */
+#define IO_8P 0xFFFF /* P7 P6 P5 P4 P3 P2 P1 P0 */
+#define IO_8O 0x5555 /* O7 O6 O5 O4 O3 O2 O1 O0 */
+
+#define GROUP_A(x) ((x) & 0xffff) /* I2C Addr: 0b'110xxxx */
+#define GROUP_B(x) ((x) << 16) /* I2C Addr: 0b'101xxxx */
+
+static const struct i2c_device_id max732x_id[] = {
+ { "max7319", GROUP_A(IO_8I) },
+ { "max7320", GROUP_B(IO_8O) },
+ { "max7321", GROUP_A(IO_8P) },
+ { "max7322", GROUP_A(IO_4I4O) },
+ { "max7323", GROUP_A(IO_4P4O) },
+ { "max7324", GROUP_A(IO_8I) | GROUP_B(IO_8O) },
+ { "max7325", GROUP_A(IO_8P) | GROUP_B(IO_8O) },
+ { "max7326", GROUP_A(IO_4I4O) | GROUP_B(IO_8O) },
+ { "max7327", GROUP_A(IO_4P4O) | GROUP_B(IO_8O) },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, max732x_id);
+
+struct max732x_chip {
+ struct gpio_chip gpio_chip;
+
+ struct i2c_client *client; /* "main" client */
+ struct i2c_client *client_dummy;
+ struct i2c_client *client_group_a;
+ struct i2c_client *client_group_b;
+
+ unsigned int mask_group_a;
+ unsigned int dir_input;
+ unsigned int dir_output;
+
+ struct mutex lock;
+ uint8_t reg_out[2];
+};
+
+static int max732x_write(struct max732x_chip *chip, int group_a, uint8_t val)
+{
+ struct i2c_client *client;
+ int ret;
+
+ client = group_a ? chip->client_group_a : chip->client_group_b;
+ ret = i2c_smbus_write_byte(client, val);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed writing\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int max732x_read(struct max732x_chip *chip, int group_a, uint8_t *val)
+{
+ struct i2c_client *client;
+ int ret;
+
+ client = group_a ? chip->client_group_a : chip->client_group_b;
+ ret = i2c_smbus_read_byte(client);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed reading\n");
+ return ret;
+ }
+
+ *val = (uint8_t)ret;
+ return 0;
+}
+
+static inline int is_group_a(struct max732x_chip *chip, unsigned off)
+{
+ return (1u << off) & chip->mask_group_a;
+}
+
+static int max732x_gpio_get_value(struct gpio_chip *gc, unsigned off)
+{
+ struct max732x_chip *chip;
+ uint8_t reg_val;
+ int ret;
+
+ chip = container_of(gc, struct max732x_chip, gpio_chip);
+
+ ret = max732x_read(chip, is_group_a(chip, off), &reg_val);
+ if (ret < 0)
+ return 0;
+
+ return reg_val & (1u << (off & 0x7));
+}
+
+static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
+{
+ struct max732x_chip *chip;
+ uint8_t reg_out, mask = 1u << (off & 0x7);
+ int ret;
+
+ chip = container_of(gc, struct max732x_chip, gpio_chip);
+
+ mutex_lock(&chip->lock);
+
+ reg_out = (off > 7) ? chip->reg_out[1] : chip->reg_out[0];
+ reg_out = (val) ? reg_out | mask : reg_out & ~mask;
+
+ ret = max732x_write(chip, is_group_a(chip, off), reg_out);
+ if (ret < 0)
+ goto out;
+
+ /* update the shadow register then */
+ if (off > 7)
+ chip->reg_out[1] = reg_out;
+ else
+ chip->reg_out[0] = reg_out;
+out:
+ mutex_unlock(&chip->lock);
+}
+
+static int max732x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
+{
+ struct max732x_chip *chip;
+ unsigned int mask = 1u << off;
+
+ chip = container_of(gc, struct max732x_chip, gpio_chip);
+
+ if ((mask & chip->dir_input) == 0) {
+ dev_dbg(&chip->client->dev, "%s port %d is output only\n",
+ chip->client->name, off);
+ return -EACCES;
+ }
+
+ return 0;
+}
+
+static int max732x_gpio_direction_output(struct gpio_chip *gc,
+ unsigned off, int val)
+{
+ struct max732x_chip *chip;
+ unsigned int mask = 1u << off;
+
+ chip = container_of(gc, struct max732x_chip, gpio_chip);
+
+ if ((mask & chip->dir_output) == 0) {
+ dev_dbg(&chip->client->dev, "%s port %d is input only\n",
+ chip->client->name, off);
+ return -EACCES;
+ }
+
+ max732x_gpio_set_value(gc, off, val);
+ return 0;
+}
+
+static int __devinit max732x_setup_gpio(struct max732x_chip *chip,
+ const struct i2c_device_id *id,
+ unsigned gpio_start)
+{
+ struct gpio_chip *gc = &chip->gpio_chip;
+ uint32_t id_data = id->driver_data;
+ int i, port = 0;
+
+ for (i = 0; i < 16; i++, id_data >>= 2) {
+ unsigned int mask = 1 << port;
+
+ switch (id_data & 0x3) {
+ case PORT_OUTPUT:
+ chip->dir_output |= mask;
+ break;
+ case PORT_INPUT:
+ chip->dir_input |= mask;
+ break;
+ case PORT_OPENDRAIN:
+ chip->dir_output |= mask;
+ chip->dir_input |= mask;
+ break;
+ default:
+ continue;
+ }
+
+ if (i < 8)
+ chip->mask_group_a |= mask;
+ port++;
+ }
+
+ if (chip->dir_input)
+ gc->direction_input = max732x_gpio_direction_input;
+ if (chip->dir_output) {
+ gc->direction_output = max732x_gpio_direction_output;
+ gc->set = max732x_gpio_set_value;
+ }
+ gc->get = max732x_gpio_get_value;
+ gc->can_sleep = 1;
+
+ gc->base = gpio_start;
+ gc->ngpio = port;
+ gc->label = chip->client->name;
+ gc->owner = THIS_MODULE;
+
+ return port;
+}
+
+static int __devinit max732x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct max732x_platform_data *pdata;
+ struct max732x_chip *chip;
+ struct i2c_client *c;
+ uint16_t addr_a, addr_b;
+ int ret, nr_port;
+
+ pdata = client->dev.platform_data;
+ if (pdata == NULL)
+ return -ENODEV;
+
+ chip = kzalloc(sizeof(struct max732x_chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+ chip->client = client;
+
+ nr_port = max732x_setup_gpio(chip, id, pdata->gpio_base);
+
+ addr_a = (client->addr & 0x0f) | 0x60;
+ addr_b = (client->addr & 0x0f) | 0x50;
+
+ switch (client->addr & 0x70) {
+ case 0x60:
+ chip->client_group_a = client;
+ if (nr_port > 7) {
+ c = i2c_new_dummy(client->adapter, addr_b);
+ chip->client_group_b = chip->client_dummy = c;
+ }
+ break;
+ case 0x50:
+ chip->client_group_b = client;
+ if (nr_port > 7) {
+ c = i2c_new_dummy(client->adapter, addr_a);
+ chip->client_group_a = chip->client_dummy = c;
+ }
+ break;
+ default:
+ dev_err(&client->dev, "invalid I2C address specified %02x\n",
+ client->addr);
+ ret = -EINVAL;
+ goto out_failed;
+ }
+
+ mutex_init(&chip->lock);
+
+ max732x_read(chip, is_group_a(chip, 0), &chip->reg_out[0]);
+ if (nr_port > 7)
+ max732x_read(chip, is_group_a(chip, 8), &chip->reg_out[1]);
+
+ ret = gpiochip_add(&chip->gpio_chip);
+ if (ret)
+ goto out_failed;
+
+ if (pdata->setup) {
+ ret = pdata->setup(client, chip->gpio_chip.base,
+ chip->gpio_chip.ngpio, pdata->context);
+ if (ret < 0)
+ dev_warn(&client->dev, "setup failed, %d\n", ret);
+ }
+
+ i2c_set_clientdata(client, chip);
+ return 0;
+
+out_failed:
+ kfree(chip);
+ return ret;
+}
+
+static int __devexit max732x_remove(struct i2c_client *client)
+{
+ struct max732x_platform_data *pdata = client->dev.platform_data;
+ struct max732x_chip *chip = i2c_get_clientdata(client);
+ int ret;
+
+ if (pdata->teardown) {
+ ret = pdata->teardown(client, chip->gpio_chip.base,
+ chip->gpio_chip.ngpio, pdata->context);
+ if (ret < 0) {
+ dev_err(&client->dev, "%s failed, %d\n",
+ "teardown", ret);
+ return ret;
+ }
+ }
+
+ ret = gpiochip_remove(&chip->gpio_chip);
+ if (ret) {
+ dev_err(&client->dev, "%s failed, %d\n",
+ "gpiochip_remove()", ret);
+ return ret;
+ }
+
+ /* unregister any dummy i2c_client */
+ if (chip->client_dummy)
+ i2c_unregister_device(chip->client_dummy);
+
+ kfree(chip);
+ return 0;
+}
+
+static struct i2c_driver max732x_driver = {
+ .driver = {
+ .name = "max732x",
+ .owner = THIS_MODULE,
+ },
+ .probe = max732x_probe,
+ .remove = __devexit_p(max732x_remove),
+ .id_table = max732x_id,
+};
+
+static int __init max732x_init(void)
+{
+ return i2c_add_driver(&max732x_driver);
+}
+module_init(max732x_init);
+
+static void __exit max732x_exit(void)
+{
+ i2c_del_driver(&max732x_driver);
+}
+module_exit(max732x_exit);
+
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
+MODULE_DESCRIPTION("GPIO expander driver for MAX732X");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c
index 7f92fdd5f0e..8a1b405fefd 100644
--- a/drivers/gpio/mcp23s08.c
+++ b/drivers/gpio/mcp23s08.c
@@ -40,15 +40,26 @@ struct mcp23s08 {
struct spi_device *spi;
u8 addr;
+ u8 cache[11];
/* lock protects the cached values */
struct mutex lock;
- u8 cache[11];
struct gpio_chip chip;
struct work_struct work;
};
+/* A given spi_device can represent up to four mcp23s08 chips
+ * sharing the same chipselect but using different addresses
+ * (e.g. chips #0 and #3 might be populated, but not #1 or $2).
+ * Driver data holds all the per-chip data.
+ */
+struct mcp23s08_driver_data {
+ unsigned ngpio;
+ struct mcp23s08 *mcp[4];
+ struct mcp23s08 chip[];
+};
+
static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
{
u8 tx[2], rx[1];
@@ -208,25 +219,18 @@ done:
/*----------------------------------------------------------------------*/
-static int mcp23s08_probe(struct spi_device *spi)
+static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr,
+ unsigned base, unsigned pullups)
{
- struct mcp23s08 *mcp;
- struct mcp23s08_platform_data *pdata;
+ struct mcp23s08_driver_data *data = spi_get_drvdata(spi);
+ struct mcp23s08 *mcp = data->mcp[addr];
int status;
int do_update = 0;
- pdata = spi->dev.platform_data;
- if (!pdata || pdata->slave > 3 || !pdata->base)
- return -ENODEV;
-
- mcp = kzalloc(sizeof *mcp, GFP_KERNEL);
- if (!mcp)
- return -ENOMEM;
-
mutex_init(&mcp->lock);
mcp->spi = spi;
- mcp->addr = 0x40 | (pdata->slave << 1);
+ mcp->addr = 0x40 | (addr << 1);
mcp->chip.label = "mcp23s08",
@@ -236,26 +240,28 @@ static int mcp23s08_probe(struct spi_device *spi)
mcp->chip.set = mcp23s08_set;
mcp->chip.dbg_show = mcp23s08_dbg_show;
- mcp->chip.base = pdata->base;
+ mcp->chip.base = base;
mcp->chip.ngpio = 8;
mcp->chip.can_sleep = 1;
+ mcp->chip.dev = &spi->dev;
mcp->chip.owner = THIS_MODULE;
- spi_set_drvdata(spi, mcp);
-
- /* verify MCP_IOCON.SEQOP = 0, so sequential reads work */
+ /* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
+ * and MCP_IOCON.HAEN = 1, so we work with all chips.
+ */
status = mcp23s08_read(mcp, MCP_IOCON);
if (status < 0)
goto fail;
- if (status & IOCON_SEQOP) {
+ if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) {
status &= ~IOCON_SEQOP;
+ status |= IOCON_HAEN;
status = mcp23s08_write(mcp, MCP_IOCON, (u8) status);
if (status < 0)
goto fail;
}
/* configure ~100K pullups */
- status = mcp23s08_write(mcp, MCP_GPPU, pdata->pullups);
+ status = mcp23s08_write(mcp, MCP_GPPU, pullups);
if (status < 0)
goto fail;
@@ -282,11 +288,58 @@ static int mcp23s08_probe(struct spi_device *spi)
tx[1] = MCP_IPOL;
memcpy(&tx[2], &mcp->cache[MCP_IPOL], sizeof(tx) - 2);
status = spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
-
- /* FIXME check status... */
+ if (status < 0)
+ goto fail;
}
status = gpiochip_add(&mcp->chip);
+fail:
+ if (status < 0)
+ dev_dbg(&spi->dev, "can't setup chip %d, --> %d\n",
+ addr, status);
+ return status;
+}
+
+static int mcp23s08_probe(struct spi_device *spi)
+{
+ struct mcp23s08_platform_data *pdata;
+ unsigned addr;
+ unsigned chips = 0;
+ struct mcp23s08_driver_data *data;
+ int status;
+ unsigned base;
+
+ pdata = spi->dev.platform_data;
+ if (!pdata || !gpio_is_valid(pdata->base))
+ return -ENODEV;
+
+ for (addr = 0; addr < 4; addr++) {
+ if (!pdata->chip[addr].is_present)
+ continue;
+ chips++;
+ }
+ if (!chips)
+ return -ENODEV;
+
+ data = kzalloc(sizeof *data + chips * sizeof(struct mcp23s08),
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ spi_set_drvdata(spi, data);
+
+ base = pdata->base;
+ for (addr = 0; addr < 4; addr++) {
+ if (!pdata->chip[addr].is_present)
+ continue;
+ chips--;
+ data->mcp[addr] = &data->chip[chips];
+ status = mcp23s08_probe_one(spi, addr, base,
+ pdata->chip[addr].pullups);
+ if (status < 0)
+ goto fail;
+ base += 8;
+ }
+ data->ngpio = base - pdata->base;
/* NOTE: these chips have a relatively sane IRQ framework, with
* per-signal masking and level/edge triggering. It's not yet
@@ -294,8 +347,9 @@ static int mcp23s08_probe(struct spi_device *spi)
*/
if (pdata->setup) {
- status = pdata->setup(spi, mcp->chip.base,
- mcp->chip.ngpio, pdata->context);
+ status = pdata->setup(spi,
+ pdata->base, data->ngpio,
+ pdata->context);
if (status < 0)
dev_dbg(&spi->dev, "setup --> %d\n", status);
}
@@ -303,19 +357,29 @@ static int mcp23s08_probe(struct spi_device *spi)
return 0;
fail:
- kfree(mcp);
+ for (addr = 0; addr < 4; addr++) {
+ int tmp;
+
+ if (!data->mcp[addr])
+ continue;
+ tmp = gpiochip_remove(&data->mcp[addr]->chip);
+ if (tmp < 0)
+ dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
+ }
+ kfree(data);
return status;
}
static int mcp23s08_remove(struct spi_device *spi)
{
- struct mcp23s08 *mcp = spi_get_drvdata(spi);
+ struct mcp23s08_driver_data *data = spi_get_drvdata(spi);
struct mcp23s08_platform_data *pdata = spi->dev.platform_data;
+ unsigned addr;
int status = 0;
if (pdata->teardown) {
status = pdata->teardown(spi,
- mcp->chip.base, mcp->chip.ngpio,
+ pdata->base, data->ngpio,
pdata->context);
if (status < 0) {
dev_err(&spi->dev, "%s --> %d\n", "teardown", status);
@@ -323,11 +387,20 @@ static int mcp23s08_remove(struct spi_device *spi)
}
}
- status = gpiochip_remove(&mcp->chip);
+ for (addr = 0; addr < 4; addr++) {
+ int tmp;
+
+ if (!data->mcp[addr])
+ continue;
+
+ tmp = gpiochip_remove(&data->mcp[addr]->chip);
+ if (tmp < 0) {
+ dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
+ status = tmp;
+ }
+ }
if (status == 0)
- kfree(mcp);
- else
- dev_err(&spi->dev, "%s --> %d\n", "remove", status);
+ kfree(data);
return status;
}
@@ -355,4 +428,3 @@ static void __exit mcp23s08_exit(void)
module_exit(mcp23s08_exit);
MODULE_LICENSE("GPL");
-
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index a380730b61a..cc8468692ae 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -188,6 +188,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
gc->base = chip->gpio_start;
gc->ngpio = gpios;
gc->label = chip->client->name;
+ gc->dev = &chip->client->dev;
gc->owner = THIS_MODULE;
}
diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c
index aa6cc8b2a2b..fc9c6ae739e 100644
--- a/drivers/gpio/pcf857x.c
+++ b/drivers/gpio/pcf857x.c
@@ -37,6 +37,8 @@ static const struct i2c_device_id pcf857x_id[] = {
{ "pca9671", 16 },
{ "pca9673", 16 },
{ "pca9675", 16 },
+ { "max7328", 8 },
+ { "max7329", 8 },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcf857x_id);
@@ -56,6 +58,7 @@ MODULE_DEVICE_TABLE(i2c, pcf857x_id);
struct pcf857x {
struct gpio_chip chip;
struct i2c_client *client;
+ struct mutex lock; /* protect 'out' */
unsigned out; /* software latch */
};
@@ -66,9 +69,14 @@ struct pcf857x {
static int pcf857x_input8(struct gpio_chip *chip, unsigned offset)
{
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
+ int status;
+ mutex_lock(&gpio->lock);
gpio->out |= (1 << offset);
- return i2c_smbus_write_byte(gpio->client, gpio->out);
+ status = i2c_smbus_write_byte(gpio->client, gpio->out);
+ mutex_unlock(&gpio->lock);
+
+ return status;
}
static int pcf857x_get8(struct gpio_chip *chip, unsigned offset)
@@ -84,12 +92,17 @@ static int pcf857x_output8(struct gpio_chip *chip, unsigned offset, int value)
{
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
unsigned bit = 1 << offset;
+ int status;
+ mutex_lock(&gpio->lock);
if (value)
gpio->out |= bit;
else
gpio->out &= ~bit;
- return i2c_smbus_write_byte(gpio->client, gpio->out);
+ status = i2c_smbus_write_byte(gpio->client, gpio->out);
+ mutex_unlock(&gpio->lock);
+
+ return status;
}
static void pcf857x_set8(struct gpio_chip *chip, unsigned offset, int value)
@@ -124,9 +137,14 @@ static int i2c_read_le16(struct i2c_client *client)
static int pcf857x_input16(struct gpio_chip *chip, unsigned offset)
{
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
+ int status;
+ mutex_lock(&gpio->lock);
gpio->out |= (1 << offset);
- return i2c_write_le16(gpio->client, gpio->out);
+ status = i2c_write_le16(gpio->client, gpio->out);
+ mutex_unlock(&gpio->lock);
+
+ return status;
}
static int pcf857x_get16(struct gpio_chip *chip, unsigned offset)
@@ -142,12 +160,17 @@ static int pcf857x_output16(struct gpio_chip *chip, unsigned offset, int value)
{
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
unsigned bit = 1 << offset;
+ int status;
+ mutex_lock(&gpio->lock);
if (value)
gpio->out |= bit;
else
gpio->out &= ~bit;
- return i2c_write_le16(gpio->client, gpio->out);
+ status = i2c_write_le16(gpio->client, gpio->out);
+ mutex_unlock(&gpio->lock);
+
+ return status;
}
static void pcf857x_set16(struct gpio_chip *chip, unsigned offset, int value)
@@ -173,8 +196,11 @@ static int pcf857x_probe(struct i2c_client *client,
if (!gpio)
return -ENOMEM;
+ mutex_init(&gpio->lock);
+
gpio->chip.base = pdata->gpio_base;
gpio->chip.can_sleep = 1;
+ gpio->chip.dev = &client->dev;
gpio->chip.owner = THIS_MODULE;
/* NOTE: the OnSemi jlc1562b is also largely compatible with
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index f43d6d3cf2f..426ac5add58 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -780,7 +780,7 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
*/
static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
{
- __le64 x;
+ u64 x;
u64 m = (1ULL << n) - 1;
if (n > 32)
@@ -796,10 +796,10 @@ static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u3
report += offset >> 3;
offset &= 7;
- x = get_unaligned((__le64 *)report);
- x &= cpu_to_le64(~(m << offset));
- x |= cpu_to_le64(((u64) value) << offset);
- put_unaligned(x, (__le64 *) report);
+ x = get_unaligned_le64(report);
+ x &= ~(m << offset);
+ x |= ((u64)value) << offset;
+ put_unaligned_le64(x, report);
}
/*
diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c
index 4c2052c658f..16feea01449 100644
--- a/drivers/hid/hid-input-quirks.c
+++ b/drivers/hid/hid-input-quirks.c
@@ -89,6 +89,29 @@ static int quirk_logitech_ultrax_remote(struct hid_usage *usage, struct input_de
return 1;
}
+static int quirk_gyration_remote(struct hid_usage *usage, struct input_dev *input,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
+ return 0;
+
+ set_bit(EV_REP, input->evbit);
+ switch(usage->hid & HID_USAGE) {
+ /* Reported on Gyration MCE Remote */
+ case 0x00d: map_key_clear(KEY_HOME); break;
+ case 0x024: map_key_clear(KEY_DVD); break;
+ case 0x025: map_key_clear(KEY_PVR); break;
+ case 0x046: map_key_clear(KEY_MEDIA); break;
+ case 0x047: map_key_clear(KEY_MP3); break;
+ case 0x049: map_key_clear(KEY_CAMERA); break;
+ case 0x04a: map_key_clear(KEY_VIDEO); break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev *input,
unsigned long **bit, int *max)
{
@@ -303,6 +326,9 @@ static int quirk_sunplus_wdesktop(struct hid_usage *usage, struct input_dev *inp
#define VENDOR_ID_EZKEY 0x0518
#define DEVICE_ID_BTC_8193 0x0002
+#define VENDOR_ID_GYRATION 0x0c16
+#define DEVICE_ID_GYRATION_REMOTE 0x0002
+
#define VENDOR_ID_LOGITECH 0x046d
#define DEVICE_ID_LOGITECH_RECEIVER 0xc101
#define DEVICE_ID_S510_RECEIVER 0xc50c
@@ -337,6 +363,8 @@ static const struct hid_input_blacklist {
{ VENDOR_ID_EZKEY, DEVICE_ID_BTC_8193, quirk_btc_8193 },
+ { VENDOR_ID_GYRATION, DEVICE_ID_GYRATION_REMOTE, quirk_gyration_remote },
+
{ VENDOR_ID_LOGITECH, DEVICE_ID_LOGITECH_RECEIVER, quirk_logitech_ultrax_remote },
{ VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER, quirk_logitech_wireless },
{ VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER_2, quirk_logitech_wireless },
@@ -438,6 +466,18 @@ int hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struc
input_event(input, usage->type, REL_WHEEL, -value);
return 1;
}
+
+ /* Gyration MCE remote "Sleep" key */
+ if (hid->vendor == VENDOR_ID_GYRATION &&
+ hid->product == DEVICE_ID_GYRATION_REMOTE &&
+ (usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK &&
+ (usage->hid & 0xff) == 0x82) {
+ input_event(input, usage->type, usage->code, 1);
+ input_sync(input);
+ input_event(input, usage->type, usage->code, 0);
+ input_sync(input);
+ return 1;
+ }
return 0;
}
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 5c52a20ad34..1b2e8dc3398 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -100,6 +100,8 @@ static struct hidinput_key_translation apple_fn_keys[] = {
{ KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
{ KEY_F3, KEY_FN_F5, APPLE_FLAG_FKEY }, /* Exposé */
{ KEY_F4, KEY_FN_F4, APPLE_FLAG_FKEY }, /* Dashboard */
+ { KEY_F5, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY },
+ { KEY_F6, KEY_KBDILLUMUP, APPLE_FLAG_FKEY },
{ KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY },
{ KEY_F8, KEY_PLAYPAUSE, APPLE_FLAG_FKEY },
{ KEY_F9, KEY_NEXTSONG, APPLE_FLAG_FKEY },
@@ -612,6 +614,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x0b6: map_key_clear(KEY_PREVIOUSSONG); break;
case 0x0b7: map_key_clear(KEY_STOPCD); break;
case 0x0b8: map_key_clear(KEY_EJECTCD); break;
+ case 0x0bc: map_key_clear(KEY_MEDIA_REPEAT); break;
case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break;
case 0x0e0: map_abs_clear(ABS_VOLUME); break;
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 2fde6c63f47..c40f0403eda 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -105,6 +105,7 @@ out:
static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
unsigned int minor = iminor(file->f_path.dentry->d_inode);
+ /* FIXME: What stops hidraw_table going NULL */
struct hid_device *dev = hidraw_table[minor]->hid;
__u8 *buf;
int ret = 0;
@@ -211,38 +212,43 @@ static int hidraw_release(struct inode * inode, struct file * file)
kfree(list->hidraw);
}
+ kfree(list);
+
return 0;
}
-static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long hidraw_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
+ struct inode *inode = file->f_path.dentry->d_inode;
unsigned int minor = iminor(inode);
+ long ret = 0;
+ /* FIXME: What stops hidraw_table going NULL */
struct hidraw *dev = hidraw_table[minor];
void __user *user_arg = (void __user*) arg;
+ lock_kernel();
switch (cmd) {
case HIDIOCGRDESCSIZE:
if (put_user(dev->hid->rsize, (int __user *)arg))
- return -EFAULT;
- return 0;
+ ret = -EFAULT;
+ break;
case HIDIOCGRDESC:
{
__u32 len;
if (get_user(len, (int __user *)arg))
- return -EFAULT;
-
- if (len > HID_MAX_DESCRIPTOR_SIZE - 1)
- return -EINVAL;
-
- if (copy_to_user(user_arg + offsetof(
- struct hidraw_report_descriptor,
- value[0]),
- dev->hid->rdesc,
- min(dev->hid->rsize, len)))
- return -EFAULT;
- return 0;
+ ret = -EFAULT;
+ else if (len > HID_MAX_DESCRIPTOR_SIZE - 1)
+ ret = -EINVAL;
+ else if (copy_to_user(user_arg + offsetof(
+ struct hidraw_report_descriptor,
+ value[0]),
+ dev->hid->rdesc,
+ min(dev->hid->rsize, len)))
+ ret = -EFAULT;
+ break;
}
case HIDIOCGRAWINFO:
{
@@ -252,15 +258,13 @@ static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd
dinfo.vendor = dev->hid->vendor;
dinfo.product = dev->hid->product;
if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
- return -EFAULT;
-
- return 0;
+ ret = -EFAULT;
+ break;
}
default:
- printk(KERN_EMERG "hidraw: unsupported ioctl() %x\n",
- cmd);
+ ret = -ENOTTY;
}
- return -EINVAL;
+ return ret;
}
static const struct file_operations hidraw_ops = {
@@ -270,7 +274,7 @@ static const struct file_operations hidraw_ops = {
.poll = hidraw_poll,
.open = hidraw_open,
.release = hidraw_release,
- .ioctl = hidraw_ioctl,
+ .unlocked_ioctl = hidraw_ioctl,
};
void hidraw_report_event(struct hid_device *hid, u8 *data, int len)
@@ -322,8 +326,9 @@ int hidraw_connect(struct hid_device *hid)
goto out;
}
- dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor),
- "%s%d", "hidraw", minor);
+ dev->dev = device_create_drvdata(hidraw_class, NULL,
+ MKDEV(hidraw_major, minor), NULL,
+ "%s%d", "hidraw", minor);
if (IS_ERR(dev->dev)) {
spin_lock(&minors_lock);
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 1df832a8fcb..61e78a4369b 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -69,12 +69,18 @@
#define USB_DEVICE_ID_APPLE_ALU_ANSI 0x0220
#define USB_DEVICE_ID_APPLE_ALU_ISO 0x0221
#define USB_DEVICE_ID_APPLE_ALU_JIS 0x0222
+#define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI 0x0223
+#define USB_DEVICE_ID_APPLE_WELLSPRING_ISO 0x0224
+#define USB_DEVICE_ID_APPLE_WELLSPRING_JIS 0x0225
#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI 0x0229
#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO 0x022a
#define USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS 0x022b
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI 0x022c
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO 0x022d
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS 0x022e
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232
#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
#define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242
@@ -241,6 +247,8 @@
#define USB_DEVICE_ID_LD_MACHINETEST 0x2040
#define USB_VENDOR_ID_LOGITECH 0x046d
+#define USB_DEVICE_ID_LOGITECH_LX3 0xc044
+#define USB_DEVICE_ID_LOGITECH_V150 0xc047
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
#define USB_DEVICE_ID_LOGITECH_HARMONY 0xc110
#define USB_DEVICE_ID_LOGITECH_HARMONY_2 0xc111
@@ -314,6 +322,7 @@
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
+#define USB_DEVICE_ID_DINOVO_DESKTOP 0xc704
#define USB_DEVICE_ID_DINOVO_EDGE 0xc714
#define USB_DEVICE_ID_DINOVO_MINI 0xc71f
@@ -443,7 +452,8 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
-
+
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP, HID_QUIRK_DUPLICATE_USAGES },
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI, HID_QUIRK_DUPLICATE_USAGES },
@@ -593,6 +603,8 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3, HID_QUIRK_INVERT_HWHEEL },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150, HID_QUIRK_INVERT_HWHEEL },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K, HID_QUIRK_MICROSOFT_KEYS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K, HID_QUIRK_MICROSOFT_KEYS },
@@ -642,6 +654,12 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, HID_QUIRK_APPLE_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS, HID_QUIRK_APPLE_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, HID_QUIRK_APPLE_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, HID_QUIRK_APPLE_HAS_FN },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
@@ -1128,7 +1146,7 @@ static void usbhid_fixup_microsoft_descriptor(unsigned char *rdesc, int rsize)
&& rdesc[557] == 0x19
&& rdesc[559] == 0x29) {
printk(KERN_INFO "Fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
- rdesc[284] = rdesc[304] = rdesc[558] = 0x35;
+ rdesc[284] = rdesc[304] = rdesc[557] = 0x35;
rdesc[352] = 0x36;
rdesc[286] = rdesc[355] = 0x46;
rdesc[306] = rdesc[559] = 0x45;
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 95cc192bc7a..842e9edb888 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -406,6 +406,7 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL);
if (!uref_multi)
return -ENOMEM;
+ lock_kernel();
uref = &uref_multi->uref;
if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
if (copy_from_user(uref_multi, user_arg,
@@ -501,12 +502,15 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
}
goodreturn:
+ unlock_kernel();
kfree(uref_multi);
return 0;
fault:
+ unlock_kernel();
kfree(uref_multi);
return -EFAULT;
inval:
+ unlock_kernel();
kfree(uref_multi);
return -EINVAL;
}
@@ -540,7 +544,7 @@ static noinline int hiddev_ioctl_string(struct hiddev *hiddev, unsigned int cmd,
return len;
}
-static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct hiddev_list *list = file->private_data;
struct hiddev *hiddev = list->hiddev;
@@ -555,7 +559,10 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
struct usbhid_device *usbhid = hid->driver_data;
void __user *user_arg = (void __user *)arg;
int i;
+
+ /* Called without BKL by compat methods so no BKL taken */
+ /* FIXME: Who or what stop this racing with a disconnect ?? */
if (!hiddev->exist)
return -EIO;
@@ -756,8 +763,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
#ifdef CONFIG_COMPAT
static long hiddev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct inode *inode = file->f_path.dentry->d_inode;
- return hiddev_ioctl(inode, file, cmd, (unsigned long)compat_ptr(arg));
+ return hiddev_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
}
#endif
@@ -768,7 +774,7 @@ static const struct file_operations hiddev_fops = {
.poll = hiddev_poll,
.open = hiddev_open,
.release = hiddev_release,
- .ioctl = hiddev_ioctl,
+ .unlocked_ioctl = hiddev_ioctl,
.fasync = hiddev_fasync,
#ifdef CONFIG_COMPAT
.compat_ioctl = hiddev_compat_ioctl,
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
index 3cd46d2e53c..0caaafe0184 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -43,7 +43,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);
-static unsigned char usb_kbd_keycode[256] = {
+static const unsigned char usb_kbd_keycode[256] = {
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
@@ -233,14 +233,6 @@ static int usb_kbd_probe(struct usb_interface *iface,
if (!usb_endpoint_is_int_in(endpoint))
return -ENODEV;
-#ifdef CONFIG_USB_HID
- if (usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
- le16_to_cpu(dev->descriptor.idProduct))
- & HID_QUIRK_IGNORE) {
- return -ENODEV;
- }
-#endif
-
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c
index 703e9d0e871..35689ef172c 100644
--- a/drivers/hid/usbhid/usbmouse.c
+++ b/drivers/hid/usbhid/usbmouse.c
@@ -129,14 +129,6 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
if (!usb_endpoint_is_int_in(endpoint))
return -ENODEV;
-#ifdef CONFIG_USB_HID
- if (usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
- le16_to_cpu(dev->descriptor.idProduct))
- & (HID_QUIRK_IGNORE|HID_QUIRK_IGNORE_MOUSE)) {
- return -ENODEV;
- }
-#endif
-
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 3db28450a3b..7321a88a511 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -55,7 +55,8 @@ again:
return ERR_PTR(err);
id = id & MAX_ID_MASK;
- hwdev = device_create(hwmon_class, dev, MKDEV(0,0), HWMON_ID_FORMAT, id);
+ hwdev = device_create_drvdata(hwmon_class, dev, MKDEV(0, 0), NULL,
+ HWMON_ID_FORMAT, id);
if (IS_ERR(hwdev)) {
spin_lock(&idr_lock);
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 50e0a465374..a95cb9465d6 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -126,7 +126,7 @@ config ISP1301_OMAP
config TPS65010
tristate "TPS6501x Power Management chips"
- depends on HAVE_GPIO_LIB
+ depends on GPIOLIB
default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
help
If you say yes here you get support for the TPS6501x series of
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index 85949685191..cf02e8fceb4 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -636,6 +636,8 @@ static int tps65010_probe(struct i2c_client *client,
tps->outmask = board->outmask;
tps->chip.label = client->name;
+ tps->chip.dev = &client->dev;
+ tps->chip.owner = THIS_MODULE;
tps->chip.set = tps65010_gpio_set;
tps->chip.direction_output = tps65010_output;
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 7608df83d6d..7bf38c41808 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -722,7 +722,8 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
INIT_LIST_HEAD(&driver->clients);
/* Walk the adapters that are already present */
- class_for_each_device(&i2c_adapter_class, driver, __attach_adapter);
+ class_for_each_device(&i2c_adapter_class, NULL, driver,
+ __attach_adapter);
mutex_unlock(&core_lock);
return 0;
@@ -782,7 +783,8 @@ void i2c_del_driver(struct i2c_driver *driver)
{
mutex_lock(&core_lock);
- class_for_each_device(&i2c_adapter_class, driver, __detach_adapter);
+ class_for_each_device(&i2c_adapter_class, NULL, driver,
+ __detach_adapter);
driver_unregister(&driver->driver);
pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 86727fa8858..9d55c6383b2 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -521,9 +521,9 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
return PTR_ERR(i2c_dev);
/* register this i2c device with the driver core */
- i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
- MKDEV(I2C_MAJOR, adap->nr),
- "i2c-%d", adap->nr);
+ i2c_dev->dev = device_create_drvdata(i2c_dev_class, &adap->dev,
+ MKDEV(I2C_MAJOR, adap->nr),
+ NULL, "i2c-%d", adap->nr);
if (IS_ERR(i2c_dev->dev)) {
res = PTR_ERR(i2c_dev->dev);
goto error;
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 15b09b89588..130ef64b44f 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -314,7 +314,7 @@ comment "IDE chipset support/bugfixes"
config IDE_GENERIC
tristate "generic/default IDE chipset support"
- depends on ALPHA || X86 || IA64 || M32R || MIPS || PPC32
+ depends on ALPHA || X86 || IA64 || M32R || MIPS
help
If unsure, say N.
@@ -510,6 +510,7 @@ config BLK_DEV_TRIFLEX
config BLK_DEV_CY82C693
tristate "CY82C693 chipset support"
+ depends on ALPHA
select IDE_TIMINGS
select BLK_DEV_IDEDMA_PCI
help
@@ -548,6 +549,7 @@ config BLK_DEV_CS5535
config BLK_DEV_HPT34X
tristate "HPT34X chipset support"
+ depends on BROKEN
select BLK_DEV_IDEDMA_PCI
help
This driver adds up to 4 more EIDE devices sharing a single
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 5d414e301a5..64e0ecdc4ed 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -1,13 +1,6 @@
#
-# Makefile for the kernel ata, atapi, and ide block device drivers.
-#
-# 12 September 2000, Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
-# Rewritten to use lists instead of if-statements.
-#
-# Note : at this point, these files are compiled on all systems.
-# In the future, some of these should be built conditionally.
-#
# link order is important here
+#
EXTRA_CFLAGS += -Idrivers/ide
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 52f58c88578..df4af408395 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -72,7 +72,7 @@ struct icside_state {
void __iomem *ioc_base;
unsigned int sel;
unsigned int type;
- ide_hwif_t *hwif[2];
+ struct ide_host *host;
};
#define ICS_TYPE_A3IN 0
@@ -375,12 +375,14 @@ static int icside_dma_test_irq(ide_drive_t *drive)
static void icside_dma_timeout(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
+
printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
if (icside_dma_test_irq(drive))
return;
- ide_dump_status(drive, "DMA timeout", ide_read_status(drive));
+ ide_dump_status(drive, "DMA timeout", hwif->tp_ops->read_status(hwif));
icside_dma_end(drive);
}
@@ -440,10 +442,10 @@ static void icside_setup_ports(hw_regs_t *hw, void __iomem *base,
static int __init
icside_register_v5(struct icside_state *state, struct expansion_card *ec)
{
- ide_hwif_t *hwif;
void __iomem *base;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw;
+ struct ide_host *host;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+ int ret;
base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
if (!base)
@@ -463,22 +465,23 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec);
- hwif = ide_find_port();
- if (!hwif)
+ host = ide_host_alloc(NULL, hws);
+ if (host == NULL)
return -ENODEV;
- ide_init_port_hw(hwif, &hw);
- default_hwif_mmiops(hwif);
-
- state->hwif[0] = hwif;
+ state->host = host;
ecard_set_drvdata(ec, state);
- idx[0] = hwif->index;
-
- ide_device_add(idx, NULL);
+ ret = ide_host_register(host, NULL, hws);
+ if (ret)
+ goto err_free;
return 0;
+err_free:
+ ide_host_free(host);
+ ecard_set_drvdata(ec, NULL);
+ return ret;
}
static const struct ide_port_info icside_v6_port_info __initdata = {
@@ -493,13 +496,12 @@ static const struct ide_port_info icside_v6_port_info __initdata = {
static int __init
icside_register_v6(struct icside_state *state, struct expansion_card *ec)
{
- ide_hwif_t *hwif, *mate;
void __iomem *ioc_base, *easi_base;
+ struct ide_host *host;
unsigned int sel = 0;
int ret;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw[2], *hws[] = { &hw[0], NULL, NULL, NULL };
struct ide_port_info d = icside_v6_port_info;
- hw_regs_t hw[2];
ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
if (!ioc_base) {
@@ -538,28 +540,11 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec);
icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec);
- /*
- * Find and register the interfaces.
- */
- hwif = ide_find_port();
- if (hwif == NULL)
+ host = ide_host_alloc(&d, hws);
+ if (host == NULL)
return -ENODEV;
- ide_init_port_hw(hwif, &hw[0]);
- default_hwif_mmiops(hwif);
-
- idx[0] = hwif->index;
-
- mate = ide_find_port();
- if (mate) {
- ide_init_port_hw(mate, &hw[1]);
- default_hwif_mmiops(mate);
-
- idx[1] = mate->index;
- }
-
- state->hwif[0] = hwif;
- state->hwif[1] = mate;
+ state->host = host;
ecard_set_drvdata(ec, state);
@@ -569,11 +554,17 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
d.dma_ops = NULL;
}
- ide_device_add(idx, &d);
+ ret = ide_host_register(host, NULL, hws);
+ if (ret)
+ goto err_free;
return 0;
-
- out:
+err_free:
+ ide_host_free(host);
+ if (d.dma_ops)
+ free_dma(ec->dma);
+ ecard_set_drvdata(ec, NULL);
+out:
return ret;
}
@@ -719,8 +710,14 @@ static int __init icside_init(void)
return ecard_register_driver(&icside_driver);
}
+static void __exit icside_exit(void);
+{
+ ecard_unregister_driver(&icside_driver);
+}
+
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("ICS IDE driver");
module_init(icside_init);
+module_exit(icside_exit);
diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c
index 2f311da4c96..176532ffae0 100644
--- a/drivers/ide/arm/ide_arm.c
+++ b/drivers/ide/arm/ide_arm.c
@@ -28,10 +28,8 @@
static int __init ide_arm_init(void)
{
- ide_hwif_t *hwif;
- hw_regs_t hw;
unsigned long base = IDE_ARM_IO, ctl = IDE_ARM_IO + 0x206;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
if (!request_region(base, 8, DRV_NAME)) {
printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
@@ -51,15 +49,7 @@ static int __init ide_arm_init(void)
hw.irq = IDE_ARM_IRQ;
hw.chipset = ide_generic;
- hwif = ide_find_port();
- if (hwif) {
- ide_init_port_hw(hwif, &hw);
- idx[0] = hwif->index;
-
- ide_device_add(idx, NULL);
- }
-
- return 0;
+ return ide_host_add(NULL, hws, NULL);
}
module_init(ide_arm_init);
diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c
index c79b85b6e4a..3e842d60eae 100644
--- a/drivers/ide/arm/palm_bk3710.c
+++ b/drivers/ide/arm/palm_bk3710.c
@@ -82,6 +82,7 @@ static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
{100, 120}, /* UDMA Mode 2 */
{100, 90}, /* UDMA Mode 3 */
{100, 60}, /* UDMA Mode 4 */
+ {85, 40}, /* UDMA Mode 5 */
};
static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
@@ -316,15 +317,14 @@ static u8 __devinit palm_bk3710_cable_detect(ide_hwif_t *hwif)
static int __devinit palm_bk3710_init_dma(ide_hwif_t *hwif,
const struct ide_port_info *d)
{
- unsigned long base =
- hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET;
-
printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name);
if (ide_allocate_dma_engine(hwif))
return -1;
- ide_setup_dma(hwif, base);
+ hwif->dma_base = hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET;
+
+ hwif->dma_ops = &sff_dma_ops;
return 0;
}
@@ -335,12 +335,11 @@ static const struct ide_port_ops palm_bk3710_ports_ops = {
.cable_detect = palm_bk3710_cable_detect,
};
-static const struct ide_port_info __devinitdata palm_bk3710_port_info = {
+static struct ide_port_info __devinitdata palm_bk3710_port_info = {
.init_dma = palm_bk3710_init_dma,
.port_ops = &palm_bk3710_ports_ops,
.host_flags = IDE_HFLAG_MMIO,
.pio_mask = ATA_PIO4,
- .udma_mask = ATA_UDMA4, /* (input clk 99MHz) */
.mwdma_mask = ATA_MWDMA2,
};
@@ -348,13 +347,12 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
{
struct clk *clk;
struct resource *mem, *irq;
- ide_hwif_t *hwif;
+ struct ide_host *host;
unsigned long base, rate;
- int i;
- hw_regs_t hw;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ int i, rc;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
- clk = clk_get(NULL, "IDECLK");
+ clk = clk_get(&pdev->dev, "IDECLK");
if (IS_ERR(clk))
return -ENODEV;
@@ -394,24 +392,17 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
hw.irq = irq->start;
hw.chipset = ide_palm3710;
- hwif = ide_find_port();
- if (hwif == NULL)
- goto out;
-
- i = hwif->index;
+ palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 :
+ ATA_UDMA5;
- ide_init_port_hw(hwif, &hw);
-
- default_hwif_mmiops(hwif);
-
- idx[0] = i;
-
- ide_device_add(idx, &palm_bk3710_port_info);
+ rc = ide_host_add(&palm_bk3710_port_info, hws, NULL);
+ if (rc)
+ goto out;
return 0;
out:
printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
- return -ENODEV;
+ return rc;
}
/* work with hotplug and coldplug */
diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
index 43057e0303c..78d27d9ae43 100644
--- a/drivers/ide/arm/rapide.c
+++ b/drivers/ide/arm/rapide.c
@@ -32,11 +32,10 @@ static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base,
static int __devinit
rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
{
- ide_hwif_t *hwif;
void __iomem *base;
+ struct ide_host *host;
int ret;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
ret = ecard_request_resources(ec);
if (ret)
@@ -53,20 +52,11 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
hw.chipset = ide_generic;
hw.dev = &ec->dev;
- hwif = ide_find_port();
- if (hwif == NULL) {
- ret = -ENOENT;
+ ret = ide_host_add(&rapide_port_info, hws, &host);
+ if (ret)
goto release;
- }
-
- ide_init_port_hw(hwif, &hw);
- default_hwif_mmiops(hwif);
-
- idx[0] = hwif->index;
- ide_device_add(idx, &rapide_port_info);
-
- ecard_set_drvdata(ec, hwif);
+ ecard_set_drvdata(ec, host);
goto out;
release:
@@ -77,11 +67,11 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
static void __devexit rapide_remove(struct expansion_card *ec)
{
- ide_hwif_t *hwif = ecard_get_drvdata(ec);
+ struct ide_host *host = ecard_get_drvdata(ec);
ecard_set_drvdata(ec, NULL);
- ide_unregister(hwif);
+ ide_host_remove(host);
ecard_release_resources(ec);
}
@@ -105,7 +95,13 @@ static int __init rapide_init(void)
return ecard_register_driver(&rapide_driver);
}
+static void __exit rapide_exit(void)
+{
+ ecard_unregister_driver(&rapide_driver);
+}
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Yellowstone RAPIDE driver");
module_init(rapide_init);
+module_exit(rapide_exit);
diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c
index 20fad6d542c..bde7a585f19 100644
--- a/drivers/ide/h8300/ide-h8300.c
+++ b/drivers/ide/h8300/ide-h8300.c
@@ -100,6 +100,8 @@ static void h8300_tf_read(ide_drive_t *drive, ide_task_t *task)
/* be sure we're looking at the low order bits */
outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+ tf->feature = inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
@@ -153,6 +155,21 @@ static void h8300_output_data(ide_drive_t *drive, struct request *rq,
mm_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
}
+static const struct ide_tp_ops h8300_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = h8300_tf_load,
+ .tf_read = h8300_tf_read,
+
+ .input_data = h8300_input_data,
+ .output_data = h8300_output_data,
+};
+
#define H8300_IDE_GAP (2)
static inline void hw_setup(hw_regs_t *hw)
@@ -167,27 +184,14 @@ static inline void hw_setup(hw_regs_t *hw)
hw->chipset = ide_generic;
}
-static inline void hwif_setup(ide_hwif_t *hwif)
-{
- default_hwif_iops(hwif);
-
- hwif->tf_load = h8300_tf_load;
- hwif->tf_read = h8300_tf_read;
-
- hwif->input_data = h8300_input_data;
- hwif->output_data = h8300_output_data;
-}
-
static const struct ide_port_info h8300_port_info = {
+ .tp_ops = &h8300_tp_ops,
.host_flags = IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA,
};
static int __init h8300_ide_init(void)
{
- hw_regs_t hw;
- ide_hwif_t *hwif;
- int index;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n");
@@ -200,19 +204,7 @@ static int __init h8300_ide_init(void)
hw_setup(&hw);
- hwif = ide_find_port_slot(&h8300_port_info);
- if (hwif == NULL)
- return -ENOENT;
-
- index = hwif->index;
- ide_init_port_hw(hwif, &hw);
- hwif_setup(hwif);
-
- idx[0] = index;
-
- ide_device_add(idx, &h8300_port_info);
-
- return 0;
+ return ide_host_add(&h8300_port_info, hws, NULL);
out_busy:
printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n");
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 2802031de67..adf04f99cde 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -22,6 +22,8 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
void (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned, int))
{
ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->hwgroup->rq;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
xfer_func_t *xferfunc;
unsigned int temp;
u16 bcount;
@@ -30,12 +32,12 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
debug_log("Enter %s - interrupt handler\n", __func__);
if (pc->flags & PC_FLAG_TIMEDOUT) {
- pc->callback(drive);
+ drive->pc_callback(drive);
return ide_stopped;
}
/* Clear the interrupt */
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
if (hwif->dma_ops->dma_end(drive) ||
@@ -63,8 +65,9 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
local_irq_enable_in_hardirq();
if (drive->media == ide_tape && !scsi &&
- (stat & ERR_STAT) && pc->c[0] == REQUEST_SENSE)
+ (stat & ERR_STAT) && rq->cmd[0] == REQUEST_SENSE)
stat &= ~ERR_STAT;
+
if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) {
/* Error detected */
debug_log("%s: I/O error\n", drive->name);
@@ -75,16 +78,17 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
goto cmd_finished;
}
- if (pc->c[0] == REQUEST_SENSE) {
+ if (rq->cmd[0] == REQUEST_SENSE) {
printk(KERN_ERR "%s: I/O error in request sense"
" command\n", drive->name);
return ide_do_reset(drive);
}
- debug_log("[cmd %x]: check condition\n", pc->c[0]);
+ debug_log("[cmd %x]: check condition\n", rq->cmd[0]);
/* Retry operation */
retry_pc(drive);
+
/* queued, but not started */
return ide_stopped;
}
@@ -95,8 +99,10 @@ cmd_finished:
dsc_handle(drive);
return ide_stopped;
}
+
/* Command finished - Call the callback function */
- pc->callback(drive);
+ drive->pc_callback(drive);
+
return ide_stopped;
}
@@ -107,16 +113,15 @@ cmd_finished:
ide_dma_off(drive);
return ide_do_reset(drive);
}
- /* Get the number of bytes to transfer on this interrupt. */
- bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) |
- hwif->INB(hwif->io_ports.lbam_addr);
- ireason = hwif->INB(hwif->io_ports.nsect_addr);
+ /* Get the number of bytes to transfer on this interrupt. */
+ ide_read_bcount_and_ireason(drive, &bcount, &ireason);
if (ireason & CD) {
printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__);
return ide_do_reset(drive);
}
+
if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) {
/* Hopefully, we will never get here */
printk(KERN_ERR "%s: We wanted to %s, but the device wants us "
@@ -125,6 +130,7 @@ cmd_finished:
(ireason & IO) ? "Read" : "Write");
return ide_do_reset(drive);
}
+
if (!(pc->flags & PC_FLAG_WRITING)) {
/* Reading - Check that we have enough space */
temp = pc->xferred + bcount;
@@ -142,7 +148,7 @@ cmd_finished:
if (pc->sg)
io_buffers(drive, pc, temp, 0);
else
- hwif->input_data(drive, NULL,
+ tp_ops->input_data(drive, NULL,
pc->cur_pos, temp);
printk(KERN_ERR "%s: transferred %d of "
"%d bytes\n",
@@ -159,9 +165,9 @@ cmd_finished:
debug_log("The device wants to send us more data than "
"expected - allowing transfer\n");
}
- xferfunc = hwif->input_data;
+ xferfunc = tp_ops->input_data;
} else
- xferfunc = hwif->output_data;
+ xferfunc = tp_ops->output_data;
if ((drive->media == ide_floppy && !scsi && !pc->buf) ||
(drive->media == ide_tape && !scsi && pc->bh) ||
@@ -175,7 +181,7 @@ cmd_finished:
pc->cur_pos += bcount;
debug_log("[cmd %x] transferred %d bytes on that intr.\n",
- pc->c[0], bcount);
+ rq->cmd[0], bcount);
/* And set the interrupt handler again */
ide_set_handler(drive, handler, timeout, expiry);
@@ -183,16 +189,27 @@ cmd_finished:
}
EXPORT_SYMBOL_GPL(ide_pc_intr);
+static u8 ide_read_ireason(ide_drive_t *drive)
+{
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_IN_NSECT;
+
+ drive->hwif->tp_ops->tf_read(drive, &task);
+
+ return task.tf.nsect & 3;
+}
+
static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
{
- ide_hwif_t *hwif = drive->hwif;
int retries = 100;
while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
"a packet command, retrying\n", drive->name);
udelay(100);
- ireason = hwif->INB(hwif->io_ports.nsect_addr);
+ ireason = ide_read_ireason(drive);
if (retries == 0) {
printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
"a packet command, ignoring\n",
@@ -210,6 +227,7 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
ide_expiry_t *expiry)
{
ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->hwgroup->rq;
ide_startstop_t startstop;
u8 ireason;
@@ -219,7 +237,7 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
return startstop;
}
- ireason = hwif->INB(hwif->io_ports.nsect_addr);
+ ireason = ide_read_ireason(drive);
if (drive->media == ide_tape && !drive->scsi)
ireason = ide_wait_ireason(drive, ireason);
@@ -239,8 +257,8 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
}
/* Send the actual packet */
- if ((pc->flags & PC_FLAG_ZIP_DRIVE) == 0)
- hwif->output_data(drive, NULL, pc->c, 12);
+ if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0)
+ hwif->tp_ops->output_data(drive, NULL, rq->cmd, 12);
return ide_started;
}
@@ -284,7 +302,7 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
bcount, dma);
/* Issue the packet command */
- if (pc->flags & PC_FLAG_DRQ_INTERRUPT) {
+ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
ide_execute_command(drive, WIN_PACKETCMD, handler,
timeout, NULL);
return ide_started;
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 6e29dd53209..e617cf08aef 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -57,23 +57,29 @@ static DEFINE_MUTEX(idecd_ref_mutex);
#define ide_cd_g(disk) \
container_of((disk)->private_data, struct cdrom_info, driver)
+static void ide_cd_release(struct kref *);
+
static struct cdrom_info *ide_cd_get(struct gendisk *disk)
{
struct cdrom_info *cd = NULL;
mutex_lock(&idecd_ref_mutex);
cd = ide_cd_g(disk);
- if (cd)
+ if (cd) {
kref_get(&cd->kref);
+ if (ide_device_get(cd->drive)) {
+ kref_put(&cd->kref, ide_cd_release);
+ cd = NULL;
+ }
+ }
mutex_unlock(&idecd_ref_mutex);
return cd;
}
-static void ide_cd_release(struct kref *);
-
static void ide_cd_put(struct cdrom_info *cd)
{
mutex_lock(&idecd_ref_mutex);
+ ide_device_put(cd->drive);
kref_put(&cd->kref, ide_cd_release);
mutex_unlock(&idecd_ref_mutex);
}
@@ -85,10 +91,8 @@ static void ide_cd_put(struct cdrom_info *cd)
/* Mark that we've seen a media change and invalidate our internal buffers. */
static void cdrom_saw_media_change(ide_drive_t *drive)
{
- struct cdrom_info *cd = drive->driver_data;
-
- cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
- cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
+ drive->atapi_flags |= IDE_AFLAG_MEDIA_CHANGED;
+ drive->atapi_flags &= ~IDE_AFLAG_TOC_VALID;
}
static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
@@ -280,11 +284,12 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 st)
*/
static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
{
- struct request *rq = HWGROUP(drive)->rq;
+ ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->hwgroup->rq;
int stat, err, sense_key;
/* check for errors */
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
if (stat_ret)
*stat_ret = stat;
@@ -528,7 +533,7 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL,
xferlen, info->dma);
- if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
+ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
/* waiting for CDB interrupt, not DMA yet. */
if (info->dma)
drive->waiting_for_dma = 0;
@@ -560,7 +565,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
struct cdrom_info *info = drive->driver_data;
ide_startstop_t startstop;
- if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
+ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
/*
* Here we should have been called after receiving an interrupt
* from the device. DRQ should how be set.
@@ -589,7 +594,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
cmd_len = ATAPI_MIN_CDB_BYTES;
/* send the command to the device */
- hwif->output_data(drive, NULL, rq->cmd, cmd_len);
+ hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
/* start the DMA if need be */
if (info->dma)
@@ -606,6 +611,8 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
int len, int ireason, int rw)
{
+ ide_hwif_t *hwif = drive->hwif;
+
/*
* ireason == 0: the drive wants to receive data from us
* ireason == 2: the drive is expecting to transfer data to us
@@ -624,7 +631,7 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
* Some drives (ASUS) seem to tell us that status info is
* available. Just get it and ignore.
*/
- (void)ide_read_status(drive);
+ (void)hwif->tp_ops->read_status(hwif);
return 0;
} else {
/* drive wants a command packet, or invalid ireason... */
@@ -645,20 +652,18 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
*/
static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
{
- struct cdrom_info *cd = drive->driver_data;
-
if ((len % SECTOR_SIZE) == 0)
return 0;
printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
drive->name, __func__, len);
- if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
+ if (drive->atapi_flags & IDE_AFLAG_LIMIT_NFRAMES)
printk(KERN_ERR " This drive is not supported by "
"this version of the driver\n");
else {
printk(KERN_ERR " Trying to limit transfer sizes\n");
- cd->cd_flags |= IDE_CD_FLAG_LIMIT_NFRAMES;
+ drive->atapi_flags |= IDE_AFLAG_LIMIT_NFRAMES;
}
return 1;
@@ -735,7 +740,7 @@ static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
if (cdrom_decode_status(drive, 0, &stat))
return ide_stopped;
- info->cd_flags |= IDE_CD_FLAG_SEEKING;
+ drive->atapi_flags |= IDE_AFLAG_SEEKING;
if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
if (--retry == 0)
@@ -892,10 +897,11 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
struct request *rq = HWGROUP(drive)->rq;
xfer_func_t *xferfunc;
ide_expiry_t *expiry = NULL;
- int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0;
+ int dma_error = 0, dma, stat, thislen, uptodate = 0;
int write = (rq_data_dir(rq) == WRITE) ? 1 : 0;
unsigned int timeout;
- u8 lowcyl, highcyl;
+ u16 len;
+ u8 ireason;
/* check for errors */
dma = info->dma;
@@ -923,12 +929,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
goto end_request;
}
- /* ok we fall to pio :/ */
- ireason = hwif->INB(hwif->io_ports.nsect_addr) & 0x3;
- lowcyl = hwif->INB(hwif->io_ports.lbam_addr);
- highcyl = hwif->INB(hwif->io_ports.lbah_addr);
-
- len = lowcyl + (256 * highcyl);
+ ide_read_bcount_and_ireason(drive, &len, &ireason);
thislen = blk_fs_request(rq) ? len : rq->data_len;
if (thislen > len)
@@ -991,10 +992,10 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
if (ireason == 0) {
write = 1;
- xferfunc = hwif->output_data;
+ xferfunc = hwif->tp_ops->output_data;
} else {
write = 0;
- xferfunc = hwif->input_data;
+ xferfunc = hwif->tp_ops->input_data;
}
/* transfer data */
@@ -1198,9 +1199,10 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
int xferlen;
if (blk_fs_request(rq)) {
- if (info->cd_flags & IDE_CD_FLAG_SEEKING) {
+ if (drive->atapi_flags & IDE_AFLAG_SEEKING) {
+ ide_hwif_t *hwif = drive->hwif;
unsigned long elapsed = jiffies - info->start_seek;
- int stat = ide_read_status(drive);
+ int stat = hwif->tp_ops->read_status(hwif);
if ((stat & SEEK_STAT) != SEEK_STAT) {
if (elapsed < IDECD_SEEK_TIMEOUT) {
@@ -1211,7 +1213,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
printk(KERN_ERR "%s: DSC timeout\n",
drive->name);
}
- info->cd_flags &= ~IDE_CD_FLAG_SEEKING;
+ drive->atapi_flags &= ~IDE_AFLAG_SEEKING;
}
if (rq_data_dir(rq) == READ &&
IDE_LARGE_SEEK(info->last_block, block,
@@ -1288,7 +1290,7 @@ int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
*/
cmd[7] = cdi->sanyo_slot % 3;
- return ide_cd_queue_pc(drive, cmd, 0, NULL, 0, sense, 0, REQ_QUIET);
+ return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, REQ_QUIET);
}
static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
@@ -1296,8 +1298,8 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
struct request_sense *sense)
{
struct {
- __u32 lba;
- __u32 blocklen;
+ __be32 lba;
+ __be32 blocklen;
} capbuf;
int stat;
@@ -1309,13 +1311,30 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
stat = ide_cd_queue_pc(drive, cmd, 0, &capbuf, &len, sense, 0,
REQ_QUIET);
- if (stat == 0) {
- *capacity = 1 + be32_to_cpu(capbuf.lba);
- *sectors_per_frame =
- be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS;
+ if (stat)
+ return stat;
+
+ /*
+ * Sanity check the given block size
+ */
+ switch (capbuf.blocklen) {
+ case __constant_cpu_to_be32(512):
+ case __constant_cpu_to_be32(1024):
+ case __constant_cpu_to_be32(2048):
+ case __constant_cpu_to_be32(4096):
+ break;
+ default:
+ printk(KERN_ERR "%s: weird block size %u\n",
+ drive->name, capbuf.blocklen);
+ printk(KERN_ERR "%s: default to 2kb block size\n",
+ drive->name);
+ capbuf.blocklen = __constant_cpu_to_be32(2048);
+ break;
}
- return stat;
+ *capacity = 1 + be32_to_cpu(capbuf.lba);
+ *sectors_per_frame = be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS;
+ return 0;
}
static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
@@ -1369,7 +1388,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
*/
(void) cdrom_check_status(drive, sense);
- if (info->cd_flags & IDE_CD_FLAG_TOC_VALID)
+ if (drive->atapi_flags & IDE_AFLAG_TOC_VALID)
return 0;
/* try to get the total cdrom capacity and sector size */
@@ -1391,7 +1410,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
if (stat)
return stat;
- if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
toc->hdr.last_track = BCD2BIN(toc->hdr.last_track);
}
@@ -1432,7 +1451,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
if (stat)
return stat;
- if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
toc->hdr.first_track = (u8)BIN2BCD(CDROM_LEADOUT);
toc->hdr.last_track = (u8)BIN2BCD(CDROM_LEADOUT);
} else {
@@ -1446,14 +1465,14 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
toc->hdr.toc_length = be16_to_cpu(toc->hdr.toc_length);
- if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
toc->hdr.last_track = BCD2BIN(toc->hdr.last_track);
}
for (i = 0; i <= ntracks; i++) {
- if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
- if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD)
+ if (drive->atapi_flags & IDE_AFLAG_TOCADDR_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD)
toc->ent[i].track = BCD2BIN(toc->ent[i].track);
msf_from_bcd(&toc->ent[i].addr.msf);
}
@@ -1476,7 +1495,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
}
- if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_TOCADDR_AS_BCD) {
/* re-read multisession information using MSF format */
stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
sizeof(ms_tmp), sense);
@@ -1500,7 +1519,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
}
/* Remember that we've read this stuff. */
- info->cd_flags |= IDE_CD_FLAG_TOC_VALID;
+ drive->atapi_flags |= IDE_AFLAG_TOC_VALID;
return 0;
}
@@ -1512,7 +1531,7 @@ int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
struct packet_command cgc;
int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
- if ((info->cd_flags & IDE_CD_FLAG_FULL_CAPS_PAGE) == 0)
+ if ((drive->atapi_flags & IDE_AFLAG_FULL_CAPS_PAGE) == 0)
size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN);
@@ -1530,15 +1549,12 @@ void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
struct cdrom_info *cd = drive->driver_data;
u16 curspeed, maxspeed;
- curspeed = *(u16 *)&buf[8 + 14];
- maxspeed = *(u16 *)&buf[8 + 8];
-
- if (cd->cd_flags & IDE_CD_FLAG_LE_SPEED_FIELDS) {
- curspeed = le16_to_cpu(curspeed);
- maxspeed = le16_to_cpu(maxspeed);
+ if (drive->atapi_flags & IDE_AFLAG_LE_SPEED_FIELDS) {
+ curspeed = le16_to_cpup((__le16 *)&buf[8 + 14]);
+ maxspeed = le16_to_cpup((__le16 *)&buf[8 + 8]);
} else {
- curspeed = be16_to_cpu(curspeed);
- maxspeed = be16_to_cpu(maxspeed);
+ curspeed = be16_to_cpup((__be16 *)&buf[8 + 14]);
+ maxspeed = be16_to_cpup((__be16 *)&buf[8 + 8]);
}
cd->current_speed = (curspeed + (176/2)) / 176;
@@ -1579,7 +1595,7 @@ static int ide_cdrom_register(ide_drive_t *drive, int nslots)
devinfo->handle = drive;
strcpy(devinfo->name, drive->name);
- if (info->cd_flags & IDE_CD_FLAG_NO_SPEED_SELECT)
+ if (drive->atapi_flags & IDE_AFLAG_NO_SPEED_SELECT)
devinfo->mask |= CDC_SELECT_SPEED;
devinfo->disk = info->disk;
@@ -1605,8 +1621,8 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
return nslots;
}
- if (cd->cd_flags & IDE_CD_FLAG_PRE_ATAPI12) {
- cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
+ if (drive->atapi_flags & IDE_AFLAG_PRE_ATAPI12) {
+ drive->atapi_flags &= ~IDE_AFLAG_NO_EJECT;
cdi->mask &= ~CDC_PLAY_AUDIO;
return nslots;
}
@@ -1624,9 +1640,9 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
return 0;
if ((buf[8 + 6] & 0x01) == 0)
- cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
+ drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
if (buf[8 + 6] & 0x08)
- cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
+ drive->atapi_flags &= ~IDE_AFLAG_NO_EJECT;
if (buf[8 + 3] & 0x01)
cdi->mask &= ~CDC_CD_R;
if (buf[8 + 3] & 0x02)
@@ -1637,7 +1653,7 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
cdi->mask &= ~(CDC_DVD_RAM | CDC_RAM);
if (buf[8 + 3] & 0x10)
cdi->mask &= ~CDC_DVD_R;
- if ((buf[8 + 4] & 0x01) || (cd->cd_flags & IDE_CD_FLAG_PLAY_AUDIO_OK))
+ if ((buf[8 + 4] & 0x01) || (drive->atapi_flags & IDE_AFLAG_PLAY_AUDIO_OK))
cdi->mask &= ~CDC_PLAY_AUDIO;
mechtype = buf[8 + 6] >> 5;
@@ -1679,7 +1695,7 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
else
printk(KERN_CONT " drive");
- printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(*(u16 *)&buf[8 + 12]));
+ printk(KERN_CONT ", %dkB Cache\n", be16_to_cpup((__be16 *)&buf[8 + 12]));
return nslots;
}
@@ -1802,43 +1818,43 @@ static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; }
static const struct cd_list_entry ide_cd_quirks_list[] = {
/* Limit transfer size per interrupt. */
- { "SAMSUNG CD-ROM SCR-2430", NULL, IDE_CD_FLAG_LIMIT_NFRAMES },
- { "SAMSUNG CD-ROM SCR-2432", NULL, IDE_CD_FLAG_LIMIT_NFRAMES },
+ { "SAMSUNG CD-ROM SCR-2430", NULL, IDE_AFLAG_LIMIT_NFRAMES },
+ { "SAMSUNG CD-ROM SCR-2432", NULL, IDE_AFLAG_LIMIT_NFRAMES },
/* SCR-3231 doesn't support the SET_CD_SPEED command. */
- { "SAMSUNG CD-ROM SCR-3231", NULL, IDE_CD_FLAG_NO_SPEED_SELECT },
+ { "SAMSUNG CD-ROM SCR-3231", NULL, IDE_AFLAG_NO_SPEED_SELECT },
/* Old NEC260 (not R) was released before ATAPI 1.2 spec. */
- { "NEC CD-ROM DRIVE:260", "1.01", IDE_CD_FLAG_TOCADDR_AS_BCD |
- IDE_CD_FLAG_PRE_ATAPI12, },
+ { "NEC CD-ROM DRIVE:260", "1.01", IDE_AFLAG_TOCADDR_AS_BCD |
+ IDE_AFLAG_PRE_ATAPI12, },
/* Vertos 300, some versions of this drive like to talk BCD. */
- { "V003S0DS", NULL, IDE_CD_FLAG_VERTOS_300_SSD, },
+ { "V003S0DS", NULL, IDE_AFLAG_VERTOS_300_SSD, },
/* Vertos 600 ESD. */
- { "V006E0DS", NULL, IDE_CD_FLAG_VERTOS_600_ESD, },
+ { "V006E0DS", NULL, IDE_AFLAG_VERTOS_600_ESD, },
/*
* Sanyo 3 CD changer uses a non-standard command for CD changing
* (by default standard ATAPI support for CD changers is used).
*/
- { "CD-ROM CDR-C3 G", NULL, IDE_CD_FLAG_SANYO_3CD },
- { "CD-ROM CDR-C3G", NULL, IDE_CD_FLAG_SANYO_3CD },
- { "CD-ROM CDR_C36", NULL, IDE_CD_FLAG_SANYO_3CD },
+ { "CD-ROM CDR-C3 G", NULL, IDE_AFLAG_SANYO_3CD },
+ { "CD-ROM CDR-C3G", NULL, IDE_AFLAG_SANYO_3CD },
+ { "CD-ROM CDR_C36", NULL, IDE_AFLAG_SANYO_3CD },
/* Stingray 8X CD-ROM. */
- { "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_CD_FLAG_PRE_ATAPI12},
+ { "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_AFLAG_PRE_ATAPI12 },
/*
* ACER 50X CD-ROM and WPI 32X CD-ROM require the full spec length
* mode sense page capabilities size, but older drives break.
*/
- { "ATAPI CD ROM DRIVE 50X MAX", NULL, IDE_CD_FLAG_FULL_CAPS_PAGE },
- { "WPI CDS-32X", NULL, IDE_CD_FLAG_FULL_CAPS_PAGE },
+ { "ATAPI CD ROM DRIVE 50X MAX", NULL, IDE_AFLAG_FULL_CAPS_PAGE },
+ { "WPI CDS-32X", NULL, IDE_AFLAG_FULL_CAPS_PAGE },
/* ACER/AOpen 24X CD-ROM has the speed fields byte-swapped. */
- { "", "241N", IDE_CD_FLAG_LE_SPEED_FIELDS },
+ { "", "241N", IDE_AFLAG_LE_SPEED_FIELDS },
/*
* Some drives used by Apple don't advertise audio play
* but they do support reading TOC & audio datas.
*/
- { "MATSHITADVD-ROM SR-8187", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
- { "MATSHITADVD-ROM SR-8186", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
- { "MATSHITADVD-ROM SR-8176", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
- { "MATSHITADVD-ROM SR-8174", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
- { "Optiarc DVD RW AD-5200A", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8187", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8186", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8176", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8174", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "Optiarc DVD RW AD-5200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
{ NULL, NULL, 0 }
};
@@ -1873,20 +1889,20 @@ static int ide_cdrom_setup(ide_drive_t *drive)
drive->special.all = 0;
- cd->cd_flags = IDE_CD_FLAG_MEDIA_CHANGED | IDE_CD_FLAG_NO_EJECT |
+ drive->atapi_flags = IDE_AFLAG_MEDIA_CHANGED | IDE_AFLAG_NO_EJECT |
ide_cd_flags(id);
if ((id->config & 0x0060) == 0x20)
- cd->cd_flags |= IDE_CD_FLAG_DRQ_INTERRUPT;
+ drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
- if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_300_SSD) &&
+ if ((drive->atapi_flags & IDE_AFLAG_VERTOS_300_SSD) &&
id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
- cd->cd_flags |= (IDE_CD_FLAG_TOCTRACKS_AS_BCD |
- IDE_CD_FLAG_TOCADDR_AS_BCD);
- else if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_600_ESD) &&
+ drive->atapi_flags |= (IDE_AFLAG_TOCTRACKS_AS_BCD |
+ IDE_AFLAG_TOCADDR_AS_BCD);
+ else if ((drive->atapi_flags & IDE_AFLAG_VERTOS_600_ESD) &&
id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
- cd->cd_flags |= IDE_CD_FLAG_TOCTRACKS_AS_BCD;
- else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD)
+ drive->atapi_flags |= IDE_AFLAG_TOCTRACKS_AS_BCD;
+ else if (drive->atapi_flags & IDE_AFLAG_SANYO_3CD)
/* 3 => use CD in slot 0 */
cdi->sanyo_slot = 3;
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index fe0ea36e412..61a4599b77d 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -27,42 +27,6 @@
#define ATAPI_CAPABILITIES_PAGE_SIZE (8 + 20)
#define ATAPI_CAPABILITIES_PAGE_PAD_SIZE 4
-enum {
- /* Device sends an interrupt when ready for a packet command. */
- IDE_CD_FLAG_DRQ_INTERRUPT = (1 << 0),
- /* Drive cannot lock the door. */
- IDE_CD_FLAG_NO_DOORLOCK = (1 << 1),
- /* Drive cannot eject the disc. */
- IDE_CD_FLAG_NO_EJECT = (1 << 2),
- /* Drive is a pre ATAPI 1.2 drive. */
- IDE_CD_FLAG_PRE_ATAPI12 = (1 << 3),
- /* TOC addresses are in BCD. */
- IDE_CD_FLAG_TOCADDR_AS_BCD = (1 << 4),
- /* TOC track numbers are in BCD. */
- IDE_CD_FLAG_TOCTRACKS_AS_BCD = (1 << 5),
- /*
- * Drive does not provide data in multiples of SECTOR_SIZE
- * when more than one interrupt is needed.
- */
- IDE_CD_FLAG_LIMIT_NFRAMES = (1 << 6),
- /* Seeking in progress. */
- IDE_CD_FLAG_SEEKING = (1 << 7),
- /* Driver has noticed a media change. */
- IDE_CD_FLAG_MEDIA_CHANGED = (1 << 8),
- /* Saved TOC information is current. */
- IDE_CD_FLAG_TOC_VALID = (1 << 9),
- /* We think that the drive door is locked. */
- IDE_CD_FLAG_DOOR_LOCKED = (1 << 10),
- /* SET_CD_SPEED command is unsupported. */
- IDE_CD_FLAG_NO_SPEED_SELECT = (1 << 11),
- IDE_CD_FLAG_VERTOS_300_SSD = (1 << 12),
- IDE_CD_FLAG_VERTOS_600_ESD = (1 << 13),
- IDE_CD_FLAG_SANYO_3CD = (1 << 14),
- IDE_CD_FLAG_FULL_CAPS_PAGE = (1 << 15),
- IDE_CD_FLAG_PLAY_AUDIO_OK = (1 << 16),
- IDE_CD_FLAG_LE_SPEED_FIELDS = (1 << 17),
-};
-
/* Structure of a MSF cdrom address. */
struct atapi_msf {
byte reserved;
@@ -128,8 +92,6 @@ struct cdrom_info {
unsigned long last_block;
unsigned long start_seek;
- unsigned int cd_flags;
-
u8 max_speed; /* Max speed of the drive. */
u8 current_speed; /* Current speed of the drive. */
diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c
index 24d002addf7..74231b41f61 100644
--- a/drivers/ide/ide-cd_ioctl.c
+++ b/drivers/ide/ide-cd_ioctl.c
@@ -27,10 +27,9 @@ int ide_cdrom_open_real(struct cdrom_device_info *cdi, int purpose)
void ide_cdrom_release_real(struct cdrom_device_info *cdi)
{
ide_drive_t *drive = cdi->handle;
- struct cdrom_info *cd = drive->driver_data;
if (!cdi->use_count)
- cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
+ drive->atapi_flags &= ~IDE_AFLAG_TOC_VALID;
}
/*
@@ -83,13 +82,12 @@ int ide_cdrom_check_media_change_real(struct cdrom_device_info *cdi,
int slot_nr)
{
ide_drive_t *drive = cdi->handle;
- struct cdrom_info *cd = drive->driver_data;
int retval;
if (slot_nr == CDSL_CURRENT) {
(void) cdrom_check_status(drive, NULL);
- retval = (cd->cd_flags & IDE_CD_FLAG_MEDIA_CHANGED) ? 1 : 0;
- cd->cd_flags &= ~IDE_CD_FLAG_MEDIA_CHANGED;
+ retval = (drive->atapi_flags & IDE_AFLAG_MEDIA_CHANGED) ? 1 : 0;
+ drive->atapi_flags &= ~IDE_AFLAG_MEDIA_CHANGED;
return retval;
} else {
return -EINVAL;
@@ -107,11 +105,11 @@ int cdrom_eject(ide_drive_t *drive, int ejectflag,
char loej = 0x02;
unsigned char cmd[BLK_MAX_CDB];
- if ((cd->cd_flags & IDE_CD_FLAG_NO_EJECT) && !ejectflag)
+ if ((drive->atapi_flags & IDE_AFLAG_NO_EJECT) && !ejectflag)
return -EDRIVE_CANT_DO_THIS;
/* reload fails on some drives, if the tray is locked */
- if ((cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED) && ejectflag)
+ if ((drive->atapi_flags & IDE_AFLAG_DOOR_LOCKED) && ejectflag)
return 0;
/* only tell drive to close tray if open, if it can do that */
@@ -123,7 +121,7 @@ int cdrom_eject(ide_drive_t *drive, int ejectflag,
cmd[0] = GPCMD_START_STOP_UNIT;
cmd[4] = loej | (ejectflag != 0);
- return ide_cd_queue_pc(drive, cmd, 0, NULL, 0, sense, 0, 0);
+ return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, 0);
}
/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
@@ -131,7 +129,6 @@ static
int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
struct request_sense *sense)
{
- struct cdrom_info *cd = drive->driver_data;
struct request_sense my_sense;
int stat;
@@ -139,7 +136,7 @@ int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
sense = &my_sense;
/* If the drive cannot lock the door, just pretend. */
- if (cd->cd_flags & IDE_CD_FLAG_NO_DOORLOCK) {
+ if (drive->atapi_flags & IDE_AFLAG_NO_DOORLOCK) {
stat = 0;
} else {
unsigned char cmd[BLK_MAX_CDB];
@@ -149,7 +146,7 @@ int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
cmd[4] = lockflag ? 1 : 0;
- stat = ide_cd_queue_pc(drive, cmd, 0, NULL, 0,
+ stat = ide_cd_queue_pc(drive, cmd, 0, NULL, NULL,
sense, 0, 0);
}
@@ -160,7 +157,7 @@ int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
(sense->asc == 0x24 || sense->asc == 0x20)) {
printk(KERN_ERR "%s: door locking not supported\n",
drive->name);
- cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
+ drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
stat = 0;
}
@@ -170,9 +167,9 @@ int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
if (stat == 0) {
if (lockflag)
- cd->cd_flags |= IDE_CD_FLAG_DOOR_LOCKED;
+ drive->atapi_flags |= IDE_AFLAG_DOOR_LOCKED;
else
- cd->cd_flags &= ~IDE_CD_FLAG_DOOR_LOCKED;
+ drive->atapi_flags &= ~IDE_AFLAG_DOOR_LOCKED;
}
return stat;
@@ -231,7 +228,7 @@ int ide_cdrom_select_speed(struct cdrom_device_info *cdi, int speed)
cmd[5] = speed & 0xff;
}
- stat = ide_cd_queue_pc(drive, cmd, 0, NULL, 0, &sense, 0, 0);
+ stat = ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, &sense, 0, 0);
if (!ide_cdrom_get_capabilities(drive, buf)) {
ide_cdrom_update_speed(drive, buf);
@@ -250,7 +247,7 @@ int ide_cdrom_get_last_session(struct cdrom_device_info *cdi,
struct request_sense sense;
int ret;
- if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0 || !info->toc) {
+ if ((drive->atapi_flags & IDE_AFLAG_TOC_VALID) == 0 || !info->toc) {
ret = ide_cd_read_toc(drive, &sense);
if (ret)
return ret;
@@ -308,7 +305,7 @@ int ide_cdrom_reset(struct cdrom_device_info *cdi)
* A reset will unlock the door. If it was previously locked,
* lock it again.
*/
- if (cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED)
+ if (drive->atapi_flags & IDE_AFLAG_DOOR_LOCKED)
(void)ide_cd_lockdoor(drive, 1, &sense);
return ret;
@@ -324,7 +321,7 @@ static int ide_cd_get_toc_entry(ide_drive_t *drive, int track,
/*
* don't serve cached data, if the toc isn't valid
*/
- if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0)
+ if ((drive->atapi_flags & IDE_AFLAG_TOC_VALID) == 0)
return -EINVAL;
/* Check validity of requested track number. */
@@ -374,7 +371,7 @@ static int ide_cd_fake_play_trkind(ide_drive_t *drive, void *arg)
lba_to_msf(lba_start, &cmd[3], &cmd[4], &cmd[5]);
lba_to_msf(lba_end - 1, &cmd[6], &cmd[7], &cmd[8]);
- return ide_cd_queue_pc(drive, cmd, 0, NULL, 0, &sense, 0, 0);
+ return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, &sense, 0, 0);
}
static int ide_cd_read_tochdr(ide_drive_t *drive, void *arg)
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 3a2e80237c1..28d85b410f7 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -56,23 +56,29 @@ static DEFINE_MUTEX(idedisk_ref_mutex);
#define ide_disk_g(disk) \
container_of((disk)->private_data, struct ide_disk_obj, driver)
+static void ide_disk_release(struct kref *);
+
static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
{
struct ide_disk_obj *idkp = NULL;
mutex_lock(&idedisk_ref_mutex);
idkp = ide_disk_g(disk);
- if (idkp)
+ if (idkp) {
kref_get(&idkp->kref);
+ if (ide_device_get(idkp->drive)) {
+ kref_put(&idkp->kref, ide_disk_release);
+ idkp = NULL;
+ }
+ }
mutex_unlock(&idedisk_ref_mutex);
return idkp;
}
-static void ide_disk_release(struct kref *);
-
static void ide_disk_put(struct ide_disk_obj *idkp)
{
mutex_lock(&idedisk_ref_mutex);
+ ide_device_put(idkp->drive);
kref_put(&idkp->kref, ide_disk_release);
mutex_unlock(&idedisk_ref_mutex);
}
@@ -158,7 +164,7 @@ static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
if (dma)
- index = drive->vdma ? 4 : 8;
+ index = 8;
else
index = drive->mult_count ? 0 : 4;
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 7ee44f86bc5..71c377a7bcf 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -100,10 +100,11 @@ static const struct drive_list_entry drive_blacklist [] = {
ide_startstop_t ide_dma_intr (ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
u8 stat = 0, dma_stat = 0;
- dma_stat = drive->hwif->dma_ops->dma_end(drive);
- stat = ide_read_status(drive);
+ dma_stat = hwif->dma_ops->dma_end(drive);
+ stat = hwif->tp_ops->read_status(hwif);
if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
if (!dma_stat) {
@@ -172,7 +173,7 @@ EXPORT_SYMBOL_GPL(ide_build_sglist);
int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
{
ide_hwif_t *hwif = HWIF(drive);
- unsigned int *table = hwif->dmatable_cpu;
+ __le32 *table = (__le32 *)hwif->dmatable_cpu;
unsigned int is_trm290 = (hwif->chipset == ide_trm290) ? 1 : 0;
unsigned int count = 0;
int i;
@@ -334,7 +335,7 @@ static int config_drive_for_dma (ide_drive_t *drive)
static int dma_timer_expiry (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- u8 dma_stat = hwif->INB(hwif->dma_status);
+ u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
printk(KERN_WARNING "%s: dma_timer_expiry: dma status == 0x%02x\n",
drive->name, dma_stat);
@@ -369,14 +370,18 @@ void ide_dma_host_set(ide_drive_t *drive, int on)
{
ide_hwif_t *hwif = HWIF(drive);
u8 unit = (drive->select.b.unit & 0x01);
- u8 dma_stat = hwif->INB(hwif->dma_status);
+ u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
if (on)
dma_stat |= (1 << (5 + unit));
else
dma_stat &= ~(1 << (5 + unit));
- hwif->OUTB(dma_stat, hwif->dma_status);
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ writeb(dma_stat,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+ else
+ outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
}
EXPORT_SYMBOL_GPL(ide_dma_host_set);
@@ -449,6 +454,7 @@ int ide_dma_setup(ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
struct request *rq = HWGROUP(drive)->rq;
unsigned int reading;
+ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
u8 dma_stat;
if (rq_data_dir(rq))
@@ -470,13 +476,21 @@ int ide_dma_setup(ide_drive_t *drive)
outl(hwif->dmatable_dma, hwif->dma_base + ATA_DMA_TABLE_OFS);
/* specify r/w */
- hwif->OUTB(reading, hwif->dma_command);
+ if (mmio)
+ writeb(reading, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ else
+ outb(reading, hwif->dma_base + ATA_DMA_CMD);
- /* read dma_status for INTR & ERROR flags */
- dma_stat = hwif->INB(hwif->dma_status);
+ /* read DMA status for INTR & ERROR flags */
+ dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
/* clear INTR & ERROR flags */
- hwif->OUTB(dma_stat|6, hwif->dma_status);
+ if (mmio)
+ writeb(dma_stat | 6,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+ else
+ outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
+
drive->waiting_for_dma = 1;
return 0;
}
@@ -492,16 +506,24 @@ EXPORT_SYMBOL_GPL(ide_dma_exec_cmd);
void ide_dma_start(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- u8 dma_cmd = hwif->INB(hwif->dma_command);
+ ide_hwif_t *hwif = drive->hwif;
+ u8 dma_cmd;
/* Note that this is done *after* the cmd has
* been issued to the drive, as per the BM-IDE spec.
* The Promise Ultra33 doesn't work correctly when
* we do this part before issuing the drive cmd.
*/
- /* start DMA */
- hwif->OUTB(dma_cmd|1, hwif->dma_command);
+ if (hwif->host_flags & IDE_HFLAG_MMIO) {
+ dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ /* start DMA */
+ writeb(dma_cmd | 1,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ } else {
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+ outb(dma_cmd | 1, hwif->dma_base + ATA_DMA_CMD);
+ }
+
hwif->dma = 1;
wmb();
}
@@ -511,18 +533,33 @@ EXPORT_SYMBOL_GPL(ide_dma_start);
/* returns 1 on error, 0 otherwise */
int __ide_dma_end (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
+ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
u8 dma_stat = 0, dma_cmd = 0;
drive->waiting_for_dma = 0;
- /* get dma_command mode */
- dma_cmd = hwif->INB(hwif->dma_command);
- /* stop DMA */
- hwif->OUTB(dma_cmd&~1, hwif->dma_command);
+
+ if (mmio) {
+ /* get DMA command mode */
+ dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ /* stop DMA */
+ writeb(dma_cmd & ~1,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ } else {
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+ outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
+ }
+
/* get DMA status */
- dma_stat = hwif->INB(hwif->dma_status);
- /* clear the INTR & ERROR bits */
- hwif->OUTB(dma_stat|6, hwif->dma_status);
+ dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+ if (mmio)
+ /* clear the INTR & ERROR bits */
+ writeb(dma_stat | 6,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+ else
+ outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
+
/* purge DMA mappings */
ide_destroy_dmatable(drive);
/* verify good DMA status */
@@ -537,7 +574,7 @@ EXPORT_SYMBOL(__ide_dma_end);
int ide_dma_test_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- u8 dma_stat = hwif->INB(hwif->dma_status);
+ u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
/* return 1 if INTR asserted */
if ((dma_stat & 4) == 4)
@@ -719,9 +756,8 @@ static int ide_tune_dma(ide_drive_t *drive)
static int ide_dma_check(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- int vdma = (hwif->host_flags & IDE_HFLAG_VDMA)? 1 : 0;
- if (!vdma && ide_tune_dma(drive))
+ if (ide_tune_dma(drive))
return 0;
/* TODO: always do PIO fallback */
@@ -730,7 +766,7 @@ static int ide_dma_check(ide_drive_t *drive)
ide_set_max_pio(drive);
- return vdma ? 0 : -1;
+ return -1;
}
int ide_id_dma_bug(ide_drive_t *drive)
@@ -842,7 +878,7 @@ int ide_allocate_dma_engine(ide_hwif_t *hwif)
}
EXPORT_SYMBOL_GPL(ide_allocate_dma_engine);
-static const struct ide_dma_ops sff_dma_ops = {
+const struct ide_dma_ops sff_dma_ops = {
.dma_host_set = ide_dma_host_set,
.dma_setup = ide_dma_setup,
.dma_exec_cmd = ide_dma_exec_cmd,
@@ -852,18 +888,5 @@ static const struct ide_dma_ops sff_dma_ops = {
.dma_timeout = ide_dma_timeout,
.dma_lost_irq = ide_dma_lost_irq,
};
-
-void ide_setup_dma(ide_hwif_t *hwif, unsigned long base)
-{
- hwif->dma_base = base;
-
- if (!hwif->dma_command)
- hwif->dma_command = hwif->dma_base + 0;
- if (!hwif->dma_status)
- hwif->dma_status = hwif->dma_base + 2;
-
- hwif->dma_ops = &sff_dma_ops;
-}
-
-EXPORT_SYMBOL_GPL(ide_setup_dma);
+EXPORT_SYMBOL_GPL(sff_dma_ops);
#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 011d72011cc..ca11a26746f 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -125,26 +125,10 @@ typedef struct ide_floppy_obj {
int wp;
/* Supports format progress report */
int srfp;
- /* Status/Action flags */
- unsigned long flags;
} idefloppy_floppy_t;
#define IDEFLOPPY_TICKS_DELAY HZ/20 /* default delay for ZIP 100 (50ms) */
-/* Floppy flag bits values. */
-enum {
- /* DRQ interrupt device */
- IDEFLOPPY_FLAG_DRQ_INTERRUPT = (1 << 0),
- /* Media may have changed */
- IDEFLOPPY_FLAG_MEDIA_CHANGED = (1 << 1),
- /* Format in progress */
- IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS = (1 << 2),
- /* Avoid commands not supported in Clik drive */
- IDEFLOPPY_FLAG_CLIK_DRIVE = (1 << 3),
- /* Requires BH algorithm for packets */
- IDEFLOPPY_FLAG_ZIP_DRIVE = (1 << 4),
-};
-
/* Defines for the MODE SENSE command */
#define MODE_SENSE_CURRENT 0x00
#define MODE_SENSE_CHANGEABLE 0x01
@@ -174,23 +158,29 @@ static DEFINE_MUTEX(idefloppy_ref_mutex);
#define ide_floppy_g(disk) \
container_of((disk)->private_data, struct ide_floppy_obj, driver)
+static void idefloppy_cleanup_obj(struct kref *);
+
static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
{
struct ide_floppy_obj *floppy = NULL;
mutex_lock(&idefloppy_ref_mutex);
floppy = ide_floppy_g(disk);
- if (floppy)
+ if (floppy) {
kref_get(&floppy->kref);
+ if (ide_device_get(floppy->drive)) {
+ kref_put(&floppy->kref, idefloppy_cleanup_obj);
+ floppy = NULL;
+ }
+ }
mutex_unlock(&idefloppy_ref_mutex);
return floppy;
}
-static void idefloppy_cleanup_obj(struct kref *);
-
static void ide_floppy_put(struct ide_floppy_obj *floppy)
{
mutex_lock(&idefloppy_ref_mutex);
+ ide_device_put(floppy->drive);
kref_put(&floppy->kref, idefloppy_cleanup_obj);
mutex_unlock(&idefloppy_ref_mutex);
}
@@ -247,9 +237,9 @@ static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
data = bvec_kmap_irq(bvec, &flags);
if (direction)
- hwif->output_data(drive, NULL, data, count);
+ hwif->tp_ops->output_data(drive, NULL, data, count);
else
- hwif->input_data(drive, NULL, data, count);
+ hwif->tp_ops->input_data(drive, NULL, data, count);
bvec_kunmap_irq(data, &flags);
bcount -= count;
@@ -291,6 +281,7 @@ static void idefloppy_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
rq->cmd_type = REQ_TYPE_SPECIAL;
rq->cmd_flags |= REQ_PREEMPT;
rq->rq_disk = floppy->disk;
+ memcpy(rq->cmd, pc->c, 12);
ide_do_drive_cmd(drive, rq);
}
@@ -354,7 +345,6 @@ static void idefloppy_init_pc(struct ide_atapi_pc *pc)
memset(pc, 0, sizeof(*pc));
pc->buf = pc->pc_buf;
pc->buf_size = IDEFLOPPY_PC_BUFFER_SIZE;
- pc->callback = ide_floppy_callback;
}
static void idefloppy_create_request_sense_cmd(struct ide_atapi_pc *pc)
@@ -402,7 +392,7 @@ static int idefloppy_transfer_pc(ide_drive_t *drive)
idefloppy_floppy_t *floppy = drive->driver_data;
/* Send the actual packet */
- drive->hwif->output_data(drive, NULL, floppy->pc->c, 12);
+ drive->hwif->tp_ops->output_data(drive, NULL, floppy->pc->c, 12);
/* Timeout for the packet command */
return IDEFLOPPY_WAIT_CMD;
@@ -429,7 +419,7 @@ static ide_startstop_t idefloppy_start_pc_transfer(ide_drive_t *drive)
* 40 and 50msec work well. idefloppy_pc_intr will not be actually
* used until after the packet is moved in about 50 msec.
*/
- if (pc->flags & PC_FLAG_ZIP_DRIVE) {
+ if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
timeout = floppy->ticks;
expiry = &idefloppy_transfer_pc;
} else {
@@ -474,7 +464,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
pc->error = IDEFLOPPY_ERROR_GENERAL;
floppy->failed_pc = NULL;
- pc->callback(drive);
+ drive->pc_callback(drive);
return ide_stopped;
}
@@ -574,6 +564,8 @@ static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]);
put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]);
+ memcpy(rq->cmd, pc->c, 12);
+
pc->rq = rq;
pc->b_count = cmd == READ ? 0 : rq->bio->bi_size;
if (rq->cmd_flags & REQ_RW)
@@ -647,12 +639,6 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
return ide_stopped;
}
- if (floppy->flags & IDEFLOPPY_FLAG_DRQ_INTERRUPT)
- pc->flags |= PC_FLAG_DRQ_INTERRUPT;
-
- if (floppy->flags & IDEFLOPPY_FLAG_ZIP_DRIVE)
- pc->flags |= PC_FLAG_ZIP_DRIVE;
-
pc->rq = rq;
return idefloppy_issue_pc(drive, pc);
@@ -671,6 +657,7 @@ static int idefloppy_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->buffer = (char *) pc;
rq->cmd_type = REQ_TYPE_SPECIAL;
+ memcpy(rq->cmd, pc->c, 12);
error = blk_execute_rq(drive->queue, floppy->disk, rq, 0);
blk_put_request(rq);
@@ -795,7 +782,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
switch (pc.buf[desc_start + 4] & 0x03) {
/* Clik! drive returns this instead of CAPACITY_CURRENT */
case CAPACITY_UNFORMATTED:
- if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE))
+ if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
/*
* If it is not a clik drive, break out
* (maintains previous driver behaviour)
@@ -841,7 +828,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
}
/* Clik! disk does not support get_flexible_disk_page */
- if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE))
+ if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
(void) ide_floppy_get_flexible_disk_page(drive);
set_capacity(floppy->disk, floppy->blocks * floppy->bs_factor);
@@ -949,11 +936,12 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
/* Else assume format_unit has finished, and we're at 0x10000 */
} else {
+ ide_hwif_t *hwif = drive->hwif;
unsigned long flags;
u8 stat;
local_irq_save(flags);
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
local_irq_restore(flags);
progress_indication = ((stat & SEEK_STAT) == 0) ? 0 : 0x10000;
@@ -1039,9 +1027,10 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
*((u16 *) &gcw) = drive->id->config;
floppy->pc = floppy->pc_stack;
+ drive->pc_callback = ide_floppy_callback;
if (((gcw[0] & 0x60) >> 5) == 1)
- floppy->flags |= IDEFLOPPY_FLAG_DRQ_INTERRUPT;
+ drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
/*
* We used to check revisions here. At this point however I'm giving up.
* Just assume they are all broken, its easier.
@@ -1052,7 +1041,7 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
* we'll leave the limitation below for the 2.2.x tree.
*/
if (!strncmp(drive->id->model, "IOMEGA ZIP 100 ATAPI", 20)) {
- floppy->flags |= IDEFLOPPY_FLAG_ZIP_DRIVE;
+ drive->atapi_flags |= IDE_AFLAG_ZIP_DRIVE;
/* This value will be visible in the /proc/ide/hdx/settings */
floppy->ticks = IDEFLOPPY_TICKS_DELAY;
blk_queue_max_sectors(drive->queue, 64);
@@ -1064,7 +1053,7 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
*/
if (strncmp(drive->id->model, "IOMEGA Clik!", 11) == 0) {
blk_queue_max_sectors(drive->queue, 64);
- floppy->flags |= IDEFLOPPY_FLAG_CLIK_DRIVE;
+ drive->atapi_flags |= IDE_AFLAG_CLIK_DRIVE;
}
(void) ide_floppy_get_capacity(drive);
@@ -1153,7 +1142,7 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
floppy->openers++;
if (floppy->openers == 1) {
- floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+ drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
/* Just in case */
idefloppy_init_pc(&pc);
@@ -1180,14 +1169,14 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
ret = -EROFS;
goto out_put_floppy;
}
- floppy->flags |= IDEFLOPPY_FLAG_MEDIA_CHANGED;
+ drive->atapi_flags |= IDE_AFLAG_MEDIA_CHANGED;
/* IOMEGA Clik! drives do not support lock/unlock commands */
- if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
+ if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) {
idefloppy_create_prevent_cmd(&pc, 1);
(void) idefloppy_queue_pc_tail(drive, &pc);
}
check_disk_change(inode->i_bdev);
- } else if (floppy->flags & IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS) {
+ } else if (drive->atapi_flags & IDE_AFLAG_FORMAT_IN_PROGRESS) {
ret = -EBUSY;
goto out_put_floppy;
}
@@ -1210,12 +1199,12 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
if (floppy->openers == 1) {
/* IOMEGA Clik! drives do not support lock/unlock commands */
- if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
+ if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) {
idefloppy_create_prevent_cmd(&pc, 0);
(void) idefloppy_queue_pc_tail(drive, &pc);
}
- floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+ drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
}
floppy->openers--;
@@ -1236,15 +1225,17 @@ static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}
-static int ide_floppy_lockdoor(idefloppy_floppy_t *floppy,
- struct ide_atapi_pc *pc, unsigned long arg, unsigned int cmd)
+static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ unsigned long arg, unsigned int cmd)
{
+ idefloppy_floppy_t *floppy = drive->driver_data;
+
if (floppy->openers > 1)
return -EBUSY;
/* The IOMEGA Clik! Drive doesn't support this command -
* no room for an eject mechanism */
- if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
+ if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) {
int prevent = arg ? 1 : 0;
if (cmd == CDROMEJECT)
@@ -1265,16 +1256,17 @@ static int ide_floppy_lockdoor(idefloppy_floppy_t *floppy,
static int ide_floppy_format_unit(idefloppy_floppy_t *floppy,
int __user *arg)
{
- int blocks, length, flags, err = 0;
struct ide_atapi_pc pc;
+ ide_drive_t *drive = floppy->drive;
+ int blocks, length, flags, err = 0;
if (floppy->openers > 1) {
/* Don't format if someone is using the disk */
- floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+ drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
return -EBUSY;
}
- floppy->flags |= IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+ drive->atapi_flags |= IDE_AFLAG_FORMAT_IN_PROGRESS;
/*
* Send ATAPI_FORMAT_UNIT to the drive.
@@ -1298,15 +1290,15 @@ static int ide_floppy_format_unit(idefloppy_floppy_t *floppy,
goto out;
}
- (void) idefloppy_get_sfrp_bit(floppy->drive);
+ (void) idefloppy_get_sfrp_bit(drive);
idefloppy_create_format_unit_cmd(&pc, blocks, length, flags);
- if (idefloppy_queue_pc_tail(floppy->drive, &pc))
+ if (idefloppy_queue_pc_tail(drive, &pc))
err = -EIO;
out:
if (err)
- floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+ drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
return err;
}
@@ -1325,7 +1317,7 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file,
case CDROMEJECT:
/* fall through */
case CDROM_LOCKDOOR:
- return ide_floppy_lockdoor(floppy, &pc, arg, cmd);
+ return ide_floppy_lockdoor(drive, &pc, arg, cmd);
case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
return 0;
case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
@@ -1366,8 +1358,8 @@ static int idefloppy_media_changed(struct gendisk *disk)
drive->attach = 0;
return 0;
}
- ret = !!(floppy->flags & IDEFLOPPY_FLAG_MEDIA_CHANGED);
- floppy->flags &= ~IDEFLOPPY_FLAG_MEDIA_CHANGED;
+ ret = !!(drive->atapi_flags & IDE_AFLAG_MEDIA_CHANGED);
+ drive->atapi_flags &= ~IDE_AFLAG_MEDIA_CHANGED;
return ret;
}
diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c
index 2d92214096a..8fe8b5b9cf7 100644
--- a/drivers/ide/ide-generic.c
+++ b/drivers/ide/ide-generic.c
@@ -20,6 +20,11 @@
#include <linux/module.h>
#include <linux/ide.h>
+/* FIXME: convert m32r to use ide_platform host driver */
+#ifdef CONFIG_M32R
+#include <asm/m32r.h>
+#endif
+
#define DRV_NAME "ide_generic"
static int probe_mask = 0x03;
@@ -28,29 +33,21 @@ MODULE_PARM_DESC(probe_mask, "probe mask for legacy ISA IDE ports");
static ssize_t store_add(struct class *cls, const char *buf, size_t n)
{
- ide_hwif_t *hwif;
unsigned int base, ctl;
- int irq;
- hw_regs_t hw;
- u8 idx[] = { 0xff, 0xff, 0xff, 0xff };
+ int irq, rc;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
if (sscanf(buf, "%x:%x:%d", &base, &ctl, &irq) != 3)
return -EINVAL;
- hwif = ide_find_port();
- if (hwif == NULL)
- return -ENOENT;
-
memset(&hw, 0, sizeof(hw));
ide_std_init_ports(&hw, base, ctl);
hw.irq = irq;
hw.chipset = ide_generic;
- ide_init_port_hw(hwif, &hw);
-
- idx[0] = hwif->index;
-
- ide_device_add(idx, NULL);
+ rc = ide_host_add(NULL, hws, NULL);
+ if (rc)
+ return rc;
return n;
};
@@ -88,20 +85,41 @@ static int __init ide_generic_sysfs_init(void)
return 0;
}
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) \
+ || defined(CONFIG_PLAT_OPSPUT)
+static const u16 legacy_bases[] = { 0x1f0 };
+static const int legacy_irqs[] = { PLD_IRQ_CFIREQ };
+#elif defined(CONFIG_PLAT_MAPPI3)
+static const u16 legacy_bases[] = { 0x1f0, 0x170 };
+static const int legacy_irqs[] = { PLD_IRQ_CFIREQ, PLD_IRQ_IDEIREQ };
+#elif defined(CONFIG_ALPHA)
+static const u16 legacy_bases[] = { 0x1f0, 0x170, 0x1e8, 0x168 };
+static const int legacy_irqs[] = { 14, 15, 11, 10 };
+#else
+static const u16 legacy_bases[] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
+static const int legacy_irqs[] = { 14, 15, 11, 10, 8, 12 };
+#endif
+
static int __init ide_generic_init(void)
{
- u8 idx[MAX_HWIFS];
- int i;
-
+ hw_regs_t hw[MAX_HWIFS], *hws[MAX_HWIFS];
+ struct ide_host *host;
+ unsigned long io_addr;
+ int i, rc;
+
+#ifdef CONFIG_MIPS
+ if (!ide_probe_legacy())
+ return -ENODEV;
+#endif
printk(KERN_INFO DRV_NAME ": please use \"probe_mask=0x3f\" module "
"parameter for probing all legacy ISA IDE ports\n");
- for (i = 0; i < MAX_HWIFS; i++) {
- ide_hwif_t *hwif;
- unsigned long io_addr = ide_default_io_base(i);
- hw_regs_t hw;
+ memset(hws, 0, sizeof(hw_regs_t *) * MAX_HWIFS);
+
+ for (i = 0; i < ARRAY_SIZE(legacy_bases); i++) {
+ io_addr = legacy_bases[i];
- idx[i] = 0xff;
+ hws[i] = NULL;
if ((probe_mask & (1 << i)) && io_addr) {
if (!request_region(io_addr, 8, DRV_NAME)) {
@@ -119,33 +137,46 @@ static int __init ide_generic_init(void)
continue;
}
- /*
- * Skip probing if the corresponding
- * slot is already occupied.
- */
- hwif = ide_find_port();
- if (hwif == NULL || hwif->index != i) {
- idx[i] = 0xff;
- continue;
- }
+ memset(&hw[i], 0, sizeof(hw[i]));
+ ide_std_init_ports(&hw[i], io_addr, io_addr + 0x206);
+#ifdef CONFIG_IA64
+ hw[i].irq = isa_irq_to_vector(legacy_irqs[i]);
+#else
+ hw[i].irq = legacy_irqs[i];
+#endif
+ hw[i].chipset = ide_generic;
- memset(&hw, 0, sizeof(hw));
- ide_std_init_ports(&hw, io_addr, io_addr + 0x206);
- hw.irq = ide_default_irq(io_addr);
- hw.chipset = ide_generic;
- ide_init_port_hw(hwif, &hw);
-
- idx[i] = i;
+ hws[i] = &hw[i];
}
}
- ide_device_add_all(idx, NULL);
+ host = ide_host_alloc_all(NULL, hws);
+ if (host == NULL) {
+ rc = -ENOMEM;
+ goto err;
+ }
+
+ rc = ide_host_register(host, NULL, hws);
+ if (rc)
+ goto err_free;
if (ide_generic_sysfs_init())
printk(KERN_ERR DRV_NAME ": failed to create ide_generic "
"class\n");
return 0;
+err_free:
+ ide_host_free(host);
+err:
+ for (i = 0; i < MAX_HWIFS; i++) {
+ if (hws[i] == NULL)
+ continue;
+
+ io_addr = hws[i]->io_ports.data_addr;
+ release_region(io_addr + 0x206, 1);
+ release_region(io_addr, 8);
+ }
+ return rc;
}
module_init(ide_generic_init);
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 661b75a89d4..a896a283f27 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -330,7 +330,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
tf->error = err;
tf->status = stat;
- drive->hwif->tf_read(drive, task);
+ drive->hwif->tp_ops->tf_read(drive, task);
if (task->tf_flags & IDE_TFLAG_DYN)
kfree(task);
@@ -381,8 +381,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
if (err == ABRT_ERR) {
if (drive->select.b.lba &&
/* some newer drives don't support WIN_SPECIFY */
- hwif->INB(hwif->io_ports.command_addr) ==
- WIN_SPECIFY)
+ hwif->tp_ops->read_status(hwif) == WIN_SPECIFY)
return ide_stopped;
} else if ((err & BAD_CRC) == BAD_CRC) {
/* UDMA crc error, just retry the operation */
@@ -408,7 +407,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
return ide_stopped;
}
- if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
rq->errors |= ERROR_RESET;
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
@@ -435,10 +434,9 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
/* add decoding error stuff */
}
- if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
/* force an abort */
- hwif->OUTBSYNC(hwif, WIN_IDLEIMMEDIATE,
- hwif->io_ports.command_addr);
+ hwif->tp_ops->exec_command(hwif, WIN_IDLEIMMEDIATE);
if (rq->errors >= ERROR_MAX) {
ide_kill_rq(drive, rq);
@@ -712,7 +710,8 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
#ifdef DEBUG
printk("%s: DRIVE_CMD (null)\n", drive->name);
#endif
- ide_end_drive_cmd(drive, ide_read_status(drive), ide_read_error(drive));
+ ide_end_drive_cmd(drive, hwif->tp_ops->read_status(hwif),
+ ide_read_error(drive));
return ide_stopped;
}
@@ -747,16 +746,17 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
* the bus may be broken enough to walk on our toes at this
* point.
*/
+ ide_hwif_t *hwif = drive->hwif;
int rc;
#ifdef DEBUG_PM
printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name);
#endif
- rc = ide_wait_not_busy(HWIF(drive), 35000);
+ rc = ide_wait_not_busy(hwif, 35000);
if (rc)
printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
SELECT_DRIVE(drive);
- ide_set_irq(drive, 1);
- rc = ide_wait_not_busy(HWIF(drive), 100000);
+ hwif->tp_ops->set_irq(hwif, 1);
+ rc = ide_wait_not_busy(hwif, 100000);
if (rc)
printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
}
@@ -1042,7 +1042,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
* quirk_list may not like intr setups/cleanups
*/
if (drive->quirk_list != 1)
- ide_set_irq(drive, 0);
+ hwif->tp_ops->set_irq(hwif, 0);
}
hwgroup->hwif = hwif;
hwgroup->drive = drive;
@@ -1142,7 +1142,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
(void)hwif->dma_ops->dma_end(drive);
ret = ide_error(drive, "dma timeout error",
- ide_read_status(drive));
+ hwif->tp_ops->read_status(hwif));
} else {
printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
hwif->dma_ops->dma_timeout(drive);
@@ -1267,7 +1267,7 @@ void ide_timer_expiry (unsigned long data)
} else
startstop =
ide_error(drive, "irq timeout",
- ide_read_status(drive));
+ hwif->tp_ops->read_status(hwif));
}
drive->service_time = jiffies - drive->service_start;
spin_lock_irq(&ide_lock);
@@ -1323,7 +1323,8 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
*/
do {
if (hwif->irq == irq) {
- stat = hwif->INB(hwif->io_ports.status_addr);
+ stat = hwif->tp_ops->read_status(hwif);
+
if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
/* Try to not flood the console with msgs */
static unsigned long last_msgtime, count;
@@ -1413,7 +1414,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
* Whack the status register, just in case
* we have a leftover pending IRQ.
*/
- (void) hwif->INB(hwif->io_ports.status_addr);
+ (void)hwif->tp_ops->read_status(hwif);
#endif /* CONFIG_BLK_DEV_IDEPCI */
}
spin_unlock_irqrestore(&ide_lock, flags);
@@ -1519,6 +1520,7 @@ EXPORT_SYMBOL(ide_do_drive_cmd);
void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
{
+ ide_hwif_t *hwif = drive->hwif;
ide_task_t task;
memset(&task, 0, sizeof(task));
@@ -1529,9 +1531,9 @@ void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
task.tf.lbah = (bcount >> 8) & 0xff;
ide_tf_dump(drive->name, &task.tf);
- ide_set_irq(drive, 1);
+ hwif->tp_ops->set_irq(hwif, 1);
SELECT_MASK(drive, 0);
- drive->hwif->tf_load(drive, &task);
+ hwif->tp_ops->tf_load(drive, &task);
}
EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load);
@@ -1543,9 +1545,9 @@ void ide_pad_transfer(ide_drive_t *drive, int write, int len)
while (len > 0) {
if (write)
- hwif->output_data(drive, NULL, buf, min(4, len));
+ hwif->tp_ops->output_data(drive, NULL, buf, min(4, len));
else
- hwif->input_data(drive, NULL, buf, min(4, len));
+ hwif->tp_ops->input_data(drive, NULL, buf, min(4, len));
len -= 4;
}
}
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 44aaec256a3..8aae9176451 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -42,18 +42,6 @@ static void ide_outb (u8 val, unsigned long port)
outb(val, port);
}
-static void ide_outbsync(ide_hwif_t *hwif, u8 addr, unsigned long port)
-{
- outb(addr, port);
-}
-
-void default_hwif_iops (ide_hwif_t *hwif)
-{
- hwif->OUTB = ide_outb;
- hwif->OUTBSYNC = ide_outbsync;
- hwif->INB = ide_inb;
-}
-
/*
* MMIO operations, typically used for SATA controllers
*/
@@ -68,31 +56,19 @@ static void ide_mm_outb (u8 value, unsigned long port)
writeb(value, (void __iomem *) port);
}
-static void ide_mm_outbsync(ide_hwif_t *hwif, u8 value, unsigned long port)
-{
- writeb(value, (void __iomem *) port);
-}
-
-void default_hwif_mmiops (ide_hwif_t *hwif)
-{
- hwif->OUTB = ide_mm_outb;
- /* Most systems will need to override OUTBSYNC, alas however
- this one is controller specific! */
- hwif->OUTBSYNC = ide_mm_outbsync;
- hwif->INB = ide_mm_inb;
-}
-
-EXPORT_SYMBOL(default_hwif_mmiops);
-
void SELECT_DRIVE (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
const struct ide_port_ops *port_ops = hwif->port_ops;
+ ide_task_t task;
if (port_ops && port_ops->selectproc)
port_ops->selectproc(drive);
- hwif->OUTB(drive->select.all, hwif->io_ports.device_addr);
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_OUT_DEVICE;
+
+ drive->hwif->tp_ops->tf_load(drive, &task);
}
void SELECT_MASK(ide_drive_t *drive, int mask)
@@ -103,7 +79,61 @@ void SELECT_MASK(ide_drive_t *drive, int mask)
port_ops->maskproc(drive, mask);
}
-static void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+void ide_exec_command(ide_hwif_t *hwif, u8 cmd)
+{
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
+ else
+ outb(cmd, hwif->io_ports.command_addr);
+}
+EXPORT_SYMBOL_GPL(ide_exec_command);
+
+u8 ide_read_status(ide_hwif_t *hwif)
+{
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ return readb((void __iomem *)hwif->io_ports.status_addr);
+ else
+ return inb(hwif->io_ports.status_addr);
+}
+EXPORT_SYMBOL_GPL(ide_read_status);
+
+u8 ide_read_altstatus(ide_hwif_t *hwif)
+{
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ return readb((void __iomem *)hwif->io_ports.ctl_addr);
+ else
+ return inb(hwif->io_ports.ctl_addr);
+}
+EXPORT_SYMBOL_GPL(ide_read_altstatus);
+
+u8 ide_read_sff_dma_status(ide_hwif_t *hwif)
+{
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ return readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+ else
+ return inb(hwif->dma_base + ATA_DMA_STATUS);
+}
+EXPORT_SYMBOL_GPL(ide_read_sff_dma_status);
+
+void ide_set_irq(ide_hwif_t *hwif, int on)
+{
+ u8 ctl = ATA_DEVCTL_OBS;
+
+ if (on == 4) { /* hack for SRST */
+ ctl |= 4;
+ on &= ~4;
+ }
+
+ ctl |= on ? 0 : 2;
+
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
+ else
+ outb(ctl, hwif->io_ports.ctl_addr);
+}
+EXPORT_SYMBOL_GPL(ide_set_irq);
+
+void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -155,8 +185,9 @@ static void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
tf_outb((tf->device & HIHI) | drive->select.all,
io_ports->device_addr);
}
+EXPORT_SYMBOL_GPL(ide_tf_load);
-static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -188,6 +219,8 @@ static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
/* be sure we're looking at the low order bits */
tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+ tf->feature = tf_inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = tf_inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
@@ -214,6 +247,7 @@ static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
tf->hob_lbah = tf_inb(io_ports->lbah_addr);
}
}
+EXPORT_SYMBOL_GPL(ide_tf_read);
/*
* Some localbus EIDE interfaces require a special access sequence
@@ -236,8 +270,8 @@ static void ata_vlb_sync(unsigned long port)
* so if an odd len is specified, be sure that there's at least one
* extra byte allocated for the buffer.
*/
-static void ata_input_data(ide_drive_t *drive, struct request *rq,
- void *buf, unsigned int len)
+void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf,
+ unsigned int len)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -277,12 +311,13 @@ static void ata_input_data(ide_drive_t *drive, struct request *rq,
insw(data_addr, buf, len / 2);
}
}
+EXPORT_SYMBOL_GPL(ide_input_data);
/*
* This is used for most PIO data transfers *to* the IDE interface
*/
-static void ata_output_data(ide_drive_t *drive, struct request *rq,
- void *buf, unsigned int len)
+void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf,
+ unsigned int len)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -320,15 +355,50 @@ static void ata_output_data(ide_drive_t *drive, struct request *rq,
outsw(data_addr, buf, len / 2);
}
}
+EXPORT_SYMBOL_GPL(ide_output_data);
+
+u8 ide_read_error(ide_drive_t *drive)
+{
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_IN_FEATURE;
+
+ drive->hwif->tp_ops->tf_read(drive, &task);
+
+ return task.tf.error;
+}
+EXPORT_SYMBOL_GPL(ide_read_error);
-void default_hwif_transport(ide_hwif_t *hwif)
+void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason)
{
- hwif->tf_load = ide_tf_load;
- hwif->tf_read = ide_tf_read;
+ ide_task_t task;
- hwif->input_data = ata_input_data;
- hwif->output_data = ata_output_data;
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM |
+ IDE_TFLAG_IN_NSECT;
+
+ drive->hwif->tp_ops->tf_read(drive, &task);
+
+ *bcount = (task.tf.lbah << 8) | task.tf.lbam;
+ *ireason = task.tf.nsect & 3;
}
+EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
+
+const struct ide_tp_ops default_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = ide_input_data,
+ .output_data = ide_output_data,
+};
void ide_fix_driveid (struct hd_driveid *id)
{
@@ -440,10 +510,8 @@ void ide_fixstring (u8 *s, const int bytecount, const int byteswap)
if (byteswap) {
/* convert from big-endian to host byte order */
- for (p = end ; p != s;) {
- unsigned short *pp = (unsigned short *) (p -= 2);
- *pp = ntohs(*pp);
- }
+ for (p = end ; p != s;)
+ be16_to_cpus((u16 *)(p -= 2));
}
/* strip leading blanks */
while (s != end && *s == ' ')
@@ -483,10 +551,10 @@ int drive_is_ready (ide_drive_t *drive)
* about possible isa-pnp and pci-pnp issues yet.
*/
if (hwif->io_ports.ctl_addr)
- stat = ide_read_altstatus(drive);
+ stat = hwif->tp_ops->read_altstatus(hwif);
else
/* Note: this may clear a pending IRQ!! */
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
if (stat & BUSY_STAT)
/* drive busy: definitely not interrupting */
@@ -511,24 +579,26 @@ EXPORT_SYMBOL(drive_is_ready);
*/
static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat)
{
+ ide_hwif_t *hwif = drive->hwif;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
unsigned long flags;
int i;
u8 stat;
udelay(1); /* spec allows drive 400ns to assert "BUSY" */
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (stat & BUSY_STAT) {
local_irq_set(flags);
timeout += jiffies;
- while ((stat = ide_read_status(drive)) & BUSY_STAT) {
+ while ((stat = tp_ops->read_status(hwif)) & BUSY_STAT) {
if (time_after(jiffies, timeout)) {
/*
* One last read after the timeout in case
* heavy interrupt load made us not make any
* progress during the timeout..
*/
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (!(stat & BUSY_STAT))
break;
@@ -548,7 +618,7 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti
*/
for (i = 0; i < 10; i++) {
udelay(1);
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (OK_STAT(stat, good, bad)) {
*rstat = stat;
@@ -674,6 +744,7 @@ no_80w:
int ide_driveid_update(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
struct hd_driveid *id;
unsigned long timeout, flags;
u8 stat;
@@ -684,9 +755,9 @@ int ide_driveid_update(ide_drive_t *drive)
*/
SELECT_MASK(drive, 1);
- ide_set_irq(drive, 0);
+ tp_ops->set_irq(hwif, 0);
msleep(50);
- hwif->OUTBSYNC(hwif, WIN_IDENTIFY, hwif->io_ports.command_addr);
+ tp_ops->exec_command(hwif, WIN_IDENTIFY);
timeout = jiffies + WAIT_WORSTCASE;
do {
if (time_after(jiffies, timeout)) {
@@ -695,11 +766,11 @@ int ide_driveid_update(ide_drive_t *drive)
}
msleep(50); /* give drive a breather */
- stat = ide_read_altstatus(drive);
+ stat = tp_ops->read_altstatus(hwif);
} while (stat & BUSY_STAT);
msleep(50); /* wait for IRQ and DRQ_STAT */
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) {
SELECT_MASK(drive, 0);
@@ -713,8 +784,8 @@ int ide_driveid_update(ide_drive_t *drive)
local_irq_restore(flags);
return 0;
}
- hwif->input_data(drive, NULL, id, SECTOR_SIZE);
- (void)ide_read_status(drive); /* clear drive IRQ */
+ tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
+ (void)tp_ops->read_status(hwif); /* clear drive IRQ */
local_irq_enable();
local_irq_restore(flags);
ide_fix_driveid(id);
@@ -735,9 +806,10 @@ int ide_driveid_update(ide_drive_t *drive)
int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
{
ide_hwif_t *hwif = drive->hwif;
- struct ide_io_ports *io_ports = &hwif->io_ports;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
int error = 0;
u8 stat;
+ ide_task_t task;
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_ops) /* check if host supports DMA */
@@ -770,12 +842,19 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
SELECT_DRIVE(drive);
SELECT_MASK(drive, 0);
udelay(1);
- ide_set_irq(drive, 0);
- hwif->OUTB(speed, io_ports->nsect_addr);
- hwif->OUTB(SETFEATURES_XFER, io_ports->feature_addr);
- hwif->OUTBSYNC(hwif, WIN_SETFEATURES, io_ports->command_addr);
+ tp_ops->set_irq(hwif, 0);
+
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT;
+ task.tf.feature = SETFEATURES_XFER;
+ task.tf.nsect = speed;
+
+ tp_ops->tf_load(drive, &task);
+
+ tp_ops->exec_command(hwif, WIN_SETFEATURES);
+
if (drive->quirk_list == 2)
- ide_set_irq(drive, 1);
+ tp_ops->set_irq(hwif, 1);
error = __ide_wait_stat(drive, drive->ready_stat,
BUSY_STAT|DRQ_STAT|ERR_STAT,
@@ -796,8 +875,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
skip:
#ifdef CONFIG_BLK_DEV_IDEDMA
- if ((speed >= XFER_SW_DMA_0 || (hwif->host_flags & IDE_HFLAG_VDMA)) &&
- drive->using_dma)
+ if (speed >= XFER_SW_DMA_0 && drive->using_dma)
hwif->dma_ops->dma_host_set(drive, 1);
else if (hwif->dma_ops) /* check if host supports DMA */
ide_dma_off_quietly(drive);
@@ -881,7 +959,7 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
spin_lock_irqsave(&ide_lock, flags);
__ide_set_handler(drive, handler, timeout, expiry);
- hwif->OUTBSYNC(hwif, cmd, hwif->io_ports.command_addr);
+ hwif->tp_ops->exec_command(hwif, cmd);
/*
* Drive takes 400nS to respond, we must avoid the IRQ being
* serviced before that.
@@ -899,7 +977,7 @@ void ide_execute_pkt_cmd(ide_drive_t *drive)
unsigned long flags;
spin_lock_irqsave(&ide_lock, flags);
- hwif->OUTBSYNC(hwif, WIN_PACKETCMD, hwif->io_ports.command_addr);
+ hwif->tp_ops->exec_command(hwif, WIN_PACKETCMD);
ndelay(400);
spin_unlock_irqrestore(&ide_lock, flags);
}
@@ -924,12 +1002,13 @@ static ide_startstop_t do_reset1 (ide_drive_t *, int);
*/
static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
{
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
+ ide_hwif_t *hwif = drive->hwif;
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
u8 stat;
SELECT_DRIVE(drive);
udelay (10);
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
if (OK_STAT(stat, 0, BUSY_STAT))
printk("%s: ATAPI reset complete\n", drive->name);
@@ -975,7 +1054,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
}
}
- tmp = ide_read_status(drive);
+ tmp = hwif->tp_ops->read_status(hwif);
if (!OK_STAT(tmp, 0, BUSY_STAT)) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
@@ -1089,8 +1168,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
ide_hwif_t *hwif;
ide_hwgroup_t *hwgroup;
struct ide_io_ports *io_ports;
+ const struct ide_tp_ops *tp_ops;
const struct ide_port_ops *port_ops;
- u8 ctl;
spin_lock_irqsave(&ide_lock, flags);
hwif = HWIF(drive);
@@ -1098,6 +1177,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
io_ports = &hwif->io_ports;
+ tp_ops = hwif->tp_ops;
+
/* We must not reset with running handlers */
BUG_ON(hwgroup->handler != NULL);
@@ -1106,7 +1187,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
pre_reset(drive);
SELECT_DRIVE(drive);
udelay (20);
- hwif->OUTBSYNC(hwif, WIN_SRST, io_ports->command_addr);
+ tp_ops->exec_command(hwif, WIN_SRST);
ndelay(400);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
hwgroup->polling = 1;
@@ -1135,16 +1216,15 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
* immediate interrupt due to the edge transition it produces.
* This single interrupt gives us a "fast poll" for drives that
* recover from reset very quickly, saving us the first 50ms wait time.
+ *
+ * TODO: add ->softreset method and stop abusing ->set_irq
*/
/* set SRST and nIEN */
- hwif->OUTBSYNC(hwif, ATA_DEVCTL_OBS | 6, io_ports->ctl_addr);
+ tp_ops->set_irq(hwif, 4);
/* more than enough time */
udelay(10);
- if (drive->quirk_list == 2)
- ctl = ATA_DEVCTL_OBS; /* clear SRST and nIEN */
- else
- ctl = ATA_DEVCTL_OBS | 2; /* clear SRST, leave nIEN */
- hwif->OUTBSYNC(hwif, ctl, io_ports->ctl_addr);
+ /* clear SRST, leave nIEN (unless device is on the quirk list) */
+ tp_ops->set_irq(hwif, drive->quirk_list == 2);
/* more than enough time */
udelay(10);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
@@ -1189,7 +1269,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
* about locking issues (2.5 work ?).
*/
mdelay(1);
- stat = hwif->INB(hwif->io_ports.status_addr);
+ stat = hwif->tp_ops->read_status(hwif);
if ((stat & BUSY_STAT) == 0)
return 0;
/*
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 13af72f09ec..97fefabea8b 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -266,22 +266,11 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
rate = ide_rate_filter(drive, rate);
+ BUG_ON(rate < XFER_PIO_0);
+
if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5)
return ide_set_pio_mode(drive, rate);
- /*
- * TODO: transfer modes 0x00-0x07 passed from the user-space are
- * currently handled here which needs fixing (please note that such
- * case could happen iff the transfer mode has already been set on
- * the device by ide-proc.c::set_xfer_rate()).
- */
- if (rate < XFER_PIO_0) {
- if (hwif->host_flags & IDE_HFLAG_ABUSE_SET_DMA_MODE)
- return ide_set_dma_mode(drive, rate);
- else
- return ide_config_drive_speed(drive, rate);
- }
-
return ide_set_dma_mode(drive, rate);
}
@@ -336,7 +325,7 @@ static void ide_dump_sector(ide_drive_t *drive)
else
task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
- drive->hwif->tf_read(drive, &task);
+ drive->hwif->tp_ops->tf_read(drive, &task);
if (lba48 || (tf->device & ATA_LBA))
printk(", LBAsect=%llu",
diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
index 03f2ef5470a..bac9b392b68 100644
--- a/drivers/ide/ide-pnp.c
+++ b/drivers/ide/ide-pnp.c
@@ -29,9 +29,10 @@ static struct pnp_device_id idepnp_devices[] = {
static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
{
- hw_regs_t hw;
- ide_hwif_t *hwif;
+ struct ide_host *host;
unsigned long base, ctl;
+ int rc;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
printk(KERN_INFO DRV_NAME ": generic PnP IDE interface\n");
@@ -59,31 +60,25 @@ static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
hw.irq = pnp_irq(dev, 0);
hw.chipset = ide_generic;
- hwif = ide_find_port();
- if (hwif) {
- u8 index = hwif->index;
- u8 idx[4] = { index, 0xff, 0xff, 0xff };
+ rc = ide_host_add(NULL, hws, &host);
+ if (rc)
+ goto out;
- ide_init_port_hw(hwif, &hw);
-
- pnp_set_drvdata(dev, hwif);
-
- ide_device_add(idx, NULL);
-
- return 0;
- }
+ pnp_set_drvdata(dev, host);
+ return 0;
+out:
release_region(ctl, 1);
release_region(base, 8);
- return -1;
+ return rc;
}
static void idepnp_remove(struct pnp_dev *dev)
{
- ide_hwif_t *hwif = pnp_get_drvdata(dev);
+ struct ide_host *host = pnp_get_drvdata(dev);
- ide_unregister(hwif);
+ ide_host_remove(host);
release_region(pnp_port_start(dev, 1), 1);
release_region(pnp_port_start(dev, 0), 8);
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 235ebdb29b2..994e41099b4 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -39,8 +39,6 @@
#include <asm/uaccess.h>
#include <asm/io.h>
-static ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
-
/**
* generic_id - add a generic drive id
* @drive: drive to make an ID block for
@@ -126,7 +124,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
id = drive->id;
/* read 512 bytes of id info */
- hwif->input_data(drive, NULL, id, SECTOR_SIZE);
+ hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
drive->id_read = 1;
local_irq_enable();
@@ -136,18 +134,6 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
#endif
ide_fix_driveid(id);
-#if defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
- /*
- * EATA SCSI controllers do a hardware ATA emulation:
- * Ignore them if there is a driver for them available.
- */
- if ((id->model[0] == 'P' && id->model[1] == 'M') ||
- (id->model[0] == 'S' && id->model[1] == 'K')) {
- printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model);
- goto err_misc;
- }
-#endif /* CONFIG_SCSI_EATA || CONFIG_SCSI_EATA_PIO */
-
/*
* WIN_IDENTIFY returns little-endian info,
* WIN_PIDENTIFY *usually* returns little-endian info.
@@ -169,7 +155,8 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
if (strstr(id->model, "E X A B Y T E N E S T"))
goto err_misc;
- printk("%s: %s, ", drive->name, id->model);
+ printk(KERN_INFO "%s: %s, ", drive->name, id->model);
+
drive->present = 1;
drive->dead = 0;
@@ -178,16 +165,17 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
*/
if (cmd == WIN_PIDENTIFY) {
u8 type = (id->config >> 8) & 0x1f;
- printk("ATAPI ");
+
+ printk(KERN_CONT "ATAPI ");
switch (type) {
case ide_floppy:
if (!strstr(id->model, "CD-ROM")) {
if (!strstr(id->model, "oppy") &&
!strstr(id->model, "poyp") &&
!strstr(id->model, "ZIP"))
- printk("cdrom or floppy?, assuming ");
+ printk(KERN_CONT "cdrom or floppy?, assuming ");
if (drive->media != ide_cdrom) {
- printk ("FLOPPY");
+ printk(KERN_CONT "FLOPPY");
drive->removable = 1;
break;
}
@@ -200,25 +188,25 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
/* kludge for Apple PowerBook internal zip */
if (!strstr(id->model, "CD-ROM") &&
strstr(id->model, "ZIP")) {
- printk ("FLOPPY");
+ printk(KERN_CONT "FLOPPY");
type = ide_floppy;
break;
}
#endif
- printk ("CD/DVD-ROM");
+ printk(KERN_CONT "CD/DVD-ROM");
break;
case ide_tape:
- printk ("TAPE");
+ printk(KERN_CONT "TAPE");
break;
case ide_optical:
- printk ("OPTICAL");
+ printk(KERN_CONT "OPTICAL");
drive->removable = 1;
break;
default:
- printk("UNKNOWN (type %d)", type);
+ printk(KERN_CONT "UNKNOWN (type %d)", type);
break;
}
- printk (" drive\n");
+ printk(KERN_CONT " drive\n");
drive->media = type;
/* an ATAPI device ignores DRDY */
drive->ready_stat = 0;
@@ -238,7 +226,9 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
drive->removable = 1;
drive->media = ide_disk;
- printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" );
+
+ printk(KERN_CONT "%s DISK drive\n",
+ (id->config == 0x848a) ? "CFA" : "ATA");
return;
@@ -267,6 +257,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
{
ide_hwif_t *hwif = HWIF(drive);
struct ide_io_ports *io_ports = &hwif->io_ports;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
int use_altstatus = 0, rc;
unsigned long timeout;
u8 s = 0, a = 0;
@@ -275,8 +266,8 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
msleep(50);
if (io_ports->ctl_addr) {
- a = ide_read_altstatus(drive);
- s = ide_read_status(drive);
+ a = tp_ops->read_altstatus(hwif);
+ s = tp_ops->read_status(hwif);
if ((a ^ s) & ~INDEX_STAT)
/* ancient Seagate drives, broken interfaces */
printk(KERN_INFO "%s: probing with STATUS(0x%02x) "
@@ -290,12 +281,18 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
/* set features register for atapi
* identify command to be sure of reply
*/
- if ((cmd == WIN_PIDENTIFY))
- /* disable dma & overlap */
- hwif->OUTB(0, io_ports->feature_addr);
+ if (cmd == WIN_PIDENTIFY) {
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ /* disable DMA & overlap */
+ task.tf_flags = IDE_TFLAG_OUT_FEATURE;
+
+ tp_ops->tf_load(drive, &task);
+ }
/* ask drive for ID */
- hwif->OUTBSYNC(hwif, cmd, hwif->io_ports.command_addr);
+ tp_ops->exec_command(hwif, cmd);
timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
timeout += jiffies;
@@ -306,13 +303,13 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
}
/* give drive a breather */
msleep(50);
- s = use_altstatus ? ide_read_altstatus(drive)
- : ide_read_status(drive);
+ s = use_altstatus ? tp_ops->read_altstatus(hwif)
+ : tp_ops->read_status(hwif);
} while (s & BUSY_STAT);
/* wait for IRQ and DRQ_STAT */
msleep(50);
- s = ide_read_status(drive);
+ s = tp_ops->read_status(hwif);
if (OK_STAT(s, DRQ_STAT, BAD_R_STAT)) {
unsigned long flags;
@@ -324,7 +321,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
/* drive responded with ID */
rc = 0;
/* clear drive IRQ */
- (void)ide_read_status(drive);
+ (void)tp_ops->read_status(hwif);
local_irq_restore(flags);
} else {
/* drive refused ID */
@@ -346,6 +343,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
static int try_to_identify (ide_drive_t *drive, u8 cmd)
{
ide_hwif_t *hwif = HWIF(drive);
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
int retval;
int autoprobe = 0;
unsigned long cookie = 0;
@@ -361,7 +359,7 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
autoprobe = 1;
cookie = probe_irq_on();
}
- ide_set_irq(drive, autoprobe);
+ tp_ops->set_irq(hwif, autoprobe);
}
retval = actual_try_to_identify(drive, cmd);
@@ -369,9 +367,9 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
if (autoprobe) {
int irq;
- ide_set_irq(drive, 0);
+ tp_ops->set_irq(hwif, 0);
/* clear drive IRQ */
- (void)ide_read_status(drive);
+ (void)tp_ops->read_status(hwif);
udelay(5);
irq = probe_irq_off(cookie);
if (!hwif->irq) {
@@ -381,7 +379,7 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
/* Mmmm.. multiple IRQs..
* don't know which was ours
*/
- printk("%s: IRQ probe failed (0x%lx)\n",
+ printk(KERN_ERR "%s: IRQ probe failed (0x%lx)\n",
drive->name, cookie);
}
}
@@ -396,7 +394,7 @@ static int ide_busy_sleep(ide_hwif_t *hwif)
do {
msleep(50);
- stat = hwif->INB(hwif->io_ports.status_addr);
+ stat = hwif->tp_ops->read_status(hwif);
if ((stat & BUSY_STAT) == 0)
return 0;
} while (time_before(jiffies, timeout));
@@ -404,6 +402,18 @@ static int ide_busy_sleep(ide_hwif_t *hwif)
return 1;
}
+static u8 ide_read_device(ide_drive_t *drive)
+{
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_IN_DEVICE;
+
+ drive->hwif->tp_ops->tf_read(drive, &task);
+
+ return task.tf.device;
+}
+
/**
* do_probe - probe an IDE device
* @drive: drive to probe
@@ -428,7 +438,7 @@ static int ide_busy_sleep(ide_hwif_t *hwif)
static int do_probe (ide_drive_t *drive, u8 cmd)
{
ide_hwif_t *hwif = HWIF(drive);
- struct ide_io_ports *io_ports = &hwif->io_ports;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
int rc;
u8 stat;
@@ -438,7 +448,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
return 4;
}
#ifdef DEBUG
- printk("probing for %s: present=%d, media=%d, probetype=%s\n",
+ printk(KERN_INFO "probing for %s: present=%d, media=%d, probetype=%s\n",
drive->name, drive->present, drive->media,
(cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI");
#endif
@@ -449,8 +459,8 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
msleep(50);
SELECT_DRIVE(drive);
msleep(50);
- if (hwif->INB(io_ports->device_addr) != drive->select.all &&
- !drive->present) {
+
+ if (ide_read_device(drive) != drive->select.all && !drive->present) {
if (drive->select.b.unit != 0) {
/* exit with drive0 selected */
SELECT_DRIVE(&hwif->drives[0]);
@@ -461,7 +471,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
return 3;
}
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (OK_STAT(stat, READY_STAT, BUSY_STAT) ||
drive->present || cmd == WIN_PIDENTIFY) {
@@ -471,7 +481,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
rc = try_to_identify(drive,cmd);
}
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (stat == (BUSY_STAT | READY_STAT))
return 4;
@@ -482,13 +492,13 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
msleep(50);
SELECT_DRIVE(drive);
msleep(50);
- hwif->OUTBSYNC(hwif, WIN_SRST, io_ports->command_addr);
+ tp_ops->exec_command(hwif, WIN_SRST);
(void)ide_busy_sleep(hwif);
rc = try_to_identify(drive, cmd);
}
/* ensure drive IRQ is clear */
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (rc == 1)
printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
@@ -502,7 +512,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
SELECT_DRIVE(&hwif->drives[0]);
msleep(50);
/* ensure drive irq is clear */
- (void)ide_read_status(drive);
+ (void)tp_ops->read_status(hwif);
}
return rc;
}
@@ -513,12 +523,14 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
static void enable_nest (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
u8 stat;
- printk("%s: enabling %s -- ", hwif->name, drive->id->model);
+ printk(KERN_INFO "%s: enabling %s -- ", hwif->name, drive->id->model);
+
SELECT_DRIVE(drive);
msleep(50);
- hwif->OUTBSYNC(hwif, EXABYTE_ENABLE_NEST, hwif->io_ports.command_addr);
+ tp_ops->exec_command(hwif, EXABYTE_ENABLE_NEST);
if (ide_busy_sleep(hwif)) {
printk(KERN_CONT "failed (timeout)\n");
@@ -527,7 +539,7 @@ static void enable_nest (ide_drive_t *drive)
msleep(50);
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (!OK_STAT(stat, 0, BAD_STAT))
printk(KERN_CONT "failed (status = 0x%02x)\n", stat);
@@ -619,7 +631,7 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
return drive->present;
}
-static void hwif_release_dev (struct device *dev)
+static void hwif_release_dev(struct device *dev)
{
ide_hwif_t *hwif = container_of(dev, ide_hwif_t, gendev);
@@ -709,7 +721,7 @@ static int ide_port_wait_ready(ide_hwif_t *hwif)
/* Ignore disks that we will not probe for later. */
if (!drive->noprobe || drive->present) {
SELECT_DRIVE(drive);
- ide_set_irq(drive, 1);
+ hwif->tp_ops->set_irq(hwif, 1);
mdelay(2);
rc = ide_wait_not_busy(hwif, 35000);
if (rc)
@@ -864,7 +876,7 @@ static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
if (m && m->hwgroup && m->hwgroup != new->hwgroup) {
if (!new->hwgroup)
return;
- printk("%s: potential irq problem with %s and %s\n",
+ printk(KERN_WARNING "%s: potential IRQ problem with %s and %s\n",
hwif->name, new->name, m->name);
}
if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */
@@ -971,6 +983,45 @@ static void ide_port_setup_devices(ide_hwif_t *hwif)
mutex_unlock(&ide_cfg_mtx);
}
+static ide_hwif_t *ide_ports[MAX_HWIFS];
+
+void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
+{
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
+
+ ide_ports[hwif->index] = NULL;
+
+ spin_lock_irq(&ide_lock);
+ /*
+ * Remove us from the hwgroup, and free
+ * the hwgroup if we were the only member
+ */
+ if (hwif->next == hwif) {
+ BUG_ON(hwgroup->hwif != hwif);
+ kfree(hwgroup);
+ } else {
+ /* There is another interface in hwgroup.
+ * Unlink us, and set hwgroup->drive and ->hwif to
+ * something sane.
+ */
+ ide_hwif_t *g = hwgroup->hwif;
+
+ while (g->next != hwif)
+ g = g->next;
+ g->next = hwif->next;
+ if (hwgroup->hwif == hwif) {
+ /* Chose a random hwif for hwgroup->hwif.
+ * It's guaranteed that there are no drives
+ * left in the hwgroup.
+ */
+ BUG_ON(hwgroup->drive != NULL);
+ hwgroup->hwif = g;
+ }
+ BUG_ON(hwgroup->hwif == hwif);
+ }
+ spin_unlock_irq(&ide_lock);
+}
+
/*
* This routine sets up the irq for an ide interface, and creates a new
* hwgroup for the irq/hwif if none was previously assigned.
@@ -998,8 +1049,9 @@ static int init_irq (ide_hwif_t *hwif)
* Group up with any other hwifs that share our irq(s).
*/
for (index = 0; index < MAX_HWIFS; index++) {
- ide_hwif_t *h = &ide_hwifs[index];
- if (h->hwgroup) { /* scan only initialized hwif's */
+ ide_hwif_t *h = ide_ports[index];
+
+ if (h && h->hwgroup) { /* scan only initialized ports */
if (hwif->irq == h->irq) {
hwif->sharing_irq = h->sharing_irq = 1;
if (hwif->chipset != ide_pci ||
@@ -1053,6 +1105,8 @@ static int init_irq (ide_hwif_t *hwif)
hwgroup->timer.data = (unsigned long) hwgroup;
}
+ ide_ports[hwif->index] = hwif;
+
/*
* Allocate the irq, if not already obtained for another hwif
*/
@@ -1066,8 +1120,7 @@ static int init_irq (ide_hwif_t *hwif)
sa = IRQF_SHARED;
if (io_ports->ctl_addr)
- /* clear nIEN */
- hwif->OUTBSYNC(hwif, ATA_DEVCTL_OBS, io_ports->ctl_addr);
+ hwif->tp_ops->set_irq(hwif, 1);
if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup))
goto out_unlink;
@@ -1082,17 +1135,17 @@ static int init_irq (ide_hwif_t *hwif)
}
#if !defined(__mc68000__)
- printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
+ printk(KERN_INFO "%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
io_ports->data_addr, io_ports->status_addr,
io_ports->ctl_addr, hwif->irq);
#else
- printk("%s at 0x%08lx on irq %d", hwif->name,
+ printk(KERN_INFO "%s at 0x%08lx on irq %d", hwif->name,
io_ports->data_addr, hwif->irq);
#endif /* __mc68000__ */
if (match)
- printk(" (%sed with %s)",
+ printk(KERN_CONT " (%sed with %s)",
hwif->sharing_irq ? "shar" : "serializ", match->name);
- printk("\n");
+ printk(KERN_CONT "\n");
mutex_unlock(&ide_cfg_mtx);
return 0;
@@ -1227,7 +1280,7 @@ static int hwif_init(ide_hwif_t *hwif)
if (!hwif->irq) {
hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
if (!hwif->irq) {
- printk("%s: DISABLED, NO IRQ\n", hwif->name);
+ printk(KERN_ERR "%s: disabled, no IRQ\n", hwif->name);
return 0;
}
}
@@ -1257,16 +1310,16 @@ static int hwif_init(ide_hwif_t *hwif)
*/
hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
if (!hwif->irq) {
- printk("%s: Disabled unable to get IRQ %d.\n",
+ printk(KERN_ERR "%s: disabled, unable to get IRQ %d\n",
hwif->name, old_irq);
goto out;
}
if (init_irq(hwif)) {
- printk("%s: probed IRQ %d and default IRQ %d failed.\n",
+ printk(KERN_ERR "%s: probed IRQ %d and default IRQ %d failed\n",
hwif->name, old_irq, hwif->irq);
goto out;
}
- printk("%s: probed IRQ %d failed, using default.\n",
+ printk(KERN_WARNING "%s: probed IRQ %d failed, using default\n",
hwif->name, hwif->irq);
done:
@@ -1345,6 +1398,9 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
hwif->host_flags |= d->host_flags;
hwif->pio_mask = d->pio_mask;
+ if (d->tp_ops)
+ hwif->tp_ops = d->tp_ops;
+
/* ->set_pio_mode for DTC2278 is currently limited to port 0 */
if (hwif->chipset != ide_dtc2278 || hwif->channel == 0)
hwif->port_ops = d->port_ops;
@@ -1363,6 +1419,7 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
if (rc < 0) {
printk(KERN_INFO "%s: DMA disabled\n", hwif->name);
+ hwif->dma_base = 0;
hwif->swdma_mask = 0;
hwif->mwdma_mask = 0;
hwif->ultra_mask = 0;
@@ -1446,18 +1503,20 @@ static int ide_sysfs_register_port(ide_hwif_t *hwif)
return rc;
}
+static unsigned int ide_indexes;
+
/**
- * ide_find_port_slot - find free ide_hwifs[] slot
+ * ide_find_port_slot - find free port slot
* @d: IDE port info
*
- * Return the new hwif. If we are out of free slots return NULL.
+ * Return the new port slot index or -ENOENT if we are out of free slots.
*/
-ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
+static int ide_find_port_slot(const struct ide_port_info *d)
{
- ide_hwif_t *hwif;
- int i;
+ int idx = -ENOENT;
u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1;
+ u8 i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;;
/*
* Claim an unassigned slot.
@@ -1469,51 +1528,114 @@ ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
* Unless there is a bootable card that does not use the standard
* ports 0x1f0/0x170 (the ide0/ide1 defaults).
*/
- if (bootable) {
- i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;
-
- for (; i < MAX_HWIFS; i++) {
- hwif = &ide_hwifs[i];
- if (hwif->chipset == ide_unknown)
- goto out_found;
- }
+ mutex_lock(&ide_cfg_mtx);
+ if (MAX_HWIFS == 1) {
+ if (ide_indexes == 0 && i == 0)
+ idx = 1;
} else {
- for (i = 2; i < MAX_HWIFS; i++) {
- hwif = &ide_hwifs[i];
- if (hwif->chipset == ide_unknown)
- goto out_found;
+ if (bootable) {
+ if ((ide_indexes | i) != (1 << MAX_HWIFS) - 1)
+ idx = ffz(ide_indexes | i);
+ } else {
+ if ((ide_indexes | 3) != (1 << MAX_HWIFS) - 1)
+ idx = ffz(ide_indexes | 3);
+ else if ((ide_indexes & 3) != 3)
+ idx = ffz(ide_indexes);
}
- for (i = 0; i < 2 && i < MAX_HWIFS; i++) {
- hwif = &ide_hwifs[i];
- if (hwif->chipset == ide_unknown)
- goto out_found;
+ }
+ if (idx >= 0)
+ ide_indexes |= (1 << idx);
+ mutex_unlock(&ide_cfg_mtx);
+
+ return idx;
+}
+
+static void ide_free_port_slot(int idx)
+{
+ mutex_lock(&ide_cfg_mtx);
+ ide_indexes &= ~(1 << idx);
+ mutex_unlock(&ide_cfg_mtx);
+}
+
+struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
+ hw_regs_t **hws)
+{
+ struct ide_host *host;
+ int i;
+
+ host = kzalloc(sizeof(*host), GFP_KERNEL);
+ if (host == NULL)
+ return NULL;
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+ ide_hwif_t *hwif;
+ int idx;
+
+ if (hws[i] == NULL)
+ continue;
+
+ hwif = kzalloc(sizeof(*hwif), GFP_KERNEL);
+ if (hwif == NULL)
+ continue;
+
+ idx = ide_find_port_slot(d);
+ if (idx < 0) {
+ printk(KERN_ERR "%s: no free slot for interface\n",
+ d ? d->name : "ide");
+ kfree(hwif);
+ continue;
}
+
+ ide_init_port_data(hwif, idx);
+
+ hwif->host = host;
+
+ host->ports[i] = hwif;
+ host->n_ports++;
}
- printk(KERN_ERR "%s: no free slot for interface\n",
- d ? d->name : "ide");
+ if (host->n_ports == 0) {
+ kfree(host);
+ return NULL;
+ }
- return NULL;
+ if (hws[0])
+ host->dev[0] = hws[0]->dev;
+
+ if (d)
+ host->host_flags = d->host_flags;
-out_found:
- ide_init_port_data(hwif, i);
- return hwif;
+ return host;
}
-EXPORT_SYMBOL_GPL(ide_find_port_slot);
+EXPORT_SYMBOL_GPL(ide_host_alloc_all);
-int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
+{
+ hw_regs_t *hws_all[MAX_HWIFS];
+ int i;
+
+ for (i = 0; i < MAX_HWIFS; i++)
+ hws_all[i] = (i < 4) ? hws[i] : NULL;
+
+ return ide_host_alloc_all(d, hws_all);
+}
+EXPORT_SYMBOL_GPL(ide_host_alloc);
+
+int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
+ hw_regs_t **hws)
{
ide_hwif_t *hwif, *mate = NULL;
- int i, rc = 0;
+ int i, j = 0;
for (i = 0; i < MAX_HWIFS; i++) {
- if (idx[i] == 0xff) {
+ hwif = host->ports[i];
+
+ if (hwif == NULL) {
mate = NULL;
continue;
}
- hwif = &ide_hwifs[idx[i]];
-
+ ide_init_port_hw(hwif, hws[i]);
ide_port_apply_params(hwif);
if (d == NULL) {
@@ -1534,10 +1656,10 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
}
for (i = 0; i < MAX_HWIFS; i++) {
- if (idx[i] == 0xff)
- continue;
+ hwif = host->ports[i];
- hwif = &ide_hwifs[idx[i]];
+ if (hwif == NULL)
+ continue;
if (ide_probe_port(hwif) == 0)
hwif->present = 1;
@@ -1551,19 +1673,20 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
}
for (i = 0; i < MAX_HWIFS; i++) {
- if (idx[i] == 0xff)
- continue;
+ hwif = host->ports[i];
- hwif = &ide_hwifs[idx[i]];
+ if (hwif == NULL)
+ continue;
if (hwif_init(hwif) == 0) {
printk(KERN_INFO "%s: failed to initialize IDE "
"interface\n", hwif->name);
hwif->present = 0;
- rc = -1;
continue;
}
+ j++;
+
if (hwif->present)
ide_port_setup_devices(hwif);
@@ -1574,10 +1697,10 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
}
for (i = 0; i < MAX_HWIFS; i++) {
- if (idx[i] == 0xff)
- continue;
+ hwif = host->ports[i];
- hwif = &ide_hwifs[idx[i]];
+ if (hwif == NULL)
+ continue;
if (hwif->chipset == ide_unknown)
hwif->chipset = ide_generic;
@@ -1587,10 +1710,10 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
}
for (i = 0; i < MAX_HWIFS; i++) {
- if (idx[i] == 0xff)
- continue;
+ hwif = host->ports[i];
- hwif = &ide_hwifs[idx[i]];
+ if (hwif == NULL)
+ continue;
ide_sysfs_register_port(hwif);
ide_proc_register_port(hwif);
@@ -1599,21 +1722,64 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
ide_proc_port_register_devices(hwif);
}
- return rc;
+ return j ? 0 : -1;
}
-EXPORT_SYMBOL_GPL(ide_device_add_all);
+EXPORT_SYMBOL_GPL(ide_host_register);
-int ide_device_add(u8 idx[4], const struct ide_port_info *d)
+int ide_host_add(const struct ide_port_info *d, hw_regs_t **hws,
+ struct ide_host **hostp)
{
- u8 idx_all[MAX_HWIFS];
+ struct ide_host *host;
+ int rc;
+
+ host = ide_host_alloc(d, hws);
+ if (host == NULL)
+ return -ENOMEM;
+
+ rc = ide_host_register(host, d, hws);
+ if (rc) {
+ ide_host_free(host);
+ return rc;
+ }
+
+ if (hostp)
+ *hostp = host;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ide_host_add);
+
+void ide_host_free(struct ide_host *host)
+{
+ ide_hwif_t *hwif;
int i;
- for (i = 0; i < MAX_HWIFS; i++)
- idx_all[i] = (i < 4) ? idx[i] : 0xff;
+ for (i = 0; i < MAX_HWIFS; i++) {
+ hwif = host->ports[i];
+
+ if (hwif == NULL)
+ continue;
+
+ ide_free_port_slot(hwif->index);
+ kfree(hwif);
+ }
- return ide_device_add_all(idx_all, d);
+ kfree(host);
}
-EXPORT_SYMBOL_GPL(ide_device_add);
+EXPORT_SYMBOL_GPL(ide_host_free);
+
+void ide_host_remove(struct ide_host *host)
+{
+ int i;
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+ if (host->ports[i])
+ ide_unregister(host->ports[i]);
+ }
+
+ ide_host_free(host);
+}
+EXPORT_SYMBOL_GPL(ide_host_remove);
void ide_port_scan(ide_hwif_t *hwif)
{
@@ -1634,11 +1800,10 @@ void ide_port_scan(ide_hwif_t *hwif)
}
EXPORT_SYMBOL_GPL(ide_port_scan);
-static void ide_legacy_init_one(u8 *idx, hw_regs_t *hw, u8 port_no,
- const struct ide_port_info *d,
+static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw,
+ u8 port_no, const struct ide_port_info *d,
unsigned long config)
{
- ide_hwif_t *hwif;
unsigned long base, ctl;
int irq;
@@ -1668,33 +1833,25 @@ static void ide_legacy_init_one(u8 *idx, hw_regs_t *hw, u8 port_no,
ide_std_init_ports(hw, base, ctl);
hw->irq = irq;
hw->chipset = d->chipset;
+ hw->config = config;
- hwif = ide_find_port_slot(d);
- if (hwif) {
- ide_init_port_hw(hwif, hw);
- if (config)
- hwif->config_data = config;
- idx[port_no] = hwif->index;
- }
+ hws[port_no] = hw;
}
int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config)
{
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw[2];
+ hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
memset(&hw, 0, sizeof(hw));
if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0)
- ide_legacy_init_one(idx, &hw[0], 0, d, config);
- ide_legacy_init_one(idx, &hw[1], 1, d, config);
+ ide_legacy_init_one(hws, &hw[0], 0, d, config);
+ ide_legacy_init_one(hws, &hw[1], 1, d, config);
- if (idx[0] == 0xff && idx[1] == 0xff &&
+ if (hws[0] == NULL && hws[1] == NULL &&
(d->host_flags & IDE_HFLAG_SINGLE))
return -ENOENT;
- ide_device_add(idx, d);
-
- return 0;
+ return ide_host_add(d, hws, NULL);
}
EXPORT_SYMBOL_GPL(ide_legacy_device_add);
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 8af88bf0969..f66c9c3f6fc 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -105,7 +105,7 @@ static int proc_ide_read_identify
len = sprintf(page, "\n");
if (drive) {
- unsigned short *val = (unsigned short *) page;
+ __le16 *val = (__le16 *)page;
err = taskfile_lib_get_identify(drive, page);
if (!err) {
@@ -113,7 +113,7 @@ static int proc_ide_read_identify
page = out;
do {
out += sprintf(out, "%04x%c",
- le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
+ le16_to_cpup(val), (++i & 7) ? ' ' : '\n');
val += 1;
} while (i < (SECTOR_WORDS * 2));
len = out - page;
@@ -345,7 +345,7 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
ide_task_t task;
int err;
- if (arg < 0 || arg > 70)
+ if (arg < XFER_PIO_0 || arg > XFER_UDMA_6)
return -EINVAL;
memset(&task, 0, sizeof(task));
@@ -357,7 +357,7 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
err = ide_no_data_taskfile(drive, &task);
- if (!err && arg) {
+ if (!err) {
ide_set_xfer_rate(drive, (u8) arg);
ide_driveid_update(drive);
}
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index b711ab96e28..82c2afe4d28 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -195,23 +195,6 @@ enum {
#define IDETAPE_BLOCK_DESCRIPTOR 0
#define IDETAPE_CAPABILITIES_PAGE 0x2a
-/* Tape flag bits values. */
-enum {
- IDETAPE_FLAG_IGNORE_DSC = (1 << 0),
- /* 0 When the tape position is unknown */
- IDETAPE_FLAG_ADDRESS_VALID = (1 << 1),
- /* Device already opened */
- IDETAPE_FLAG_BUSY = (1 << 2),
- /* Attempt to auto-detect the current user block size */
- IDETAPE_FLAG_DETECT_BS = (1 << 3),
- /* Currently on a filemark */
- IDETAPE_FLAG_FILEMARK = (1 << 4),
- /* DRQ interrupt device */
- IDETAPE_FLAG_DRQ_INTERRUPT = (1 << 5),
- /* 0 = no tape is loaded, so we don't rewind after ejecting */
- IDETAPE_FLAG_MEDIUM_PRESENT = (1 << 6),
-};
-
/*
* Most of our global data which we need to save even as we leave the driver due
* to an interrupt or a timer event is stored in the struct defined below.
@@ -312,8 +295,6 @@ typedef struct ide_tape_obj {
/* Wasted space in each stage */
int excess_bh_size;
- /* Status/Action flags: long for set_bit */
- unsigned long flags;
/* protects the ide-tape queue */
spinlock_t lock;
@@ -341,23 +322,29 @@ static struct class *idetape_sysfs_class;
#define ide_tape_g(disk) \
container_of((disk)->private_data, struct ide_tape_obj, driver)
+static void ide_tape_release(struct kref *);
+
static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
{
struct ide_tape_obj *tape = NULL;
mutex_lock(&idetape_ref_mutex);
tape = ide_tape_g(disk);
- if (tape)
+ if (tape) {
kref_get(&tape->kref);
+ if (ide_device_get(tape->drive)) {
+ kref_put(&tape->kref, ide_tape_release);
+ tape = NULL;
+ }
+ }
mutex_unlock(&idetape_ref_mutex);
return tape;
}
-static void ide_tape_release(struct kref *);
-
static void ide_tape_put(struct ide_tape_obj *tape)
{
mutex_lock(&idetape_ref_mutex);
+ ide_device_put(tape->drive);
kref_put(&tape->kref, ide_tape_release);
mutex_unlock(&idetape_ref_mutex);
}
@@ -398,7 +385,7 @@ static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
count = min(
(unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
bcount);
- drive->hwif->input_data(drive, NULL, bh->b_data +
+ drive->hwif->tp_ops->input_data(drive, NULL, bh->b_data +
atomic_read(&bh->b_count), count);
bcount -= count;
atomic_add(count, &bh->b_count);
@@ -424,7 +411,7 @@ static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
return;
}
count = min((unsigned int)pc->b_count, (unsigned int)bcount);
- drive->hwif->output_data(drive, NULL, pc->b_data, count);
+ drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count);
bcount -= count;
pc->b_data += count;
pc->b_count -= count;
@@ -585,7 +572,6 @@ static void ide_tape_kfree_buffer(idetape_tape_t *tape)
bh = bh->b_reqnext;
kfree(prev_bh);
}
- kfree(tape->merge_bh);
}
static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
@@ -665,15 +651,15 @@ static void ide_tape_callback(ide_drive_t *drive)
if (readpos[0] & 0x4) {
printk(KERN_INFO "ide-tape: Block location is unknown"
"to the tape\n");
- clear_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags);
+ clear_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags);
uptodate = 0;
} else {
debug_log(DBG_SENSE, "Block Location - %u\n",
- be32_to_cpu(*(u32 *)&readpos[4]));
+ be32_to_cpup((__be32 *)&readpos[4]));
tape->partition = readpos[1];
- tape->first_frame = be32_to_cpu(*(u32 *)&readpos[4]);
- set_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags);
+ tape->first_frame = be32_to_cpup((__be32 *)&readpos[4]);
+ set_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags);
}
}
@@ -690,7 +676,6 @@ static void idetape_init_pc(struct ide_atapi_pc *pc)
pc->buf_size = IDETAPE_PC_BUFFER_SIZE;
pc->bh = NULL;
pc->b_data = NULL;
- pc->callback = ide_tape_callback;
}
static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc)
@@ -705,7 +690,7 @@ static void idetape_init_rq(struct request *rq, u8 cmd)
{
blk_rq_init(NULL, rq);
rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->cmd[0] = cmd;
+ rq->cmd[13] = cmd;
}
/*
@@ -732,6 +717,7 @@ static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
rq->cmd_flags |= REQ_PREEMPT;
rq->buffer = (char *) pc;
rq->rq_disk = tape->disk;
+ memcpy(rq->cmd, pc->c, 12);
ide_do_drive_cmd(drive, rq);
}
@@ -742,7 +728,6 @@ static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
*/
static void idetape_retry_pc(ide_drive_t *drive)
{
- idetape_tape_t *tape = drive->driver_data;
struct ide_atapi_pc *pc;
struct request *rq;
@@ -750,7 +735,7 @@ static void idetape_retry_pc(ide_drive_t *drive)
pc = idetape_next_pc_storage(drive);
rq = idetape_next_rq_storage(drive);
idetape_create_request_sense_cmd(pc);
- set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
+ set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
idetape_queue_pc_head(drive, pc, rq);
}
@@ -887,7 +872,7 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
pc->error = IDETAPE_ERROR_GENERAL;
}
tape->failed_pc = NULL;
- pc->callback(drive);
+ drive->pc_callback(drive);
return ide_stopped;
}
debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
@@ -927,11 +912,12 @@ static void idetape_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
struct ide_atapi_pc *pc = tape->pc;
u8 stat;
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
if (stat & SEEK_STAT) {
if (stat & ERR_STAT) {
@@ -948,14 +934,17 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
pc->error = IDETAPE_ERROR_GENERAL;
tape->failed_pc = NULL;
}
- pc->callback(drive);
+ drive->pc_callback(drive);
return ide_stopped;
}
static void ide_tape_create_rw_cmd(idetape_tape_t *tape,
- struct ide_atapi_pc *pc, unsigned int length,
- struct idetape_bh *bh, u8 opcode)
+ struct ide_atapi_pc *pc, struct request *rq,
+ u8 opcode)
{
+ struct idetape_bh *bh = (struct idetape_bh *)rq->special;
+ unsigned int length = rq->current_nr_sectors;
+
idetape_init_pc(pc);
put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
pc->c[1] = 1;
@@ -975,11 +964,14 @@ static void ide_tape_create_rw_cmd(idetape_tape_t *tape,
pc->b_data = bh->b_data;
pc->b_count = atomic_read(&bh->b_count);
}
+
+ memcpy(rq->cmd, pc->c, 12);
}
static ide_startstop_t idetape_do_request(ide_drive_t *drive,
struct request *rq, sector_t block)
{
+ ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
struct ide_atapi_pc *pc = NULL;
struct request *postponed_rq = tape->postponed_rq;
@@ -1017,17 +1009,17 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
* If the tape is still busy, postpone our request and service
* the other device meanwhile.
*/
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
- if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
- set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
+ if (!drive->dsc_overlap && !(rq->cmd[13] & REQ_IDETAPE_PC2))
+ set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
if (drive->post_reset == 1) {
- set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
+ set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
drive->post_reset = 0;
}
- if (!test_and_clear_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags) &&
+ if (!test_and_clear_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags) &&
(stat & SEEK_STAT) == 0) {
if (postponed_rq == NULL) {
tape->dsc_polling_start = jiffies;
@@ -1036,7 +1028,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
} else if (time_after(jiffies, tape->dsc_timeout)) {
printk(KERN_ERR "ide-tape: %s: DSC timeout\n",
tape->name);
- if (rq->cmd[0] & REQ_IDETAPE_PC2) {
+ if (rq->cmd[13] & REQ_IDETAPE_PC2) {
idetape_media_access_finished(drive);
return ide_stopped;
} else {
@@ -1049,35 +1041,29 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
idetape_postpone_request(drive);
return ide_stopped;
}
- if (rq->cmd[0] & REQ_IDETAPE_READ) {
+ if (rq->cmd[13] & REQ_IDETAPE_READ) {
pc = idetape_next_pc_storage(drive);
- ide_tape_create_rw_cmd(tape, pc, rq->current_nr_sectors,
- (struct idetape_bh *)rq->special,
- READ_6);
+ ide_tape_create_rw_cmd(tape, pc, rq, READ_6);
goto out;
}
- if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
+ if (rq->cmd[13] & REQ_IDETAPE_WRITE) {
pc = idetape_next_pc_storage(drive);
- ide_tape_create_rw_cmd(tape, pc, rq->current_nr_sectors,
- (struct idetape_bh *)rq->special,
- WRITE_6);
+ ide_tape_create_rw_cmd(tape, pc, rq, WRITE_6);
goto out;
}
- if (rq->cmd[0] & REQ_IDETAPE_PC1) {
+ if (rq->cmd[13] & REQ_IDETAPE_PC1) {
pc = (struct ide_atapi_pc *) rq->buffer;
- rq->cmd[0] &= ~(REQ_IDETAPE_PC1);
- rq->cmd[0] |= REQ_IDETAPE_PC2;
+ rq->cmd[13] &= ~(REQ_IDETAPE_PC1);
+ rq->cmd[13] |= REQ_IDETAPE_PC2;
goto out;
}
- if (rq->cmd[0] & REQ_IDETAPE_PC2) {
+ if (rq->cmd[13] & REQ_IDETAPE_PC2) {
idetape_media_access_finished(drive);
return ide_stopped;
}
BUG();
-out:
- if (test_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags))
- pc->flags |= PC_FLAG_DRQ_INTERRUPT;
+out:
return idetape_issue_pc(drive, pc);
}
@@ -1281,8 +1267,9 @@ static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->cmd[0] = REQ_IDETAPE_PC1;
+ rq->cmd[13] = REQ_IDETAPE_PC1;
rq->buffer = (char *)pc;
+ memcpy(rq->cmd, pc->c, 12);
error = blk_execute_rq(drive->queue, tape->disk, rq, 0);
blk_put_request(rq);
return error;
@@ -1304,7 +1291,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
int load_attempted = 0;
/* Wait for the tape to become ready */
- set_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags);
+ set_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags);
timeout += jiffies;
while (time_before(jiffies, timeout)) {
idetape_create_test_unit_ready_cmd(&pc);
@@ -1397,7 +1384,7 @@ static void __ide_tape_discard_merge_buffer(ide_drive_t *drive)
if (tape->chrdev_dir != IDETAPE_DIR_READ)
return;
- clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags);
+ clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags);
tape->merge_bh_size = 0;
if (tape->merge_bh != NULL) {
ide_tape_kfree_buffer(tape);
@@ -1465,7 +1452,7 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->cmd[0] = cmd;
+ rq->cmd[13] = cmd;
rq->rq_disk = tape->disk;
rq->special = (void *)bh;
rq->sector = tape->first_frame;
@@ -1636,7 +1623,7 @@ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks);
/* If we are at a filemark, return a read length of 0 */
- if (test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
+ if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags))
return 0;
idetape_init_read(drive);
@@ -1746,7 +1733,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
if (tape->chrdev_dir == IDETAPE_DIR_READ) {
tape->merge_bh_size = 0;
- if (test_and_clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
+ if (test_and_clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags))
++count;
ide_tape_discard_merge_buffer(drive, 0);
}
@@ -1801,7 +1788,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
if (tape->chrdev_dir != IDETAPE_DIR_READ) {
- if (test_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags))
+ if (test_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags))
if (count > tape->blk_size &&
(count % tape->blk_size) == 0)
tape->user_bs_factor = count / tape->blk_size;
@@ -1841,7 +1828,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
tape->merge_bh_size = bytes_read-temp;
}
finish:
- if (!actually_read && test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags)) {
+ if (!actually_read && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) {
debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name);
idetape_space_over_filemarks(drive, MTFSF, 1);
@@ -2027,7 +2014,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
!IDETAPE_LU_LOAD_MASK);
retval = idetape_queue_pc_tail(drive, &pc);
if (!retval)
- clear_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags);
+ clear_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags);
return retval;
case MTNOP:
ide_tape_discard_merge_buffer(drive, 0);
@@ -2050,9 +2037,9 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
mt_count % tape->blk_size)
return -EIO;
tape->user_bs_factor = mt_count / tape->blk_size;
- clear_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags);
+ clear_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags);
} else
- set_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags);
+ set_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags);
return 0;
case MTSEEK:
ide_tape_discard_merge_buffer(drive, 0);
@@ -2202,20 +2189,20 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
filp->private_data = tape;
- if (test_and_set_bit(IDETAPE_FLAG_BUSY, &tape->flags)) {
+ if (test_and_set_bit(IDE_AFLAG_BUSY, &drive->atapi_flags)) {
retval = -EBUSY;
goto out_put_tape;
}
retval = idetape_wait_ready(drive, 60 * HZ);
if (retval) {
- clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+ clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name);
goto out_put_tape;
}
idetape_read_position(drive);
- if (!test_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags))
+ if (!test_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags))
(void)idetape_rewind_tape(drive);
/* Read block size and write protect status from drive. */
@@ -2231,7 +2218,7 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
if (tape->write_prot) {
if ((filp->f_flags & O_ACCMODE) == O_WRONLY ||
(filp->f_flags & O_ACCMODE) == O_RDWR) {
- clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+ clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
retval = -EROFS;
goto out_put_tape;
}
@@ -2291,7 +2278,7 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
ide_tape_discard_merge_buffer(drive, 1);
}
- if (minor < 128 && test_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags))
+ if (minor < 128 && test_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags))
(void) idetape_rewind_tape(drive);
if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
if (tape->door_locked == DOOR_LOCKED) {
@@ -2301,7 +2288,7 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
}
}
}
- clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+ clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
ide_tape_put(tape);
unlock_kernel();
return 0;
@@ -2394,23 +2381,23 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
caps = pc.buf + 4 + pc.buf[3];
/* convert to host order and save for later use */
- speed = be16_to_cpu(*(u16 *)&caps[14]);
- max_speed = be16_to_cpu(*(u16 *)&caps[8]);
+ speed = be16_to_cpup((__be16 *)&caps[14]);
+ max_speed = be16_to_cpup((__be16 *)&caps[8]);
- put_unaligned(max_speed, (u16 *)&caps[8]);
- put_unaligned(be16_to_cpu(*(u16 *)&caps[12]), (u16 *)&caps[12]);
- put_unaligned(speed, (u16 *)&caps[14]);
- put_unaligned(be16_to_cpu(*(u16 *)&caps[16]), (u16 *)&caps[16]);
+ *(u16 *)&caps[8] = max_speed;
+ *(u16 *)&caps[12] = be16_to_cpup((__be16 *)&caps[12]);
+ *(u16 *)&caps[14] = speed;
+ *(u16 *)&caps[16] = be16_to_cpup((__be16 *)&caps[16]);
if (!speed) {
printk(KERN_INFO "ide-tape: %s: invalid tape speed "
"(assuming 650KB/sec)\n", drive->name);
- put_unaligned(650, (u16 *)&caps[14]);
+ *(u16 *)&caps[14] = 650;
}
if (!max_speed) {
printk(KERN_INFO "ide-tape: %s: invalid max_speed "
"(assuming 650KB/sec)\n", drive->name);
- put_unaligned(650, (u16 *)&caps[8]);
+ *(u16 *)&caps[8] = 650;
}
memcpy(&tape->caps, caps, 20);
@@ -2464,6 +2451,8 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
u8 gcw[2];
u16 *ctl = (u16 *)&tape->caps[12];
+ drive->pc_callback = ide_tape_callback;
+
spin_lock_init(&tape->lock);
drive->dsc_overlap = 1;
if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) {
@@ -2484,7 +2473,7 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
/* Command packet DRQ type */
if (((gcw[0] & 0x60) >> 5) == 1)
- set_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags);
+ set_bit(IDE_AFLAG_DRQ_INTERRUPT, &drive->atapi_flags);
idetape_get_inquiry_results(drive);
idetape_get_mode_sense_results(drive);
@@ -2697,10 +2686,12 @@ static int ide_tape_probe(ide_drive_t *drive)
idetape_setup(drive, tape, minor);
- device_create(idetape_sysfs_class, &drive->gendev,
- MKDEV(IDETAPE_MAJOR, minor), "%s", tape->name);
- device_create(idetape_sysfs_class, &drive->gendev,
- MKDEV(IDETAPE_MAJOR, minor + 128), "n%s", tape->name);
+ device_create_drvdata(idetape_sysfs_class, &drive->gendev,
+ MKDEV(IDETAPE_MAJOR, minor), NULL,
+ "%s", tape->name);
+ device_create_drvdata(idetape_sysfs_class, &drive->gendev,
+ MKDEV(IDETAPE_MAJOR, minor + 128), NULL,
+ "n%s", tape->name);
g->fops = &idetape_block_ops;
ide_register_region(g);
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 1fbdb746dc8..7fb6f1c8627 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -64,6 +64,7 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
ide_hwif_t *hwif = HWIF(drive);
struct ide_taskfile *tf = &task->tf;
ide_handler_t *handler = NULL;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
const struct ide_dma_ops *dma_ops = hwif->dma_ops;
if (task->data_phase == TASKFILE_MULTI_IN ||
@@ -80,15 +81,15 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
ide_tf_dump(drive->name, tf);
- ide_set_irq(drive, 1);
+ tp_ops->set_irq(hwif, 1);
SELECT_MASK(drive, 0);
- hwif->tf_load(drive, task);
+ tp_ops->tf_load(drive, task);
}
switch (task->data_phase) {
case TASKFILE_MULTI_OUT:
case TASKFILE_OUT:
- hwif->OUTBSYNC(hwif, tf->command, hwif->io_ports.command_addr);
+ tp_ops->exec_command(hwif, tf->command);
ndelay(400); /* FIXME */
return pre_task_out_intr(drive, task->rq);
case TASKFILE_MULTI_IN:
@@ -124,7 +125,11 @@ EXPORT_SYMBOL_GPL(do_rw_taskfile);
*/
static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
{
- u8 stat = ide_read_status(drive);
+ ide_hwif_t *hwif = drive->hwif;
+ u8 stat;
+
+ local_irq_enable_in_hardirq();
+ stat = hwif->tp_ops->read_status(hwif);
if (OK_STAT(stat, READY_STAT, BAD_STAT))
drive->mult_count = drive->mult_req;
@@ -141,11 +146,18 @@ static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
*/
static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
int retries = 5;
u8 stat;
- while (((stat = ide_read_status(drive)) & BUSY_STAT) && retries--)
+ local_irq_enable_in_hardirq();
+
+ while (1) {
+ stat = hwif->tp_ops->read_status(hwif);
+ if ((stat & BUSY_STAT) == 0 || retries-- == 0)
+ break;
udelay(10);
+ };
if (OK_STAT(stat, READY_STAT, BAD_STAT))
return ide_stopped;
@@ -162,7 +174,11 @@ static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
*/
static ide_startstop_t recal_intr(ide_drive_t *drive)
{
- u8 stat = ide_read_status(drive);
+ ide_hwif_t *hwif = drive->hwif;
+ u8 stat;
+
+ local_irq_enable_in_hardirq();
+ stat = hwif->tp_ops->read_status(hwif);
if (!OK_STAT(stat, READY_STAT, BAD_STAT))
return ide_error(drive, "recal_intr", stat);
@@ -174,11 +190,12 @@ static ide_startstop_t recal_intr(ide_drive_t *drive)
*/
static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
{
- ide_task_t *args = HWGROUP(drive)->rq->special;
+ ide_hwif_t *hwif = drive->hwif;
+ ide_task_t *args = hwif->hwgroup->rq->special;
u8 stat;
local_irq_enable_in_hardirq();
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
if (!OK_STAT(stat, READY_STAT, BAD_STAT))
return ide_error(drive, "task_no_data_intr", stat);
@@ -192,6 +209,7 @@ static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
static u8 wait_drive_not_busy(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
int retries;
u8 stat;
@@ -200,7 +218,7 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
* take up to 6 ms on some ATAPI devices, so we will wait max 10 ms.
*/
for (retries = 0; retries < 1000; retries++) {
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
if (stat & BUSY_STAT)
udelay(10);
@@ -255,9 +273,9 @@ static void ide_pio_sector(ide_drive_t *drive, struct request *rq,
/* do the actual data transfer */
if (write)
- hwif->output_data(drive, rq, buf, SECTOR_SIZE);
+ hwif->tp_ops->output_data(drive, rq, buf, SECTOR_SIZE);
else
- hwif->input_data(drive, rq, buf, SECTOR_SIZE);
+ hwif->tp_ops->input_data(drive, rq, buf, SECTOR_SIZE);
kunmap_atomic(buf, KM_BIO_SRC_IRQ);
#ifdef CONFIG_HIGHMEM
@@ -383,8 +401,8 @@ static ide_startstop_t task_in_unexpected(ide_drive_t *drive, struct request *rq
static ide_startstop_t task_in_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- struct request *rq = HWGROUP(drive)->rq;
- u8 stat = ide_read_status(drive);
+ struct request *rq = hwif->hwgroup->rq;
+ u8 stat = hwif->tp_ops->read_status(hwif);
/* Error? */
if (stat & ERR_STAT)
@@ -418,7 +436,7 @@ static ide_startstop_t task_out_intr (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
struct request *rq = HWGROUP(drive)->rq;
- u8 stat = ide_read_status(drive);
+ u8 stat = hwif->tp_ops->read_status(hwif);
if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
return task_error(drive, rq, __func__, stat);
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index d4a6b102a77..772451600e4 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
- * Copyrifht (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz
+ * Copyright (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz
*/
/*
@@ -101,8 +101,7 @@ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
init_completion(&hwif->gendev_rel_comp);
- default_hwif_iops(hwif);
- default_hwif_transport(hwif);
+ hwif->tp_ops = &default_tp_ops;
ide_port_init_devices_data(hwif);
}
@@ -134,41 +133,6 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif)
}
}
-void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
-{
- ide_hwgroup_t *hwgroup = hwif->hwgroup;
-
- spin_lock_irq(&ide_lock);
- /*
- * Remove us from the hwgroup, and free
- * the hwgroup if we were the only member
- */
- if (hwif->next == hwif) {
- BUG_ON(hwgroup->hwif != hwif);
- kfree(hwgroup);
- } else {
- /* There is another interface in hwgroup.
- * Unlink us, and set hwgroup->drive and ->hwif to
- * something sane.
- */
- ide_hwif_t *g = hwgroup->hwif;
-
- while (g->next != hwif)
- g = g->next;
- g->next = hwif->next;
- if (hwgroup->hwif == hwif) {
- /* Chose a random hwif for hwgroup->hwif.
- * It's guaranteed that there are no drives
- * left in the hwgroup.
- */
- BUG_ON(hwgroup->drive != NULL);
- hwgroup->hwif = g;
- }
- BUG_ON(hwgroup->hwif == hwif);
- }
- spin_unlock_irq(&ide_lock);
-}
-
/* Called with ide_lock held. */
static void __ide_port_unregister_devices(ide_hwif_t *hwif)
{
@@ -269,16 +233,9 @@ void ide_unregister(ide_hwif_t *hwif)
if (hwif->dma_base)
ide_release_dma_engine(hwif);
- spin_lock_irq(&ide_lock);
- /* restore hwif data to pristine status */
- ide_init_port_data(hwif, hwif->index);
- spin_unlock_irq(&ide_lock);
-
mutex_unlock(&ide_cfg_mtx);
}
-EXPORT_SYMBOL(ide_unregister);
-
void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
{
memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports));
@@ -287,8 +244,8 @@ void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
hwif->dev = hw->dev;
hwif->gendev.parent = hw->parent ? hw->parent : hw->dev;
hwif->ack_intr = hw->ack_intr;
+ hwif->config_data = hw->config;
}
-EXPORT_SYMBOL_GPL(ide_init_port_hw);
/*
* Locks for IDE setting functionality
@@ -661,6 +618,53 @@ set_val:
EXPORT_SYMBOL(generic_ide_ioctl);
+/**
+ * ide_device_get - get an additional reference to a ide_drive_t
+ * @drive: device to get a reference to
+ *
+ * Gets a reference to the ide_drive_t and increments the use count of the
+ * underlying LLDD module.
+ */
+int ide_device_get(ide_drive_t *drive)
+{
+ struct device *host_dev;
+ struct module *module;
+
+ if (!get_device(&drive->gendev))
+ return -ENXIO;
+
+ host_dev = drive->hwif->host->dev[0];
+ module = host_dev ? host_dev->driver->owner : NULL;
+
+ if (module && !try_module_get(module)) {
+ put_device(&drive->gendev);
+ return -ENXIO;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ide_device_get);
+
+/**
+ * ide_device_put - release a reference to a ide_drive_t
+ * @drive: device to release a reference on
+ *
+ * Release a reference to the ide_drive_t and decrements the use count of
+ * the underlying LLDD module.
+ */
+void ide_device_put(ide_drive_t *drive)
+{
+#ifdef CONFIG_MODULE_UNLOAD
+ struct device *host_dev = drive->hwif->host->dev[0];
+ struct module *module = host_dev ? host_dev->driver->owner : NULL;
+
+ if (module)
+ module_put(module);
+#endif
+ put_device(&drive->gendev);
+}
+EXPORT_SYMBOL_GPL(ide_device_put);
+
static int ide_bus_match(struct device *dev, struct device_driver *drv)
{
return 1;
diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
index 0497e7f85b0..7c2afa97f41 100644
--- a/drivers/ide/legacy/buddha.c
+++ b/drivers/ide/legacy/buddha.c
@@ -37,6 +37,8 @@
#define CATWEASEL_NUM_HWIFS 3
#define XSURF_NUM_HWIFS 2
+#define MAX_NUM_HWIFS 3
+
/*
* Bases of the IDE interfaces (relative to the board address)
*/
@@ -148,18 +150,14 @@ static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base,
static int __init buddha_init(void)
{
- hw_regs_t hw;
- ide_hwif_t *hwif;
- int i;
-
struct zorro_dev *z = NULL;
u_long buddha_board = 0;
BuddhaType type;
- int buddha_num_hwifs;
+ int buddha_num_hwifs, i;
while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
unsigned long board;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw[MAX_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) {
buddha_num_hwifs = BUDDHA_NUM_HWIFS;
@@ -221,19 +219,13 @@ fail_base2:
ack_intr = xsurf_ack_intr;
}
- buddha_setup_ports(&hw, base, ctl, irq_port, ack_intr);
+ buddha_setup_ports(&hw[i], base, ctl, irq_port,
+ ack_intr);
- hwif = ide_find_port();
- if (hwif) {
- u8 index = hwif->index;
-
- ide_init_port_hw(hwif, &hw);
-
- idx[i] = index;
- }
+ hws[i] = &hw[i];
}
- ide_device_add(idx, NULL);
+ ide_host_add(NULL, hws, NULL);
}
return 0;
diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
index 129a812bb57..724f95073d8 100644
--- a/drivers/ide/legacy/falconide.c
+++ b/drivers/ide/legacy/falconide.c
@@ -66,6 +66,27 @@ static void falconide_output_data(ide_drive_t *drive, struct request *rq,
outsw_swapw(data_addr, buf, (len + 1) / 2);
}
+/* Atari has a byte-swapped IDE interface */
+static const struct ide_tp_ops falconide_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = falconide_input_data,
+ .output_data = falconide_output_data,
+};
+
+static const struct ide_port_info falconide_port_info = {
+ .tp_ops = &falconide_tp_ops,
+ .host_flags = IDE_HFLAG_NO_DMA,
+};
+
static void __init falconide_setup_ports(hw_regs_t *hw)
{
int i;
@@ -91,11 +112,12 @@ static void __init falconide_setup_ports(hw_regs_t *hw)
static int __init falconide_init(void)
{
- hw_regs_t hw;
- ide_hwif_t *hwif;
+ struct ide_host *host;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+ int rc;
if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE))
- return 0;
+ return -ENODEV;
printk(KERN_INFO "ide: Falcon IDE controller\n");
@@ -106,23 +128,25 @@ static int __init falconide_init(void)
falconide_setup_ports(&hw);
- hwif = ide_find_port();
- if (hwif) {
- u8 index = hwif->index;
- u8 idx[4] = { index, 0xff, 0xff, 0xff };
-
- ide_init_port_hw(hwif, &hw);
+ host = ide_host_alloc(&falconide_port_info, hws);
+ if (host == NULL) {
+ rc = -ENOMEM;
+ goto err;
+ }
- /* Atari has a byte-swapped IDE interface */
- hwif->input_data = falconide_input_data;
- hwif->output_data = falconide_output_data;
+ ide_get_lock(NULL, NULL);
+ rc = ide_host_register(host, &falconide_port_info, hws);
+ ide_release_lock();
- ide_get_lock(NULL, NULL);
- ide_device_add(idx, NULL);
- ide_release_lock();
- }
+ if (rc)
+ goto err_free;
return 0;
+err_free:
+ ide_host_free(host);
+err:
+ release_mem_region(ATA_HD_BASE, 0x40);
+ return rc;
}
module_init(falconide_init);
diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
index 7e74b20202d..51ba085d7aa 100644
--- a/drivers/ide/legacy/gayle.c
+++ b/drivers/ide/legacy/gayle.c
@@ -31,6 +31,8 @@
#define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */
#define GAYLE_BASE_1200 0xda0000 /* A1200/A600 and E-Matrix 530 */
+#define GAYLE_IDEREG_SIZE 0x2000
+
/*
* Offsets from one of the above bases
*/
@@ -56,13 +58,11 @@
#define GAYLE_NUM_HWIFS 1
#define GAYLE_NUM_PROBE_HWIFS GAYLE_NUM_HWIFS
#define GAYLE_HAS_CONTROL_REG 1
-#define GAYLE_IDEREG_SIZE 0x2000
#else /* CONFIG_BLK_DEV_IDEDOUBLER */
#define GAYLE_NUM_HWIFS 2
#define GAYLE_NUM_PROBE_HWIFS (ide_doubler ? GAYLE_NUM_HWIFS : \
GAYLE_NUM_HWIFS-1)
#define GAYLE_HAS_CONTROL_REG (!ide_doubler)
-#define GAYLE_IDEREG_SIZE (ide_doubler ? 0x1000 : 0x2000)
static int ide_doubler;
module_param_named(doubler, ide_doubler, bool, 0);
@@ -124,8 +124,11 @@ static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base,
static int __init gayle_init(void)
{
- int a4000, i;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ unsigned long phys_base, res_start, res_n;
+ unsigned long base, ctrlport, irqport;
+ ide_ack_intr_t *ack_intr;
+ int a4000, i, rc;
+ hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
if (!MACH_IS_AMIGA)
return -ENODEV;
@@ -148,13 +151,6 @@ found:
#endif
"");
- for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
- unsigned long base, ctrlport, irqport;
- ide_ack_intr_t *ack_intr;
- hw_regs_t hw;
- ide_hwif_t *hwif;
- unsigned long phys_base, res_start, res_n;
-
if (a4000) {
phys_base = GAYLE_BASE_4000;
irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000);
@@ -168,33 +164,26 @@ found:
* FIXME: we now have selectable modes between mmio v/s iomio
*/
- phys_base += i*GAYLE_NEXT_PORT;
-
res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1);
res_n = GAYLE_IDEREG_SIZE;
if (!request_mem_region(res_start, res_n, "IDE"))
- continue;
+ return -EBUSY;
- base = (unsigned long)ZTWO_VADDR(phys_base);
+ for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
+ base = (unsigned long)ZTWO_VADDR(phys_base + i * GAYLE_NEXT_PORT);
ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
- gayle_setup_ports(&hw, base, ctrlport, irqport, ack_intr);
-
- hwif = ide_find_port();
- if (hwif) {
- u8 index = hwif->index;
-
- ide_init_port_hw(hwif, &hw);
+ gayle_setup_ports(&hw[i], base, ctrlport, irqport, ack_intr);
- idx[i] = index;
- } else
- release_mem_region(res_start, res_n);
+ hws[i] = &hw[i];
}
- ide_device_add(idx, NULL);
+ rc = ide_host_add(NULL, hws, NULL);
+ if (rc)
+ release_mem_region(res_start, res_n);
- return 0;
+ return rc;
}
module_init(gayle_init);
diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c
index 7bc8fd59ea9..98f7c95e39e 100644
--- a/drivers/ide/legacy/ht6560b.c
+++ b/drivers/ide/legacy/ht6560b.c
@@ -3,34 +3,12 @@
*/
/*
- *
- * Version 0.01 Initial version hacked out of ide.c
- *
- * Version 0.02 Added support for PIO modes, auto-tune
- *
- * Version 0.03 Some cleanups
- *
- * Version 0.05 PIO mode cycle timings auto-tune using bus-speed
- *
- * Version 0.06 Prefetch mode now defaults no OFF. To set
- * prefetch mode OFF/ON use "hdparm -p8/-p9".
- * Unmask irq is disabled when prefetch mode
- * is enabled.
- *
- * Version 0.07 Trying to fix CD-ROM detection problem.
- * "Prefetch" mode bit OFF for ide disks and
- * ON for anything else.
- *
- * Version 0.08 Need to force prefetch for CDs and other non-disk
- * devices. (not sure which devices exactly need
- * prefetch)
- *
* HT-6560B EIDE-controller support
* To activate controller support use kernel parameter "ide0=ht6560b".
* Use hdparm utility to enable PIO mode support.
*
* Author: Mikko Ala-Fossi <maf@iki.fi>
- * Jan Evert van Grootheest <janevert@caiway.nl>
+ * Jan Evert van Grootheest <j.e.van.grootheest@caiway.nl>
*
* Try: http://www.maf.iki.fi/~maf/ht6560b/
*/
diff --git a/drivers/ide/legacy/ide-4drives.c b/drivers/ide/legacy/ide-4drives.c
index 89c8ff0a4d0..c76d55de699 100644
--- a/drivers/ide/legacy/ide-4drives.c
+++ b/drivers/ide/legacy/ide-4drives.c
@@ -28,10 +28,8 @@ static const struct ide_port_info ide_4drives_port_info = {
static int __init ide_4drives_init(void)
{
- ide_hwif_t *hwif, *mate;
unsigned long base = 0x1f0, ctl = 0x3f6;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw;
+ hw_regs_t hw, *hws[] = { &hw, &hw, NULL, NULL };
if (probe_4drives == 0)
return -ENODEV;
@@ -55,21 +53,7 @@ static int __init ide_4drives_init(void)
hw.irq = 14;
hw.chipset = ide_4drives;
- hwif = ide_find_port();
- if (hwif) {
- ide_init_port_hw(hwif, &hw);
- idx[0] = hwif->index;
- }
-
- mate = ide_find_port();
- if (mate) {
- ide_init_port_hw(mate, &hw);
- idx[1] = mate->index;
- }
-
- ide_device_add(idx, &ide_4drives_port_info);
-
- return 0;
+ return ide_host_add(&ide_4drives_port_info, hws, NULL);
}
module_init(ide_4drives_init);
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index 27b1e0b7ecb..21bfac13784 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -74,7 +74,7 @@ INT_MODULE_PARM(pc_debug, 0);
typedef struct ide_info_t {
struct pcmcia_device *p_dev;
- ide_hwif_t *hwif;
+ struct ide_host *host;
int ndev;
dev_node_t node;
} ide_info_t;
@@ -132,7 +132,7 @@ static int ide_probe(struct pcmcia_device *link)
static void ide_detach(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
- ide_hwif_t *hwif = info->hwif;
+ ide_hwif_t *hwif = info->host->ports[0];
unsigned long data_addr, ctl_addr;
DEBUG(0, "ide_detach(0x%p)\n", link);
@@ -157,13 +157,13 @@ static const struct ide_port_info idecs_port_info = {
.host_flags = IDE_HFLAG_NO_DMA,
};
-static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl,
+static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
unsigned long irq, struct pcmcia_device *handle)
{
+ struct ide_host *host;
ide_hwif_t *hwif;
- hw_regs_t hw;
- int i;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ int i, rc;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
if (!request_region(io, 8, DRV_NAME)) {
printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
@@ -184,30 +184,24 @@ static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl,
hw.chipset = ide_pci;
hw.dev = &handle->dev;
- hwif = ide_find_port();
- if (hwif == NULL)
+ rc = ide_host_add(&idecs_port_info, hws, &host);
+ if (rc)
goto out_release;
- i = hwif->index;
-
- ide_init_port_hw(hwif, &hw);
-
- idx[0] = i;
-
- ide_device_add(idx, &idecs_port_info);
+ hwif = host->ports[0];
if (hwif->present)
- return hwif;
+ return host;
/* retry registration in case device is still spinning up */
for (i = 0; i < 10; i++) {
msleep(100);
ide_port_scan(hwif);
if (hwif->present)
- return hwif;
+ return host;
}
- return hwif;
+ return host;
out_release:
release_region(ctl, 1);
@@ -239,7 +233,7 @@ static int ide_config(struct pcmcia_device *link)
cistpl_cftable_entry_t *cfg;
int pass, last_ret = 0, last_fn = 0, is_kme = 0;
unsigned long io_base, ctl_base;
- ide_hwif_t *hwif;
+ struct ide_host *host;
DEBUG(0, "ide_config(0x%p)\n", link);
@@ -334,21 +328,21 @@ static int ide_config(struct pcmcia_device *link)
if (is_kme)
outb(0x81, ctl_base+1);
- hwif = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
- if (hwif == NULL && link->io.NumPorts1 == 0x20) {
+ host = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
+ if (host == NULL && link->io.NumPorts1 == 0x20) {
outb(0x02, ctl_base + 0x10);
- hwif = idecs_register(io_base + 0x10, ctl_base + 0x10,
+ host = idecs_register(io_base + 0x10, ctl_base + 0x10,
link->irq.AssignedIRQ, link);
}
- if (hwif == NULL)
+ if (host == NULL)
goto failed;
info->ndev = 1;
- sprintf(info->node.dev_name, "hd%c", 'a' + hwif->index * 2);
- info->node.major = hwif->major;
+ sprintf(info->node.dev_name, "hd%c", 'a' + host->ports[0]->index * 2);
+ info->node.major = host->ports[0]->major;
info->node.minor = 0;
- info->hwif = hwif;
+ info->host = host;
link->dev_node = &info->node;
printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
@@ -379,15 +373,15 @@ failed:
static void ide_release(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
- ide_hwif_t *hwif = info->hwif;
+ struct ide_host *host = info->host;
DEBUG(0, "ide_release(0x%p)\n", link);
- if (info->ndev) {
+ if (info->ndev)
/* FIXME: if this fails we need to queue the cleanup somehow
-- need to investigate the required PCMCIA magic */
- ide_unregister(hwif);
- }
+ ide_host_remove(host);
+
info->ndev = 0;
pcmcia_disable_device(link);
diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c
index a249562b34b..051b4ab0f35 100644
--- a/drivers/ide/legacy/ide_platform.c
+++ b/drivers/ide/legacy/ide_platform.c
@@ -52,12 +52,10 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
{
struct resource *res_base, *res_alt, *res_irq;
void __iomem *base, *alt_base;
- ide_hwif_t *hwif;
struct pata_platform_info *pdata;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- int ret = 0;
- int mmio = 0;
- hw_regs_t hw;
+ struct ide_host *host;
+ int ret = 0, mmio = 0;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
struct ide_port_info d = platform_ide_port_info;
pdata = pdev->dev.platform_data;
@@ -94,28 +92,18 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
res_alt->start, res_alt->end - res_alt->start + 1);
}
- hwif = ide_find_port();
- if (!hwif) {
- ret = -ENODEV;
- goto out;
- }
-
memset(&hw, 0, sizeof(hw));
plat_ide_setup_ports(&hw, base, alt_base, pdata, res_irq->start);
hw.dev = &pdev->dev;
- ide_init_port_hw(hwif, &hw);
-
- if (mmio) {
+ if (mmio)
d.host_flags |= IDE_HFLAG_MMIO;
- default_hwif_mmiops(hwif);
- }
- idx[0] = hwif->index;
-
- ide_device_add(idx, &d);
+ ret = ide_host_add(&d, hws, &host);
+ if (ret)
+ goto out;
- platform_set_drvdata(pdev, hwif);
+ platform_set_drvdata(pdev, host);
return 0;
@@ -125,9 +113,9 @@ out:
static int __devexit plat_ide_remove(struct platform_device *pdev)
{
- ide_hwif_t *hwif = pdev->dev.driver_data;
+ struct ide_host *host = pdev->dev.driver_data;
- ide_unregister(hwif);
+ ide_host_remove(host);
return 0;
}
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index 0a6195bcfed..a0bb167980e 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -91,11 +91,10 @@ static const char *mac_ide_name[] =
static int __init macide_init(void)
{
- ide_hwif_t *hwif;
ide_ack_intr_t *ack_intr;
unsigned long base;
int irq;
- hw_regs_t hw;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
if (!MACH_IS_MAC)
return -ENODEV;
@@ -125,17 +124,7 @@ static int __init macide_init(void)
macide_setup_ports(&hw, base, irq, ack_intr);
- hwif = ide_find_port();
- if (hwif) {
- u8 index = hwif->index;
- u8 idx[4] = { index, 0xff, 0xff, 0xff };
-
- ide_init_port_hw(hwif, &hw);
-
- ide_device_add(idx, NULL);
- }
-
- return 0;
+ return ide_host_add(NULL, hws, NULL);
}
module_init(macide_init);
diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
index 9c2b9d078f6..4abd8fc7819 100644
--- a/drivers/ide/legacy/q40ide.c
+++ b/drivers/ide/legacy/q40ide.c
@@ -96,6 +96,27 @@ static void q40ide_output_data(ide_drive_t *drive, struct request *rq,
outsw_swapw(data_addr, buf, (len + 1) / 2);
}
+/* Q40 has a byte-swapped IDE interface */
+static const struct ide_tp_ops q40ide_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = q40ide_input_data,
+ .output_data = q40ide_output_data,
+};
+
+static const struct ide_port_info q40ide_port_info = {
+ .tp_ops = &q40ide_tp_ops,
+ .host_flags = IDE_HFLAG_NO_DMA,
+};
+
/*
* the static array is needed to have the name reported in /proc/ioports,
* hwif->name unfortunately isn't available yet
@@ -111,9 +132,7 @@ static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={
static int __init q40ide_init(void)
{
int i;
- ide_hwif_t *hwif;
- const char *name;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
if (!MACH_IS_Q40)
return -ENODEV;
@@ -121,9 +140,8 @@ static int __init q40ide_init(void)
printk(KERN_INFO "ide: Q40 IDE controller\n");
for (i = 0; i < Q40IDE_NUM_HWIFS; i++) {
- hw_regs_t hw;
+ const char *name = q40_ide_names[i];
- name = q40_ide_names[i];
if (!request_region(pcide_bases[i], 8, name)) {
printk("could not reserve ports %lx-%lx for %s\n",
pcide_bases[i],pcide_bases[i]+8,name);
@@ -135,26 +153,13 @@ static int __init q40ide_init(void)
release_region(pcide_bases[i], 8);
continue;
}
- q40_ide_setup_ports(&hw, pcide_bases[i],
- NULL,
-// m68kide_iops,
+ q40_ide_setup_ports(&hw[i], pcide_bases[i], NULL,
q40ide_default_irq(pcide_bases[i]));
- hwif = ide_find_port();
- if (hwif) {
- ide_init_port_hw(hwif, &hw);
-
- /* Q40 has a byte-swapped IDE interface */
- hwif->input_data = q40ide_input_data;
- hwif->output_data = q40ide_output_data;
-
- idx[i] = hwif->index;
- }
+ hws[i] = &hw[i];
}
- ide_device_add(idx, NULL);
-
- return 0;
+ return ide_host_add(&q40ide_port_info, hws, NULL);
}
module_init(q40ide_init);
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index 48d57cae63c..11b7f61aae4 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -519,6 +519,23 @@ static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif)
*ata_regs = ahwif->regbase + (14 << IDE_REG_SHIFT);
}
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+static const struct ide_tp_ops au1xxx_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = au1xxx_input_data,
+ .output_data = au1xxx_output_data,
+};
+#endif
+
static const struct ide_port_ops au1xxx_port_ops = {
.set_pio_mode = au1xxx_set_pio_mode,
.set_dma_mode = auide_set_dma_mode,
@@ -526,6 +543,9 @@ static const struct ide_port_ops au1xxx_port_ops = {
static const struct ide_port_info au1xxx_port_info = {
.init_dma = auide_ddma_init,
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+ .tp_ops = &au1xxx_tp_ops,
+#endif
.port_ops = &au1xxx_port_ops,
#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
.dma_ops = &au1xxx_dma_ops,
@@ -543,11 +563,10 @@ static int au_ide_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
_auide_hwif *ahwif = &auide_hwif;
- ide_hwif_t *hwif;
struct resource *res;
+ struct ide_host *host;
int ret = 0;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
char *mode = "MWDMA2";
@@ -584,36 +603,19 @@ static int au_ide_probe(struct device *dev)
goto out;
}
- hwif = ide_find_port();
- if (hwif == NULL) {
- ret = -ENOENT;
- goto out;
- }
-
memset(&hw, 0, sizeof(hw));
auide_setup_ports(&hw, ahwif);
hw.irq = ahwif->irq;
hw.dev = dev;
hw.chipset = ide_au1xxx;
- ide_init_port_hw(hwif, &hw);
-
- /* If the user has selected DDMA assisted copies,
- then set up a few local I/O function entry points
- */
-
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
- hwif->input_data = au1xxx_input_data;
- hwif->output_data = au1xxx_output_data;
-#endif
-
- auide_hwif.hwif = hwif;
-
- idx[0] = hwif->index;
+ ret = ide_host_add(&au1xxx_port_info, hws, &host);
+ if (ret)
+ goto out;
- ide_device_add(idx, &au1xxx_port_info);
+ auide_hwif.hwif = host->ports[0];
- dev_set_drvdata(dev, hwif);
+ dev_set_drvdata(dev, host);
printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode );
@@ -625,10 +627,10 @@ static int au_ide_remove(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct resource *res;
- ide_hwif_t *hwif = dev_get_drvdata(dev);
+ struct ide_host *host = dev_get_drvdata(dev);
_auide_hwif *ahwif = &auide_hwif;
- ide_unregister(hwif);
+ ide_host_remove(host);
iounmap((void *)ahwif->regbase);
diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
index 9f1212cc4ae..badf79fc9e3 100644
--- a/drivers/ide/mips/swarm.c
+++ b/drivers/ide/mips/swarm.c
@@ -72,12 +72,11 @@ static const struct ide_port_info swarm_port_info = {
*/
static int __devinit swarm_ide_probe(struct device *dev)
{
- ide_hwif_t *hwif;
u8 __iomem *base;
+ struct ide_host *host;
phys_t offset, size;
- hw_regs_t hw;
- int i;
- u8 idx[] = { 0xff, 0xff, 0xff, 0xff };
+ int i, rc;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
if (!SIBYTE_HAVE_IDE)
return -ENODEV;
@@ -116,26 +115,17 @@ static int __devinit swarm_ide_probe(struct device *dev)
hw.irq = K_INT_GB_IDE;
hw.chipset = ide_generic;
- hwif = ide_find_port_slot(&swarm_port_info);
- if (hwif == NULL)
+ rc = ide_host_add(&swarm_port_info, hws, &host);
+ if (rc)
goto err;
- ide_init_port_hw(hwif, &hw);
-
- /* Setup MMIO ops. */
- default_hwif_mmiops(hwif);
-
- idx[0] = hwif->index;
-
- ide_device_add(idx, &swarm_port_info);
-
- dev_set_drvdata(dev, hwif);
+ dev_set_drvdata(dev, host);
return 0;
err:
release_resource(&swarm_ide_resource);
iounmap(base);
- return -ENOMEM;
+ return rc;
}
static struct device_driver swarm_ide_driver = {
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index ae7a4329a58..e0c8fe7d9fe 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -13,6 +13,8 @@
#include <asm/io.h>
+#define DRV_NAME "aec62xx"
+
struct chipset_bus_clock_list_entry {
u8 xfer_speed;
u8 chipset_settings;
@@ -59,10 +61,6 @@ static const struct chipset_bus_clock_list_entry aec6xxx_34_base [] = {
{ 0, 0x00, 0x00 }
};
-#define BUSCLOCK(D) \
- ((struct chipset_bus_clock_list_entry *) pci_get_drvdata((D)))
-
-
/*
* TO DO: active tuning and correction of cards without a bios.
*/
@@ -88,6 +86,8 @@ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
u16 d_conf = 0;
u8 ultra = 0, ultra_conf = 0;
u8 tmp0 = 0, tmp1 = 0, tmp2 = 0;
@@ -96,7 +96,7 @@ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
local_irq_save(flags);
/* 0x40|(2*drive->dn): Active, 0x41|(2*drive->dn): Recovery */
pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf);
- tmp0 = pci_bus_clock_list(speed, BUSCLOCK(dev));
+ tmp0 = pci_bus_clock_list(speed, bus_clock);
d_conf = ((tmp0 & 0xf0) << 4) | (tmp0 & 0xf);
pci_write_config_word(dev, 0x40|(2*drive->dn), d_conf);
@@ -104,7 +104,7 @@ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
tmp2 = 0x00;
pci_read_config_byte(dev, 0x54, &ultra);
tmp1 = ((0x00 << (2*drive->dn)) | (ultra & ~(3 << (2*drive->dn))));
- ultra_conf = pci_bus_clock_list_ultra(speed, BUSCLOCK(dev));
+ ultra_conf = pci_bus_clock_list_ultra(speed, bus_clock);
tmp2 = ((ultra_conf << (2*drive->dn)) | (tmp1 & ~(3 << (2*drive->dn))));
pci_write_config_byte(dev, 0x54, tmp2);
local_irq_restore(flags);
@@ -114,6 +114,8 @@ static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
u8 unit = (drive->select.b.unit & 0x01);
u8 tmp1 = 0, tmp2 = 0;
u8 ultra = 0, drive_conf = 0, ultra_conf = 0;
@@ -122,12 +124,12 @@ static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
local_irq_save(flags);
/* high 4-bits: Active, low 4-bits: Recovery */
pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf);
- drive_conf = pci_bus_clock_list(speed, BUSCLOCK(dev));
+ drive_conf = pci_bus_clock_list(speed, bus_clock);
pci_write_config_byte(dev, 0x40|drive->dn, drive_conf);
pci_read_config_byte(dev, (0x44|hwif->channel), &ultra);
tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit))));
- ultra_conf = pci_bus_clock_list_ultra(speed, BUSCLOCK(dev));
+ ultra_conf = pci_bus_clock_list_ultra(speed, bus_clock);
tmp2 = ((ultra_conf << (4*unit)) | (tmp1 & ~(7 << (4*unit))));
pci_write_config_byte(dev, (0x44|hwif->channel), tmp2);
local_irq_restore(flags);
@@ -138,15 +140,8 @@ static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio)
drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0);
}
-static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev)
{
- int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
-
- if (bus_speed <= 33)
- pci_set_drvdata(dev, (void *) aec6xxx_33_base);
- else
- pci_set_drvdata(dev, (void *) aec6xxx_34_base);
-
/* These are necessary to get AEC6280 Macintosh cards to work */
if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) ||
(dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)) {
@@ -187,57 +182,56 @@ static const struct ide_port_ops atp86x_port_ops = {
};
static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
- { /* 0 */
- .name = "AEC6210",
+ { /* 0: AEC6210 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_aec62xx,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.port_ops = &atp850_port_ops,
.host_flags = IDE_HFLAG_SERIALIZE |
IDE_HFLAG_NO_ATAPI_DMA |
IDE_HFLAG_NO_DSC |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA2,
- },{ /* 1 */
- .name = "AEC6260",
+ },
+ { /* 1: AEC6260 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_aec62xx,
.port_ops = &atp86x_port_ops,
.host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
- },{ /* 2 */
- .name = "AEC6260R",
+ },
+ { /* 2: AEC6260R */
+ .name = DRV_NAME,
.init_chipset = init_chipset_aec62xx,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.port_ops = &atp86x_port_ops,
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_NON_BOOTABLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
- },{ /* 3 */
- .name = "AEC6280",
+ },
+ { /* 3: AEC6280 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_aec62xx,
.port_ops = &atp86x_port_ops,
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
- },{ /* 4 */
- .name = "AEC6280R",
+ },
+ { /* 4: AEC6280R */
+ .name = DRV_NAME,
.init_chipset = init_chipset_aec62xx,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.port_ops = &atp86x_port_ops,
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
@@ -259,10 +253,17 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
+ const struct chipset_bus_clock_list_entry *bus_clock;
struct ide_port_info d;
u8 idx = id->driver_data;
+ int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
int err;
+ if (bus_speed <= 33)
+ bus_clock = aec6xxx_33_base;
+ else
+ bus_clock = aec6xxx_34_base;
+
err = pci_enable_device(dev);
if (err)
return err;
@@ -273,18 +274,25 @@ static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_devi
unsigned long dma_base = pci_resource_start(dev, 4);
if (inb(dma_base + 2) & 0x10) {
- d.name = (idx == 4) ? "AEC6880R" : "AEC6880";
+ printk(KERN_INFO DRV_NAME " %s: AEC6880%s card detected"
+ "\n", pci_name(dev), (idx == 4) ? "R" : "");
d.udma_mask = ATA_UDMA6;
}
}
- err = ide_setup_pci_device(dev, &d);
+ err = ide_pci_init_one(dev, &d, (void *)bus_clock);
if (err)
pci_disable_device(dev);
return err;
}
+static void __devexit aec62xx_remove(struct pci_dev *dev)
+{
+ ide_pci_remove(dev);
+ pci_disable_device(dev);
+}
+
static const struct pci_device_id aec62xx_pci_tbl[] = {
{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF), 0 },
{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP860), 1 },
@@ -299,6 +307,7 @@ static struct pci_driver driver = {
.name = "AEC62xx_IDE",
.id_table = aec62xx_pci_tbl,
.probe = aec62xx_init_one,
+ .remove = aec62xx_remove,
};
static int __init aec62xx_ide_init(void)
@@ -306,7 +315,13 @@ static int __init aec62xx_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit aec62xx_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(aec62xx_ide_init);
+module_exit(aec62xx_ide_exit);
MODULE_AUTHOR("Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for ARTOP AEC62xx IDE");
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index 80d19c0eb78..b582687e0cd 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -38,6 +38,8 @@
#include <asm/io.h>
+#define DRV_NAME "alim15x3"
+
/*
* Allow UDMA on M1543C-E chipset for WDC disks that ignore CRC checking
* (this is DANGEROUS and could result in data corruption).
@@ -207,13 +209,12 @@ static int ali15x3_dma_setup(ide_drive_t *drive)
/**
* init_chipset_ali15x3 - Initialise an ALi IDE controller
* @dev: PCI device
- * @name: Name of the controller
*
* This function initializes the ALI IDE controller and where
* appropriate also sets up the 1533 southbridge.
*/
-
-static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const char *name)
+
+static unsigned int __devinit init_chipset_ali15x3(struct pci_dev *dev)
{
unsigned long flags;
u8 tmpbyte;
@@ -471,7 +472,15 @@ static int __devinit init_dma_ali15x3(ide_hwif_t *hwif,
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long base = ide_pci_dma_base(hwif, d);
- if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
+ if (base == 0)
+ return -1;
+
+ hwif->dma_base = base;
+
+ if (ide_pci_check_simplex(hwif, d) < 0)
+ return -1;
+
+ if (ide_pci_set_master(dev, d->name) < 0)
return -1;
if (!hwif->channel)
@@ -483,7 +492,7 @@ static int __devinit init_dma_ali15x3(ide_hwif_t *hwif,
if (ide_allocate_dma_engine(hwif))
return -1;
- ide_setup_dma(hwif, base);
+ hwif->dma_ops = &sff_dma_ops;
return 0;
}
@@ -507,7 +516,7 @@ static const struct ide_dma_ops ali_dma_ops = {
};
static const struct ide_port_info ali15x3_chipset __devinitdata = {
- .name = "ALI15X3",
+ .name = DRV_NAME,
.init_chipset = init_chipset_ali15x3,
.init_hwif = init_hwif_ali15x3,
.init_dma = init_dma_ali15x3,
@@ -557,7 +566,7 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev
if (idx == 0)
d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
- return ide_setup_pci_device(dev, &d);
+ return ide_pci_init_one(dev, &d, NULL);
}
@@ -572,6 +581,7 @@ static struct pci_driver driver = {
.name = "ALI15x3_IDE",
.id_table = alim15x3_pci_tbl,
.probe = alim15x3_init_one,
+ .remove = ide_pci_remove,
};
static int __init ali15x3_ide_init(void)
@@ -579,7 +589,13 @@ static int __init ali15x3_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit ali15x3_ide_exit(void)
+{
+ return pci_unregister_driver(&driver);
+}
+
module_init(ali15x3_ide_init);
+module_exit(ali15x3_ide_exit);
MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox");
MODULE_DESCRIPTION("PCI driver module for ALi 15x3 IDE");
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index 0bfcdd0e77b..2cea7bf51a0 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -21,6 +21,8 @@
#include <linux/init.h>
#include <linux/ide.h>
+#define DRV_NAME "amd74xx"
+
enum {
AMD_IDE_CONFIG = 0x41,
AMD_CABLE_DETECT = 0x42,
@@ -110,15 +112,13 @@ static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio)
amd_set_drive(drive, XFER_PIO_0 + pio);
}
-static void __devinit amd7409_cable_detect(struct pci_dev *dev,
- const char *name)
+static void __devinit amd7409_cable_detect(struct pci_dev *dev)
{
/* no host side cable detection */
amd_80w = 0x03;
}
-static void __devinit amd7411_cable_detect(struct pci_dev *dev,
- const char *name)
+static void __devinit amd7411_cable_detect(struct pci_dev *dev)
{
int i;
u32 u = 0;
@@ -129,9 +129,9 @@ static void __devinit amd7411_cable_detect(struct pci_dev *dev,
amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
for (i = 24; i >= 0; i -= 8)
if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
- printk(KERN_WARNING "%s: BIOS didn't set cable bits "
- "correctly. Enabling workaround.\n",
- name);
+ printk(KERN_WARNING DRV_NAME " %s: BIOS didn't set "
+ "cable bits correctly. Enabling workaround.\n",
+ pci_name(dev));
amd_80w |= (1 << (1 - (i >> 4)));
}
}
@@ -140,8 +140,7 @@ static void __devinit amd7411_cable_detect(struct pci_dev *dev,
* The initialization callback. Initialize drive independent registers.
*/
-static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev,
- const char *name)
+static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev)
{
u8 t = 0, offset = amd_offset(dev);
@@ -154,9 +153,9 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev,
; /* no UDMA > 2 */
else if (dev->vendor == PCI_VENDOR_ID_AMD &&
dev->device == PCI_DEVICE_ID_AMD_VIPER_7409)
- amd7409_cable_detect(dev, name);
+ amd7409_cable_detect(dev);
else
- amd7411_cable_detect(dev, name);
+ amd7411_cable_detect(dev);
/*
* Take care of prefetch & postwrite.
@@ -173,24 +172,6 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev,
t |= 0xf0;
pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t);
-/*
- * Determine the system bus clock.
- */
-
- amd_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000;
-
- switch (amd_clock) {
- case 33000: amd_clock = 33333; break;
- case 37000: amd_clock = 37500; break;
- case 41000: amd_clock = 41666; break;
- }
-
- if (amd_clock < 20000 || amd_clock > 50000) {
- printk(KERN_WARNING "%s: User given PCI clock speed impossible (%d), using 33 MHz instead.\n",
- name, amd_clock);
- amd_clock = 33333;
- }
-
return dev->irq;
}
@@ -218,14 +199,13 @@ static const struct ide_port_ops amd_port_ops = {
#define IDE_HFLAGS_AMD \
(IDE_HFLAG_PIO_NO_BLACKLIST | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
IDE_HFLAG_POST_SET_MODE | \
IDE_HFLAG_IO_32BIT | \
IDE_HFLAG_UNMASK_IRQS)
-#define DECLARE_AMD_DEV(name_str, swdma, udma) \
+#define DECLARE_AMD_DEV(swdma, udma) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.init_chipset = init_chipset_amd74xx, \
.init_hwif = init_hwif_amd74xx, \
.enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, \
@@ -237,9 +217,9 @@ static const struct ide_port_ops amd_port_ops = {
.udma_mask = udma, \
}
-#define DECLARE_NV_DEV(name_str, udma) \
+#define DECLARE_NV_DEV(udma) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.init_chipset = init_chipset_amd74xx, \
.init_hwif = init_hwif_amd74xx, \
.enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, \
@@ -252,31 +232,15 @@ static const struct ide_port_ops amd_port_ops = {
}
static const struct ide_port_info amd74xx_chipsets[] __devinitdata = {
- /* 0 */ DECLARE_AMD_DEV("AMD7401", 0x00, ATA_UDMA2),
- /* 1 */ DECLARE_AMD_DEV("AMD7409", ATA_SWDMA2, ATA_UDMA4),
- /* 2 */ DECLARE_AMD_DEV("AMD7411", ATA_SWDMA2, ATA_UDMA5),
- /* 3 */ DECLARE_AMD_DEV("AMD7441", ATA_SWDMA2, ATA_UDMA5),
- /* 4 */ DECLARE_AMD_DEV("AMD8111", ATA_SWDMA2, ATA_UDMA6),
-
- /* 5 */ DECLARE_NV_DEV("NFORCE", ATA_UDMA5),
- /* 6 */ DECLARE_NV_DEV("NFORCE2", ATA_UDMA6),
- /* 7 */ DECLARE_NV_DEV("NFORCE2-U400R", ATA_UDMA6),
- /* 8 */ DECLARE_NV_DEV("NFORCE2-U400R-SATA", ATA_UDMA6),
- /* 9 */ DECLARE_NV_DEV("NFORCE3-150", ATA_UDMA6),
- /* 10 */ DECLARE_NV_DEV("NFORCE3-250", ATA_UDMA6),
- /* 11 */ DECLARE_NV_DEV("NFORCE3-250-SATA", ATA_UDMA6),
- /* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2", ATA_UDMA6),
- /* 13 */ DECLARE_NV_DEV("NFORCE-CK804", ATA_UDMA6),
- /* 14 */ DECLARE_NV_DEV("NFORCE-MCP04", ATA_UDMA6),
- /* 15 */ DECLARE_NV_DEV("NFORCE-MCP51", ATA_UDMA6),
- /* 16 */ DECLARE_NV_DEV("NFORCE-MCP55", ATA_UDMA6),
- /* 17 */ DECLARE_NV_DEV("NFORCE-MCP61", ATA_UDMA6),
- /* 18 */ DECLARE_NV_DEV("NFORCE-MCP65", ATA_UDMA6),
- /* 19 */ DECLARE_NV_DEV("NFORCE-MCP67", ATA_UDMA6),
- /* 20 */ DECLARE_NV_DEV("NFORCE-MCP73", ATA_UDMA6),
- /* 21 */ DECLARE_NV_DEV("NFORCE-MCP77", ATA_UDMA6),
-
- /* 22 */ DECLARE_AMD_DEV("AMD5536", ATA_SWDMA2, ATA_UDMA5),
+ /* 0: AMD7401 */ DECLARE_AMD_DEV(0x00, ATA_UDMA2),
+ /* 1: AMD7409 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA4),
+ /* 2: AMD7411/7441 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5),
+ /* 3: AMD8111 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA6),
+
+ /* 4: NFORCE */ DECLARE_NV_DEV(ATA_UDMA5),
+ /* 5: >= NFORCE2 */ DECLARE_NV_DEV(ATA_UDMA6),
+
+ /* 6: AMD5536 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5),
};
static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
@@ -293,47 +257,64 @@ static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_
if (dev->revision <= 7)
d.swdma_mask = 0;
d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
- } else if (idx == 4) {
+ } else if (idx == 3) {
if (dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
d.udma_mask = ATA_UDMA5;
}
- printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n",
- d.name, pci_name(dev), dev->revision,
- amd_dma[fls(d.udma_mask) - 1]);
+ printk(KERN_INFO "%s %s: UDMA%s controller\n",
+ d.name, pci_name(dev), amd_dma[fls(d.udma_mask) - 1]);
+
+ /*
+ * Determine the system bus clock.
+ */
+ amd_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000;
+
+ switch (amd_clock) {
+ case 33000: amd_clock = 33333; break;
+ case 37000: amd_clock = 37500; break;
+ case 41000: amd_clock = 41666; break;
+ }
+
+ if (amd_clock < 20000 || amd_clock > 50000) {
+ printk(KERN_WARNING "%s: User given PCI clock speed impossible"
+ " (%d), using 33 MHz instead.\n",
+ d.name, amd_clock);
+ amd_clock = 33333;
+ }
- return ide_setup_pci_device(dev, &d);
+ return ide_pci_init_one(dev, &d, NULL);
}
static const struct pci_device_id amd74xx_pci_tbl[] = {
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_COBRA_7401), 0 },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_VIPER_7409), 1 },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_VIPER_7411), 2 },
- { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_OPUS_7441), 3 },
- { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_8111_IDE), 4 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE), 5 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE), 6 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE), 7 },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_OPUS_7441), 2 },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_8111_IDE), 3 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE), 4 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE), 5 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA), 8 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA), 5 },
#endif
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE), 9 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE), 10 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE), 5 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA), 11 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2), 12 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2), 5 },
#endif
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE), 13 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE), 14 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE), 15 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE), 16 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE), 17 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE), 18 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE), 19 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE), 20 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE), 21 },
- { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), 22 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE), 5 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE), 5 },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), 6 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
@@ -342,6 +323,7 @@ static struct pci_driver driver = {
.name = "AMD_IDE",
.id_table = amd74xx_pci_tbl,
.probe = amd74xx_probe,
+ .remove = ide_pci_remove,
};
static int __init amd74xx_ide_init(void)
@@ -349,7 +331,13 @@ static int __init amd74xx_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit amd74xx_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(amd74xx_ide_init);
+module_exit(amd74xx_ide_exit);
MODULE_AUTHOR("Vojtech Pavlik");
MODULE_DESCRIPTION("AMD PCI IDE driver");
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index 8b637181681..332f08f43b5 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -11,6 +11,8 @@
#include <linux/ide.h>
#include <linux/init.h>
+#define DRV_NAME "atiixp"
+
#define ATIIXP_IDE_PIO_TIMING 0x40
#define ATIIXP_IDE_MDMA_TIMING 0x44
#define ATIIXP_IDE_PIO_CONTROL 0x48
@@ -137,16 +139,17 @@ static const struct ide_port_ops atiixp_port_ops = {
};
static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
- { /* 0 */
- .name = "ATIIXP",
+ { /* 0: IXP200/300/400/700 */
+ .name = DRV_NAME,
.enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
.port_ops = &atiixp_port_ops,
.host_flags = IDE_HFLAG_LEGACY_IRQS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
- },{ /* 1 */
- .name = "SB600_PATA",
+ },
+ { /* 1: IXP600 */
+ .name = DRV_NAME,
.enablebits = {{0x48,0x01,0x00}, {0x00,0x00,0x00}},
.port_ops = &atiixp_port_ops,
.host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS,
@@ -167,7 +170,7 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
static int __devinit atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &atiixp_pci_info[id->driver_data]);
+ return ide_pci_init_one(dev, &atiixp_pci_info[id->driver_data], NULL);
}
static const struct pci_device_id atiixp_pci_tbl[] = {
@@ -184,6 +187,7 @@ static struct pci_driver driver = {
.name = "ATIIXP_IDE",
.id_table = atiixp_pci_tbl,
.probe = atiixp_init_one,
+ .remove = ide_pci_remove,
};
static int __init atiixp_ide_init(void)
@@ -191,7 +195,13 @@ static int __init atiixp_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit atiixp_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(atiixp_ide_init);
+module_exit(atiixp_ide_exit);
MODULE_AUTHOR("HUI YU");
MODULE_DESCRIPTION("PCI driver module for ATI IXP IDE");
diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
index 1ad1e23e310..e6c62006ca1 100644
--- a/drivers/ide/pci/cmd640.c
+++ b/drivers/ide/pci/cmd640.c
@@ -181,11 +181,6 @@ static u8 recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */
static DEFINE_SPINLOCK(cmd640_lock);
/*
- * These are initialized to point at the devices we control
- */
-static ide_hwif_t *cmd_hwif0, *cmd_hwif1;
-
-/*
* Interface to access cmd640x registers
*/
static unsigned int cmd640_key;
@@ -717,8 +712,7 @@ static int __init cmd640x_init(void)
int second_port_cmd640 = 0, rc;
const char *bus_type, *port2;
u8 b, cfr;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw[2];
+ hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
if (cmd640_vlb && probe_for_cmd640_vlb()) {
bus_type = "VLB";
@@ -781,15 +775,10 @@ static int __init cmd640x_init(void)
printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x"
"\n", 'a' + cmd640_chip_version - 1, bus_type, cfr);
- cmd_hwif0 = ide_find_port();
-
/*
* Initialize data for primary port
*/
- if (cmd_hwif0) {
- ide_init_port_hw(cmd_hwif0, &hw[0]);
- idx[0] = cmd_hwif0->index;
- }
+ hws[0] = &hw[0];
/*
* Ensure compatibility by always using the slowest timings
@@ -829,13 +818,9 @@ static int __init cmd640x_init(void)
/*
* Initialize data for secondary cmd640 port, if enabled
*/
- if (second_port_cmd640) {
- cmd_hwif1 = ide_find_port();
- if (cmd_hwif1) {
- ide_init_port_hw(cmd_hwif1, &hw[1]);
- idx[1] = cmd_hwif1->index;
- }
- }
+ if (second_port_cmd640)
+ hws[1] = &hw[1];
+
printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n",
second_port_cmd640 ? "" : "not ", port2);
@@ -843,9 +828,7 @@ static int __init cmd640x_init(void)
cmd640_dump_regs();
#endif
- ide_device_add(idx, &cmd640_port_info);
-
- return 1;
+ return ide_host_add(&cmd640_port_info, hws, NULL);
}
module_param_named(probe_vlb, cmd640_vlb, bool, 0);
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index cfa784bacf4..1360b4fa9fd 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -19,6 +19,8 @@
#include <asm/io.h>
+#define DRV_NAME "cmd64x"
+
#define CMD_DEBUG 0
#if CMD_DEBUG
@@ -262,7 +264,7 @@ static int cmd648_dma_test_irq(ide_drive_t *drive)
unsigned long base = hwif->dma_base - (hwif->channel * 8);
u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
MRDMODE_INTR_CH0;
- u8 dma_stat = inb(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
u8 mrdmode = inb(base + 1);
#ifdef DEBUG
@@ -286,7 +288,7 @@ static int cmd64x_dma_test_irq(ide_drive_t *drive)
int irq_reg = hwif->channel ? ARTTIM23 : CFR;
u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 :
CFR_INTR_CH0;
- u8 dma_stat = inb(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
u8 irq_stat = 0;
(void) pci_read_config_byte(dev, irq_reg, &irq_stat);
@@ -317,41 +319,23 @@ static int cmd646_1_dma_end(ide_drive_t *drive)
drive->waiting_for_dma = 0;
/* get DMA status */
- dma_stat = inb(hwif->dma_status);
+ dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
/* read DMA command state */
- dma_cmd = inb(hwif->dma_command);
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
/* stop DMA */
- outb(dma_cmd & ~1, hwif->dma_command);
+ outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
/* clear the INTR & ERROR bits */
- outb(dma_stat | 6, hwif->dma_status);
+ outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
/* and free any DMA resources */
ide_destroy_dmatable(drive);
/* verify good DMA status */
return (dma_stat & 7) != 4;
}
-static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev)
{
u8 mrdmode = 0;
- if (dev->device == PCI_DEVICE_ID_CMD_646) {
-
- switch (dev->revision) {
- case 0x07:
- case 0x05:
- printk("%s: UltraDMA capable\n", name);
- break;
- case 0x03:
- default:
- printk("%s: MultiWord DMA force limited\n", name);
- break;
- case 0x01:
- printk("%s: MultiWord DMA limited, "
- "IRQ workaround enabled\n", name);
- break;
- }
- }
-
/* Set a good latency timer and cache line size value. */
(void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
/* FIXME: pci_set_master() to ensure a good latency timer value */
@@ -425,8 +409,8 @@ static const struct ide_dma_ops cmd648_dma_ops = {
};
static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
- { /* 0 */
- .name = "CMD643",
+ { /* 0: CMD643 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_cmd64x,
.enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
.port_ops = &cmd64x_port_ops,
@@ -436,8 +420,9 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = 0x00, /* no udma */
- },{ /* 1 */
- .name = "CMD646",
+ },
+ { /* 1: CMD646 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_cmd64x,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
.chipset = ide_cmd646,
@@ -447,8 +432,9 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA2,
- },{ /* 2 */
- .name = "CMD648",
+ },
+ { /* 2: CMD648 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_cmd64x,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
.port_ops = &cmd64x_port_ops,
@@ -457,8 +443,9 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
- },{ /* 3 */
- .name = "CMD649",
+ },
+ { /* 3: CMD649 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_cmd64x,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
.port_ops = &cmd64x_port_ops,
@@ -507,7 +494,7 @@ static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_devic
}
}
- return ide_setup_pci_device(dev, &d);
+ return ide_pci_init_one(dev, &d, NULL);
}
static const struct pci_device_id cmd64x_pci_tbl[] = {
@@ -523,6 +510,7 @@ static struct pci_driver driver = {
.name = "CMD64x_IDE",
.id_table = cmd64x_pci_tbl,
.probe = cmd64x_init_one,
+ .remove = ide_pci_remove,
};
static int __init cmd64x_ide_init(void)
@@ -530,7 +518,13 @@ static int __init cmd64x_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit cmd64x_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(cmd64x_ide_init);
+module_exit(cmd64x_ide_exit);
MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for CMD64x IDE");
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
index 992b1cf8db6..c0364b287f1 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/pci/cs5520.c
@@ -41,6 +41,8 @@
#include <linux/ide.h>
#include <linux/dma-mapping.h>
+#define DRV_NAME "cs5520"
+
struct pio_clocks
{
int address;
@@ -62,8 +64,6 @@ static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
struct pci_dev *pdev = to_pci_dev(hwif->dev);
int controller = drive->dn > 1 ? 1 : 0;
- /* FIXME: if DMA = 1 do we need to set the DMA bit here ? */
-
/* 8bit CAT/CRT - 8bit command timing for channel */
pci_write_config_byte(pdev, 0x62 + controller,
(cs5520_pio_clocks[pio].recovery << 4) |
@@ -89,52 +89,16 @@ static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed)
cs5520_set_pio_mode(drive, 0);
}
-/*
- * We wrap the DMA activate to set the vdma flag. This is needed
- * so that the IDE DMA layer issues PIO not DMA commands over the
- * DMA channel
- *
- * ATAPI is harder so disable it for now using IDE_HFLAG_NO_ATAPI_DMA
- */
-
-static void cs5520_dma_host_set(ide_drive_t *drive, int on)
-{
- drive->vdma = on;
- ide_dma_host_set(drive, on);
-}
-
static const struct ide_port_ops cs5520_port_ops = {
.set_pio_mode = cs5520_set_pio_mode,
.set_dma_mode = cs5520_set_dma_mode,
};
-static const struct ide_dma_ops cs5520_dma_ops = {
- .dma_host_set = cs5520_dma_host_set,
- .dma_setup = ide_dma_setup,
- .dma_exec_cmd = ide_dma_exec_cmd,
- .dma_start = ide_dma_start,
- .dma_end = __ide_dma_end,
- .dma_test_irq = ide_dma_test_irq,
- .dma_lost_irq = ide_dma_lost_irq,
- .dma_timeout = ide_dma_timeout,
-};
-
-/* FIXME: VDMA is disabled because it caused system hangs */
-#define DECLARE_CS_DEV(name_str) \
- { \
- .name = name_str, \
- .port_ops = &cs5520_port_ops, \
- .dma_ops = &cs5520_dma_ops, \
- .host_flags = IDE_HFLAG_ISA_PORTS | \
- IDE_HFLAG_CS5520 | \
- IDE_HFLAG_NO_ATAPI_DMA | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE, \
- .pio_mask = ATA_PIO4, \
- }
-
-static const struct ide_port_info cyrix_chipsets[] __devinitdata = {
- /* 0 */ DECLARE_CS_DEV("Cyrix 5510"),
- /* 1 */ DECLARE_CS_DEV("Cyrix 5520")
+static const struct ide_port_info cyrix_chipset __devinitdata = {
+ .name = DRV_NAME,
+ .port_ops = &cs5520_port_ops,
+ .host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_CS5520,
+ .pio_mask = ATA_PIO4,
};
/*
@@ -145,8 +109,8 @@ static const struct ide_port_info cyrix_chipsets[] __devinitdata = {
static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- const struct ide_port_info *d = &cyrix_chipsets[id->driver_data];
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ const struct ide_port_info *d = &cyrix_chipset;
+ hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
ide_setup_pci_noise(dev, d);
@@ -159,7 +123,8 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
}
pci_set_master(dev);
if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
- printk(KERN_WARNING "cs5520: No suitable DMA available.\n");
+ printk(KERN_WARNING "%s: No suitable DMA available.\n",
+ d->name);
return -ENODEV;
}
@@ -168,11 +133,9 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
* do all the device setup for us
*/
- ide_pci_setup_ports(dev, d, 14, &idx[0]);
-
- ide_device_add(idx, d);
+ ide_pci_setup_ports(dev, d, 14, &hw[0], &hws[0]);
- return 0;
+ return ide_host_add(d, hws, NULL);
}
static const struct pci_device_id cs5520_pci_tbl[] = {
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index f5534c1ff34..f235db8c678 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -22,6 +22,8 @@
#include <asm/io.h>
+#define DRV_NAME "cs5530"
+
/*
* Here are the standard PIO mode 0-4 timings for each "format".
* Format-0 uses fast data reg timings, with slower command reg timings.
@@ -127,12 +129,11 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
/**
* init_chipset_5530 - set up 5530 bridge
* @dev: PCI device
- * @name: device name
*
* Initialize the cs5530 bridge for reliable IDE DMA operation.
*/
-static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_cs5530(struct pci_dev *dev)
{
struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
@@ -151,11 +152,11 @@ static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const ch
}
}
if (!master_0) {
- printk(KERN_ERR "%s: unable to locate PCI MASTER function\n", name);
+ printk(KERN_ERR DRV_NAME ": unable to locate PCI MASTER function\n");
goto out;
}
if (!cs5530_0) {
- printk(KERN_ERR "%s: unable to locate CS5530 LEGACY function\n", name);
+ printk(KERN_ERR DRV_NAME ": unable to locate CS5530 LEGACY function\n");
goto out;
}
@@ -243,7 +244,7 @@ static const struct ide_port_ops cs5530_port_ops = {
};
static const struct ide_port_info cs5530_chipset __devinitdata = {
- .name = "CS5530",
+ .name = DRV_NAME,
.init_chipset = init_chipset_cs5530,
.init_hwif = init_hwif_cs5530,
.port_ops = &cs5530_port_ops,
@@ -256,7 +257,7 @@ static const struct ide_port_info cs5530_chipset __devinitdata = {
static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &cs5530_chipset);
+ return ide_pci_init_one(dev, &cs5530_chipset, NULL);
}
static const struct pci_device_id cs5530_pci_tbl[] = {
@@ -269,6 +270,7 @@ static struct pci_driver driver = {
.name = "CS5530 IDE",
.id_table = cs5530_pci_tbl,
.probe = cs5530_init_one,
+ .remove = ide_pci_remove,
};
static int __init cs5530_ide_init(void)
@@ -276,7 +278,13 @@ static int __init cs5530_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit cs5530_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(cs5530_ide_init);
+module_exit(cs5530_ide_exit);
MODULE_AUTHOR("Mark Lord");
MODULE_DESCRIPTION("PCI driver module for Cyrix/NS 5530 IDE");
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
index dc97c48623f..f7b50cdeefa 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/pci/cs5535.c
@@ -26,6 +26,8 @@
#include <linux/pci.h>
#include <linux/ide.h>
+#define DRV_NAME "cs5535"
+
#define MSR_ATAC_BASE 0x51300000
#define ATAC_GLD_MSR_CAP (MSR_ATAC_BASE+0)
#define ATAC_GLD_MSR_CONFIG (MSR_ATAC_BASE+0x01)
@@ -169,10 +171,9 @@ static const struct ide_port_ops cs5535_port_ops = {
};
static const struct ide_port_info cs5535_chipset __devinitdata = {
- .name = "CS5535",
+ .name = DRV_NAME,
.port_ops = &cs5535_port_ops,
- .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE |
- IDE_HFLAG_ABUSE_SET_DMA_MODE,
+ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
@@ -181,7 +182,7 @@ static const struct ide_port_info cs5535_chipset __devinitdata = {
static int __devinit cs5535_init_one(struct pci_dev *dev,
const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &cs5535_chipset);
+ return ide_pci_init_one(dev, &cs5535_chipset, NULL);
}
static const struct pci_device_id cs5535_pci_tbl[] = {
@@ -195,6 +196,7 @@ static struct pci_driver driver = {
.name = "CS5535_IDE",
.id_table = cs5535_pci_tbl,
.probe = cs5535_init_one,
+ .remove = ide_pci_remove,
};
static int __init cs5535_ide_init(void)
@@ -202,7 +204,13 @@ static int __init cs5535_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit cs5535_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(cs5535_ide_init);
+module_exit(cs5535_ide_exit);
MODULE_AUTHOR("AMD");
MODULE_DESCRIPTION("PCI driver module for AMD/NS CS5535 IDE");
diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
index e14ad5530fa..bfae2f882f4 100644
--- a/drivers/ide/pci/cy82c693.c
+++ b/drivers/ide/pci/cy82c693.c
@@ -48,6 +48,8 @@
#include <asm/io.h>
+#define DRV_NAME "cy82c693"
+
/* the current version */
#define CY82_VERSION "CY82C693U driver v0.34 99-13-12 Andreas S. Krebs (akrebs@altavista.net)"
@@ -330,7 +332,7 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
/*
* this function is called during init and is used to setup the cy82c693 chip
*/
-static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev)
{
if (PCI_FUNC(dev->devfn) != 1)
return 0;
@@ -349,8 +351,8 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c
data = inb(CY82_DATA_PORT);
#if CY82C693_DEBUG_INFO
- printk(KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n",
- name, data);
+ printk(KERN_INFO DRV_NAME ": Peripheral Configuration Register: 0x%X\n",
+ data);
#endif /* CY82C693_DEBUG_INFO */
/*
@@ -371,8 +373,8 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c
outb(data, CY82_DATA_PORT);
#if CY82C693_DEBUG_INFO
- printk(KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n",
- name, data);
+ printk(KERN_INFO ": New Peripheral Configuration Register: 0x%X\n",
+ data);
#endif /* CY82C693_DEBUG_INFO */
#endif /* CY82C693_SETDMA_CLOCK */
@@ -398,7 +400,7 @@ static const struct ide_port_ops cy82c693_port_ops = {
};
static const struct ide_port_info cy82c693_chipset __devinitdata = {
- .name = "CY82C693",
+ .name = DRV_NAME,
.init_chipset = init_chipset_cy82c693,
.init_iops = init_iops_cy82c693,
.port_ops = &cy82c693_port_ops,
@@ -419,12 +421,22 @@ static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_dev
if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
PCI_FUNC(dev->devfn) == 1) {
dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
- ret = ide_setup_pci_devices(dev, dev2, &cy82c693_chipset);
- /* We leak pci refs here but thats ok - we can't be unloaded */
+ ret = ide_pci_init_two(dev, dev2, &cy82c693_chipset, NULL);
+ if (ret)
+ pci_dev_put(dev2);
}
return ret;
}
+static void __devexit cy82c693_remove(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
+
+ ide_pci_remove(dev);
+ pci_dev_put(dev2);
+}
+
static const struct pci_device_id cy82c693_pci_tbl[] = {
{ PCI_VDEVICE(CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693), 0 },
{ 0, },
@@ -435,6 +447,7 @@ static struct pci_driver driver = {
.name = "Cypress_IDE",
.id_table = cy82c693_pci_tbl,
.probe = cy82c693_init_one,
+ .remove = cy82c693_remove,
};
static int __init cy82c693_ide_init(void)
@@ -442,7 +455,13 @@ static int __init cy82c693_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit cy82c693_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(cy82c693_ide_init);
+module_exit(cy82c693_ide_exit);
MODULE_AUTHOR("Andreas Krebs, Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for the Cypress CY82C693 IDE");
diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c
index 0106e2a2df7..f84bfb4f600 100644
--- a/drivers/ide/pci/delkin_cb.c
+++ b/drivers/ide/pci/delkin_cb.c
@@ -56,11 +56,10 @@ static const struct ide_port_info delkin_cb_port_info = {
static int __devinit
delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
{
+ struct ide_host *host;
unsigned long base;
- hw_regs_t hw;
- ide_hwif_t *hwif = NULL;
int i, rc;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
rc = pci_enable_device(dev);
if (rc) {
@@ -87,34 +86,26 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
hw.dev = &dev->dev;
hw.chipset = ide_pci; /* this enables IRQ sharing */
- hwif = ide_find_port();
- if (hwif == NULL)
+ rc = ide_host_add(&delkin_cb_port_info, hws, &host);
+ if (rc)
goto out_disable;
- i = hwif->index;
-
- ide_init_port_hw(hwif, &hw);
-
- idx[0] = i;
-
- ide_device_add(idx, &delkin_cb_port_info);
-
- pci_set_drvdata(dev, hwif);
+ pci_set_drvdata(dev, host);
return 0;
out_disable:
pci_release_regions(dev);
pci_disable_device(dev);
- return -ENODEV;
+ return rc;
}
static void
delkin_cb_remove (struct pci_dev *dev)
{
- ide_hwif_t *hwif = pci_get_drvdata(dev);
+ struct ide_host *host = pci_get_drvdata(dev);
- ide_unregister(hwif);
+ ide_host_remove(host);
pci_release_regions(dev);
pci_disable_device(dev);
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index 041720e2276..b07d4f4273b 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -27,6 +27,8 @@
#include <linux/ide.h>
#include <linux/init.h>
+#define DRV_NAME "ide_pci_generic"
+
static int ide_generic_all; /* Set to claim all devices */
module_param_named(all_generic_ide, ide_generic_all, bool, 0444);
@@ -34,9 +36,9 @@ MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE st
#define IDE_HFLAGS_UMC (IDE_HFLAG_NO_DMA | IDE_HFLAG_FORCE_LEGACY_IRQS)
-#define DECLARE_GENERIC_PCI_DEV(name_str, extra_flags) \
+#define DECLARE_GENERIC_PCI_DEV(extra_flags) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | \
extra_flags, \
.swdma_mask = ATA_SWDMA2, \
@@ -45,10 +47,11 @@ MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE st
}
static const struct ide_port_info generic_chipsets[] __devinitdata = {
- /* 0 */ DECLARE_GENERIC_PCI_DEV("Unknown", 0),
+ /* 0: Unknown */
+ DECLARE_GENERIC_PCI_DEV(0),
- { /* 1 */
- .name = "NS87410",
+ { /* 1: NS87410 */
+ .name = DRV_NAME,
.enablebits = { {0x43, 0x08, 0x08}, {0x47, 0x08, 0x08} },
.host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA,
.swdma_mask = ATA_SWDMA2,
@@ -56,17 +59,15 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
.udma_mask = ATA_UDMA6,
},
- /* 2 */ DECLARE_GENERIC_PCI_DEV("SAMURAI", 0),
- /* 3 */ DECLARE_GENERIC_PCI_DEV("HT6565", 0),
- /* 4 */ DECLARE_GENERIC_PCI_DEV("UM8673F", IDE_HFLAGS_UMC),
- /* 5 */ DECLARE_GENERIC_PCI_DEV("UM8886A", IDE_HFLAGS_UMC),
- /* 6 */ DECLARE_GENERIC_PCI_DEV("UM8886BF", IDE_HFLAGS_UMC),
- /* 7 */ DECLARE_GENERIC_PCI_DEV("HINT_IDE", 0),
- /* 8 */ DECLARE_GENERIC_PCI_DEV("VIA_IDE", IDE_HFLAG_NO_AUTODMA),
- /* 9 */ DECLARE_GENERIC_PCI_DEV("OPTI621V", IDE_HFLAG_NO_AUTODMA),
-
- { /* 10 */
- .name = "VIA8237SATA",
+ /* 2: SAMURAI / HT6565 / HINT_IDE */
+ DECLARE_GENERIC_PCI_DEV(0),
+ /* 3: UM8673F / UM8886A / UM8886BF */
+ DECLARE_GENERIC_PCI_DEV(IDE_HFLAGS_UMC),
+ /* 4: VIA_IDE / OPTI621V / Piccolo010{2,3,5} */
+ DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_AUTODMA),
+
+ { /* 5: VIA8237SATA */
+ .name = DRV_NAME,
.host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
IDE_HFLAG_OFF_BOARD,
.swdma_mask = ATA_SWDMA2,
@@ -74,12 +75,8 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
.udma_mask = ATA_UDMA6,
},
- /* 11 */ DECLARE_GENERIC_PCI_DEV("Piccolo0102", IDE_HFLAG_NO_AUTODMA),
- /* 12 */ DECLARE_GENERIC_PCI_DEV("Piccolo0103", IDE_HFLAG_NO_AUTODMA),
- /* 13 */ DECLARE_GENERIC_PCI_DEV("Piccolo0105", IDE_HFLAG_NO_AUTODMA),
-
- { /* 14 */
- .name = "Revolution",
+ { /* 6: Revolution */
+ .name = DRV_NAME,
.host_flags = IDE_HFLAG_CLEAR_SIMPLEX |
IDE_HFLAG_TRUST_BIOS_FOR_DMA |
IDE_HFLAG_OFF_BOARD,
@@ -134,12 +131,12 @@ static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_devi
u16 command;
pci_read_config_word(dev, PCI_COMMAND, &command);
if (!(command & PCI_COMMAND_IO)) {
- printk(KERN_INFO "Skipping disabled %s IDE "
- "controller.\n", d->name);
+ printk(KERN_INFO "%s %s: skipping disabled "
+ "controller\n", d->name, pci_name(dev));
goto out;
}
}
- ret = ide_setup_pci_device(dev, d);
+ ret = ide_pci_init_one(dev, d, NULL);
out:
return ret;
}
@@ -147,20 +144,20 @@ out:
static const struct pci_device_id generic_pci_tbl[] = {
{ PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_87410), 1 },
{ PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE), 2 },
- { PCI_VDEVICE(HOLTEK, PCI_DEVICE_ID_HOLTEK_6565), 3 },
- { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8673F), 4 },
- { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886A), 5 },
- { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886BF), 6 },
- { PCI_VDEVICE(HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), 7 },
- { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C561), 8 },
- { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C558), 9 },
+ { PCI_VDEVICE(HOLTEK, PCI_DEVICE_ID_HOLTEK_6565), 2 },
+ { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8673F), 3 },
+ { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886A), 3 },
+ { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886BF), 3 },
+ { PCI_VDEVICE(HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), 2 },
+ { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C561), 4 },
+ { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C558), 4 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
- { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8237_SATA), 10 },
+ { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8237_SATA), 5 },
#endif
- { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO), 11 },
- { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), 12 },
- { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), 13 },
- { PCI_VDEVICE(NETCELL, PCI_DEVICE_ID_REVOLUTION), 14 },
+ { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO), 4 },
+ { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), 4 },
+ { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), 4 },
+ { PCI_VDEVICE(NETCELL, PCI_DEVICE_ID_REVOLUTION), 6 },
/*
* Must come last. If you add entries adjust
* this table and generic_chipsets[] appropriately.
@@ -174,6 +171,7 @@ static struct pci_driver driver = {
.name = "PCI_IDE",
.id_table = generic_pci_tbl,
.probe = generic_init_one,
+ .remove = ide_pci_remove,
};
static int __init generic_ide_init(void)
@@ -181,7 +179,13 @@ static int __init generic_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit generic_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(generic_ide_init);
+module_exit(generic_ide_exit);
MODULE_AUTHOR("Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for generic PCI IDE");
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index 84c36c11719..6009b0b9655 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -33,6 +33,8 @@
#include <linux/init.h>
#include <linux/ide.h>
+#define DRV_NAME "hpt34x"
+
#define HPT343_DEBUG_DRIVE_INFO 0
static void hpt34x_set_mode(ide_drive_t *drive, const u8 speed)
@@ -77,7 +79,7 @@ static void hpt34x_set_pio_mode(ide_drive_t *drive, const u8 pio)
*/
#define HPT34X_PCI_INIT_REG 0x80
-static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev)
{
int i = 0;
unsigned long hpt34xIoBase = pci_resource_start(dev, 4);
@@ -123,19 +125,18 @@ static const struct ide_port_ops hpt34x_port_ops = {
#define IDE_HFLAGS_HPT34X \
(IDE_HFLAG_NO_ATAPI_DMA | \
IDE_HFLAG_NO_DSC | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
IDE_HFLAG_NO_AUTODMA)
static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
- { /* 0 */
- .name = "HPT343",
+ { /* 0: HPT343 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_hpt34x,
.port_ops = &hpt34x_port_ops,
.host_flags = IDE_HFLAGS_HPT34X | IDE_HFLAG_NON_BOOTABLE,
.pio_mask = ATA_PIO5,
},
- { /* 1 */
- .name = "HPT345",
+ { /* 1: HPT345 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_hpt34x,
.port_ops = &hpt34x_port_ops,
.host_flags = IDE_HFLAGS_HPT34X | IDE_HFLAG_OFF_BOARD,
@@ -157,7 +158,7 @@ static int __devinit hpt34x_init_one(struct pci_dev *dev, const struct pci_devic
d = &hpt34x_chipsets[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0];
- return ide_setup_pci_device(dev, d);
+ return ide_pci_init_one(dev, d, NULL);
}
static const struct pci_device_id hpt34x_pci_tbl[] = {
@@ -170,6 +171,7 @@ static struct pci_driver driver = {
.name = "HPT34x_IDE",
.id_table = hpt34x_pci_tbl,
.probe = hpt34x_init_one,
+ .remove = ide_pci_remove,
};
static int __init hpt34x_ide_init(void)
@@ -177,7 +179,13 @@ static int __init hpt34x_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit hpt34x_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(hpt34x_ide_init);
+module_exit(hpt34x_ide_exit);
MODULE_AUTHOR("Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for Highpoint 34x IDE");
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 397c6cbe953..5271b246b88 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -131,6 +131,8 @@
#include <asm/uaccess.h>
#include <asm/io.h>
+#define DRV_NAME "hpt366"
+
/* various tuning parameters */
#define HPT_RESET_STATE_ENGINE
#undef HPT_DELAY_INTERRUPT
@@ -620,7 +622,8 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct hpt_info *info = pci_get_drvdata(dev);
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]);
u8 mask = hwif->ultra_mask;
switch (info->chip_type) {
@@ -660,7 +663,8 @@ static u8 hpt3xx_mdma_filter(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct hpt_info *info = pci_get_drvdata(dev);
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]);
switch (info->chip_type) {
case HPT372 :
@@ -694,8 +698,10 @@ static u32 get_speed_setting(u8 speed, struct hpt_info *info)
static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
{
- struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
- struct hpt_info *info = pci_get_drvdata(dev);
+ ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]);
struct hpt_timings *t = info->timings;
u8 itr_addr = 0x40 + (drive->dn * 4);
u32 old_itr = 0;
@@ -738,7 +744,8 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct hpt_info *info = pci_get_drvdata(dev);
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]);
if (drive->quirk_list) {
if (info->chip_type >= HPT370) {
@@ -801,9 +808,9 @@ static void hpt370_irq_timeout(ide_drive_t *drive)
printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff);
/* get DMA command mode */
- dma_cmd = inb(hwif->dma_command);
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
/* stop DMA */
- outb(dma_cmd & ~0x1, hwif->dma_command);
+ outb(dma_cmd & ~0x1, hwif->dma_base + ATA_DMA_CMD);
hpt370_clear_engine(drive);
}
@@ -818,12 +825,12 @@ static void hpt370_dma_start(ide_drive_t *drive)
static int hpt370_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- u8 dma_stat = inb(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
if (dma_stat & 0x01) {
/* wait a little */
udelay(20);
- dma_stat = inb(hwif->dma_status);
+ dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
if (dma_stat & 0x01)
hpt370_irq_timeout(drive);
}
@@ -850,7 +857,7 @@ static int hpt374_dma_test_irq(ide_drive_t *drive)
return 0;
}
- dma_stat = inb(hwif->dma_status);
+ dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
/* return 1 if INTR asserted */
if (dma_stat & 4)
return 1;
@@ -963,24 +970,16 @@ static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f
return 1;
}
-static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev)
{
- struct hpt_info *info = kmalloc(sizeof(struct hpt_info), GFP_KERNEL);
unsigned long io_base = pci_resource_start(dev, 4);
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct hpt_info *info = host->host_priv + (&dev->dev == host->dev[1]);
+ const char *name = DRV_NAME;
u8 pci_clk, dpll_clk = 0; /* PCI and DPLL clock in MHz */
u8 chip_type;
enum ata_clock clock;
- if (info == NULL) {
- printk(KERN_ERR "%s: out of memory!\n", name);
- return -ENOMEM;
- }
-
- /*
- * Copy everything from a static "template" structure
- * to just allocated per-chip hpt_info structure.
- */
- memcpy(info, pci_get_drvdata(dev), sizeof(struct hpt_info));
chip_type = info->chip_type;
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
@@ -1048,8 +1047,8 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
if ((temp & 0xFFFFF000) != 0xABCDE000) {
int i;
- printk(KERN_WARNING "%s: no clock data saved by BIOS\n",
- name);
+ printk(KERN_WARNING "%s %s: no clock data saved by "
+ "BIOS\n", name, pci_name(dev));
/* Calculate the average value of f_CNT. */
for (temp = i = 0; i < 128; i++) {
@@ -1074,8 +1073,9 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
else
pci_clk = 66;
- printk(KERN_INFO "%s: DPLL base: %d MHz, f_CNT: %d, "
- "assuming %d MHz PCI\n", name, dpll_clk, f_cnt, pci_clk);
+ printk(KERN_INFO "%s %s: DPLL base: %d MHz, f_CNT: %d, "
+ "assuming %d MHz PCI\n", name, pci_name(dev),
+ dpll_clk, f_cnt, pci_clk);
} else {
u32 itr1 = 0;
@@ -1141,8 +1141,8 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
}
if (info->timings->clock_table[clock] == NULL) {
- printk(KERN_ERR "%s: unknown bus timing!\n", name);
- kfree(info);
+ printk(KERN_ERR "%s %s: unknown bus timing!\n",
+ name, pci_name(dev));
return -EIO;
}
@@ -1168,17 +1168,19 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
f_low += adjust >> 1;
}
if (adjust == 8) {
- printk(KERN_ERR "%s: DPLL did not stabilize!\n", name);
- kfree(info);
+ printk(KERN_ERR "%s %s: DPLL did not stabilize!\n",
+ name, pci_name(dev));
return -EIO;
}
- printk("%s: using %d MHz DPLL clock\n", name, dpll_clk);
+ printk(KERN_INFO "%s %s: using %d MHz DPLL clock\n",
+ name, pci_name(dev), dpll_clk);
} else {
/* Mark the fact that we're not using the DPLL. */
dpll_clk = 0;
- printk("%s: using %d MHz PCI clock\n", name, pci_clk);
+ printk(KERN_INFO "%s %s: using %d MHz PCI clock\n",
+ name, pci_name(dev), pci_clk);
}
/* Store the clock frequencies. */
@@ -1186,9 +1188,6 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
info->pci_clk = pci_clk;
info->clock = clock;
- /* Point to this chip's own instance of the hpt_info structure. */
- pci_set_drvdata(dev, info);
-
if (chip_type >= HPT370) {
u8 mcr1, mcr4;
@@ -1218,7 +1217,8 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
static u8 __devinit hpt3xx_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct hpt_info *info = pci_get_drvdata(dev);
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]);
u8 chip_type = info->chip_type;
u8 scr1 = 0, ata66 = hwif->channel ? 0x01 : 0x02;
@@ -1262,7 +1262,8 @@ static u8 __devinit hpt3xx_cable_detect(ide_hwif_t *hwif)
static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct hpt_info *info = pci_get_drvdata(dev);
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct hpt_info *info = host->host_priv + (hwif->dev == host->dev[1]);
int serialize = HPT_SERIALIZE_IO;
u8 chip_type = info->chip_type;
u8 new_mcr, old_mcr = 0;
@@ -1320,7 +1321,15 @@ static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
unsigned long flags, base = ide_pci_dma_base(hwif, d);
u8 dma_old, dma_new, masterdma = 0, slavedma = 0;
- if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
+ if (base == 0)
+ return -1;
+
+ hwif->dma_base = base;
+
+ if (ide_pci_check_simplex(hwif, d) < 0)
+ return -1;
+
+ if (ide_pci_set_master(dev, d->name) < 0)
return -1;
dma_old = inb(base + 2);
@@ -1346,7 +1355,7 @@ static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
if (ide_allocate_dma_engine(hwif))
return -1;
- ide_setup_dma(hwif, base);
+ hwif->dma_ops = &sff_dma_ops;
return 0;
}
@@ -1356,7 +1365,8 @@ static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
if (dev2->irq != dev->irq) {
/* FIXME: we need a core pci_set_interrupt() */
dev2->irq = dev->irq;
- printk(KERN_INFO "HPT374: PCI config space interrupt fixed\n");
+ printk(KERN_INFO DRV_NAME " %s: PCI config space interrupt "
+ "fixed\n", pci_name(dev2));
}
}
@@ -1391,8 +1401,8 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
if (pin1 != pin2 && dev->irq == dev2->irq) {
- printk(KERN_INFO "HPT36x: onboard version of chipset, "
- "pin1=%d pin2=%d\n", pin1, pin2);
+ printk(KERN_INFO DRV_NAME " %s: onboard version of chipset, "
+ "pin1=%d pin2=%d\n", pci_name(dev), pin1, pin2);
return 1;
}
@@ -1401,7 +1411,6 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
#define IDE_HFLAGS_HPT3XX \
(IDE_HFLAG_NO_ATAPI_DMA | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
IDE_HFLAG_OFF_BOARD)
static const struct ide_port_ops hpt3xx_port_ops = {
@@ -1448,8 +1457,8 @@ static const struct ide_dma_ops hpt36x_dma_ops = {
};
static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
- { /* 0 */
- .name = "HPT36x",
+ { /* 0: HPT36x */
+ .name = DRV_NAME,
.init_chipset = init_chipset_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
@@ -1465,53 +1474,9 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
.host_flags = IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
- },{ /* 1 */
- .name = "HPT372A",
- .init_chipset = init_chipset_hpt366,
- .init_hwif = init_hwif_hpt366,
- .init_dma = init_dma_hpt366,
- .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- .port_ops = &hpt3xx_port_ops,
- .dma_ops = &hpt37x_dma_ops,
- .host_flags = IDE_HFLAGS_HPT3XX,
- .pio_mask = ATA_PIO4,
- .mwdma_mask = ATA_MWDMA2,
- },{ /* 2 */
- .name = "HPT302",
- .init_chipset = init_chipset_hpt366,
- .init_hwif = init_hwif_hpt366,
- .init_dma = init_dma_hpt366,
- .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- .port_ops = &hpt3xx_port_ops,
- .dma_ops = &hpt37x_dma_ops,
- .host_flags = IDE_HFLAGS_HPT3XX,
- .pio_mask = ATA_PIO4,
- .mwdma_mask = ATA_MWDMA2,
- },{ /* 3 */
- .name = "HPT371",
- .init_chipset = init_chipset_hpt366,
- .init_hwif = init_hwif_hpt366,
- .init_dma = init_dma_hpt366,
- .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- .port_ops = &hpt3xx_port_ops,
- .dma_ops = &hpt37x_dma_ops,
- .host_flags = IDE_HFLAGS_HPT3XX,
- .pio_mask = ATA_PIO4,
- .mwdma_mask = ATA_MWDMA2,
- },{ /* 4 */
- .name = "HPT374",
- .init_chipset = init_chipset_hpt366,
- .init_hwif = init_hwif_hpt366,
- .init_dma = init_dma_hpt366,
- .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- .udma_mask = ATA_UDMA5,
- .port_ops = &hpt3xx_port_ops,
- .dma_ops = &hpt37x_dma_ops,
- .host_flags = IDE_HFLAGS_HPT3XX,
- .pio_mask = ATA_PIO4,
- .mwdma_mask = ATA_MWDMA2,
- },{ /* 5 */
- .name = "HPT372N",
+ },
+ { /* 1: HPT3xx */
+ .name = DRV_NAME,
.init_chipset = init_chipset_hpt366,
.init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366,
@@ -1535,10 +1500,12 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
const struct hpt_info *info = NULL;
+ struct hpt_info *dyn_info;
struct pci_dev *dev2 = NULL;
struct ide_port_info d;
u8 idx = id->driver_data;
u8 rev = dev->revision;
+ int ret;
if ((idx == 0 || idx == 4) && (PCI_FUNC(dev->devfn) & 1))
return -ENODEV;
@@ -1575,24 +1542,35 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic
break;
}
- d = hpt366_chipsets[idx];
+ printk(KERN_INFO DRV_NAME ": %s chipset detected\n", info->chip_name);
+
+ d = hpt366_chipsets[min_t(u8, idx, 1)];
- d.name = info->chip_name;
d.udma_mask = info->udma_mask;
/* fixup ->dma_ops for HPT370/HPT370A */
if (info == &hpt370 || info == &hpt370a)
d.dma_ops = &hpt370_dma_ops;
- pci_set_drvdata(dev, (void *)info);
-
if (info == &hpt36x || info == &hpt374)
dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
- if (dev2) {
- int ret;
+ dyn_info = kzalloc(sizeof(*dyn_info) * (dev2 ? 2 : 1), GFP_KERNEL);
+ if (dyn_info == NULL) {
+ printk(KERN_ERR "%s %s: out of memory!\n",
+ d.name, pci_name(dev));
+ pci_dev_put(dev2);
+ return -ENOMEM;
+ }
- pci_set_drvdata(dev2, (void *)info);
+ /*
+ * Copy everything from a static "template" structure
+ * to just allocated per-chip hpt_info structure.
+ */
+ memcpy(dyn_info, info, sizeof(*dyn_info));
+
+ if (dev2) {
+ memcpy(dyn_info + 1, info, sizeof(*dyn_info));
if (info == &hpt374)
hpt374_init(dev, dev2);
@@ -1601,13 +1579,30 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic
d.host_flags &= ~IDE_HFLAG_NON_BOOTABLE;
}
- ret = ide_setup_pci_devices(dev, dev2, &d);
- if (ret < 0)
+ ret = ide_pci_init_two(dev, dev2, &d, dyn_info);
+ if (ret < 0) {
pci_dev_put(dev2);
+ kfree(dyn_info);
+ }
return ret;
}
- return ide_setup_pci_device(dev, &d);
+ ret = ide_pci_init_one(dev, &d, dyn_info);
+ if (ret < 0)
+ kfree(dyn_info);
+
+ return ret;
+}
+
+static void __devexit hpt366_remove(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct ide_info *info = host->host_priv;
+ struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
+
+ ide_pci_remove(dev);
+ pci_dev_put(dev2);
+ kfree(info);
}
static const struct pci_device_id hpt366_pci_tbl[] __devinitconst = {
@@ -1625,6 +1620,7 @@ static struct pci_driver driver = {
.name = "HPT366_IDE",
.id_table = hpt366_pci_tbl,
.probe = hpt366_init_one,
+ .remove = hpt366_remove,
};
static int __init hpt366_ide_init(void)
@@ -1632,7 +1628,13 @@ static int __init hpt366_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit hpt366_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(hpt366_ide_init);
+module_exit(hpt366_ide_exit);
MODULE_AUTHOR("Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE");
diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
index 2b71bdf74e7..6eba8f18826 100644
--- a/drivers/ide/pci/it8213.c
+++ b/drivers/ide/pci/it8213.c
@@ -14,6 +14,8 @@
#include <linux/ide.h>
#include <linux/init.h>
+#define DRV_NAME "it8213"
+
/**
* it8213_set_pio_mode - set host controller for PIO mode
* @drive: drive
@@ -155,23 +157,17 @@ static const struct ide_port_ops it8213_port_ops = {
.cable_detect = it8213_cable_detect,
};
-#define DECLARE_ITE_DEV(name_str) \
- { \
- .name = name_str, \
- .enablebits = { {0x41, 0x80, 0x80} }, \
- .port_ops = &it8213_port_ops, \
- .host_flags = IDE_HFLAG_SINGLE, \
- .pio_mask = ATA_PIO4, \
- .swdma_mask = ATA_SWDMA2_ONLY, \
- .mwdma_mask = ATA_MWDMA12_ONLY, \
- .udma_mask = ATA_UDMA6, \
- }
-
-static const struct ide_port_info it8213_chipsets[] __devinitdata = {
- /* 0 */ DECLARE_ITE_DEV("IT8213"),
+static const struct ide_port_info it8213_chipset __devinitdata = {
+ .name = DRV_NAME,
+ .enablebits = { {0x41, 0x80, 0x80} },
+ .port_ops = &it8213_port_ops,
+ .host_flags = IDE_HFLAG_SINGLE,
+ .pio_mask = ATA_PIO4,
+ .swdma_mask = ATA_SWDMA2_ONLY,
+ .mwdma_mask = ATA_MWDMA12_ONLY,
+ .udma_mask = ATA_UDMA6,
};
-
/**
* it8213_init_one - pci layer discovery entry
* @dev: PCI device
@@ -184,7 +180,7 @@ static const struct ide_port_info it8213_chipsets[] __devinitdata = {
static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &it8213_chipsets[id->driver_data]);
+ return ide_pci_init_one(dev, &it8213_chipset, NULL);
}
static const struct pci_device_id it8213_pci_tbl[] = {
@@ -198,6 +194,7 @@ static struct pci_driver driver = {
.name = "ITE8213_IDE",
.id_table = it8213_pci_tbl,
.probe = it8213_init_one,
+ .remove = ide_pci_remove,
};
static int __init it8213_ide_init(void)
@@ -205,7 +202,13 @@ static int __init it8213_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit it8213_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(it8213_ide_init);
+module_exit(it8213_ide_exit);
MODULE_AUTHOR("Jack Lee, Alan Cox");
MODULE_DESCRIPTION("PCI driver module for the ITE 8213");
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index cbf64720299..e16a1d113a2 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -67,6 +67,8 @@
#include <linux/ide.h>
#include <linux/init.h>
+#define DRV_NAME "it821x"
+
struct it821x_dev
{
unsigned int smart:1, /* Are we in smart raid mode */
@@ -534,8 +536,9 @@ static struct ide_dma_ops it821x_pass_through_dma_ops = {
static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct it821x_dev **itdevs = (struct it821x_dev **)pci_get_drvdata(dev);
- struct it821x_dev *idev = itdevs[hwif->channel];
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct it821x_dev *itdevs = host->host_priv;
+ struct it821x_dev *idev = itdevs + hwif->channel;
u8 conf;
ide_set_hwifdata(hwif, idev);
@@ -568,7 +571,8 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
idev->timing10 = 1;
hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
if (idev->smart == 0)
- printk(KERN_WARNING "it821x: Revision 0x10, workarounds activated.\n");
+ printk(KERN_WARNING DRV_NAME " %s: revision 0x10, "
+ "workarounds activated\n", pci_name(dev));
}
if (idev->smart == 0) {
@@ -601,18 +605,20 @@ static void __devinit it8212_disable_raid(struct pci_dev *dev)
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
}
-static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev)
{
u8 conf;
static char *mode[2] = { "pass through", "smart" };
/* Force the card into bypass mode if so requested */
if (it8212_noraid) {
- printk(KERN_INFO "it8212: forcing bypass mode.\n");
+ printk(KERN_INFO DRV_NAME " %s: forcing bypass mode\n",
+ pci_name(dev));
it8212_disable_raid(dev);
}
pci_read_config_byte(dev, 0x50, &conf);
- printk(KERN_INFO "it821x: controller in %s mode.\n", mode[conf & 1]);
+ printk(KERN_INFO DRV_NAME " %s: controller in %s mode\n",
+ pci_name(dev), mode[conf & 1]);
return 0;
}
@@ -624,17 +630,12 @@ static const struct ide_port_ops it821x_port_ops = {
.cable_detect = it821x_cable_detect,
};
-#define DECLARE_ITE_DEV(name_str) \
- { \
- .name = name_str, \
- .init_chipset = init_chipset_it821x, \
- .init_hwif = init_hwif_it821x, \
- .port_ops = &it821x_port_ops, \
- .pio_mask = ATA_PIO4, \
- }
-
-static const struct ide_port_info it821x_chipsets[] __devinitdata = {
- /* 0 */ DECLARE_ITE_DEV("IT8212"),
+static const struct ide_port_info it821x_chipset __devinitdata = {
+ .name = DRV_NAME,
+ .init_chipset = init_chipset_it821x,
+ .init_hwif = init_hwif_it821x,
+ .port_ops = &it821x_port_ops,
+ .pio_mask = ATA_PIO4,
};
/**
@@ -648,23 +649,29 @@ static const struct ide_port_info it821x_chipsets[] __devinitdata = {
static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- struct it821x_dev *itdevs[2] = { NULL, NULL} , *itdev;
- unsigned int i;
-
- for (i = 0; i < 2; i++) {
- itdev = kzalloc(sizeof(*itdev), GFP_KERNEL);
- if (itdev == NULL) {
- kfree(itdevs[0]);
- printk(KERN_ERR "it821x: out of memory\n");
- return -ENOMEM;
- }
+ struct it821x_dev *itdevs;
+ int rc;
- itdevs[i] = itdev;
+ itdevs = kzalloc(2 * sizeof(*itdevs), GFP_KERNEL);
+ if (itdevs == NULL) {
+ printk(KERN_ERR DRV_NAME " %s: out of memory\n", pci_name(dev));
+ return -ENOMEM;
}
- pci_set_drvdata(dev, itdevs);
+ rc = ide_pci_init_one(dev, &it821x_chipset, itdevs);
+ if (rc)
+ kfree(itdevs);
- return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
+ return rc;
+}
+
+static void __devexit it821x_remove(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct it821x_dev *itdevs = host->host_priv;
+
+ ide_pci_remove(dev);
+ kfree(itdevs);
}
static const struct pci_device_id it821x_pci_tbl[] = {
@@ -679,6 +686,7 @@ static struct pci_driver driver = {
.name = "ITE821x IDE",
.id_table = it821x_pci_tbl,
.probe = it821x_init_one,
+ .remove = it821x_remove,
};
static int __init it821x_ide_init(void)
@@ -686,7 +694,13 @@ static int __init it821x_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit it821x_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(it821x_ide_init);
+module_exit(it821x_ide_exit);
module_param_named(noraid, it8212_noraid, int, S_IRUGO);
MODULE_PARM_DESC(noraid, "Force card into bypass mode");
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index 96ef7394f28..545b6e172d9 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -12,6 +12,8 @@
#include <linux/ide.h>
#include <linux/init.h>
+#define DRV_NAME "jmicron"
+
typedef enum {
PORT_PATA0 = 0,
PORT_PATA1 = 1,
@@ -102,7 +104,7 @@ static const struct ide_port_ops jmicron_port_ops = {
};
static const struct ide_port_info jmicron_chipset __devinitdata = {
- .name = "JMB",
+ .name = DRV_NAME,
.enablebits = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } },
.port_ops = &jmicron_port_ops,
.pio_mask = ATA_PIO5,
@@ -121,7 +123,7 @@ static const struct ide_port_info jmicron_chipset __devinitdata = {
static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &jmicron_chipset);
+ return ide_pci_init_one(dev, &jmicron_chipset, NULL);
}
/* All JMB PATA controllers have and will continue to have the same
@@ -152,6 +154,7 @@ static struct pci_driver driver = {
.name = "JMicron IDE",
.id_table = jmicron_pci_tbl,
.probe = jmicron_init_one,
+ .remove = ide_pci_remove,
};
static int __init jmicron_ide_init(void)
@@ -159,7 +162,13 @@ static int __init jmicron_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit jmicron_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(jmicron_ide_init);
+module_exit(jmicron_ide_exit);
MODULE_AUTHOR("Alan Cox");
MODULE_DESCRIPTION("PCI driver module for the JMicron in legacy modes");
diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
index 45ba71a7182..ffefcd15196 100644
--- a/drivers/ide/pci/ns87415.c
+++ b/drivers/ide/pci/ns87415.c
@@ -19,6 +19,8 @@
#include <asm/io.h>
+#define DRV_NAME "ns87415"
+
#ifdef CONFIG_SUPERIO
/* SUPERIO 87560 is a PoS chip that NatSem denies exists.
* Unfortunately, it's built-in on all Astro-based PA-RISC workstations
@@ -28,10 +30,6 @@
*/
#include <asm/superio.h>
-static unsigned long superio_ide_status[2];
-static unsigned long superio_ide_select[2];
-static unsigned long superio_ide_dma_status[2];
-
#define SUPERIO_IDE_MAX_RETRIES 25
/* Because of a defect in Super I/O, all reads of the PCI DMA status
@@ -40,27 +38,28 @@ static unsigned long superio_ide_dma_status[2];
*/
static u8 superio_ide_inb (unsigned long port)
{
- if (port == superio_ide_status[0] ||
- port == superio_ide_status[1] ||
- port == superio_ide_select[0] ||
- port == superio_ide_select[1] ||
- port == superio_ide_dma_status[0] ||
- port == superio_ide_dma_status[1]) {
- u8 tmp;
- int retries = SUPERIO_IDE_MAX_RETRIES;
+ u8 tmp;
+ int retries = SUPERIO_IDE_MAX_RETRIES;
- /* printk(" [ reading port 0x%x with retry ] ", port); */
+ /* printk(" [ reading port 0x%x with retry ] ", port); */
- do {
- tmp = inb(port);
- if (tmp == 0)
- udelay(50);
- } while (tmp == 0 && retries-- > 0);
+ do {
+ tmp = inb(port);
+ if (tmp == 0)
+ udelay(50);
+ } while (tmp == 0 && retries-- > 0);
- return tmp;
- }
+ return tmp;
+}
- return inb(port);
+static u8 superio_read_status(ide_hwif_t *hwif)
+{
+ return superio_ide_inb(hwif->io_ports.status_addr);
+}
+
+static u8 superio_read_sff_dma_status(ide_hwif_t *hwif)
+{
+ return superio_ide_inb(hwif->dma_base + ATA_DMA_STATUS);
}
static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
@@ -78,6 +77,8 @@ static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
/* be sure we're looking at the low order bits */
outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+ tf->feature = inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
@@ -105,36 +106,32 @@ static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
}
}
-static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
-{
- struct pci_dev *pdev = to_pci_dev(hwif->dev);
- u32 base, dmabase;
- u8 port = hwif->channel, tmp;
-
- base = pci_resource_start(pdev, port * 2) & ~3;
- dmabase = pci_resource_start(pdev, 4) & ~3;
-
- superio_ide_status[port] = base + 7;
- superio_ide_select[port] = base + 6;
- superio_ide_dma_status[port] = dmabase + (!port ? 2 : 0xa);
+static const struct ide_tp_ops superio_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = superio_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = superio_read_sff_dma_status,
- /* Clear error/interrupt, enable dma */
- tmp = superio_ide_inb(superio_ide_dma_status[port]);
- outb(tmp | 0x66, superio_ide_dma_status[port]);
+ .set_irq = ide_set_irq,
- hwif->tf_read = superio_tf_read;
+ .tf_load = ide_tf_load,
+ .tf_read = superio_tf_read,
- /* We need to override inb to workaround a SuperIO errata */
- hwif->INB = superio_ide_inb;
-}
+ .input_data = ide_input_data,
+ .output_data = ide_output_data,
+};
-static void __devinit init_iops_ns87415(ide_hwif_t *hwif)
+static void __devinit superio_init_iops(struct hwif_s *hwif)
{
- struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ u32 dma_stat;
+ u8 port = hwif->channel, tmp;
- if (PCI_SLOT(dev->devfn) == 0xE)
- /* Built-in - assume it's under superio. */
- superio_ide_init_iops(hwif);
+ dma_stat = (pci_resource_start(pdev, 4) & ~3) + (!port ? 2 : 0xa);
+
+ /* Clear error/interrupt, enable dma */
+ tmp = superio_ide_inb(dma_stat);
+ outb(tmp | 0x66, dma_stat);
}
#endif
@@ -200,14 +197,14 @@ static int ns87415_dma_end(ide_drive_t *drive)
u8 dma_stat = 0, dma_cmd = 0;
drive->waiting_for_dma = 0;
- dma_stat = hwif->INB(hwif->dma_status);
- /* get dma command mode */
- dma_cmd = hwif->INB(hwif->dma_command);
+ dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+ /* get DMA command mode */
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
/* stop DMA */
- outb(dma_cmd & ~1, hwif->dma_command);
+ outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
/* from ERRATA: clear the INTR & ERROR bits */
- dma_cmd = hwif->INB(hwif->dma_command);
- outb(dma_cmd | 6, hwif->dma_command);
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+ outb(dma_cmd | 6, hwif->dma_base + ATA_DMA_CMD);
/* and free any DMA resources */
ide_destroy_dmatable(drive);
/* verify good DMA status */
@@ -276,7 +273,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
outb(8, hwif->io_ports.ctl_addr);
do {
udelay(50);
- stat = hwif->INB(hwif->io_ports.status_addr);
+ stat = hwif->tp_ops->read_status(hwif);
if (stat == 0xff)
break;
} while ((stat & BUSY_STAT) && --timeout);
@@ -291,7 +288,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
if (!hwif->dma_base)
return;
- outb(0x60, hwif->dma_status);
+ outb(0x60, hwif->dma_base + ATA_DMA_STATUS);
}
static const struct ide_port_ops ns87415_port_ops = {
@@ -310,10 +307,7 @@ static const struct ide_dma_ops ns87415_dma_ops = {
};
static const struct ide_port_info ns87415_chipset __devinitdata = {
- .name = "NS87415",
-#ifdef CONFIG_SUPERIO
- .init_iops = init_iops_ns87415,
-#endif
+ .name = DRV_NAME,
.init_hwif = init_hwif_ns87415,
.port_ops = &ns87415_port_ops,
.dma_ops = &ns87415_dma_ops,
@@ -323,7 +317,16 @@ static const struct ide_port_info ns87415_chipset __devinitdata = {
static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &ns87415_chipset);
+ struct ide_port_info d = ns87415_chipset;
+
+#ifdef CONFIG_SUPERIO
+ if (PCI_SLOT(dev->devfn) == 0xE) {
+ /* Built-in - assume it's under superio. */
+ d.init_iops = superio_init_iops;
+ d.tp_ops = &superio_tp_ops;
+ }
+#endif
+ return ide_pci_init_one(dev, &d, NULL);
}
static const struct pci_device_id ns87415_pci_tbl[] = {
@@ -336,6 +339,7 @@ static struct pci_driver driver = {
.name = "NS87415_IDE",
.id_table = ns87415_pci_tbl,
.probe = ns87415_init_one,
+ .remove = ide_pci_remove,
};
static int __init ns87415_ide_init(void)
@@ -343,7 +347,13 @@ static int __init ns87415_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit ns87415_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(ns87415_ide_init);
+module_exit(ns87415_ide_exit);
MODULE_AUTHOR("Mark Lord, Eddie Dost, Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for NS87415 IDE");
diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
index 725c80508d9..e28e672ddaf 100644
--- a/drivers/ide/pci/opti621.c
+++ b/drivers/ide/pci/opti621.c
@@ -90,6 +90,8 @@
#include <asm/io.h>
+#define DRV_NAME "opti621"
+
#define READ_REG 0 /* index of Read cycle timing register */
#define WRITE_REG 1 /* index of Write cycle timing register */
#define CNTRL_REG 3 /* index of Control register */
@@ -200,7 +202,7 @@ static const struct ide_port_ops opti621_port_ops = {
};
static const struct ide_port_info opti621_chipset __devinitdata = {
- .name = "OPTI621/X",
+ .name = DRV_NAME,
.enablebits = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
.port_ops = &opti621_port_ops,
.host_flags = IDE_HFLAG_NO_DMA,
@@ -209,7 +211,7 @@ static const struct ide_port_info opti621_chipset __devinitdata = {
static int __devinit opti621_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &opti621_chipset);
+ return ide_pci_init_one(dev, &opti621_chipset, NULL);
}
static const struct pci_device_id opti621_pci_tbl[] = {
@@ -223,6 +225,7 @@ static struct pci_driver driver = {
.name = "Opti621_IDE",
.id_table = opti621_pci_tbl,
.probe = opti621_init_one,
+ .remove = ide_pci_remove,
};
static int __init opti621_ide_init(void)
@@ -230,7 +233,13 @@ static int __init opti621_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit opti621_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(opti621_ide_init);
+module_exit(opti621_ide_exit);
MODULE_AUTHOR("Jaromir Koutek, Jan Harkes, Mark Lord");
MODULE_DESCRIPTION("PCI driver module for Opti621 IDE");
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 070df8ab3b2..998615fa285 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -31,6 +31,8 @@
#include <asm/pci-bridge.h>
#endif
+#define DRV_NAME "pdc202xx_new"
+
#undef DEBUG
#ifdef DEBUG
@@ -324,8 +326,9 @@ static void __devinit apple_kiwi_init(struct pci_dev *pdev)
}
#endif /* CONFIG_PPC_PMAC */
-static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev)
{
+ const char *name = DRV_NAME;
unsigned long dma_base = pci_resource_start(dev, 4);
unsigned long sec_dma_base = dma_base + 0x08;
long pll_input, pll_output, ratio;
@@ -358,12 +361,13 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
* registers setting.
*/
pll_input = detect_pll_input_clock(dma_base);
- printk("%s: PLL input clock is %ld kHz\n", name, pll_input / 1000);
+ printk(KERN_INFO "%s %s: PLL input clock is %ld kHz\n",
+ name, pci_name(dev), pll_input / 1000);
/* Sanity check */
if (unlikely(pll_input < 5000000L || pll_input > 70000000L)) {
- printk(KERN_ERR "%s: Bad PLL input clock %ld Hz, giving up!\n",
- name, pll_input);
+ printk(KERN_ERR "%s %s: Bad PLL input clock %ld Hz, giving up!"
+ "\n", name, pci_name(dev), pll_input);
goto out;
}
@@ -399,7 +403,8 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
r = 0x00;
} else {
/* Invalid ratio */
- printk(KERN_ERR "%s: Bad ratio %ld, giving up!\n", name, ratio);
+ printk(KERN_ERR "%s %s: Bad ratio %ld, giving up!\n",
+ name, pci_name(dev), ratio);
goto out;
}
@@ -409,7 +414,8 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
if (unlikely(f < 0 || f > 127)) {
/* Invalid F */
- printk(KERN_ERR "%s: F[%d] invalid!\n", name, f);
+ printk(KERN_ERR "%s %s: F[%d] invalid!\n",
+ name, pci_name(dev), f);
goto out;
}
@@ -455,8 +461,8 @@ static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
if (dev2->irq != dev->irq) {
dev2->irq = dev->irq;
- printk(KERN_INFO "PDC20270: PCI config space "
- "interrupt fixed\n");
+ printk(KERN_INFO DRV_NAME " %s: PCI config space "
+ "interrupt fixed\n", pci_name(dev));
}
return dev2;
@@ -473,9 +479,9 @@ static const struct ide_port_ops pdcnew_port_ops = {
.cable_detect = pdcnew_cable_detect,
};
-#define DECLARE_PDCNEW_DEV(name_str, udma) \
+#define DECLARE_PDCNEW_DEV(udma) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.init_chipset = init_chipset_pdcnew, \
.port_ops = &pdcnew_port_ops, \
.host_flags = IDE_HFLAG_POST_SET_MODE | \
@@ -487,13 +493,8 @@ static const struct ide_port_ops pdcnew_port_ops = {
}
static const struct ide_port_info pdcnew_chipsets[] __devinitdata = {
- /* 0 */ DECLARE_PDCNEW_DEV("PDC20268", ATA_UDMA5),
- /* 1 */ DECLARE_PDCNEW_DEV("PDC20269", ATA_UDMA6),
- /* 2 */ DECLARE_PDCNEW_DEV("PDC20270", ATA_UDMA5),
- /* 3 */ DECLARE_PDCNEW_DEV("PDC20271", ATA_UDMA6),
- /* 4 */ DECLARE_PDCNEW_DEV("PDC20275", ATA_UDMA6),
- /* 5 */ DECLARE_PDCNEW_DEV("PDC20276", ATA_UDMA6),
- /* 6 */ DECLARE_PDCNEW_DEV("PDC20277", ATA_UDMA6),
+ /* 0: PDC202{68,70} */ DECLARE_PDCNEW_DEV(ATA_UDMA5),
+ /* 1: PDC202{69,71,75,76,77} */ DECLARE_PDCNEW_DEV(ATA_UDMA6),
};
/**
@@ -507,13 +508,10 @@ static const struct ide_port_info pdcnew_chipsets[] __devinitdata = {
static int __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- const struct ide_port_info *d;
+ const struct ide_port_info *d = &pdcnew_chipsets[id->driver_data];
struct pci_dev *bridge = dev->bus->self;
- u8 idx = id->driver_data;
-
- d = &pdcnew_chipsets[idx];
- if (idx == 2 && bridge &&
+ if (dev->device == PCI_DEVICE_ID_PROMISE_20270 && bridge &&
bridge->vendor == PCI_VENDOR_ID_DEC &&
bridge->device == PCI_DEVICE_ID_DEC_21150) {
struct pci_dev *dev2;
@@ -524,33 +522,42 @@ static int __devinit pdc202new_init_one(struct pci_dev *dev, const struct pci_de
dev2 = pdc20270_get_dev2(dev);
if (dev2) {
- int ret = ide_setup_pci_devices(dev, dev2, d);
+ int ret = ide_pci_init_two(dev, dev2, d, NULL);
if (ret < 0)
pci_dev_put(dev2);
return ret;
}
}
- if (idx == 5 && bridge &&
+ if (dev->device == PCI_DEVICE_ID_PROMISE_20276 && bridge &&
bridge->vendor == PCI_VENDOR_ID_INTEL &&
(bridge->device == PCI_DEVICE_ID_INTEL_I960 ||
bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) {
- printk(KERN_INFO "PDC20276: attached to I2O RAID controller, "
- "skipping\n");
+ printk(KERN_INFO DRV_NAME " %s: attached to I2O RAID controller,"
+ " skipping\n", pci_name(dev));
return -ENODEV;
}
- return ide_setup_pci_device(dev, d);
+ return ide_pci_init_one(dev, d, NULL);
+}
+
+static void __devexit pdc202new_remove(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
+
+ ide_pci_remove(dev);
+ pci_dev_put(dev2);
}
static const struct pci_device_id pdc202new_pci_tbl[] = {
{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20268), 0 },
{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20269), 1 },
- { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20270), 2 },
- { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20271), 3 },
- { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20275), 4 },
- { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20276), 5 },
- { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20277), 6 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20270), 0 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20271), 1 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20275), 1 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20276), 1 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20277), 1 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl);
@@ -559,6 +566,7 @@ static struct pci_driver driver = {
.name = "Promise_IDE",
.id_table = pdc202new_pci_tbl,
.probe = pdc202new_init_one,
+ .remove = pdc202new_remove,
};
static int __init pdc202new_ide_init(void)
@@ -566,7 +574,13 @@ static int __init pdc202new_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit pdc202new_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(pdc202new_ide_init);
+module_exit(pdc202new_ide_exit);
MODULE_AUTHOR("Andre Hedrick, Frank Tiernan");
MODULE_DESCRIPTION("PCI driver module for Promise PDC20268 and higher");
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index fca89eda5c0..6ff2def58da 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -20,6 +20,8 @@
#include <asm/io.h>
+#define DRV_NAME "pdc202xx_old"
+
#define PDC202XX_DEBUG_DRIVE_INFO 0
static const char *pdc_quirk_drives[] = {
@@ -206,7 +208,7 @@ static int pdc202xx_dma_test_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned long high_16 = hwif->extra_base - 16;
- u8 dma_stat = inb(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
u8 sc1d = inb(high_16 + 0x001d);
if (hwif->channel) {
@@ -263,8 +265,7 @@ static void pdc202xx_dma_timeout(ide_drive_t *drive)
ide_dma_timeout(drive);
}
-static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev,
- const char *name)
+static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev)
{
unsigned long dmabase = pci_resource_start(dev, 4);
u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0;
@@ -304,15 +305,14 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
if (irq != irq2) {
pci_write_config_byte(dev,
(PCI_INTERRUPT_LINE)|0x80, irq); /* 0xbc */
- printk(KERN_INFO "%s: PCI config space interrupt "
- "mirror fixed\n", name);
+ printk(KERN_INFO "%s %s: PCI config space interrupt "
+ "mirror fixed\n", name, pci_name(dev));
}
}
}
#define IDE_HFLAGS_PDC202XX \
(IDE_HFLAG_ERROR_STOPS_FIFO | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
IDE_HFLAG_OFF_BOARD)
static const struct ide_port_ops pdc20246_port_ops = {
@@ -351,9 +351,9 @@ static const struct ide_dma_ops pdc2026x_dma_ops = {
.dma_timeout = pdc202xx_dma_timeout,
};
-#define DECLARE_PDC2026X_DEV(name_str, udma, extra_flags) \
+#define DECLARE_PDC2026X_DEV(udma, extra_flags) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.init_chipset = init_chipset_pdc202xx, \
.port_ops = &pdc2026x_port_ops, \
.dma_ops = &pdc2026x_dma_ops, \
@@ -364,8 +364,8 @@ static const struct ide_dma_ops pdc2026x_dma_ops = {
}
static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
- { /* 0 */
- .name = "PDC20246",
+ { /* 0: PDC20246 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_pdc202xx,
.port_ops = &pdc20246_port_ops,
.dma_ops = &pdc20246_dma_ops,
@@ -375,10 +375,10 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
.udma_mask = ATA_UDMA2,
},
- /* 1 */ DECLARE_PDC2026X_DEV("PDC20262", ATA_UDMA4, 0),
- /* 2 */ DECLARE_PDC2026X_DEV("PDC20263", ATA_UDMA4, 0),
- /* 3 */ DECLARE_PDC2026X_DEV("PDC20265", ATA_UDMA5, IDE_HFLAG_RQSIZE_256),
- /* 4 */ DECLARE_PDC2026X_DEV("PDC20267", ATA_UDMA5, IDE_HFLAG_RQSIZE_256),
+ /* 1: PDC2026{2,3} */
+ DECLARE_PDC2026X_DEV(ATA_UDMA4, 0),
+ /* 2: PDC2026{5,7} */
+ DECLARE_PDC2026X_DEV(ATA_UDMA5, IDE_HFLAG_RQSIZE_256),
};
/**
@@ -397,31 +397,32 @@ static int __devinit pdc202xx_init_one(struct pci_dev *dev, const struct pci_dev
d = &pdc202xx_chipsets[idx];
- if (idx < 3)
+ if (idx < 2)
pdc202ata4_fixup_irq(dev, d->name);
- if (idx == 3) {
+ if (dev->vendor == PCI_DEVICE_ID_PROMISE_20265) {
struct pci_dev *bridge = dev->bus->self;
if (bridge &&
bridge->vendor == PCI_VENDOR_ID_INTEL &&
(bridge->device == PCI_DEVICE_ID_INTEL_I960 ||
bridge->device == PCI_DEVICE_ID_INTEL_I960RM)) {
- printk(KERN_INFO "ide: Skipping Promise PDC20265 "
- "attached to I2O RAID controller\n");
+ printk(KERN_INFO DRV_NAME " %s: skipping Promise "
+ "PDC20265 attached to I2O RAID controller\n",
+ pci_name(dev));
return -ENODEV;
}
}
- return ide_setup_pci_device(dev, d);
+ return ide_pci_init_one(dev, d, NULL);
}
static const struct pci_device_id pdc202xx_pci_tbl[] = {
{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0 },
{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1 },
- { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 2 },
- { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20265), 3 },
- { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20267), 4 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 1 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20265), 2 },
+ { PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20267), 2 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl);
@@ -430,6 +431,7 @@ static struct pci_driver driver = {
.name = "Promise_Old_IDE",
.id_table = pdc202xx_pci_tbl,
.probe = pdc202xx_init_one,
+ .remove = ide_pci_remove,
};
static int __init pdc202xx_ide_init(void)
@@ -437,7 +439,13 @@ static int __init pdc202xx_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit pdc202xx_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(pdc202xx_ide_init);
+module_exit(pdc202xx_ide_exit);
MODULE_AUTHOR("Andre Hedrick, Frank Tiernan");
MODULE_DESCRIPTION("PCI driver module for older Promise IDE");
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index f04738d14a6..7fc3022dcf6 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -54,6 +54,8 @@
#include <asm/io.h>
+#define DRV_NAME "piix"
+
static int no_piix_dma;
/**
@@ -198,13 +200,12 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
/**
* init_chipset_ich - set up the ICH chipset
* @dev: PCI device to set up
- * @name: Name of the device
*
* Initialize the PCI device as required. For the ICH this turns
* out to be nice and simple.
*/
-static unsigned int __devinit init_chipset_ich(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_ich(struct pci_dev *dev)
{
u32 extra = 0;
@@ -227,9 +228,9 @@ static void piix_dma_clear_irq(ide_drive_t *drive)
u8 dma_stat;
/* clear the INTR & ERROR bits */
- dma_stat = inb(hwif->dma_status);
+ dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
/* Should we force the bit as well ? */
- outb(dma_stat, hwif->dma_status);
+ outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
}
struct ich_laptop {
@@ -314,9 +315,9 @@ static const struct ide_port_ops piix_port_ops = {
#define IDE_HFLAGS_PIIX 0
#endif
-#define DECLARE_PIIX_DEV(name_str, udma) \
+#define DECLARE_PIIX_DEV(udma) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.init_hwif = init_hwif_piix, \
.enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
.port_ops = &piix_port_ops, \
@@ -327,9 +328,9 @@ static const struct ide_port_ops piix_port_ops = {
.udma_mask = udma, \
}
-#define DECLARE_ICH_DEV(name_str, udma) \
+#define DECLARE_ICH_DEV(udma) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.init_chipset = init_chipset_ich, \
.init_hwif = init_hwif_ich, \
.enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
@@ -342,45 +343,31 @@ static const struct ide_port_ops piix_port_ops = {
}
static const struct ide_port_info piix_pci_info[] __devinitdata = {
- /* 0 */ DECLARE_PIIX_DEV("PIIXa", 0x00), /* no udma */
- /* 1 */ DECLARE_PIIX_DEV("PIIXb", 0x00), /* no udma */
-
- /* 2 */
+ /* 0: MPIIX */
{ /*
* MPIIX actually has only a single IDE channel mapped to
* the primary or secondary ports depending on the value
* of the bit 14 of the IDETIM register at offset 0x6c
*/
- .name = "MPIIX",
+ .name = DRV_NAME,
.enablebits = {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}},
.host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA |
IDE_HFLAGS_PIIX,
.pio_mask = ATA_PIO4,
/* This is a painful system best to let it self tune for now */
},
-
- /* 3 */ DECLARE_PIIX_DEV("PIIX3", 0x00), /* no udma */
- /* 4 */ DECLARE_PIIX_DEV("PIIX4", ATA_UDMA2),
- /* 5 */ DECLARE_ICH_DEV("ICH0", ATA_UDMA2),
- /* 6 */ DECLARE_PIIX_DEV("PIIX4", ATA_UDMA2),
- /* 7 */ DECLARE_ICH_DEV("ICH", ATA_UDMA4),
- /* 8 */ DECLARE_PIIX_DEV("PIIX4", ATA_UDMA4),
- /* 9 */ DECLARE_PIIX_DEV("PIIX4", ATA_UDMA2),
- /* 10 */ DECLARE_ICH_DEV("ICH2", ATA_UDMA5),
- /* 11 */ DECLARE_ICH_DEV("ICH2M", ATA_UDMA5),
- /* 12 */ DECLARE_ICH_DEV("ICH3M", ATA_UDMA5),
- /* 13 */ DECLARE_ICH_DEV("ICH3", ATA_UDMA5),
- /* 14 */ DECLARE_ICH_DEV("ICH4", ATA_UDMA5),
- /* 15 */ DECLARE_ICH_DEV("ICH5", ATA_UDMA5),
- /* 16 */ DECLARE_ICH_DEV("C-ICH", ATA_UDMA5),
- /* 17 */ DECLARE_ICH_DEV("ICH4", ATA_UDMA5),
- /* 18 */ DECLARE_ICH_DEV("ICH5-SATA", ATA_UDMA5),
- /* 19 */ DECLARE_ICH_DEV("ICH5", ATA_UDMA5),
- /* 20 */ DECLARE_ICH_DEV("ICH6", ATA_UDMA5),
- /* 21 */ DECLARE_ICH_DEV("ICH7", ATA_UDMA5),
- /* 22 */ DECLARE_ICH_DEV("ICH4", ATA_UDMA5),
- /* 23 */ DECLARE_ICH_DEV("ESB2", ATA_UDMA5),
- /* 24 */ DECLARE_ICH_DEV("ICH8M", ATA_UDMA5),
+ /* 1: PIIXa/PIIXb/PIIX3 */
+ DECLARE_PIIX_DEV(0x00), /* no udma */
+ /* 2: PIIX4 */
+ DECLARE_PIIX_DEV(ATA_UDMA2),
+ /* 3: ICH0 */
+ DECLARE_ICH_DEV(ATA_UDMA2),
+ /* 4: ICH */
+ DECLARE_ICH_DEV(ATA_UDMA4),
+ /* 5: PIIX4 */
+ DECLARE_PIIX_DEV(ATA_UDMA4),
+ /* 6: ICH[2-7]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */
+ DECLARE_ICH_DEV(ATA_UDMA5),
};
/**
@@ -394,7 +381,7 @@ static const struct ide_port_info piix_pci_info[] __devinitdata = {
static int __devinit piix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &piix_pci_info[id->driver_data]);
+ return ide_pci_init_one(dev, &piix_pci_info[id->driver_data], NULL);
}
/**
@@ -421,39 +408,39 @@ static void __devinit piix_check_450nx(void)
no_piix_dma = 2;
}
if(no_piix_dma)
- printk(KERN_WARNING "piix: 450NX errata present, disabling IDE DMA.\n");
+ printk(KERN_WARNING DRV_NAME ": 450NX errata present, disabling IDE DMA.\n");
if(no_piix_dma == 2)
- printk(KERN_WARNING "piix: A BIOS update may resolve this.\n");
+ printk(KERN_WARNING DRV_NAME ": A BIOS update may resolve this.\n");
}
static const struct pci_device_id piix_pci_tbl[] = {
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_0), 0 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_1), 1 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371MX), 2 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371SB_1), 3 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371AB), 4 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AB_1), 5 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82443MX_1), 6 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AA_1), 7 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82372FB_1), 8 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82451NX), 9 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_9), 10 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_8), 11 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_10), 12 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_11), 13 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_11), 14 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_11), 15 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801E_11), 16 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_10), 17 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_0), 1 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371FB_1), 1 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371MX), 0 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371SB_1), 1 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82371AB), 2 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AB_1), 3 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82443MX_1), 2 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801AA_1), 4 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82372FB_1), 5 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82451NX), 2 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_9), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801BA_8), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_10), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801CA_11), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_11), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_11), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801E_11), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_10), 6 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_1), 18 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801EB_1), 6 },
#endif
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2), 19 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19), 20 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21), 21 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1), 22 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18), 23 },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6), 24 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18), 6 },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6), 6 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
@@ -462,6 +449,7 @@ static struct pci_driver driver = {
.name = "PIIX_IDE",
.id_table = piix_pci_tbl,
.probe = piix_init_one,
+ .remove = ide_pci_remove,
};
static int __init piix_ide_init(void)
@@ -470,7 +458,13 @@ static int __init piix_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit piix_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(piix_ide_init);
+module_exit(piix_ide_exit);
MODULE_AUTHOR("Andre Hedrick, Andrzej Krzysztofowicz");
MODULE_DESCRIPTION("PCI driver module for Intel PIIX IDE");
diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c
index 532154adba2..8d11ee838a2 100644
--- a/drivers/ide/pci/rz1000.c
+++ b/drivers/ide/pci/rz1000.c
@@ -21,6 +21,8 @@
#include <linux/ide.h>
#include <linux/init.h>
+#define DRV_NAME "rz1000"
+
static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
@@ -40,7 +42,7 @@ static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
}
static const struct ide_port_info rz1000_chipset __devinitdata = {
- .name = "RZ100x",
+ .name = DRV_NAME,
.init_hwif = init_hwif_rz1000,
.chipset = ide_rz1000,
.host_flags = IDE_HFLAG_NO_DMA,
@@ -48,7 +50,7 @@ static const struct ide_port_info rz1000_chipset __devinitdata = {
static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &rz1000_chipset);
+ return ide_pci_init_one(dev, &rz1000_chipset, NULL);
}
static const struct pci_device_id rz1000_pci_tbl[] = {
@@ -62,6 +64,7 @@ static struct pci_driver driver = {
.name = "RZ1000_IDE",
.id_table = rz1000_pci_tbl,
.probe = rz1000_init_one,
+ .remove = ide_pci_remove,
};
static int __init rz1000_ide_init(void)
@@ -69,7 +72,13 @@ static int __init rz1000_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit rz1000_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(rz1000_ide_init);
+module_exit(rz1000_ide_exit);
MODULE_AUTHOR("Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for RZ1000 IDE");
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index 14c787b5d95..8efaed16fea 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -22,6 +22,8 @@
#include <asm/io.h>
+#define DRV_NAME "sc1200"
+
#define SC1200_REV_A 0x00
#define SC1200_REV_B1 0x01
#define SC1200_REV_B3 0x02
@@ -234,21 +236,11 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
* we only save state when going from full power to less
*/
if (state.event == PM_EVENT_ON) {
- struct sc1200_saved_state *ss;
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct sc1200_saved_state *ss = host->host_priv;
unsigned int r;
/*
- * allocate a permanent save area, if not already allocated
- */
- ss = (struct sc1200_saved_state *)pci_get_drvdata(dev);
- if (ss == NULL) {
- ss = kmalloc(sizeof(*ss), GFP_KERNEL);
- if (ss == NULL)
- return -ENOMEM;
- pci_set_drvdata(dev, ss);
- }
-
- /*
* save timing registers
* (this may be unnecessary if BIOS also does it)
*/
@@ -263,7 +255,8 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
static int sc1200_resume (struct pci_dev *dev)
{
- struct sc1200_saved_state *ss;
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct sc1200_saved_state *ss = host->host_priv;
unsigned int r;
int i;
@@ -271,16 +264,12 @@ static int sc1200_resume (struct pci_dev *dev)
if (i)
return i;
- ss = (struct sc1200_saved_state *)pci_get_drvdata(dev);
-
/*
* restore timing registers
* (this may be unnecessary if BIOS also does it)
*/
- if (ss) {
- for (r = 0; r < 8; r++)
- pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]);
- }
+ for (r = 0; r < 8; r++)
+ pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]);
return 0;
}
@@ -304,7 +293,7 @@ static const struct ide_dma_ops sc1200_dma_ops = {
};
static const struct ide_port_info sc1200_chipset __devinitdata = {
- .name = "SC1200",
+ .name = DRV_NAME,
.port_ops = &sc1200_port_ops,
.dma_ops = &sc1200_dma_ops,
.host_flags = IDE_HFLAG_SERIALIZE |
@@ -317,7 +306,19 @@ static const struct ide_port_info sc1200_chipset __devinitdata = {
static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &sc1200_chipset);
+ struct sc1200_saved_state *ss = NULL;
+ int rc;
+
+#ifdef CONFIG_PM
+ ss = kmalloc(sizeof(*ss), GFP_KERNEL);
+ if (ss == NULL)
+ return -ENOMEM;
+#endif
+ rc = ide_pci_init_one(dev, &sc1200_chipset, ss);
+ if (rc)
+ kfree(ss);
+
+ return rc;
}
static const struct pci_device_id sc1200_pci_tbl[] = {
@@ -330,6 +331,7 @@ static struct pci_driver driver = {
.name = "SC1200_IDE",
.id_table = sc1200_pci_tbl,
.probe = sc1200_init_one,
+ .remove = ide_pci_remove,
#ifdef CONFIG_PM
.suspend = sc1200_suspend,
.resume = sc1200_resume,
@@ -341,7 +343,13 @@ static int __init sc1200_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit sc1200_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(sc1200_ide_init);
+module_exit(sc1200_ide_exit);
MODULE_AUTHOR("Mark Lord");
MODULE_DESCRIPTION("PCI driver module for NS SC1200 IDE");
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
index 789c66dfbde..94a7ab86423 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
@@ -65,7 +65,7 @@
static struct scc_ports {
unsigned long ctl, dma;
- ide_hwif_t *hwif; /* for removing port from system */
+ struct ide_host *host; /* for removing port from system */
} scc_ports[MAX_HWIFS];
/* PIO transfer mode table */
@@ -126,6 +126,46 @@ static u8 scc_ide_inb(unsigned long port)
return (u8)data;
}
+static void scc_exec_command(ide_hwif_t *hwif, u8 cmd)
+{
+ out_be32((void *)hwif->io_ports.command_addr, cmd);
+ eieio();
+ in_be32((void *)(hwif->dma_base + 0x01c));
+ eieio();
+}
+
+static u8 scc_read_status(ide_hwif_t *hwif)
+{
+ return (u8)in_be32((void *)hwif->io_ports.status_addr);
+}
+
+static u8 scc_read_altstatus(ide_hwif_t *hwif)
+{
+ return (u8)in_be32((void *)hwif->io_ports.ctl_addr);
+}
+
+static u8 scc_read_sff_dma_status(ide_hwif_t *hwif)
+{
+ return (u8)in_be32((void *)(hwif->dma_base + 4));
+}
+
+static void scc_set_irq(ide_hwif_t *hwif, int on)
+{
+ u8 ctl = ATA_DEVCTL_OBS;
+
+ if (on == 4) { /* hack for SRST */
+ ctl |= 4;
+ on &= ~4;
+ }
+
+ ctl |= on ? 0 : 2;
+
+ out_be32((void *)hwif->io_ports.ctl_addr, ctl);
+ eieio();
+ in_be32((void *)(hwif->dma_base + 0x01c));
+ eieio();
+}
+
static void scc_ide_insw(unsigned long port, void *addr, u32 count)
{
u16 *ptr = (u16 *)addr;
@@ -148,14 +188,6 @@ static void scc_ide_outb(u8 addr, unsigned long port)
out_be32((void*)port, addr);
}
-static void scc_ide_outbsync(ide_hwif_t *hwif, u8 addr, unsigned long port)
-{
- out_be32((void*)port, addr);
- eieio();
- in_be32((void*)(hwif->dma_base + 0x01c));
- eieio();
-}
-
static void
scc_ide_outsw(unsigned long port, void *addr, u32 count)
{
@@ -261,14 +293,14 @@ static void scc_dma_host_set(ide_drive_t *drive, int on)
{
ide_hwif_t *hwif = drive->hwif;
u8 unit = (drive->select.b.unit & 0x01);
- u8 dma_stat = scc_ide_inb(hwif->dma_status);
+ u8 dma_stat = scc_ide_inb(hwif->dma_base + 4);
if (on)
dma_stat |= (1 << (5 + unit));
else
dma_stat &= ~(1 << (5 + unit));
- scc_ide_outb(dma_stat, hwif->dma_status);
+ scc_ide_outb(dma_stat, hwif->dma_base + 4);
}
/**
@@ -304,13 +336,13 @@ static int scc_dma_setup(ide_drive_t *drive)
out_be32((void __iomem *)(hwif->dma_base + 8), hwif->dmatable_dma);
/* specify r/w */
- out_be32((void __iomem *)hwif->dma_command, reading);
+ out_be32((void __iomem *)hwif->dma_base, reading);
- /* read dma_status for INTR & ERROR flags */
- dma_stat = in_be32((void __iomem *)hwif->dma_status);
+ /* read DMA status for INTR & ERROR flags */
+ dma_stat = in_be32((void __iomem *)(hwif->dma_base + 4));
/* clear INTR & ERROR flags */
- out_be32((void __iomem *)hwif->dma_status, dma_stat|6);
+ out_be32((void __iomem *)(hwif->dma_base + 4), dma_stat | 6);
drive->waiting_for_dma = 1;
return 0;
}
@@ -318,10 +350,10 @@ static int scc_dma_setup(ide_drive_t *drive)
static void scc_dma_start(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- u8 dma_cmd = scc_ide_inb(hwif->dma_command);
+ u8 dma_cmd = scc_ide_inb(hwif->dma_base);
/* start DMA */
- scc_ide_outb(dma_cmd | 1, hwif->dma_command);
+ scc_ide_outb(dma_cmd | 1, hwif->dma_base);
hwif->dma = 1;
wmb();
}
@@ -333,13 +365,13 @@ static int __scc_dma_end(ide_drive_t *drive)
drive->waiting_for_dma = 0;
/* get DMA command mode */
- dma_cmd = scc_ide_inb(hwif->dma_command);
+ dma_cmd = scc_ide_inb(hwif->dma_base);
/* stop DMA */
- scc_ide_outb(dma_cmd & ~1, hwif->dma_command);
+ scc_ide_outb(dma_cmd & ~1, hwif->dma_base);
/* get DMA status */
- dma_stat = scc_ide_inb(hwif->dma_status);
+ dma_stat = scc_ide_inb(hwif->dma_base + 4);
/* clear the INTR & ERROR bits */
- scc_ide_outb(dma_stat | 6, hwif->dma_status);
+ scc_ide_outb(dma_stat | 6, hwif->dma_base + 4);
/* purge DMA mappings */
ide_destroy_dmatable(drive);
/* verify good DMA status */
@@ -359,6 +391,7 @@ static int __scc_dma_end(ide_drive_t *drive)
static int scc_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
+ void __iomem *dma_base = (void __iomem *)hwif->dma_base;
unsigned long intsts_port = hwif->dma_base + 0x014;
u32 reg;
int dma_stat, data_loss = 0;
@@ -397,7 +430,7 @@ static int scc_dma_end(ide_drive_t *drive)
printk(KERN_WARNING "%s: SERROR\n", SCC_PATA_NAME);
out_be32((void __iomem *)intsts_port, INTSTS_SERROR|INTSTS_BMSINT);
- out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+ out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
continue;
}
@@ -412,7 +445,7 @@ static int scc_dma_end(ide_drive_t *drive)
out_be32((void __iomem *)intsts_port, INTSTS_PRERR|INTSTS_BMSINT);
- out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+ out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
continue;
}
@@ -420,12 +453,12 @@ static int scc_dma_end(ide_drive_t *drive)
printk(KERN_WARNING "%s: Response Error\n", SCC_PATA_NAME);
out_be32((void __iomem *)intsts_port, INTSTS_RERR|INTSTS_BMSINT);
- out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+ out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
continue;
}
if (reg & INTSTS_ICERR) {
- out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+ out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
printk(KERN_WARNING "%s: Illegal Configuration\n", SCC_PATA_NAME);
out_be32((void __iomem *)intsts_port, INTSTS_ICERR|INTSTS_BMSINT);
@@ -553,14 +586,9 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev,
const struct ide_port_info *d)
{
struct scc_ports *ports = pci_get_drvdata(dev);
- ide_hwif_t *hwif = NULL;
- hw_regs_t hw;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- int i;
-
- hwif = ide_find_port_slot(d);
- if (hwif == NULL)
- return -ENOMEM;
+ struct ide_host *host;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+ int i, rc;
memset(&hw, 0, sizeof(hw));
for (i = 0; i <= 8; i++)
@@ -568,11 +596,12 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev,
hw.irq = dev->irq;
hw.dev = &dev->dev;
hw.chipset = ide_pci;
- ide_init_port_hw(hwif, &hw);
- idx[0] = hwif->index;
+ rc = ide_host_add(d, hws, &host);
+ if (rc)
+ return rc;
- ide_device_add(idx, d);
+ ports->host = host;
return 0;
}
@@ -701,6 +730,8 @@ static void scc_tf_read(ide_drive_t *drive, ide_task_t *task)
/* be sure we're looking at the low order bits */
scc_ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+ tf->feature = scc_ide_inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = scc_ide_inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
@@ -774,16 +805,6 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
ide_set_hwifdata(hwif, ports);
- hwif->tf_load = scc_tf_load;
- hwif->tf_read = scc_tf_read;
-
- hwif->input_data = scc_input_data;
- hwif->output_data = scc_output_data;
-
- hwif->INB = scc_ide_inb;
- hwif->OUTB = scc_ide_outb;
- hwif->OUTBSYNC = scc_ide_outbsync;
-
hwif->dma_base = dma_base;
hwif->config_data = ports->ctl;
}
@@ -824,11 +845,6 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
{
struct scc_ports *ports = ide_get_hwifdata(hwif);
- ports->hwif = hwif;
-
- hwif->dma_command = hwif->dma_base;
- hwif->dma_status = hwif->dma_base + 0x04;
-
/* PTERADD */
out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma);
@@ -838,6 +854,21 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
hwif->ultra_mask = ATA_UDMA5; /* 100MHz */
}
+static const struct ide_tp_ops scc_tp_ops = {
+ .exec_command = scc_exec_command,
+ .read_status = scc_read_status,
+ .read_altstatus = scc_read_altstatus,
+ .read_sff_dma_status = scc_read_sff_dma_status,
+
+ .set_irq = scc_set_irq,
+
+ .tf_load = scc_tf_load,
+ .tf_read = scc_tf_read,
+
+ .input_data = scc_input_data,
+ .output_data = scc_output_data,
+};
+
static const struct ide_port_ops scc_port_ops = {
.set_pio_mode = scc_set_pio_mode,
.set_dma_mode = scc_set_dma_mode,
@@ -861,6 +892,7 @@ static const struct ide_dma_ops scc_dma_ops = {
.name = name_str, \
.init_iops = init_iops_scc, \
.init_hwif = init_hwif_scc, \
+ .tp_ops = &scc_tp_ops, \
.port_ops = &scc_port_ops, \
.dma_ops = &scc_dma_ops, \
.host_flags = IDE_HFLAG_SINGLE, \
@@ -895,7 +927,8 @@ static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_i
static void __devexit scc_remove(struct pci_dev *dev)
{
struct scc_ports *ports = pci_get_drvdata(dev);
- ide_hwif_t *hwif = ports->hwif;
+ struct ide_host *host = ports->host;
+ ide_hwif_t *hwif = host->ports[0];
if (hwif->dmatable_cpu) {
pci_free_consistent(dev, PRD_ENTRIES * PRD_BYTES,
@@ -903,7 +936,7 @@ static void __devexit scc_remove(struct pci_dev *dev)
hwif->dmatable_cpu = NULL;
}
- ide_unregister(hwif);
+ ide_host_remove(host);
iounmap((void*)ports->dma);
iounmap((void*)ports->ctl);
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index a1fb20826a5..d173f293772 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -38,6 +38,8 @@
#include <asm/io.h>
+#define DRV_NAME "serverworks"
+
#define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
#define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
@@ -172,7 +174,7 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
pci_write_config_byte(dev, 0x54, ultra_enable);
}
-static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_svwks(struct pci_dev *dev)
{
unsigned int reg;
u8 btr;
@@ -188,7 +190,8 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
pci_read_config_dword(isa_dev, 0x64, &reg);
reg &= ~0x00002000; /* disable 600ns interrupt mask */
if(!(reg & 0x00004000))
- printk(KERN_DEBUG "%s: UDMA not BIOS enabled.\n", name);
+ printk(KERN_DEBUG DRV_NAME " %s: UDMA not BIOS "
+ "enabled.\n", pci_name(dev));
reg |= 0x00004000; /* enable UDMA/33 support */
pci_write_config_dword(isa_dev, 0x64, reg);
}
@@ -349,45 +352,47 @@ static const struct ide_port_ops svwks_port_ops = {
.cable_detect = svwks_cable_detect,
};
-#define IDE_HFLAGS_SVWKS \
- (IDE_HFLAG_LEGACY_IRQS | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE)
+#define IDE_HFLAGS_SVWKS IDE_HFLAG_LEGACY_IRQS
static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
- { /* 0 */
- .name = "SvrWks OSB4",
+ { /* 0: OSB4 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_svwks,
.port_ops = &osb4_port_ops,
.host_flags = IDE_HFLAGS_SVWKS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = 0x00, /* UDMA is problematic on OSB4 */
- },{ /* 1 */
- .name = "SvrWks CSB5",
+ },
+ { /* 1: CSB5 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_svwks,
.port_ops = &svwks_port_ops,
.host_flags = IDE_HFLAGS_SVWKS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
- },{ /* 2 */
- .name = "SvrWks CSB6",
+ },
+ { /* 2: CSB6 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_svwks,
.port_ops = &svwks_port_ops,
.host_flags = IDE_HFLAGS_SVWKS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
- },{ /* 3 */
- .name = "SvrWks CSB6",
+ },
+ { /* 3: CSB6-2 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_svwks,
.port_ops = &svwks_port_ops,
.host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
- },{ /* 4 */
- .name = "SvrWks HT1000",
+ },
+ { /* 4: HT1000 */
+ .name = DRV_NAME,
.init_chipset = init_chipset_svwks,
.port_ops = &svwks_port_ops,
.host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
@@ -424,7 +429,7 @@ static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device
d.host_flags &= ~IDE_HFLAG_SINGLE;
}
- return ide_setup_pci_device(dev, &d);
+ return ide_pci_init_one(dev, &d, NULL);
}
static const struct pci_device_id svwks_pci_tbl[] = {
@@ -441,6 +446,7 @@ static struct pci_driver driver = {
.name = "Serverworks_IDE",
.id_table = svwks_pci_tbl,
.probe = svwks_init_one,
+ .remove = ide_pci_remove,
};
static int __init svwks_ide_init(void)
@@ -448,7 +454,13 @@ static int __init svwks_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit svwks_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(svwks_ide_init);
+module_exit(svwks_ide_exit);
MODULE_AUTHOR("Michael Aubry. Andrzej Krzysztofowicz, Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for Serverworks OSB4/CSB5/CSB6 IDE");
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index c79ff5b4108..42eef19a18f 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -127,7 +127,7 @@ sgiioc4_checkirq(ide_hwif_t * hwif)
return 0;
}
-static u8 sgiioc4_INB(unsigned long);
+static u8 sgiioc4_read_status(ide_hwif_t *);
static int
sgiioc4_clearirq(ide_drive_t * drive)
@@ -141,18 +141,19 @@ sgiioc4_clearirq(ide_drive_t * drive)
intr_reg = readl((void __iomem *)other_ir);
if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */
/*
- * Using sgiioc4_INB to read the Status register has a side
- * effect of clearing the interrupt. The first read should
+ * Using sgiioc4_read_status to read the Status register has a
+ * side effect of clearing the interrupt. The first read should
* clear it if it is set. The second read should return
* a "clear" status if it got cleared. If not, then spin
* for a bit trying to clear it.
*/
- u8 stat = sgiioc4_INB(io_ports->status_addr);
+ u8 stat = sgiioc4_read_status(hwif);
int count = 0;
- stat = sgiioc4_INB(io_ports->status_addr);
+
+ stat = sgiioc4_read_status(hwif);
while ((stat & 0x80) && (count++ < 100)) {
udelay(1);
- stat = sgiioc4_INB(io_ports->status_addr);
+ stat = sgiioc4_read_status(hwif);
}
if (intr_reg & 0x02) {
@@ -304,9 +305,9 @@ sgiioc4_dma_lost_irq(ide_drive_t * drive)
ide_dma_lost_irq(drive);
}
-static u8
-sgiioc4_INB(unsigned long port)
+static u8 sgiioc4_read_status(ide_hwif_t *hwif)
{
+ unsigned long port = hwif->io_ports.status_addr;
u8 reg = (u8) readb((void __iomem *) port);
if ((port & 0xFFF) == 0x11C) { /* Status register of IOC4 */
@@ -549,6 +550,21 @@ static int sgiioc4_dma_setup(ide_drive_t *drive)
return 0;
}
+static const struct ide_tp_ops sgiioc4_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = sgiioc4_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = ide_input_data,
+ .output_data = ide_output_data,
+};
+
static const struct ide_port_ops sgiioc4_port_ops = {
.set_dma_mode = sgiioc4_set_dma_mode,
/* reset DMA engine, clear IRQs */
@@ -571,6 +587,7 @@ static const struct ide_port_info sgiioc4_port_info __devinitdata = {
.name = DRV_NAME,
.chipset = ide_pci,
.init_dma = ide_dma_sgiioc4,
+ .tp_ops = &sgiioc4_tp_ops,
.port_ops = &sgiioc4_port_ops,
.dma_ops = &sgiioc4_dma_ops,
.host_flags = IDE_HFLAG_MMIO,
@@ -583,10 +600,10 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
unsigned long cmd_base, irqport;
unsigned long bar0, cmd_phys_base, ctl;
void __iomem *virt_base;
- ide_hwif_t *hwif;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw;
+ struct ide_host *host;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
struct ide_port_info d = sgiioc4_port_info;
+ int rc;
/* Get the CmdBlk and CtrlBlk Base Registers */
bar0 = pci_resource_start(dev, 0);
@@ -618,30 +635,26 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
hw.chipset = ide_pci;
hw.dev = &dev->dev;
- hwif = ide_find_port_slot(&d);
- if (hwif == NULL)
- goto err;
-
- ide_init_port_hw(hwif, &hw);
-
- /* The IOC4 uses MMIO rather than Port IO. */
- default_hwif_mmiops(hwif);
-
/* Initializing chipset IRQ Registers */
writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
- hwif->INB = &sgiioc4_INB;
-
- idx[0] = hwif->index;
+ host = ide_host_alloc(&d, hws);
+ if (host == NULL) {
+ rc = -ENOMEM;
+ goto err;
+ }
- if (ide_device_add(idx, &d))
- return -EIO;
+ rc = ide_host_register(host, &d, hws);
+ if (rc)
+ goto err_free;
return 0;
+err_free:
+ ide_host_free(host);
err:
release_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE);
iounmap(virt_base);
- return -ENOMEM;
+ return rc;
}
static unsigned int __devinit
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 6e9d7655d89..b8ad9ad6cf0 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -44,6 +44,8 @@
#include <linux/init.h>
#include <linux/io.h>
+#define DRV_NAME "siimage"
+
/**
* pdev_is_sata - check if device is SATA
* @pdev: PCI device to check
@@ -127,9 +129,10 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
static u8 sil_ioread8(struct pci_dev *dev, unsigned long addr)
{
+ struct ide_host *host = pci_get_drvdata(dev);
u8 tmp = 0;
- if (pci_get_drvdata(dev))
+ if (host->host_priv)
tmp = readb((void __iomem *)addr);
else
pci_read_config_byte(dev, addr, &tmp);
@@ -139,9 +142,10 @@ static u8 sil_ioread8(struct pci_dev *dev, unsigned long addr)
static u16 sil_ioread16(struct pci_dev *dev, unsigned long addr)
{
+ struct ide_host *host = pci_get_drvdata(dev);
u16 tmp = 0;
- if (pci_get_drvdata(dev))
+ if (host->host_priv)
tmp = readw((void __iomem *)addr);
else
pci_read_config_word(dev, addr, &tmp);
@@ -151,7 +155,9 @@ static u16 sil_ioread16(struct pci_dev *dev, unsigned long addr)
static void sil_iowrite8(struct pci_dev *dev, u8 val, unsigned long addr)
{
- if (pci_get_drvdata(dev))
+ struct ide_host *host = pci_get_drvdata(dev);
+
+ if (host->host_priv)
writeb(val, (void __iomem *)addr);
else
pci_write_config_byte(dev, addr, val);
@@ -159,7 +165,9 @@ static void sil_iowrite8(struct pci_dev *dev, u8 val, unsigned long addr)
static void sil_iowrite16(struct pci_dev *dev, u16 val, unsigned long addr)
{
- if (pci_get_drvdata(dev))
+ struct ide_host *host = pci_get_drvdata(dev);
+
+ if (host->host_priv)
writew(val, (void __iomem *)addr);
else
pci_write_config_word(dev, addr, val);
@@ -167,7 +175,9 @@ static void sil_iowrite16(struct pci_dev *dev, u16 val, unsigned long addr)
static void sil_iowrite32(struct pci_dev *dev, u32 val, unsigned long addr)
{
- if (pci_get_drvdata(dev))
+ struct ide_host *host = pci_get_drvdata(dev);
+
+ if (host->host_priv)
writel(val, (void __iomem *)addr);
else
pci_write_config_dword(dev, addr, val);
@@ -334,7 +344,7 @@ static int siimage_io_dma_test_irq(ide_drive_t *drive)
unsigned long addr = siimage_selreg(hwif, 1);
/* return 1 if INTR asserted */
- if (hwif->INB(hwif->dma_status) & 4)
+ if (inb(hwif->dma_base + ATA_DMA_STATUS) & 4)
return 1;
/* return 1 if Device INTR asserted */
@@ -382,7 +392,7 @@ static int siimage_mmio_dma_test_irq(ide_drive_t *drive)
}
/* return 1 if INTR asserted */
- if (readb((void __iomem *)hwif->dma_status) & 0x04)
+ if (readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS)) & 4)
return 1;
/* return 1 if Device INTR asserted */
@@ -445,66 +455,24 @@ static void sil_sata_pre_reset(ide_drive_t *drive)
}
/**
- * setup_mmio_siimage - switch controller into MMIO mode
- * @dev: PCI device we are configuring
- * @name: device name
- *
- * Attempt to put the device into MMIO mode. There are some slight
- * complications here with certain systems where the MMIO BAR isn't
- * mapped, so we have to be sure that we can fall back to I/O.
- */
-
-static unsigned int setup_mmio_siimage(struct pci_dev *dev, const char *name)
-{
- resource_size_t bar5 = pci_resource_start(dev, 5);
- unsigned long barsize = pci_resource_len(dev, 5);
- void __iomem *ioaddr;
-
- /*
- * Drop back to PIO if we can't map the MMIO. Some systems
- * seem to get terminally confused in the PCI spaces.
- */
- if (!request_mem_region(bar5, barsize, name)) {
- printk(KERN_WARNING "siimage: IDE controller MMIO ports not "
- "available.\n");
- return 0;
- }
-
- ioaddr = ioremap(bar5, barsize);
- if (ioaddr == NULL) {
- release_mem_region(bar5, barsize);
- return 0;
- }
-
- pci_set_master(dev);
- pci_set_drvdata(dev, (void *) ioaddr);
-
- return 1;
-}
-
-/**
* init_chipset_siimage - set up an SI device
* @dev: PCI device
- * @name: device name
*
* Perform the initial PCI set up for this device. Attempt to switch
* to 133 MHz clocking if the system isn't already set up to do it.
*/
-static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev,
- const char *name)
+static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev)
{
+ struct ide_host *host = pci_get_drvdata(dev);
+ void __iomem *ioaddr = host->host_priv;
unsigned long base, scsc_addr;
- void __iomem *ioaddr = NULL;
- u8 rev = dev->revision, tmp, BA5_EN;
+ u8 rev = dev->revision, tmp;
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, rev ? 1 : 255);
- pci_read_config_byte(dev, 0x8A, &BA5_EN);
-
- if ((BA5_EN & 0x01) || pci_resource_start(dev, 5))
- if (setup_mmio_siimage(dev, name))
- ioaddr = pci_get_drvdata(dev);
+ if (ioaddr)
+ pci_set_master(dev);
base = (unsigned long)ioaddr;
@@ -571,7 +539,8 @@ static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev,
{ "== 100", "== 133", "== 2X PCI", "DISABLED!" };
tmp >>= 4;
- printk(KERN_INFO "%s: BASE CLOCK %s\n", name, clk_str[tmp & 3]);
+ printk(KERN_INFO DRV_NAME " %s: BASE CLOCK %s\n",
+ pci_name(dev), clk_str[tmp & 3]);
}
return 0;
@@ -592,7 +561,8 @@ static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev,
static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
- void *addr = pci_get_drvdata(dev);
+ struct ide_host *host = pci_get_drvdata(dev);
+ void *addr = host->host_priv;
u8 ch = hwif->channel;
struct ide_io_ports *io_ports = &hwif->io_ports;
unsigned long base;
@@ -601,7 +571,7 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
* Fill in the basic hwif bits
*/
hwif->host_flags |= IDE_HFLAG_MMIO;
- default_hwif_mmiops(hwif);
+
hwif->hwif_data = addr;
/*
@@ -691,16 +661,15 @@ static void __devinit sil_quirkproc(ide_drive_t *drive)
static void __devinit init_iops_siimage(ide_hwif_t *hwif)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct ide_host *host = pci_get_drvdata(dev);
hwif->hwif_data = NULL;
/* Pessimal until we finish probing */
hwif->rqsize = 15;
- if (pci_get_drvdata(dev) == NULL)
- return;
-
- init_mmio_iops_siimage(hwif);
+ if (host->host_priv)
+ init_mmio_iops_siimage(hwif);
}
/**
@@ -748,9 +717,9 @@ static const struct ide_dma_ops sil_dma_ops = {
.dma_lost_irq = ide_dma_lost_irq,
};
-#define DECLARE_SII_DEV(name_str, p_ops) \
+#define DECLARE_SII_DEV(p_ops) \
{ \
- .name = name_str, \
+ .name = DRV_NAME, \
.init_chipset = init_chipset_siimage, \
.init_iops = init_iops_siimage, \
.port_ops = p_ops, \
@@ -761,9 +730,8 @@ static const struct ide_dma_ops sil_dma_ops = {
}
static const struct ide_port_info siimage_chipsets[] __devinitdata = {
- /* 0 */ DECLARE_SII_DEV("SiI680", &sil_pata_port_ops),
- /* 1 */ DECLARE_SII_DEV("SiI3112 Serial ATA", &sil_sata_port_ops),
- /* 2 */ DECLARE_SII_DEV("Adaptec AAR-1210SA", &sil_sata_port_ops)
+ /* 0: SiI680 */ DECLARE_SII_DEV(&sil_pata_port_ops),
+ /* 1: SiI3112 */ DECLARE_SII_DEV(&sil_sata_port_ops)
};
/**
@@ -778,8 +746,13 @@ static const struct ide_port_info siimage_chipsets[] __devinitdata = {
static int __devinit siimage_init_one(struct pci_dev *dev,
const struct pci_device_id *id)
{
+ void __iomem *ioaddr = NULL;
+ resource_size_t bar5 = pci_resource_start(dev, 5);
+ unsigned long barsize = pci_resource_len(dev, 5);
+ int rc;
struct ide_port_info d;
u8 idx = id->driver_data;
+ u8 BA5_EN;
d = siimage_chipsets[idx];
@@ -787,7 +760,7 @@ static int __devinit siimage_init_one(struct pci_dev *dev,
static int first = 1;
if (first) {
- printk(KERN_INFO "siimage: For full SATA support you "
+ printk(KERN_INFO DRV_NAME ": For full SATA support you "
"should use the libata sata_sil module.\n");
first = 0;
}
@@ -795,14 +768,61 @@ static int __devinit siimage_init_one(struct pci_dev *dev,
d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
}
- return ide_setup_pci_device(dev, &d);
+ rc = pci_enable_device(dev);
+ if (rc)
+ return rc;
+
+ pci_read_config_byte(dev, 0x8A, &BA5_EN);
+ if ((BA5_EN & 0x01) || bar5) {
+ /*
+ * Drop back to PIO if we can't map the MMIO. Some systems
+ * seem to get terminally confused in the PCI spaces.
+ */
+ if (!request_mem_region(bar5, barsize, d.name)) {
+ printk(KERN_WARNING DRV_NAME " %s: MMIO ports not "
+ "available\n", pci_name(dev));
+ } else {
+ ioaddr = ioremap(bar5, barsize);
+ if (ioaddr == NULL)
+ release_mem_region(bar5, barsize);
+ }
+ }
+
+ rc = ide_pci_init_one(dev, &d, ioaddr);
+ if (rc) {
+ if (ioaddr) {
+ iounmap(ioaddr);
+ release_mem_region(bar5, barsize);
+ }
+ pci_disable_device(dev);
+ }
+
+ return rc;
+}
+
+static void __devexit siimage_remove(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ void __iomem *ioaddr = host->host_priv;
+
+ ide_pci_remove(dev);
+
+ if (ioaddr) {
+ resource_size_t bar5 = pci_resource_start(dev, 5);
+ unsigned long barsize = pci_resource_len(dev, 5);
+
+ iounmap(ioaddr);
+ release_mem_region(bar5, barsize);
+ }
+
+ pci_disable_device(dev);
}
static const struct pci_device_id siimage_pci_tbl[] = {
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), 0 },
#ifdef CONFIG_BLK_DEV_IDE_SATA
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_3112), 1 },
- { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_1210SA), 2 },
+ { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_1210SA), 1 },
#endif
{ 0, },
};
@@ -812,6 +832,7 @@ static struct pci_driver driver = {
.name = "SiI_IDE",
.id_table = siimage_pci_tbl,
.probe = siimage_init_one,
+ .remove = siimage_remove,
};
static int __init siimage_ide_init(void)
@@ -819,7 +840,13 @@ static int __init siimage_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit siimage_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(siimage_ide_init);
+module_exit(siimage_ide_exit);
MODULE_AUTHOR("Andre Hedrick, Alan Cox");
MODULE_DESCRIPTION("PCI driver module for SiI IDE");
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index 2389945ca95..cc95f90b53b 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -52,6 +52,8 @@
#include <linux/init.h>
#include <linux/ide.h>
+#define DRV_NAME "sis5513"
+
/* registers layout and init values are chipset family dependant */
#define ATA_16 0x01
@@ -380,8 +382,9 @@ static int __devinit sis_find_family(struct pci_dev *dev)
}
pci_dev_put(host);
- printk(KERN_INFO "SIS5513: %s %s controller\n",
- SiSHostChipInfo[i].name, chipset_capability[chipset_family]);
+ printk(KERN_INFO DRV_NAME " %s: %s %s controller\n",
+ pci_name(dev), SiSHostChipInfo[i].name,
+ chipset_capability[chipset_family]);
}
if (!chipset_family) { /* Belongs to pci-quirks */
@@ -396,7 +399,8 @@ static int __devinit sis_find_family(struct pci_dev *dev)
pci_write_config_dword(dev, 0x54, idemisc);
if (trueid == 0x5518) {
- printk(KERN_INFO "SIS5513: SiS 962/963 MuTIOL IDE UDMA133 controller\n");
+ printk(KERN_INFO DRV_NAME " %s: SiS 962/963 MuTIOL IDE UDMA133 controller\n",
+ pci_name(dev));
chipset_family = ATA_133;
/* Check for 5513 compability mapping
@@ -405,7 +409,8 @@ static int __devinit sis_find_family(struct pci_dev *dev)
*/
if ((idemisc & 0x40000000) == 0) {
pci_write_config_dword(dev, 0x54, idemisc | 0x40000000);
- printk(KERN_INFO "SIS5513: Switching to 5513 register mapping\n");
+ printk(KERN_INFO DRV_NAME " %s: Switching to 5513 register mapping\n",
+ pci_name(dev));
}
}
}
@@ -429,10 +434,12 @@ static int __devinit sis_find_family(struct pci_dev *dev)
pci_dev_put(lpc_bridge);
if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) {
- printk(KERN_INFO "SIS5513: SiS 961B MuTIOL IDE UDMA133 controller\n");
+ printk(KERN_INFO DRV_NAME " %s: SiS 961B MuTIOL IDE UDMA133 controller\n",
+ pci_name(dev));
chipset_family = ATA_133a;
} else {
- printk(KERN_INFO "SIS5513: SiS 961 MuTIOL IDE UDMA100 controller\n");
+ printk(KERN_INFO DRV_NAME " %s: SiS 961 MuTIOL IDE UDMA100 controller\n",
+ pci_name(dev));
chipset_family = ATA_100;
}
}
@@ -441,8 +448,7 @@ static int __devinit sis_find_family(struct pci_dev *dev)
return chipset_family;
}
-static unsigned int __devinit init_chipset_sis5513(struct pci_dev *dev,
- const char *name)
+static unsigned int __devinit init_chipset_sis5513(struct pci_dev *dev)
{
/* Make general config ops here
1/ tell IDE channels to operate in Compatibility mode only
@@ -555,7 +561,7 @@ static const struct ide_port_ops sis_ata133_port_ops = {
};
static const struct ide_port_info sis5513_chipset __devinitdata = {
- .name = "SIS5513",
+ .name = DRV_NAME,
.init_chipset = init_chipset_sis5513,
.enablebits = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} },
.host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA,
@@ -583,7 +589,13 @@ static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_devi
d.udma_mask = udma_rates[chipset_family];
- return ide_setup_pci_device(dev, &d);
+ return ide_pci_init_one(dev, &d, NULL);
+}
+
+static void __devexit sis5513_remove(struct pci_dev *dev)
+{
+ ide_pci_remove(dev);
+ pci_disable_device(dev);
}
static const struct pci_device_id sis5513_pci_tbl[] = {
@@ -598,6 +610,7 @@ static struct pci_driver driver = {
.name = "SIS_IDE",
.id_table = sis5513_pci_tbl,
.probe = sis5513_init_one,
+ .remove = sis5513_remove,
};
static int __init sis5513_ide_init(void)
@@ -605,7 +618,13 @@ static int __init sis5513_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit sis5513_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(sis5513_ide_init);
+module_exit(sis5513_ide_exit);
MODULE_AUTHOR("Lionel Bouton, L C Chang, Andre Hedrick, Vojtech Pavlik");
MODULE_DESCRIPTION("PCI driver module for SIS IDE");
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 6efbde29717..73905bcc08f 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -23,6 +23,8 @@
#include <asm/io.h>
+#define DRV_NAME "sl82c105"
+
#undef DEBUG
#ifdef DEBUG
@@ -157,9 +159,9 @@ static void sl82c105_dma_lost_irq(ide_drive_t *drive)
* Was DMA enabled? If so, disable it - we're resetting the
* host. The IDE layer will be handling the drive for us.
*/
- dma_cmd = inb(hwif->dma_command);
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
if (dma_cmd & 1) {
- outb(dma_cmd & ~1, hwif->dma_command);
+ outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
printk("sl82c105: DMA was enabled\n");
}
@@ -270,7 +272,7 @@ static u8 sl82c105_bridge_revision(struct pci_dev *dev)
* channel 0 here at least, but channel 1 has to be enabled by
* firmware or arch code. We still set both to 16 bits mode.
*/
-static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const char *msg)
+static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev)
{
u32 val;
@@ -301,7 +303,7 @@ static const struct ide_dma_ops sl82c105_dma_ops = {
};
static const struct ide_port_info sl82c105_chipset __devinitdata = {
- .name = "W82C105",
+ .name = DRV_NAME,
.init_chipset = init_chipset_sl82c105,
.enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
.port_ops = &sl82c105_port_ops,
@@ -328,14 +330,14 @@ static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_dev
* Never ever EVER under any circumstances enable
* DMA when the bridge is this old.
*/
- printk(KERN_INFO "W82C105_IDE: Winbond W83C553 bridge "
+ printk(KERN_INFO DRV_NAME ": Winbond W83C553 bridge "
"revision %d, BM-DMA disabled\n", rev);
d.dma_ops = NULL;
d.mwdma_mask = 0;
d.host_flags &= ~IDE_HFLAG_SERIALIZE_DMA;
}
- return ide_setup_pci_device(dev, &d);
+ return ide_pci_init_one(dev, &d, NULL);
}
static const struct pci_device_id sl82c105_pci_tbl[] = {
@@ -348,6 +350,7 @@ static struct pci_driver driver = {
.name = "W82C105_IDE",
.id_table = sl82c105_pci_tbl,
.probe = sl82c105_init_one,
+ .remove = ide_pci_remove,
};
static int __init sl82c105_ide_init(void)
@@ -355,7 +358,13 @@ static int __init sl82c105_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit sl82c105_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(sl82c105_ide_init);
+module_exit(sl82c105_ide_exit);
MODULE_DESCRIPTION("PCI driver module for W82C105 IDE");
MODULE_LICENSE("GPL");
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index dae6e2c94d8..13d1fa491f2 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -15,6 +15,8 @@
#include <linux/ide.h>
#include <linux/init.h>
+#define DRV_NAME "slc90e66"
+
static DEFINE_SPINLOCK(slc90e66_lock);
static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
@@ -132,7 +134,7 @@ static const struct ide_port_ops slc90e66_port_ops = {
};
static const struct ide_port_info slc90e66_chipset __devinitdata = {
- .name = "SLC90E66",
+ .name = DRV_NAME,
.enablebits = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} },
.port_ops = &slc90e66_port_ops,
.host_flags = IDE_HFLAG_LEGACY_IRQS,
@@ -144,7 +146,7 @@ static const struct ide_port_info slc90e66_chipset __devinitdata = {
static int __devinit slc90e66_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &slc90e66_chipset);
+ return ide_pci_init_one(dev, &slc90e66_chipset, NULL);
}
static const struct pci_device_id slc90e66_pci_tbl[] = {
@@ -157,6 +159,7 @@ static struct pci_driver driver = {
.name = "SLC90e66_IDE",
.id_table = slc90e66_pci_tbl,
.probe = slc90e66_init_one,
+ .remove = ide_pci_remove,
};
static int __init slc90e66_ide_init(void)
@@ -164,7 +167,13 @@ static int __init slc90e66_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit slc90e66_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(slc90e66_ide_init);
+module_exit(slc90e66_ide_exit);
MODULE_AUTHOR("Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for SLC90E66 IDE");
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index 9b4b27a4c71..b1cb8a9ce5a 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -11,6 +11,8 @@
#include <linux/pci.h>
#include <linux/ide.h>
+#define DRV_NAME "tc86c001"
+
static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
@@ -63,7 +65,7 @@ static int tc86c001_timer_expiry(ide_drive_t *drive)
ide_hwif_t *hwif = HWIF(drive);
ide_expiry_t *expiry = ide_get_hwifdata(hwif);
ide_hwgroup_t *hwgroup = HWGROUP(drive);
- u8 dma_stat = inb(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
/* Restore a higher level driver's expiry handler first. */
hwgroup->expiry = expiry;
@@ -71,21 +73,24 @@ static int tc86c001_timer_expiry(ide_drive_t *drive)
if ((dma_stat & 5) == 1) { /* DMA active and no interrupt */
unsigned long sc_base = hwif->config_data;
unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04);
- u8 dma_cmd = inb(hwif->dma_command);
+ u8 dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
printk(KERN_WARNING "%s: DMA interrupt possibly stuck, "
"attempting recovery...\n", drive->name);
/* Stop DMA */
- outb(dma_cmd & ~0x01, hwif->dma_command);
+ outb(dma_cmd & ~0x01, hwif->dma_base + ATA_DMA_CMD);
/* Setup the dummy DMA transfer */
outw(0, sc_base + 0x0a); /* Sector Count */
outw(0, twcr_port); /* Transfer Word Count 1 or 2 */
/* Start the dummy DMA transfer */
- outb(0x00, hwif->dma_command); /* clear R_OR_WCTR for write */
- outb(0x01, hwif->dma_command); /* set START_STOPBM */
+
+ /* clear R_OR_WCTR for write */
+ outb(0x00, hwif->dma_base + ATA_DMA_CMD);
+ /* set START_STOPBM */
+ outb(0x01, hwif->dma_base + ATA_DMA_CMD);
/*
* If an interrupt was pending, it should come thru shortly.
@@ -170,16 +175,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
hwif->rqsize = 0xffff;
}
-static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev,
- const char *name)
-{
- int err = pci_request_region(dev, 5, name);
-
- if (err)
- printk(KERN_ERR "%s: system control regs already in use", name);
- return err;
-}
-
static const struct ide_port_ops tc86c001_port_ops = {
.set_pio_mode = tc86c001_set_pio_mode,
.set_dma_mode = tc86c001_set_mode,
@@ -198,13 +193,11 @@ static const struct ide_dma_ops tc86c001_dma_ops = {
};
static const struct ide_port_info tc86c001_chipset __devinitdata = {
- .name = "TC86C001",
- .init_chipset = init_chipset_tc86c001,
+ .name = DRV_NAME,
.init_hwif = init_hwif_tc86c001,
.port_ops = &tc86c001_port_ops,
.dma_ops = &tc86c001_dma_ops,
- .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD |
- IDE_HFLAG_ABUSE_SET_DMA_MODE,
+ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
@@ -213,7 +206,37 @@ static const struct ide_port_info tc86c001_chipset __devinitdata = {
static int __devinit tc86c001_init_one(struct pci_dev *dev,
const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &tc86c001_chipset);
+ int rc;
+
+ rc = pci_enable_device(dev);
+ if (rc)
+ goto out;
+
+ rc = pci_request_region(dev, 5, DRV_NAME);
+ if (rc) {
+ printk(KERN_ERR DRV_NAME ": system control regs already in use");
+ goto out_disable;
+ }
+
+ rc = ide_pci_init_one(dev, &tc86c001_chipset, NULL);
+ if (rc)
+ goto out_release;
+
+ goto out;
+
+out_release:
+ pci_release_region(dev, 5);
+out_disable:
+ pci_disable_device(dev);
+out:
+ return rc;
+}
+
+static void __devexit tc86c001_remove(struct pci_dev *dev)
+{
+ ide_pci_remove(dev);
+ pci_release_region(dev, 5);
+ pci_disable_device(dev);
}
static const struct pci_device_id tc86c001_pci_tbl[] = {
@@ -225,14 +248,22 @@ MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl);
static struct pci_driver driver = {
.name = "TC86C001",
.id_table = tc86c001_pci_tbl,
- .probe = tc86c001_init_one
+ .probe = tc86c001_init_one,
+ .remove = tc86c001_remove,
};
static int __init tc86c001_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
+
+static void __exit tc86c001_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(tc86c001_ide_init);
+module_exit(tc86c001_ide_exit);
MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
MODULE_DESCRIPTION("PCI driver module for TC86C001 IDE");
diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
index db65a558d4e..b77ec35151b 100644
--- a/drivers/ide/pci/triflex.c
+++ b/drivers/ide/pci/triflex.c
@@ -33,6 +33,8 @@
#include <linux/ide.h>
#include <linux/init.h>
+#define DRV_NAME "triflex"
+
static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
@@ -93,7 +95,7 @@ static const struct ide_port_ops triflex_port_ops = {
};
static const struct ide_port_info triflex_device __devinitdata = {
- .name = "TRIFLEX",
+ .name = DRV_NAME,
.enablebits = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
.port_ops = &triflex_port_ops,
.pio_mask = ATA_PIO4,
@@ -104,7 +106,7 @@ static const struct ide_port_info triflex_device __devinitdata = {
static int __devinit triflex_init_one(struct pci_dev *dev,
const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &triflex_device);
+ return ide_pci_init_one(dev, &triflex_device, NULL);
}
static const struct pci_device_id triflex_pci_tbl[] = {
@@ -117,6 +119,7 @@ static struct pci_driver driver = {
.name = "TRIFLEX_IDE",
.id_table = triflex_pci_tbl,
.probe = triflex_init_one,
+ .remove = ide_pci_remove,
};
static int __init triflex_ide_init(void)
@@ -124,7 +127,13 @@ static int __init triflex_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit triflex_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(triflex_ide_init);
+module_exit(triflex_ide_exit);
MODULE_AUTHOR("Torben Mathiasen");
MODULE_DESCRIPTION("PCI driver module for Compaq Triflex IDE");
diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
index a8a3138682e..fd28b49977f 100644
--- a/drivers/ide/pci/trm290.c
+++ b/drivers/ide/pci/trm290.c
@@ -141,6 +141,8 @@
#include <asm/io.h>
+#define DRV_NAME "trm290"
+
static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
{
ide_hwif_t *hwif = HWIF(drive);
@@ -245,10 +247,10 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
u8 reg = 0;
if ((dev->class & 5) && cfg_base)
- printk(KERN_INFO "TRM290: chip");
+ printk(KERN_INFO DRV_NAME " %s: chip", pci_name(dev));
else {
cfg_base = 0x3df0;
- printk(KERN_INFO "TRM290: using default");
+ printk(KERN_INFO DRV_NAME " %s: using default", pci_name(dev));
}
printk(KERN_CONT " config base at 0x%04x\n", cfg_base);
hwif->config_data = cfg_base;
@@ -325,7 +327,7 @@ static struct ide_dma_ops trm290_dma_ops = {
};
static const struct ide_port_info trm290_chipset __devinitdata = {
- .name = "TRM290",
+ .name = DRV_NAME,
.init_hwif = init_hwif_trm290,
.chipset = ide_trm290,
.port_ops = &trm290_port_ops,
@@ -340,7 +342,7 @@ static const struct ide_port_info trm290_chipset __devinitdata = {
static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &trm290_chipset);
+ return ide_pci_init_one(dev, &trm290_chipset, NULL);
}
static const struct pci_device_id trm290_pci_tbl[] = {
@@ -353,6 +355,7 @@ static struct pci_driver driver = {
.name = "TRM290_IDE",
.id_table = trm290_pci_tbl,
.probe = trm290_init_one,
+ .remove = ide_pci_remove,
};
static int __init trm290_ide_init(void)
@@ -360,7 +363,13 @@ static int __init trm290_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit trm290_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(trm290_ide_init);
+module_exit(trm290_ide_exit);
MODULE_AUTHOR("Mark Lord");
MODULE_DESCRIPTION("PCI driver module for Tekram TRM290 IDE");
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index e47384c70c4..454d2bf62dc 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -35,6 +35,8 @@
#include <asm/processor.h>
#endif
+#define DRV_NAME "via82cxxx"
+
#define VIA_IDE_ENABLE 0x40
#define VIA_IDE_CONFIG 0x41
#define VIA_FIFO_CONFIG 0x43
@@ -113,7 +115,8 @@ struct via82cxxx_dev
static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct via82cxxx_dev *vdev = pci_get_drvdata(dev);
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct via82cxxx_dev *vdev = host->host_priv;
u8 t;
if (~vdev->via_config->flags & VIA_BAD_AST) {
@@ -153,7 +156,8 @@ static void via_set_drive(ide_drive_t *drive, const u8 speed)
ide_hwif_t *hwif = drive->hwif;
ide_drive_t *peer = hwif->drives + (~drive->dn & 1);
struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct via82cxxx_dev *vdev = pci_get_drvdata(dev);
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct via82cxxx_dev *vdev = host->host_priv;
struct ide_timing t, p;
unsigned int T, UT;
@@ -258,37 +262,19 @@ static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
/**
* init_chipset_via82cxxx - initialization handler
* @dev: PCI device
- * @name: Name of interface
*
* The initialization callback. Here we determine the IDE chip type
* and initialize its drive independent registers.
*/
-static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev)
{
- struct pci_dev *isa = NULL;
- struct via82cxxx_dev *vdev;
- struct via_isa_bridge *via_config;
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct via82cxxx_dev *vdev = host->host_priv;
+ struct via_isa_bridge *via_config = vdev->via_config;
u8 t, v;
u32 u;
- vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
- if (!vdev) {
- printk(KERN_ERR "VP_IDE: out of memory :(\n");
- return -ENOMEM;
- }
- pci_set_drvdata(dev, vdev);
-
- /*
- * Find the ISA bridge to see how good the IDE is.
- */
- vdev->via_config = via_config = via_config_find(&isa);
-
- /* We checked this earlier so if it fails here deeep badness
- is involved */
-
- BUG_ON(!via_config->id);
-
/*
* Detect cable and configure Clk66
*/
@@ -334,39 +320,6 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const
pci_write_config_byte(dev, VIA_FIFO_CONFIG, t);
- /*
- * Determine system bus clock.
- */
-
- via_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000;
-
- switch (via_clock) {
- case 33000: via_clock = 33333; break;
- case 37000: via_clock = 37500; break;
- case 41000: via_clock = 41666; break;
- }
-
- if (via_clock < 20000 || via_clock > 50000) {
- printk(KERN_WARNING "VP_IDE: User given PCI clock speed "
- "impossible (%d), using 33 MHz instead.\n", via_clock);
- printk(KERN_WARNING "VP_IDE: Use ide0=ata66 if you want "
- "to assume 80-wire cable.\n");
- via_clock = 33333;
- }
-
- /*
- * Print the boot message.
- */
-
- printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %sDMA%s "
- "controller on pci%s\n",
- via_config->name, isa->revision,
- via_config->udma_mask ? "U" : "MW",
- via_dma[via_config->udma_mask ?
- (fls(via_config->udma_mask) - 1) : 0],
- pci_name(dev));
-
- pci_dev_put(isa);
return 0;
}
@@ -402,7 +355,8 @@ static int via_cable_override(struct pci_dev *pdev)
static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif)
{
struct pci_dev *pdev = to_pci_dev(hwif->dev);
- struct via82cxxx_dev *vdev = pci_get_drvdata(pdev);
+ struct ide_host *host = pci_get_drvdata(pdev);
+ struct via82cxxx_dev *vdev = host->host_priv;
if (via_cable_override(pdev))
return ATA_CBL_PATA40_SHORT;
@@ -420,12 +374,11 @@ static const struct ide_port_ops via_port_ops = {
};
static const struct ide_port_info via82cxxx_chipset __devinitdata = {
- .name = "VP_IDE",
+ .name = DRV_NAME,
.init_chipset = init_chipset_via82cxxx,
.enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
.port_ops = &via_port_ops,
.host_flags = IDE_HFLAG_PIO_NO_BLACKLIST |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_POST_SET_MODE |
IDE_HFLAG_IO_32BIT,
.pio_mask = ATA_PIO5,
@@ -437,6 +390,8 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i
{
struct pci_dev *isa = NULL;
struct via_isa_bridge *via_config;
+ struct via82cxxx_dev *vdev;
+ int rc;
u8 idx = id->driver_data;
struct ide_port_info d;
@@ -446,12 +401,42 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i
* Find the ISA bridge and check we know what it is.
*/
via_config = via_config_find(&isa);
- pci_dev_put(isa);
if (!via_config->id) {
- printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, disabling DMA.\n");
+ printk(KERN_WARNING DRV_NAME " %s: unknown chipset, skipping\n",
+ pci_name(dev));
return -ENODEV;
}
+ /*
+ * Print the boot message.
+ */
+ printk(KERN_INFO DRV_NAME " %s: VIA %s (rev %02x) IDE %sDMA%s\n",
+ pci_name(dev), via_config->name, isa->revision,
+ via_config->udma_mask ? "U" : "MW",
+ via_dma[via_config->udma_mask ?
+ (fls(via_config->udma_mask) - 1) : 0]);
+
+ pci_dev_put(isa);
+
+ /*
+ * Determine system bus clock.
+ */
+ via_clock = (ide_pci_clk ? ide_pci_clk : 33) * 1000;
+
+ switch (via_clock) {
+ case 33000: via_clock = 33333; break;
+ case 37000: via_clock = 37500; break;
+ case 41000: via_clock = 41666; break;
+ }
+
+ if (via_clock < 20000 || via_clock > 50000) {
+ printk(KERN_WARNING DRV_NAME ": User given PCI clock speed "
+ "impossible (%d), using 33 MHz instead.\n", via_clock);
+ printk(KERN_WARNING DRV_NAME ": Use ide0=ata66 if you want "
+ "to assume 80-wire cable.\n");
+ via_clock = 33333;
+ }
+
if (idx == 0)
d.host_flags |= IDE_HFLAG_NO_AUTODMA;
else
@@ -467,7 +452,29 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i
d.udma_mask = via_config->udma_mask;
- return ide_setup_pci_device(dev, &d);
+ vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+ if (!vdev) {
+ printk(KERN_ERR DRV_NAME " %s: out of memory :(\n",
+ pci_name(dev));
+ return -ENOMEM;
+ }
+
+ vdev->via_config = via_config;
+
+ rc = ide_pci_init_one(dev, &d, vdev);
+ if (rc)
+ kfree(vdev);
+
+ return rc;
+}
+
+static void __devexit via_remove(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct via82cxxx_dev *vdev = host->host_priv;
+
+ ide_pci_remove(dev);
+ kfree(vdev);
}
static const struct pci_device_id via_pci_tbl[] = {
@@ -484,6 +491,7 @@ static struct pci_driver driver = {
.name = "VIA_IDE",
.id_table = via_pci_tbl,
.probe = via_init_one,
+ .remove = via_remove,
};
static int __init via_ide_init(void)
@@ -491,7 +499,13 @@ static int __init via_ide_init(void)
return ide_pci_register_driver(&driver);
}
+static void __exit via_ide_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
module_init(via_ide_init);
+module_exit(via_ide_exit);
MODULE_AUTHOR("Vojtech Pavlik, Michel Aubry, Jeff Garzik, Andre Hedrick");
MODULE_DESCRIPTION("PCI driver module for VIA IDE");
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 93fb9067c04..c521bf6e1bf 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -48,6 +48,8 @@
#include <asm/mediabay.h>
#endif
+#define DRV_NAME "ide-pmac"
+
#undef IDE_PMAC_DEBUG
#define DMA_WAIT_TIMEOUT 50
@@ -424,7 +426,9 @@ static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
static void
pmac_ide_selectproc(ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
if (pmif == NULL)
return;
@@ -444,7 +448,9 @@ pmac_ide_selectproc(ide_drive_t *drive)
static void
pmac_ide_kauai_selectproc(ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
if (pmif == NULL)
return;
@@ -465,7 +471,9 @@ pmac_ide_kauai_selectproc(ide_drive_t *drive)
static void
pmac_ide_do_update_timings(ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
if (pmif == NULL)
return;
@@ -478,12 +486,26 @@ pmac_ide_do_update_timings(ide_drive_t *drive)
pmac_ide_selectproc(drive);
}
-static void pmac_outbsync(ide_hwif_t *hwif, u8 value, unsigned long port)
+static void pmac_exec_command(ide_hwif_t *hwif, u8 cmd)
{
- u32 tmp;
-
- writeb(value, (void __iomem *) port);
- tmp = readl((void __iomem *)(hwif->io_ports.data_addr
+ writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
+ (void)readl((void __iomem *)(hwif->io_ports.data_addr
+ + IDE_TIMING_CONFIG));
+}
+
+static void pmac_set_irq(ide_hwif_t *hwif, int on)
+{
+ u8 ctl = ATA_DEVCTL_OBS;
+
+ if (on == 4) { /* hack for SRST */
+ ctl |= 4;
+ on &= ~4;
+ }
+
+ ctl |= on ? 0 : 2;
+
+ writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
+ (void)readl((void __iomem *)(hwif->io_ports.data_addr
+ IDE_TIMING_CONFIG));
}
@@ -493,11 +515,13 @@ static void pmac_outbsync(ide_hwif_t *hwif, u8 value, unsigned long port)
static void
pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
struct ide_timing *tim = ide_timing_find_mode(XFER_PIO_0 + pio);
u32 *timings, t;
unsigned accessTicks, recTicks;
unsigned accessTime, recTime;
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
unsigned int cycle_time;
if (pmif == NULL)
@@ -778,9 +802,11 @@ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
int unit = (drive->select.b.unit & 0x01);
int ret = 0;
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
u32 *timings, *timings2, tl[2];
timings = &pmif->timings[unit];
@@ -852,11 +878,8 @@ sanitize_timings(pmac_ide_hwif_t *pmif)
/* Suspend call back, should be called after the child devices
* have actually been suspended
*/
-static int
-pmac_ide_do_suspend(ide_hwif_t *hwif)
+static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif)
{
- pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
-
/* We clear the timings */
pmif->timings[0] = 0;
pmif->timings[1] = 0;
@@ -884,11 +907,8 @@ pmac_ide_do_suspend(ide_hwif_t *hwif)
/* Resume call back, should be called before the child devices
* are resumed
*/
-static int
-pmac_ide_do_resume(ide_hwif_t *hwif)
+static int pmac_ide_do_resume(pmac_ide_hwif_t *pmif)
{
- pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
-
/* Hard reset & re-enable controller (do we really need to reset ? -BenH) */
if (!pmif->mediabay) {
ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 1);
@@ -916,7 +936,8 @@ pmac_ide_do_resume(ide_hwif_t *hwif)
static u8 pmac_ide_cable_detect(ide_hwif_t *hwif)
{
- pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)ide_get_hwifdata(hwif);
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
struct device_node *np = pmif->node;
const char *cable = of_get_property(np, "cable-type", NULL);
@@ -936,7 +957,40 @@ static u8 pmac_ide_cable_detect(ide_hwif_t *hwif)
return ATA_CBL_PATA40;
}
+static void pmac_ide_init_dev(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+
+ if (pmif->mediabay) {
+#ifdef CONFIG_PMAC_MEDIABAY
+ if (check_media_bay_by_base(pmif->regbase, MB_CD) == 0) {
+ drive->noprobe = 0;
+ return;
+ }
+#endif
+ drive->noprobe = 1;
+ }
+}
+
+static const struct ide_tp_ops pmac_tp_ops = {
+ .exec_command = pmac_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = pmac_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = ide_input_data,
+ .output_data = ide_output_data,
+};
+
static const struct ide_port_ops pmac_ide_ata6_port_ops = {
+ .init_dev = pmac_ide_init_dev,
.set_pio_mode = pmac_ide_set_pio_mode,
.set_dma_mode = pmac_ide_set_dma_mode,
.selectproc = pmac_ide_kauai_selectproc,
@@ -944,6 +998,7 @@ static const struct ide_port_ops pmac_ide_ata6_port_ops = {
};
static const struct ide_port_ops pmac_ide_ata4_port_ops = {
+ .init_dev = pmac_ide_init_dev,
.set_pio_mode = pmac_ide_set_pio_mode,
.set_dma_mode = pmac_ide_set_dma_mode,
.selectproc = pmac_ide_selectproc,
@@ -951,6 +1006,7 @@ static const struct ide_port_ops pmac_ide_ata4_port_ops = {
};
static const struct ide_port_ops pmac_ide_port_ops = {
+ .init_dev = pmac_ide_init_dev,
.set_pio_mode = pmac_ide_set_pio_mode,
.set_dma_mode = pmac_ide_set_dma_mode,
.selectproc = pmac_ide_selectproc,
@@ -959,12 +1015,14 @@ static const struct ide_port_ops pmac_ide_port_ops = {
static const struct ide_dma_ops pmac_dma_ops;
static const struct ide_port_info pmac_port_info = {
+ .name = DRV_NAME,
.init_dma = pmac_ide_init_dma,
.chipset = ide_pmac,
+ .tp_ops = &pmac_tp_ops,
+ .port_ops = &pmac_ide_port_ops,
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
.dma_ops = &pmac_dma_ops,
#endif
- .port_ops = &pmac_ide_port_ops,
.host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
IDE_HFLAG_POST_SET_MODE |
IDE_HFLAG_MMIO |
@@ -977,13 +1035,15 @@ static const struct ide_port_info pmac_port_info = {
* Setup, register & probe an IDE channel driven by this driver, this is
* called by one of the 2 probe functions (macio or PCI).
*/
-static int __devinit
-pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
+static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw)
{
struct device_node *np = pmif->node;
const int *bidp;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ struct ide_host *host;
+ ide_hwif_t *hwif;
+ hw_regs_t *hws[] = { hw, NULL, NULL, NULL };
struct ide_port_info d = pmac_port_info;
+ int rc;
pmif->broken_dma = pmif->broken_dma_warn = 0;
if (of_device_is_compatible(np, "shasta-ata")) {
@@ -1054,31 +1114,16 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY));
}
- /* Setup MMIO ops */
- default_hwif_mmiops(hwif);
- hwif->OUTBSYNC = pmac_outbsync;
+ printk(KERN_INFO DRV_NAME ": Found Apple %s controller (%s), "
+ "bus ID %d%s, irq %d\n", model_name[pmif->kind],
+ pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id,
+ pmif->mediabay ? " (mediabay)" : "", hw->irq);
- hwif->hwif_data = pmif;
- ide_init_port_hw(hwif, hw);
+ rc = ide_host_add(&d, hws, &host);
+ if (rc)
+ return rc;
- printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n",
- hwif->index, model_name[pmif->kind], pmif->aapl_bus_id,
- pmif->mediabay ? " (mediabay)" : "", hwif->irq);
-
- if (pmif->mediabay) {
-#ifdef CONFIG_PMAC_MEDIABAY
- if (check_media_bay_by_base(pmif->regbase, MB_CD)) {
-#else
- if (1) {
-#endif
- hwif->drives[0].noprobe = 1;
- hwif->drives[1].noprobe = 1;
- }
- }
-
- idx[0] = hwif->index;
-
- ide_device_add(idx, &d);
+ hwif = host->ports[0];
return 0;
}
@@ -1101,7 +1146,6 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
{
void __iomem *base;
unsigned long regbase;
- ide_hwif_t *hwif;
pmac_ide_hwif_t *pmif;
int irq, rc;
hw_regs_t hw;
@@ -1110,14 +1154,6 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
if (pmif == NULL)
return -ENOMEM;
- hwif = ide_find_port();
- if (hwif == NULL) {
- printk(KERN_ERR "ide-pmac: MacIO interface attach with no slot\n");
- printk(KERN_ERR " %s\n", mdev->ofdev.node->full_name);
- rc = -ENODEV;
- goto out_free_pmif;
- }
-
if (macio_resource_count(mdev) == 0) {
printk(KERN_WARNING "ide-pmac: no address for %s\n",
mdev->ofdev.node->full_name);
@@ -1164,7 +1200,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
} else
pmif->dma_regs = NULL;
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
- dev_set_drvdata(&mdev->ofdev.dev, hwif);
+ dev_set_drvdata(&mdev->ofdev.dev, pmif);
memset(&hw, 0, sizeof(hw));
pmac_ide_init_ports(&hw, pmif->regbase);
@@ -1172,7 +1208,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
hw.dev = &mdev->bus->pdev->dev;
hw.parent = &mdev->ofdev.dev;
- rc = pmac_ide_setup_device(pmif, hwif, &hw);
+ rc = pmac_ide_setup_device(pmif, &hw);
if (rc != 0) {
/* The inteface is released to the common IDE layer */
dev_set_drvdata(&mdev->ofdev.dev, NULL);
@@ -1195,12 +1231,13 @@ out_free_pmif:
static int
pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t mesg)
{
- ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
- int rc = 0;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
+ int rc = 0;
if (mesg.event != mdev->ofdev.dev.power.power_state.event
&& (mesg.event & PM_EVENT_SLEEP)) {
- rc = pmac_ide_do_suspend(hwif);
+ rc = pmac_ide_do_suspend(pmif);
if (rc == 0)
mdev->ofdev.dev.power.power_state = mesg;
}
@@ -1211,11 +1248,12 @@ pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t mesg)
static int
pmac_ide_macio_resume(struct macio_dev *mdev)
{
- ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
- int rc = 0;
-
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
+ int rc = 0;
+
if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) {
- rc = pmac_ide_do_resume(hwif);
+ rc = pmac_ide_do_resume(pmif);
if (rc == 0)
mdev->ofdev.dev.power.power_state = PMSG_ON;
}
@@ -1229,7 +1267,6 @@ pmac_ide_macio_resume(struct macio_dev *mdev)
static int __devinit
pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
{
- ide_hwif_t *hwif;
struct device_node *np;
pmac_ide_hwif_t *pmif;
void __iomem *base;
@@ -1247,14 +1284,6 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
if (pmif == NULL)
return -ENOMEM;
- hwif = ide_find_port();
- if (hwif == NULL) {
- printk(KERN_ERR "ide-pmac: PCI interface attach with no slot\n");
- printk(KERN_ERR " %s\n", np->full_name);
- rc = -ENODEV;
- goto out_free_pmif;
- }
-
if (pci_enable_device(pdev)) {
printk(KERN_WARNING "ide-pmac: Can't enable PCI device for "
"%s\n", np->full_name);
@@ -1284,14 +1313,14 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
pmif->kauai_fcr = base;
pmif->irq = pdev->irq;
- pci_set_drvdata(pdev, hwif);
+ pci_set_drvdata(pdev, pmif);
memset(&hw, 0, sizeof(hw));
pmac_ide_init_ports(&hw, pmif->regbase);
hw.irq = pdev->irq;
hw.dev = &pdev->dev;
- rc = pmac_ide_setup_device(pmif, hwif, &hw);
+ rc = pmac_ide_setup_device(pmif, &hw);
if (rc != 0) {
/* The inteface is released to the common IDE layer */
pci_set_drvdata(pdev, NULL);
@@ -1310,12 +1339,12 @@ out_free_pmif:
static int
pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
{
- ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
- int rc = 0;
-
+ pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)pci_get_drvdata(pdev);
+ int rc = 0;
+
if (mesg.event != pdev->dev.power.power_state.event
&& (mesg.event & PM_EVENT_SLEEP)) {
- rc = pmac_ide_do_suspend(hwif);
+ rc = pmac_ide_do_suspend(pmif);
if (rc == 0)
pdev->dev.power.power_state = mesg;
}
@@ -1326,11 +1355,11 @@ pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
static int
pmac_ide_pci_resume(struct pci_dev *pdev)
{
- ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
- int rc = 0;
-
+ pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)pci_get_drvdata(pdev);
+ int rc = 0;
+
if (pdev->dev.power.power_state.event != PM_EVENT_ON) {
- rc = pmac_ide_do_resume(hwif);
+ rc = pmac_ide_do_resume(pmif);
if (rc == 0)
pdev->dev.power.power_state = PMSG_ON;
}
@@ -1421,10 +1450,11 @@ out:
static int
pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
{
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
struct dbdma_cmd *table;
int i, count = 0;
- ide_hwif_t *hwif = HWIF(drive);
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
struct scatterlist *sg;
int wr = (rq_data_dir(rq) == WRITE);
@@ -1520,7 +1550,8 @@ static int
pmac_ide_dma_setup(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
struct request *rq = HWGROUP(drive)->rq;
u8 unit = (drive->select.b.unit & 0x01);
u8 ata4;
@@ -1560,7 +1591,9 @@ pmac_ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
static void
pmac_ide_dma_start(ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
volatile struct dbdma_regs __iomem *dma;
dma = pmif->dma_regs;
@@ -1576,7 +1609,9 @@ pmac_ide_dma_start(ide_drive_t *drive)
static int
pmac_ide_dma_end (ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
volatile struct dbdma_regs __iomem *dma;
u32 dstat;
@@ -1604,7 +1639,9 @@ pmac_ide_dma_end (ide_drive_t *drive)
static int
pmac_ide_dma_test_irq (ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
volatile struct dbdma_regs __iomem *dma;
unsigned long status, timeout;
@@ -1664,7 +1701,9 @@ static void pmac_ide_dma_host_set(ide_drive_t *drive, int on)
static void
pmac_ide_dma_lost_irq (ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
volatile struct dbdma_regs __iomem *dma;
unsigned long status;
@@ -1694,7 +1733,8 @@ static const struct ide_dma_ops pmac_dma_ops = {
static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
const struct ide_port_info *d)
{
- pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
struct pci_dev *dev = to_pci_dev(hwif->dev);
/* We won't need pci_dev if we switch to generic consistent
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 65fc08b6b6d..a8e9e8a69a5 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -39,17 +39,18 @@ static int ide_setup_pci_baseregs(struct pci_dev *dev, const char *name)
if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||
(progif & 5) != 5) {
if ((progif & 0xa) != 0xa) {
- printk(KERN_INFO "%s: device not capable of full "
- "native PCI mode\n", name);
+ printk(KERN_INFO "%s %s: device not capable of full "
+ "native PCI mode\n", name, pci_name(dev));
return -EOPNOTSUPP;
}
- printk("%s: placing both ports into native PCI mode\n", name);
+ printk(KERN_INFO "%s %s: placing both ports into native PCI "
+ "mode\n", name, pci_name(dev));
(void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);
if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||
(progif & 5) != 5) {
- printk(KERN_ERR "%s: rewrite of PROGIF failed, wanted "
- "0x%04x, got 0x%04x\n",
- name, progif|5, progif);
+ printk(KERN_ERR "%s %s: rewrite of PROGIF failed, "
+ "wanted 0x%04x, got 0x%04x\n",
+ name, pci_name(dev), progif | 5, progif);
return -EOPNOTSUPP;
}
}
@@ -57,14 +58,14 @@ static int ide_setup_pci_baseregs(struct pci_dev *dev, const char *name)
}
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
-static void ide_pci_clear_simplex(unsigned long dma_base, const char *name)
+static int ide_pci_clear_simplex(unsigned long dma_base, const char *name)
{
u8 dma_stat = inb(dma_base + 2);
outb(dma_stat & 0x60, dma_base + 2);
dma_stat = inb(dma_base + 2);
- if (dma_stat & 0x80)
- printk(KERN_INFO "%s: simplex device: DMA forced\n", name);
+
+ return (dma_stat & 0x80) ? 1 : 0;
}
/**
@@ -73,15 +74,12 @@ static void ide_pci_clear_simplex(unsigned long dma_base, const char *name)
* @d: IDE port info
*
* Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space.
- * Where a device has a partner that is already in DMA mode we check
- * and enforce IDE simplex rules.
*/
unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long dma_base = 0;
- u8 dma_stat = 0;
if (hwif->host_flags & IDE_HFLAG_MMIO)
return hwif->dma_base;
@@ -94,7 +92,8 @@ unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d)
dma_base = pci_resource_start(dev, baridx);
if (dma_base == 0) {
- printk(KERN_ERR "%s: DMA base is invalid\n", d->name);
+ printk(KERN_ERR "%s %s: DMA base is invalid\n",
+ d->name, pci_name(dev));
return 0;
}
}
@@ -102,11 +101,22 @@ unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d)
if (hwif->channel)
dma_base += 8;
- if (d->host_flags & IDE_HFLAG_CS5520)
+ return dma_base;
+}
+EXPORT_SYMBOL_GPL(ide_pci_dma_base);
+
+int ide_pci_check_simplex(ide_hwif_t *hwif, const struct ide_port_info *d)
+{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ u8 dma_stat;
+
+ if (d->host_flags & (IDE_HFLAG_MMIO | IDE_HFLAG_CS5520))
goto out;
if (d->host_flags & IDE_HFLAG_CLEAR_SIMPLEX) {
- ide_pci_clear_simplex(dma_base, d->name);
+ if (ide_pci_clear_simplex(hwif->dma_base, d->name))
+ printk(KERN_INFO "%s %s: simplex device: DMA forced\n",
+ d->name, pci_name(dev));
goto out;
}
@@ -120,15 +130,16 @@ unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d)
* we tune the drive then try to grab DMA ownership if we want to be
* the DMA end. This has to be become dynamic to handle hot-plug.
*/
- dma_stat = hwif->INB(dma_base + 2);
+ dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) {
- printk(KERN_INFO "%s: simplex device: DMA disabled\n", d->name);
- dma_base = 0;
+ printk(KERN_INFO "%s %s: simplex device: DMA disabled\n",
+ d->name, pci_name(dev));
+ return -1;
}
out:
- return dma_base;
+ return 0;
}
-EXPORT_SYMBOL_GPL(ide_pci_dma_base);
+EXPORT_SYMBOL_GPL(ide_pci_check_simplex);
/*
* Set up BM-DMA capability (PnP BIOS should have done this)
@@ -144,8 +155,8 @@ int ide_pci_set_master(struct pci_dev *dev, const char *name)
if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) ||
(pcicmd & PCI_COMMAND_MASTER) == 0) {
- printk(KERN_ERR "%s: error updating PCICMD on %s\n",
- name, pci_name(dev));
+ printk(KERN_ERR "%s %s: error updating PCICMD\n",
+ name, pci_name(dev));
return -EIO;
}
}
@@ -157,9 +168,9 @@ EXPORT_SYMBOL_GPL(ide_pci_set_master);
void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d)
{
- printk(KERN_INFO "%s: IDE controller (0x%04x:0x%04x rev 0x%02x) at "
- " PCI slot %s\n", d->name, dev->vendor, dev->device,
- dev->revision, pci_name(dev));
+ printk(KERN_INFO "%s %s: IDE controller (0x%04x:0x%04x rev 0x%02x)\n",
+ d->name, pci_name(dev),
+ dev->vendor, dev->device, dev->revision);
}
EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
@@ -184,11 +195,12 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
if (pci_enable_device(dev)) {
ret = pci_enable_device_io(dev);
if (ret < 0) {
- printk(KERN_WARNING "%s: (ide_setup_pci_device:) "
- "Could not enable device.\n", d->name);
+ printk(KERN_WARNING "%s %s: couldn't enable device\n",
+ d->name, pci_name(dev));
goto out;
}
- printk(KERN_WARNING "%s: BIOS configuration fixed.\n", d->name);
+ printk(KERN_WARNING "%s %s: BIOS configuration fixed\n",
+ d->name, pci_name(dev));
}
/*
@@ -198,7 +210,8 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
*/
ret = pci_set_dma_mask(dev, DMA_32BIT_MASK);
if (ret < 0) {
- printk(KERN_ERR "%s: can't set dma mask\n", d->name);
+ printk(KERN_ERR "%s %s: can't set DMA mask\n",
+ d->name, pci_name(dev));
goto out;
}
@@ -216,7 +229,8 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
ret = pci_request_selected_regions(dev, bars, d->name);
if (ret < 0)
- printk(KERN_ERR "%s: can't reserve resources\n", d->name);
+ printk(KERN_ERR "%s %s: can't reserve resources\n",
+ d->name, pci_name(dev));
out:
return ret;
}
@@ -242,15 +256,18 @@ static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d)
*/
if (ide_setup_pci_baseregs(dev, d->name) ||
pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) {
- printk(KERN_INFO "%s: device disabled (BIOS)\n", d->name);
+ printk(KERN_INFO "%s %s: device disabled (BIOS)\n",
+ d->name, pci_name(dev));
return -ENODEV;
}
if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) {
- printk(KERN_ERR "%s: error accessing PCI regs\n", d->name);
+ printk(KERN_ERR "%s %s: error accessing PCI regs\n",
+ d->name, pci_name(dev));
return -EIO;
}
if (!(pcicmd & PCI_COMMAND_IO)) {
- printk(KERN_ERR "%s: unable to enable IDE controller\n", d->name);
+ printk(KERN_ERR "%s %s: unable to enable IDE controller\n",
+ d->name, pci_name(dev));
return -ENXIO;
}
return 0;
@@ -284,33 +301,32 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *
}
/**
- * ide_hwif_configure - configure an IDE interface
+ * ide_hw_configure - configure a hw_regs_t instance
* @dev: PCI device holding interface
* @d: IDE port info
* @port: port number
* @irq: PCI IRQ
+ * @hw: hw_regs_t instance corresponding to this port
*
* Perform the initial set up for the hardware interface structure. This
* is done per interface port rather than per PCI device. There may be
* more than one port per device.
*
- * Returns the new hardware interface structure, or NULL on a failure
+ * Returns zero on success or an error code.
*/
-static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
- const struct ide_port_info *d,
- unsigned int port, int irq)
+static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d,
+ unsigned int port, int irq, hw_regs_t *hw)
{
unsigned long ctl = 0, base = 0;
- ide_hwif_t *hwif;
- struct hw_regs_s hw;
if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) {
if (ide_pci_check_iomem(dev, d, 2 * port) ||
ide_pci_check_iomem(dev, d, 2 * port + 1)) {
- printk(KERN_ERR "%s: I/O baseregs (BIOS) are reported "
- "as MEM for port %d!\n", d->name, port);
- return NULL;
+ printk(KERN_ERR "%s %s: I/O baseregs (BIOS) are "
+ "reported as MEM for port %d!\n",
+ d->name, pci_name(dev), port);
+ return -EINVAL;
}
ctl = pci_resource_start(dev, 2*port+1);
@@ -322,24 +338,18 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
}
if (!base || !ctl) {
- printk(KERN_ERR "%s: bad PCI BARs for port %d, skipping\n",
- d->name, port);
- return NULL;
+ printk(KERN_ERR "%s %s: bad PCI BARs for port %d, skipping\n",
+ d->name, pci_name(dev), port);
+ return -EINVAL;
}
- hwif = ide_find_port_slot(d);
- if (hwif == NULL)
- return NULL;
-
- memset(&hw, 0, sizeof(hw));
- hw.irq = irq;
- hw.dev = &dev->dev;
- hw.chipset = d->chipset ? d->chipset : ide_pci;
- ide_std_init_ports(&hw, base, ctl | 2);
+ memset(hw, 0, sizeof(*hw));
+ hw->irq = irq;
+ hw->dev = &dev->dev;
+ hw->chipset = d->chipset ? d->chipset : ide_pci;
+ ide_std_init_ports(hw, base, ctl | 2);
- ide_init_port_hw(hwif, &hw);
-
- return hwif;
+ return 0;
}
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
@@ -362,7 +372,15 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
(dev->class & 0x80))) {
unsigned long base = ide_pci_dma_base(hwif, d);
- if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
+ if (base == 0)
+ return -1;
+
+ hwif->dma_base = base;
+
+ if (ide_pci_check_simplex(hwif, d) < 0)
+ return -1;
+
+ if (ide_pci_set_master(dev, d->name) < 0)
return -1;
if (hwif->host_flags & IDE_HFLAG_MMIO)
@@ -376,7 +394,7 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
if (ide_allocate_dma_engine(hwif))
return -1;
- ide_setup_dma(hwif, base);
+ hwif->dma_ops = &sff_dma_ops;
}
return 0;
@@ -388,14 +406,14 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
* @dev: PCI device
* @d: IDE port info
* @noisy: verbose flag
- * @config: returned as 1 if we configured the hardware
*
* Set up the PCI and controller side of the IDE interface. This brings
* up the PCI side of the device, checks that the device is enabled
* and enables it if need be
*/
-static int ide_setup_pci_controller(struct pci_dev *dev, const struct ide_port_info *d, int noisy, int *config)
+static int ide_setup_pci_controller(struct pci_dev *dev,
+ const struct ide_port_info *d, int noisy)
{
int ret;
u16 pcicmd;
@@ -409,15 +427,16 @@ static int ide_setup_pci_controller(struct pci_dev *dev, const struct ide_port_i
ret = pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
if (ret < 0) {
- printk(KERN_ERR "%s: error accessing PCI regs\n", d->name);
+ printk(KERN_ERR "%s %s: error accessing PCI regs\n",
+ d->name, pci_name(dev));
goto out;
}
if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */
ret = ide_pci_configure(dev, d);
if (ret < 0)
goto out;
- *config = 1;
- printk(KERN_INFO "%s: device enabled (Linux)\n", d->name);
+ printk(KERN_INFO "%s %s: device enabled (Linux)\n",
+ d->name, pci_name(dev));
}
out:
@@ -429,7 +448,8 @@ out:
* @dev: PCI device
* @d: IDE port info
* @pciirq: IRQ line
- * @idx: ATA index table to update
+ * @hw: hw_regs_t instances corresponding to this PCI IDE device
+ * @hws: hw_regs_t pointers table to update
*
* Scan the interfaces attached to this device and do any
* necessary per port setup. Attach the devices and ask the
@@ -440,10 +460,10 @@ out:
* where the chipset setup is not the default PCI IDE one.
*/
-void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int pciirq, u8 *idx)
+void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d,
+ int pciirq, hw_regs_t *hw, hw_regs_t **hws)
{
int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port;
- ide_hwif_t *hwif;
u8 tmp;
/*
@@ -455,15 +475,15 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int
if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) ||
(tmp & e->mask) != e->val)) {
- printk(KERN_INFO "%s: IDE port disabled\n", d->name);
+ printk(KERN_INFO "%s %s: IDE port disabled\n",
+ d->name, pci_name(dev));
continue; /* port not enabled */
}
- hwif = ide_hwif_configure(dev, d, port, pciirq);
- if (hwif == NULL)
+ if (ide_hw_configure(dev, d, port, pciirq, hw + port))
continue;
- *(idx + port) = hwif->index;
+ *(hws + port) = hw + port;
}
}
EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
@@ -480,95 +500,162 @@ EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
*/
static int do_ide_setup_pci_device(struct pci_dev *dev,
const struct ide_port_info *d,
- u8 *idx, u8 noisy)
+ u8 noisy)
{
- int tried_config = 0;
int pciirq, ret;
- ret = ide_setup_pci_controller(dev, d, noisy, &tried_config);
- if (ret < 0)
- goto out;
-
/*
* Can we trust the reported IRQ?
*/
pciirq = dev->irq;
+ /*
+ * This allows offboard ide-pci cards the enable a BIOS,
+ * verify interrupt settings of split-mirror pci-config
+ * space, place chipset into init-mode, and/or preserve
+ * an interrupt if the card is not native ide support.
+ */
+ ret = d->init_chipset ? d->init_chipset(dev) : 0;
+ if (ret < 0)
+ goto out;
+
/* Is it an "IDE storage" device in non-PCI mode? */
if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 5) != 5) {
if (noisy)
- printk(KERN_INFO "%s: not 100%% native mode: "
- "will probe irqs later\n", d->name);
- /*
- * This allows offboard ide-pci cards the enable a BIOS,
- * verify interrupt settings of split-mirror pci-config
- * space, place chipset into init-mode, and/or preserve
- * an interrupt if the card is not native ide support.
- */
- ret = d->init_chipset ? d->init_chipset(dev, d->name) : 0;
- if (ret < 0)
- goto out;
+ printk(KERN_INFO "%s %s: not 100%% native mode: will "
+ "probe irqs later\n", d->name, pci_name(dev));
pciirq = ret;
- } else if (tried_config) {
- if (noisy)
- printk(KERN_INFO "%s: will probe irqs later\n", d->name);
- pciirq = 0;
- } else if (!pciirq) {
- if (noisy)
- printk(KERN_WARNING "%s: bad irq (%d): will probe later\n",
- d->name, pciirq);
- pciirq = 0;
- } else {
- if (d->init_chipset) {
- ret = d->init_chipset(dev, d->name);
- if (ret < 0)
- goto out;
- }
- if (noisy)
- printk(KERN_INFO "%s: 100%% native mode on irq %d\n",
- d->name, pciirq);
+ } else if (!pciirq && noisy) {
+ printk(KERN_WARNING "%s %s: bad irq (%d): will probe later\n",
+ d->name, pci_name(dev), pciirq);
+ } else if (noisy) {
+ printk(KERN_INFO "%s %s: 100%% native mode on irq %d\n",
+ d->name, pci_name(dev), pciirq);
}
- /* FIXME: silent failure can happen */
-
- ide_pci_setup_ports(dev, d, pciirq, idx);
+ ret = pciirq;
out:
return ret;
}
-int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d)
+int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d,
+ void *priv)
{
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ struct ide_host *host;
+ hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
int ret;
- ret = do_ide_setup_pci_device(dev, d, &idx[0], 1);
+ ret = ide_setup_pci_controller(dev, d, 1);
+ if (ret < 0)
+ goto out;
+
+ ide_pci_setup_ports(dev, d, 0, &hw[0], &hws[0]);
+
+ host = ide_host_alloc(d, hws);
+ if (host == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ host->dev[0] = &dev->dev;
+
+ host->host_priv = priv;
+
+ pci_set_drvdata(dev, host);
+
+ ret = do_ide_setup_pci_device(dev, d, 1);
+ if (ret < 0)
+ goto out;
- if (ret >= 0)
- ide_device_add(idx, d);
+ /* fixup IRQ */
+ hw[1].irq = hw[0].irq = ret;
+ ret = ide_host_register(host, d, hws);
+ if (ret)
+ ide_host_free(host);
+out:
return ret;
}
-EXPORT_SYMBOL_GPL(ide_setup_pci_device);
+EXPORT_SYMBOL_GPL(ide_pci_init_one);
-int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
- const struct ide_port_info *d)
+int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2,
+ const struct ide_port_info *d, void *priv)
{
struct pci_dev *pdev[] = { dev1, dev2 };
+ struct ide_host *host;
int ret, i;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
+
+ for (i = 0; i < 2; i++) {
+ ret = ide_setup_pci_controller(pdev[i], d, !i);
+ if (ret < 0)
+ goto out;
+
+ ide_pci_setup_ports(pdev[i], d, 0, &hw[i*2], &hws[i*2]);
+ }
+
+ host = ide_host_alloc(d, hws);
+ if (host == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ host->dev[0] = &dev1->dev;
+ host->dev[1] = &dev2->dev;
+
+ host->host_priv = priv;
+
+ pci_set_drvdata(pdev[0], host);
+ pci_set_drvdata(pdev[1], host);
for (i = 0; i < 2; i++) {
- ret = do_ide_setup_pci_device(pdev[i], d, &idx[i*2], !i);
+ ret = do_ide_setup_pci_device(pdev[i], d, !i);
+
/*
* FIXME: Mom, mom, they stole me the helper function to undo
* do_ide_setup_pci_device() on the first device!
*/
if (ret < 0)
goto out;
+
+ /* fixup IRQ */
+ hw[i*2 + 1].irq = hw[i*2].irq = ret;
}
- ide_device_add(idx, d);
+ ret = ide_host_register(host, d, hws);
+ if (ret)
+ ide_host_free(host);
out:
return ret;
}
-EXPORT_SYMBOL_GPL(ide_setup_pci_devices);
+EXPORT_SYMBOL_GPL(ide_pci_init_two);
+
+void ide_pci_remove(struct pci_dev *dev)
+{
+ struct ide_host *host = pci_get_drvdata(dev);
+ struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
+ int bars;
+
+ if (host->host_flags & IDE_HFLAG_SINGLE)
+ bars = (1 << 2) - 1;
+ else
+ bars = (1 << 4) - 1;
+
+ if ((host->host_flags & IDE_HFLAG_NO_DMA) == 0) {
+ if (host->host_flags & IDE_HFLAG_CS5520)
+ bars |= (1 << 2);
+ else
+ bars |= (1 << 4);
+ }
+
+ ide_host_remove(host);
+
+ if (dev2)
+ pci_release_selected_regions(dev2, bars);
+ pci_release_selected_regions(dev, bars);
+
+ if (dev2)
+ pci_disable_device(dev2);
+ pci_disable_device(dev);
+}
+EXPORT_SYMBOL_GPL(ide_pci_remove);
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 9d19aec5820..b6eb2cf2591 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2296,9 +2296,10 @@ static void dv1394_add_host(struct hpsb_host *host)
ohci = (struct ti_ohci *)host->hostdata;
- device_create(hpsb_protocol_class, NULL, MKDEV(
- IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
- "dv1394-%d", id);
+ device_create_drvdata(hpsb_protocol_class, NULL,
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), NULL,
+ "dv1394-%d", id);
dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
diff --git a/drivers/ieee1394/iso.c b/drivers/ieee1394/iso.c
index 07ca35c98f9..1cf6487b65b 100644
--- a/drivers/ieee1394/iso.c
+++ b/drivers/ieee1394/iso.c
@@ -11,6 +11,7 @@
#include <linux/pci.h>
#include <linux/sched.h>
+#include <linux/mm.h>
#include <linux/slab.h>
#include "hosts.h"
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 05710c7c122..994a21e5a0a 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -754,7 +754,8 @@ static void nodemgr_remove_uds(struct node_entry *ne)
*/
mutex_lock(&nodemgr_serialize_remove_uds);
for (;;) {
- dev = class_find_device(&nodemgr_ud_class, ne, __match_ne);
+ dev = class_find_device(&nodemgr_ud_class, NULL, ne,
+ __match_ne);
if (!dev)
break;
ud = container_of(dev, struct unit_directory, unit_dev);
@@ -901,7 +902,8 @@ static struct node_entry *find_entry_by_guid(u64 guid)
struct device *dev;
struct node_entry *ne;
- dev = class_find_device(&nodemgr_ne_class, &guid, __match_ne_guid);
+ dev = class_find_device(&nodemgr_ne_class, NULL, &guid,
+ __match_ne_guid);
if (!dev)
return NULL;
ne = container_of(dev, struct node_entry, node_dev);
@@ -940,7 +942,8 @@ static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
param.host = host;
param.nodeid = nodeid;
- dev = class_find_device(&nodemgr_ne_class, &param, __match_ne_nodeid);
+ dev = class_find_device(&nodemgr_ne_class, NULL, &param,
+ __match_ne_nodeid);
if (!dev)
return NULL;
ne = container_of(dev, struct node_entry, node_dev);
@@ -1453,7 +1456,8 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
ne->in_limbo = 1;
WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
- class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_driver_suspend);
+ class_for_each_device(&nodemgr_ud_class, NULL, ne,
+ __nodemgr_driver_suspend);
}
@@ -1462,7 +1466,8 @@ static void nodemgr_resume_ne(struct node_entry *ne)
ne->in_limbo = 0;
device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
- class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_driver_resume);
+ class_for_each_device(&nodemgr_ud_class, NULL, ne,
+ __nodemgr_driver_resume);
HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
}
@@ -1498,7 +1503,8 @@ static int __nodemgr_update_pdrv(struct device *dev, void *data)
static void nodemgr_update_pdrv(struct node_entry *ne)
{
- class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_update_pdrv);
+ class_for_each_device(&nodemgr_ud_class, NULL, ne,
+ __nodemgr_update_pdrv);
}
@@ -1591,7 +1597,8 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
* while probes are time-consuming. (Well, those probes need some
* improvement...) */
- class_for_each_device(&nodemgr_ne_class, &param, __nodemgr_node_probe);
+ class_for_each_device(&nodemgr_ne_class, NULL, &param,
+ __nodemgr_node_probe);
/* If we had a bus reset while we were scanning the bus, it is
* possible that we did not probe all nodes. In that case, we
@@ -1826,7 +1833,7 @@ int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
hip.cb = cb;
hip.data = data;
- error = class_for_each_device(&hpsb_host_class, &hip,
+ error = class_for_each_device(&hpsb_host_class, NULL, &hip,
__nodemgr_for_each_host);
return error;
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 96f2847b040..6fa9e4a2184 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -3010,10 +3010,10 @@ static int __init init_raw1394(void)
hpsb_register_highlevel(&raw1394_highlevel);
if (IS_ERR
- (device_create(
+ (device_create_drvdata(
hpsb_protocol_class, NULL,
MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
- RAW1394_DEVICE_NAME))) {
+ NULL, RAW1394_DEVICE_NAME))) {
ret = -EFAULT;
goto out_unreg;
}
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 069b9f6bf16..25db6e67fa4 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -1341,9 +1341,9 @@ static void video1394_add_host (struct hpsb_host *host)
hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
- device_create(hpsb_protocol_class, NULL,
- MKDEV(IEEE1394_MAJOR, minor),
- "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
+ device_create_drvdata(hpsb_protocol_class, NULL,
+ MKDEV(IEEE1394_MAJOR, minor), NULL,
+ "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
}
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 55738eead3b..922d35f4fc0 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -44,6 +44,7 @@
#include <linux/spinlock.h>
#include <linux/sysfs.h>
#include <linux/workqueue.h>
+#include <linux/kdev_t.h>
#include <rdma/ib_cache.h>
#include <rdma/ib_cm.h>
@@ -162,8 +163,8 @@ struct cm_port {
struct cm_device {
struct list_head list;
- struct ib_device *device;
- struct kobject dev_obj;
+ struct ib_device *ib_device;
+ struct device *device;
u8 ack_delay;
struct cm_port *port[0];
};
@@ -339,7 +340,7 @@ static void cm_init_av_for_response(struct cm_port *port, struct ib_wc *wc,
{
av->port = port;
av->pkey_index = wc->pkey_index;
- ib_init_ah_from_wc(port->cm_dev->device, port->port_num, wc,
+ ib_init_ah_from_wc(port->cm_dev->ib_device, port->port_num, wc,
grh, &av->ah_attr);
}
@@ -353,7 +354,7 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
read_lock_irqsave(&cm.device_lock, flags);
list_for_each_entry(cm_dev, &cm.device_list, list) {
- if (!ib_find_cached_gid(cm_dev->device, &path->sgid,
+ if (!ib_find_cached_gid(cm_dev->ib_device, &path->sgid,
&p, NULL)) {
port = cm_dev->port[p-1];
break;
@@ -364,13 +365,13 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
if (!port)
return -EINVAL;
- ret = ib_find_cached_pkey(cm_dev->device, port->port_num,
+ ret = ib_find_cached_pkey(cm_dev->ib_device, port->port_num,
be16_to_cpu(path->pkey), &av->pkey_index);
if (ret)
return ret;
av->port = port;
- ib_init_ah_from_path(cm_dev->device, port->port_num, path,
+ ib_init_ah_from_path(cm_dev->ib_device, port->port_num, path,
&av->ah_attr);
av->timeout = path->packet_life_time + 1;
return 0;
@@ -1515,7 +1516,7 @@ static int cm_req_handler(struct cm_work *work)
req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
- cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);
+ cm_id = ib_create_cm_id(work->port->cm_dev->ib_device, NULL, NULL);
if (IS_ERR(cm_id))
return PTR_ERR(cm_id);
@@ -1550,7 +1551,7 @@ static int cm_req_handler(struct cm_work *work)
cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]);
ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av);
if (ret) {
- ib_get_cached_gid(work->port->cm_dev->device,
+ ib_get_cached_gid(work->port->cm_dev->ib_device,
work->port->port_num, 0, &work->path[0].sgid);
ib_send_cm_rej(cm_id, IB_CM_REJ_INVALID_GID,
&work->path[0].sgid, sizeof work->path[0].sgid,
@@ -2950,7 +2951,7 @@ static int cm_sidr_req_handler(struct cm_work *work)
struct cm_sidr_req_msg *sidr_req_msg;
struct ib_wc *wc;
- cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);
+ cm_id = ib_create_cm_id(work->port->cm_dev->ib_device, NULL, NULL);
if (IS_ERR(cm_id))
return PTR_ERR(cm_id);
cm_id_priv = container_of(cm_id, struct cm_id_private, id);
@@ -3578,7 +3579,7 @@ static void cm_get_ack_delay(struct cm_device *cm_dev)
{
struct ib_device_attr attr;
- if (ib_query_device(cm_dev->device, &attr))
+ if (ib_query_device(cm_dev->ib_device, &attr))
cm_dev->ack_delay = 0; /* acks will rely on packet life time */
else
cm_dev->ack_delay = attr.local_ca_ack_delay;
@@ -3618,18 +3619,6 @@ static struct kobj_type cm_port_obj_type = {
.release = cm_release_port_obj
};
-static void cm_release_dev_obj(struct kobject *obj)
-{
- struct cm_device *cm_dev;
-
- cm_dev = container_of(obj, struct cm_device, dev_obj);
- kfree(cm_dev);
-}
-
-static struct kobj_type cm_dev_obj_type = {
- .release = cm_release_dev_obj
-};
-
struct class cm_class = {
.name = "infiniband_cm",
};
@@ -3640,7 +3629,7 @@ static int cm_create_port_fs(struct cm_port *port)
int i, ret;
ret = kobject_init_and_add(&port->port_obj, &cm_port_obj_type,
- &port->cm_dev->dev_obj,
+ &port->cm_dev->device->kobj,
"%d", port->port_num);
if (ret) {
kfree(port);
@@ -3676,7 +3665,7 @@ static void cm_remove_port_fs(struct cm_port *port)
kobject_put(&port->port_obj);
}
-static void cm_add_one(struct ib_device *device)
+static void cm_add_one(struct ib_device *ib_device)
{
struct cm_device *cm_dev;
struct cm_port *port;
@@ -3691,26 +3680,27 @@ static void cm_add_one(struct ib_device *device)
int ret;
u8 i;
- if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
+ if (rdma_node_get_transport(ib_device->node_type) != RDMA_TRANSPORT_IB)
return;
cm_dev = kzalloc(sizeof(*cm_dev) + sizeof(*port) *
- device->phys_port_cnt, GFP_KERNEL);
+ ib_device->phys_port_cnt, GFP_KERNEL);
if (!cm_dev)
return;
- cm_dev->device = device;
+ cm_dev->ib_device = ib_device;
cm_get_ack_delay(cm_dev);
- ret = kobject_init_and_add(&cm_dev->dev_obj, &cm_dev_obj_type,
- &cm_class.subsys.kobj, "%s", device->name);
- if (ret) {
+ cm_dev->device = device_create_drvdata(&cm_class, &ib_device->dev,
+ MKDEV(0, 0), NULL,
+ "%s", ib_device->name);
+ if (!cm_dev->device) {
kfree(cm_dev);
return;
}
set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
- for (i = 1; i <= device->phys_port_cnt; i++) {
+ for (i = 1; i <= ib_device->phys_port_cnt; i++) {
port = kzalloc(sizeof *port, GFP_KERNEL);
if (!port)
goto error1;
@@ -3723,7 +3713,7 @@ static void cm_add_one(struct ib_device *device)
if (ret)
goto error1;
- port->mad_agent = ib_register_mad_agent(device, i,
+ port->mad_agent = ib_register_mad_agent(ib_device, i,
IB_QPT_GSI,
&reg_req,
0,
@@ -3733,11 +3723,11 @@ static void cm_add_one(struct ib_device *device)
if (IS_ERR(port->mad_agent))
goto error2;
- ret = ib_modify_port(device, i, 0, &port_modify);
+ ret = ib_modify_port(ib_device, i, 0, &port_modify);
if (ret)
goto error3;
}
- ib_set_client_data(device, &cm_client, cm_dev);
+ ib_set_client_data(ib_device, &cm_client, cm_dev);
write_lock_irqsave(&cm.device_lock, flags);
list_add_tail(&cm_dev->list, &cm.device_list);
@@ -3753,14 +3743,14 @@ error1:
port_modify.clr_port_cap_mask = IB_PORT_CM_SUP;
while (--i) {
port = cm_dev->port[i-1];
- ib_modify_port(device, port->port_num, 0, &port_modify);
+ ib_modify_port(ib_device, port->port_num, 0, &port_modify);
ib_unregister_mad_agent(port->mad_agent);
cm_remove_port_fs(port);
}
- kobject_put(&cm_dev->dev_obj);
+ device_unregister(cm_dev->device);
}
-static void cm_remove_one(struct ib_device *device)
+static void cm_remove_one(struct ib_device *ib_device)
{
struct cm_device *cm_dev;
struct cm_port *port;
@@ -3770,7 +3760,7 @@ static void cm_remove_one(struct ib_device *device)
unsigned long flags;
int i;
- cm_dev = ib_get_client_data(device, &cm_client);
+ cm_dev = ib_get_client_data(ib_device, &cm_client);
if (!cm_dev)
return;
@@ -3778,14 +3768,14 @@ static void cm_remove_one(struct ib_device *device)
list_del(&cm_dev->list);
write_unlock_irqrestore(&cm.device_lock, flags);
- for (i = 1; i <= device->phys_port_cnt; i++) {
+ for (i = 1; i <= ib_device->phys_port_cnt; i++) {
port = cm_dev->port[i-1];
- ib_modify_port(device, port->port_num, 0, &port_modify);
+ ib_modify_port(ib_device, port->port_num, 0, &port_modify);
ib_unregister_mad_agent(port->mad_agent);
flush_workqueue(cm.wq);
cm_remove_port_fs(port);
}
- kobject_put(&cm_dev->dev_obj);
+ device_unregister(cm_dev->device);
}
static int __init ib_cm_init(void)
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index ae11d5cc74d..e980ff3335d 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -168,6 +168,12 @@ struct cma_work {
struct rdma_cm_event event;
};
+struct cma_ndev_work {
+ struct work_struct work;
+ struct rdma_id_private *id;
+ struct rdma_cm_event event;
+};
+
union cma_ip_addr {
struct in6_addr ip6;
struct {
@@ -914,7 +920,10 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
struct rdma_cm_event event;
int ret = 0;
- if (cma_disable_callback(id_priv, CMA_CONNECT))
+ if ((ib_event->event != IB_CM_TIMEWAIT_EXIT &&
+ cma_disable_callback(id_priv, CMA_CONNECT)) ||
+ (ib_event->event == IB_CM_TIMEWAIT_EXIT &&
+ cma_disable_callback(id_priv, CMA_DISCONNECT)))
return 0;
memset(&event, 0, sizeof event);
@@ -950,6 +959,8 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
event.event = RDMA_CM_EVENT_DISCONNECTED;
break;
case IB_CM_TIMEWAIT_EXIT:
+ event.event = RDMA_CM_EVENT_TIMEWAIT_EXIT;
+ break;
case IB_CM_MRA_RECEIVED:
/* ignore event */
goto out;
@@ -1598,6 +1609,30 @@ out:
kfree(work);
}
+static void cma_ndev_work_handler(struct work_struct *_work)
+{
+ struct cma_ndev_work *work = container_of(_work, struct cma_ndev_work, work);
+ struct rdma_id_private *id_priv = work->id;
+ int destroy = 0;
+
+ mutex_lock(&id_priv->handler_mutex);
+ if (id_priv->state == CMA_DESTROYING ||
+ id_priv->state == CMA_DEVICE_REMOVAL)
+ goto out;
+
+ if (id_priv->id.event_handler(&id_priv->id, &work->event)) {
+ cma_exch(id_priv, CMA_DESTROYING);
+ destroy = 1;
+ }
+
+out:
+ mutex_unlock(&id_priv->handler_mutex);
+ cma_deref_id(id_priv);
+ if (destroy)
+ rdma_destroy_id(&id_priv->id);
+ kfree(work);
+}
+
static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms)
{
struct rdma_route *route = &id_priv->id.route;
@@ -2723,6 +2758,65 @@ void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr)
}
EXPORT_SYMBOL(rdma_leave_multicast);
+static int cma_netdev_change(struct net_device *ndev, struct rdma_id_private *id_priv)
+{
+ struct rdma_dev_addr *dev_addr;
+ struct cma_ndev_work *work;
+
+ dev_addr = &id_priv->id.route.addr.dev_addr;
+
+ if ((dev_addr->src_dev == ndev) &&
+ memcmp(dev_addr->src_dev_addr, ndev->dev_addr, ndev->addr_len)) {
+ printk(KERN_INFO "RDMA CM addr change for ndev %s used by id %p\n",
+ ndev->name, &id_priv->id);
+ work = kzalloc(sizeof *work, GFP_KERNEL);
+ if (!work)
+ return -ENOMEM;
+
+ INIT_WORK(&work->work, cma_ndev_work_handler);
+ work->id = id_priv;
+ work->event.event = RDMA_CM_EVENT_ADDR_CHANGE;
+ atomic_inc(&id_priv->refcount);
+ queue_work(cma_wq, &work->work);
+ }
+
+ return 0;
+}
+
+static int cma_netdev_callback(struct notifier_block *self, unsigned long event,
+ void *ctx)
+{
+ struct net_device *ndev = (struct net_device *)ctx;
+ struct cma_device *cma_dev;
+ struct rdma_id_private *id_priv;
+ int ret = NOTIFY_DONE;
+
+ if (dev_net(ndev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (event != NETDEV_BONDING_FAILOVER)
+ return NOTIFY_DONE;
+
+ if (!(ndev->flags & IFF_MASTER) || !(ndev->priv_flags & IFF_BONDING))
+ return NOTIFY_DONE;
+
+ mutex_lock(&lock);
+ list_for_each_entry(cma_dev, &dev_list, list)
+ list_for_each_entry(id_priv, &cma_dev->id_list, list) {
+ ret = cma_netdev_change(ndev, id_priv);
+ if (ret)
+ goto out;
+ }
+
+out:
+ mutex_unlock(&lock);
+ return ret;
+}
+
+static struct notifier_block cma_nb = {
+ .notifier_call = cma_netdev_callback
+};
+
static void cma_add_one(struct ib_device *device)
{
struct cma_device *cma_dev;
@@ -2831,6 +2925,7 @@ static int cma_init(void)
ib_sa_register_client(&sa_client);
rdma_addr_register_client(&addr_client);
+ register_netdevice_notifier(&cma_nb);
ret = ib_register_client(&cma_client);
if (ret)
@@ -2838,6 +2933,7 @@ static int cma_init(void)
return 0;
err:
+ unregister_netdevice_notifier(&cma_nb);
rdma_addr_unregister_client(&addr_client);
ib_sa_unregister_client(&sa_client);
destroy_workqueue(cma_wq);
@@ -2847,6 +2943,7 @@ err:
static void cma_cleanup(void)
{
ib_unregister_client(&cma_client);
+ unregister_netdevice_notifier(&cma_nb);
rdma_addr_unregister_client(&addr_client);
ib_sa_unregister_client(&sa_client);
destroy_workqueue(cma_wq);
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index 81c9195b512..8f9509e1ebf 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -942,8 +942,7 @@ static int iwcm_init_qp_init_attr(struct iwcm_id_private *cm_id_priv,
case IW_CM_STATE_CONN_RECV:
case IW_CM_STATE_ESTABLISHED:
*qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS;
- qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE |
- IB_ACCESS_REMOTE_WRITE|
+ qp_attr->qp_access_flags = IB_ACCESS_REMOTE_WRITE|
IB_ACCESS_REMOTE_READ;
ret = 0;
break;
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 1341de793e5..7863a50d56f 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -1064,7 +1064,8 @@ static void ib_sa_remove_one(struct ib_device *device)
for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
ib_unregister_mad_agent(sa_dev->port[i].agent);
- kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
+ if (sa_dev->port[i].sm_ah)
+ kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
}
kfree(sa_dev);
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 1e9e99a1393..0b0618edd64 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -194,6 +194,7 @@ struct ehca_qp {
u32 packet_count;
atomic_t nr_events; /* events seen */
wait_queue_head_t wait_completion;
+ int mig_armed;
};
#define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ)
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
index bc3b37d2070..46288220cfb 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -114,7 +114,9 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
}
props->max_pkeys = 16;
- props->local_ca_ack_delay = min_t(u8, rblock->local_ca_ack_delay, 255);
+ /* Some FW versions say 0 here; insert sensible value in that case */
+ props->local_ca_ack_delay = rblock->local_ca_ack_delay ?
+ min_t(u8, rblock->local_ca_ack_delay, 255) : 12;
props->max_raw_ipv6_qp = limit_uint(rblock->max_raw_ipv6_qp);
props->max_raw_ethy_qp = limit_uint(rblock->max_raw_ethy_qp);
props->max_mcast_grp = limit_uint(rblock->max_mcast_grp);
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 0792d930c48..cb55be04442 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -178,6 +178,10 @@ static void dispatch_qp_event(struct ehca_shca *shca, struct ehca_qp *qp,
{
struct ib_event event;
+ /* PATH_MIG without the QP ever having been armed is false alarm */
+ if (event_type == IB_EVENT_PATH_MIG && !qp->mig_armed)
+ return;
+
event.device = &shca->ib_device;
event.event = event_type;
@@ -646,8 +650,8 @@ static inline int find_next_online_cpu(struct ehca_comp_pool *pool)
ehca_dmp(&cpu_online_map, sizeof(cpumask_t), "");
spin_lock_irqsave(&pool->last_cpu_lock, flags);
- cpu = next_cpu(pool->last_cpu, cpu_online_map);
- if (cpu == NR_CPUS)
+ cpu = next_cpu_nr(pool->last_cpu, cpu_online_map);
+ if (cpu >= nr_cpu_ids)
cpu = first_cpu(cpu_online_map);
pool->last_cpu = cpu;
spin_unlock_irqrestore(&pool->last_cpu_lock, flags);
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index 3f59587338e..ea13efddf17 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -1460,6 +1460,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
goto modify_qp_exit2;
}
mqpcb->path_migration_state = attr->path_mig_state + 1;
+ if (attr->path_mig_state == IB_MIG_REARM)
+ my_qp->mig_armed = 1;
update_mask |=
EHCA_BMASK_SET(MQPCB_MASK_PATH_MIGRATION_STATE, 1);
}
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.c b/drivers/infiniband/hw/ehca/ipz_pt_fn.c
index 661f8db6270..c3a32846543 100644
--- a/drivers/infiniband/hw/ehca/ipz_pt_fn.c
+++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.c
@@ -163,6 +163,7 @@ static int alloc_small_queue_page(struct ipz_queue *queue, struct ehca_pd *pd)
out:
ehca_err(pd->ib_pd.device, "failed to allocate small queue page");
+ mutex_unlock(&pd->lock);
return 0;
}
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index 35f301c88b5..56c0eda3c07 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -2455,7 +2455,7 @@ static int init_cdev(int minor, char *name, const struct file_operations *fops,
goto err_cdev;
}
- device = device_create(ipath_class, NULL, dev, name);
+ device = device_create_drvdata(ipath_class, NULL, dev, NULL, name);
if (IS_ERR(device)) {
ret = PTR_ERR(device);
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index 299f20832ab..0b191a4842c 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -637,6 +637,7 @@ repoll:
case MLX4_OPCODE_SEND_IMM:
wc->wc_flags |= IB_WC_WITH_IMM;
case MLX4_OPCODE_SEND:
+ case MLX4_OPCODE_SEND_INVAL:
wc->opcode = IB_WC_SEND;
break;
case MLX4_OPCODE_RDMA_READ:
@@ -657,6 +658,12 @@ repoll:
case MLX4_OPCODE_LSO:
wc->opcode = IB_WC_LSO;
break;
+ case MLX4_OPCODE_FMR:
+ wc->opcode = IB_WC_FAST_REG_MR;
+ break;
+ case MLX4_OPCODE_LOCAL_INVAL:
+ wc->opcode = IB_WC_LOCAL_INV;
+ break;
}
} else {
wc->byte_len = be32_to_cpu(cqe->byte_cnt);
@@ -667,6 +674,11 @@ repoll:
wc->wc_flags = IB_WC_WITH_IMM;
wc->ex.imm_data = cqe->immed_rss_invalid;
break;
+ case MLX4_RECV_OPCODE_SEND_INVAL:
+ wc->opcode = IB_WC_RECV;
+ wc->wc_flags = IB_WC_WITH_INVALIDATE;
+ wc->ex.invalidate_rkey = be32_to_cpu(cqe->immed_rss_invalid);
+ break;
case MLX4_RECV_OPCODE_SEND:
wc->opcode = IB_WC_RECV;
wc->wc_flags = 0;
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index bcf50648fa1..38d6907ab52 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -104,6 +104,12 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;
if (dev->dev->caps.max_gso_sz)
props->device_cap_flags |= IB_DEVICE_UD_TSO;
+ if (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_RESERVED_LKEY)
+ props->device_cap_flags |= IB_DEVICE_LOCAL_DMA_LKEY;
+ if ((dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_LOCAL_INV) &&
+ (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_REMOTE_INV) &&
+ (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_FAST_REG_WR))
+ props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
0xffffff;
@@ -127,6 +133,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
props->max_srq = dev->dev->caps.num_srqs - dev->dev->caps.reserved_srqs;
props->max_srq_wr = dev->dev->caps.max_srq_wqes - 1;
props->max_srq_sge = dev->dev->caps.max_srq_sge;
+ props->max_fast_reg_page_list_len = PAGE_SIZE / sizeof (u64);
props->local_ca_ack_delay = dev->dev->caps.local_ca_ack_delay;
props->atomic_cap = dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_ATOMIC ?
IB_ATOMIC_HCA : IB_ATOMIC_NONE;
@@ -565,6 +572,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
strlcpy(ibdev->ib_dev.name, "mlx4_%d", IB_DEVICE_NAME_MAX);
ibdev->ib_dev.owner = THIS_MODULE;
ibdev->ib_dev.node_type = RDMA_NODE_IB_CA;
+ ibdev->ib_dev.local_dma_lkey = dev->caps.reserved_lkey;
ibdev->ib_dev.phys_port_cnt = dev->caps.num_ports;
ibdev->ib_dev.num_comp_vectors = 1;
ibdev->ib_dev.dma_device = &dev->pdev->dev;
@@ -627,6 +635,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->ib_dev.get_dma_mr = mlx4_ib_get_dma_mr;
ibdev->ib_dev.reg_user_mr = mlx4_ib_reg_user_mr;
ibdev->ib_dev.dereg_mr = mlx4_ib_dereg_mr;
+ ibdev->ib_dev.alloc_fast_reg_mr = mlx4_ib_alloc_fast_reg_mr;
+ ibdev->ib_dev.alloc_fast_reg_page_list = mlx4_ib_alloc_fast_reg_page_list;
+ ibdev->ib_dev.free_fast_reg_page_list = mlx4_ib_free_fast_reg_page_list;
ibdev->ib_dev.attach_mcast = mlx4_ib_mcg_attach;
ibdev->ib_dev.detach_mcast = mlx4_ib_mcg_detach;
ibdev->ib_dev.process_mad = mlx4_ib_process_mad;
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index c4cf5b69eef..d26a91317d4 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -83,6 +83,11 @@ struct mlx4_ib_mr {
struct ib_umem *umem;
};
+struct mlx4_ib_fast_reg_page_list {
+ struct ib_fast_reg_page_list ibfrpl;
+ dma_addr_t map;
+};
+
struct mlx4_ib_fmr {
struct ib_fmr ibfmr;
struct mlx4_fmr mfmr;
@@ -199,6 +204,11 @@ static inline struct mlx4_ib_mr *to_mmr(struct ib_mr *ibmr)
return container_of(ibmr, struct mlx4_ib_mr, ibmr);
}
+static inline struct mlx4_ib_fast_reg_page_list *to_mfrpl(struct ib_fast_reg_page_list *ibfrpl)
+{
+ return container_of(ibfrpl, struct mlx4_ib_fast_reg_page_list, ibfrpl);
+}
+
static inline struct mlx4_ib_fmr *to_mfmr(struct ib_fmr *ibfmr)
{
return container_of(ibfmr, struct mlx4_ib_fmr, ibfmr);
@@ -239,6 +249,11 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
u64 virt_addr, int access_flags,
struct ib_udata *udata);
int mlx4_ib_dereg_mr(struct ib_mr *mr);
+struct ib_mr *mlx4_ib_alloc_fast_reg_mr(struct ib_pd *pd,
+ int max_page_list_len);
+struct ib_fast_reg_page_list *mlx4_ib_alloc_fast_reg_page_list(struct ib_device *ibdev,
+ int page_list_len);
+void mlx4_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list);
int mlx4_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period);
int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata);
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c
index 68e92485fc7..db2086faa4e 100644
--- a/drivers/infiniband/hw/mlx4/mr.c
+++ b/drivers/infiniband/hw/mlx4/mr.c
@@ -183,6 +183,76 @@ int mlx4_ib_dereg_mr(struct ib_mr *ibmr)
return 0;
}
+struct ib_mr *mlx4_ib_alloc_fast_reg_mr(struct ib_pd *pd,
+ int max_page_list_len)
+{
+ struct mlx4_ib_dev *dev = to_mdev(pd->device);
+ struct mlx4_ib_mr *mr;
+ int err;
+
+ mr = kmalloc(sizeof *mr, GFP_KERNEL);
+ if (!mr)
+ return ERR_PTR(-ENOMEM);
+
+ err = mlx4_mr_alloc(dev->dev, to_mpd(pd)->pdn, 0, 0, 0,
+ max_page_list_len, 0, &mr->mmr);
+ if (err)
+ goto err_free;
+
+ err = mlx4_mr_enable(dev->dev, &mr->mmr);
+ if (err)
+ goto err_mr;
+
+ return &mr->ibmr;
+
+err_mr:
+ mlx4_mr_free(dev->dev, &mr->mmr);
+
+err_free:
+ kfree(mr);
+ return ERR_PTR(err);
+}
+
+struct ib_fast_reg_page_list *mlx4_ib_alloc_fast_reg_page_list(struct ib_device *ibdev,
+ int page_list_len)
+{
+ struct mlx4_ib_dev *dev = to_mdev(ibdev);
+ struct mlx4_ib_fast_reg_page_list *mfrpl;
+ int size = page_list_len * sizeof (u64);
+
+ if (size > PAGE_SIZE)
+ return ERR_PTR(-EINVAL);
+
+ mfrpl = kmalloc(sizeof *mfrpl, GFP_KERNEL);
+ if (!mfrpl)
+ return ERR_PTR(-ENOMEM);
+
+ mfrpl->ibfrpl.page_list = dma_alloc_coherent(&dev->dev->pdev->dev,
+ size, &mfrpl->map,
+ GFP_KERNEL);
+ if (!mfrpl->ibfrpl.page_list)
+ goto err_free;
+
+ WARN_ON(mfrpl->map & 0x3f);
+
+ return &mfrpl->ibfrpl;
+
+err_free:
+ kfree(mfrpl);
+ return ERR_PTR(-ENOMEM);
+}
+
+void mlx4_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list)
+{
+ struct mlx4_ib_dev *dev = to_mdev(page_list->device);
+ struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(page_list);
+ int size = page_list->max_page_list_len * sizeof (u64);
+
+ dma_free_coherent(&dev->dev->pdev->dev, size, page_list->page_list,
+ mfrpl->map);
+ kfree(mfrpl);
+}
+
struct ib_fmr *mlx4_ib_fmr_alloc(struct ib_pd *pd, int acc,
struct ib_fmr_attr *fmr_attr)
{
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 89eb6cbe592..02a99bc4442 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -78,6 +78,9 @@ static const __be32 mlx4_ib_opcode[] = {
[IB_WR_RDMA_READ] = __constant_cpu_to_be32(MLX4_OPCODE_RDMA_READ),
[IB_WR_ATOMIC_CMP_AND_SWP] = __constant_cpu_to_be32(MLX4_OPCODE_ATOMIC_CS),
[IB_WR_ATOMIC_FETCH_AND_ADD] = __constant_cpu_to_be32(MLX4_OPCODE_ATOMIC_FA),
+ [IB_WR_SEND_WITH_INV] = __constant_cpu_to_be32(MLX4_OPCODE_SEND_INVAL),
+ [IB_WR_LOCAL_INV] = __constant_cpu_to_be32(MLX4_OPCODE_LOCAL_INVAL),
+ [IB_WR_FAST_REG_MR] = __constant_cpu_to_be32(MLX4_OPCODE_FMR),
};
static struct mlx4_ib_sqp *to_msqp(struct mlx4_ib_qp *mqp)
@@ -976,6 +979,10 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pdn);
context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
+ /* Set "fast registration enabled" for all kernel QPs */
+ if (!qp->ibqp.uobject)
+ context->params1 |= cpu_to_be32(1 << 11);
+
if (attr_mask & IB_QP_RNR_RETRY) {
context->params1 |= cpu_to_be32(attr->rnr_retry << 13);
optpar |= MLX4_QP_OPTPAR_RNR_RETRY;
@@ -1322,6 +1329,38 @@ static int mlx4_wq_overflow(struct mlx4_ib_wq *wq, int nreq, struct ib_cq *ib_cq
return cur + nreq >= wq->max_post;
}
+static __be32 convert_access(int acc)
+{
+ return (acc & IB_ACCESS_REMOTE_ATOMIC ? cpu_to_be32(MLX4_WQE_FMR_PERM_ATOMIC) : 0) |
+ (acc & IB_ACCESS_REMOTE_WRITE ? cpu_to_be32(MLX4_WQE_FMR_PERM_REMOTE_WRITE) : 0) |
+ (acc & IB_ACCESS_REMOTE_READ ? cpu_to_be32(MLX4_WQE_FMR_PERM_REMOTE_READ) : 0) |
+ (acc & IB_ACCESS_LOCAL_WRITE ? cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_WRITE) : 0) |
+ cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_READ);
+}
+
+static void set_fmr_seg(struct mlx4_wqe_fmr_seg *fseg, struct ib_send_wr *wr)
+{
+ struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(wr->wr.fast_reg.page_list);
+
+ fseg->flags = convert_access(wr->wr.fast_reg.access_flags);
+ fseg->mem_key = cpu_to_be32(wr->wr.fast_reg.rkey);
+ fseg->buf_list = cpu_to_be64(mfrpl->map);
+ fseg->start_addr = cpu_to_be64(wr->wr.fast_reg.iova_start);
+ fseg->reg_len = cpu_to_be64(wr->wr.fast_reg.length);
+ fseg->offset = 0; /* XXX -- is this just for ZBVA? */
+ fseg->page_size = cpu_to_be32(wr->wr.fast_reg.page_shift);
+ fseg->reserved[0] = 0;
+ fseg->reserved[1] = 0;
+}
+
+static void set_local_inv_seg(struct mlx4_wqe_local_inval_seg *iseg, u32 rkey)
+{
+ iseg->flags = 0;
+ iseg->mem_key = cpu_to_be32(rkey);
+ iseg->guest_id = 0;
+ iseg->pa = 0;
+}
+
static __always_inline void set_raddr_seg(struct mlx4_wqe_raddr_seg *rseg,
u64 remote_addr, u32 rkey)
{
@@ -1395,7 +1434,7 @@ static void __set_data_seg(struct mlx4_wqe_data_seg *dseg, struct ib_sge *sg)
dseg->addr = cpu_to_be64(sg->addr);
}
-static int build_lso_seg(struct mlx4_lso_seg *wqe, struct ib_send_wr *wr,
+static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr,
struct mlx4_ib_qp *qp, unsigned *lso_seg_len)
{
unsigned halign = ALIGN(sizeof *wqe + wr->wr.ud.hlen, 16);
@@ -1423,6 +1462,21 @@ static int build_lso_seg(struct mlx4_lso_seg *wqe, struct ib_send_wr *wr,
return 0;
}
+static __be32 send_ieth(struct ib_send_wr *wr)
+{
+ switch (wr->opcode) {
+ case IB_WR_SEND_WITH_IMM:
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ return wr->ex.imm_data;
+
+ case IB_WR_SEND_WITH_INV:
+ return cpu_to_be32(wr->ex.invalidate_rkey);
+
+ default:
+ return 0;
+ }
+}
+
int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
struct ib_send_wr **bad_wr)
{
@@ -1469,11 +1523,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
MLX4_WQE_CTRL_TCP_UDP_CSUM) : 0) |
qp->sq_signal_bits;
- if (wr->opcode == IB_WR_SEND_WITH_IMM ||
- wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
- ctrl->imm = wr->ex.imm_data;
- else
- ctrl->imm = 0;
+ ctrl->imm = send_ieth(wr);
wqe += sizeof *ctrl;
size = sizeof *ctrl / 16;
@@ -1505,6 +1555,18 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
size += sizeof (struct mlx4_wqe_raddr_seg) / 16;
break;
+ case IB_WR_LOCAL_INV:
+ set_local_inv_seg(wqe, wr->ex.invalidate_rkey);
+ wqe += sizeof (struct mlx4_wqe_local_inval_seg);
+ size += sizeof (struct mlx4_wqe_local_inval_seg) / 16;
+ break;
+
+ case IB_WR_FAST_REG_MR:
+ set_fmr_seg(wqe, wr);
+ wqe += sizeof (struct mlx4_wqe_fmr_seg);
+ size += sizeof (struct mlx4_wqe_fmr_seg) / 16;
+ break;
+
default:
/* No extra segments required for sends */
break;
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index ee4d073c889..252590116df 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -202,6 +202,7 @@ struct mthca_pd_table {
struct mthca_buddy {
unsigned long **bits;
+ int *num_free;
int max_order;
spinlock_t lock;
};
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index 8489b1e81c0..882e6b73591 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -89,23 +89,26 @@ static u32 mthca_buddy_alloc(struct mthca_buddy *buddy, int order)
spin_lock(&buddy->lock);
- for (o = order; o <= buddy->max_order; ++o) {
- m = 1 << (buddy->max_order - o);
- seg = find_first_bit(buddy->bits[o], m);
- if (seg < m)
- goto found;
- }
+ for (o = order; o <= buddy->max_order; ++o)
+ if (buddy->num_free[o]) {
+ m = 1 << (buddy->max_order - o);
+ seg = find_first_bit(buddy->bits[o], m);
+ if (seg < m)
+ goto found;
+ }
spin_unlock(&buddy->lock);
return -1;
found:
clear_bit(seg, buddy->bits[o]);
+ --buddy->num_free[o];
while (o > order) {
--o;
seg <<= 1;
set_bit(seg ^ 1, buddy->bits[o]);
+ ++buddy->num_free[o];
}
spin_unlock(&buddy->lock);
@@ -123,11 +126,13 @@ static void mthca_buddy_free(struct mthca_buddy *buddy, u32 seg, int order)
while (test_bit(seg ^ 1, buddy->bits[order])) {
clear_bit(seg ^ 1, buddy->bits[order]);
+ --buddy->num_free[order];
seg >>= 1;
++order;
}
set_bit(seg, buddy->bits[order]);
+ ++buddy->num_free[order];
spin_unlock(&buddy->lock);
}
@@ -141,7 +146,9 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
GFP_KERNEL);
- if (!buddy->bits)
+ buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof (int *),
+ GFP_KERNEL);
+ if (!buddy->bits || !buddy->num_free)
goto err_out;
for (i = 0; i <= buddy->max_order; ++i) {
@@ -154,6 +161,7 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
}
set_bit(0, buddy->bits[buddy->max_order]);
+ buddy->num_free[buddy->max_order] = 1;
return 0;
@@ -161,9 +169,10 @@ err_out_free:
for (i = 0; i <= buddy->max_order; ++i)
kfree(buddy->bits[i]);
+err_out:
kfree(buddy->bits);
+ kfree(buddy->num_free);
-err_out:
return -ENOMEM;
}
@@ -175,6 +184,7 @@ static void mthca_buddy_cleanup(struct mthca_buddy *buddy)
kfree(buddy->bits[i]);
kfree(buddy->bits);
+ kfree(buddy->num_free);
}
static u32 mthca_alloc_mtt_range(struct mthca_dev *dev, int order,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 8be9ea0436e..f51201b17bf 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -548,7 +548,7 @@ static int path_rec_start(struct net_device *dev,
path_rec_completion,
path, &path->query);
if (path->query_id < 0) {
- ipoib_warn(priv, "ib_sa_path_rec_get failed\n");
+ ipoib_warn(priv, "ib_sa_path_rec_get failed: %d\n", path->query_id);
path->query = NULL;
return path->query_id;
}
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index 3a917c1f796..63462ecca14 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -483,6 +483,7 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve
break;
case RDMA_CM_EVENT_DISCONNECTED:
case RDMA_CM_EVENT_DEVICE_REMOVAL:
+ case RDMA_CM_EVENT_ADDR_CHANGE:
iser_disconnected_handler(cma_id);
break;
default:
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index adbf29f0169..71c1971abf8 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -37,6 +37,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/semaphore.h>
#include <linux/slab.h>
#include <linux/pci_ids.h>
diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c
index 94e444b4ee1..b12b7ee4b6a 100644
--- a/drivers/input/keyboard/tosakbd.c
+++ b/drivers/input/keyboard/tosakbd.c
@@ -215,8 +215,6 @@ static int tosakbd_suspend(struct platform_device *dev, pm_message_t state)
unsigned long flags;
spin_lock_irqsave(&tosakbd->lock, flags);
- PGSR1 = (PGSR1 & ~TOSA_GPIO_LOW_STROBE_BIT);
- PGSR2 = (PGSR2 & ~TOSA_GPIO_HIGH_STROBE_BIT);
tosakbd->suspended = 1;
spin_unlock_irqrestore(&tosakbd->lock, flags);
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index 49d8abfe38f..daa9d422033 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -44,6 +44,7 @@
#include <linux/proc_fs.h>
#include <linux/poll.h>
#include <linux/rtc.h>
+#include <linux/semaphore.h>
MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
MODULE_DESCRIPTION("HP i8042 SDC + MSM-58321 RTC Driver");
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 7b233a492ad..0d395979b2d 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -67,9 +67,9 @@
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/time.h>
+#include <linux/semaphore.h>
#include <linux/slab.h>
#include <linux/hil.h>
-#include <linux/semaphore.h>
#include <asm/io.h>
#include <asm/system.h>
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 8a35029caca..871b0cbca5e 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1302,11 +1302,12 @@ static void capinc_tty_hangup(struct tty_struct *tty)
#endif
}
-static void capinc_tty_break_ctl(struct tty_struct *tty, int state)
+static int capinc_tty_break_ctl(struct tty_struct *tty, int state)
{
#ifdef _DEBUG_TTYFUNCS
printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state);
#endif
+ return 0;
}
static void capinc_tty_flush_buffer(struct tty_struct *tty)
@@ -1552,7 +1553,8 @@ static int __init capi_init(void)
return PTR_ERR(capi_class);
}
- device_create(capi_class, NULL, MKDEV(capi_major, 0), "capi");
+ device_create_drvdata(capi_class, NULL, MKDEV(capi_major, 0), NULL,
+ "capi");
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
if (capinc_tty_init() < 0) {
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index 091deb9d1c4..c2bd97d2927 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -575,7 +575,8 @@ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
else
skb = iraw_encode(skb, HW_HDR_LEN, 0);
if (!skb) {
- err("unable to allocate memory for encoding!\n");
+ dev_err(bcs->cs->dev,
+ "unable to allocate memory for encoding!\n");
return -ENOMEM;
}
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 5255b5e20e1..3f11910c7cc 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -1050,10 +1050,9 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
}
/* retrieve block of data to send */
- ifd->offset = gigaset_isowbuf_getbytes(ubc->isooutbuf,
- ifd->length);
- if (ifd->offset < 0) {
- if (ifd->offset == -EBUSY) {
+ rc = gigaset_isowbuf_getbytes(ubc->isooutbuf, ifd->length);
+ if (rc < 0) {
+ if (rc == -EBUSY) {
gig_dbg(DEBUG_ISO,
"%s: buffer busy at frame %d",
__func__, nframe);
@@ -1062,11 +1061,12 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
} else {
dev_err(ucx->bcs->cs->dev,
"%s: buffer error %d at frame %d\n",
- __func__, ifd->offset, nframe);
- return ifd->offset;
+ __func__, rc, nframe);
+ return rc;
}
break;
}
+ ifd->offset = rc;
ucx->limit = ubc->isooutbuf->nextread;
ifd->status = 0;
ifd->actual_length = 0;
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 827c32c1679..9d3ce7718e5 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -287,7 +287,7 @@ struct event_t *gigaset_add_event(struct cardstate *cs,
tail = cs->ev_tail;
next = (tail + 1) % MAX_EVENTS;
if (unlikely(next == cs->ev_head))
- err("event queue full");
+ dev_err(cs->dev, "event queue full\n");
else {
event = cs->events + tail;
event->type = type;
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index f365993161f..00375295499 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -106,7 +106,6 @@ enum debuglevel {
#undef err
#undef info
#undef warn
-#undef notice
#define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \
format "\n" , ## arg)
@@ -114,8 +113,6 @@ enum debuglevel {
format "\n" , ## arg)
#define warn(format, arg...) printk(KERN_WARNING KBUILD_MODNAME ": " \
format "\n" , ## arg)
-#define notice(format, arg...) printk(KERN_NOTICE KBUILD_MODNAME ": " \
- format "\n" , ## arg)
#ifdef CONFIG_GIGASET_DEBUG
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index 9e089f06a94..3c127a8cbaf 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -46,7 +46,8 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
return -ENODEV;
}
if (channel < 0 || channel >= cs->channels) {
- err("%s: invalid channel ID (%d)", __func__, channel);
+ dev_err(cs->dev, "%s: invalid channel ID (%d)\n",
+ __func__, channel);
return -ENODEV;
}
bcs = &cs->bcs[channel];
@@ -58,11 +59,13 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
if (!len) {
if (ack)
- notice("%s: not ACKing empty packet", __func__);
+ dev_notice(cs->dev, "%s: not ACKing empty packet\n",
+ __func__);
return 0;
}
if (len > MAX_BUF_SIZE) {
- err("%s: packet too large (%d bytes)", __func__, len);
+ dev_err(cs->dev, "%s: packet too large (%d bytes)\n",
+ __func__, len);
return -EINVAL;
}
@@ -116,8 +119,7 @@ static int command_from_LL(isdn_ctrl *cntrl)
gigaset_debugdrivers();
if (!cs) {
- warn("LL tried to access unknown device with nr. %d",
- cntrl->driver);
+ err("%s: invalid driver ID (%d)", __func__, cntrl->driver);
return -ENODEV;
}
@@ -126,7 +128,7 @@ static int command_from_LL(isdn_ctrl *cntrl)
gig_dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver: %d, arg: %ld)",
cntrl->driver, cntrl->arg);
- warn("ISDN_CMD_IOCTL is not supported.");
+ dev_warn(cs->dev, "ISDN_CMD_IOCTL not supported\n");
return -EINVAL;
case ISDN_CMD_DIAL:
@@ -138,22 +140,23 @@ static int command_from_LL(isdn_ctrl *cntrl)
cntrl->parm.setup.si1, cntrl->parm.setup.si2);
if (cntrl->arg >= cs->channels) {
- err("ISDN_CMD_DIAL: invalid channel (%d)",
- (int) cntrl->arg);
+ dev_err(cs->dev,
+ "ISDN_CMD_DIAL: invalid channel (%d)\n",
+ (int) cntrl->arg);
return -EINVAL;
}
bcs = cs->bcs + cntrl->arg;
if (!gigaset_get_channel(bcs)) {
- err("ISDN_CMD_DIAL: channel not free");
+ dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
return -EBUSY;
}
sp = kmalloc(sizeof *sp, GFP_ATOMIC);
if (!sp) {
gigaset_free_channel(bcs);
- err("ISDN_CMD_DIAL: out of memory");
+ dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n");
return -ENOMEM;
}
*sp = cntrl->parm.setup;
@@ -173,8 +176,9 @@ static int command_from_LL(isdn_ctrl *cntrl)
gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD");
if (cntrl->arg >= cs->channels) {
- err("ISDN_CMD_ACCEPTD: invalid channel (%d)",
- (int) cntrl->arg);
+ dev_err(cs->dev,
+ "ISDN_CMD_ACCEPTD: invalid channel (%d)\n",
+ (int) cntrl->arg);
return -EINVAL;
}
@@ -196,8 +200,9 @@ static int command_from_LL(isdn_ctrl *cntrl)
(int) cntrl->arg);
if (cntrl->arg >= cs->channels) {
- err("ISDN_CMD_HANGUP: invalid channel (%u)",
- (unsigned) cntrl->arg);
+ dev_err(cs->dev,
+ "ISDN_CMD_HANGUP: invalid channel (%d)\n",
+ (int) cntrl->arg);
return -EINVAL;
}
@@ -224,8 +229,9 @@ static int command_from_LL(isdn_ctrl *cntrl)
cntrl->arg & 0xff, (cntrl->arg >> 8));
if ((cntrl->arg & 0xff) >= cs->channels) {
- err("ISDN_CMD_SETL2: invalid channel (%u)",
- (unsigned) cntrl->arg & 0xff);
+ dev_err(cs->dev,
+ "ISDN_CMD_SETL2: invalid channel (%d)\n",
+ (int) cntrl->arg & 0xff);
return -EINVAL;
}
@@ -244,14 +250,16 @@ static int command_from_LL(isdn_ctrl *cntrl)
cntrl->arg & 0xff, (cntrl->arg >> 8));
if ((cntrl->arg & 0xff) >= cs->channels) {
- err("ISDN_CMD_SETL3: invalid channel (%u)",
- (unsigned) cntrl->arg & 0xff);
+ dev_err(cs->dev,
+ "ISDN_CMD_SETL3: invalid channel (%d)\n",
+ (int) cntrl->arg & 0xff);
return -EINVAL;
}
if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) {
- err("ISDN_CMD_SETL3: invalid protocol %lu",
- cntrl->arg >> 8);
+ dev_err(cs->dev,
+ "ISDN_CMD_SETL3: invalid protocol %lu\n",
+ cntrl->arg >> 8);
return -EINVAL;
}
@@ -262,8 +270,9 @@ static int command_from_LL(isdn_ctrl *cntrl)
case ISDN_CMD_ALERT:
gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME
if (cntrl->arg >= cs->channels) {
- err("ISDN_CMD_ALERT: invalid channel (%d)",
- (int) cntrl->arg);
+ dev_err(cs->dev,
+ "ISDN_CMD_ALERT: invalid channel (%d)\n",
+ (int) cntrl->arg);
return -EINVAL;
}
//bcs = cs->bcs + cntrl->arg;
@@ -295,7 +304,8 @@ static int command_from_LL(isdn_ctrl *cntrl)
gig_dbg(DEBUG_ANY, "ISDN_CMD_GETSIL");
break;
default:
- err("unknown command %d from LL", cntrl->command);
+ dev_err(cs->dev, "unknown command %d from LL\n",
+ cntrl->command);
return -EINVAL;
}
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index af195b07c19..521951a898e 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -197,7 +197,7 @@ static void if_close(struct tty_struct *tty, struct file *filp)
mutex_lock(&cs->mutex);
if (!cs->open_count)
- warn("%s: device not opened", __func__);
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
else {
if (!--cs->open_count) {
spin_lock_irqsave(&cs->lock, flags);
@@ -232,7 +232,7 @@ static int if_ioctl(struct tty_struct *tty, struct file *file,
return -ERESTARTSYS; // FIXME -EINTR?
if (!cs->open_count)
- warn("%s: device not opened", __func__);
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
else {
retval = 0;
switch (cmd) {
@@ -364,9 +364,9 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count)
return -ERESTARTSYS; // FIXME -EINTR?
if (!cs->open_count)
- warn("%s: device not opened", __func__);
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
else if (cs->mstate != MS_LOCKED) {
- warn("can't write to unlocked device");
+ dev_warn(cs->dev, "can't write to unlocked device\n");
retval = -EBUSY;
} else if (!cs->connected) {
gig_dbg(DEBUG_ANY, "can't write to unplugged device");
@@ -398,9 +398,9 @@ static int if_write_room(struct tty_struct *tty)
return -ERESTARTSYS; // FIXME -EINTR?
if (!cs->open_count)
- warn("%s: device not opened", __func__);
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
else if (cs->mstate != MS_LOCKED) {
- warn("can't write to unlocked device");
+ dev_warn(cs->dev, "can't write to unlocked device\n");
retval = -EBUSY;
} else if (!cs->connected) {
gig_dbg(DEBUG_ANY, "can't write to unplugged device");
@@ -430,9 +430,9 @@ static int if_chars_in_buffer(struct tty_struct *tty)
return -ERESTARTSYS; // FIXME -EINTR?
if (!cs->open_count)
- warn("%s: device not opened", __func__);
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
else if (cs->mstate != MS_LOCKED) {
- warn("can't write to unlocked device");
+ dev_warn(cs->dev, "can't write to unlocked device\n");
retval = -EBUSY;
} else if (!cs->connected) {
gig_dbg(DEBUG_ANY, "can't write to unplugged device");
@@ -460,7 +460,7 @@ static void if_throttle(struct tty_struct *tty)
mutex_lock(&cs->mutex);
if (!cs->open_count)
- warn("%s: device not opened", __func__);
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
else {
//FIXME
}
@@ -483,7 +483,7 @@ static void if_unthrottle(struct tty_struct *tty)
mutex_lock(&cs->mutex);
if (!cs->open_count)
- warn("%s: device not opened", __func__);
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
else {
//FIXME
}
@@ -510,7 +510,7 @@ static void if_set_termios(struct tty_struct *tty, struct ktermios *old)
mutex_lock(&cs->mutex);
if (!cs->open_count) {
- warn("%s: device not opened", __func__);
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
goto out;
}
@@ -623,7 +623,8 @@ void gigaset_if_init(struct cardstate *cs)
if (!IS_ERR(cs->tty_dev))
dev_set_drvdata(cs->tty_dev, cs);
else {
- warn("could not register device to the tty subsystem");
+ dev_warn(cs->dev,
+ "could not register device to the tty subsystem\n");
cs->tty_dev = NULL;
}
mutex_unlock(&cs->mutex);
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index 77d20ab0cd4..4661830a49d 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -498,8 +498,9 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
if (status) {
ucs->busy = 0;
- err("could not submit urb (error %d)\n",
- -status);
+ dev_err(cs->dev,
+ "could not submit urb (error %d)\n",
+ -status);
cb->len = 0; /* skip urb => remove cb+wakeup
in next loop cycle */
}
@@ -670,7 +671,7 @@ static int write_modem(struct cardstate *cs)
spin_unlock_irqrestore(&cs->lock, flags);
if (ret) {
- err("could not submit urb (error %d)\n", -ret);
+ dev_err(cs->dev, "could not submit urb (error %d)\n", -ret);
ucs->busy = 0;
}
diff --git a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h
index 2044e7173ab..cff7a635433 100644
--- a/drivers/isdn/hisax/st5481.h
+++ b/drivers/isdn/hisax/st5481.h
@@ -220,7 +220,7 @@ enum {
#define ERR(format, arg...) \
printk(KERN_ERR "%s:%s: " format "\n" , __FILE__, __func__ , ## arg)
-#define WARN(format, arg...) \
+#define WARNING(format, arg...) \
printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__, __func__ , ## arg)
#define INFO(format, arg...) \
@@ -412,7 +412,7 @@ struct st5481_adapter {
({ \
int status; \
if ((status = usb_submit_urb(urb, mem_flags)) < 0) { \
- WARN("usb_submit_urb failed,status=%d", status); \
+ WARNING("usb_submit_urb failed,status=%d", status); \
} \
status; \
})
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c
index fa64115cd7c..0074b600a0e 100644
--- a/drivers/isdn/hisax/st5481_b.c
+++ b/drivers/isdn/hisax/st5481_b.c
@@ -180,7 +180,7 @@ static void usb_b_out_complete(struct urb *urb)
DBG(4,"urb killed status %d", urb->status);
return; // Give up
default:
- WARN("urb status %d",urb->status);
+ WARNING("urb status %d",urb->status);
if (b_out->busy == 0) {
st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL);
}
@@ -372,6 +372,6 @@ void st5481_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL);
break;
default:
- WARN("pr %#x\n", pr);
+ WARNING("pr %#x\n", pr);
}
}
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
index b8c4855cc88..077991c1cd0 100644
--- a/drivers/isdn/hisax/st5481_d.c
+++ b/drivers/isdn/hisax/st5481_d.c
@@ -389,7 +389,7 @@ static void usb_d_out_complete(struct urb *urb)
DBG(1,"urb killed status %d", urb->status);
break;
default:
- WARN("urb status %d",urb->status);
+ WARNING("urb status %d",urb->status);
if (d_out->busy == 0) {
st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
}
@@ -420,7 +420,7 @@ static void dout_start_xmit(struct FsmInst *fsm, int event, void *arg)
isdnhdlc_out_init(&d_out->hdlc_state, 1, 0);
if (test_and_set_bit(buf_nr, &d_out->busy)) {
- WARN("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy);
+ WARNING("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy);
return;
}
urb = d_out->urb[buf_nr];
@@ -601,7 +601,7 @@ void st5481_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg)
FsmEvent(&adapter->d_out.fsm, EV_DOUT_START_XMIT, NULL);
break;
default:
- WARN("pr %#x\n", pr);
+ WARNING("pr %#x\n", pr);
break;
}
}
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
index 427a8b0520f..ec3c0e50766 100644
--- a/drivers/isdn/hisax/st5481_usb.c
+++ b/drivers/isdn/hisax/st5481_usb.c
@@ -66,7 +66,7 @@ static void usb_ctrl_msg(struct st5481_adapter *adapter,
struct ctrl_msg *ctrl_msg;
if ((w_index = fifo_add(&ctrl->msg_fifo.f)) < 0) {
- WARN("control msg FIFO full");
+ WARNING("control msg FIFO full");
return;
}
ctrl_msg = &ctrl->msg_fifo.data[w_index];
@@ -139,7 +139,7 @@ static void usb_ctrl_complete(struct urb *urb)
DBG(1,"urb killed status %d", urb->status);
return; // Give up
default:
- WARN("urb status %d",urb->status);
+ WARNING("urb status %d",urb->status);
break;
}
}
@@ -198,7 +198,7 @@ static void usb_int_complete(struct urb *urb)
DBG(2, "urb shutting down with status: %d", urb->status);
return;
default:
- WARN("nonzero urb status received: %d", urb->status);
+ WARNING("nonzero urb status received: %d", urb->status);
goto exit;
}
@@ -235,7 +235,7 @@ static void usb_int_complete(struct urb *urb)
exit:
status = usb_submit_urb (urb, GFP_ATOMIC);
if (status)
- WARN("usb_submit_urb failed with result %d", status);
+ WARNING("usb_submit_urb failed with result %d", status);
}
/* ======================================================================
@@ -257,7 +257,7 @@ int st5481_setup_usb(struct st5481_adapter *adapter)
DBG(2,"");
if ((status = usb_reset_configuration (dev)) < 0) {
- WARN("reset_configuration failed,status=%d",status);
+ WARNING("reset_configuration failed,status=%d",status);
return status;
}
@@ -269,7 +269,7 @@ int st5481_setup_usb(struct st5481_adapter *adapter)
// Check if the config is sane
if ( altsetting->desc.bNumEndpoints != 7 ) {
- WARN("expecting 7 got %d endpoints!", altsetting->desc.bNumEndpoints);
+ WARNING("expecting 7 got %d endpoints!", altsetting->desc.bNumEndpoints);
return -EINVAL;
}
@@ -279,7 +279,7 @@ int st5481_setup_usb(struct st5481_adapter *adapter)
// Use alternative setting 3 on interface 0 to have 2B+D
if ((status = usb_set_interface (dev, 0, 3)) < 0) {
- WARN("usb_set_interface failed,status=%d",status);
+ WARNING("usb_set_interface failed,status=%d",status);
return status;
}
@@ -497,7 +497,7 @@ static void usb_in_complete(struct urb *urb)
DBG(1,"urb killed status %d", urb->status);
return; // Give up
default:
- WARN("urb status %d",urb->status);
+ WARNING("urb status %d",urb->status);
break;
}
}
@@ -523,7 +523,7 @@ static void usb_in_complete(struct urb *urb)
DBG(4,"count=%d",status);
DBG_PACKET(0x400, in->rcvbuf, status);
if (!(skb = dev_alloc_skb(status))) {
- WARN("receive out of memory\n");
+ WARNING("receive out of memory\n");
break;
}
memcpy(skb_put(skb, status), in->rcvbuf, status);
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 86a369bc57d..9556262dda5 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -103,6 +103,14 @@ config LEDS_HP6XX
This option enables led support for the handheld
HP Jornada 620/660/680/690.
+config LEDS_PCA9532
+ tristate "LED driver for PCA9532 dimmer"
+ depends on LEDS_CLASS && I2C && INPUT && EXPERIMENTAL
+ help
+ This option enables support for NXP pca9532
+ led controller. It is generally only usefull
+ as a platform driver
+
config LEDS_GPIO
tristate "LED Support for GPIO connected LEDs"
depends on LEDS_CLASS && GENERIC_GPIO
@@ -147,6 +155,14 @@ config LEDS_CLEVO_MAIL
To compile this driver as a module, choose M here: the
module will be called leds-clevo-mail.
+config LEDS_PCA955X
+ tristate "LED Support for PCA955x I2C chips"
+ depends on LEDS_CLASS && I2C
+ help
+ This option enables support for LEDs connected to PCA955x
+ LED driver chips accessed via the I2C bus. Supported
+ devices include PCA9550, PCA9551, PCA9552, and PCA9553.
+
comment "LED Triggers"
config LEDS_TRIGGERS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 973d626f5f4..ff7982b4456 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -16,11 +16,13 @@ obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o
obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
+obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o
obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
+obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index 0f242b3f09b..f910eaffe3a 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -111,16 +111,17 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
flags);
if (led_cdev->trigger->deactivate)
led_cdev->trigger->deactivate(led_cdev);
+ led_cdev->trigger = NULL;
led_set_brightness(led_cdev, LED_OFF);
}
if (trigger) {
write_lock_irqsave(&trigger->leddev_list_lock, flags);
list_add_tail(&led_cdev->trig_list, &trigger->led_cdevs);
write_unlock_irqrestore(&trigger->leddev_list_lock, flags);
+ led_cdev->trigger = trigger;
if (trigger->activate)
trigger->activate(led_cdev);
}
- led_cdev->trigger = trigger;
}
EXPORT_SYMBOL_GPL(led_trigger_set);
diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c
index 28db6c1444e..52297c3ab24 100644
--- a/drivers/leds/leds-atmel-pwm.c
+++ b/drivers/leds/leds-atmel-pwm.c
@@ -37,7 +37,7 @@ static int __init pwmled_probe(struct platform_device *pdev)
{
const struct gpio_led_platform_data *pdata;
struct pwmled *leds;
- unsigned i;
+ int i;
int status;
pdata = pdev->dev.platform_data;
diff --git a/drivers/leds/leds-h1940.c b/drivers/leds/leds-h1940.c
index bcec4223038..73c70502168 100644
--- a/drivers/leds/leds-h1940.c
+++ b/drivers/leds/leds-h1940.c
@@ -23,7 +23,8 @@
/*
* Green led.
*/
-void h1940_greenled_set(struct led_classdev *led_dev, enum led_brightness value)
+static void h1940_greenled_set(struct led_classdev *led_dev,
+ enum led_brightness value)
{
switch (value) {
case LED_HALF:
@@ -52,7 +53,8 @@ static struct led_classdev h1940_greenled = {
/*
* Red led.
*/
-void h1940_redled_set(struct led_classdev *led_dev, enum led_brightness value)
+static void h1940_redled_set(struct led_classdev *led_dev,
+ enum led_brightness value)
{
switch (value) {
case LED_HALF:
@@ -82,7 +84,8 @@ static struct led_classdev h1940_redled = {
* Blue led.
* (it can only be blue flashing led)
*/
-void h1940_blueled_set(struct led_classdev *led_dev, enum led_brightness value)
+static void h1940_blueled_set(struct led_classdev *led_dev,
+ enum led_brightness value)
{
if (value) {
/* flashing Blue */
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c
new file mode 100644
index 00000000000..4064d4f6b33
--- /dev/null
+++ b/drivers/leds/leds-pca9532.c
@@ -0,0 +1,337 @@
+/*
+ * pca9532.c - 16-bit Led dimmer
+ *
+ * Copyright (C) 2008 Riku Voipio <riku.voipio@movial.fi>
+ *
+ * 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; version 2 of the License.
+ *
+ * Datasheet: http://www.nxp.com/acrobat/datasheets/PCA9532_3.pdf
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/mutex.h>
+#include <linux/leds-pca9532.h>
+
+static const unsigned short normal_i2c[] = { /*0x60,*/ I2C_CLIENT_END};
+I2C_CLIENT_INSMOD_1(pca9532);
+
+#define PCA9532_REG_PSC(i) (0x2+(i)*2)
+#define PCA9532_REG_PWM(i) (0x3+(i)*2)
+#define PCA9532_REG_LS0 0x6
+#define LED_REG(led) ((led>>2)+PCA9532_REG_LS0)
+#define LED_NUM(led) (led & 0x3)
+
+#define ldev_to_led(c) container_of(c, struct pca9532_led, ldev)
+
+struct pca9532_data {
+ struct i2c_client *client;
+ struct pca9532_led leds[16];
+ struct mutex update_lock;
+ struct input_dev *idev;
+ u8 pwm[2];
+ u8 psc[2];
+};
+
+static int pca9532_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int pca9532_remove(struct i2c_client *client);
+
+static const struct i2c_device_id pca9532_id[] = {
+ { "pca9532", 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, pca9532_id);
+
+static struct i2c_driver pca9532_driver = {
+ .driver = {
+ .name = "pca9532",
+ },
+ .probe = pca9532_probe,
+ .remove = pca9532_remove,
+ .id_table = pca9532_id,
+};
+
+/* We have two pwm/blinkers, but 16 possible leds to drive. Additionaly,
+ * the clever Thecus people are using one pwm to drive the beeper. So,
+ * as a compromise we average one pwm to the values requested by all
+ * leds that are not ON/OFF.
+ * */
+static int pca9532_setpwm(struct i2c_client *client, int pwm, int blink,
+ enum led_brightness value)
+{
+ int a = 0, b = 0, i = 0;
+ struct pca9532_data *data = i2c_get_clientdata(client);
+ for (i = 0; i < 16; i++) {
+ if (data->leds[i].type == PCA9532_TYPE_LED &&
+ data->leds[i].state == PCA9532_PWM0+pwm) {
+ a++;
+ b += data->leds[i].ldev.brightness;
+ }
+ }
+ if (a == 0) {
+ dev_err(&client->dev,
+ "fear of division by zero %d/%d, wanted %d\n",
+ b, a, value);
+ return -EINVAL;
+ }
+ b = b/a;
+ if (b > 0xFF)
+ return -EINVAL;
+ mutex_lock(&data->update_lock);
+ data->pwm[pwm] = b;
+ i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(pwm),
+ data->pwm[pwm]);
+ data->psc[pwm] = blink;
+ i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(pwm),
+ data->psc[pwm]);
+ mutex_unlock(&data->update_lock);
+ return 0;
+}
+
+/* Set LED routing */
+static void pca9532_setled(struct pca9532_led *led)
+{
+ struct i2c_client *client = led->client;
+ struct pca9532_data *data = i2c_get_clientdata(client);
+ char reg;
+
+ mutex_lock(&data->update_lock);
+ reg = i2c_smbus_read_byte_data(client, LED_REG(led->id));
+ /* zero led bits */
+ reg = reg & ~(0x3<<LED_NUM(led->id)*2);
+ /* set the new value */
+ reg = reg | (led->state << LED_NUM(led->id)*2);
+ i2c_smbus_write_byte_data(client, LED_REG(led->id), reg);
+ mutex_unlock(&data->update_lock);
+}
+
+static void pca9532_set_brightness(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ int err = 0;
+ struct pca9532_led *led = ldev_to_led(led_cdev);
+
+ if (value == LED_OFF)
+ led->state = PCA9532_OFF;
+ else if (value == LED_FULL)
+ led->state = PCA9532_ON;
+ else {
+ led->state = PCA9532_PWM0; /* Thecus: hardcode one pwm */
+ err = pca9532_setpwm(led->client, 0, 0, value);
+ if (err)
+ return; /* XXX: led api doesn't allow error code? */
+ }
+ pca9532_setled(led);
+}
+
+static int pca9532_set_blink(struct led_classdev *led_cdev,
+ unsigned long *delay_on, unsigned long *delay_off)
+{
+ struct pca9532_led *led = ldev_to_led(led_cdev);
+ struct i2c_client *client = led->client;
+ int psc;
+
+ if (*delay_on == 0 && *delay_off == 0) {
+ /* led subsystem ask us for a blink rate */
+ *delay_on = 1000;
+ *delay_off = 1000;
+ }
+ if (*delay_on != *delay_off || *delay_on > 1690 || *delay_on < 6)
+ return -EINVAL;
+
+ /* Thecus specific: only use PSC/PWM 0 */
+ psc = (*delay_on * 152-1)/1000;
+ return pca9532_setpwm(client, 0, psc, led_cdev->brightness);
+}
+
+int pca9532_event(struct input_dev *dev, unsigned int type, unsigned int code,
+ int value)
+{
+ struct pca9532_data *data = input_get_drvdata(dev);
+
+ if (type != EV_SND && (code != SND_BELL || code != SND_TONE))
+ return -1;
+
+ /* XXX: allow different kind of beeps with psc/pwm modifications */
+ if (value > 1 && value < 32767)
+ data->pwm[1] = 127;
+ else
+ data->pwm[1] = 0;
+
+ dev_info(&dev->dev, "setting beep to %d \n", data->pwm[1]);
+ mutex_lock(&data->update_lock);
+ i2c_smbus_write_byte_data(data->client, PCA9532_REG_PWM(1),
+ data->pwm[1]);
+ mutex_unlock(&data->update_lock);
+
+ return 0;
+}
+
+static int pca9532_configure(struct i2c_client *client,
+ struct pca9532_data *data, struct pca9532_platform_data *pdata)
+{
+ int i, err = 0;
+
+ for (i = 0; i < 2; i++) {
+ data->pwm[i] = pdata->pwm[i];
+ data->psc[i] = pdata->psc[i];
+ i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(i),
+ data->pwm[i]);
+ i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(i),
+ data->psc[i]);
+ }
+
+ for (i = 0; i < 16; i++) {
+ struct pca9532_led *led = &data->leds[i];
+ struct pca9532_led *pled = &pdata->leds[i];
+ led->client = client;
+ led->id = i;
+ led->type = pled->type;
+ switch (led->type) {
+ case PCA9532_TYPE_NONE:
+ break;
+ case PCA9532_TYPE_LED:
+ led->state = pled->state;
+ led->name = pled->name;
+ led->ldev.name = led->name;
+ led->ldev.brightness = LED_OFF;
+ led->ldev.brightness_set = pca9532_set_brightness;
+ led->ldev.blink_set = pca9532_set_blink;
+ if (led_classdev_register(&client->dev,
+ &led->ldev) < 0) {
+ dev_err(&client->dev,
+ "couldn't register LED %s\n",
+ led->name);
+ goto exit;
+ }
+ pca9532_setled(led);
+ break;
+ case PCA9532_TYPE_N2100_BEEP:
+ BUG_ON(data->idev);
+ led->state = PCA9532_PWM1;
+ pca9532_setled(led);
+ data->idev = input_allocate_device();
+ if (data->idev == NULL) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ data->idev->name = pled->name;
+ data->idev->phys = "i2c/pca9532";
+ data->idev->id.bustype = BUS_HOST;
+ data->idev->id.vendor = 0x001f;
+ data->idev->id.product = 0x0001;
+ data->idev->id.version = 0x0100;
+ data->idev->evbit[0] = BIT_MASK(EV_SND);
+ data->idev->sndbit[0] = BIT_MASK(SND_BELL) |
+ BIT_MASK(SND_TONE);
+ data->idev->event = pca9532_event;
+ input_set_drvdata(data->idev, data);
+ err = input_register_device(data->idev);
+ if (err) {
+ input_free_device(data->idev);
+ data->idev = NULL;
+ goto exit;
+ }
+ break;
+ }
+ }
+ return 0;
+
+exit:
+ if (i > 0)
+ for (i = i - 1; i >= 0; i--)
+ switch (data->leds[i].type) {
+ case PCA9532_TYPE_NONE:
+ break;
+ case PCA9532_TYPE_LED:
+ led_classdev_unregister(&data->leds[i].ldev);
+ break;
+ case PCA9532_TYPE_N2100_BEEP:
+ if (data->idev != NULL) {
+ input_unregister_device(data->idev);
+ input_free_device(data->idev);
+ data->idev = NULL;
+ }
+ break;
+ }
+
+ return err;
+
+}
+
+static int pca9532_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pca9532_data *data = i2c_get_clientdata(client);
+ struct pca9532_platform_data *pca9532_pdata = client->dev.platform_data;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA))
+ return -EIO;
+
+ data = kzalloc(sizeof(struct pca9532_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ dev_info(&client->dev, "setting platform data\n");
+ i2c_set_clientdata(client, data);
+ data->client = client;
+ mutex_init(&data->update_lock);
+
+ if (pca9532_pdata == NULL)
+ return -EIO;
+
+ pca9532_configure(client, data, pca9532_pdata);
+ return 0;
+
+}
+
+static int pca9532_remove(struct i2c_client *client)
+{
+ struct pca9532_data *data = i2c_get_clientdata(client);
+ int i;
+ for (i = 0; i < 16; i++)
+ switch (data->leds[i].type) {
+ case PCA9532_TYPE_NONE:
+ break;
+ case PCA9532_TYPE_LED:
+ led_classdev_unregister(&data->leds[i].ldev);
+ break;
+ case PCA9532_TYPE_N2100_BEEP:
+ if (data->idev != NULL) {
+ input_unregister_device(data->idev);
+ input_free_device(data->idev);
+ data->idev = NULL;
+ }
+ break;
+ }
+
+ kfree(data);
+ i2c_set_clientdata(client, NULL);
+ return 0;
+}
+
+static int __init pca9532_init(void)
+{
+ return i2c_add_driver(&pca9532_driver);
+}
+
+static void __exit pca9532_exit(void)
+{
+ i2c_del_driver(&pca9532_driver);
+}
+
+MODULE_AUTHOR("Riku Voipio <riku.voipio@movial.fi>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PCA 9532 LED dimmer");
+
+module_init(pca9532_init);
+module_exit(pca9532_exit);
+
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
new file mode 100644
index 00000000000..146c0697286
--- /dev/null
+++ b/drivers/leds/leds-pca955x.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright 2007-2008 Extreme Engineering Solutions, Inc.
+ *
+ * Author: Nate Case <ncase@xes-inc.com>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License. See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * LED driver for various PCA955x I2C LED drivers
+ *
+ * Supported devices:
+ *
+ * Device Description 7-bit slave address
+ * ------ ----------- -------------------
+ * PCA9550 2-bit driver 0x60 .. 0x61
+ * PCA9551 8-bit driver 0x60 .. 0x67
+ * PCA9552 16-bit driver 0x60 .. 0x67
+ * PCA9553/01 4-bit driver 0x62
+ * PCA9553/02 4-bit driver 0x63
+ *
+ * Philips PCA955x LED driver chips follow a register map as shown below:
+ *
+ * Control Register Description
+ * ---------------- -----------
+ * 0x0 Input register 0
+ * ..
+ * NUM_INPUT_REGS - 1 Last Input register X
+ *
+ * NUM_INPUT_REGS Frequency prescaler 0
+ * NUM_INPUT_REGS + 1 PWM register 0
+ * NUM_INPUT_REGS + 2 Frequency prescaler 1
+ * NUM_INPUT_REGS + 3 PWM register 1
+ *
+ * NUM_INPUT_REGS + 4 LED selector 0
+ * NUM_INPUT_REGS + 4
+ * + NUM_LED_REGS - 1 Last LED selector
+ *
+ * where NUM_INPUT_REGS and NUM_LED_REGS vary depending on how many
+ * bits the chip supports.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/leds.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+
+/* LED select registers determine the source that drives LED outputs */
+#define PCA955X_LS_LED_ON 0x0 /* Output LOW */
+#define PCA955X_LS_LED_OFF 0x1 /* Output HI-Z */
+#define PCA955X_LS_BLINK0 0x2 /* Blink at PWM0 rate */
+#define PCA955X_LS_BLINK1 0x3 /* Blink at PWM1 rate */
+
+enum pca955x_type {
+ pca9550,
+ pca9551,
+ pca9552,
+ pca9553,
+};
+
+struct pca955x_chipdef {
+ int bits;
+ u8 slv_addr; /* 7-bit slave address mask */
+ int slv_addr_shift; /* Number of bits to ignore */
+};
+
+static struct pca955x_chipdef pca955x_chipdefs[] = {
+ [pca9550] = {
+ .bits = 2,
+ .slv_addr = /* 110000x */ 0x60,
+ .slv_addr_shift = 1,
+ },
+ [pca9551] = {
+ .bits = 8,
+ .slv_addr = /* 1100xxx */ 0x60,
+ .slv_addr_shift = 3,
+ },
+ [pca9552] = {
+ .bits = 16,
+ .slv_addr = /* 1100xxx */ 0x60,
+ .slv_addr_shift = 3,
+ },
+ [pca9553] = {
+ .bits = 4,
+ .slv_addr = /* 110001x */ 0x62,
+ .slv_addr_shift = 1,
+ },
+};
+
+static const struct i2c_device_id pca955x_id[] = {
+ { "pca9550", pca9550 },
+ { "pca9551", pca9551 },
+ { "pca9552", pca9552 },
+ { "pca9553", pca9553 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, pca955x_id);
+
+struct pca955x_led {
+ struct pca955x_chipdef *chipdef;
+ struct i2c_client *client;
+ struct work_struct work;
+ spinlock_t lock;
+ enum led_brightness brightness;
+ struct led_classdev led_cdev;
+ int led_num; /* 0 .. 15 potentially */
+ char name[32];
+};
+
+/* 8 bits per input register */
+static inline int pca95xx_num_input_regs(int bits)
+{
+ return (bits + 7) / 8;
+}
+
+/* 4 bits per LED selector register */
+static inline int pca95xx_num_led_regs(int bits)
+{
+ return (bits + 3) / 4;
+}
+
+/*
+ * Return an LED selector register value based on an existing one, with
+ * the appropriate 2-bit state value set for the given LED number (0-3).
+ */
+static inline u8 pca955x_ledsel(u8 oldval, int led_num, int state)
+{
+ return (oldval & (~(0x3 << (led_num << 1)))) |
+ ((state & 0x3) << (led_num << 1));
+}
+
+/*
+ * Write to frequency prescaler register, used to program the
+ * period of the PWM output. period = (PSCx + 1) / 38
+ */
+static void pca955x_write_psc(struct i2c_client *client, int n, u8 val)
+{
+ struct pca955x_led *pca955x = i2c_get_clientdata(client);
+
+ i2c_smbus_write_byte_data(client,
+ pca95xx_num_input_regs(pca955x->chipdef->bits) + 2*n,
+ val);
+}
+
+/*
+ * Write to PWM register, which determines the duty cycle of the
+ * output. LED is OFF when the count is less than the value of this
+ * register, and ON when it is greater. If PWMx == 0, LED is always OFF.
+ *
+ * Duty cycle is (256 - PWMx) / 256
+ */
+static void pca955x_write_pwm(struct i2c_client *client, int n, u8 val)
+{
+ struct pca955x_led *pca955x = i2c_get_clientdata(client);
+
+ i2c_smbus_write_byte_data(client,
+ pca95xx_num_input_regs(pca955x->chipdef->bits) + 1 + 2*n,
+ val);
+}
+
+/*
+ * Write to LED selector register, which determines the source that
+ * drives the LED output.
+ */
+static void pca955x_write_ls(struct i2c_client *client, int n, u8 val)
+{
+ struct pca955x_led *pca955x = i2c_get_clientdata(client);
+
+ i2c_smbus_write_byte_data(client,
+ pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n,
+ val);
+}
+
+/*
+ * Read the LED selector register, which determines the source that
+ * drives the LED output.
+ */
+static u8 pca955x_read_ls(struct i2c_client *client, int n)
+{
+ struct pca955x_led *pca955x = i2c_get_clientdata(client);
+
+ return (u8) i2c_smbus_read_byte_data(client,
+ pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n);
+}
+
+static void pca955x_led_work(struct work_struct *work)
+{
+ struct pca955x_led *pca955x;
+ u8 ls;
+ int chip_ls; /* which LSx to use (0-3 potentially) */
+ int ls_led; /* which set of bits within LSx to use (0-3) */
+
+ pca955x = container_of(work, struct pca955x_led, work);
+ chip_ls = pca955x->led_num / 4;
+ ls_led = pca955x->led_num % 4;
+
+ ls = pca955x_read_ls(pca955x->client, chip_ls);
+
+ switch (pca955x->brightness) {
+ case LED_FULL:
+ ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_ON);
+ break;
+ case LED_OFF:
+ ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_OFF);
+ break;
+ case LED_HALF:
+ ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_BLINK0);
+ break;
+ default:
+ /*
+ * Use PWM1 for all other values. This has the unwanted
+ * side effect of making all LEDs on the chip share the
+ * same brightness level if set to a value other than
+ * OFF, HALF, or FULL. But, this is probably better than
+ * just turning off for all other values.
+ */
+ pca955x_write_pwm(pca955x->client, 1, 255-pca955x->brightness);
+ ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_BLINK1);
+ break;
+ }
+
+ pca955x_write_ls(pca955x->client, chip_ls, ls);
+}
+
+void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+ struct pca955x_led *pca955x;
+
+ pca955x = container_of(led_cdev, struct pca955x_led, led_cdev);
+
+ spin_lock(&pca955x->lock);
+ pca955x->brightness = value;
+
+ /*
+ * Must use workqueue for the actual I/O since I2C operations
+ * can sleep.
+ */
+ schedule_work(&pca955x->work);
+
+ spin_unlock(&pca955x->lock);
+}
+
+static int __devinit pca955x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pca955x_led *pca955x;
+ int i;
+ int err = -ENODEV;
+ struct pca955x_chipdef *chip;
+ struct i2c_adapter *adapter;
+ struct led_platform_data *pdata;
+
+ chip = &pca955x_chipdefs[id->driver_data];
+ adapter = to_i2c_adapter(client->dev.parent);
+ pdata = client->dev.platform_data;
+
+ /* Make sure the slave address / chip type combo given is possible */
+ if ((client->addr & ~((1 << chip->slv_addr_shift) - 1)) !=
+ chip->slv_addr) {
+ dev_err(&client->dev, "invalid slave address %02x\n",
+ client->addr);
+ return -ENODEV;
+ }
+
+ printk(KERN_INFO "leds-pca955x: Using %s %d-bit LED driver at "
+ "slave address 0x%02x\n",
+ id->name, chip->bits, client->addr);
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
+ return -EIO;
+
+ if (pdata) {
+ if (pdata->num_leds != chip->bits) {
+ dev_err(&client->dev, "board info claims %d LEDs"
+ " on a %d-bit chip\n",
+ pdata->num_leds, chip->bits);
+ return -ENODEV;
+ }
+ }
+
+ for (i = 0; i < chip->bits; i++) {
+ pca955x = kzalloc(sizeof(struct pca955x_led), GFP_KERNEL);
+ if (!pca955x) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ pca955x->chipdef = chip;
+ pca955x->client = client;
+ pca955x->led_num = i;
+ /* Platform data can specify LED names and default triggers */
+ if (pdata) {
+ if (pdata->leds[i].name)
+ snprintf(pca955x->name, 32, "pca955x:%s",
+ pdata->leds[i].name);
+ if (pdata->leds[i].default_trigger)
+ pca955x->led_cdev.default_trigger =
+ pdata->leds[i].default_trigger;
+ } else {
+ snprintf(pca955x->name, 32, "pca955x:%d", i);
+ }
+ spin_lock_init(&pca955x->lock);
+
+ pca955x->led_cdev.name = pca955x->name;
+ pca955x->led_cdev.brightness_set =
+ pca955x_led_set;
+
+ /*
+ * Client data is a pointer to the _first_ pca955x_led
+ * struct
+ */
+ if (i == 0)
+ i2c_set_clientdata(client, pca955x);
+
+ INIT_WORK(&(pca955x->work), pca955x_led_work);
+
+ led_classdev_register(&client->dev, &(pca955x->led_cdev));
+ }
+
+ /* Turn off LEDs */
+ for (i = 0; i < pca95xx_num_led_regs(chip->bits); i++)
+ pca955x_write_ls(client, i, 0x55);
+
+ /* PWM0 is used for half brightness or 50% duty cycle */
+ pca955x_write_pwm(client, 0, 255-LED_HALF);
+
+ /* PWM1 is used for variable brightness, default to OFF */
+ pca955x_write_pwm(client, 1, 0);
+
+ /* Set to fast frequency so we do not see flashing */
+ pca955x_write_psc(client, 0, 0);
+ pca955x_write_psc(client, 1, 0);
+
+ return 0;
+exit:
+ return err;
+}
+
+static int __devexit pca955x_remove(struct i2c_client *client)
+{
+ struct pca955x_led *pca955x = i2c_get_clientdata(client);
+ int leds = pca955x->chipdef->bits;
+ int i;
+
+ for (i = 0; i < leds; i++) {
+ led_classdev_unregister(&(pca955x->led_cdev));
+ cancel_work_sync(&(pca955x->work));
+ kfree(pca955x);
+ pca955x = pca955x + 1;
+ }
+
+ return 0;
+}
+
+static struct i2c_driver pca955x_driver = {
+ .driver = {
+ .name = "leds-pca955x",
+ .owner = THIS_MODULE,
+ },
+ .probe = pca955x_probe,
+ .remove = __devexit_p(pca955x_remove),
+ .id_table = pca955x_id,
+};
+
+static int __init pca955x_leds_init(void)
+{
+ return i2c_add_driver(&pca955x_driver);
+}
+
+static void __exit pca955x_leds_exit(void)
+{
+ i2c_del_driver(&pca955x_driver);
+}
+
+module_init(pca955x_leds_init);
+module_exit(pca955x_leds_exit);
+
+MODULE_AUTHOR("Nate Case <ncase@xes-inc.com>");
+MODULE_DESCRIPTION("PCA955x LED driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 1a8de57289e..37344aaee22 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -98,16 +98,20 @@ static u32 lg_get_features(struct virtio_device *vdev)
return features;
}
-static void lg_set_features(struct virtio_device *vdev, u32 features)
+static void lg_finalize_features(struct virtio_device *vdev)
{
- unsigned int i;
+ unsigned int i, bits;
struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
/* Second half of bitmap is features we accept. */
u8 *out_features = lg_features(desc) + desc->feature_len;
+ /* Give virtio_ring a chance to accept features. */
+ vring_transport_features(vdev);
+
memset(out_features, 0, desc->feature_len);
- for (i = 0; i < min(desc->feature_len * 8, 32); i++) {
- if (features & (1 << i))
+ bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8;
+ for (i = 0; i < bits; i++) {
+ if (test_bit(i, vdev->features))
out_features[i / 8] |= (1 << (i % 8));
}
}
@@ -297,7 +301,7 @@ static void lg_del_vq(struct virtqueue *vq)
/* The ops structure which hooks everything together. */
static struct virtio_config_ops lguest_config_ops = {
.get_features = lg_get_features,
- .set_features = lg_set_features,
+ .finalize_features = lg_finalize_features,
.get = lg_get,
.set = lg_set,
.get_status = lg_get_status,
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index e5d446804d3..cae52485208 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -862,7 +862,8 @@ adbdev_init(void)
adb_dev_class = class_create(THIS_MODULE, "adb");
if (IS_ERR(adb_dev_class))
return;
- device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), "adb");
+ device_create_drvdata(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL,
+ "adb");
platform_device_register(&adb_pfdev);
platform_driver_probe(&adb_pfdrv, adb_dummy_probe);
diff --git a/drivers/mca/mca-bus.c b/drivers/mca/mca-bus.c
index 67b8e9453b1..ef2dbfe7471 100644
--- a/drivers/mca/mca-bus.c
+++ b/drivers/mca/mca-bus.c
@@ -40,7 +40,7 @@ static struct mca_bus *mca_root_busses[MAX_MCA_BUSSES];
struct mca_device_info {
short pos_id; /* the 2 byte pos id for this card */
- char name[DEVICE_NAME_SIZE];
+ char name[50];
};
static int mca_bus_match (struct device *dev, struct device_driver *drv)
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index e208a60c048..e7132770a3b 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -233,9 +233,9 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
mutex_unlock(&dvbdev_register_lock);
- clsdev = device_create(dvb_class, adap->device,
+ clsdev = device_create_drvdata(dvb_class, adap->device,
MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
- "dvb%d.%s%d", adap->num, dnames[type], id);
+ NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
if (IS_ERR(clsdev)) {
printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
__func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c
index 6ec4bf81fc7..77b3c338506 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c
@@ -20,6 +20,7 @@
#include <linux/kthread.h>
#include <linux/freezer.h>
+#include <linux/mm.h>
#include "dvbdev.h"
#include "pvrusb2-debug.h"
#include "pvrusb2-hdw-internal.h"
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
index 05a1376405e..b4824782d85 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ioread.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
@@ -22,6 +22,7 @@
#include "pvrusb2-debug.h"
#include <linux/errno.h>
#include <linux/string.h>
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
index 7388d0cee3d..5646a6a3293 100644
--- a/drivers/media/video/uvc/uvc_queue.c
+++ b/drivers/media/video/uvc/uvc_queue.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/version.h>
+#include <linux/mm.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/usb.h>
diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c
index 0a88c44ace0..b7b05842cf2 100644
--- a/drivers/media/video/videobuf-core.c
+++ b/drivers/media/video/videobuf-core.c
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c
index a054668eda1..4e3bfbcdf15 100644
--- a/drivers/memstick/host/jmb38x_ms.c
+++ b/drivers/memstick/host/jmb38x_ms.c
@@ -51,7 +51,7 @@ struct jmb38x_ms_host {
void __iomem *addr;
spinlock_t lock;
int id;
- char host_id[DEVICE_ID_SIZE];
+ char host_id[32];
int irq;
unsigned int block_pos;
unsigned long timeout_jiffies;
@@ -781,7 +781,7 @@ static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt)
spin_lock_init(&host->lock);
host->id = cnt;
- snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d",
+ snprintf(host->host_id, sizeof(host->host_id), DRIVER_NAME ":slot%d",
host->id);
host->irq = jm->pdev->irq;
host->timeout_jiffies = msecs_to_jiffies(1000);
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 75e599b85b6..34402c47027 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -1670,7 +1670,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work);
spin_lock_init(&ioc->fault_reset_work_lock);
- snprintf(ioc->reset_work_q_name, KOBJ_NAME_LEN, "mpt_poll_%d", ioc->id);
+ snprintf(ioc->reset_work_q_name, sizeof(ioc->reset_work_q_name),
+ "mpt_poll_%d", ioc->id);
ioc->reset_work_q =
create_singlethread_workqueue(ioc->reset_work_q_name);
if (!ioc->reset_work_q) {
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 6adab648dbb..dff048cfa10 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -707,12 +707,12 @@ typedef struct _MPT_ADAPTER
u8 fc_link_speed[2];
spinlock_t fc_rescan_work_lock;
struct work_struct fc_rescan_work;
- char fc_rescan_work_q_name[KOBJ_NAME_LEN];
+ char fc_rescan_work_q_name[20];
struct workqueue_struct *fc_rescan_work_q;
struct scsi_cmnd **ScsiLookup;
spinlock_t scsi_lookup_lock;
- char reset_work_q_name[KOBJ_NAME_LEN];
+ char reset_work_q_name[20];
struct workqueue_struct *reset_work_q;
struct delayed_work fault_reset_work;
spinlock_t fault_reset_work_lock;
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index fc31ca6829d..b36cae9ec6d 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -1326,8 +1326,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* initialize workqueue */
- snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d",
- sh->host_no);
+ snprintf(ioc->fc_rescan_work_q_name, sizeof(ioc->fc_rescan_work_q_name),
+ "mptfc_wq_%d", sh->host_no);
ioc->fc_rescan_work_q =
create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
if (!ioc->fc_rescan_work_q)
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index 489d7c5c496..8774c670e66 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -243,29 +243,41 @@ static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry)
/* create user entries for this device */
tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
- if (tmp && (tmp != i2o_dev))
- sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
- "user");
+ if (tmp && (tmp != i2o_dev)) {
+ rc = sysfs_create_link(&i2o_dev->device.kobj,
+ &tmp->device.kobj, "user");
+ if (rc)
+ goto unreg_dev;
+ }
/* create user entries refering to this device */
list_for_each_entry(tmp, &c->devices, list)
if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
- && (tmp != i2o_dev))
- sysfs_create_link(&tmp->device.kobj,
- &i2o_dev->device.kobj, "user");
+ && (tmp != i2o_dev)) {
+ rc = sysfs_create_link(&tmp->device.kobj,
+ &i2o_dev->device.kobj, "user");
+ if (rc)
+ goto rmlink1;
+ }
/* create parent entries for this device */
tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
- if (tmp && (tmp != i2o_dev))
- sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
- "parent");
+ if (tmp && (tmp != i2o_dev)) {
+ rc = sysfs_create_link(&i2o_dev->device.kobj,
+ &tmp->device.kobj, "parent");
+ if (rc)
+ goto rmlink1;
+ }
/* create parent entries refering to this device */
list_for_each_entry(tmp, &c->devices, list)
if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
- && (tmp != i2o_dev))
- sysfs_create_link(&tmp->device.kobj,
- &i2o_dev->device.kobj, "parent");
+ && (tmp != i2o_dev)) {
+ rc = sysfs_create_link(&tmp->device.kobj,
+ &i2o_dev->device.kobj, "parent");
+ if (rc)
+ goto rmlink2;
+ }
i2o_driver_notify_device_add_all(i2o_dev);
@@ -273,6 +285,24 @@ static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry)
return 0;
+rmlink2:
+ /* If link creating failed halfway, we loop whole list to cleanup.
+ * And we don't care wrong removing of link, because sysfs_remove_link
+ * will take care of it.
+ */
+ list_for_each_entry(tmp, &c->devices, list) {
+ if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+ sysfs_remove_link(&tmp->device.kobj, "parent");
+ }
+ sysfs_remove_link(&i2o_dev->device.kobj, "parent");
+rmlink1:
+ list_for_each_entry(tmp, &c->devices, list)
+ if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+ sysfs_remove_link(&tmp->device.kobj, "user");
+ sysfs_remove_link(&i2o_dev->device.kobj, "user");
+unreg_dev:
+ list_del(&i2o_dev->list);
+ device_unregister(&i2o_dev->device);
err:
kfree(i2o_dev);
return rc;
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 260bade0a5e..883e7ea31de 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -5,6 +5,10 @@
menu "Multifunction device drivers"
depends on HAS_IOMEM
+config MFD_CORE
+ tristate
+ default n
+
config MFD_SM501
tristate "Support for Silicon Motion SM501"
---help---
@@ -15,6 +19,14 @@ config MFD_SM501
interface. The device may be connected by PCI or local bus with
varying functions enabled.
+config MFD_SM501_GPIO
+ bool "Export GPIO via GPIO layer"
+ depends on MFD_SM501 && HAVE_GPIO_LIB
+ ---help---
+ This option uses the gpio library layer to export the 64 GPIO
+ lines on the SM501. The platform data is used to supply the
+ base number for the first GPIO line to register.
+
config MFD_ASIC3
bool "Support for Compaq ASIC3"
depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM
@@ -24,7 +36,7 @@ config MFD_ASIC3
config HTC_EGPIO
bool "HTC EGPIO support"
- depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM
+ depends on GENERIC_HARDIRQS && GPIOLIB && ARM
help
This driver supports the CPLD egpio chip present on
several HTC phones. It provides basic support for input
@@ -38,6 +50,13 @@ config HTC_PASIC3
HTC Magician devices, respectively. Actual functionality is
handled by the leds-pasic3 and ds1wm drivers.
+config MFD_TC6393XB
+ bool "Support Toshiba TC6393XB"
+ depends on GPIOLIB && ARM
+ select MFD_CORE
+ help
+ Support for Toshiba Mobile IO Controller TC6393XB
+
endmenu
menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index eef4e26807d..33daa2f45dd 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -8,6 +8,10 @@ obj-$(CONFIG_MFD_ASIC3) += asic3.o
obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
+obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o
+
+obj-$(CONFIG_MFD_CORE) += mfd-core.o
+
obj-$(CONFIG_MCP) += mcp-core.o
obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c
index 8872cc07751..6be43172dc6 100644
--- a/drivers/mfd/htc-egpio.c
+++ b/drivers/mfd/htc-egpio.c
@@ -318,6 +318,8 @@ static int __init egpio_probe(struct platform_device *pdev)
ei->chip[i].dev = &(pdev->dev);
chip = &(ei->chip[i].chip);
chip->label = "htc-egpio";
+ chip->dev = &pdev->dev;
+ chip->owner = THIS_MODULE;
chip->get = egpio_get;
chip->set = egpio_set;
chip->direction_input = egpio_direction_input;
diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c
index 633cbba072f..91b294dcc13 100644
--- a/drivers/mfd/htc-pasic3.c
+++ b/drivers/mfd/htc-pasic3.c
@@ -238,6 +238,8 @@ static int pasic3_remove(struct platform_device *pdev)
return 0;
}
+MODULE_ALIAS("platform:pasic3");
+
static struct platform_driver pasic3_driver = {
.driver = {
.name = "pasic3",
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
index 1eab7cffcea..b5272b5ce3f 100644
--- a/drivers/mfd/mcp-sa11x0.c
+++ b/drivers/mfd/mcp-sa11x0.c
@@ -242,6 +242,8 @@ static int mcp_sa11x0_resume(struct platform_device *dev)
/*
* The driver for the SA11x0 MCP port.
*/
+MODULE_ALIAS("platform:sa11x0-mcp");
+
static struct platform_driver mcp_sa11x0_driver = {
.probe = mcp_sa11x0_probe,
.remove = mcp_sa11x0_remove,
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
new file mode 100644
index 00000000000..0454be4266c
--- /dev/null
+++ b/drivers/mfd/mfd-core.c
@@ -0,0 +1,114 @@
+/*
+ * drivers/mfd/mfd-core.c
+ *
+ * core MFD support
+ * Copyright (c) 2006 Ian Molton
+ * Copyright (c) 2007,2008 Dmitry Baryshkov
+ *
+ * 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/platform_device.h>
+#include <linux/mfd/core.h>
+
+static int mfd_add_device(struct platform_device *parent,
+ const struct mfd_cell *cell,
+ struct resource *mem_base,
+ int irq_base)
+{
+ struct resource res[cell->num_resources];
+ struct platform_device *pdev;
+ int ret = -ENOMEM;
+ int r;
+
+ pdev = platform_device_alloc(cell->name, parent->id);
+ if (!pdev)
+ goto fail_alloc;
+
+ pdev->dev.parent = &parent->dev;
+
+ ret = platform_device_add_data(pdev,
+ cell, sizeof(struct mfd_cell));
+ if (ret)
+ goto fail_device;
+
+ memset(res, 0, sizeof(res));
+ for (r = 0; r < cell->num_resources; r++) {
+ res[r].name = cell->resources[r].name;
+ res[r].flags = cell->resources[r].flags;
+
+ /* Find out base to use */
+ if (cell->resources[r].flags & IORESOURCE_MEM) {
+ res[r].parent = mem_base;
+ res[r].start = mem_base->start +
+ cell->resources[r].start;
+ res[r].end = mem_base->start +
+ cell->resources[r].end;
+ } else if (cell->resources[r].flags & IORESOURCE_IRQ) {
+ res[r].start = irq_base +
+ cell->resources[r].start;
+ res[r].end = irq_base +
+ cell->resources[r].end;
+ } else {
+ res[r].parent = cell->resources[r].parent;
+ res[r].start = cell->resources[r].start;
+ res[r].end = cell->resources[r].end;
+ }
+ }
+
+ platform_device_add_resources(pdev, res, cell->num_resources);
+
+ ret = platform_device_add(pdev);
+ if (ret)
+ goto fail_device;
+
+ return 0;
+
+/* platform_device_del(pdev); */
+fail_device:
+ platform_device_put(pdev);
+fail_alloc:
+ return ret;
+}
+
+int mfd_add_devices(
+ struct platform_device *parent,
+ const struct mfd_cell *cells, int n_devs,
+ struct resource *mem_base,
+ int irq_base)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < n_devs; i++) {
+ ret = mfd_add_device(parent, cells + i, mem_base, irq_base);
+ if (ret)
+ break;
+ }
+
+ if (ret)
+ mfd_remove_devices(parent);
+
+ return ret;
+}
+EXPORT_SYMBOL(mfd_add_devices);
+
+static int mfd_remove_devices_fn(struct device *dev, void *unused)
+{
+ platform_device_unregister(
+ container_of(dev, struct platform_device, dev));
+ return 0;
+}
+
+void mfd_remove_devices(struct platform_device *parent)
+{
+ device_for_each_child(&parent->dev, NULL, mfd_remove_devices_fn);
+}
+EXPORT_SYMBOL(mfd_remove_devices);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov");
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 2fe64734d8a..7aebad4c06f 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -19,6 +19,7 @@
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/pci.h>
+#include <linux/i2c-gpio.h>
#include <linux/sm501.h>
#include <linux/sm501-regs.h>
@@ -31,10 +32,37 @@ struct sm501_device {
struct platform_device pdev;
};
+struct sm501_gpio;
+
+#ifdef CONFIG_MFD_SM501_GPIO
+#include <linux/gpio.h>
+
+struct sm501_gpio_chip {
+ struct gpio_chip gpio;
+ struct sm501_gpio *ourgpio; /* to get back to parent. */
+ void __iomem *regbase;
+};
+
+struct sm501_gpio {
+ struct sm501_gpio_chip low;
+ struct sm501_gpio_chip high;
+ spinlock_t lock;
+
+ unsigned int registered : 1;
+ void __iomem *regs;
+ struct resource *regs_res;
+};
+#else
+struct sm501_gpio {
+ /* no gpio support, empty definition for sm501_devdata. */
+};
+#endif
+
struct sm501_devdata {
spinlock_t reg_lock;
struct mutex clock_lock;
struct list_head devices;
+ struct sm501_gpio gpio;
struct device *dev;
struct resource *io_res;
@@ -42,6 +70,7 @@ struct sm501_devdata {
struct resource *regs_claim;
struct sm501_platdata *platdata;
+
unsigned int in_suspend;
unsigned long pm_misc;
@@ -52,6 +81,7 @@ struct sm501_devdata {
unsigned int rev;
};
+
#define MHZ (1000 * 1000)
#ifdef DEBUG
@@ -276,58 +306,6 @@ unsigned long sm501_modify_reg(struct device *dev,
EXPORT_SYMBOL_GPL(sm501_modify_reg);
-unsigned long sm501_gpio_get(struct device *dev,
- unsigned long gpio)
-{
- struct sm501_devdata *sm = dev_get_drvdata(dev);
- unsigned long result;
- unsigned long reg;
-
- reg = (gpio > 32) ? SM501_GPIO_DATA_HIGH : SM501_GPIO_DATA_LOW;
- result = readl(sm->regs + reg);
-
- result >>= (gpio & 31);
- return result & 1UL;
-}
-
-EXPORT_SYMBOL_GPL(sm501_gpio_get);
-
-void sm501_gpio_set(struct device *dev,
- unsigned long gpio,
- unsigned int to,
- unsigned int dir)
-{
- struct sm501_devdata *sm = dev_get_drvdata(dev);
-
- unsigned long bit = 1 << (gpio & 31);
- unsigned long base;
- unsigned long save;
- unsigned long val;
-
- base = (gpio > 32) ? SM501_GPIO_DATA_HIGH : SM501_GPIO_DATA_LOW;
- base += SM501_GPIO;
-
- spin_lock_irqsave(&sm->reg_lock, save);
-
- val = readl(sm->regs + base) & ~bit;
- if (to)
- val |= bit;
- writel(val, sm->regs + base);
-
- val = readl(sm->regs + SM501_GPIO_DDR_LOW) & ~bit;
- if (dir)
- val |= bit;
-
- writel(val, sm->regs + SM501_GPIO_DDR_LOW);
- sm501_sync_regs(sm);
-
- spin_unlock_irqrestore(&sm->reg_lock, save);
-
-}
-
-EXPORT_SYMBOL_GPL(sm501_gpio_set);
-
-
/* sm501_unit_power
*
* alters the power active gate to set specific units on or off
@@ -906,6 +884,313 @@ static int sm501_register_display(struct sm501_devdata *sm,
return sm501_register_device(sm, pdev);
}
+#ifdef CONFIG_MFD_SM501_GPIO
+
+static inline struct sm501_gpio_chip *to_sm501_gpio(struct gpio_chip *gc)
+{
+ return container_of(gc, struct sm501_gpio_chip, gpio);
+}
+
+static inline struct sm501_devdata *sm501_gpio_to_dev(struct sm501_gpio *gpio)
+{
+ return container_of(gpio, struct sm501_devdata, gpio);
+}
+
+static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset)
+
+{
+ struct sm501_gpio_chip *smgpio = to_sm501_gpio(chip);
+ unsigned long result;
+
+ result = readl(smgpio->regbase + SM501_GPIO_DATA_LOW);
+ result >>= offset;
+
+ return result & 1UL;
+}
+
+static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+
+{
+ struct sm501_gpio_chip *smchip = to_sm501_gpio(chip);
+ struct sm501_gpio *smgpio = smchip->ourgpio;
+ unsigned long bit = 1 << offset;
+ void __iomem *regs = smchip->regbase;
+ unsigned long save;
+ unsigned long val;
+
+ dev_dbg(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d)\n",
+ __func__, chip, offset);
+
+ spin_lock_irqsave(&smgpio->lock, save);
+
+ val = readl(regs + SM501_GPIO_DATA_LOW) & ~bit;
+ if (value)
+ val |= bit;
+ writel(val, regs);
+
+ sm501_sync_regs(sm501_gpio_to_dev(smgpio));
+ spin_unlock_irqrestore(&smgpio->lock, save);
+}
+
+static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct sm501_gpio_chip *smchip = to_sm501_gpio(chip);
+ struct sm501_gpio *smgpio = smchip->ourgpio;
+ void __iomem *regs = smchip->regbase;
+ unsigned long bit = 1 << offset;
+ unsigned long save;
+ unsigned long ddr;
+
+ dev_info(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d)\n",
+ __func__, chip, offset);
+
+ spin_lock_irqsave(&smgpio->lock, save);
+
+ ddr = readl(regs + SM501_GPIO_DDR_LOW);
+ writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW);
+
+ sm501_sync_regs(sm501_gpio_to_dev(smgpio));
+ spin_unlock_irqrestore(&smgpio->lock, save);
+
+ return 0;
+}
+
+static int sm501_gpio_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct sm501_gpio_chip *smchip = to_sm501_gpio(chip);
+ struct sm501_gpio *smgpio = smchip->ourgpio;
+ unsigned long bit = 1 << offset;
+ void __iomem *regs = smchip->regbase;
+ unsigned long save;
+ unsigned long val;
+ unsigned long ddr;
+
+ dev_dbg(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d,%d)\n",
+ __func__, chip, offset, value);
+
+ spin_lock_irqsave(&smgpio->lock, save);
+
+ val = readl(regs + SM501_GPIO_DATA_LOW);
+ if (value)
+ val |= bit;
+ else
+ val &= ~bit;
+ writel(val, regs);
+
+ ddr = readl(regs + SM501_GPIO_DDR_LOW);
+ writel(ddr | bit, regs + SM501_GPIO_DDR_LOW);
+
+ sm501_sync_regs(sm501_gpio_to_dev(smgpio));
+ writel(val, regs + SM501_GPIO_DATA_LOW);
+
+ sm501_sync_regs(sm501_gpio_to_dev(smgpio));
+ spin_unlock_irqrestore(&smgpio->lock, save);
+
+ return 0;
+}
+
+static struct gpio_chip gpio_chip_template = {
+ .ngpio = 32,
+ .direction_input = sm501_gpio_input,
+ .direction_output = sm501_gpio_output,
+ .set = sm501_gpio_set,
+ .get = sm501_gpio_get,
+};
+
+static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm,
+ struct sm501_gpio *gpio,
+ struct sm501_gpio_chip *chip)
+{
+ struct sm501_platdata *pdata = sm->platdata;
+ struct gpio_chip *gchip = &chip->gpio;
+ int base = pdata->gpio_base;
+
+ chip->gpio = gpio_chip_template;
+
+ if (chip == &gpio->high) {
+ if (base > 0)
+ base += 32;
+ chip->regbase = gpio->regs + SM501_GPIO_DATA_HIGH;
+ gchip->label = "SM501-HIGH";
+ } else {
+ chip->regbase = gpio->regs + SM501_GPIO_DATA_LOW;
+ gchip->label = "SM501-LOW";
+ }
+
+ gchip->base = base;
+ chip->ourgpio = gpio;
+
+ return gpiochip_add(gchip);
+}
+
+static int sm501_register_gpio(struct sm501_devdata *sm)
+{
+ struct sm501_gpio *gpio = &sm->gpio;
+ resource_size_t iobase = sm->io_res->start + SM501_GPIO;
+ int ret;
+ int tmp;
+
+ dev_dbg(sm->dev, "registering gpio block %08llx\n",
+ (unsigned long long)iobase);
+
+ spin_lock_init(&gpio->lock);
+
+ gpio->regs_res = request_mem_region(iobase, 0x20, "sm501-gpio");
+ if (gpio->regs_res == NULL) {
+ dev_err(sm->dev, "gpio: failed to request region\n");
+ return -ENXIO;
+ }
+
+ gpio->regs = ioremap(iobase, 0x20);
+ if (gpio->regs == NULL) {
+ dev_err(sm->dev, "gpio: failed to remap registers\n");
+ ret = -ENXIO;
+ goto err_claimed;
+ }
+
+ /* Register both our chips. */
+
+ ret = sm501_gpio_register_chip(sm, gpio, &gpio->low);
+ if (ret) {
+ dev_err(sm->dev, "failed to add low chip\n");
+ goto err_mapped;
+ }
+
+ ret = sm501_gpio_register_chip(sm, gpio, &gpio->high);
+ if (ret) {
+ dev_err(sm->dev, "failed to add high chip\n");
+ goto err_low_chip;
+ }
+
+ gpio->registered = 1;
+
+ return 0;
+
+ err_low_chip:
+ tmp = gpiochip_remove(&gpio->low.gpio);
+ if (tmp) {
+ dev_err(sm->dev, "cannot remove low chip, cannot tidy up\n");
+ return ret;
+ }
+
+ err_mapped:
+ iounmap(gpio->regs);
+
+ err_claimed:
+ release_resource(gpio->regs_res);
+ kfree(gpio->regs_res);
+
+ return ret;
+}
+
+static void sm501_gpio_remove(struct sm501_devdata *sm)
+{
+ struct sm501_gpio *gpio = &sm->gpio;
+ int ret;
+
+ if (!sm->gpio.registered)
+ return;
+
+ ret = gpiochip_remove(&gpio->low.gpio);
+ if (ret)
+ dev_err(sm->dev, "cannot remove low chip, cannot tidy up\n");
+
+ ret = gpiochip_remove(&gpio->high.gpio);
+ if (ret)
+ dev_err(sm->dev, "cannot remove high chip, cannot tidy up\n");
+
+ iounmap(gpio->regs);
+ release_resource(gpio->regs_res);
+ kfree(gpio->regs_res);
+}
+
+static inline int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin)
+{
+ struct sm501_gpio *gpio = &sm->gpio;
+ int base = (pin < 32) ? gpio->low.gpio.base : gpio->high.gpio.base;
+
+ return (pin % 32) + base;
+}
+
+static inline int sm501_gpio_isregistered(struct sm501_devdata *sm)
+{
+ return sm->gpio.registered;
+}
+#else
+static inline int sm501_register_gpio(struct sm501_devdata *sm)
+{
+ return 0;
+}
+
+static inline void sm501_gpio_remove(struct sm501_devdata *sm)
+{
+}
+
+static inline int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin)
+{
+ return -1;
+}
+
+static inline int sm501_gpio_isregistered(struct sm501_devdata *sm)
+{
+ return 0;
+}
+#endif
+
+static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm,
+ struct sm501_platdata_gpio_i2c *iic)
+{
+ struct i2c_gpio_platform_data *icd;
+ struct platform_device *pdev;
+
+ pdev = sm501_create_subdev(sm, "i2c-gpio", 0,
+ sizeof(struct i2c_gpio_platform_data));
+ if (!pdev)
+ return -ENOMEM;
+
+ icd = pdev->dev.platform_data;
+
+ /* We keep the pin_sda and pin_scl fields relative in case the
+ * same platform data is passed to >1 SM501.
+ */
+
+ icd->sda_pin = sm501_gpio_pin2nr(sm, iic->pin_sda);
+ icd->scl_pin = sm501_gpio_pin2nr(sm, iic->pin_scl);
+ icd->timeout = iic->timeout;
+ icd->udelay = iic->udelay;
+
+ /* note, we can't use either of the pin numbers, as the i2c-gpio
+ * driver uses the platform.id field to generate the bus number
+ * to register with the i2c core; The i2c core doesn't have enough
+ * entries to deal with anything we currently use.
+ */
+
+ pdev->id = iic->bus_num;
+
+ dev_info(sm->dev, "registering i2c-%d: sda=%d (%d), scl=%d (%d)\n",
+ iic->bus_num,
+ icd->sda_pin, iic->pin_sda, icd->scl_pin, iic->pin_scl);
+
+ return sm501_register_device(sm, pdev);
+}
+
+static int sm501_register_gpio_i2c(struct sm501_devdata *sm,
+ struct sm501_platdata *pdata)
+{
+ struct sm501_platdata_gpio_i2c *iic = pdata->gpio_i2c;
+ int index;
+ int ret;
+
+ for (index = 0; index < pdata->gpio_i2c_nr; index++, iic++) {
+ ret = sm501_register_gpio_i2c_instance(sm, iic);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
/* sm501_dbg_regs
*
* Debug attribute to attach to parent device to show core registers
@@ -1013,6 +1298,7 @@ static unsigned int sm501_mem_local[] = {
static int sm501_init_dev(struct sm501_devdata *sm)
{
struct sm501_initdata *idata;
+ struct sm501_platdata *pdata;
resource_size_t mem_avail;
unsigned long dramctrl;
unsigned long devid;
@@ -1051,7 +1337,9 @@ static int sm501_init_dev(struct sm501_devdata *sm)
/* check to see if we have some device initialisation */
- idata = sm->platdata ? sm->platdata->init : NULL;
+ pdata = sm->platdata;
+ idata = pdata ? pdata->init : NULL;
+
if (idata) {
sm501_init_regs(sm, idata);
@@ -1059,6 +1347,15 @@ static int sm501_init_dev(struct sm501_devdata *sm)
sm501_register_usbhost(sm, &mem_avail);
if (idata->devices & (SM501_USE_UART0 | SM501_USE_UART1))
sm501_register_uart(sm, idata->devices);
+ if (idata->devices & SM501_USE_GPIO)
+ sm501_register_gpio(sm);
+ }
+
+ if (pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
+ if (!sm501_gpio_isregistered(sm))
+ dev_err(sm->dev, "no gpio available for i2c gpio.\n");
+ else
+ sm501_register_gpio_i2c(sm, pdata);
}
ret = sm501_check_clocks(sm);
@@ -1138,8 +1435,31 @@ static int sm501_plat_probe(struct platform_device *dev)
}
#ifdef CONFIG_PM
+
/* power management support */
+static void sm501_set_power(struct sm501_devdata *sm, int on)
+{
+ struct sm501_platdata *pd = sm->platdata;
+
+ if (pd == NULL)
+ return;
+
+ if (pd->get_power) {
+ if (pd->get_power(sm->dev) == on) {
+ dev_dbg(sm->dev, "is already %d\n", on);
+ return;
+ }
+ }
+
+ if (pd->set_power) {
+ dev_dbg(sm->dev, "setting power to %d\n", on);
+
+ pd->set_power(sm->dev, on);
+ sm501_mdelay(sm, 10);
+ }
+}
+
static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state)
{
struct sm501_devdata *sm = platform_get_drvdata(pdev);
@@ -1148,6 +1468,12 @@ static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state)
sm->pm_misc = readl(sm->regs + SM501_MISC_CONTROL);
sm501_dump_regs(sm);
+
+ if (sm->platdata) {
+ if (sm->platdata->flags & SM501_FLAG_SUSPEND_OFF)
+ sm501_set_power(sm, 0);
+ }
+
return 0;
}
@@ -1155,6 +1481,8 @@ static int sm501_plat_resume(struct platform_device *pdev)
{
struct sm501_devdata *sm = platform_get_drvdata(pdev);
+ sm501_set_power(sm, 1);
+
sm501_dump_regs(sm);
sm501_dump_gate(sm);
sm501_dump_clk(sm);
@@ -1229,6 +1557,7 @@ static struct sm501_platdata_fb sm501_fb_pdata = {
static struct sm501_platdata sm501_pci_platdata = {
.init = &sm501_pci_initdata,
.fb = &sm501_fb_pdata,
+ .gpio_base = -1,
};
static int sm501_pci_probe(struct pci_dev *dev,
@@ -1335,6 +1664,8 @@ static void sm501_dev_remove(struct sm501_devdata *sm)
sm501_remove_sub(sm, smdev);
device_remove_file(sm->dev, &dev_attr_dbg_regs);
+
+ sm501_gpio_remove(sm);
}
static void sm501_pci_remove(struct pci_dev *dev)
@@ -1378,6 +1709,8 @@ static struct pci_driver sm501_pci_drv = {
.remove = sm501_pci_remove,
};
+MODULE_ALIAS("platform:sm501");
+
static struct platform_driver sm501_plat_drv = {
.driver = {
.name = "sm501",
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
new file mode 100644
index 00000000000..2d87501b6fd
--- /dev/null
+++ b/drivers/mfd/tc6393xb.c
@@ -0,0 +1,600 @@
+/*
+ * Toshiba TC6393XB SoC support
+ *
+ * Copyright(c) 2005-2006 Chris Humbert
+ * Copyright(c) 2005 Dirk Opfer
+ * Copyright(c) 2005 Ian Molton <spyro@f2s.com>
+ * Copyright(c) 2007 Dmitry Baryshkov
+ *
+ * Based on code written by Sharp/Lineo for 2.4 kernels
+ * Based on locomo.c
+ *
+ * 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/module.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/clk.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mfd/tc6393xb.h>
+#include <linux/gpio.h>
+
+#define SCR_REVID 0x08 /* b Revision ID */
+#define SCR_ISR 0x50 /* b Interrupt Status */
+#define SCR_IMR 0x52 /* b Interrupt Mask */
+#define SCR_IRR 0x54 /* b Interrupt Routing */
+#define SCR_GPER 0x60 /* w GP Enable */
+#define SCR_GPI_SR(i) (0x64 + (i)) /* b3 GPI Status */
+#define SCR_GPI_IMR(i) (0x68 + (i)) /* b3 GPI INT Mask */
+#define SCR_GPI_EDER(i) (0x6c + (i)) /* b3 GPI Edge Detect Enable */
+#define SCR_GPI_LIR(i) (0x70 + (i)) /* b3 GPI Level Invert */
+#define SCR_GPO_DSR(i) (0x78 + (i)) /* b3 GPO Data Set */
+#define SCR_GPO_DOECR(i) (0x7c + (i)) /* b3 GPO Data OE Control */
+#define SCR_GP_IARCR(i) (0x80 + (i)) /* b3 GP Internal Active Register Control */
+#define SCR_GP_IARLCR(i) (0x84 + (i)) /* b3 GP INTERNAL Active Register Level Control */
+#define SCR_GPI_BCR(i) (0x88 + (i)) /* b3 GPI Buffer Control */
+#define SCR_GPA_IARCR 0x8c /* w GPa Internal Active Register Control */
+#define SCR_GPA_IARLCR 0x90 /* w GPa Internal Active Register Level Control */
+#define SCR_GPA_BCR 0x94 /* w GPa Buffer Control */
+#define SCR_CCR 0x98 /* w Clock Control */
+#define SCR_PLL2CR 0x9a /* w PLL2 Control */
+#define SCR_PLL1CR 0x9c /* l PLL1 Control */
+#define SCR_DIARCR 0xa0 /* b Device Internal Active Register Control */
+#define SCR_DBOCR 0xa1 /* b Device Buffer Off Control */
+#define SCR_FER 0xe0 /* b Function Enable */
+#define SCR_MCR 0xe4 /* w Mode Control */
+#define SCR_CONFIG 0xfc /* b Configuration Control */
+#define SCR_DEBUG 0xff /* b Debug */
+
+#define SCR_CCR_CK32K BIT(0)
+#define SCR_CCR_USBCK BIT(1)
+#define SCR_CCR_UNK1 BIT(4)
+#define SCR_CCR_MCLK_MASK (7 << 8)
+#define SCR_CCR_MCLK_OFF (0 << 8)
+#define SCR_CCR_MCLK_12 (1 << 8)
+#define SCR_CCR_MCLK_24 (2 << 8)
+#define SCR_CCR_MCLK_48 (3 << 8)
+#define SCR_CCR_HCLK_MASK (3 << 12)
+#define SCR_CCR_HCLK_24 (0 << 12)
+#define SCR_CCR_HCLK_48 (1 << 12)
+
+#define SCR_FER_USBEN BIT(0) /* USB host enable */
+#define SCR_FER_LCDCVEN BIT(1) /* polysilicon TFT enable */
+#define SCR_FER_SLCDEN BIT(2) /* SLCD enable */
+
+#define SCR_MCR_RDY_MASK (3 << 0)
+#define SCR_MCR_RDY_OPENDRAIN (0 << 0)
+#define SCR_MCR_RDY_TRISTATE (1 << 0)
+#define SCR_MCR_RDY_PUSHPULL (2 << 0)
+#define SCR_MCR_RDY_UNK BIT(2)
+#define SCR_MCR_RDY_EN BIT(3)
+#define SCR_MCR_INT_MASK (3 << 4)
+#define SCR_MCR_INT_OPENDRAIN (0 << 4)
+#define SCR_MCR_INT_TRISTATE (1 << 4)
+#define SCR_MCR_INT_PUSHPULL (2 << 4)
+#define SCR_MCR_INT_UNK BIT(6)
+#define SCR_MCR_INT_EN BIT(7)
+/* bits 8 - 16 are unknown */
+
+#define TC_GPIO_BIT(i) (1 << (i & 0x7))
+
+/*--------------------------------------------------------------------------*/
+
+struct tc6393xb {
+ void __iomem *scr;
+
+ struct gpio_chip gpio;
+
+ struct clk *clk; /* 3,6 Mhz */
+
+ spinlock_t lock; /* protects RMW cycles */
+
+ struct {
+ u8 fer;
+ u16 ccr;
+ u8 gpi_bcr[3];
+ u8 gpo_dsr[3];
+ u8 gpo_doecr[3];
+ } suspend_state;
+
+ struct resource rscr;
+ struct resource *iomem;
+ int irq;
+ int irq_base;
+};
+
+enum {
+ TC6393XB_CELL_NAND,
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int tc6393xb_nand_enable(struct platform_device *nand)
+{
+ struct platform_device *dev = to_platform_device(nand->dev.parent);
+ struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ /* SMD buffer on */
+ dev_dbg(&dev->dev, "SMD buffer on\n");
+ iowrite8(0xff, tc6393xb->scr + SCR_GPI_BCR(1));
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+ return 0;
+}
+
+static struct resource __devinitdata tc6393xb_nand_resources[] = {
+ {
+ .name = TMIO_NAND_CONFIG,
+ .start = 0x0100,
+ .end = 0x01ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = TMIO_NAND_CONTROL,
+ .start = 0x1000,
+ .end = 0x1007,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = TMIO_NAND_IRQ,
+ .start = IRQ_TC6393_NAND,
+ .end = IRQ_TC6393_NAND,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mfd_cell __devinitdata tc6393xb_cells[] = {
+ [TC6393XB_CELL_NAND] = {
+ .name = "tmio-nand",
+ .enable = tc6393xb_nand_enable,
+ .num_resources = ARRAY_SIZE(tc6393xb_nand_resources),
+ .resources = tc6393xb_nand_resources,
+ },
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int tc6393xb_gpio_get(struct gpio_chip *chip,
+ unsigned offset)
+{
+ struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
+
+ /* XXX: does dsr also represent inputs? */
+ return ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8))
+ & TC_GPIO_BIT(offset);
+}
+
+static void __tc6393xb_gpio_set(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
+ u8 dsr;
+
+ dsr = ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8));
+ if (value)
+ dsr |= TC_GPIO_BIT(offset);
+ else
+ dsr &= ~TC_GPIO_BIT(offset);
+
+ iowrite8(dsr, tc6393xb->scr + SCR_GPO_DSR(offset / 8));
+}
+
+static void tc6393xb_gpio_set(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
+ unsigned long flags;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ __tc6393xb_gpio_set(chip, offset, value);
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+}
+
+static int tc6393xb_gpio_direction_input(struct gpio_chip *chip,
+ unsigned offset)
+{
+ struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
+ unsigned long flags;
+ u8 doecr;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ doecr = ioread8(tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
+ doecr &= ~TC_GPIO_BIT(offset);
+ iowrite8(doecr, tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+ return 0;
+}
+
+static int tc6393xb_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
+ unsigned long flags;
+ u8 doecr;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ __tc6393xb_gpio_set(chip, offset, value);
+
+ doecr = ioread8(tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
+ doecr |= TC_GPIO_BIT(offset);
+ iowrite8(doecr, tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+ return 0;
+}
+
+static int tc6393xb_register_gpio(struct tc6393xb *tc6393xb, int gpio_base)
+{
+ tc6393xb->gpio.label = "tc6393xb";
+ tc6393xb->gpio.base = gpio_base;
+ tc6393xb->gpio.ngpio = 16;
+ tc6393xb->gpio.set = tc6393xb_gpio_set;
+ tc6393xb->gpio.get = tc6393xb_gpio_get;
+ tc6393xb->gpio.direction_input = tc6393xb_gpio_direction_input;
+ tc6393xb->gpio.direction_output = tc6393xb_gpio_direction_output;
+
+ return gpiochip_add(&tc6393xb->gpio);
+}
+
+/*--------------------------------------------------------------------------*/
+
+static void
+tc6393xb_irq(unsigned int irq, struct irq_desc *desc)
+{
+ struct tc6393xb *tc6393xb = get_irq_data(irq);
+ unsigned int isr;
+ unsigned int i, irq_base;
+
+ irq_base = tc6393xb->irq_base;
+
+ while ((isr = ioread8(tc6393xb->scr + SCR_ISR) &
+ ~ioread8(tc6393xb->scr + SCR_IMR)))
+ for (i = 0; i < TC6393XB_NR_IRQS; i++) {
+ if (isr & (1 << i))
+ generic_handle_irq(irq_base + i);
+ }
+}
+
+static void tc6393xb_irq_ack(unsigned int irq)
+{
+}
+
+static void tc6393xb_irq_mask(unsigned int irq)
+{
+ struct tc6393xb *tc6393xb = get_irq_chip_data(irq);
+ unsigned long flags;
+ u8 imr;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+ imr = ioread8(tc6393xb->scr + SCR_IMR);
+ imr |= 1 << (irq - tc6393xb->irq_base);
+ iowrite8(imr, tc6393xb->scr + SCR_IMR);
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+}
+
+static void tc6393xb_irq_unmask(unsigned int irq)
+{
+ struct tc6393xb *tc6393xb = get_irq_chip_data(irq);
+ unsigned long flags;
+ u8 imr;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+ imr = ioread8(tc6393xb->scr + SCR_IMR);
+ imr &= ~(1 << (irq - tc6393xb->irq_base));
+ iowrite8(imr, tc6393xb->scr + SCR_IMR);
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+}
+
+static struct irq_chip tc6393xb_chip = {
+ .name = "tc6393xb",
+ .ack = tc6393xb_irq_ack,
+ .mask = tc6393xb_irq_mask,
+ .unmask = tc6393xb_irq_unmask,
+};
+
+static void tc6393xb_attach_irq(struct platform_device *dev)
+{
+ struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+ unsigned int irq, irq_base;
+
+ irq_base = tc6393xb->irq_base;
+
+ for (irq = irq_base; irq < irq_base + TC6393XB_NR_IRQS; irq++) {
+ set_irq_chip(irq, &tc6393xb_chip);
+ set_irq_chip_data(irq, tc6393xb);
+ set_irq_handler(irq, handle_edge_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ }
+
+ set_irq_type(tc6393xb->irq, IRQT_FALLING);
+ set_irq_data(tc6393xb->irq, tc6393xb);
+ set_irq_chained_handler(tc6393xb->irq, tc6393xb_irq);
+}
+
+static void tc6393xb_detach_irq(struct platform_device *dev)
+{
+ struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+ unsigned int irq, irq_base;
+
+ set_irq_chained_handler(tc6393xb->irq, NULL);
+ set_irq_data(tc6393xb->irq, NULL);
+
+ irq_base = tc6393xb->irq_base;
+
+ for (irq = irq_base; irq < irq_base + TC6393XB_NR_IRQS; irq++) {
+ set_irq_flags(irq, 0);
+ set_irq_chip(irq, NULL);
+ set_irq_chip_data(irq, NULL);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int tc6393xb_hw_init(struct platform_device *dev)
+{
+ struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+ struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+ int i;
+
+ iowrite8(tc6393xb->suspend_state.fer, tc6393xb->scr + SCR_FER);
+ iowrite16(tcpd->scr_pll2cr, tc6393xb->scr + SCR_PLL2CR);
+ iowrite16(tc6393xb->suspend_state.ccr, tc6393xb->scr + SCR_CCR);
+ iowrite16(SCR_MCR_RDY_OPENDRAIN | SCR_MCR_RDY_UNK | SCR_MCR_RDY_EN |
+ SCR_MCR_INT_OPENDRAIN | SCR_MCR_INT_UNK | SCR_MCR_INT_EN |
+ BIT(15), tc6393xb->scr + SCR_MCR);
+ iowrite16(tcpd->scr_gper, tc6393xb->scr + SCR_GPER);
+ iowrite8(0, tc6393xb->scr + SCR_IRR);
+ iowrite8(0xbf, tc6393xb->scr + SCR_IMR);
+
+ for (i = 0; i < 3; i++) {
+ iowrite8(tc6393xb->suspend_state.gpo_dsr[i],
+ tc6393xb->scr + SCR_GPO_DSR(i));
+ iowrite8(tc6393xb->suspend_state.gpo_doecr[i],
+ tc6393xb->scr + SCR_GPO_DOECR(i));
+ iowrite8(tc6393xb->suspend_state.gpi_bcr[i],
+ tc6393xb->scr + SCR_GPI_BCR(i));
+ }
+
+ return 0;
+}
+
+static int __devinit tc6393xb_probe(struct platform_device *dev)
+{
+ struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+ struct tc6393xb *tc6393xb;
+ struct resource *iomem;
+ struct resource *rscr;
+ int retval, temp;
+ int i;
+
+ iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!iomem)
+ return -EINVAL;
+
+ tc6393xb = kzalloc(sizeof *tc6393xb, GFP_KERNEL);
+ if (!tc6393xb) {
+ retval = -ENOMEM;
+ goto err_kzalloc;
+ }
+
+ spin_lock_init(&tc6393xb->lock);
+
+ platform_set_drvdata(dev, tc6393xb);
+ tc6393xb->iomem = iomem;
+ tc6393xb->irq = platform_get_irq(dev, 0);
+ tc6393xb->irq_base = tcpd->irq_base;
+
+ tc6393xb->clk = clk_get(&dev->dev, "GPIO27_CLK" /* "CK3P6MI" */);
+ if (IS_ERR(tc6393xb->clk)) {
+ retval = PTR_ERR(tc6393xb->clk);
+ goto err_clk_get;
+ }
+
+ rscr = &tc6393xb->rscr;
+ rscr->name = "tc6393xb-core";
+ rscr->start = iomem->start;
+ rscr->end = iomem->start + 0xff;
+ rscr->flags = IORESOURCE_MEM;
+
+ retval = request_resource(iomem, rscr);
+ if (retval)
+ goto err_request_scr;
+
+ tc6393xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1);
+ if (!tc6393xb->scr) {
+ retval = -ENOMEM;
+ goto err_ioremap;
+ }
+
+ retval = clk_enable(tc6393xb->clk);
+ if (retval)
+ goto err_clk_enable;
+
+ retval = tcpd->enable(dev);
+ if (retval)
+ goto err_enable;
+
+ tc6393xb->suspend_state.fer = 0;
+ for (i = 0; i < 3; i++) {
+ tc6393xb->suspend_state.gpo_dsr[i] =
+ (tcpd->scr_gpo_dsr >> (8 * i)) & 0xff;
+ tc6393xb->suspend_state.gpo_doecr[i] =
+ (tcpd->scr_gpo_doecr >> (8 * i)) & 0xff;
+ }
+ /*
+ * It may be necessary to change this back to
+ * platform-dependant code
+ */
+ tc6393xb->suspend_state.ccr = SCR_CCR_UNK1 |
+ SCR_CCR_HCLK_48;
+
+ retval = tc6393xb_hw_init(dev);
+ if (retval)
+ goto err_hw_init;
+
+ printk(KERN_INFO "Toshiba tc6393xb revision %d at 0x%08lx, irq %d\n",
+ ioread8(tc6393xb->scr + SCR_REVID),
+ (unsigned long) iomem->start, tc6393xb->irq);
+
+ tc6393xb->gpio.base = -1;
+
+ if (tcpd->gpio_base >= 0) {
+ retval = tc6393xb_register_gpio(tc6393xb, tcpd->gpio_base);
+ if (retval)
+ goto err_gpio_add;
+ }
+
+ if (tc6393xb->irq)
+ tc6393xb_attach_irq(dev);
+
+ tc6393xb_cells[TC6393XB_CELL_NAND].driver_data = tcpd->nand_data;
+
+ retval = mfd_add_devices(dev,
+ tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
+ iomem, tcpd->irq_base);
+
+ return 0;
+
+ if (tc6393xb->irq)
+ tc6393xb_detach_irq(dev);
+
+err_gpio_add:
+ if (tc6393xb->gpio.base != -1)
+ temp = gpiochip_remove(&tc6393xb->gpio);
+err_hw_init:
+ tcpd->disable(dev);
+err_clk_enable:
+ clk_disable(tc6393xb->clk);
+err_enable:
+ iounmap(tc6393xb->scr);
+err_ioremap:
+ release_resource(&tc6393xb->rscr);
+err_request_scr:
+ clk_put(tc6393xb->clk);
+err_clk_get:
+ kfree(tc6393xb);
+err_kzalloc:
+ return retval;
+}
+
+static int __devexit tc6393xb_remove(struct platform_device *dev)
+{
+ struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+ struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+ int ret;
+
+ mfd_remove_devices(dev);
+
+ if (tc6393xb->irq)
+ tc6393xb_detach_irq(dev);
+
+ if (tc6393xb->gpio.base != -1) {
+ ret = gpiochip_remove(&tc6393xb->gpio);
+ if (ret) {
+ dev_err(&dev->dev, "Can't remove gpio chip: %d\n", ret);
+ return ret;
+ }
+ }
+
+ ret = tcpd->disable(dev);
+
+ clk_disable(tc6393xb->clk);
+
+ iounmap(tc6393xb->scr);
+
+ release_resource(&tc6393xb->rscr);
+
+ platform_set_drvdata(dev, NULL);
+
+ clk_put(tc6393xb->clk);
+
+ kfree(tc6393xb);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int tc6393xb_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+ struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+ int i;
+
+
+ tc6393xb->suspend_state.ccr = ioread16(tc6393xb->scr + SCR_CCR);
+ tc6393xb->suspend_state.fer = ioread8(tc6393xb->scr + SCR_FER);
+
+ for (i = 0; i < 3; i++) {
+ tc6393xb->suspend_state.gpo_dsr[i] =
+ ioread8(tc6393xb->scr + SCR_GPO_DSR(i));
+ tc6393xb->suspend_state.gpo_doecr[i] =
+ ioread8(tc6393xb->scr + SCR_GPO_DOECR(i));
+ tc6393xb->suspend_state.gpi_bcr[i] =
+ ioread8(tc6393xb->scr + SCR_GPI_BCR(i));
+ }
+
+ return tcpd->suspend(dev);
+}
+
+static int tc6393xb_resume(struct platform_device *dev)
+{
+ struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+ int ret = tcpd->resume(dev);
+
+ if (ret)
+ return ret;
+
+ return tc6393xb_hw_init(dev);
+}
+#else
+#define tc6393xb_suspend NULL
+#define tc6393xb_resume NULL
+#endif
+
+static struct platform_driver tc6393xb_driver = {
+ .probe = tc6393xb_probe,
+ .remove = __devexit_p(tc6393xb_remove),
+ .suspend = tc6393xb_suspend,
+ .resume = tc6393xb_resume,
+
+ .driver = {
+ .name = "tc6393xb",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init tc6393xb_init(void)
+{
+ return platform_driver_register(&tc6393xb_driver);
+}
+
+static void __exit tc6393xb_exit(void)
+{
+ platform_driver_unregister(&tc6393xb_driver);
+}
+
+subsys_initcall(tc6393xb_init);
+module_exit(tc6393xb_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov and Dirk Opfer");
+MODULE_DESCRIPTION("tc6393xb Toshiba Mobile IO Controller");
+MODULE_ALIAS("platform:tc6393xb");
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1921b8dbb24..321eb913463 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -77,11 +77,13 @@ config IBM_ASM
for your IBM server.
config PHANTOM
- tristate "Sensable PHANToM"
+ tristate "Sensable PHANToM (PCI)"
depends on PCI
help
Say Y here if you want to build a driver for Sensable PHANToM device.
+ This driver is only for PCI PHANToMs.
+
If you choose to build module, its name will be phantom. If unsure,
say N here.
@@ -212,6 +214,18 @@ config TC1100_WMI
This is a driver for the WMI extensions (wireless and bluetooth power
control) of the HP Compaq TC1100 tablet.
+config HP_WMI
+ tristate "HP WMI extras"
+ depends on ACPI_WMI
+ depends on INPUT
+ depends on RFKILL
+ help
+ Say Y here if you want to support WMI-based hotkeys on HP laptops and
+ to read data from WMI such as docking or ambient light sensor state.
+
+ To compile this driver as a module, choose M here: the module will
+ be called hp-wmi.
+
config MSI_LAPTOP
tristate "MSI Laptop Extras"
depends on X86
@@ -279,6 +293,8 @@ config THINKPAD_ACPI
select INPUT
select NEW_LEDS
select LEDS_CLASS
+ select NET
+ select RFKILL
---help---
This is a driver for the IBM and Lenovo ThinkPad laptops. It adds
support for Fn-Fx key combinations, Bluetooth control, video
@@ -420,4 +436,18 @@ config SGI_XP
this feature will allow for direct communication between SSIs
based on a network adapter and DMA messaging.
+config HP_ILO
+ tristate "Channel interface driver for HP iLO/iLO2 processor"
+ depends on PCI
+ default n
+ help
+ The channel interface driver allows applications to communicate
+ with iLO/iLO2 management processors present on HP ProLiant
+ servers. Upon loading, the driver creates /dev/hpilo/dXccbN files,
+ which can be used to gather data from the management processor,
+ via read and write system calls.
+
+ To compile this driver as a module, choose M here: the
+ module will be called hpilo.
+
endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index a6dac6a2e7e..f5e273420c0 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_ACER_WMI) += acer-wmi.o
obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
+obj-$(CONFIG_HP_WMI) += hp-wmi.o
obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o
obj-$(CONFIG_LKDTM) += lkdtm.o
obj-$(CONFIG_TIFM_CORE) += tifm_core.o
@@ -27,3 +28,4 @@ obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
obj-$(CONFIG_KGDB_TESTS) += kgdbts.o
obj-$(CONFIG_SGI_XP) += sgi-xp/
+obj-$(CONFIG_HP_ILO) += hpilo.o
diff --git a/drivers/misc/atmel_pwm.c b/drivers/misc/atmel_pwm.c
index 5b5a14dab3d..6aa5294dfec 100644
--- a/drivers/misc/atmel_pwm.c
+++ b/drivers/misc/atmel_pwm.c
@@ -211,8 +211,7 @@ int pwm_clk_alloc(unsigned prescale, unsigned div)
if ((mr & 0xffff) == 0) {
mr |= val;
ret = PWM_CPR_CLKA;
- }
- if ((mr & (0xffff << 16)) == 0) {
+ } else if ((mr & (0xffff << 16)) == 0) {
mr |= val << 16;
ret = PWM_CPR_CLKB;
}
diff --git a/drivers/misc/hp-wmi.c b/drivers/misc/hp-wmi.c
new file mode 100644
index 00000000000..1dbcbcb323a
--- /dev/null
+++ b/drivers/misc/hp-wmi.c
@@ -0,0 +1,494 @@
+/*
+ * HP WMI hotkeys
+ *
+ * Copyright (C) 2008 Red Hat <mjg@redhat.com>
+ *
+ * Portions based on wistron_btns.c:
+ * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
+ * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
+ * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/input.h>
+#include <acpi/acpi_drivers.h>
+#include <linux/platform_device.h>
+#include <linux/acpi.h>
+#include <linux/rfkill.h>
+#include <linux/string.h>
+
+MODULE_AUTHOR("Matthew Garrett <mjg59@srcf.ucam.org>");
+MODULE_DESCRIPTION("HP laptop WMI hotkeys driver");
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("wmi:95F24279-4D7B-4334-9387-ACCDC67EF61C");
+MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
+
+#define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C"
+#define HPWMI_BIOS_GUID "5FB7F034-2C63-45e9-BE91-3D44E2C707E4"
+
+#define HPWMI_DISPLAY_QUERY 0x1
+#define HPWMI_HDDTEMP_QUERY 0x2
+#define HPWMI_ALS_QUERY 0x3
+#define HPWMI_DOCK_QUERY 0x4
+#define HPWMI_WIRELESS_QUERY 0x5
+
+static int __init hp_wmi_bios_setup(struct platform_device *device);
+static int __exit hp_wmi_bios_remove(struct platform_device *device);
+
+struct bios_args {
+ u32 signature;
+ u32 command;
+ u32 commandtype;
+ u32 datasize;
+ u32 data;
+};
+
+struct bios_return {
+ u32 sigpass;
+ u32 return_code;
+ u32 value;
+};
+
+struct key_entry {
+ char type; /* See KE_* below */
+ u8 code;
+ u16 keycode;
+};
+
+enum { KE_KEY, KE_SW, KE_END };
+
+static struct key_entry hp_wmi_keymap[] = {
+ {KE_SW, 0x01, SW_DOCK},
+ {KE_KEY, 0x02, KEY_BRIGHTNESSUP},
+ {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN},
+ {KE_KEY, 0x04, KEY_HELP},
+ {KE_END, 0}
+};
+
+static struct input_dev *hp_wmi_input_dev;
+static struct platform_device *hp_wmi_platform_dev;
+
+static struct rfkill *wifi_rfkill;
+static struct rfkill *bluetooth_rfkill;
+static struct rfkill *wwan_rfkill;
+
+static struct platform_driver hp_wmi_driver = {
+ .driver = {
+ .name = "hp-wmi",
+ .owner = THIS_MODULE,
+ },
+ .probe = hp_wmi_bios_setup,
+ .remove = hp_wmi_bios_remove,
+};
+
+static int hp_wmi_perform_query(int query, int write, int value)
+{
+ struct bios_return bios_return;
+ acpi_status status;
+ union acpi_object *obj;
+ struct bios_args args = {
+ .signature = 0x55434553,
+ .command = write ? 0x2 : 0x1,
+ .commandtype = query,
+ .datasize = write ? 0x4 : 0,
+ .data = value,
+ };
+ struct acpi_buffer input = { sizeof(struct bios_args), &args };
+ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+
+ status = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, 0x3, &input, &output);
+
+ obj = output.pointer;
+
+ if (!obj || obj->type != ACPI_TYPE_BUFFER)
+ return -EINVAL;
+
+ bios_return = *((struct bios_return *)obj->buffer.pointer);
+ if (bios_return.return_code > 0)
+ return bios_return.return_code * -1;
+ else
+ return bios_return.value;
+}
+
+static int hp_wmi_display_state(void)
+{
+ return hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, 0);
+}
+
+static int hp_wmi_hddtemp_state(void)
+{
+ return hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, 0);
+}
+
+static int hp_wmi_als_state(void)
+{
+ return hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, 0);
+}
+
+static int hp_wmi_dock_state(void)
+{
+ return hp_wmi_perform_query(HPWMI_DOCK_QUERY, 0, 0);
+}
+
+static int hp_wmi_wifi_set(void *data, enum rfkill_state state)
+{
+ if (state)
+ return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x101);
+ else
+ return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x100);
+}
+
+static int hp_wmi_bluetooth_set(void *data, enum rfkill_state state)
+{
+ if (state)
+ return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x202);
+ else
+ return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x200);
+}
+
+static int hp_wmi_wwan_set(void *data, enum rfkill_state state)
+{
+ if (state)
+ return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x404);
+ else
+ return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x400);
+}
+
+static int hp_wmi_wifi_state(void)
+{
+ int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
+
+ if (wireless & 0x100)
+ return 1;
+ else
+ return 0;
+}
+
+static int hp_wmi_bluetooth_state(void)
+{
+ int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
+
+ if (wireless & 0x10000)
+ return 1;
+ else
+ return 0;
+}
+
+static int hp_wmi_wwan_state(void)
+{
+ int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
+
+ if (wireless & 0x1000000)
+ return 1;
+ else
+ return 0;
+}
+
+static ssize_t show_display(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int value = hp_wmi_display_state();
+ if (value < 0)
+ return -EINVAL;
+ return sprintf(buf, "%d\n", value);
+}
+
+static ssize_t show_hddtemp(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int value = hp_wmi_hddtemp_state();
+ if (value < 0)
+ return -EINVAL;
+ return sprintf(buf, "%d\n", value);
+}
+
+static ssize_t show_als(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int value = hp_wmi_als_state();
+ if (value < 0)
+ return -EINVAL;
+ return sprintf(buf, "%d\n", value);
+}
+
+static ssize_t show_dock(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int value = hp_wmi_dock_state();
+ if (value < 0)
+ return -EINVAL;
+ return sprintf(buf, "%d\n", value);
+}
+
+static ssize_t set_als(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u32 tmp = simple_strtoul(buf, NULL, 10);
+ hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, tmp);
+ return count;
+}
+
+static DEVICE_ATTR(display, S_IRUGO, show_display, NULL);
+static DEVICE_ATTR(hddtemp, S_IRUGO, show_hddtemp, NULL);
+static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als);
+static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL);
+
+static struct key_entry *hp_wmi_get_entry_by_scancode(int code)
+{
+ struct key_entry *key;
+
+ for (key = hp_wmi_keymap; key->type != KE_END; key++)
+ if (code == key->code)
+ return key;
+
+ return NULL;
+}
+
+static struct key_entry *hp_wmi_get_entry_by_keycode(int keycode)
+{
+ struct key_entry *key;
+
+ for (key = hp_wmi_keymap; key->type != KE_END; key++)
+ if (key->type == KE_KEY && keycode == key->keycode)
+ return key;
+
+ return NULL;
+}
+
+static int hp_wmi_getkeycode(struct input_dev *dev, int scancode, int *keycode)
+{
+ struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode);
+
+ if (key && key->type == KE_KEY) {
+ *keycode = key->keycode;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int hp_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode)
+{
+ struct key_entry *key;
+ int old_keycode;
+
+ if (keycode < 0 || keycode > KEY_MAX)
+ return -EINVAL;
+
+ key = hp_wmi_get_entry_by_scancode(scancode);
+ if (key && key->type == KE_KEY) {
+ old_keycode = key->keycode;
+ key->keycode = keycode;
+ set_bit(keycode, dev->keybit);
+ if (!hp_wmi_get_entry_by_keycode(old_keycode))
+ clear_bit(old_keycode, dev->keybit);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+void hp_wmi_notify(u32 value, void *context)
+{
+ struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
+ static struct key_entry *key;
+ union acpi_object *obj;
+
+ wmi_get_event_data(value, &response);
+
+ obj = (union acpi_object *)response.pointer;
+
+ if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == 8) {
+ int eventcode = *((u8 *) obj->buffer.pointer);
+ key = hp_wmi_get_entry_by_scancode(eventcode);
+ if (key) {
+ switch (key->type) {
+ case KE_KEY:
+ input_report_key(hp_wmi_input_dev,
+ key->keycode, 1);
+ input_sync(hp_wmi_input_dev);
+ input_report_key(hp_wmi_input_dev,
+ key->keycode, 0);
+ input_sync(hp_wmi_input_dev);
+ break;
+ case KE_SW:
+ input_report_switch(hp_wmi_input_dev,
+ key->keycode,
+ hp_wmi_dock_state());
+ input_sync(hp_wmi_input_dev);
+ break;
+ }
+ } else if (eventcode == 0x5) {
+ if (wifi_rfkill)
+ wifi_rfkill->state = hp_wmi_wifi_state();
+ if (bluetooth_rfkill)
+ bluetooth_rfkill->state =
+ hp_wmi_bluetooth_state();
+ if (wwan_rfkill)
+ wwan_rfkill->state = hp_wmi_wwan_state();
+ } else
+ printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
+ eventcode);
+ } else
+ printk(KERN_INFO "HP WMI: Unknown response received\n");
+}
+
+static int __init hp_wmi_input_setup(void)
+{
+ struct key_entry *key;
+ int err;
+
+ hp_wmi_input_dev = input_allocate_device();
+
+ hp_wmi_input_dev->name = "HP WMI hotkeys";
+ hp_wmi_input_dev->phys = "wmi/input0";
+ hp_wmi_input_dev->id.bustype = BUS_HOST;
+ hp_wmi_input_dev->getkeycode = hp_wmi_getkeycode;
+ hp_wmi_input_dev->setkeycode = hp_wmi_setkeycode;
+
+ for (key = hp_wmi_keymap; key->type != KE_END; key++) {
+ switch (key->type) {
+ case KE_KEY:
+ set_bit(EV_KEY, hp_wmi_input_dev->evbit);
+ set_bit(key->keycode, hp_wmi_input_dev->keybit);
+ break;
+ case KE_SW:
+ set_bit(EV_SW, hp_wmi_input_dev->evbit);
+ set_bit(key->keycode, hp_wmi_input_dev->swbit);
+ break;
+ }
+ }
+
+ err = input_register_device(hp_wmi_input_dev);
+
+ if (err) {
+ input_free_device(hp_wmi_input_dev);
+ return err;
+ }
+
+ return 0;
+}
+
+static void cleanup_sysfs(struct platform_device *device)
+{
+ device_remove_file(&device->dev, &dev_attr_display);
+ device_remove_file(&device->dev, &dev_attr_hddtemp);
+ device_remove_file(&device->dev, &dev_attr_als);
+ device_remove_file(&device->dev, &dev_attr_dock);
+}
+
+static int __init hp_wmi_bios_setup(struct platform_device *device)
+{
+ int err;
+
+ err = device_create_file(&device->dev, &dev_attr_display);
+ if (err)
+ goto add_sysfs_error;
+ err = device_create_file(&device->dev, &dev_attr_hddtemp);
+ if (err)
+ goto add_sysfs_error;
+ err = device_create_file(&device->dev, &dev_attr_als);
+ if (err)
+ goto add_sysfs_error;
+ err = device_create_file(&device->dev, &dev_attr_dock);
+ if (err)
+ goto add_sysfs_error;
+
+ wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN);
+ wifi_rfkill->name = "hp-wifi";
+ wifi_rfkill->state = hp_wmi_wifi_state();
+ wifi_rfkill->toggle_radio = hp_wmi_wifi_set;
+ wifi_rfkill->user_claim_unsupported = 1;
+
+ bluetooth_rfkill = rfkill_allocate(&device->dev,
+ RFKILL_TYPE_BLUETOOTH);
+ bluetooth_rfkill->name = "hp-bluetooth";
+ bluetooth_rfkill->state = hp_wmi_bluetooth_state();
+ bluetooth_rfkill->toggle_radio = hp_wmi_bluetooth_set;
+ bluetooth_rfkill->user_claim_unsupported = 1;
+
+ wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WIMAX);
+ wwan_rfkill->name = "hp-wwan";
+ wwan_rfkill->state = hp_wmi_wwan_state();
+ wwan_rfkill->toggle_radio = hp_wmi_wwan_set;
+ wwan_rfkill->user_claim_unsupported = 1;
+
+ rfkill_register(wifi_rfkill);
+ rfkill_register(bluetooth_rfkill);
+ rfkill_register(wwan_rfkill);
+
+ return 0;
+add_sysfs_error:
+ cleanup_sysfs(device);
+ return err;
+}
+
+static int __exit hp_wmi_bios_remove(struct platform_device *device)
+{
+ cleanup_sysfs(device);
+
+ rfkill_unregister(wifi_rfkill);
+ rfkill_unregister(bluetooth_rfkill);
+ rfkill_unregister(wwan_rfkill);
+
+ return 0;
+}
+
+static int __init hp_wmi_init(void)
+{
+ int err;
+
+ if (wmi_has_guid(HPWMI_EVENT_GUID)) {
+ err = wmi_install_notify_handler(HPWMI_EVENT_GUID,
+ hp_wmi_notify, NULL);
+ if (!err)
+ hp_wmi_input_setup();
+ }
+
+ if (wmi_has_guid(HPWMI_BIOS_GUID)) {
+ err = platform_driver_register(&hp_wmi_driver);
+ if (err)
+ return 0;
+ hp_wmi_platform_dev = platform_device_alloc("hp-wmi", -1);
+ if (!hp_wmi_platform_dev) {
+ platform_driver_unregister(&hp_wmi_driver);
+ return 0;
+ }
+ platform_device_add(hp_wmi_platform_dev);
+ }
+
+ return 0;
+}
+
+static void __exit hp_wmi_exit(void)
+{
+ if (wmi_has_guid(HPWMI_EVENT_GUID)) {
+ wmi_remove_notify_handler(HPWMI_EVENT_GUID);
+ input_unregister_device(hp_wmi_input_dev);
+ }
+ if (hp_wmi_platform_dev) {
+ platform_device_del(hp_wmi_platform_dev);
+ platform_driver_unregister(&hp_wmi_driver);
+ }
+}
+
+module_init(hp_wmi_init);
+module_exit(hp_wmi_exit);
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
new file mode 100644
index 00000000000..05e29828923
--- /dev/null
+++ b/drivers/misc/hpilo.c
@@ -0,0 +1,768 @@
+/*
+ * Driver for HP iLO/iLO2 management processor.
+ *
+ * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
+ * David Altobelli <david.altobelli@hp.com>
+ *
+ * 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/types.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/file.h>
+#include <linux/cdev.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include "hpilo.h"
+
+static struct class *ilo_class;
+static unsigned int ilo_major;
+static char ilo_hwdev[MAX_ILO_DEV];
+
+static inline int get_entry_id(int entry)
+{
+ return (entry & ENTRY_MASK_DESCRIPTOR) >> ENTRY_BITPOS_DESCRIPTOR;
+}
+
+static inline int get_entry_len(int entry)
+{
+ return ((entry & ENTRY_MASK_QWORDS) >> ENTRY_BITPOS_QWORDS) << 3;
+}
+
+static inline int mk_entry(int id, int len)
+{
+ int qlen = len & 7 ? (len >> 3) + 1 : len >> 3;
+ return id << ENTRY_BITPOS_DESCRIPTOR | qlen << ENTRY_BITPOS_QWORDS;
+}
+
+static inline int desc_mem_sz(int nr_entry)
+{
+ return nr_entry << L2_QENTRY_SZ;
+}
+
+/*
+ * FIFO queues, shared with hardware.
+ *
+ * If a queue has empty slots, an entry is added to the queue tail,
+ * and that entry is marked as occupied.
+ * Entries can be dequeued from the head of the list, when the device
+ * has marked the entry as consumed.
+ *
+ * Returns true on successful queue/dequeue, false on failure.
+ */
+static int fifo_enqueue(struct ilo_hwinfo *hw, char *fifobar, int entry)
+{
+ struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar);
+ int ret = 0;
+
+ spin_lock(&hw->fifo_lock);
+ if (!(fifo_q->fifobar[(fifo_q->tail + 1) & fifo_q->imask]
+ & ENTRY_MASK_O)) {
+ fifo_q->fifobar[fifo_q->tail & fifo_q->imask] |=
+ (entry & ENTRY_MASK_NOSTATE) | fifo_q->merge;
+ fifo_q->tail += 1;
+ ret = 1;
+ }
+ spin_unlock(&hw->fifo_lock);
+
+ return ret;
+}
+
+static int fifo_dequeue(struct ilo_hwinfo *hw, char *fifobar, int *entry)
+{
+ struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar);
+ int ret = 0;
+ u64 c;
+
+ spin_lock(&hw->fifo_lock);
+ c = fifo_q->fifobar[fifo_q->head & fifo_q->imask];
+ if (c & ENTRY_MASK_C) {
+ if (entry)
+ *entry = c & ENTRY_MASK_NOSTATE;
+
+ fifo_q->fifobar[fifo_q->head & fifo_q->imask] =
+ (c | ENTRY_MASK) + 1;
+ fifo_q->head += 1;
+ ret = 1;
+ }
+ spin_unlock(&hw->fifo_lock);
+
+ return ret;
+}
+
+static int ilo_pkt_enqueue(struct ilo_hwinfo *hw, struct ccb *ccb,
+ int dir, int id, int len)
+{
+ char *fifobar;
+ int entry;
+
+ if (dir == SENDQ)
+ fifobar = ccb->ccb_u1.send_fifobar;
+ else
+ fifobar = ccb->ccb_u3.recv_fifobar;
+
+ entry = mk_entry(id, len);
+ return fifo_enqueue(hw, fifobar, entry);
+}
+
+static int ilo_pkt_dequeue(struct ilo_hwinfo *hw, struct ccb *ccb,
+ int dir, int *id, int *len, void **pkt)
+{
+ char *fifobar, *desc;
+ int entry = 0, pkt_id = 0;
+ int ret;
+
+ if (dir == SENDQ) {
+ fifobar = ccb->ccb_u1.send_fifobar;
+ desc = ccb->ccb_u2.send_desc;
+ } else {
+ fifobar = ccb->ccb_u3.recv_fifobar;
+ desc = ccb->ccb_u4.recv_desc;
+ }
+
+ ret = fifo_dequeue(hw, fifobar, &entry);
+ if (ret) {
+ pkt_id = get_entry_id(entry);
+ if (id)
+ *id = pkt_id;
+ if (len)
+ *len = get_entry_len(entry);
+ if (pkt)
+ *pkt = (void *)(desc + desc_mem_sz(pkt_id));
+ }
+
+ return ret;
+}
+
+static inline void doorbell_set(struct ccb *ccb)
+{
+ iowrite8(1, ccb->ccb_u5.db_base);
+}
+
+static inline void doorbell_clr(struct ccb *ccb)
+{
+ iowrite8(2, ccb->ccb_u5.db_base);
+}
+static inline int ctrl_set(int l2sz, int idxmask, int desclim)
+{
+ int active = 0, go = 1;
+ return l2sz << CTRL_BITPOS_L2SZ |
+ idxmask << CTRL_BITPOS_FIFOINDEXMASK |
+ desclim << CTRL_BITPOS_DESCLIMIT |
+ active << CTRL_BITPOS_A |
+ go << CTRL_BITPOS_G;
+}
+static void ctrl_setup(struct ccb *ccb, int nr_desc, int l2desc_sz)
+{
+ /* for simplicity, use the same parameters for send and recv ctrls */
+ ccb->send_ctrl = ctrl_set(l2desc_sz, nr_desc-1, nr_desc-1);
+ ccb->recv_ctrl = ctrl_set(l2desc_sz, nr_desc-1, nr_desc-1);
+}
+
+static inline int fifo_sz(int nr_entry)
+{
+ /* size of a fifo is determined by the number of entries it contains */
+ return (nr_entry * sizeof(u64)) + FIFOHANDLESIZE;
+}
+
+static void fifo_setup(void *base_addr, int nr_entry)
+{
+ struct fifo *fifo_q = base_addr;
+ int i;
+
+ /* set up an empty fifo */
+ fifo_q->head = 0;
+ fifo_q->tail = 0;
+ fifo_q->reset = 0;
+ fifo_q->nrents = nr_entry;
+ fifo_q->imask = nr_entry - 1;
+ fifo_q->merge = ENTRY_MASK_O;
+
+ for (i = 0; i < nr_entry; i++)
+ fifo_q->fifobar[i] = 0;
+}
+
+static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data)
+{
+ struct ccb *driver_ccb;
+ struct ccb __iomem *device_ccb;
+ int retries;
+
+ driver_ccb = &data->driver_ccb;
+ device_ccb = data->mapped_ccb;
+
+ /* complicated dance to tell the hw we are stopping */
+ doorbell_clr(driver_ccb);
+ iowrite32(ioread32(&device_ccb->send_ctrl) & ~(1 << CTRL_BITPOS_G),
+ &device_ccb->send_ctrl);
+ iowrite32(ioread32(&device_ccb->recv_ctrl) & ~(1 << CTRL_BITPOS_G),
+ &device_ccb->recv_ctrl);
+
+ /* give iLO some time to process stop request */
+ for (retries = 1000; retries > 0; retries--) {
+ doorbell_set(driver_ccb);
+ udelay(1);
+ if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A))
+ &&
+ !(ioread32(&device_ccb->recv_ctrl) & (1 << CTRL_BITPOS_A)))
+ break;
+ }
+ if (retries == 0)
+ dev_err(&pdev->dev, "Closing, but controller still active\n");
+
+ /* clear the hw ccb */
+ memset_io(device_ccb, 0, sizeof(struct ccb));
+
+ /* free resources used to back send/recv queues */
+ pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa);
+}
+
+static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
+{
+ char *dma_va, *dma_pa;
+ int pkt_id, pkt_sz, i, error;
+ struct ccb *driver_ccb, *ilo_ccb;
+ struct pci_dev *pdev;
+
+ driver_ccb = &data->driver_ccb;
+ ilo_ccb = &data->ilo_ccb;
+ pdev = hw->ilo_dev;
+
+ data->dma_size = 2 * fifo_sz(NR_QENTRY) +
+ 2 * desc_mem_sz(NR_QENTRY) +
+ ILO_START_ALIGN + ILO_CACHE_SZ;
+
+ error = -ENOMEM;
+ data->dma_va = pci_alloc_consistent(pdev, data->dma_size,
+ &data->dma_pa);
+ if (!data->dma_va)
+ goto out;
+
+ dma_va = (char *)data->dma_va;
+ dma_pa = (char *)data->dma_pa;
+
+ memset(dma_va, 0, data->dma_size);
+
+ dma_va = (char *)roundup((unsigned long)dma_va, ILO_START_ALIGN);
+ dma_pa = (char *)roundup((unsigned long)dma_pa, ILO_START_ALIGN);
+
+ /*
+ * Create two ccb's, one with virt addrs, one with phys addrs.
+ * Copy the phys addr ccb to device shared mem.
+ */
+ ctrl_setup(driver_ccb, NR_QENTRY, L2_QENTRY_SZ);
+ ctrl_setup(ilo_ccb, NR_QENTRY, L2_QENTRY_SZ);
+
+ fifo_setup(dma_va, NR_QENTRY);
+ driver_ccb->ccb_u1.send_fifobar = dma_va + FIFOHANDLESIZE;
+ ilo_ccb->ccb_u1.send_fifobar = dma_pa + FIFOHANDLESIZE;
+ dma_va += fifo_sz(NR_QENTRY);
+ dma_pa += fifo_sz(NR_QENTRY);
+
+ dma_va = (char *)roundup((unsigned long)dma_va, ILO_CACHE_SZ);
+ dma_pa = (char *)roundup((unsigned long)dma_pa, ILO_CACHE_SZ);
+
+ fifo_setup(dma_va, NR_QENTRY);
+ driver_ccb->ccb_u3.recv_fifobar = dma_va + FIFOHANDLESIZE;
+ ilo_ccb->ccb_u3.recv_fifobar = dma_pa + FIFOHANDLESIZE;
+ dma_va += fifo_sz(NR_QENTRY);
+ dma_pa += fifo_sz(NR_QENTRY);
+
+ driver_ccb->ccb_u2.send_desc = dma_va;
+ ilo_ccb->ccb_u2.send_desc = dma_pa;
+ dma_pa += desc_mem_sz(NR_QENTRY);
+ dma_va += desc_mem_sz(NR_QENTRY);
+
+ driver_ccb->ccb_u4.recv_desc = dma_va;
+ ilo_ccb->ccb_u4.recv_desc = dma_pa;
+
+ driver_ccb->channel = slot;
+ ilo_ccb->channel = slot;
+
+ driver_ccb->ccb_u5.db_base = hw->db_vaddr + (slot << L2_DB_SIZE);
+ ilo_ccb->ccb_u5.db_base = NULL; /* hw ccb's doorbell is not used */
+
+ /* copy the ccb with physical addrs to device memory */
+ data->mapped_ccb = (struct ccb __iomem *)
+ (hw->ram_vaddr + (slot * ILOHW_CCB_SZ));
+ memcpy_toio(data->mapped_ccb, ilo_ccb, sizeof(struct ccb));
+
+ /* put packets on the send and receive queues */
+ pkt_sz = 0;
+ for (pkt_id = 0; pkt_id < NR_QENTRY; pkt_id++) {
+ ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, pkt_sz);
+ doorbell_set(driver_ccb);
+ }
+
+ pkt_sz = desc_mem_sz(1);
+ for (pkt_id = 0; pkt_id < NR_QENTRY; pkt_id++)
+ ilo_pkt_enqueue(hw, driver_ccb, RECVQ, pkt_id, pkt_sz);
+
+ doorbell_clr(driver_ccb);
+
+ /* make sure iLO is really handling requests */
+ for (i = 1000; i > 0; i--) {
+ if (ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, NULL, NULL))
+ break;
+ udelay(1);
+ }
+
+ if (i) {
+ ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, 0);
+ doorbell_set(driver_ccb);
+ } else {
+ dev_err(&pdev->dev, "Open could not dequeue a packet\n");
+ error = -EBUSY;
+ goto free;
+ }
+
+ return 0;
+free:
+ pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa);
+out:
+ return error;
+}
+
+static inline int is_channel_reset(struct ccb *ccb)
+{
+ /* check for this particular channel needing a reset */
+ return FIFOBARTOHANDLE(ccb->ccb_u1.send_fifobar)->reset;
+}
+
+static inline void set_channel_reset(struct ccb *ccb)
+{
+ /* set a flag indicating this channel needs a reset */
+ FIFOBARTOHANDLE(ccb->ccb_u1.send_fifobar)->reset = 1;
+}
+
+static inline int is_device_reset(struct ilo_hwinfo *hw)
+{
+ /* check for global reset condition */
+ return ioread32(&hw->mmio_vaddr[DB_OUT]) & (1 << DB_RESET);
+}
+
+static inline void clear_device(struct ilo_hwinfo *hw)
+{
+ /* clear the device (reset bits, pending channel entries) */
+ iowrite32(-1, &hw->mmio_vaddr[DB_OUT]);
+}
+
+static void ilo_locked_reset(struct ilo_hwinfo *hw)
+{
+ int slot;
+
+ /*
+ * Mapped memory is zeroed on ilo reset, so set a per ccb flag
+ * to indicate that this ccb needs to be closed and reopened.
+ */
+ for (slot = 0; slot < MAX_CCB; slot++) {
+ if (!hw->ccb_alloc[slot])
+ continue;
+ set_channel_reset(&hw->ccb_alloc[slot]->driver_ccb);
+ }
+
+ clear_device(hw);
+}
+
+static void ilo_reset(struct ilo_hwinfo *hw)
+{
+ spin_lock(&hw->alloc_lock);
+
+ /* reset might have been handled after lock was taken */
+ if (is_device_reset(hw))
+ ilo_locked_reset(hw);
+
+ spin_unlock(&hw->alloc_lock);
+}
+
+static ssize_t ilo_read(struct file *fp, char __user *buf,
+ size_t len, loff_t *off)
+{
+ int err, found, cnt, pkt_id, pkt_len;
+ struct ccb_data *data;
+ struct ccb *driver_ccb;
+ struct ilo_hwinfo *hw;
+ void *pkt;
+
+ data = fp->private_data;
+ driver_ccb = &data->driver_ccb;
+ hw = data->ilo_hw;
+
+ if (is_device_reset(hw) || is_channel_reset(driver_ccb)) {
+ /*
+ * If the device has been reset, applications
+ * need to close and reopen all ccbs.
+ */
+ ilo_reset(hw);
+ return -ENODEV;
+ }
+
+ /*
+ * This function is to be called when data is expected
+ * in the channel, and will return an error if no packet is found
+ * during the loop below. The sleep/retry logic is to allow
+ * applications to call read() immediately post write(),
+ * and give iLO some time to process the sent packet.
+ */
+ cnt = 20;
+ do {
+ /* look for a received packet */
+ found = ilo_pkt_dequeue(hw, driver_ccb, RECVQ, &pkt_id,
+ &pkt_len, &pkt);
+ if (found)
+ break;
+ cnt--;
+ msleep(100);
+ } while (!found && cnt);
+
+ if (!found)
+ return -EAGAIN;
+
+ /* only copy the length of the received packet */
+ if (pkt_len < len)
+ len = pkt_len;
+
+ err = copy_to_user(buf, pkt, len);
+
+ /* return the received packet to the queue */
+ ilo_pkt_enqueue(hw, driver_ccb, RECVQ, pkt_id, desc_mem_sz(1));
+
+ return err ? -EFAULT : len;
+}
+
+static ssize_t ilo_write(struct file *fp, const char __user *buf,
+ size_t len, loff_t *off)
+{
+ int err, pkt_id, pkt_len;
+ struct ccb_data *data;
+ struct ccb *driver_ccb;
+ struct ilo_hwinfo *hw;
+ void *pkt;
+
+ data = fp->private_data;
+ driver_ccb = &data->driver_ccb;
+ hw = data->ilo_hw;
+
+ if (is_device_reset(hw) || is_channel_reset(driver_ccb)) {
+ /*
+ * If the device has been reset, applications
+ * need to close and reopen all ccbs.
+ */
+ ilo_reset(hw);
+ return -ENODEV;
+ }
+
+ /* get a packet to send the user command */
+ if (!ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, &pkt_len, &pkt))
+ return -EBUSY;
+
+ /* limit the length to the length of the packet */
+ if (pkt_len < len)
+ len = pkt_len;
+
+ /* on failure, set the len to 0 to return empty packet to the device */
+ err = copy_from_user(pkt, buf, len);
+ if (err)
+ len = 0;
+
+ /* send the packet */
+ ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, len);
+ doorbell_set(driver_ccb);
+
+ return err ? -EFAULT : len;
+}
+
+static int ilo_close(struct inode *ip, struct file *fp)
+{
+ int slot;
+ struct ccb_data *data;
+ struct ilo_hwinfo *hw;
+
+ slot = iminor(ip) % MAX_CCB;
+ hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev);
+
+ spin_lock(&hw->alloc_lock);
+
+ if (is_device_reset(hw))
+ ilo_locked_reset(hw);
+
+ if (hw->ccb_alloc[slot]->ccb_cnt == 1) {
+
+ data = fp->private_data;
+
+ ilo_ccb_close(hw->ilo_dev, data);
+
+ kfree(data);
+ hw->ccb_alloc[slot] = NULL;
+ } else
+ hw->ccb_alloc[slot]->ccb_cnt--;
+
+ spin_unlock(&hw->alloc_lock);
+
+ return 0;
+}
+
+static int ilo_open(struct inode *ip, struct file *fp)
+{
+ int slot, error;
+ struct ccb_data *data;
+ struct ilo_hwinfo *hw;
+
+ slot = iminor(ip) % MAX_CCB;
+ hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev);
+
+ /* new ccb allocation */
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ spin_lock(&hw->alloc_lock);
+
+ if (is_device_reset(hw))
+ ilo_locked_reset(hw);
+
+ /* each fd private_data holds sw/hw view of ccb */
+ if (hw->ccb_alloc[slot] == NULL) {
+ /* create a channel control block for this minor */
+ error = ilo_ccb_open(hw, data, slot);
+ if (!error) {
+ hw->ccb_alloc[slot] = data;
+ hw->ccb_alloc[slot]->ccb_cnt = 1;
+ hw->ccb_alloc[slot]->ccb_excl = fp->f_flags & O_EXCL;
+ hw->ccb_alloc[slot]->ilo_hw = hw;
+ } else
+ kfree(data);
+ } else {
+ kfree(data);
+ if (fp->f_flags & O_EXCL || hw->ccb_alloc[slot]->ccb_excl) {
+ /*
+ * The channel exists, and either this open
+ * or a previous open of this channel wants
+ * exclusive access.
+ */
+ error = -EBUSY;
+ } else {
+ hw->ccb_alloc[slot]->ccb_cnt++;
+ error = 0;
+ }
+ }
+ spin_unlock(&hw->alloc_lock);
+
+ if (!error)
+ fp->private_data = hw->ccb_alloc[slot];
+
+ return error;
+}
+
+static const struct file_operations ilo_fops = {
+ .owner = THIS_MODULE,
+ .read = ilo_read,
+ .write = ilo_write,
+ .open = ilo_open,
+ .release = ilo_close,
+};
+
+static void ilo_unmap_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
+{
+ pci_iounmap(pdev, hw->db_vaddr);
+ pci_iounmap(pdev, hw->ram_vaddr);
+ pci_iounmap(pdev, hw->mmio_vaddr);
+}
+
+static int __devinit ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
+{
+ int error = -ENOMEM;
+
+ /* map the memory mapped i/o registers */
+ hw->mmio_vaddr = pci_iomap(pdev, 1, 0);
+ if (hw->mmio_vaddr == NULL) {
+ dev_err(&pdev->dev, "Error mapping mmio\n");
+ goto out;
+ }
+
+ /* map the adapter shared memory region */
+ hw->ram_vaddr = pci_iomap(pdev, 2, MAX_CCB * ILOHW_CCB_SZ);
+ if (hw->ram_vaddr == NULL) {
+ dev_err(&pdev->dev, "Error mapping shared mem\n");
+ goto mmio_free;
+ }
+
+ /* map the doorbell aperture */
+ hw->db_vaddr = pci_iomap(pdev, 3, MAX_CCB * ONE_DB_SIZE);
+ if (hw->db_vaddr == NULL) {
+ dev_err(&pdev->dev, "Error mapping doorbell\n");
+ goto ram_free;
+ }
+
+ return 0;
+ram_free:
+ pci_iounmap(pdev, hw->ram_vaddr);
+mmio_free:
+ pci_iounmap(pdev, hw->mmio_vaddr);
+out:
+ return error;
+}
+
+static void ilo_remove(struct pci_dev *pdev)
+{
+ int i, minor;
+ struct ilo_hwinfo *ilo_hw = pci_get_drvdata(pdev);
+
+ clear_device(ilo_hw);
+
+ minor = MINOR(ilo_hw->cdev.dev);
+ for (i = minor; i < minor + MAX_CCB; i++)
+ device_destroy(ilo_class, MKDEV(ilo_major, i));
+
+ cdev_del(&ilo_hw->cdev);
+ ilo_unmap_device(pdev, ilo_hw);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ kfree(ilo_hw);
+ ilo_hwdev[(minor / MAX_CCB)] = 0;
+}
+
+static int __devinit ilo_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int devnum, minor, start, error;
+ struct ilo_hwinfo *ilo_hw;
+
+ /* find a free range for device files */
+ for (devnum = 0; devnum < MAX_ILO_DEV; devnum++) {
+ if (ilo_hwdev[devnum] == 0) {
+ ilo_hwdev[devnum] = 1;
+ break;
+ }
+ }
+
+ if (devnum == MAX_ILO_DEV) {
+ dev_err(&pdev->dev, "Error finding free device\n");
+ return -ENODEV;
+ }
+
+ /* track global allocations for this device */
+ error = -ENOMEM;
+ ilo_hw = kzalloc(sizeof(*ilo_hw), GFP_KERNEL);
+ if (!ilo_hw)
+ goto out;
+
+ ilo_hw->ilo_dev = pdev;
+ spin_lock_init(&ilo_hw->alloc_lock);
+ spin_lock_init(&ilo_hw->fifo_lock);
+
+ error = pci_enable_device(pdev);
+ if (error)
+ goto free;
+
+ pci_set_master(pdev);
+
+ error = pci_request_regions(pdev, ILO_NAME);
+ if (error)
+ goto disable;
+
+ error = ilo_map_device(pdev, ilo_hw);
+ if (error)
+ goto free_regions;
+
+ pci_set_drvdata(pdev, ilo_hw);
+ clear_device(ilo_hw);
+
+ cdev_init(&ilo_hw->cdev, &ilo_fops);
+ ilo_hw->cdev.owner = THIS_MODULE;
+ start = devnum * MAX_CCB;
+ error = cdev_add(&ilo_hw->cdev, MKDEV(ilo_major, start), MAX_CCB);
+ if (error) {
+ dev_err(&pdev->dev, "Could not add cdev\n");
+ goto unmap;
+ }
+
+ for (minor = 0 ; minor < MAX_CCB; minor++) {
+ struct device *dev;
+ dev = device_create(ilo_class, &pdev->dev,
+ MKDEV(ilo_major, minor), NULL,
+ "hpilo!d%dccb%d", devnum, minor);
+ if (IS_ERR(dev))
+ dev_err(&pdev->dev, "Could not create files\n");
+ }
+
+ return 0;
+unmap:
+ ilo_unmap_device(pdev, ilo_hw);
+free_regions:
+ pci_release_regions(pdev);
+disable:
+ pci_disable_device(pdev);
+free:
+ kfree(ilo_hw);
+out:
+ ilo_hwdev[devnum] = 0;
+ return error;
+}
+
+static struct pci_device_id ilo_devices[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB204) },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, ilo_devices);
+
+static struct pci_driver ilo_driver = {
+ .name = ILO_NAME,
+ .id_table = ilo_devices,
+ .probe = ilo_probe,
+ .remove = __devexit_p(ilo_remove),
+};
+
+static int __init ilo_init(void)
+{
+ int error;
+ dev_t dev;
+
+ ilo_class = class_create(THIS_MODULE, "iLO");
+ if (IS_ERR(ilo_class)) {
+ error = PTR_ERR(ilo_class);
+ goto out;
+ }
+
+ error = alloc_chrdev_region(&dev, 0, MAX_OPEN, ILO_NAME);
+ if (error)
+ goto class_destroy;
+
+ ilo_major = MAJOR(dev);
+
+ error = pci_register_driver(&ilo_driver);
+ if (error)
+ goto chr_remove;
+
+ return 0;
+chr_remove:
+ unregister_chrdev_region(dev, MAX_OPEN);
+class_destroy:
+ class_destroy(ilo_class);
+out:
+ return error;
+}
+
+static void __exit ilo_exit(void)
+{
+ pci_unregister_driver(&ilo_driver);
+ unregister_chrdev_region(MKDEV(ilo_major, 0), MAX_OPEN);
+ class_destroy(ilo_class);
+}
+
+MODULE_VERSION("0.05");
+MODULE_ALIAS(ILO_NAME);
+MODULE_DESCRIPTION(ILO_NAME);
+MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>");
+MODULE_LICENSE("GPL v2");
+
+module_init(ilo_init);
+module_exit(ilo_exit);
diff --git a/drivers/misc/hpilo.h b/drivers/misc/hpilo.h
new file mode 100644
index 00000000000..a281207696c
--- /dev/null
+++ b/drivers/misc/hpilo.h
@@ -0,0 +1,189 @@
+/*
+ * linux/drivers/char/hpilo.h
+ *
+ * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
+ * David Altobelli <david.altobelli@hp.com>
+ *
+ * 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.
+ */
+#ifndef __HPILO_H
+#define __HPILO_H
+
+#define ILO_NAME "hpilo"
+
+/* max number of open channel control blocks per device, hw limited to 32 */
+#define MAX_CCB 8
+/* max number of supported devices */
+#define MAX_ILO_DEV 1
+/* max number of files */
+#define MAX_OPEN (MAX_CCB * MAX_ILO_DEV)
+
+/*
+ * Per device, used to track global memory allocations.
+ */
+struct ilo_hwinfo {
+ /* mmio registers on device */
+ char __iomem *mmio_vaddr;
+
+ /* doorbell registers on device */
+ char __iomem *db_vaddr;
+
+ /* shared memory on device used for channel control blocks */
+ char __iomem *ram_vaddr;
+
+ /* files corresponding to this device */
+ struct ccb_data *ccb_alloc[MAX_CCB];
+
+ struct pci_dev *ilo_dev;
+
+ spinlock_t alloc_lock;
+ spinlock_t fifo_lock;
+
+ struct cdev cdev;
+};
+
+/* offset from mmio_vaddr */
+#define DB_OUT 0xD4
+/* DB_OUT reset bit */
+#define DB_RESET 26
+
+/*
+ * Channel control block. Used to manage hardware queues.
+ * The format must match hw's version. The hw ccb is 128 bytes,
+ * but the context area shouldn't be touched by the driver.
+ */
+#define ILOSW_CCB_SZ 64
+#define ILOHW_CCB_SZ 128
+struct ccb {
+ union {
+ char *send_fifobar;
+ u64 padding1;
+ } ccb_u1;
+ union {
+ char *send_desc;
+ u64 padding2;
+ } ccb_u2;
+ u64 send_ctrl;
+
+ union {
+ char *recv_fifobar;
+ u64 padding3;
+ } ccb_u3;
+ union {
+ char *recv_desc;
+ u64 padding4;
+ } ccb_u4;
+ u64 recv_ctrl;
+
+ union {
+ char __iomem *db_base;
+ u64 padding5;
+ } ccb_u5;
+
+ u64 channel;
+
+ /* unused context area (64 bytes) */
+};
+
+/* ccb queue parameters */
+#define SENDQ 1
+#define RECVQ 2
+#define NR_QENTRY 4
+#define L2_QENTRY_SZ 12
+
+/* ccb ctrl bitfields */
+#define CTRL_BITPOS_L2SZ 0
+#define CTRL_BITPOS_FIFOINDEXMASK 4
+#define CTRL_BITPOS_DESCLIMIT 18
+#define CTRL_BITPOS_A 30
+#define CTRL_BITPOS_G 31
+
+/* ccb doorbell macros */
+#define L2_DB_SIZE 14
+#define ONE_DB_SIZE (1 << L2_DB_SIZE)
+
+/*
+ * Per fd structure used to track the ccb allocated to that dev file.
+ */
+struct ccb_data {
+ /* software version of ccb, using virtual addrs */
+ struct ccb driver_ccb;
+
+ /* hardware version of ccb, using physical addrs */
+ struct ccb ilo_ccb;
+
+ /* hardware ccb is written to this shared mapped device memory */
+ struct ccb __iomem *mapped_ccb;
+
+ /* dma'able memory used for send/recv queues */
+ void *dma_va;
+ dma_addr_t dma_pa;
+ size_t dma_size;
+
+ /* pointer to hardware device info */
+ struct ilo_hwinfo *ilo_hw;
+
+ /* usage count, to allow for shared ccb's */
+ int ccb_cnt;
+
+ /* open wanted exclusive access to this ccb */
+ int ccb_excl;
+};
+
+/*
+ * FIFO queue structure, shared with hw.
+ */
+#define ILO_START_ALIGN 4096
+#define ILO_CACHE_SZ 128
+struct fifo {
+ u64 nrents; /* user requested number of fifo entries */
+ u64 imask; /* mask to extract valid fifo index */
+ u64 merge; /* O/C bits to merge in during enqueue operation */
+ u64 reset; /* set to non-zero when the target device resets */
+ u8 pad_0[ILO_CACHE_SZ - (sizeof(u64) * 4)];
+
+ u64 head;
+ u8 pad_1[ILO_CACHE_SZ - (sizeof(u64))];
+
+ u64 tail;
+ u8 pad_2[ILO_CACHE_SZ - (sizeof(u64))];
+
+ u64 fifobar[1];
+};
+
+/* convert between struct fifo, and the fifobar, which is saved in the ccb */
+#define FIFOHANDLESIZE (sizeof(struct fifo) - sizeof(u64))
+#define FIFOBARTOHANDLE(_fifo) \
+ ((struct fifo *)(((char *)(_fifo)) - FIFOHANDLESIZE))
+
+/* the number of qwords to consume from the entry descriptor */
+#define ENTRY_BITPOS_QWORDS 0
+/* descriptor index number (within a specified queue) */
+#define ENTRY_BITPOS_DESCRIPTOR 10
+/* state bit, fifo entry consumed by consumer */
+#define ENTRY_BITPOS_C 22
+/* state bit, fifo entry is occupied */
+#define ENTRY_BITPOS_O 23
+
+#define ENTRY_BITS_QWORDS 10
+#define ENTRY_BITS_DESCRIPTOR 12
+#define ENTRY_BITS_C 1
+#define ENTRY_BITS_O 1
+#define ENTRY_BITS_TOTAL \
+ (ENTRY_BITS_C + ENTRY_BITS_O + \
+ ENTRY_BITS_QWORDS + ENTRY_BITS_DESCRIPTOR)
+
+/* extract various entry fields */
+#define ENTRY_MASK ((1 << ENTRY_BITS_TOTAL) - 1)
+#define ENTRY_MASK_C (((1 << ENTRY_BITS_C) - 1) << ENTRY_BITPOS_C)
+#define ENTRY_MASK_O (((1 << ENTRY_BITS_O) - 1) << ENTRY_BITPOS_O)
+#define ENTRY_MASK_QWORDS \
+ (((1 << ENTRY_BITS_QWORDS) - 1) << ENTRY_BITPOS_QWORDS)
+#define ENTRY_MASK_DESCRIPTOR \
+ (((1 << ENTRY_BITS_DESCRIPTOR) - 1) << ENTRY_BITPOS_DESCRIPTOR)
+
+#define ENTRY_MASK_NOSTATE (ENTRY_MASK >> (ENTRY_BITS_C + ENTRY_BITS_O))
+
+#endif /* __HPILO_H */
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index 18616247009..daf585689ce 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -399,8 +399,9 @@ static int __devinit phantom_probe(struct pci_dev *pdev,
goto err_irq;
}
- if (IS_ERR(device_create(phantom_class, &pdev->dev, MKDEV(phantom_major,
- minor), "phantom%u", minor)))
+ if (IS_ERR(device_create_drvdata(phantom_class, &pdev->dev,
+ MKDEV(phantom_major, minor),
+ NULL, "phantom%u", minor)))
dev_err(&pdev->dev, "can't create device\n");
pci_set_drvdata(pdev, pht);
@@ -562,6 +563,6 @@ module_init(phantom_init);
module_exit(phantom_exit);
MODULE_AUTHOR("Jiri Slaby <jirislaby@gmail.com>");
-MODULE_DESCRIPTION("Sensable Phantom driver");
+MODULE_DESCRIPTION("Sensable Phantom driver (PCI devices)");
MODULE_LICENSE("GPL");
MODULE_VERSION(PHANTOM_VERSION);
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c
index 08256ed0d9a..579b01ff82d 100644
--- a/drivers/misc/sgi-xp/xpc_main.c
+++ b/drivers/misc/sgi-xp/xpc_main.c
@@ -229,10 +229,11 @@ xpc_hb_checker(void *ignore)
int last_IRQ_count = 0;
int new_IRQ_count;
int force_IRQ = 0;
+ cpumask_of_cpu_ptr(cpumask, XPC_HB_CHECK_CPU);
/* this thread was marked active by xpc_hb_init() */
- set_cpus_allowed(current, cpumask_of_cpu(XPC_HB_CHECK_CPU));
+ set_cpus_allowed_ptr(current, cpumask);
/* set our heartbeating to other partitions into motion */
xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ);
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index b5969298f3d..d3eb7903c34 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -21,7 +21,7 @@
* 02110-1301, USA.
*/
-#define TPACPI_VERSION "0.20"
+#define TPACPI_VERSION "0.21"
#define TPACPI_SYSFS_VERSION 0x020200
/*
@@ -68,6 +68,7 @@
#include <linux/hwmon-sysfs.h>
#include <linux/input.h>
#include <linux/leds.h>
+#include <linux/rfkill.h>
#include <asm/uaccess.h>
#include <linux/dmi.h>
@@ -144,6 +145,12 @@ enum {
#define TPACPI_MAX_ACPI_ARGS 3
+/* rfkill switches */
+enum {
+ TPACPI_RFK_BLUETOOTH_SW_ID = 0,
+ TPACPI_RFK_WWAN_SW_ID,
+};
+
/* Debugging */
#define TPACPI_LOG TPACPI_FILE ": "
#define TPACPI_ERR KERN_ERR TPACPI_LOG
@@ -905,6 +912,43 @@ static int __init tpacpi_check_std_acpi_brightness_support(void)
return 0;
}
+static int __init tpacpi_new_rfkill(const unsigned int id,
+ struct rfkill **rfk,
+ const enum rfkill_type rfktype,
+ const char *name,
+ int (*toggle_radio)(void *, enum rfkill_state),
+ int (*get_state)(void *, enum rfkill_state *))
+{
+ int res;
+ enum rfkill_state initial_state;
+
+ *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype);
+ if (!*rfk) {
+ printk(TPACPI_ERR
+ "failed to allocate memory for rfkill class\n");
+ return -ENOMEM;
+ }
+
+ (*rfk)->name = name;
+ (*rfk)->get_state = get_state;
+ (*rfk)->toggle_radio = toggle_radio;
+
+ if (!get_state(NULL, &initial_state))
+ (*rfk)->state = initial_state;
+
+ res = rfkill_register(*rfk);
+ if (res < 0) {
+ printk(TPACPI_ERR
+ "failed to register %s rfkill switch: %d\n",
+ name, res);
+ rfkill_free(*rfk);
+ *rfk = NULL;
+ return res;
+ }
+
+ return 0;
+}
+
/*************************************************************************
* thinkpad-acpi driver attributes
*/
@@ -1285,21 +1329,6 @@ static int hotkey_status_set(int status)
return 0;
}
-static void tpacpi_input_send_radiosw(void)
-{
- int wlsw;
-
- if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) {
- mutex_lock(&tpacpi_inputdev_send_mutex);
-
- input_report_switch(tpacpi_inputdev,
- SW_RFKILL_ALL, !!wlsw);
- input_sync(tpacpi_inputdev);
-
- mutex_unlock(&tpacpi_inputdev_send_mutex);
- }
-}
-
static void tpacpi_input_send_tabletsw(void)
{
int state;
@@ -1921,6 +1950,30 @@ static struct attribute *hotkey_mask_attributes[] __initdata = {
&dev_attr_hotkey_wakeup_hotunplug_complete.attr,
};
+static void bluetooth_update_rfk(void);
+static void wan_update_rfk(void);
+static void tpacpi_send_radiosw_update(void)
+{
+ int wlsw;
+
+ /* Sync these BEFORE sending any rfkill events */
+ if (tp_features.bluetooth)
+ bluetooth_update_rfk();
+ if (tp_features.wan)
+ wan_update_rfk();
+
+ if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) {
+ mutex_lock(&tpacpi_inputdev_send_mutex);
+
+ input_report_switch(tpacpi_inputdev,
+ SW_RFKILL_ALL, !!wlsw);
+ input_sync(tpacpi_inputdev);
+
+ mutex_unlock(&tpacpi_inputdev_send_mutex);
+ }
+ hotkey_radio_sw_notify_change();
+}
+
static void hotkey_exit(void)
{
#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
@@ -2167,9 +2220,10 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
printk(TPACPI_INFO
"radio switch found; radios are %s\n",
enabled(status, 0));
+ }
+ if (tp_features.hotkey_wlsw)
res = add_to_attr_set(hotkey_dev_attributes,
&dev_attr_hotkey_radio_sw.attr);
- }
/* For X41t, X60t, X61t Tablets... */
if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
@@ -2287,7 +2341,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
tpacpi_inputdev->close = &hotkey_inputdev_close;
hotkey_poll_setup_safe(1);
- tpacpi_input_send_radiosw();
+ tpacpi_send_radiosw_update();
tpacpi_input_send_tabletsw();
return 0;
@@ -2419,8 +2473,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
case 7:
/* 0x7000-0x7FFF: misc */
if (tp_features.hotkey_wlsw && hkey == 0x7000) {
- tpacpi_input_send_radiosw();
- hotkey_radio_sw_notify_change();
+ tpacpi_send_radiosw_update();
send_acpi_ev = 0;
break;
}
@@ -2463,8 +2516,7 @@ static void hotkey_resume(void)
printk(TPACPI_ERR
"error while trying to read hot key mask "
"from firmware\n");
- tpacpi_input_send_radiosw();
- hotkey_radio_sw_notify_change();
+ tpacpi_send_radiosw_update();
hotkey_tablet_mode_notify_change();
hotkey_wakeup_reason_notify_change();
hotkey_wakeup_hotunplug_complete_notify_change();
@@ -2581,8 +2633,66 @@ enum {
TP_ACPI_BLUETOOTH_UNK = 0x04, /* unknown function */
};
-static int bluetooth_get_radiosw(void);
-static int bluetooth_set_radiosw(int radio_on);
+static struct rfkill *tpacpi_bluetooth_rfkill;
+
+static int bluetooth_get_radiosw(void)
+{
+ int status;
+
+ if (!tp_features.bluetooth)
+ return -ENODEV;
+
+ /* WLSW overrides bluetooth in firmware/hardware, reflect that */
+ if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
+ return RFKILL_STATE_HARD_BLOCKED;
+
+ if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
+ return -EIO;
+
+ return ((status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0) ?
+ RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED;
+}
+
+static void bluetooth_update_rfk(void)
+{
+ int status;
+
+ if (!tpacpi_bluetooth_rfkill)
+ return;
+
+ status = bluetooth_get_radiosw();
+ if (status < 0)
+ return;
+ rfkill_force_state(tpacpi_bluetooth_rfkill, status);
+}
+
+static int bluetooth_set_radiosw(int radio_on, int update_rfk)
+{
+ int status;
+
+ if (!tp_features.bluetooth)
+ return -ENODEV;
+
+ /* WLSW overrides bluetooth in firmware/hardware, but there is no
+ * reason to risk weird behaviour. */
+ if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status
+ && radio_on)
+ return -EPERM;
+
+ if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
+ return -EIO;
+ if (radio_on)
+ status |= TP_ACPI_BLUETOOTH_RADIOSSW;
+ else
+ status &= ~TP_ACPI_BLUETOOTH_RADIOSSW;
+ if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
+ return -EIO;
+
+ if (update_rfk)
+ bluetooth_update_rfk();
+
+ return 0;
+}
/* sysfs bluetooth enable ---------------------------------------------- */
static ssize_t bluetooth_enable_show(struct device *dev,
@@ -2595,7 +2705,8 @@ static ssize_t bluetooth_enable_show(struct device *dev,
if (status < 0)
return status;
- return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0);
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ (status == RFKILL_STATE_UNBLOCKED) ? 1 : 0);
}
static ssize_t bluetooth_enable_store(struct device *dev,
@@ -2608,7 +2719,7 @@ static ssize_t bluetooth_enable_store(struct device *dev,
if (parse_strtoul(buf, 1, &t))
return -EINVAL;
- res = bluetooth_set_radiosw(t);
+ res = bluetooth_set_radiosw(t, 1);
return (res) ? res : count;
}
@@ -2628,6 +2739,31 @@ static const struct attribute_group bluetooth_attr_group = {
.attrs = bluetooth_attributes,
};
+static int tpacpi_bluetooth_rfk_get(void *data, enum rfkill_state *state)
+{
+ int bts = bluetooth_get_radiosw();
+
+ if (bts < 0)
+ return bts;
+
+ *state = bts;
+ return 0;
+}
+
+static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state)
+{
+ return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
+}
+
+static void bluetooth_exit(void)
+{
+ if (tpacpi_bluetooth_rfkill)
+ rfkill_unregister(tpacpi_bluetooth_rfkill);
+
+ sysfs_remove_group(&tpacpi_pdev->dev.kobj,
+ &bluetooth_attr_group);
+}
+
static int __init bluetooth_init(struct ibm_init_struct *iibm)
{
int res;
@@ -2646,57 +2782,32 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
str_supported(tp_features.bluetooth),
status);
- if (tp_features.bluetooth) {
- if (!(status & TP_ACPI_BLUETOOTH_HWPRESENT)) {
- /* no bluetooth hardware present in system */
- tp_features.bluetooth = 0;
- dbg_printk(TPACPI_DBG_INIT,
- "bluetooth hardware not installed\n");
- } else {
- res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
- &bluetooth_attr_group);
- if (res)
- return res;
- }
+ if (tp_features.bluetooth &&
+ !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) {
+ /* no bluetooth hardware present in system */
+ tp_features.bluetooth = 0;
+ dbg_printk(TPACPI_DBG_INIT,
+ "bluetooth hardware not installed\n");
}
- return (tp_features.bluetooth)? 0 : 1;
-}
-
-static void bluetooth_exit(void)
-{
- sysfs_remove_group(&tpacpi_pdev->dev.kobj,
- &bluetooth_attr_group);
-}
-
-static int bluetooth_get_radiosw(void)
-{
- int status;
-
if (!tp_features.bluetooth)
- return -ENODEV;
-
- if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
- return -EIO;
-
- return ((status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0);
-}
-
-static int bluetooth_set_radiosw(int radio_on)
-{
- int status;
+ return 1;
- if (!tp_features.bluetooth)
- return -ENODEV;
+ res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
+ &bluetooth_attr_group);
+ if (res)
+ return res;
- if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
- return -EIO;
- if (radio_on)
- status |= TP_ACPI_BLUETOOTH_RADIOSSW;
- else
- status &= ~TP_ACPI_BLUETOOTH_RADIOSSW;
- if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
- return -EIO;
+ res = tpacpi_new_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID,
+ &tpacpi_bluetooth_rfkill,
+ RFKILL_TYPE_BLUETOOTH,
+ "tpacpi_bluetooth_sw",
+ tpacpi_bluetooth_rfk_set,
+ tpacpi_bluetooth_rfk_get);
+ if (res) {
+ bluetooth_exit();
+ return res;
+ }
return 0;
}
@@ -2711,7 +2822,8 @@ static int bluetooth_read(char *p)
len += sprintf(p + len, "status:\t\tnot supported\n");
else {
len += sprintf(p + len, "status:\t\t%s\n",
- (status)? "enabled" : "disabled");
+ (status == RFKILL_STATE_UNBLOCKED) ?
+ "enabled" : "disabled");
len += sprintf(p + len, "commands:\tenable, disable\n");
}
@@ -2727,9 +2839,9 @@ static int bluetooth_write(char *buf)
while ((cmd = next_cmd(&buf))) {
if (strlencmp(cmd, "enable") == 0) {
- bluetooth_set_radiosw(1);
+ bluetooth_set_radiosw(1, 1);
} else if (strlencmp(cmd, "disable") == 0) {
- bluetooth_set_radiosw(0);
+ bluetooth_set_radiosw(0, 1);
} else
return -EINVAL;
}
@@ -2755,8 +2867,66 @@ enum {
TP_ACPI_WANCARD_UNK = 0x04, /* unknown function */
};
-static int wan_get_radiosw(void);
-static int wan_set_radiosw(int radio_on);
+static struct rfkill *tpacpi_wan_rfkill;
+
+static int wan_get_radiosw(void)
+{
+ int status;
+
+ if (!tp_features.wan)
+ return -ENODEV;
+
+ /* WLSW overrides WWAN in firmware/hardware, reflect that */
+ if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
+ return RFKILL_STATE_HARD_BLOCKED;
+
+ if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
+ return -EIO;
+
+ return ((status & TP_ACPI_WANCARD_RADIOSSW) != 0) ?
+ RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED;
+}
+
+static void wan_update_rfk(void)
+{
+ int status;
+
+ if (!tpacpi_wan_rfkill)
+ return;
+
+ status = wan_get_radiosw();
+ if (status < 0)
+ return;
+ rfkill_force_state(tpacpi_wan_rfkill, status);
+}
+
+static int wan_set_radiosw(int radio_on, int update_rfk)
+{
+ int status;
+
+ if (!tp_features.wan)
+ return -ENODEV;
+
+ /* WLSW overrides bluetooth in firmware/hardware, but there is no
+ * reason to risk weird behaviour. */
+ if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status
+ && radio_on)
+ return -EPERM;
+
+ if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
+ return -EIO;
+ if (radio_on)
+ status |= TP_ACPI_WANCARD_RADIOSSW;
+ else
+ status &= ~TP_ACPI_WANCARD_RADIOSSW;
+ if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
+ return -EIO;
+
+ if (update_rfk)
+ wan_update_rfk();
+
+ return 0;
+}
/* sysfs wan enable ---------------------------------------------------- */
static ssize_t wan_enable_show(struct device *dev,
@@ -2769,7 +2939,8 @@ static ssize_t wan_enable_show(struct device *dev,
if (status < 0)
return status;
- return snprintf(buf, PAGE_SIZE, "%d\n", status ? 1 : 0);
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ (status == RFKILL_STATE_UNBLOCKED) ? 1 : 0);
}
static ssize_t wan_enable_store(struct device *dev,
@@ -2782,7 +2953,7 @@ static ssize_t wan_enable_store(struct device *dev,
if (parse_strtoul(buf, 1, &t))
return -EINVAL;
- res = wan_set_radiosw(t);
+ res = wan_set_radiosw(t, 1);
return (res) ? res : count;
}
@@ -2802,6 +2973,31 @@ static const struct attribute_group wan_attr_group = {
.attrs = wan_attributes,
};
+static int tpacpi_wan_rfk_get(void *data, enum rfkill_state *state)
+{
+ int wans = wan_get_radiosw();
+
+ if (wans < 0)
+ return wans;
+
+ *state = wans;
+ return 0;
+}
+
+static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state)
+{
+ return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
+}
+
+static void wan_exit(void)
+{
+ if (tpacpi_wan_rfkill)
+ rfkill_unregister(tpacpi_wan_rfkill);
+
+ sysfs_remove_group(&tpacpi_pdev->dev.kobj,
+ &wan_attr_group);
+}
+
static int __init wan_init(struct ibm_init_struct *iibm)
{
int res;
@@ -2818,57 +3014,32 @@ static int __init wan_init(struct ibm_init_struct *iibm)
str_supported(tp_features.wan),
status);
- if (tp_features.wan) {
- if (!(status & TP_ACPI_WANCARD_HWPRESENT)) {
- /* no wan hardware present in system */
- tp_features.wan = 0;
- dbg_printk(TPACPI_DBG_INIT,
- "wan hardware not installed\n");
- } else {
- res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
- &wan_attr_group);
- if (res)
- return res;
- }
+ if (tp_features.wan &&
+ !(status & TP_ACPI_WANCARD_HWPRESENT)) {
+ /* no wan hardware present in system */
+ tp_features.wan = 0;
+ dbg_printk(TPACPI_DBG_INIT,
+ "wan hardware not installed\n");
}
- return (tp_features.wan)? 0 : 1;
-}
-
-static void wan_exit(void)
-{
- sysfs_remove_group(&tpacpi_pdev->dev.kobj,
- &wan_attr_group);
-}
-
-static int wan_get_radiosw(void)
-{
- int status;
-
if (!tp_features.wan)
- return -ENODEV;
-
- if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
- return -EIO;
-
- return ((status & TP_ACPI_WANCARD_RADIOSSW) != 0);
-}
-
-static int wan_set_radiosw(int radio_on)
-{
- int status;
+ return 1;
- if (!tp_features.wan)
- return -ENODEV;
+ res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
+ &wan_attr_group);
+ if (res)
+ return res;
- if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
- return -EIO;
- if (radio_on)
- status |= TP_ACPI_WANCARD_RADIOSSW;
- else
- status &= ~TP_ACPI_WANCARD_RADIOSSW;
- if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
- return -EIO;
+ res = tpacpi_new_rfkill(TPACPI_RFK_WWAN_SW_ID,
+ &tpacpi_wan_rfkill,
+ RFKILL_TYPE_WWAN,
+ "tpacpi_wwan_sw",
+ tpacpi_wan_rfk_set,
+ tpacpi_wan_rfk_get);
+ if (res) {
+ wan_exit();
+ return res;
+ }
return 0;
}
@@ -2883,7 +3054,8 @@ static int wan_read(char *p)
len += sprintf(p + len, "status:\t\tnot supported\n");
else {
len += sprintf(p + len, "status:\t\t%s\n",
- (status)? "enabled" : "disabled");
+ (status == RFKILL_STATE_UNBLOCKED) ?
+ "enabled" : "disabled");
len += sprintf(p + len, "commands:\tenable, disable\n");
}
@@ -2899,9 +3071,9 @@ static int wan_write(char *buf)
while ((cmd = next_cmd(&buf))) {
if (strlencmp(cmd, "enable") == 0) {
- wan_set_radiosw(1);
+ wan_set_radiosw(1, 1);
} else if (strlencmp(cmd, "disable") == 0) {
- wan_set_radiosw(0);
+ wan_set_radiosw(0, 1);
} else
return -EINVAL;
}
@@ -6168,13 +6340,18 @@ err_out:
/* Probing */
-static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp)
+/* returns 0 - probe ok, or < 0 - probe error.
+ * Probe ok doesn't mean thinkpad found.
+ * On error, kfree() cleanup on tp->* is not performed, caller must do it */
+static int __must_check __init get_thinkpad_model_data(
+ struct thinkpad_id_data *tp)
{
const struct dmi_device *dev = NULL;
char ec_fw_string[18];
+ char const *s;
if (!tp)
- return;
+ return -EINVAL;
memset(tp, 0, sizeof(*tp));
@@ -6183,12 +6360,14 @@ static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp)
else if (dmi_name_in_vendors("LENOVO"))
tp->vendor = PCI_VENDOR_ID_LENOVO;
else
- return;
+ return 0;
- tp->bios_version_str = kstrdup(dmi_get_system_info(DMI_BIOS_VERSION),
- GFP_KERNEL);
+ s = dmi_get_system_info(DMI_BIOS_VERSION);
+ tp->bios_version_str = kstrdup(s, GFP_KERNEL);
+ if (s && !tp->bios_version_str)
+ return -ENOMEM;
if (!tp->bios_version_str)
- return;
+ return 0;
tp->bios_model = tp->bios_version_str[0]
| (tp->bios_version_str[1] << 8);
@@ -6207,21 +6386,27 @@ static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp)
ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL);
+ if (!tp->ec_version_str)
+ return -ENOMEM;
tp->ec_model = ec_fw_string[0]
| (ec_fw_string[1] << 8);
break;
}
}
- tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION),
- GFP_KERNEL);
- if (tp->model_str && strnicmp(tp->model_str, "ThinkPad", 8) != 0) {
- kfree(tp->model_str);
- tp->model_str = NULL;
+ s = dmi_get_system_info(DMI_PRODUCT_VERSION);
+ if (s && !strnicmp(s, "ThinkPad", 8)) {
+ tp->model_str = kstrdup(s, GFP_KERNEL);
+ if (!tp->model_str)
+ return -ENOMEM;
}
- tp->nummodel_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_NAME),
- GFP_KERNEL);
+ s = dmi_get_system_info(DMI_PRODUCT_NAME);
+ tp->nummodel_str = kstrdup(s, GFP_KERNEL);
+ if (s && !tp->nummodel_str)
+ return -ENOMEM;
+
+ return 0;
}
static int __init probe_for_thinkpad(void)
@@ -6484,7 +6669,13 @@ static int __init thinkpad_acpi_module_init(void)
/* Driver-level probe */
- get_thinkpad_model_data(&thinkpad_id);
+ ret = get_thinkpad_model_data(&thinkpad_id);
+ if (ret) {
+ printk(TPACPI_ERR
+ "unable to get DMI data: %d\n", ret);
+ thinkpad_acpi_module_exit();
+ return ret;
+ }
ret = probe_for_thinkpad();
if (ret) {
thinkpad_acpi_module_exit();
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index d6b9b486417..a067fe43630 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -21,13 +21,17 @@
#define RESULT_UNSUP_HOST 2
#define RESULT_UNSUP_CARD 3
-#define BUFFER_SIZE (PAGE_SIZE * 4)
+#define BUFFER_ORDER 2
+#define BUFFER_SIZE (PAGE_SIZE << BUFFER_ORDER)
struct mmc_test_card {
struct mmc_card *card;
u8 scratch[BUFFER_SIZE];
u8 *buffer;
+#ifdef CONFIG_HIGHMEM
+ struct page *highmem;
+#endif
};
/*******************************************************************/
@@ -384,14 +388,16 @@ static int mmc_test_transfer(struct mmc_test_card *test,
int ret, i;
unsigned long flags;
+ BUG_ON(blocks * blksz > BUFFER_SIZE);
+
if (write) {
for (i = 0;i < blocks * blksz;i++)
test->scratch[i] = i;
} else {
- memset(test->scratch, 0, BUFFER_SIZE);
+ memset(test->scratch, 0, blocks * blksz);
}
local_irq_save(flags);
- sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
+ sg_copy_from_buffer(sg, sg_len, test->scratch, blocks * blksz);
local_irq_restore(flags);
ret = mmc_test_set_blksize(test, blksz);
@@ -438,7 +444,7 @@ static int mmc_test_transfer(struct mmc_test_card *test,
}
} else {
local_irq_save(flags);
- sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
+ sg_copy_to_buffer(sg, sg_len, test->scratch, blocks * blksz);
local_irq_restore(flags);
for (i = 0;i < blocks * blksz;i++) {
if (test->scratch[i] != (u8)i)
@@ -799,6 +805,157 @@ static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
return 0;
}
+static int mmc_test_bigsg_write(struct mmc_test_card *test)
+{
+ int ret;
+ unsigned int size;
+ struct scatterlist sg;
+
+ if (test->card->host->max_blk_count == 1)
+ return RESULT_UNSUP_HOST;
+
+ size = PAGE_SIZE * 2;
+ size = min(size, test->card->host->max_req_size);
+ size = min(size, test->card->host->max_seg_size);
+ size = min(size, test->card->host->max_blk_count * 512);
+
+ memset(test->buffer, 0, BUFFER_SIZE);
+
+ if (size < 1024)
+ return RESULT_UNSUP_HOST;
+
+ sg_init_table(&sg, 1);
+ sg_init_one(&sg, test->buffer, BUFFER_SIZE);
+
+ ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mmc_test_bigsg_read(struct mmc_test_card *test)
+{
+ int ret, i;
+ unsigned int size;
+ struct scatterlist sg;
+
+ if (test->card->host->max_blk_count == 1)
+ return RESULT_UNSUP_HOST;
+
+ size = PAGE_SIZE * 2;
+ size = min(size, test->card->host->max_req_size);
+ size = min(size, test->card->host->max_seg_size);
+ size = min(size, test->card->host->max_blk_count * 512);
+
+ if (size < 1024)
+ return RESULT_UNSUP_HOST;
+
+ memset(test->buffer, 0xCD, BUFFER_SIZE);
+
+ sg_init_table(&sg, 1);
+ sg_init_one(&sg, test->buffer, BUFFER_SIZE);
+ ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
+ if (ret)
+ return ret;
+
+ /* mmc_test_transfer() doesn't check for read overflows */
+ for (i = size;i < BUFFER_SIZE;i++) {
+ if (test->buffer[i] != 0xCD)
+ return RESULT_FAIL;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_HIGHMEM
+
+static int mmc_test_write_high(struct mmc_test_card *test)
+{
+ int ret;
+ struct scatterlist sg;
+
+ sg_init_table(&sg, 1);
+ sg_set_page(&sg, test->highmem, 512, 0);
+
+ ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mmc_test_read_high(struct mmc_test_card *test)
+{
+ int ret;
+ struct scatterlist sg;
+
+ sg_init_table(&sg, 1);
+ sg_set_page(&sg, test->highmem, 512, 0);
+
+ ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mmc_test_multi_write_high(struct mmc_test_card *test)
+{
+ int ret;
+ unsigned int size;
+ struct scatterlist sg;
+
+ if (test->card->host->max_blk_count == 1)
+ return RESULT_UNSUP_HOST;
+
+ size = PAGE_SIZE * 2;
+ size = min(size, test->card->host->max_req_size);
+ size = min(size, test->card->host->max_seg_size);
+ size = min(size, test->card->host->max_blk_count * 512);
+
+ if (size < 1024)
+ return RESULT_UNSUP_HOST;
+
+ sg_init_table(&sg, 1);
+ sg_set_page(&sg, test->highmem, size, 0);
+
+ ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mmc_test_multi_read_high(struct mmc_test_card *test)
+{
+ int ret;
+ unsigned int size;
+ struct scatterlist sg;
+
+ if (test->card->host->max_blk_count == 1)
+ return RESULT_UNSUP_HOST;
+
+ size = PAGE_SIZE * 2;
+ size = min(size, test->card->host->max_req_size);
+ size = min(size, test->card->host->max_seg_size);
+ size = min(size, test->card->host->max_blk_count * 512);
+
+ if (size < 1024)
+ return RESULT_UNSUP_HOST;
+
+ sg_init_table(&sg, 1);
+ sg_set_page(&sg, test->highmem, size, 0);
+
+ ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+#endif /* CONFIG_HIGHMEM */
+
static const struct mmc_test_case mmc_test_cases[] = {
{
.name = "Basic write (no data verification)",
@@ -913,6 +1070,53 @@ static const struct mmc_test_case mmc_test_cases[] = {
.name = "Correct xfer_size at read (midway failure)",
.run = mmc_test_multi_xfersize_read,
},
+
+ {
+ .name = "Over-sized SG list write",
+ .prepare = mmc_test_prepare_write,
+ .run = mmc_test_bigsg_write,
+ .cleanup = mmc_test_cleanup,
+ },
+
+ {
+ .name = "Over-sized SG list read",
+ .prepare = mmc_test_prepare_read,
+ .run = mmc_test_bigsg_read,
+ .cleanup = mmc_test_cleanup,
+ },
+
+#ifdef CONFIG_HIGHMEM
+
+ {
+ .name = "Highmem write",
+ .prepare = mmc_test_prepare_write,
+ .run = mmc_test_write_high,
+ .cleanup = mmc_test_cleanup,
+ },
+
+ {
+ .name = "Highmem read",
+ .prepare = mmc_test_prepare_read,
+ .run = mmc_test_read_high,
+ .cleanup = mmc_test_cleanup,
+ },
+
+ {
+ .name = "Multi-block highmem write",
+ .prepare = mmc_test_prepare_write,
+ .run = mmc_test_multi_write_high,
+ .cleanup = mmc_test_cleanup,
+ },
+
+ {
+ .name = "Multi-block highmem read",
+ .prepare = mmc_test_prepare_read,
+ .run = mmc_test_multi_read_high,
+ .cleanup = mmc_test_cleanup,
+ },
+
+#endif /* CONFIG_HIGHMEM */
+
};
static struct mutex mmc_test_lock;
@@ -1014,12 +1218,23 @@ static ssize_t mmc_test_store(struct device *dev,
test->card = card;
test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
+#ifdef CONFIG_HIGHMEM
+ test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER);
+#endif
+
+#ifdef CONFIG_HIGHMEM
+ if (test->buffer && test->highmem) {
+#else
if (test->buffer) {
+#endif
mutex_lock(&mmc_test_lock);
mmc_test_run(test, testcase);
mutex_unlock(&mmc_test_lock);
}
+#ifdef CONFIG_HIGHMEM
+ __free_pages(test->highmem, BUFFER_ORDER);
+#endif
kfree(test->buffer);
kfree(test);
@@ -1041,6 +1256,8 @@ static int mmc_test_probe(struct mmc_card *card)
if (ret)
return ret;
+ dev_info(&card->dev, "Card claimed for testing.\n");
+
return 0;
}
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 7731ddefdc1..3dee97e7d16 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -148,7 +148,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
printk(KERN_WARNING "%s: unable to allocate "
"bounce buffer\n", mmc_card_name(card));
} else {
- blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_HIGH);
+ blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
blk_queue_max_sectors(mq->queue, bouncesz / 512);
blk_queue_max_phys_segments(mq->queue, bouncesz / 512);
blk_queue_max_hw_segments(mq->queue, bouncesz / 512);
@@ -290,55 +290,15 @@ void mmc_queue_resume(struct mmc_queue *mq)
}
}
-static void copy_sg(struct scatterlist *dst, unsigned int dst_len,
- struct scatterlist *src, unsigned int src_len)
-{
- unsigned int chunk;
- char *dst_buf, *src_buf;
- unsigned int dst_size, src_size;
-
- dst_buf = NULL;
- src_buf = NULL;
- dst_size = 0;
- src_size = 0;
-
- while (src_len) {
- BUG_ON(dst_len == 0);
-
- if (dst_size == 0) {
- dst_buf = sg_virt(dst);
- dst_size = dst->length;
- }
-
- if (src_size == 0) {
- src_buf = sg_virt(src);
- src_size = src->length;
- }
-
- chunk = min(dst_size, src_size);
-
- memcpy(dst_buf, src_buf, chunk);
-
- dst_buf += chunk;
- src_buf += chunk;
- dst_size -= chunk;
- src_size -= chunk;
-
- if (dst_size == 0) {
- dst++;
- dst_len--;
- }
-
- if (src_size == 0) {
- src++;
- src_len--;
- }
- }
-}
-
+/*
+ * Prepare the sg list(s) to be handed of to the host driver
+ */
unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
{
unsigned int sg_len;
+ size_t buflen;
+ struct scatterlist *sg;
+ int i;
if (!mq->bounce_buf)
return blk_rq_map_sg(mq->queue, mq->req, mq->sg);
@@ -349,47 +309,52 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
mq->bounce_sg_len = sg_len;
- /*
- * Shortcut in the event we only get a single entry.
- */
- if (sg_len == 1) {
- memcpy(mq->sg, mq->bounce_sg, sizeof(struct scatterlist));
- return 1;
- }
+ buflen = 0;
+ for_each_sg(mq->bounce_sg, sg, sg_len, i)
+ buflen += sg->length;
- sg_init_one(mq->sg, mq->bounce_buf, 0);
-
- while (sg_len) {
- mq->sg[0].length += mq->bounce_sg[sg_len - 1].length;
- sg_len--;
- }
+ sg_init_one(mq->sg, mq->bounce_buf, buflen);
return 1;
}
+/*
+ * If writing, bounce the data to the buffer before the request
+ * is sent to the host driver
+ */
void mmc_queue_bounce_pre(struct mmc_queue *mq)
{
+ unsigned long flags;
+
if (!mq->bounce_buf)
return;
- if (mq->bounce_sg_len == 1)
- return;
if (rq_data_dir(mq->req) != WRITE)
return;
- copy_sg(mq->sg, 1, mq->bounce_sg, mq->bounce_sg_len);
+ local_irq_save(flags);
+ sg_copy_to_buffer(mq->bounce_sg, mq->bounce_sg_len,
+ mq->bounce_buf, mq->sg[0].length);
+ local_irq_restore(flags);
}
+/*
+ * If reading, bounce the data from the buffer after the request
+ * has been handled by the host driver
+ */
void mmc_queue_bounce_post(struct mmc_queue *mq)
{
+ unsigned long flags;
+
if (!mq->bounce_buf)
return;
- if (mq->bounce_sg_len == 1)
- return;
if (rq_data_dir(mq->req) != READ)
return;
- copy_sg(mq->bounce_sg, mq->bounce_sg_len, mq->sg, 1);
+ local_irq_save(flags);
+ sg_copy_from_buffer(mq->bounce_sg, mq->bounce_sg_len,
+ mq->bounce_buf, mq->sg[0].length);
+ local_irq_restore(flags);
}
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index 3f15eb20489..99b20917cc0 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -1043,7 +1043,7 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev)
goto out6;
}
- platform_set_drvdata(pdev, mmc);
+ platform_set_drvdata(pdev, host);
printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X"
" (mode=%s)\n", pdev->id, host->iobase,
@@ -1087,13 +1087,10 @@ out0:
static int __devexit au1xmmc_remove(struct platform_device *pdev)
{
- struct mmc_host *mmc = platform_get_drvdata(pdev);
- struct au1xmmc_host *host;
-
- if (mmc) {
- host = mmc_priv(mmc);
+ struct au1xmmc_host *host = platform_get_drvdata(pdev);
- mmc_remove_host(mmc);
+ if (host) {
+ mmc_remove_host(host->mmc);
#ifdef CONFIG_LEDS_CLASS
if (host->platdata && host->platdata->led)
@@ -1101,8 +1098,8 @@ static int __devexit au1xmmc_remove(struct platform_device *pdev)
#endif
if (host->platdata && host->platdata->cd_setup &&
- !(mmc->caps & MMC_CAP_NEEDS_POLL))
- host->platdata->cd_setup(mmc, 0);
+ !(host->mmc->caps & MMC_CAP_NEEDS_POLL))
+ host->platdata->cd_setup(host->mmc, 0);
au_writel(0, HOST_ENABLE(host));
au_writel(0, HOST_CONFIG(host));
@@ -1122,16 +1119,49 @@ static int __devexit au1xmmc_remove(struct platform_device *pdev)
release_resource(host->ioarea);
kfree(host->ioarea);
- mmc_free_host(mmc);
+ mmc_free_host(host->mmc);
+ platform_set_drvdata(pdev, NULL);
}
return 0;
}
+#ifdef CONFIG_PM
+static int au1xmmc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct au1xmmc_host *host = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = mmc_suspend_host(host->mmc, state);
+ if (ret)
+ return ret;
+
+ au_writel(0, HOST_CONFIG2(host));
+ au_writel(0, HOST_CONFIG(host));
+ au_writel(0xffffffff, HOST_STATUS(host));
+ au_writel(0, HOST_ENABLE(host));
+ au_sync();
+
+ return 0;
+}
+
+static int au1xmmc_resume(struct platform_device *pdev)
+{
+ struct au1xmmc_host *host = platform_get_drvdata(pdev);
+
+ au1xmmc_reset_controller(host);
+
+ return mmc_resume_host(host->mmc);
+}
+#else
+#define au1xmmc_suspend NULL
+#define au1xmmc_resume NULL
+#endif
+
static struct platform_driver au1xmmc_driver = {
.probe = au1xmmc_probe,
.remove = au1xmmc_remove,
- .suspend = NULL,
- .resume = NULL,
+ .suspend = au1xmmc_suspend,
+ .resume = au1xmmc_resume,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index d39f5973886..a8e18fe5307 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -177,7 +177,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
if (dalgn)
DALGN |= (1 << host->dma);
else
- DALGN &= (1 << host->dma);
+ DALGN &= ~(1 << host->dma);
DDADR(host->dma) = host->sg_dma;
DCSR(host->dma) = DCSR_RUN;
}
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 6a1e4994b72..be550c26da6 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -1331,21 +1331,30 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
return ret;
}
+static void s3cmci_shutdown(struct platform_device *pdev)
+{
+ struct mmc_host *mmc = platform_get_drvdata(pdev);
+ struct s3cmci_host *host = mmc_priv(mmc);
+
+ if (host->irq_cd >= 0)
+ free_irq(host->irq_cd, host);
+
+ mmc_remove_host(mmc);
+ clk_disable(host->clk);
+}
+
static int __devexit s3cmci_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
struct s3cmci_host *host = mmc_priv(mmc);
- mmc_remove_host(mmc);
+ s3cmci_shutdown(pdev);
- clk_disable(host->clk);
clk_put(host->clk);
tasklet_disable(&host->pio_tasklet);
s3c2410_dma_free(S3CMCI_DMA, &s3cmci_dma_client);
- if (host->irq_cd >= 0)
- free_irq(host->irq_cd, host);
free_irq(host->irq, host);
iounmap(host->base);
@@ -1355,17 +1364,17 @@ static int __devexit s3cmci_remove(struct platform_device *pdev)
return 0;
}
-static int __devinit s3cmci_probe_2410(struct platform_device *dev)
+static int __devinit s3cmci_2410_probe(struct platform_device *dev)
{
return s3cmci_probe(dev, 0);
}
-static int __devinit s3cmci_probe_2412(struct platform_device *dev)
+static int __devinit s3cmci_2412_probe(struct platform_device *dev)
{
return s3cmci_probe(dev, 1);
}
-static int __devinit s3cmci_probe_2440(struct platform_device *dev)
+static int __devinit s3cmci_2440_probe(struct platform_device *dev)
{
return s3cmci_probe(dev, 1);
}
@@ -1392,29 +1401,32 @@ static int s3cmci_resume(struct platform_device *dev)
#endif /* CONFIG_PM */
-static struct platform_driver s3cmci_driver_2410 = {
+static struct platform_driver s3cmci_2410_driver = {
.driver.name = "s3c2410-sdi",
.driver.owner = THIS_MODULE,
- .probe = s3cmci_probe_2410,
+ .probe = s3cmci_2410_probe,
.remove = __devexit_p(s3cmci_remove),
+ .shutdown = s3cmci_shutdown,
.suspend = s3cmci_suspend,
.resume = s3cmci_resume,
};
-static struct platform_driver s3cmci_driver_2412 = {
+static struct platform_driver s3cmci_2412_driver = {
.driver.name = "s3c2412-sdi",
.driver.owner = THIS_MODULE,
- .probe = s3cmci_probe_2412,
+ .probe = s3cmci_2412_probe,
.remove = __devexit_p(s3cmci_remove),
+ .shutdown = s3cmci_shutdown,
.suspend = s3cmci_suspend,
.resume = s3cmci_resume,
};
-static struct platform_driver s3cmci_driver_2440 = {
+static struct platform_driver s3cmci_2440_driver = {
.driver.name = "s3c2440-sdi",
.driver.owner = THIS_MODULE,
- .probe = s3cmci_probe_2440,
+ .probe = s3cmci_2440_probe,
.remove = __devexit_p(s3cmci_remove),
+ .shutdown = s3cmci_shutdown,
.suspend = s3cmci_suspend,
.resume = s3cmci_resume,
};
@@ -1422,17 +1434,17 @@ static struct platform_driver s3cmci_driver_2440 = {
static int __init s3cmci_init(void)
{
- platform_driver_register(&s3cmci_driver_2410);
- platform_driver_register(&s3cmci_driver_2412);
- platform_driver_register(&s3cmci_driver_2440);
+ platform_driver_register(&s3cmci_2410_driver);
+ platform_driver_register(&s3cmci_2412_driver);
+ platform_driver_register(&s3cmci_2440_driver);
return 0;
}
static void __exit s3cmci_exit(void)
{
- platform_driver_unregister(&s3cmci_driver_2410);
- platform_driver_unregister(&s3cmci_driver_2412);
- platform_driver_unregister(&s3cmci_driver_2440);
+ platform_driver_unregister(&s3cmci_2410_driver);
+ platform_driver_unregister(&s3cmci_2412_driver);
+ platform_driver_unregister(&s3cmci_2440_driver);
}
module_init(s3cmci_init);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 17701c3da73..c3a5db72ddd 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -173,119 +173,95 @@ static void sdhci_led_control(struct led_classdev *led,
* *
\*****************************************************************************/
-static inline char* sdhci_sg_to_buffer(struct sdhci_host* host)
-{
- return sg_virt(host->cur_sg);
-}
-
-static inline int sdhci_next_sg(struct sdhci_host* host)
-{
- /*
- * Skip to next SG entry.
- */
- host->cur_sg++;
- host->num_sg--;
-
- /*
- * Any entries left?
- */
- if (host->num_sg > 0) {
- host->offset = 0;
- host->remain = host->cur_sg->length;
- }
-
- return host->num_sg;
-}
-
static void sdhci_read_block_pio(struct sdhci_host *host)
{
- int blksize, chunk_remain;
- u32 data;
- char *buffer;
- int size;
+ unsigned long flags;
+ size_t blksize, len, chunk;
+ u32 scratch;
+ u8 *buf;
DBG("PIO reading\n");
blksize = host->data->blksz;
- chunk_remain = 0;
- data = 0;
+ chunk = 0;
- buffer = sdhci_sg_to_buffer(host) + host->offset;
+ local_irq_save(flags);
while (blksize) {
- if (chunk_remain == 0) {
- data = readl(host->ioaddr + SDHCI_BUFFER);
- chunk_remain = min(blksize, 4);
- }
+ if (!sg_miter_next(&host->sg_miter))
+ BUG();
- size = min(host->remain, chunk_remain);
+ len = min(host->sg_miter.length, blksize);
- chunk_remain -= size;
- blksize -= size;
- host->offset += size;
- host->remain -= size;
+ blksize -= len;
+ host->sg_miter.consumed = len;
- while (size) {
- *buffer = data & 0xFF;
- buffer++;
- data >>= 8;
- size--;
- }
+ buf = host->sg_miter.addr;
- if (host->remain == 0) {
- if (sdhci_next_sg(host) == 0) {
- BUG_ON(blksize != 0);
- return;
+ while (len) {
+ if (chunk == 0) {
+ scratch = readl(host->ioaddr + SDHCI_BUFFER);
+ chunk = 4;
}
- buffer = sdhci_sg_to_buffer(host);
+
+ *buf = scratch & 0xFF;
+
+ buf++;
+ scratch >>= 8;
+ chunk--;
+ len--;
}
}
+
+ sg_miter_stop(&host->sg_miter);
+
+ local_irq_restore(flags);
}
static void sdhci_write_block_pio(struct sdhci_host *host)
{
- int blksize, chunk_remain;
- u32 data;
- char *buffer;
- int bytes, size;
+ unsigned long flags;
+ size_t blksize, len, chunk;
+ u32 scratch;
+ u8 *buf;
DBG("PIO writing\n");
blksize = host->data->blksz;
- chunk_remain = 4;
- data = 0;
+ chunk = 0;
+ scratch = 0;
- bytes = 0;
- buffer = sdhci_sg_to_buffer(host) + host->offset;
+ local_irq_save(flags);
while (blksize) {
- size = min(host->remain, chunk_remain);
-
- chunk_remain -= size;
- blksize -= size;
- host->offset += size;
- host->remain -= size;
-
- while (size) {
- data >>= 8;
- data |= (u32)*buffer << 24;
- buffer++;
- size--;
- }
+ if (!sg_miter_next(&host->sg_miter))
+ BUG();
- if (chunk_remain == 0) {
- writel(data, host->ioaddr + SDHCI_BUFFER);
- chunk_remain = min(blksize, 4);
- }
+ len = min(host->sg_miter.length, blksize);
+
+ blksize -= len;
+ host->sg_miter.consumed = len;
+
+ buf = host->sg_miter.addr;
- if (host->remain == 0) {
- if (sdhci_next_sg(host) == 0) {
- BUG_ON(blksize != 0);
- return;
+ while (len) {
+ scratch |= (u32)*buf << (chunk * 8);
+
+ buf++;
+ chunk++;
+ len--;
+
+ if ((chunk == 4) || ((len == 0) && (blksize == 0))) {
+ writel(scratch, host->ioaddr + SDHCI_BUFFER);
+ chunk = 0;
+ scratch = 0;
}
- buffer = sdhci_sg_to_buffer(host);
}
}
+
+ sg_miter_stop(&host->sg_miter);
+
+ local_irq_restore(flags);
}
static void sdhci_transfer_pio(struct sdhci_host *host)
@@ -294,7 +270,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host)
BUG_ON(!host->data);
- if (host->num_sg == 0)
+ if (host->blocks == 0)
return;
if (host->data->flags & MMC_DATA_READ)
@@ -308,7 +284,8 @@ static void sdhci_transfer_pio(struct sdhci_host *host)
else
sdhci_write_block_pio(host);
- if (host->num_sg == 0)
+ host->blocks--;
+ if (host->blocks == 0)
break;
}
@@ -389,6 +366,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
if (offset) {
if (data->flags & MMC_DATA_WRITE) {
buffer = sdhci_kmap_atomic(sg, &flags);
+ WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3));
memcpy(align, buffer, offset);
sdhci_kunmap_atomic(buffer, &flags);
}
@@ -510,6 +488,7 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
size = 4 - (sg_dma_address(sg) & 0x3);
buffer = sdhci_kmap_atomic(sg, &flags);
+ WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3));
memcpy(buffer, align, size);
sdhci_kunmap_atomic(buffer, &flags);
@@ -687,7 +666,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
WARN_ON(1);
host->flags &= ~SDHCI_USE_DMA;
} else {
- WARN_ON(count != 1);
+ WARN_ON(sg_cnt != 1);
writel(sg_dma_address(data->sg),
host->ioaddr + SDHCI_DMA_ADDRESS);
}
@@ -711,11 +690,9 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
}
if (!(host->flags & SDHCI_REQ_USE_DMA)) {
- host->cur_sg = data->sg;
- host->num_sg = data->sg_len;
-
- host->offset = 0;
- host->remain = host->cur_sg->length;
+ sg_miter_start(&host->sg_miter,
+ data->sg, data->sg_len, SG_MITER_ATOMIC);
+ host->blocks = data->blocks;
}
/* We do not handle DMA boundaries, so set it to max (512 KiB) */
@@ -1581,9 +1558,15 @@ int sdhci_add_host(struct sdhci_host *host)
}
}
- /* XXX: Hack to get MMC layer to avoid highmem */
- if (!(host->flags & SDHCI_USE_DMA))
- mmc_dev(host->mmc)->dma_mask = NULL;
+ /*
+ * If we use DMA, then it's up to the caller to set the DMA
+ * mask, but PIO does not need the hw shim so we set a new
+ * mask here in that case.
+ */
+ if (!(host->flags & SDHCI_USE_DMA)) {
+ host->dma_mask = DMA_BIT_MASK(64);
+ mmc_dev(host->mmc)->dma_mask = &host->dma_mask;
+ }
host->max_clk =
(caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 5bb35528176..a06bf8b8934 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -212,6 +212,7 @@ struct sdhci_host {
/* Internal data */
struct mmc_host *mmc; /* MMC structure */
+ u64 dma_mask; /* custom DMA mask */
#ifdef CONFIG_LEDS_CLASS
struct led_classdev led; /* LED control */
@@ -238,10 +239,8 @@ struct sdhci_host {
struct mmc_data *data; /* Current data request */
unsigned int data_early:1; /* Data finished before cmd */
- struct scatterlist *cur_sg; /* We're working on this */
- int num_sg; /* Entries left */
- int offset; /* Offset into current sg */
- int remain; /* Bytes left in current */
+ struct sg_mapping_iter sg_miter; /* SG state for PIO */
+ unsigned int blocks; /* remaining PIO blocks */
int sg_count; /* Mapped sg entries */
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 519d942e794..7b72a1b3611 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -241,6 +241,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
{
struct block_device *bdev;
struct block2mtd_dev *dev;
+ char *name;
if (!devname)
return NULL;
@@ -279,12 +280,13 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
/* Setup the MTD structure */
/* make the name contain the block device in */
- dev->mtd.name = kmalloc(sizeof("block2mtd: ") + strlen(devname),
+ name = kmalloc(sizeof("block2mtd: ") + strlen(devname) + 1,
GFP_KERNEL);
- if (!dev->mtd.name)
+ if (!name)
goto devinit_err;
- sprintf(dev->mtd.name, "block2mtd: %s", devname);
+ sprintf(name, "block2mtd: %s", devname);
+ dev->mtd.name = name;
dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
dev->mtd.erasesize = erase_size;
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
index c42f4b83f68..3fcf92130aa 100644
--- a/drivers/mtd/maps/uclinux.c
+++ b/drivers/mtd/maps/uclinux.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
+#include <linux/mm.h>
#include <linux/major.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 129d429cd2d..aef9f4b687c 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -28,10 +28,13 @@ static void mtd_notify_add(struct mtd_info* mtd)
if (!mtd)
return;
- device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2), "mtd%d", mtd->index);
+ device_create_drvdata(mtd_class, NULL,
+ MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
+ NULL, "mtd%d", mtd->index);
- device_create(mtd_class, NULL,
- MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1), "mtd%dro", mtd->index);
+ device_create_drvdata(mtd_class, NULL,
+ MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
+ NULL, "mtd%dro", mtd->index);
}
static void mtd_notify_remove(struct mtd_info* mtd)
diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c
index cb663ef245d..fc8529bedfd 100644
--- a/drivers/mtd/nand/cmx270_nand.c
+++ b/drivers/mtd/nand/cmx270_nand.c
@@ -20,9 +20,11 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#include <linux/gpio.h>
#include <asm/io.h>
#include <asm/irq.h>
+#include <asm/mach-types.h>
#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
@@ -30,20 +32,6 @@
#define GPIO_NAND_CS (11)
#define GPIO_NAND_RB (89)
-/* This macro needed to ensure in-order operation of GPIO and local
- * bus. Without both asm command and dummy uncached read there're
- * states when NAND access is broken. I've looked for such macro(s) in
- * include/asm-arm but found nothing approptiate.
- * dmac_clean_range is close, but is makes cache invalidation
- * unnecessary here and it cannot be used in module
- */
-#define DRAIN_WB() \
- do { \
- unsigned char dummy; \
- asm volatile ("mcr p15, 0, r0, c7, c10, 4":::"r0"); \
- dummy=*((unsigned char*)UNCACHED_ADDR); \
- } while(0)
-
/* MTD structure for CM-X270 board */
static struct mtd_info *cmx270_nand_mtd;
@@ -103,14 +91,14 @@ static int cmx270_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
static inline void nand_cs_on(void)
{
- GPCR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
+ gpio_set_value(GPIO_NAND_CS, 0);
}
static void nand_cs_off(void)
{
- DRAIN_WB();
+ dsb();
- GPSR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
+ gpio_set_value(GPIO_NAND_CS, 1);
}
/*
@@ -122,7 +110,7 @@ static void cmx270_hwcontrol(struct mtd_info *mtd, int dat,
struct nand_chip* this = mtd->priv;
unsigned int nandaddr = (unsigned int)this->IO_ADDR_W;
- DRAIN_WB();
+ dsb();
if (ctrl & NAND_CTRL_CHANGE) {
if ( ctrl & NAND_ALE )
@@ -139,12 +127,12 @@ static void cmx270_hwcontrol(struct mtd_info *mtd, int dat,
nand_cs_off();
}
- DRAIN_WB();
+ dsb();
this->IO_ADDR_W = (void __iomem*)nandaddr;
if (dat != NAND_CMD_NONE)
writel((dat << 16), this->IO_ADDR_W);
- DRAIN_WB();
+ dsb();
}
/*
@@ -152,9 +140,9 @@ static void cmx270_hwcontrol(struct mtd_info *mtd, int dat,
*/
static int cmx270_device_ready(struct mtd_info *mtd)
{
- DRAIN_WB();
+ dsb();
- return (GPLR(GPIO_NAND_RB) & GPIO_bit(GPIO_NAND_RB));
+ return (gpio_get_value(GPIO_NAND_RB));
}
/*
@@ -168,20 +156,40 @@ static int cmx270_init(void)
int mtd_parts_nb = 0;
int ret;
+ if (!machine_is_armcore())
+ return -ENODEV;
+
+ ret = gpio_request(GPIO_NAND_CS, "NAND CS");
+ if (ret) {
+ pr_warning("CM-X270: failed to request NAND CS gpio\n");
+ return ret;
+ }
+
+ gpio_direction_output(GPIO_NAND_CS, 1);
+
+ ret = gpio_request(GPIO_NAND_RB, "NAND R/B");
+ if (ret) {
+ pr_warning("CM-X270: failed to request NAND R/B gpio\n");
+ goto err_gpio_request;
+ }
+
+ gpio_direction_input(GPIO_NAND_RB);
+
/* Allocate memory for MTD device structure and private data */
cmx270_nand_mtd = kzalloc(sizeof(struct mtd_info) +
sizeof(struct nand_chip),
GFP_KERNEL);
if (!cmx270_nand_mtd) {
- printk("Unable to allocate CM-X270 NAND MTD device structure.\n");
- return -ENOMEM;
+ pr_debug("Unable to allocate CM-X270 NAND MTD device structure.\n");
+ ret = -ENOMEM;
+ goto err_kzalloc;
}
cmx270_nand_io = ioremap(PXA_CS1_PHYS, 12);
if (!cmx270_nand_io) {
- printk("Unable to ioremap NAND device\n");
+ pr_debug("Unable to ioremap NAND device\n");
ret = -EINVAL;
- goto err1;
+ goto err_ioremap;
}
/* Get pointer to private data */
@@ -209,9 +217,9 @@ static int cmx270_init(void)
/* Scan to find existence of the device */
if (nand_scan (cmx270_nand_mtd, 1)) {
- printk(KERN_NOTICE "No NAND device\n");
+ pr_notice("No NAND device\n");
ret = -ENXIO;
- goto err2;
+ goto err_scan;
}
#ifdef CONFIG_MTD_CMDLINE_PARTS
@@ -229,18 +237,22 @@ static int cmx270_init(void)
}
/* Register the partitions */
- printk(KERN_NOTICE "Using %s partition definition\n", part_type);
+ pr_notice("Using %s partition definition\n", part_type);
ret = add_mtd_partitions(cmx270_nand_mtd, mtd_parts, mtd_parts_nb);
if (ret)
- goto err2;
+ goto err_scan;
/* Return happy */
return 0;
-err2:
+err_scan:
iounmap(cmx270_nand_io);
-err1:
+err_ioremap:
kfree(cmx270_nand_mtd);
+err_kzalloc:
+ gpio_free(GPIO_NAND_RB);
+err_gpio_request:
+ gpio_free(GPIO_NAND_CS);
return ret;
@@ -255,6 +267,9 @@ static void cmx270_cleanup(void)
/* Release resources, unregister device */
nand_release(cmx270_nand_mtd);
+ gpio_free(GPIO_NAND_RB);
+ gpio_free(GPIO_NAND_CS);
+
iounmap(cmx270_nand_io);
/* Free the MTD device structure */
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 961416ac061..c7630a22831 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -51,14 +51,13 @@
* @name: MTD device name or number string
* @vid_hdr_offs: VID header offset
*/
-struct mtd_dev_param
-{
+struct mtd_dev_param {
char name[MTD_PARAM_LEN_MAX];
int vid_hdr_offs;
};
/* Numbers of elements set in the @mtd_dev_param array */
-static int mtd_devs = 0;
+static int mtd_devs;
/* MTD devices specification parameters */
static struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES];
@@ -160,8 +159,7 @@ void ubi_put_device(struct ubi_device *ubi)
}
/**
- * ubi_get_by_major - get UBI device description object by character device
- * major number.
+ * ubi_get_by_major - get UBI device by character device major number.
* @major: major number
*
* This function is similar to 'ubi_get_device()', but it searches the device
@@ -355,15 +353,34 @@ static void kill_volumes(struct ubi_device *ubi)
}
/**
+ * free_user_volumes - free all user volumes.
+ * @ubi: UBI device description object
+ *
+ * Normally the volumes are freed at the release function of the volume device
+ * objects. However, on error paths the volumes have to be freed before the
+ * device objects have been initialized.
+ */
+static void free_user_volumes(struct ubi_device *ubi)
+{
+ int i;
+
+ for (i = 0; i < ubi->vtbl_slots; i++)
+ if (ubi->volumes[i]) {
+ kfree(ubi->volumes[i]->eba_tbl);
+ kfree(ubi->volumes[i]);
+ }
+}
+
+/**
* uif_init - initialize user interfaces for an UBI device.
* @ubi: UBI device description object
*
* This function returns zero in case of success and a negative error code in
- * case of failure.
+ * case of failure. Note, this function destroys all volumes if it failes.
*/
static int uif_init(struct ubi_device *ubi)
{
- int i, err;
+ int i, err, do_free = 0;
dev_t dev;
sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
@@ -384,7 +401,7 @@ static int uif_init(struct ubi_device *ubi)
ubi_assert(MINOR(dev) == 0);
cdev_init(&ubi->cdev, &ubi_cdev_operations);
- dbg_msg("%s major is %u", ubi->ubi_name, MAJOR(dev));
+ dbg_gen("%s major is %u", ubi->ubi_name, MAJOR(dev));
ubi->cdev.owner = THIS_MODULE;
err = cdev_add(&ubi->cdev, dev, 1);
@@ -410,10 +427,13 @@ static int uif_init(struct ubi_device *ubi)
out_volumes:
kill_volumes(ubi);
+ do_free = 0;
out_sysfs:
ubi_sysfs_close(ubi);
cdev_del(&ubi->cdev);
out_unreg:
+ if (do_free)
+ free_user_volumes(ubi);
unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);
ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err);
return err;
@@ -422,6 +442,10 @@ out_unreg:
/**
* uif_close - close user interfaces for an UBI device.
* @ubi: UBI device description object
+ *
+ * Note, since this function un-registers UBI volume device objects (@vol->dev),
+ * the memory allocated voe the volumes is freed as well (in the release
+ * function).
*/
static void uif_close(struct ubi_device *ubi)
{
@@ -432,6 +456,21 @@ static void uif_close(struct ubi_device *ubi)
}
/**
+ * free_internal_volumes - free internal volumes.
+ * @ubi: UBI device description object
+ */
+static void free_internal_volumes(struct ubi_device *ubi)
+{
+ int i;
+
+ for (i = ubi->vtbl_slots;
+ i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
+ kfree(ubi->volumes[i]->eba_tbl);
+ kfree(ubi->volumes[i]);
+ }
+}
+
+/**
* attach_by_scanning - attach an MTD device using scanning method.
* @ubi: UBI device descriptor
*
@@ -475,6 +514,7 @@ static int attach_by_scanning(struct ubi_device *ubi)
out_wl:
ubi_wl_close(ubi);
out_vtbl:
+ free_internal_volumes(ubi);
vfree(ubi->vtbl);
out_si:
ubi_scan_destroy_si(si);
@@ -482,7 +522,7 @@ out_si:
}
/**
- * io_init - initialize I/O unit for a given UBI device.
+ * io_init - initialize I/O sub-system for a given UBI device.
* @ubi: UBI device description object
*
* If @ubi->vid_hdr_offset or @ubi->leb_start is zero, default offsets are
@@ -530,7 +570,11 @@ static int io_init(struct ubi_device *ubi)
ubi->min_io_size = ubi->mtd->writesize;
ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;
- /* Make sure minimal I/O unit is power of 2 */
+ /*
+ * Make sure minimal I/O unit is power of 2. Note, there is no
+ * fundamental reason for this assumption. It is just an optimization
+ * which allows us to avoid costly division operations.
+ */
if (!is_power_of_2(ubi->min_io_size)) {
ubi_err("min. I/O unit (%d) is not power of 2",
ubi->min_io_size);
@@ -581,7 +625,7 @@ static int io_init(struct ubi_device *ubi)
if (ubi->vid_hdr_offset < UBI_EC_HDR_SIZE ||
ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE ||
ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE ||
- ubi->leb_start % ubi->min_io_size) {
+ ubi->leb_start & (ubi->min_io_size - 1)) {
ubi_err("bad VID header (%d) or data offsets (%d)",
ubi->vid_hdr_offset, ubi->leb_start);
return -EINVAL;
@@ -646,7 +690,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
/*
* Clear the auto-resize flag in the volume in-memory copy of the
- * volume table, and 'ubi_resize_volume()' will propogate this change
+ * volume table, and 'ubi_resize_volume()' will propagate this change
* to the flash.
*/
ubi->vtbl[vol_id].flags &= ~UBI_VTBL_AUTORESIZE_FLG;
@@ -655,7 +699,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
struct ubi_vtbl_record vtbl_rec;
/*
- * No avalilable PEBs to re-size the volume, clear the flag on
+ * No available PEBs to re-size the volume, clear the flag on
* flash and exit.
*/
memcpy(&vtbl_rec, &ubi->vtbl[vol_id],
@@ -682,13 +726,13 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
/**
* ubi_attach_mtd_dev - attach an MTD device.
- * @mtd_dev: MTD device description object
+ * @mtd: MTD device description object
* @ubi_num: number to assign to the new UBI device
* @vid_hdr_offset: VID header offset
*
* This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number
* to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in
- * which case this function finds a vacant device nubert and assings it
+ * which case this function finds a vacant device number and assigns it
* automatically. Returns the new UBI device number in case of success and a
* negative error code in case of failure.
*
@@ -698,7 +742,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
{
struct ubi_device *ubi;
- int i, err;
+ int i, err, do_free = 1;
/*
* Check if we already have the same MTD device attached.
@@ -735,7 +779,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
if (!ubi_devices[ubi_num])
break;
if (ubi_num == UBI_MAX_DEVICES) {
- dbg_err("only %d UBI devices may be created", UBI_MAX_DEVICES);
+ dbg_err("only %d UBI devices may be created",
+ UBI_MAX_DEVICES);
return -ENFILE;
}
} else {
@@ -760,6 +805,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
mutex_init(&ubi->buf_mutex);
mutex_init(&ubi->ckvol_mutex);
+ mutex_init(&ubi->mult_mutex);
mutex_init(&ubi->volumes_mutex);
spin_lock_init(&ubi->volumes_lock);
@@ -798,7 +844,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
err = uif_init(ubi);
if (err)
- goto out_detach;
+ goto out_nofree;
ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
if (IS_ERR(ubi->bgt_thread)) {
@@ -824,20 +870,22 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
ubi->beb_rsvd_pebs);
ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);
- /* Enable the background thread */
- if (!DBG_DISABLE_BGT) {
+ if (!DBG_DISABLE_BGT)
ubi->thread_enabled = 1;
- wake_up_process(ubi->bgt_thread);
- }
+ wake_up_process(ubi->bgt_thread);
ubi_devices[ubi_num] = ubi;
return ubi_num;
out_uif:
uif_close(ubi);
+out_nofree:
+ do_free = 0;
out_detach:
- ubi_eba_close(ubi);
ubi_wl_close(ubi);
+ if (do_free)
+ free_user_volumes(ubi);
+ free_internal_volumes(ubi);
vfree(ubi->vtbl);
out_free:
vfree(ubi->peb_buf1);
@@ -899,8 +947,8 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
kthread_stop(ubi->bgt_thread);
uif_close(ubi);
- ubi_eba_close(ubi);
ubi_wl_close(ubi);
+ free_internal_volumes(ubi);
vfree(ubi->vtbl);
put_mtd_device(ubi->mtd);
vfree(ubi->peb_buf1);
@@ -1044,8 +1092,7 @@ static void __exit ubi_exit(void)
module_exit(ubi_exit);
/**
- * bytes_str_to_int - convert a string representing number of bytes to an
- * integer.
+ * bytes_str_to_int - convert a number of bytes string into an integer.
* @str: the string to convert
*
* This function returns positive resulting integer in case of success and a
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 89193ba9451..03c759b4eeb 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -39,9 +39,9 @@
#include <linux/stat.h>
#include <linux/ioctl.h>
#include <linux/capability.h>
+#include <linux/uaccess.h>
#include <linux/smp_lock.h>
#include <mtd/ubi-user.h>
-#include <asm/uaccess.h>
#include <asm/div64.h>
#include "ubi.h"
@@ -116,7 +116,7 @@ static int vol_cdev_open(struct inode *inode, struct file *file)
else
mode = UBI_READONLY;
- dbg_msg("open volume %d, mode %d", vol_id, mode);
+ dbg_gen("open volume %d, mode %d", vol_id, mode);
desc = ubi_open_volume(ubi_num, vol_id, mode);
unlock_kernel();
@@ -132,7 +132,7 @@ static int vol_cdev_release(struct inode *inode, struct file *file)
struct ubi_volume_desc *desc = file->private_data;
struct ubi_volume *vol = desc->vol;
- dbg_msg("release volume %d, mode %d", vol->vol_id, desc->mode);
+ dbg_gen("release volume %d, mode %d", vol->vol_id, desc->mode);
if (vol->updating) {
ubi_warn("update of volume %d not finished, volume is damaged",
@@ -141,7 +141,7 @@ static int vol_cdev_release(struct inode *inode, struct file *file)
vol->updating = 0;
vfree(vol->upd_buf);
} else if (vol->changing_leb) {
- dbg_msg("only %lld of %lld bytes received for atomic LEB change"
+ dbg_gen("only %lld of %lld bytes received for atomic LEB change"
" for volume %d:%d, cancel", vol->upd_received,
vol->upd_bytes, vol->ubi->ubi_num, vol->vol_id);
vol->changing_leb = 0;
@@ -183,7 +183,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
return -EINVAL;
}
- dbg_msg("seek volume %d, offset %lld, origin %d, new offset %lld",
+ dbg_gen("seek volume %d, offset %lld, origin %d, new offset %lld",
vol->vol_id, offset, origin, new_offset);
file->f_pos = new_offset;
@@ -201,7 +201,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
void *tbuf;
uint64_t tmp;
- dbg_msg("read %zd bytes from offset %lld of volume %d",
+ dbg_gen("read %zd bytes from offset %lld of volume %d",
count, *offp, vol->vol_id);
if (vol->updating) {
@@ -216,7 +216,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
return 0;
if (vol->corrupted)
- dbg_msg("read from corrupted volume %d", vol->vol_id);
+ dbg_gen("read from corrupted volume %d", vol->vol_id);
if (*offp + count > vol->used_bytes)
count_save = count = vol->used_bytes - *offp;
@@ -285,7 +285,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
char *tbuf;
uint64_t tmp;
- dbg_msg("requested: write %zd bytes to offset %lld of volume %u",
+ dbg_gen("requested: write %zd bytes to offset %lld of volume %u",
count, *offp, vol->vol_id);
if (vol->vol_type == UBI_STATIC_VOLUME)
@@ -295,7 +295,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
off = do_div(tmp, vol->usable_leb_size);
lnum = tmp;
- if (off % ubi->min_io_size) {
+ if (off & (ubi->min_io_size - 1)) {
dbg_err("unaligned position");
return -EINVAL;
}
@@ -304,7 +304,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
count_save = count = vol->used_bytes - *offp;
/* We can write only in fractions of the minimum I/O unit */
- if (count % ubi->min_io_size) {
+ if (count & (ubi->min_io_size - 1)) {
dbg_err("unaligned write length");
return -EINVAL;
}
@@ -352,7 +352,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
}
#else
-#define vol_cdev_direct_write(file, buf, count, offp) -EPERM
+#define vol_cdev_direct_write(file, buf, count, offp) (-EPERM)
#endif /* CONFIG_MTD_UBI_DEBUG_USERSPACE_IO */
static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
@@ -437,7 +437,8 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
break;
}
- rsvd_bytes = vol->reserved_pebs * (ubi->leb_size-vol->data_pad);
+ rsvd_bytes = (long long)vol->reserved_pebs *
+ ubi->leb_size-vol->data_pad;
if (bytes < 0 || bytes > rsvd_bytes) {
err = -EINVAL;
break;
@@ -513,7 +514,7 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
break;
}
- dbg_msg("erase LEB %d:%d", vol->vol_id, lnum);
+ dbg_gen("erase LEB %d:%d", vol->vol_id, lnum);
err = ubi_eba_unmap_leb(ubi, vol, lnum);
if (err)
break;
@@ -564,7 +565,7 @@ static int verify_mkvol_req(const struct ubi_device *ubi,
if (req->alignment > ubi->leb_size)
goto bad;
- n = req->alignment % ubi->min_io_size;
+ n = req->alignment & (ubi->min_io_size - 1);
if (req->alignment != 1 && n)
goto bad;
@@ -573,6 +574,10 @@ static int verify_mkvol_req(const struct ubi_device *ubi,
goto bad;
}
+ n = strnlen(req->name, req->name_len + 1);
+ if (n != req->name_len)
+ goto bad;
+
return 0;
bad:
@@ -600,6 +605,166 @@ static int verify_rsvol_req(const struct ubi_device *ubi,
return 0;
}
+/**
+ * rename_volumes - rename UBI volumes.
+ * @ubi: UBI device description object
+ * @req: volumes re-name request
+ *
+ * This is a helper function for the volume re-name IOCTL which validates the
+ * the request, opens the volume and calls corresponding volumes management
+ * function. Returns zero in case of success and a negative error code in case
+ * of failure.
+ */
+static int rename_volumes(struct ubi_device *ubi,
+ struct ubi_rnvol_req *req)
+{
+ int i, n, err;
+ struct list_head rename_list;
+ struct ubi_rename_entry *re, *re1;
+
+ if (req->count < 0 || req->count > UBI_MAX_RNVOL)
+ return -EINVAL;
+
+ if (req->count == 0)
+ return 0;
+
+ /* Validate volume IDs and names in the request */
+ for (i = 0; i < req->count; i++) {
+ if (req->ents[i].vol_id < 0 ||
+ req->ents[i].vol_id >= ubi->vtbl_slots)
+ return -EINVAL;
+ if (req->ents[i].name_len < 0)
+ return -EINVAL;
+ if (req->ents[i].name_len > UBI_VOL_NAME_MAX)
+ return -ENAMETOOLONG;
+ req->ents[i].name[req->ents[i].name_len] = '\0';
+ n = strlen(req->ents[i].name);
+ if (n != req->ents[i].name_len)
+ err = -EINVAL;
+ }
+
+ /* Make sure volume IDs and names are unique */
+ for (i = 0; i < req->count - 1; i++) {
+ for (n = i + 1; n < req->count; n++) {
+ if (req->ents[i].vol_id == req->ents[n].vol_id) {
+ dbg_err("duplicated volume id %d",
+ req->ents[i].vol_id);
+ return -EINVAL;
+ }
+ if (!strcmp(req->ents[i].name, req->ents[n].name)) {
+ dbg_err("duplicated volume name \"%s\"",
+ req->ents[i].name);
+ return -EINVAL;
+ }
+ }
+ }
+
+ /* Create the re-name list */
+ INIT_LIST_HEAD(&rename_list);
+ for (i = 0; i < req->count; i++) {
+ int vol_id = req->ents[i].vol_id;
+ int name_len = req->ents[i].name_len;
+ const char *name = req->ents[i].name;
+
+ re = kzalloc(sizeof(struct ubi_rename_entry), GFP_KERNEL);
+ if (!re) {
+ err = -ENOMEM;
+ goto out_free;
+ }
+
+ re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE);
+ if (IS_ERR(re->desc)) {
+ err = PTR_ERR(re->desc);
+ dbg_err("cannot open volume %d, error %d", vol_id, err);
+ kfree(re);
+ goto out_free;
+ }
+
+ /* Skip this re-naming if the name does not really change */
+ if (re->desc->vol->name_len == name_len &&
+ !memcmp(re->desc->vol->name, name, name_len)) {
+ ubi_close_volume(re->desc);
+ kfree(re);
+ continue;
+ }
+
+ re->new_name_len = name_len;
+ memcpy(re->new_name, name, name_len);
+ list_add_tail(&re->list, &rename_list);
+ dbg_msg("will rename volume %d from \"%s\" to \"%s\"",
+ vol_id, re->desc->vol->name, name);
+ }
+
+ if (list_empty(&rename_list))
+ return 0;
+
+ /* Find out the volumes which have to be removed */
+ list_for_each_entry(re, &rename_list, list) {
+ struct ubi_volume_desc *desc;
+ int no_remove_needed = 0;
+
+ /*
+ * Volume @re->vol_id is going to be re-named to
+ * @re->new_name, while its current name is @name. If a volume
+ * with name @re->new_name currently exists, it has to be
+ * removed, unless it is also re-named in the request (@req).
+ */
+ list_for_each_entry(re1, &rename_list, list) {
+ if (re->new_name_len == re1->desc->vol->name_len &&
+ !memcmp(re->new_name, re1->desc->vol->name,
+ re1->desc->vol->name_len)) {
+ no_remove_needed = 1;
+ break;
+ }
+ }
+
+ if (no_remove_needed)
+ continue;
+
+ /*
+ * It seems we need to remove volume with name @re->new_name,
+ * if it exists.
+ */
+ desc = ubi_open_volume_nm(ubi->ubi_num, re->new_name, UBI_EXCLUSIVE);
+ if (IS_ERR(desc)) {
+ err = PTR_ERR(desc);
+ if (err == -ENODEV)
+ /* Re-naming into a non-existing volume name */
+ continue;
+
+ /* The volume exists but busy, or an error occurred */
+ dbg_err("cannot open volume \"%s\", error %d",
+ re->new_name, err);
+ goto out_free;
+ }
+
+ re = kzalloc(sizeof(struct ubi_rename_entry), GFP_KERNEL);
+ if (!re) {
+ err = -ENOMEM;
+ ubi_close_volume(desc);
+ goto out_free;
+ }
+
+ re->remove = 1;
+ re->desc = desc;
+ list_add(&re->list, &rename_list);
+ dbg_msg("will remove volume %d, name \"%s\"",
+ re->desc->vol->vol_id, re->desc->vol->name);
+ }
+
+ mutex_lock(&ubi->volumes_mutex);
+ err = ubi_rename_volumes(ubi, &rename_list);
+ mutex_unlock(&ubi->volumes_mutex);
+
+out_free:
+ list_for_each_entry_safe(re, re1, &rename_list, list) {
+ ubi_close_volume(re->desc);
+ list_del(&re->list);
+ kfree(re);
+ }
+ return err;
+}
+
static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -621,19 +786,18 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
{
struct ubi_mkvol_req req;
- dbg_msg("create volume");
+ dbg_gen("create volume");
err = copy_from_user(&req, argp, sizeof(struct ubi_mkvol_req));
if (err) {
err = -EFAULT;
break;
}
+ req.name[req.name_len] = '\0';
err = verify_mkvol_req(ubi, &req);
if (err)
break;
- req.name[req.name_len] = '\0';
-
mutex_lock(&ubi->volumes_mutex);
err = ubi_create_volume(ubi, &req);
mutex_unlock(&ubi->volumes_mutex);
@@ -652,7 +816,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
{
int vol_id;
- dbg_msg("remove volume");
+ dbg_gen("remove volume");
err = get_user(vol_id, (__user int32_t *)argp);
if (err) {
err = -EFAULT;
@@ -666,7 +830,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
}
mutex_lock(&ubi->volumes_mutex);
- err = ubi_remove_volume(desc);
+ err = ubi_remove_volume(desc, 0);
mutex_unlock(&ubi->volumes_mutex);
/*
@@ -685,7 +849,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
uint64_t tmp;
struct ubi_rsvol_req req;
- dbg_msg("re-size volume");
+ dbg_gen("re-size volume");
err = copy_from_user(&req, argp, sizeof(struct ubi_rsvol_req));
if (err) {
err = -EFAULT;
@@ -713,6 +877,32 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
break;
}
+ /* Re-name volumes command */
+ case UBI_IOCRNVOL:
+ {
+ struct ubi_rnvol_req *req;
+
+ dbg_msg("re-name volumes");
+ req = kmalloc(sizeof(struct ubi_rnvol_req), GFP_KERNEL);
+ if (!req) {
+ err = -ENOMEM;
+ break;
+ };
+
+ err = copy_from_user(req, argp, sizeof(struct ubi_rnvol_req));
+ if (err) {
+ err = -EFAULT;
+ kfree(req);
+ break;
+ }
+
+ mutex_lock(&ubi->mult_mutex);
+ err = rename_volumes(ubi, req);
+ mutex_unlock(&ubi->mult_mutex);
+ kfree(req);
+ break;
+ }
+
default:
err = -ENOTTY;
break;
@@ -738,7 +928,7 @@ static int ctrl_cdev_ioctl(struct inode *inode, struct file *file,
struct ubi_attach_req req;
struct mtd_info *mtd;
- dbg_msg("attach MTD device");
+ dbg_gen("attach MTD device");
err = copy_from_user(&req, argp, sizeof(struct ubi_attach_req));
if (err) {
err = -EFAULT;
@@ -778,7 +968,7 @@ static int ctrl_cdev_ioctl(struct inode *inode, struct file *file,
{
int ubi_num;
- dbg_msg("dettach MTD device");
+ dbg_gen("dettach MTD device");
err = get_user(ubi_num, (__user int32_t *)argp);
if (err) {
err = -EFAULT;
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 56956ec2845..c0ed60e8ade 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -24,7 +24,7 @@
* changes.
*/
-#ifdef CONFIG_MTD_UBI_DEBUG_MSG
+#ifdef CONFIG_MTD_UBI_DEBUG
#include "ubi.h"
@@ -34,14 +34,19 @@
*/
void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
{
- dbg_msg("erase counter header dump:");
- dbg_msg("magic %#08x", be32_to_cpu(ec_hdr->magic));
- dbg_msg("version %d", (int)ec_hdr->version);
- dbg_msg("ec %llu", (long long)be64_to_cpu(ec_hdr->ec));
- dbg_msg("vid_hdr_offset %d", be32_to_cpu(ec_hdr->vid_hdr_offset));
- dbg_msg("data_offset %d", be32_to_cpu(ec_hdr->data_offset));
- dbg_msg("hdr_crc %#08x", be32_to_cpu(ec_hdr->hdr_crc));
- dbg_msg("erase counter header hexdump:");
+ printk(KERN_DEBUG "Erase counter header dump:\n");
+ printk(KERN_DEBUG "\tmagic %#08x\n",
+ be32_to_cpu(ec_hdr->magic));
+ printk(KERN_DEBUG "\tversion %d\n", (int)ec_hdr->version);
+ printk(KERN_DEBUG "\tec %llu\n",
+ (long long)be64_to_cpu(ec_hdr->ec));
+ printk(KERN_DEBUG "\tvid_hdr_offset %d\n",
+ be32_to_cpu(ec_hdr->vid_hdr_offset));
+ printk(KERN_DEBUG "\tdata_offset %d\n",
+ be32_to_cpu(ec_hdr->data_offset));
+ printk(KERN_DEBUG "\thdr_crc %#08x\n",
+ be32_to_cpu(ec_hdr->hdr_crc));
+ printk(KERN_DEBUG "erase counter header hexdump:\n");
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
ec_hdr, UBI_EC_HDR_SIZE, 1);
}
@@ -52,22 +57,23 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
*/
void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
{
- dbg_msg("volume identifier header dump:");
- dbg_msg("magic %08x", be32_to_cpu(vid_hdr->magic));
- dbg_msg("version %d", (int)vid_hdr->version);
- dbg_msg("vol_type %d", (int)vid_hdr->vol_type);
- dbg_msg("copy_flag %d", (int)vid_hdr->copy_flag);
- dbg_msg("compat %d", (int)vid_hdr->compat);
- dbg_msg("vol_id %d", be32_to_cpu(vid_hdr->vol_id));
- dbg_msg("lnum %d", be32_to_cpu(vid_hdr->lnum));
- dbg_msg("leb_ver %u", be32_to_cpu(vid_hdr->leb_ver));
- dbg_msg("data_size %d", be32_to_cpu(vid_hdr->data_size));
- dbg_msg("used_ebs %d", be32_to_cpu(vid_hdr->used_ebs));
- dbg_msg("data_pad %d", be32_to_cpu(vid_hdr->data_pad));
- dbg_msg("sqnum %llu",
+ printk(KERN_DEBUG "Volume identifier header dump:\n");
+ printk(KERN_DEBUG "\tmagic %08x\n", be32_to_cpu(vid_hdr->magic));
+ printk(KERN_DEBUG "\tversion %d\n", (int)vid_hdr->version);
+ printk(KERN_DEBUG "\tvol_type %d\n", (int)vid_hdr->vol_type);
+ printk(KERN_DEBUG "\tcopy_flag %d\n", (int)vid_hdr->copy_flag);
+ printk(KERN_DEBUG "\tcompat %d\n", (int)vid_hdr->compat);
+ printk(KERN_DEBUG "\tvol_id %d\n", be32_to_cpu(vid_hdr->vol_id));
+ printk(KERN_DEBUG "\tlnum %d\n", be32_to_cpu(vid_hdr->lnum));
+ printk(KERN_DEBUG "\tdata_size %d\n", be32_to_cpu(vid_hdr->data_size));
+ printk(KERN_DEBUG "\tused_ebs %d\n", be32_to_cpu(vid_hdr->used_ebs));
+ printk(KERN_DEBUG "\tdata_pad %d\n", be32_to_cpu(vid_hdr->data_pad));
+ printk(KERN_DEBUG "\tsqnum %llu\n",
(unsigned long long)be64_to_cpu(vid_hdr->sqnum));
- dbg_msg("hdr_crc %08x", be32_to_cpu(vid_hdr->hdr_crc));
- dbg_msg("volume identifier header hexdump:");
+ printk(KERN_DEBUG "\thdr_crc %08x\n", be32_to_cpu(vid_hdr->hdr_crc));
+ printk(KERN_DEBUG "Volume identifier header hexdump:\n");
+ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+ vid_hdr, UBI_VID_HDR_SIZE, 1);
}
/**
@@ -76,27 +82,27 @@ void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
*/
void ubi_dbg_dump_vol_info(const struct ubi_volume *vol)
{
- dbg_msg("volume information dump:");
- dbg_msg("vol_id %d", vol->vol_id);
- dbg_msg("reserved_pebs %d", vol->reserved_pebs);
- dbg_msg("alignment %d", vol->alignment);
- dbg_msg("data_pad %d", vol->data_pad);
- dbg_msg("vol_type %d", vol->vol_type);
- dbg_msg("name_len %d", vol->name_len);
- dbg_msg("usable_leb_size %d", vol->usable_leb_size);
- dbg_msg("used_ebs %d", vol->used_ebs);
- dbg_msg("used_bytes %lld", vol->used_bytes);
- dbg_msg("last_eb_bytes %d", vol->last_eb_bytes);
- dbg_msg("corrupted %d", vol->corrupted);
- dbg_msg("upd_marker %d", vol->upd_marker);
+ printk(KERN_DEBUG "Volume information dump:\n");
+ printk(KERN_DEBUG "\tvol_id %d\n", vol->vol_id);
+ printk(KERN_DEBUG "\treserved_pebs %d\n", vol->reserved_pebs);
+ printk(KERN_DEBUG "\talignment %d\n", vol->alignment);
+ printk(KERN_DEBUG "\tdata_pad %d\n", vol->data_pad);
+ printk(KERN_DEBUG "\tvol_type %d\n", vol->vol_type);
+ printk(KERN_DEBUG "\tname_len %d\n", vol->name_len);
+ printk(KERN_DEBUG "\tusable_leb_size %d\n", vol->usable_leb_size);
+ printk(KERN_DEBUG "\tused_ebs %d\n", vol->used_ebs);
+ printk(KERN_DEBUG "\tused_bytes %lld\n", vol->used_bytes);
+ printk(KERN_DEBUG "\tlast_eb_bytes %d\n", vol->last_eb_bytes);
+ printk(KERN_DEBUG "\tcorrupted %d\n", vol->corrupted);
+ printk(KERN_DEBUG "\tupd_marker %d\n", vol->upd_marker);
if (vol->name_len <= UBI_VOL_NAME_MAX &&
strnlen(vol->name, vol->name_len + 1) == vol->name_len) {
- dbg_msg("name %s", vol->name);
+ printk(KERN_DEBUG "\tname %s\n", vol->name);
} else {
- dbg_msg("the 1st 5 characters of the name: %c%c%c%c%c",
- vol->name[0], vol->name[1], vol->name[2],
- vol->name[3], vol->name[4]);
+ printk(KERN_DEBUG "\t1st 5 characters of name: %c%c%c%c%c\n",
+ vol->name[0], vol->name[1], vol->name[2],
+ vol->name[3], vol->name[4]);
}
}
@@ -109,28 +115,29 @@ void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
{
int name_len = be16_to_cpu(r->name_len);
- dbg_msg("volume table record %d dump:", idx);
- dbg_msg("reserved_pebs %d", be32_to_cpu(r->reserved_pebs));
- dbg_msg("alignment %d", be32_to_cpu(r->alignment));
- dbg_msg("data_pad %d", be32_to_cpu(r->data_pad));
- dbg_msg("vol_type %d", (int)r->vol_type);
- dbg_msg("upd_marker %d", (int)r->upd_marker);
- dbg_msg("name_len %d", name_len);
+ printk(KERN_DEBUG "Volume table record %d dump:\n", idx);
+ printk(KERN_DEBUG "\treserved_pebs %d\n",
+ be32_to_cpu(r->reserved_pebs));
+ printk(KERN_DEBUG "\talignment %d\n", be32_to_cpu(r->alignment));
+ printk(KERN_DEBUG "\tdata_pad %d\n", be32_to_cpu(r->data_pad));
+ printk(KERN_DEBUG "\tvol_type %d\n", (int)r->vol_type);
+ printk(KERN_DEBUG "\tupd_marker %d\n", (int)r->upd_marker);
+ printk(KERN_DEBUG "\tname_len %d\n", name_len);
if (r->name[0] == '\0') {
- dbg_msg("name NULL");
+ printk(KERN_DEBUG "\tname NULL\n");
return;
}
if (name_len <= UBI_VOL_NAME_MAX &&
strnlen(&r->name[0], name_len + 1) == name_len) {
- dbg_msg("name %s", &r->name[0]);
+ printk(KERN_DEBUG "\tname %s\n", &r->name[0]);
} else {
- dbg_msg("1st 5 characters of the name: %c%c%c%c%c",
+ printk(KERN_DEBUG "\t1st 5 characters of name: %c%c%c%c%c\n",
r->name[0], r->name[1], r->name[2], r->name[3],
r->name[4]);
}
- dbg_msg("crc %#08x", be32_to_cpu(r->crc));
+ printk(KERN_DEBUG "\tcrc %#08x\n", be32_to_cpu(r->crc));
}
/**
@@ -139,15 +146,15 @@ void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
*/
void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv)
{
- dbg_msg("volume scanning information dump:");
- dbg_msg("vol_id %d", sv->vol_id);
- dbg_msg("highest_lnum %d", sv->highest_lnum);
- dbg_msg("leb_count %d", sv->leb_count);
- dbg_msg("compat %d", sv->compat);
- dbg_msg("vol_type %d", sv->vol_type);
- dbg_msg("used_ebs %d", sv->used_ebs);
- dbg_msg("last_data_size %d", sv->last_data_size);
- dbg_msg("data_pad %d", sv->data_pad);
+ printk(KERN_DEBUG "Volume scanning information dump:\n");
+ printk(KERN_DEBUG "\tvol_id %d\n", sv->vol_id);
+ printk(KERN_DEBUG "\thighest_lnum %d\n", sv->highest_lnum);
+ printk(KERN_DEBUG "\tleb_count %d\n", sv->leb_count);
+ printk(KERN_DEBUG "\tcompat %d\n", sv->compat);
+ printk(KERN_DEBUG "\tvol_type %d\n", sv->vol_type);
+ printk(KERN_DEBUG "\tused_ebs %d\n", sv->used_ebs);
+ printk(KERN_DEBUG "\tlast_data_size %d\n", sv->last_data_size);
+ printk(KERN_DEBUG "\tdata_pad %d\n", sv->data_pad);
}
/**
@@ -157,14 +164,13 @@ void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv)
*/
void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type)
{
- dbg_msg("eraseblock scanning information dump:");
- dbg_msg("ec %d", seb->ec);
- dbg_msg("pnum %d", seb->pnum);
+ printk(KERN_DEBUG "eraseblock scanning information dump:\n");
+ printk(KERN_DEBUG "\tec %d\n", seb->ec);
+ printk(KERN_DEBUG "\tpnum %d\n", seb->pnum);
if (type == 0) {
- dbg_msg("lnum %d", seb->lnum);
- dbg_msg("scrub %d", seb->scrub);
- dbg_msg("sqnum %llu", seb->sqnum);
- dbg_msg("leb_ver %u", seb->leb_ver);
+ printk(KERN_DEBUG "\tlnum %d\n", seb->lnum);
+ printk(KERN_DEBUG "\tscrub %d\n", seb->scrub);
+ printk(KERN_DEBUG "\tsqnum %llu\n", seb->sqnum);
}
}
@@ -176,16 +182,16 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req)
{
char nm[17];
- dbg_msg("volume creation request dump:");
- dbg_msg("vol_id %d", req->vol_id);
- dbg_msg("alignment %d", req->alignment);
- dbg_msg("bytes %lld", (long long)req->bytes);
- dbg_msg("vol_type %d", req->vol_type);
- dbg_msg("name_len %d", req->name_len);
+ printk(KERN_DEBUG "Volume creation request dump:\n");
+ printk(KERN_DEBUG "\tvol_id %d\n", req->vol_id);
+ printk(KERN_DEBUG "\talignment %d\n", req->alignment);
+ printk(KERN_DEBUG "\tbytes %lld\n", (long long)req->bytes);
+ printk(KERN_DEBUG "\tvol_type %d\n", req->vol_type);
+ printk(KERN_DEBUG "\tname_len %d\n", req->name_len);
memcpy(nm, req->name, 16);
nm[16] = 0;
- dbg_msg("the 1st 16 characters of the name: %s", nm);
+ printk(KERN_DEBUG "\t1st 16 characters of name: %s\n", nm);
}
-#endif /* CONFIG_MTD_UBI_DEBUG_MSG */
+#endif /* CONFIG_MTD_UBI_DEBUG */
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index 8ea99d8c9e1..78e914d23ec 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -24,21 +24,16 @@
#ifdef CONFIG_MTD_UBI_DEBUG
#include <linux/random.h>
-#define ubi_assert(expr) BUG_ON(!(expr))
#define dbg_err(fmt, ...) ubi_err(fmt, ##__VA_ARGS__)
-#else
-#define ubi_assert(expr) ({})
-#define dbg_err(fmt, ...) ({})
-#endif
-#ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT
-#define DBG_DISABLE_BGT 1
-#else
-#define DBG_DISABLE_BGT 0
-#endif
+#define ubi_assert(expr) do { \
+ if (unlikely(!(expr))) { \
+ printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \
+ __func__, __LINE__, current->pid); \
+ ubi_dbg_dump_stack(); \
+ } \
+} while (0)
-#ifdef CONFIG_MTD_UBI_DEBUG_MSG
-/* Generic debugging message */
#define dbg_msg(fmt, ...) \
printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \
current->pid, __func__, ##__VA_ARGS__)
@@ -61,36 +56,29 @@ void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv);
void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type);
void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
+#ifdef CONFIG_MTD_UBI_DEBUG_MSG
+/* General debugging messages */
+#define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
#else
-
-#define dbg_msg(fmt, ...) ({})
-#define ubi_dbg_dump_stack() ({})
-#define ubi_dbg_dump_ec_hdr(ec_hdr) ({})
-#define ubi_dbg_dump_vid_hdr(vid_hdr) ({})
-#define ubi_dbg_dump_vol_info(vol) ({})
-#define ubi_dbg_dump_vtbl_record(r, idx) ({})
-#define ubi_dbg_dump_sv(sv) ({})
-#define ubi_dbg_dump_seb(seb, type) ({})
-#define ubi_dbg_dump_mkvol_req(req) ({})
-
-#endif /* CONFIG_MTD_UBI_DEBUG_MSG */
+#define dbg_gen(fmt, ...) ({})
+#endif
#ifdef CONFIG_MTD_UBI_DEBUG_MSG_EBA
-/* Messages from the eraseblock association unit */
+/* Messages from the eraseblock association sub-system */
#define dbg_eba(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
#else
#define dbg_eba(fmt, ...) ({})
#endif
#ifdef CONFIG_MTD_UBI_DEBUG_MSG_WL
-/* Messages from the wear-leveling unit */
+/* Messages from the wear-leveling sub-system */
#define dbg_wl(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
#else
#define dbg_wl(fmt, ...) ({})
#endif
#ifdef CONFIG_MTD_UBI_DEBUG_MSG_IO
-/* Messages from the input/output unit */
+/* Messages from the input/output sub-system */
#define dbg_io(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
#else
#define dbg_io(fmt, ...) ({})
@@ -105,6 +93,12 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
#define UBI_IO_DEBUG 0
#endif
+#ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT
+#define DBG_DISABLE_BGT 1
+#else
+#define DBG_DISABLE_BGT 0
+#endif
+
#ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS
/**
* ubi_dbg_is_bitflip - if it is time to emulate a bit-flip.
@@ -149,4 +143,30 @@ static inline int ubi_dbg_is_erase_failure(void)
#define ubi_dbg_is_erase_failure() 0
#endif
+#else
+
+#define ubi_assert(expr) ({})
+#define dbg_err(fmt, ...) ({})
+#define dbg_msg(fmt, ...) ({})
+#define dbg_gen(fmt, ...) ({})
+#define dbg_eba(fmt, ...) ({})
+#define dbg_wl(fmt, ...) ({})
+#define dbg_io(fmt, ...) ({})
+#define dbg_bld(fmt, ...) ({})
+#define ubi_dbg_dump_stack() ({})
+#define ubi_dbg_dump_ec_hdr(ec_hdr) ({})
+#define ubi_dbg_dump_vid_hdr(vid_hdr) ({})
+#define ubi_dbg_dump_vol_info(vol) ({})
+#define ubi_dbg_dump_vtbl_record(r, idx) ({})
+#define ubi_dbg_dump_sv(sv) ({})
+#define ubi_dbg_dump_seb(seb, type) ({})
+#define ubi_dbg_dump_mkvol_req(req) ({})
+
+#define UBI_IO_DEBUG 0
+#define DBG_DISABLE_BGT 0
+#define ubi_dbg_is_bitflip() 0
+#define ubi_dbg_is_write_failure() 0
+#define ubi_dbg_is_erase_failure() 0
+
+#endif /* !CONFIG_MTD_UBI_DEBUG */
#endif /* !__UBI_DEBUG_H__ */
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 7ce91ca742b..e04bcf1dff8 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -19,20 +19,20 @@
*/
/*
- * The UBI Eraseblock Association (EBA) unit.
+ * The UBI Eraseblock Association (EBA) sub-system.
*
- * This unit is responsible for I/O to/from logical eraseblock.
+ * This sub-system is responsible for I/O to/from logical eraseblock.
*
* Although in this implementation the EBA table is fully kept and managed in
* RAM, which assumes poor scalability, it might be (partially) maintained on
* flash in future implementations.
*
- * The EBA unit implements per-logical eraseblock locking. Before accessing a
- * logical eraseblock it is locked for reading or writing. The per-logical
- * eraseblock locking is implemented by means of the lock tree. The lock tree
- * is an RB-tree which refers all the currently locked logical eraseblocks. The
- * lock tree elements are &struct ubi_ltree_entry objects. They are indexed by
- * (@vol_id, @lnum) pairs.
+ * The EBA sub-system implements per-logical eraseblock locking. Before
+ * accessing a logical eraseblock it is locked for reading or writing. The
+ * per-logical eraseblock locking is implemented by means of the lock tree. The
+ * lock tree is an RB-tree which refers all the currently locked logical
+ * eraseblocks. The lock tree elements are &struct ubi_ltree_entry objects.
+ * They are indexed by (@vol_id, @lnum) pairs.
*
* EBA also maintains the global sequence counter which is incremented each
* time a logical eraseblock is mapped to a physical eraseblock and it is
@@ -189,9 +189,7 @@ static struct ubi_ltree_entry *ltree_add_entry(struct ubi_device *ubi,
le->users += 1;
spin_unlock(&ubi->ltree_lock);
- if (le_free)
- kfree(le_free);
-
+ kfree(le_free);
return le;
}
@@ -223,22 +221,18 @@ static int leb_read_lock(struct ubi_device *ubi, int vol_id, int lnum)
*/
static void leb_read_unlock(struct ubi_device *ubi, int vol_id, int lnum)
{
- int free = 0;
struct ubi_ltree_entry *le;
spin_lock(&ubi->ltree_lock);
le = ltree_lookup(ubi, vol_id, lnum);
le->users -= 1;
ubi_assert(le->users >= 0);
+ up_read(&le->mutex);
if (le->users == 0) {
rb_erase(&le->rb, &ubi->ltree);
- free = 1;
+ kfree(le);
}
spin_unlock(&ubi->ltree_lock);
-
- up_read(&le->mutex);
- if (free)
- kfree(le);
}
/**
@@ -274,7 +268,6 @@ static int leb_write_lock(struct ubi_device *ubi, int vol_id, int lnum)
*/
static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum)
{
- int free;
struct ubi_ltree_entry *le;
le = ltree_add_entry(ubi, vol_id, lnum);
@@ -289,12 +282,9 @@ static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum)
ubi_assert(le->users >= 0);
if (le->users == 0) {
rb_erase(&le->rb, &ubi->ltree);
- free = 1;
- } else
- free = 0;
- spin_unlock(&ubi->ltree_lock);
- if (free)
kfree(le);
+ }
+ spin_unlock(&ubi->ltree_lock);
return 1;
}
@@ -307,23 +297,18 @@ static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum)
*/
static void leb_write_unlock(struct ubi_device *ubi, int vol_id, int lnum)
{
- int free;
struct ubi_ltree_entry *le;
spin_lock(&ubi->ltree_lock);
le = ltree_lookup(ubi, vol_id, lnum);
le->users -= 1;
ubi_assert(le->users >= 0);
+ up_write(&le->mutex);
if (le->users == 0) {
rb_erase(&le->rb, &ubi->ltree);
- free = 1;
- } else
- free = 0;
- spin_unlock(&ubi->ltree_lock);
-
- up_write(&le->mutex);
- if (free)
kfree(le);
+ }
+ spin_unlock(&ubi->ltree_lock);
}
/**
@@ -516,9 +501,8 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
struct ubi_vid_hdr *vid_hdr;
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
- if (!vid_hdr) {
+ if (!vid_hdr)
return -ENOMEM;
- }
mutex_lock(&ubi->buf_mutex);
@@ -752,7 +736,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
/* If this is the last LEB @len may be unaligned */
len = ALIGN(data_size, ubi->min_io_size);
else
- ubi_assert(len % ubi->min_io_size == 0);
+ ubi_assert(!(len & (ubi->min_io_size - 1)));
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
if (!vid_hdr)
@@ -919,7 +903,7 @@ retry:
}
if (vol->eba_tbl[lnum] >= 0) {
- err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 1);
+ err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 0);
if (err)
goto out_leb_unlock;
}
@@ -1141,7 +1125,7 @@ out_unlock_leb:
}
/**
- * ubi_eba_init_scan - initialize the EBA unit using scanning information.
+ * ubi_eba_init_scan - initialize the EBA sub-system using scanning information.
* @ubi: UBI device description object
* @si: scanning information
*
@@ -1156,7 +1140,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
struct ubi_scan_leb *seb;
struct rb_node *rb;
- dbg_eba("initialize EBA unit");
+ dbg_eba("initialize EBA sub-system");
spin_lock_init(&ubi->ltree_lock);
mutex_init(&ubi->alc_mutex);
@@ -1222,7 +1206,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
ubi->rsvd_pebs += ubi->beb_rsvd_pebs;
}
- dbg_eba("EBA unit is initialized");
+ dbg_eba("EBA sub-system is initialized");
return 0;
out_free:
@@ -1233,20 +1217,3 @@ out_free:
}
return err;
}
-
-/**
- * ubi_eba_close - close EBA unit.
- * @ubi: UBI device description object
- */
-void ubi_eba_close(const struct ubi_device *ubi)
-{
- int i, num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT;
-
- dbg_eba("close EBA unit");
-
- for (i = 0; i < num_volumes; i++) {
- if (!ubi->volumes[i])
- continue;
- kfree(ubi->volumes[i]->eba_tbl);
- }
-}
diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c
index e909b390069..605812bb0b1 100644
--- a/drivers/mtd/ubi/gluebi.c
+++ b/drivers/mtd/ubi/gluebi.c
@@ -111,7 +111,7 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len,
struct ubi_device *ubi;
uint64_t tmp = from;
- dbg_msg("read %zd bytes from offset %lld", len, from);
+ dbg_gen("read %zd bytes from offset %lld", len, from);
if (len < 0 || from < 0 || from + len > mtd->size)
return -EINVAL;
@@ -162,7 +162,7 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len,
struct ubi_device *ubi;
uint64_t tmp = to;
- dbg_msg("write %zd bytes to offset %lld", len, to);
+ dbg_gen("write %zd bytes to offset %lld", len, to);
if (len < 0 || to < 0 || len + to > mtd->size)
return -EINVAL;
@@ -215,7 +215,7 @@ static int gluebi_erase(struct mtd_info *mtd, struct erase_info *instr)
struct ubi_volume *vol;
struct ubi_device *ubi;
- dbg_msg("erase %u bytes at offset %u", instr->len, instr->addr);
+ dbg_gen("erase %u bytes at offset %u", instr->len, instr->addr);
if (instr->addr < 0 || instr->addr > mtd->size - mtd->erasesize)
return -EINVAL;
@@ -249,8 +249,8 @@ static int gluebi_erase(struct mtd_info *mtd, struct erase_info *instr)
if (err)
goto out_err;
- instr->state = MTD_ERASE_DONE;
- mtd_erase_callback(instr);
+ instr->state = MTD_ERASE_DONE;
+ mtd_erase_callback(instr);
return 0;
out_err:
@@ -299,12 +299,12 @@ int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol)
mtd->size = vol->used_bytes;
if (add_mtd_device(mtd)) {
- ubi_err("cannot not add MTD device\n");
+ ubi_err("cannot not add MTD device");
kfree(mtd->name);
return -ENFILE;
}
- dbg_msg("added mtd%d (\"%s\"), size %u, EB size %u",
+ dbg_gen("added mtd%d (\"%s\"), size %u, EB size %u",
mtd->index, mtd->name, mtd->size, mtd->erasesize);
return 0;
}
@@ -322,7 +322,7 @@ int ubi_destroy_gluebi(struct ubi_volume *vol)
int err;
struct mtd_info *mtd = &vol->gluebi_mtd;
- dbg_msg("remove mtd%d", mtd->index);
+ dbg_gen("remove mtd%d", mtd->index);
err = del_mtd_device(mtd);
if (err)
return err;
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 4ac11df7b04..2fb64be44f1 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -20,15 +20,15 @@
*/
/*
- * UBI input/output unit.
+ * UBI input/output sub-system.
*
- * This unit provides a uniform way to work with all kinds of the underlying
- * MTD devices. It also implements handy functions for reading and writing UBI
- * headers.
+ * This sub-system provides a uniform way to work with all kinds of the
+ * underlying MTD devices. It also implements handy functions for reading and
+ * writing UBI headers.
*
* We are trying to have a paranoid mindset and not to trust to what we read
- * from the flash media in order to be more secure and robust. So this unit
- * validates every single header it reads from the flash media.
+ * from the flash media in order to be more secure and robust. So this
+ * sub-system validates every single header it reads from the flash media.
*
* Some words about how the eraseblock headers are stored.
*
@@ -79,11 +79,11 @@
* 512-byte chunks, we have to allocate one more buffer and copy our VID header
* to offset 448 of this buffer.
*
- * The I/O unit does the following trick in order to avoid this extra copy.
- * It always allocates a @ubi->vid_hdr_alsize bytes buffer for the VID header
- * and returns a pointer to offset @ubi->vid_hdr_shift of this buffer. When the
- * VID header is being written out, it shifts the VID header pointer back and
- * writes the whole sub-page.
+ * The I/O sub-system does the following trick in order to avoid this extra
+ * copy. It always allocates a @ubi->vid_hdr_alsize bytes buffer for the VID
+ * header and returns a pointer to offset @ubi->vid_hdr_shift of this buffer.
+ * When the VID header is being written out, it shifts the VID header pointer
+ * back and writes the whole sub-page.
*/
#include <linux/crc32.h>
@@ -156,15 +156,19 @@ retry:
/*
* -EUCLEAN is reported if there was a bit-flip which
* was corrected, so this is harmless.
+ *
+ * We do not report about it here unless debugging is
+ * enabled. A corresponding message will be printed
+ * later, when it is has been scrubbed.
*/
- ubi_msg("fixable bit-flip detected at PEB %d", pnum);
+ dbg_msg("fixable bit-flip detected at PEB %d", pnum);
ubi_assert(len == read);
return UBI_IO_BITFLIPS;
}
if (read != len && retries++ < UBI_IO_RETRIES) {
- dbg_io("error %d while reading %d bytes from PEB %d:%d, "
- "read only %zd bytes, retry",
+ dbg_io("error %d while reading %d bytes from PEB %d:%d,"
+ " read only %zd bytes, retry",
err, len, pnum, offset, read);
yield();
goto retry;
@@ -187,7 +191,7 @@ retry:
ubi_assert(len == read);
if (ubi_dbg_is_bitflip()) {
- dbg_msg("bit-flip (emulated)");
+ dbg_gen("bit-flip (emulated)");
err = UBI_IO_BITFLIPS;
}
}
@@ -391,6 +395,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
{
int err, i, patt_count;
+ ubi_msg("run torture test for PEB %d", pnum);
patt_count = ARRAY_SIZE(patterns);
ubi_assert(patt_count > 0);
@@ -434,6 +439,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
}
err = patt_count;
+ ubi_msg("PEB %d passed torture test, do not mark it a bad", pnum);
out:
mutex_unlock(&ubi->buf_mutex);
@@ -699,8 +705,8 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
if (hdr_crc != crc) {
if (verbose) {
- ubi_warn("bad EC header CRC at PEB %d, calculated %#08x,"
- " read %#08x", pnum, crc, hdr_crc);
+ ubi_warn("bad EC header CRC at PEB %d, calculated "
+ "%#08x, read %#08x", pnum, crc, hdr_crc);
ubi_dbg_dump_ec_hdr(ec_hdr);
}
return UBI_IO_BAD_EC_HDR;
@@ -1095,8 +1101,7 @@ fail:
}
/**
- * paranoid_check_peb_ec_hdr - check that the erase counter header of a
- * physical eraseblock is in-place and is all right.
+ * paranoid_check_peb_ec_hdr - check erase counter header.
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to check
*
@@ -1174,8 +1179,7 @@ fail:
}
/**
- * paranoid_check_peb_vid_hdr - check that the volume identifier header of a
- * physical eraseblock is in-place and is all right.
+ * paranoid_check_peb_vid_hdr - check volume identifier header.
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to check
*
@@ -1256,7 +1260,7 @@ static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
fail:
ubi_err("paranoid check failed for PEB %d", pnum);
- dbg_msg("hex dump of the %d-%d region", offset, offset + len);
+ ubi_msg("hex dump of the %d-%d region", offset, offset + len);
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
ubi->dbg_peb_buf, len, 1);
err = 1;
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index a70d58823f8..5d9bcf109c1 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -106,7 +106,7 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
struct ubi_device *ubi;
struct ubi_volume *vol;
- dbg_msg("open device %d volume %d, mode %d", ubi_num, vol_id, mode);
+ dbg_gen("open device %d volume %d, mode %d", ubi_num, vol_id, mode);
if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
return ERR_PTR(-EINVAL);
@@ -215,7 +215,7 @@ struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name,
struct ubi_device *ubi;
struct ubi_volume_desc *ret;
- dbg_msg("open volume %s, mode %d", name, mode);
+ dbg_gen("open volume %s, mode %d", name, mode);
if (!name)
return ERR_PTR(-EINVAL);
@@ -266,7 +266,7 @@ void ubi_close_volume(struct ubi_volume_desc *desc)
struct ubi_volume *vol = desc->vol;
struct ubi_device *ubi = vol->ubi;
- dbg_msg("close volume %d, mode %d", vol->vol_id, desc->mode);
+ dbg_gen("close volume %d, mode %d", vol->vol_id, desc->mode);
spin_lock(&ubi->volumes_lock);
switch (desc->mode) {
@@ -323,7 +323,7 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
struct ubi_device *ubi = vol->ubi;
int err, vol_id = vol->vol_id;
- dbg_msg("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
+ dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 ||
lnum >= vol->used_ebs || offset < 0 || len < 0 ||
@@ -388,7 +388,7 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
struct ubi_device *ubi = vol->ubi;
int vol_id = vol->vol_id;
- dbg_msg("write %d bytes to LEB %d:%d:%d", len, vol_id, lnum, offset);
+ dbg_gen("write %d bytes to LEB %d:%d:%d", len, vol_id, lnum, offset);
if (vol_id < 0 || vol_id >= ubi->vtbl_slots)
return -EINVAL;
@@ -397,8 +397,8 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
return -EROFS;
if (lnum < 0 || lnum >= vol->reserved_pebs || offset < 0 || len < 0 ||
- offset + len > vol->usable_leb_size || offset % ubi->min_io_size ||
- len % ubi->min_io_size)
+ offset + len > vol->usable_leb_size ||
+ offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1))
return -EINVAL;
if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
@@ -438,7 +438,7 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
struct ubi_device *ubi = vol->ubi;
int vol_id = vol->vol_id;
- dbg_msg("atomically write %d bytes to LEB %d:%d", len, vol_id, lnum);
+ dbg_gen("atomically write %d bytes to LEB %d:%d", len, vol_id, lnum);
if (vol_id < 0 || vol_id >= ubi->vtbl_slots)
return -EINVAL;
@@ -447,7 +447,7 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
return -EROFS;
if (lnum < 0 || lnum >= vol->reserved_pebs || len < 0 ||
- len > vol->usable_leb_size || len % ubi->min_io_size)
+ len > vol->usable_leb_size || len & (ubi->min_io_size - 1))
return -EINVAL;
if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
@@ -482,7 +482,7 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum)
struct ubi_device *ubi = vol->ubi;
int err;
- dbg_msg("erase LEB %d:%d", vol->vol_id, lnum);
+ dbg_gen("erase LEB %d:%d", vol->vol_id, lnum);
if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
return -EROFS;
@@ -542,7 +542,7 @@ int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum)
struct ubi_volume *vol = desc->vol;
struct ubi_device *ubi = vol->ubi;
- dbg_msg("unmap LEB %d:%d", vol->vol_id, lnum);
+ dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum);
if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
return -EROFS;
@@ -579,7 +579,7 @@ int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
struct ubi_volume *vol = desc->vol;
struct ubi_device *ubi = vol->ubi;
- dbg_msg("unmap LEB %d:%d", vol->vol_id, lnum);
+ dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum);
if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
return -EROFS;
@@ -621,7 +621,7 @@ int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum)
{
struct ubi_volume *vol = desc->vol;
- dbg_msg("test LEB %d:%d", vol->vol_id, lnum);
+ dbg_gen("test LEB %d:%d", vol->vol_id, lnum);
if (lnum < 0 || lnum >= vol->reserved_pebs)
return -EINVAL;
@@ -632,3 +632,27 @@ int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum)
return vol->eba_tbl[lnum] >= 0;
}
EXPORT_SYMBOL_GPL(ubi_is_mapped);
+
+/**
+ * ubi_sync - synchronize UBI device buffers.
+ * @ubi_num: UBI device to synchronize
+ *
+ * The underlying MTD device may cache data in hardware or in software. This
+ * function ensures the caches are flushed. Returns zero in case of success and
+ * a negative error code in case of failure.
+ */
+int ubi_sync(int ubi_num)
+{
+ struct ubi_device *ubi;
+
+ ubi = ubi_get_device(ubi_num);
+ if (!ubi)
+ return -ENODEV;
+
+ if (ubi->mtd->sync)
+ ubi->mtd->sync(ubi->mtd);
+
+ ubi_put_device(ubi);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ubi_sync);
diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c
index 93e05281201..22ad3140294 100644
--- a/drivers/mtd/ubi/misc.c
+++ b/drivers/mtd/ubi/misc.c
@@ -37,7 +37,7 @@ int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf,
{
int i;
- ubi_assert(length % ubi->min_io_size == 0);
+ ubi_assert(!(length & (ubi->min_io_size - 1)));
for (i = length - 1; i >= 0; i--)
if (((const uint8_t *)buf)[i] != 0xFF)
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 96d410e106a..967bb4406df 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -19,9 +19,9 @@
*/
/*
- * UBI scanning unit.
+ * UBI scanning sub-system.
*
- * This unit is responsible for scanning the flash media, checking UBI
+ * This sub-system is responsible for scanning the flash media, checking UBI
* headers and providing complete information about the UBI flash image.
*
* The scanning information is represented by a &struct ubi_scan_info' object.
@@ -93,8 +93,7 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
}
/**
- * validate_vid_hdr - check that volume identifier header is correct and
- * consistent.
+ * validate_vid_hdr - check volume identifier header.
* @vid_hdr: the volume identifier header to check
* @sv: information about the volume this logical eraseblock belongs to
* @pnum: physical eraseblock number the VID header came from
@@ -103,7 +102,7 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
* non-zero if an inconsistency was found and zero if not.
*
* Note, UBI does sanity check of everything it reads from the flash media.
- * Most of the checks are done in the I/O unit. Here we check that the
+ * Most of the checks are done in the I/O sub-system. Here we check that the
* information in the VID header is consistent to the information in other VID
* headers of the same volume.
*/
@@ -247,45 +246,21 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
struct ubi_vid_hdr *vh = NULL;
unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum);
- if (seb->sqnum == 0 && sqnum2 == 0) {
- long long abs, v1 = seb->leb_ver, v2 = be32_to_cpu(vid_hdr->leb_ver);
-
+ if (sqnum2 == seb->sqnum) {
/*
- * UBI constantly increases the logical eraseblock version
- * number and it can overflow. Thus, we have to bear in mind
- * that versions that are close to %0xFFFFFFFF are less then
- * versions that are close to %0.
- *
- * The UBI WL unit guarantees that the number of pending tasks
- * is not greater then %0x7FFFFFFF. So, if the difference
- * between any two versions is greater or equivalent to
- * %0x7FFFFFFF, there was an overflow and the logical
- * eraseblock with lower version is actually newer then the one
- * with higher version.
- *
- * FIXME: but this is anyway obsolete and will be removed at
- * some point.
+ * This must be a really ancient UBI image which has been
+ * created before sequence numbers support has been added. At
+ * that times we used 32-bit LEB versions stored in logical
+ * eraseblocks. That was before UBI got into mainline. We do not
+ * support these images anymore. Well, those images will work
+ * still work, but only if no unclean reboots happened.
*/
- dbg_bld("using old crappy leb_ver stuff");
-
- if (v1 == v2) {
- ubi_err("PEB %d and PEB %d have the same version %lld",
- seb->pnum, pnum, v1);
- return -EINVAL;
- }
-
- abs = v1 - v2;
- if (abs < 0)
- abs = -abs;
+ ubi_err("unsupported on-flash UBI format\n");
+ return -EINVAL;
+ }
- if (abs < 0x7FFFFFFF)
- /* Non-overflow situation */
- second_is_newer = (v2 > v1);
- else
- second_is_newer = (v2 < v1);
- } else
- /* Obviously the LEB with lower sequence counter is older */
- second_is_newer = sqnum2 > seb->sqnum;
+ /* Obviously the LEB with lower sequence counter is older */
+ second_is_newer = !!(sqnum2 > seb->sqnum);
/*
* Now we know which copy is newer. If the copy flag of the PEB with
@@ -293,7 +268,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
* check data CRC. For the second PEB we already have the VID header,
* for the first one - we'll need to re-read it from flash.
*
- * FIXME: this may be optimized so that we wouldn't read twice.
+ * Note: this may be optimized so that we wouldn't read twice.
*/
if (second_is_newer) {
@@ -379,8 +354,7 @@ out_free_vidh:
}
/**
- * ubi_scan_add_used - add information about a physical eraseblock to the
- * scanning information.
+ * ubi_scan_add_used - add physical eraseblock to the scanning information.
* @ubi: UBI device description object
* @si: scanning information
* @pnum: the physical eraseblock number
@@ -400,7 +374,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
int bitflips)
{
int err, vol_id, lnum;
- uint32_t leb_ver;
unsigned long long sqnum;
struct ubi_scan_volume *sv;
struct ubi_scan_leb *seb;
@@ -409,10 +382,9 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
vol_id = be32_to_cpu(vid_hdr->vol_id);
lnum = be32_to_cpu(vid_hdr->lnum);
sqnum = be64_to_cpu(vid_hdr->sqnum);
- leb_ver = be32_to_cpu(vid_hdr->leb_ver);
- dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, ver %u, bitflips %d",
- pnum, vol_id, lnum, ec, sqnum, leb_ver, bitflips);
+ dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, bitflips %d",
+ pnum, vol_id, lnum, ec, sqnum, bitflips);
sv = add_volume(si, vol_id, pnum, vid_hdr);
if (IS_ERR(sv) < 0)
@@ -445,25 +417,20 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
*/
dbg_bld("this LEB already exists: PEB %d, sqnum %llu, "
- "LEB ver %u, EC %d", seb->pnum, seb->sqnum,
- seb->leb_ver, seb->ec);
-
- /*
- * Make sure that the logical eraseblocks have different
- * versions. Otherwise the image is bad.
- */
- if (seb->leb_ver == leb_ver && leb_ver != 0) {
- ubi_err("two LEBs with same version %u", leb_ver);
- ubi_dbg_dump_seb(seb, 0);
- ubi_dbg_dump_vid_hdr(vid_hdr);
- return -EINVAL;
- }
+ "EC %d", seb->pnum, seb->sqnum, seb->ec);
/*
* Make sure that the logical eraseblocks have different
* sequence numbers. Otherwise the image is bad.
*
- * FIXME: remove 'sqnum != 0' check when leb_ver is removed.
+ * However, if the sequence number is zero, we assume it must
+ * be an ancient UBI image from the era when UBI did not have
+ * sequence numbers. We still can attach these images, unless
+ * there is a need to distinguish between old and new
+ * eraseblocks, in which case we'll refuse the image in
+ * 'compare_lebs()'. In other words, we attach old clean
+ * images, but refuse attaching old images with duplicated
+ * logical eraseblocks because there was an unclean reboot.
*/
if (seb->sqnum == sqnum && sqnum != 0) {
ubi_err("two LEBs with same sequence number %llu",
@@ -503,7 +470,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
seb->pnum = pnum;
seb->scrub = ((cmp_res & 2) || bitflips);
seb->sqnum = sqnum;
- seb->leb_ver = leb_ver;
if (sv->highest_lnum == lnum)
sv->last_data_size =
@@ -540,7 +506,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
seb->lnum = lnum;
seb->sqnum = sqnum;
seb->scrub = bitflips;
- seb->leb_ver = leb_ver;
if (sv->highest_lnum <= lnum) {
sv->highest_lnum = lnum;
@@ -554,8 +519,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
}
/**
- * ubi_scan_find_sv - find information about a particular volume in the
- * scanning information.
+ * ubi_scan_find_sv - find volume in the scanning information.
* @si: scanning information
* @vol_id: the requested volume ID
*
@@ -584,8 +548,7 @@ struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si,
}
/**
- * ubi_scan_find_seb - find information about a particular logical
- * eraseblock in the volume scanning information.
+ * ubi_scan_find_seb - find LEB in the volume scanning information.
* @sv: a pointer to the volume scanning information
* @lnum: the requested logical eraseblock
*
@@ -645,9 +608,9 @@ void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv)
*
* This function erases physical eraseblock 'pnum', and writes the erase
* counter header to it. This function should only be used on UBI device
- * initialization stages, when the EBA unit had not been yet initialized. This
- * function returns zero in case of success and a negative error code in case
- * of failure.
+ * initialization stages, when the EBA sub-system had not been yet initialized.
+ * This function returns zero in case of success and a negative error code in
+ * case of failure.
*/
int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si,
int pnum, int ec)
@@ -687,9 +650,10 @@ out_free:
* @si: scanning information
*
* This function returns a free physical eraseblock. It is supposed to be
- * called on the UBI initialization stages when the wear-leveling unit is not
- * initialized yet. This function picks a physical eraseblocks from one of the
- * lists, writes the EC header if it is needed, and removes it from the list.
+ * called on the UBI initialization stages when the wear-leveling sub-system is
+ * not initialized yet. This function picks a physical eraseblocks from one of
+ * the lists, writes the EC header if it is needed, and removes it from the
+ * list.
*
* This function returns scanning physical eraseblock information in case of
* success and an error code in case of failure.
@@ -742,8 +706,7 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
}
/**
- * process_eb - read UBI headers, check them and add corresponding data
- * to the scanning information.
+ * process_eb - read, check UBI headers, and add them to scanning information.
* @ubi: UBI device description object
* @si: scanning information
* @pnum: the physical eraseblock number
@@ -751,7 +714,8 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
* This function returns a zero if the physical eraseblock was successfully
* handled and a negative error code in case of failure.
*/
-static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum)
+static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
+ int pnum)
{
long long uninitialized_var(ec);
int err, bitflips = 0, vol_id, ec_corr = 0;
@@ -764,8 +728,9 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum
return err;
else if (err) {
/*
- * FIXME: this is actually duty of the I/O unit to initialize
- * this, but MTD does not provide enough information.
+ * FIXME: this is actually duty of the I/O sub-system to
+ * initialize this, but MTD does not provide enough
+ * information.
*/
si->bad_peb_count += 1;
return 0;
@@ -930,7 +895,7 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
for (pnum = 0; pnum < ubi->peb_count; pnum++) {
cond_resched();
- dbg_msg("process PEB %d", pnum);
+ dbg_gen("process PEB %d", pnum);
err = process_eb(ubi, si, pnum);
if (err < 0)
goto out_vidh;
@@ -1079,8 +1044,7 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si)
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
/**
- * paranoid_check_si - check if the scanning information is correct and
- * consistent.
+ * paranoid_check_si - check the scanning information.
* @ubi: UBI device description object
* @si: scanning information
*
@@ -1265,11 +1229,6 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
ubi_err("bad data_pad %d", sv->data_pad);
goto bad_vid_hdr;
}
-
- if (seb->leb_ver != be32_to_cpu(vidh->leb_ver)) {
- ubi_err("bad leb_ver %u", seb->leb_ver);
- goto bad_vid_hdr;
- }
}
if (!last_seb)
@@ -1299,8 +1258,7 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
if (err < 0) {
kfree(buf);
return err;
- }
- else if (err)
+ } else if (err)
buf[pnum] = 1;
}
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h
index 966b9b682a4..61df208e2f2 100644
--- a/drivers/mtd/ubi/scan.h
+++ b/drivers/mtd/ubi/scan.h
@@ -34,7 +34,6 @@
* @u: unions RB-tree or @list links
* @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects
* @u.list: link in one of the eraseblock lists
- * @leb_ver: logical eraseblock version (obsolete)
*
* One object of this type is allocated for each physical eraseblock during
* scanning.
@@ -49,7 +48,6 @@ struct ubi_scan_leb {
struct rb_node rb;
struct list_head list;
} u;
- uint32_t leb_ver;
};
/**
@@ -59,16 +57,16 @@ struct ubi_scan_leb {
* @leb_count: number of logical eraseblocks in this volume
* @vol_type: volume type
* @used_ebs: number of used logical eraseblocks in this volume (only for
- * static volumes)
+ * static volumes)
* @last_data_size: amount of data in the last logical eraseblock of this
- * volume (always equivalent to the usable logical eraseblock size in case of
- * dynamic volumes)
+ * volume (always equivalent to the usable logical eraseblock
+ * size in case of dynamic volumes)
* @data_pad: how many bytes at the end of logical eraseblocks of this volume
- * are not used (due to volume alignment)
+ * are not used (due to volume alignment)
* @compat: compatibility flags of this volume
* @rb: link in the volume RB-tree
* @root: root of the RB-tree containing all the eraseblock belonging to this
- * volume (&struct ubi_scan_leb objects)
+ * volume (&struct ubi_scan_leb objects)
*
* One object of this type is allocated for each volume during scanning.
*/
@@ -92,8 +90,8 @@ struct ubi_scan_volume {
* @free: list of free physical eraseblocks
* @erase: list of physical eraseblocks which have to be erased
* @alien: list of physical eraseblocks which should not be used by UBI (e.g.,
+ * those belonging to "preserve"-compatible internal volumes)
* @bad_peb_count: count of bad physical eraseblocks
- * those belonging to "preserve"-compatible internal volumes)
* @vols_found: number of volumes found during scanning
* @highest_vol_id: highest volume ID
* @alien_peb_count: count of physical eraseblocks in the @alien list
@@ -106,8 +104,8 @@ struct ubi_scan_volume {
* @ec_count: a temporary variable used when calculating @mean_ec
*
* This data structure contains the result of scanning and may be used by other
- * UBI units to build final UBI data structures, further error-recovery and so
- * on.
+ * UBI sub-systems to build final UBI data structures, further error-recovery
+ * and so on.
*/
struct ubi_scan_info {
struct rb_root volumes;
@@ -132,8 +130,7 @@ struct ubi_device;
struct ubi_vid_hdr;
/*
- * ubi_scan_move_to_list - move a physical eraseblock from the volume tree to a
- * list.
+ * ubi_scan_move_to_list - move a PEB from the volume tree to a list.
*
* @sv: volume scanning information
* @seb: scanning eraseblock infprmation
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h
index c3185d9fd04..2ad94040905 100644
--- a/drivers/mtd/ubi/ubi-media.h
+++ b/drivers/mtd/ubi/ubi-media.h
@@ -98,10 +98,11 @@ enum {
* Compatibility constants used by internal volumes.
*
* @UBI_COMPAT_DELETE: delete this internal volume before anything is written
- * to the flash
+ * to the flash
* @UBI_COMPAT_RO: attach this device in read-only mode
* @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its
- * physical eraseblocks, don't allow the wear-leveling unit to move them
+ * physical eraseblocks, don't allow the wear-leveling
+ * sub-system to move them
* @UBI_COMPAT_REJECT: reject this UBI image
*/
enum {
@@ -123,7 +124,7 @@ enum {
* struct ubi_ec_hdr - UBI erase counter header.
* @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC)
* @version: version of UBI implementation which is supposed to accept this
- * UBI image
+ * UBI image
* @padding1: reserved for future, zeroes
* @ec: the erase counter
* @vid_hdr_offset: where the VID header starts
@@ -159,24 +160,23 @@ struct ubi_ec_hdr {
* struct ubi_vid_hdr - on-flash UBI volume identifier header.
* @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC)
* @version: UBI implementation version which is supposed to accept this UBI
- * image (%UBI_VERSION)
+ * image (%UBI_VERSION)
* @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
* @copy_flag: if this logical eraseblock was copied from another physical
- * eraseblock (for wear-leveling reasons)
+ * eraseblock (for wear-leveling reasons)
* @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
- * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
+ * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
* @vol_id: ID of this volume
* @lnum: logical eraseblock number
- * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be
- * removed, kept only for not breaking older UBI users)
+ * @padding1: reserved for future, zeroes
* @data_size: how many bytes of data this logical eraseblock contains
* @used_ebs: total number of used logical eraseblocks in this volume
* @data_pad: how many bytes at the end of this physical eraseblock are not
- * used
+ * used
* @data_crc: CRC checksum of the data stored in this logical eraseblock
- * @padding1: reserved for future, zeroes
- * @sqnum: sequence number
* @padding2: reserved for future, zeroes
+ * @sqnum: sequence number
+ * @padding3: reserved for future, zeroes
* @hdr_crc: volume identifier header CRC checksum
*
* The @sqnum is the value of the global sequence counter at the time when this
@@ -224,10 +224,6 @@ struct ubi_ec_hdr {
* checksum is correct, this physical eraseblock is selected (P1). Otherwise
* the older one (P) is selected.
*
- * Note, there is an obsolete @leb_ver field which was used instead of @sqnum
- * in the past. But it is not used anymore and we keep it in order to be able
- * to deal with old UBI images. It will be removed at some point.
- *
* There are 2 sorts of volumes in UBI: user volumes and internal volumes.
* Internal volumes are not seen from outside and are used for various internal
* UBI purposes. In this implementation there is only one internal volume - the
@@ -248,9 +244,9 @@ struct ubi_ec_hdr {
* The @data_crc field contains the CRC checksum of the contents of the logical
* eraseblock if this is a static volume. In case of dynamic volumes, it does
* not contain the CRC checksum as a rule. The only exception is when the
- * data of the physical eraseblock was moved by the wear-leveling unit, then
- * the wear-leveling unit calculates the data CRC and stores it in the
- * @data_crc field. And of course, the @copy_flag is %in this case.
+ * data of the physical eraseblock was moved by the wear-leveling sub-system,
+ * then the wear-leveling sub-system calculates the data CRC and stores it in
+ * the @data_crc field. And of course, the @copy_flag is %in this case.
*
* The @data_size field is used only for static volumes because UBI has to know
* how many bytes of data are stored in this eraseblock. For dynamic volumes,
@@ -277,14 +273,14 @@ struct ubi_vid_hdr {
__u8 compat;
__be32 vol_id;
__be32 lnum;
- __be32 leb_ver; /* obsolete, to be removed, don't use */
+ __u8 padding1[4];
__be32 data_size;
__be32 used_ebs;
__be32 data_pad;
__be32 data_crc;
- __u8 padding1[4];
+ __u8 padding2[4];
__be64 sqnum;
- __u8 padding2[12];
+ __u8 padding3[12];
__be32 hdr_crc;
} __attribute__ ((packed));
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 67dcbd11c15..1c3fa18c26a 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -74,15 +74,15 @@
#define UBI_IO_RETRIES 3
/*
- * Error codes returned by the I/O unit.
+ * Error codes returned by the I/O sub-system.
*
* UBI_IO_PEB_EMPTY: the physical eraseblock is empty, i.e. it contains only
- * 0xFF bytes
+ * %0xFF bytes
* UBI_IO_PEB_FREE: the physical eraseblock is free, i.e. it contains only a
- * valid erase counter header, and the rest are %0xFF bytes
+ * valid erase counter header, and the rest are %0xFF bytes
* UBI_IO_BAD_EC_HDR: the erase counter header is corrupted (bad magic or CRC)
* UBI_IO_BAD_VID_HDR: the volume identifier header is corrupted (bad magic or
- * CRC)
+ * CRC)
* UBI_IO_BITFLIPS: bit-flips were detected and corrected
*/
enum {
@@ -99,9 +99,9 @@ enum {
* @ec: erase counter
* @pnum: physical eraseblock number
*
- * This data structure is used in the WL unit. Each physical eraseblock has a
- * corresponding &struct wl_entry object which may be kept in different
- * RB-trees. See WL unit for details.
+ * This data structure is used in the WL sub-system. Each physical eraseblock
+ * has a corresponding &struct wl_entry object which may be kept in different
+ * RB-trees. See WL sub-system for details.
*/
struct ubi_wl_entry {
struct rb_node rb;
@@ -118,10 +118,10 @@ struct ubi_wl_entry {
* @mutex: read/write mutex to implement read/write access serialization to
* the (@vol_id, @lnum) logical eraseblock
*
- * This data structure is used in the EBA unit to implement per-LEB locking.
- * When a logical eraseblock is being locked - corresponding
+ * This data structure is used in the EBA sub-system to implement per-LEB
+ * locking. When a logical eraseblock is being locked - corresponding
* &struct ubi_ltree_entry object is inserted to the lock tree (@ubi->ltree).
- * See EBA unit for details.
+ * See EBA sub-system for details.
*/
struct ubi_ltree_entry {
struct rb_node rb;
@@ -131,6 +131,27 @@ struct ubi_ltree_entry {
struct rw_semaphore mutex;
};
+/**
+ * struct ubi_rename_entry - volume re-name description data structure.
+ * @new_name_len: new volume name length
+ * @new_name: new volume name
+ * @remove: if not zero, this volume should be removed, not re-named
+ * @desc: descriptor of the volume
+ * @list: links re-name entries into a list
+ *
+ * This data structure is utilized in the multiple volume re-name code. Namely,
+ * UBI first creates a list of &struct ubi_rename_entry objects from the
+ * &struct ubi_rnvol_req request object, and then utilizes this list to do all
+ * the job.
+ */
+struct ubi_rename_entry {
+ int new_name_len;
+ char new_name[UBI_VOL_NAME_MAX + 1];
+ int remove;
+ struct ubi_volume_desc *desc;
+ struct list_head list;
+};
+
struct ubi_volume_desc;
/**
@@ -206,7 +227,7 @@ struct ubi_volume {
int alignment;
int data_pad;
int name_len;
- char name[UBI_VOL_NAME_MAX+1];
+ char name[UBI_VOL_NAME_MAX + 1];
int upd_ebs;
int ch_lnum;
@@ -225,7 +246,7 @@ struct ubi_volume {
#ifdef CONFIG_MTD_UBI_GLUEBI
/*
* Gluebi-related stuff may be compiled out.
- * TODO: this should not be built into UBI but should be a separate
+ * Note: this should not be built into UBI but should be a separate
* ubimtd driver which works on top of UBI and emulates MTD devices.
*/
struct ubi_volume_desc *gluebi_desc;
@@ -235,8 +256,7 @@ struct ubi_volume {
};
/**
- * struct ubi_volume_desc - descriptor of the UBI volume returned when it is
- * opened.
+ * struct ubi_volume_desc - UBI volume descriptor returned when it is opened.
* @vol: reference to the corresponding volume description object
* @mode: open mode (%UBI_READONLY, %UBI_READWRITE, or %UBI_EXCLUSIVE)
*/
@@ -273,7 +293,7 @@ struct ubi_wl_entry;
* @vtbl_size: size of the volume table in bytes
* @vtbl: in-RAM volume table copy
* @volumes_mutex: protects on-flash volume table and serializes volume
- * changes, like creation, deletion, update, resize
+ * changes, like creation, deletion, update, re-size and re-name
*
* @max_ec: current highest erase counter value
* @mean_ec: current mean erase counter value
@@ -293,6 +313,7 @@ struct ubi_wl_entry;
* @move_to, @move_to_put @erase_pending, @wl_scheduled, and @works
* fields
* @move_mutex: serializes eraseblock moves
+ * @work_sem: sycnhronizes the WL worker with use tasks
* @wl_scheduled: non-zero if the wear-leveling was scheduled
* @lookuptbl: a table to quickly find a &struct ubi_wl_entry object for any
* physical eraseblock
@@ -316,11 +337,11 @@ struct ubi_wl_entry;
* @ro_mode: if the UBI device is in read-only mode
* @leb_size: logical eraseblock size
* @leb_start: starting offset of logical eraseblocks within physical
- * eraseblocks
+ * eraseblocks
* @ec_hdr_alsize: size of the EC header aligned to @hdrs_min_io_size
* @vid_hdr_alsize: size of the VID header aligned to @hdrs_min_io_size
* @vid_hdr_offset: starting offset of the volume identifier header (might be
- * unaligned)
+ * unaligned)
* @vid_hdr_aloffset: starting offset of the VID header aligned to
* @hdrs_min_io_size
* @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset
@@ -331,6 +352,8 @@ struct ubi_wl_entry;
* @peb_buf1: a buffer of PEB size used for different purposes
* @peb_buf2: another buffer of PEB size used for different purposes
* @buf_mutex: proptects @peb_buf1 and @peb_buf2
+ * @ckvol_mutex: serializes static volume checking when opening
+ * @mult_mutex: serializes operations on multiple volumes, like re-nameing
* @dbg_peb_buf: buffer of PEB size used for debugging
* @dbg_buf_mutex: proptects @dbg_peb_buf
*/
@@ -356,16 +379,16 @@ struct ubi_device {
struct mutex volumes_mutex;
int max_ec;
- /* TODO: mean_ec is not updated run-time, fix */
+ /* Note, mean_ec is not updated run-time - should be fixed */
int mean_ec;
- /* EBA unit's stuff */
+ /* EBA sub-system's stuff */
unsigned long long global_sqnum;
spinlock_t ltree_lock;
struct rb_root ltree;
struct mutex alc_mutex;
- /* Wear-leveling unit's stuff */
+ /* Wear-leveling sub-system's stuff */
struct rb_root used;
struct rb_root free;
struct rb_root scrub;
@@ -388,7 +411,7 @@ struct ubi_device {
int thread_enabled;
char bgt_name[sizeof(UBI_BGT_NAME_PATTERN)+2];
- /* I/O unit's stuff */
+ /* I/O sub-system's stuff */
long long flash_size;
int peb_count;
int peb_size;
@@ -411,6 +434,7 @@ struct ubi_device {
void *peb_buf2;
struct mutex buf_mutex;
struct mutex ckvol_mutex;
+ struct mutex mult_mutex;
#ifdef CONFIG_MTD_UBI_DEBUG
void *dbg_peb_buf;
struct mutex dbg_buf_mutex;
@@ -427,12 +451,15 @@ extern struct mutex ubi_devices_mutex;
/* vtbl.c */
int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
struct ubi_vtbl_record *vtbl_rec);
+int ubi_vtbl_rename_volumes(struct ubi_device *ubi,
+ struct list_head *rename_list);
int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si);
/* vmt.c */
int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req);
-int ubi_remove_volume(struct ubi_volume_desc *desc);
+int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl);
int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs);
+int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list);
int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol);
void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol);
@@ -447,7 +474,8 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
const void __user *buf, int count);
/* misc.c */
-int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf, int length);
+int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf,
+ int length);
int ubi_check_volume(struct ubi_device *ubi, int vol_id);
void ubi_calculate_reserved(struct ubi_device *ubi);
@@ -477,7 +505,6 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
struct ubi_vid_hdr *vid_hdr);
int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si);
-void ubi_eba_close(const struct ubi_device *ubi);
/* wl.c */
int ubi_wl_get_peb(struct ubi_device *ubi, int dtype);
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
index ddaa1a56cc6..8b89cc18ff0 100644
--- a/drivers/mtd/ubi/upd.c
+++ b/drivers/mtd/ubi/upd.c
@@ -39,7 +39,7 @@
*/
#include <linux/err.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/div64.h>
#include "ubi.h"
@@ -56,11 +56,11 @@ static int set_update_marker(struct ubi_device *ubi, struct ubi_volume *vol)
int err;
struct ubi_vtbl_record vtbl_rec;
- dbg_msg("set update marker for volume %d", vol->vol_id);
+ dbg_gen("set update marker for volume %d", vol->vol_id);
if (vol->upd_marker) {
ubi_assert(ubi->vtbl[vol->vol_id].upd_marker);
- dbg_msg("already set");
+ dbg_gen("already set");
return 0;
}
@@ -92,7 +92,7 @@ static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol,
uint64_t tmp;
struct ubi_vtbl_record vtbl_rec;
- dbg_msg("clear update marker for volume %d", vol->vol_id);
+ dbg_gen("clear update marker for volume %d", vol->vol_id);
memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id],
sizeof(struct ubi_vtbl_record));
@@ -133,7 +133,7 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
int i, err;
uint64_t tmp;
- dbg_msg("start update of volume %d, %llu bytes", vol->vol_id, bytes);
+ dbg_gen("start update of volume %d, %llu bytes", vol->vol_id, bytes);
ubi_assert(!vol->updating && !vol->changing_leb);
vol->updating = 1;
@@ -183,7 +183,7 @@ int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
{
ubi_assert(!vol->updating && !vol->changing_leb);
- dbg_msg("start changing LEB %d:%d, %u bytes",
+ dbg_gen("start changing LEB %d:%d, %u bytes",
vol->vol_id, req->lnum, req->bytes);
if (req->bytes == 0)
return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0,
@@ -237,16 +237,17 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
int err;
if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
- len = ALIGN(len, ubi->min_io_size);
- memset(buf + len, 0xFF, len - len);
+ int l = ALIGN(len, ubi->min_io_size);
- len = ubi_calc_data_len(ubi, buf, len);
+ memset(buf + len, 0xFF, l - len);
+ len = ubi_calc_data_len(ubi, buf, l);
if (len == 0) {
- dbg_msg("all %d bytes contain 0xFF - skip", len);
+ dbg_gen("all %d bytes contain 0xFF - skip", len);
return 0;
}
- err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len, UBI_UNKNOWN);
+ err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len,
+ UBI_UNKNOWN);
} else {
/*
* When writing static volume, and this is the last logical
@@ -267,6 +268,7 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
/**
* ubi_more_update_data - write more update data.
+ * @ubi: UBI device description object
* @vol: volume description object
* @buf: write data (user-space memory buffer)
* @count: how much bytes to write
@@ -283,7 +285,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
uint64_t tmp;
int lnum, offs, err = 0, len, to_write = count;
- dbg_msg("write %d of %lld bytes, %lld already passed",
+ dbg_gen("write %d of %lld bytes, %lld already passed",
count, vol->upd_bytes, vol->upd_received);
if (ubi->ro_mode)
@@ -384,6 +386,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
/**
* ubi_more_leb_change_data - accept more data for atomic LEB change.
+ * @ubi: UBI device description object
* @vol: volume description object
* @buf: write data (user-space memory buffer)
* @count: how much bytes to write
@@ -400,7 +403,7 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
{
int err;
- dbg_msg("write %d of %lld bytes, %lld already passed",
+ dbg_gen("write %d of %lld bytes, %lld already passed",
count, vol->upd_bytes, vol->upd_received);
if (ubi->ro_mode)
@@ -418,7 +421,8 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
if (vol->upd_received == vol->upd_bytes) {
int len = ALIGN((int)vol->upd_bytes, ubi->min_io_size);
- memset(vol->upd_buf + vol->upd_bytes, 0xFF, len - vol->upd_bytes);
+ memset(vol->upd_buf + vol->upd_bytes, 0xFF,
+ len - vol->upd_bytes);
len = ubi_calc_data_len(ubi, vol->upd_buf, len);
err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum,
vol->upd_buf, len, UBI_UNKNOWN);
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 5be58d85c63..3531ca9a1e2 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -28,9 +28,9 @@
#include "ubi.h"
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
-static void paranoid_check_volumes(struct ubi_device *ubi);
+static int paranoid_check_volumes(struct ubi_device *ubi);
#else
-#define paranoid_check_volumes(ubi)
+#define paranoid_check_volumes(ubi) 0
#endif
static ssize_t vol_attribute_show(struct device *dev,
@@ -127,6 +127,7 @@ static void vol_release(struct device *dev)
{
struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev);
+ kfree(vol->eba_tbl);
kfree(vol);
}
@@ -201,7 +202,7 @@ static void volume_sysfs_close(struct ubi_volume *vol)
*/
int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
{
- int i, err, vol_id = req->vol_id, dont_free = 0;
+ int i, err, vol_id = req->vol_id, do_free = 1;
struct ubi_volume *vol;
struct ubi_vtbl_record vtbl_rec;
uint64_t bytes;
@@ -217,7 +218,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
spin_lock(&ubi->volumes_lock);
if (vol_id == UBI_VOL_NUM_AUTO) {
/* Find unused volume ID */
- dbg_msg("search for vacant volume ID");
+ dbg_gen("search for vacant volume ID");
for (i = 0; i < ubi->vtbl_slots; i++)
if (!ubi->volumes[i]) {
vol_id = i;
@@ -232,7 +233,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
req->vol_id = vol_id;
}
- dbg_msg("volume ID %d, %llu bytes, type %d, name %s",
+ dbg_gen("volume ID %d, %llu bytes, type %d, name %s",
vol_id, (unsigned long long)req->bytes,
(int)req->vol_type, req->name);
@@ -252,7 +253,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
goto out_unlock;
}
- /* Calculate how many eraseblocks are requested */
+ /* Calculate how many eraseblocks are requested */
vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment;
bytes = req->bytes;
if (do_div(bytes, vol->usable_leb_size))
@@ -274,7 +275,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
vol->data_pad = ubi->leb_size % vol->alignment;
vol->vol_type = req->vol_type;
vol->name_len = req->name_len;
- memcpy(vol->name, req->name, vol->name_len + 1);
+ memcpy(vol->name, req->name, vol->name_len);
vol->ubi = ubi;
/*
@@ -349,7 +350,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
vtbl_rec.vol_type = UBI_VID_DYNAMIC;
else
vtbl_rec.vol_type = UBI_VID_STATIC;
- memcpy(vtbl_rec.name, vol->name, vol->name_len + 1);
+ memcpy(vtbl_rec.name, vol->name, vol->name_len);
err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
if (err)
@@ -360,19 +361,19 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
ubi->vol_count += 1;
spin_unlock(&ubi->volumes_lock);
- paranoid_check_volumes(ubi);
- return 0;
+ err = paranoid_check_volumes(ubi);
+ return err;
out_sysfs:
/*
- * We have registered our device, we should not free the volume*
+ * We have registered our device, we should not free the volume
* description object in this function in case of an error - it is
* freed by the release function.
*
* Get device reference to prevent the release function from being
* called just after sysfs has been closed.
*/
- dont_free = 1;
+ do_free = 0;
get_device(&vol->dev);
volume_sysfs_close(vol);
out_gluebi:
@@ -382,17 +383,18 @@ out_gluebi:
out_cdev:
cdev_del(&vol->cdev);
out_mapping:
- kfree(vol->eba_tbl);
+ if (do_free)
+ kfree(vol->eba_tbl);
out_acc:
spin_lock(&ubi->volumes_lock);
ubi->rsvd_pebs -= vol->reserved_pebs;
ubi->avail_pebs += vol->reserved_pebs;
out_unlock:
spin_unlock(&ubi->volumes_lock);
- if (dont_free)
- put_device(&vol->dev);
- else
+ if (do_free)
kfree(vol);
+ else
+ put_device(&vol->dev);
ubi_err("cannot create volume %d, error %d", vol_id, err);
return err;
}
@@ -400,19 +402,20 @@ out_unlock:
/**
* ubi_remove_volume - remove volume.
* @desc: volume descriptor
+ * @no_vtbl: do not change volume table if not zero
*
* This function removes volume described by @desc. The volume has to be opened
* in "exclusive" mode. Returns zero in case of success and a negative error
* code in case of failure. The caller has to have the @ubi->volumes_mutex
* locked.
*/
-int ubi_remove_volume(struct ubi_volume_desc *desc)
+int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl)
{
struct ubi_volume *vol = desc->vol;
struct ubi_device *ubi = vol->ubi;
int i, err, vol_id = vol->vol_id, reserved_pebs = vol->reserved_pebs;
- dbg_msg("remove UBI volume %d", vol_id);
+ dbg_gen("remove UBI volume %d", vol_id);
ubi_assert(desc->mode == UBI_EXCLUSIVE);
ubi_assert(vol == ubi->volumes[vol_id]);
@@ -435,9 +438,11 @@ int ubi_remove_volume(struct ubi_volume_desc *desc)
if (err)
goto out_err;
- err = ubi_change_vtbl_record(ubi, vol_id, NULL);
- if (err)
- goto out_err;
+ if (!no_vtbl) {
+ err = ubi_change_vtbl_record(ubi, vol_id, NULL);
+ if (err)
+ goto out_err;
+ }
for (i = 0; i < vol->reserved_pebs; i++) {
err = ubi_eba_unmap_leb(ubi, vol, i);
@@ -445,8 +450,6 @@ int ubi_remove_volume(struct ubi_volume_desc *desc)
goto out_err;
}
- kfree(vol->eba_tbl);
- vol->eba_tbl = NULL;
cdev_del(&vol->cdev);
volume_sysfs_close(vol);
@@ -465,8 +468,9 @@ int ubi_remove_volume(struct ubi_volume_desc *desc)
ubi->vol_count -= 1;
spin_unlock(&ubi->volumes_lock);
- paranoid_check_volumes(ubi);
- return 0;
+ if (!no_vtbl)
+ err = paranoid_check_volumes(ubi);
+ return err;
out_err:
ubi_err("cannot remove volume %d, error %d", vol_id, err);
@@ -497,7 +501,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
if (ubi->ro_mode)
return -EROFS;
- dbg_msg("re-size volume %d to from %d to %d PEBs",
+ dbg_gen("re-size volume %d to from %d to %d PEBs",
vol_id, vol->reserved_pebs, reserved_pebs);
if (vol->vol_type == UBI_STATIC_VOLUME &&
@@ -586,8 +590,8 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
(long long)vol->used_ebs * vol->usable_leb_size;
}
- paranoid_check_volumes(ubi);
- return 0;
+ err = paranoid_check_volumes(ubi);
+ return err;
out_acc:
if (pebs > 0) {
@@ -602,6 +606,44 @@ out_free:
}
/**
+ * ubi_rename_volumes - re-name UBI volumes.
+ * @ubi: UBI device description object
+ * @rename_list: list of &struct ubi_rename_entry objects
+ *
+ * This function re-names or removes volumes specified in the re-name list.
+ * Returns zero in case of success and a negative error code in case of
+ * failure.
+ */
+int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list)
+{
+ int err;
+ struct ubi_rename_entry *re;
+
+ err = ubi_vtbl_rename_volumes(ubi, rename_list);
+ if (err)
+ return err;
+
+ list_for_each_entry(re, rename_list, list) {
+ if (re->remove) {
+ err = ubi_remove_volume(re->desc, 1);
+ if (err)
+ break;
+ } else {
+ struct ubi_volume *vol = re->desc->vol;
+
+ spin_lock(&ubi->volumes_lock);
+ vol->name_len = re->new_name_len;
+ memcpy(vol->name, re->new_name, re->new_name_len + 1);
+ spin_unlock(&ubi->volumes_lock);
+ }
+ }
+
+ if (!err)
+ err = paranoid_check_volumes(ubi);
+ return err;
+}
+
+/**
* ubi_add_volume - add volume.
* @ubi: UBI device description object
* @vol: volume description object
@@ -615,8 +657,7 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol)
int err, vol_id = vol->vol_id;
dev_t dev;
- dbg_msg("add volume %d", vol_id);
- ubi_dbg_dump_vol_info(vol);
+ dbg_gen("add volume %d", vol_id);
/* Register character device for the volume */
cdev_init(&vol->cdev, &ubi_vol_cdev_operations);
@@ -650,8 +691,8 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol)
return err;
}
- paranoid_check_volumes(ubi);
- return 0;
+ err = paranoid_check_volumes(ubi);
+ return err;
out_gluebi:
err = ubi_destroy_gluebi(vol);
@@ -672,7 +713,7 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol)
{
int err;
- dbg_msg("free volume %d", vol->vol_id);
+ dbg_gen("free volume %d", vol->vol_id);
ubi->volumes[vol->vol_id] = NULL;
err = ubi_destroy_gluebi(vol);
@@ -686,8 +727,10 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol)
* paranoid_check_volume - check volume information.
* @ubi: UBI device description object
* @vol_id: volume ID
+ *
+ * Returns zero if volume is all right and a a negative error code if not.
*/
-static void paranoid_check_volume(struct ubi_device *ubi, int vol_id)
+static int paranoid_check_volume(struct ubi_device *ubi, int vol_id)
{
int idx = vol_id2idx(ubi, vol_id);
int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker;
@@ -705,16 +748,7 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id)
goto fail;
}
spin_unlock(&ubi->volumes_lock);
- return;
- }
-
- if (vol->exclusive) {
- /*
- * The volume may be being created at the moment, do not check
- * it (e.g., it may be in the middle of ubi_create_volume().
- */
- spin_unlock(&ubi->volumes_lock);
- return;
+ return 0;
}
if (vol->reserved_pebs < 0 || vol->alignment < 0 || vol->data_pad < 0 ||
@@ -727,7 +761,7 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id)
goto fail;
}
- n = vol->alignment % ubi->min_io_size;
+ n = vol->alignment & (ubi->min_io_size - 1);
if (vol->alignment != 1 && n) {
ubi_err("alignment is not multiple of min I/O unit");
goto fail;
@@ -824,31 +858,39 @@ static void paranoid_check_volume(struct ubi_device *ubi, int vol_id)
if (alignment != vol->alignment || data_pad != vol->data_pad ||
upd_marker != vol->upd_marker || vol_type != vol->vol_type ||
- name_len!= vol->name_len || strncmp(name, vol->name, name_len)) {
+ name_len != vol->name_len || strncmp(name, vol->name, name_len)) {
ubi_err("volume info is different");
goto fail;
}
spin_unlock(&ubi->volumes_lock);
- return;
+ return 0;
fail:
ubi_err("paranoid check failed for volume %d", vol_id);
- ubi_dbg_dump_vol_info(vol);
+ if (vol)
+ ubi_dbg_dump_vol_info(vol);
ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id);
spin_unlock(&ubi->volumes_lock);
- BUG();
+ return -EINVAL;
}
/**
* paranoid_check_volumes - check information about all volumes.
* @ubi: UBI device description object
+ *
+ * Returns zero if volumes are all right and a a negative error code if not.
*/
-static void paranoid_check_volumes(struct ubi_device *ubi)
+static int paranoid_check_volumes(struct ubi_device *ubi)
{
- int i;
+ int i, err = 0;
- for (i = 0; i < ubi->vtbl_slots; i++)
- paranoid_check_volume(ubi, i);
+ for (i = 0; i < ubi->vtbl_slots; i++) {
+ err = paranoid_check_volume(ubi, i);
+ if (err)
+ break;
+ }
+
+ return err;
}
#endif
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index af36b12be27..217d0e111b2 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -115,8 +115,58 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
}
/**
- * vtbl_check - check if volume table is not corrupted and contains sensible
- * data.
+ * ubi_vtbl_rename_volumes - rename UBI volumes in the volume table.
+ * @ubi: UBI device description object
+ * @rename_list: list of &struct ubi_rename_entry objects
+ *
+ * This function re-names multiple volumes specified in @req in the volume
+ * table. Returns zero in case of success and a negative error code in case of
+ * failure.
+ */
+int ubi_vtbl_rename_volumes(struct ubi_device *ubi,
+ struct list_head *rename_list)
+{
+ int i, err;
+ struct ubi_rename_entry *re;
+ struct ubi_volume *layout_vol;
+
+ list_for_each_entry(re, rename_list, list) {
+ uint32_t crc;
+ struct ubi_volume *vol = re->desc->vol;
+ struct ubi_vtbl_record *vtbl_rec = &ubi->vtbl[vol->vol_id];
+
+ if (re->remove) {
+ memcpy(vtbl_rec, &empty_vtbl_record,
+ sizeof(struct ubi_vtbl_record));
+ continue;
+ }
+
+ vtbl_rec->name_len = cpu_to_be16(re->new_name_len);
+ memcpy(vtbl_rec->name, re->new_name, re->new_name_len);
+ memset(vtbl_rec->name + re->new_name_len, 0,
+ UBI_VOL_NAME_MAX + 1 - re->new_name_len);
+ crc = crc32(UBI_CRC32_INIT, vtbl_rec,
+ UBI_VTBL_RECORD_SIZE_CRC);
+ vtbl_rec->crc = cpu_to_be32(crc);
+ }
+
+ layout_vol = ubi->volumes[vol_id2idx(ubi, UBI_LAYOUT_VOLUME_ID)];
+ for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
+ err = ubi_eba_unmap_leb(ubi, layout_vol, i);
+ if (err)
+ return err;
+
+ err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
+ ubi->vtbl_size, UBI_LONGTERM);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+/**
+ * vtbl_check - check if volume table is not corrupted and sensible.
* @ubi: UBI device description object
* @vtbl: volume table
*
@@ -127,7 +177,7 @@ static int vtbl_check(const struct ubi_device *ubi,
const struct ubi_vtbl_record *vtbl)
{
int i, n, reserved_pebs, alignment, data_pad, vol_type, name_len;
- int upd_marker;
+ int upd_marker, err;
uint32_t crc;
const char *name;
@@ -153,7 +203,7 @@ static int vtbl_check(const struct ubi_device *ubi,
if (reserved_pebs == 0) {
if (memcmp(&vtbl[i], &empty_vtbl_record,
UBI_VTBL_RECORD_SIZE)) {
- dbg_err("bad empty record");
+ err = 2;
goto bad;
}
continue;
@@ -161,56 +211,57 @@ static int vtbl_check(const struct ubi_device *ubi,
if (reserved_pebs < 0 || alignment < 0 || data_pad < 0 ||
name_len < 0) {
- dbg_err("negative values");
+ err = 3;
goto bad;
}
if (alignment > ubi->leb_size || alignment == 0) {
- dbg_err("bad alignment");
+ err = 4;
goto bad;
}
- n = alignment % ubi->min_io_size;
+ n = alignment & (ubi->min_io_size - 1);
if (alignment != 1 && n) {
- dbg_err("alignment is not multiple of min I/O unit");
+ err = 5;
goto bad;
}
n = ubi->leb_size % alignment;
if (data_pad != n) {
dbg_err("bad data_pad, has to be %d", n);
+ err = 6;
goto bad;
}
if (vol_type != UBI_VID_DYNAMIC && vol_type != UBI_VID_STATIC) {
- dbg_err("bad vol_type");
+ err = 7;
goto bad;
}
if (upd_marker != 0 && upd_marker != 1) {
- dbg_err("bad upd_marker");
+ err = 8;
goto bad;
}
if (reserved_pebs > ubi->good_peb_count) {
dbg_err("too large reserved_pebs, good PEBs %d",
ubi->good_peb_count);
+ err = 9;
goto bad;
}
if (name_len > UBI_VOL_NAME_MAX) {
- dbg_err("too long volume name, max %d",
- UBI_VOL_NAME_MAX);
+ err = 10;
goto bad;
}
if (name[0] == '\0') {
- dbg_err("NULL volume name");
+ err = 11;
goto bad;
}
if (name_len != strnlen(name, name_len + 1)) {
- dbg_err("bad name_len");
+ err = 12;
goto bad;
}
}
@@ -235,7 +286,7 @@ static int vtbl_check(const struct ubi_device *ubi,
return 0;
bad:
- ubi_err("volume table check failed, record %d", i);
+ ubi_err("volume table check failed: record %d, error %d", i, err);
ubi_dbg_dump_vtbl_record(&vtbl[i], i);
return -EINVAL;
}
@@ -287,7 +338,6 @@ retry:
vid_hdr->data_pad = cpu_to_be32(0);
vid_hdr->lnum = cpu_to_be32(copy);
vid_hdr->sqnum = cpu_to_be64(++si->max_sqnum);
- vid_hdr->leb_ver = cpu_to_be32(old_seb ? old_seb->leb_ver + 1: 0);
/* The EC header is already there, write the VID header */
err = ubi_io_write_vid_hdr(ubi, new_seb->pnum, vid_hdr);
@@ -370,7 +420,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
* to LEB 0.
*/
- dbg_msg("check layout volume");
+ dbg_gen("check layout volume");
/* Read both LEB 0 and LEB 1 into memory */
ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) {
@@ -384,7 +434,16 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0,
ubi->vtbl_size);
if (err == UBI_IO_BITFLIPS || err == -EBADMSG)
- /* Scrub the PEB later */
+ /*
+ * Scrub the PEB later. Note, -EBADMSG indicates an
+ * uncorrectable ECC error, but we have our own CRC and
+ * the data will be checked later. If the data is OK,
+ * the PEB will be scrubbed (because we set
+ * seb->scrub). If the data is not OK, the contents of
+ * the PEB will be recovered from the second copy, and
+ * seb->scrub will be cleared in
+ * 'ubi_scan_add_used()'.
+ */
seb->scrub = 1;
else if (err)
goto out_free;
@@ -400,7 +459,8 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
if (!leb_corrupted[0]) {
/* LEB 0 is OK */
if (leb[1])
- leb_corrupted[1] = memcmp(leb[0], leb[1], ubi->vtbl_size);
+ leb_corrupted[1] = memcmp(leb[0], leb[1],
+ ubi->vtbl_size);
if (leb_corrupted[1]) {
ubi_warn("volume table copy #2 is corrupted");
err = create_vtbl(ubi, si, 1, leb[0]);
@@ -620,30 +680,32 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
static int check_sv(const struct ubi_volume *vol,
const struct ubi_scan_volume *sv)
{
+ int err;
+
if (sv->highest_lnum >= vol->reserved_pebs) {
- dbg_err("bad highest_lnum");
+ err = 1;
goto bad;
}
if (sv->leb_count > vol->reserved_pebs) {
- dbg_err("bad leb_count");
+ err = 2;
goto bad;
}
if (sv->vol_type != vol->vol_type) {
- dbg_err("bad vol_type");
+ err = 3;
goto bad;
}
if (sv->used_ebs > vol->reserved_pebs) {
- dbg_err("bad used_ebs");
+ err = 4;
goto bad;
}
if (sv->data_pad != vol->data_pad) {
- dbg_err("bad data_pad");
+ err = 5;
goto bad;
}
return 0;
bad:
- ubi_err("bad scanning information");
+ ubi_err("bad scanning information, error %d", err);
ubi_dbg_dump_sv(sv);
ubi_dbg_dump_vol_info(vol);
return -EINVAL;
@@ -672,14 +734,13 @@ static int check_scanning_info(const struct ubi_device *ubi,
return -EINVAL;
}
- if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT&&
+ if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT &&
si->highest_vol_id < UBI_INTERNAL_VOL_START) {
ubi_err("too large volume ID %d found by scanning",
si->highest_vol_id);
return -EINVAL;
}
-
for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
cond_resched();
@@ -717,8 +778,7 @@ static int check_scanning_info(const struct ubi_device *ubi,
}
/**
- * ubi_read_volume_table - read volume table.
- * information.
+ * ubi_read_volume_table - read the volume table.
* @ubi: UBI device description object
* @si: scanning information
*
@@ -797,11 +857,10 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
out_free:
vfree(ubi->vtbl);
- for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++)
- if (ubi->volumes[i]) {
- kfree(ubi->volumes[i]);
- ubi->volumes[i] = NULL;
- }
+ for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
+ kfree(ubi->volumes[i]);
+ ubi->volumes[i] = NULL;
+ }
return err;
}
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index a471a491f0a..05d70937b54 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -19,22 +19,22 @@
*/
/*
- * UBI wear-leveling unit.
+ * UBI wear-leveling sub-system.
*
- * This unit is responsible for wear-leveling. It works in terms of physical
- * eraseblocks and erase counters and knows nothing about logical eraseblocks,
- * volumes, etc. From this unit's perspective all physical eraseblocks are of
- * two types - used and free. Used physical eraseblocks are those that were
- * "get" by the 'ubi_wl_get_peb()' function, and free physical eraseblocks are
- * those that were put by the 'ubi_wl_put_peb()' function.
+ * This sub-system is responsible for wear-leveling. It works in terms of
+ * physical* eraseblocks and erase counters and knows nothing about logical
+ * eraseblocks, volumes, etc. From this sub-system's perspective all physical
+ * eraseblocks are of two types - used and free. Used physical eraseblocks are
+ * those that were "get" by the 'ubi_wl_get_peb()' function, and free physical
+ * eraseblocks are those that were put by the 'ubi_wl_put_peb()' function.
*
* Physical eraseblocks returned by 'ubi_wl_get_peb()' have only erase counter
- * header. The rest of the physical eraseblock contains only 0xFF bytes.
+ * header. The rest of the physical eraseblock contains only %0xFF bytes.
*
- * When physical eraseblocks are returned to the WL unit by means of the
+ * When physical eraseblocks are returned to the WL sub-system by means of the
* 'ubi_wl_put_peb()' function, they are scheduled for erasure. The erasure is
* done asynchronously in context of the per-UBI device background thread,
- * which is also managed by the WL unit.
+ * which is also managed by the WL sub-system.
*
* The wear-leveling is ensured by means of moving the contents of used
* physical eraseblocks with low erase counter to free physical eraseblocks
@@ -43,34 +43,36 @@
* The 'ubi_wl_get_peb()' function accepts data type hints which help to pick
* an "optimal" physical eraseblock. For example, when it is known that the
* physical eraseblock will be "put" soon because it contains short-term data,
- * the WL unit may pick a free physical eraseblock with low erase counter, and
- * so forth.
+ * the WL sub-system may pick a free physical eraseblock with low erase
+ * counter, and so forth.
*
- * If the WL unit fails to erase a physical eraseblock, it marks it as bad.
+ * If the WL sub-system fails to erase a physical eraseblock, it marks it as
+ * bad.
*
- * This unit is also responsible for scrubbing. If a bit-flip is detected in a
- * physical eraseblock, it has to be moved. Technically this is the same as
- * moving it for wear-leveling reasons.
+ * This sub-system is also responsible for scrubbing. If a bit-flip is detected
+ * in a physical eraseblock, it has to be moved. Technically this is the same
+ * as moving it for wear-leveling reasons.
*
- * As it was said, for the UBI unit all physical eraseblocks are either "free"
- * or "used". Free eraseblock are kept in the @wl->free RB-tree, while used
- * eraseblocks are kept in a set of different RB-trees: @wl->used,
+ * As it was said, for the UBI sub-system all physical eraseblocks are either
+ * "free" or "used". Free eraseblock are kept in the @wl->free RB-tree, while
+ * used eraseblocks are kept in a set of different RB-trees: @wl->used,
* @wl->prot.pnum, @wl->prot.aec, and @wl->scrub.
*
* Note, in this implementation, we keep a small in-RAM object for each physical
* eraseblock. This is surely not a scalable solution. But it appears to be good
* enough for moderately large flashes and it is simple. In future, one may
- * re-work this unit and make it more scalable.
+ * re-work this sub-system and make it more scalable.
*
- * At the moment this unit does not utilize the sequence number, which was
- * introduced relatively recently. But it would be wise to do this because the
- * sequence number of a logical eraseblock characterizes how old is it. For
+ * At the moment this sub-system does not utilize the sequence number, which
+ * was introduced relatively recently. But it would be wise to do this because
+ * the sequence number of a logical eraseblock characterizes how old is it. For
* example, when we move a PEB with low erase counter, and we need to pick the
* target PEB, we pick a PEB with the highest EC if our PEB is "old" and we
* pick target PEB with an average EC if our PEB is not very "old". This is a
- * room for future re-works of the WL unit.
+ * room for future re-works of the WL sub-system.
*
- * FIXME: looks too complex, should be simplified (later).
+ * Note: the stuff with protection trees looks too complex and is difficult to
+ * understand. Should be fixed.
*/
#include <linux/slab.h>
@@ -92,20 +94,21 @@
/*
* Maximum difference between two erase counters. If this threshold is
- * exceeded, the WL unit starts moving data from used physical eraseblocks with
- * low erase counter to free physical eraseblocks with high erase counter.
+ * exceeded, the WL sub-system starts moving data from used physical
+ * eraseblocks with low erase counter to free physical eraseblocks with high
+ * erase counter.
*/
#define UBI_WL_THRESHOLD CONFIG_MTD_UBI_WL_THRESHOLD
/*
- * When a physical eraseblock is moved, the WL unit has to pick the target
+ * When a physical eraseblock is moved, the WL sub-system has to pick the target
* physical eraseblock to move to. The simplest way would be just to pick the
* one with the highest erase counter. But in certain workloads this could lead
* to an unlimited wear of one or few physical eraseblock. Indeed, imagine a
* situation when the picked physical eraseblock is constantly erased after the
* data is written to it. So, we have a constant which limits the highest erase
- * counter of the free physical eraseblock to pick. Namely, the WL unit does
- * not pick eraseblocks with erase counter greater then the lowest erase
+ * counter of the free physical eraseblock to pick. Namely, the WL sub-system
+ * does not pick eraseblocks with erase counter greater then the lowest erase
* counter plus %WL_FREE_MAX_DIFF.
*/
#define WL_FREE_MAX_DIFF (2*UBI_WL_THRESHOLD)
@@ -123,11 +126,11 @@
* @abs_ec: the absolute erase counter value when the protection ends
* @e: the wear-leveling entry of the physical eraseblock under protection
*
- * When the WL unit returns a physical eraseblock, the physical eraseblock is
- * protected from being moved for some "time". For this reason, the physical
- * eraseblock is not directly moved from the @wl->free tree to the @wl->used
- * tree. There is one more tree in between where this physical eraseblock is
- * temporarily stored (@wl->prot).
+ * When the WL sub-system returns a physical eraseblock, the physical
+ * eraseblock is protected from being moved for some "time". For this reason,
+ * the physical eraseblock is not directly moved from the @wl->free tree to the
+ * @wl->used tree. There is one more tree in between where this physical
+ * eraseblock is temporarily stored (@wl->prot).
*
* All this protection stuff is needed because:
* o we don't want to move physical eraseblocks just after we have given them
@@ -175,7 +178,6 @@ struct ubi_wl_prot_entry {
* @list: a link in the list of pending works
* @func: worker function
* @priv: private data of the worker function
- *
* @e: physical eraseblock to erase
* @torture: if the physical eraseblock has to be tortured
*
@@ -473,52 +475,47 @@ retry:
}
switch (dtype) {
- case UBI_LONGTERM:
- /*
- * For long term data we pick a physical eraseblock
- * with high erase counter. But the highest erase
- * counter we can pick is bounded by the the lowest
- * erase counter plus %WL_FREE_MAX_DIFF.
- */
- e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
- protect = LT_PROTECTION;
- break;
- case UBI_UNKNOWN:
- /*
- * For unknown data we pick a physical eraseblock with
- * medium erase counter. But we by no means can pick a
- * physical eraseblock with erase counter greater or
- * equivalent than the lowest erase counter plus
- * %WL_FREE_MAX_DIFF.
- */
- first = rb_entry(rb_first(&ubi->free),
- struct ubi_wl_entry, rb);
- last = rb_entry(rb_last(&ubi->free),
- struct ubi_wl_entry, rb);
+ case UBI_LONGTERM:
+ /*
+ * For long term data we pick a physical eraseblock with high
+ * erase counter. But the highest erase counter we can pick is
+ * bounded by the the lowest erase counter plus
+ * %WL_FREE_MAX_DIFF.
+ */
+ e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
+ protect = LT_PROTECTION;
+ break;
+ case UBI_UNKNOWN:
+ /*
+ * For unknown data we pick a physical eraseblock with medium
+ * erase counter. But we by no means can pick a physical
+ * eraseblock with erase counter greater or equivalent than the
+ * lowest erase counter plus %WL_FREE_MAX_DIFF.
+ */
+ first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, rb);
+ last = rb_entry(rb_last(&ubi->free), struct ubi_wl_entry, rb);
- if (last->ec - first->ec < WL_FREE_MAX_DIFF)
- e = rb_entry(ubi->free.rb_node,
- struct ubi_wl_entry, rb);
- else {
- medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2;
- e = find_wl_entry(&ubi->free, medium_ec);
- }
- protect = U_PROTECTION;
- break;
- case UBI_SHORTTERM:
- /*
- * For short term data we pick a physical eraseblock
- * with the lowest erase counter as we expect it will
- * be erased soon.
- */
- e = rb_entry(rb_first(&ubi->free),
- struct ubi_wl_entry, rb);
- protect = ST_PROTECTION;
- break;
- default:
- protect = 0;
- e = NULL;
- BUG();
+ if (last->ec - first->ec < WL_FREE_MAX_DIFF)
+ e = rb_entry(ubi->free.rb_node,
+ struct ubi_wl_entry, rb);
+ else {
+ medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2;
+ e = find_wl_entry(&ubi->free, medium_ec);
+ }
+ protect = U_PROTECTION;
+ break;
+ case UBI_SHORTTERM:
+ /*
+ * For short term data we pick a physical eraseblock with the
+ * lowest erase counter as we expect it will be erased soon.
+ */
+ e = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, rb);
+ protect = ST_PROTECTION;
+ break;
+ default:
+ protect = 0;
+ e = NULL;
+ BUG();
}
/*
@@ -582,7 +579,8 @@ found:
* This function returns zero in case of success and a negative error code in
* case of failure.
*/
-static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, int torture)
+static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
+ int torture)
{
int err;
struct ubi_ec_hdr *ec_hdr;
@@ -634,8 +632,7 @@ out_free:
}
/**
- * check_protection_over - check if it is time to stop protecting some
- * physical eraseblocks.
+ * check_protection_over - check if it is time to stop protecting some PEBs.
* @ubi: UBI device description object
*
* This function is called after each erase operation, when the absolute erase
@@ -871,6 +868,10 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
}
ubi_free_vid_hdr(ubi, vid_hdr);
+ if (scrubbing && !protect)
+ ubi_msg("scrubbed PEB %d, data moved to PEB %d",
+ e1->pnum, e2->pnum);
+
spin_lock(&ubi->wl_lock);
if (protect)
prot_tree_add(ubi, e1, pe, protect);
@@ -1054,8 +1055,8 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
spin_unlock(&ubi->wl_lock);
/*
- * One more erase operation has happened, take care about protected
- * physical eraseblocks.
+ * One more erase operation has happened, take care about
+ * protected physical eraseblocks.
*/
check_protection_over(ubi);
@@ -1136,7 +1137,7 @@ out_ro:
}
/**
- * ubi_wl_put_peb - return a physical eraseblock to the wear-leveling unit.
+ * ubi_wl_put_peb - return a PEB to the wear-leveling sub-system.
* @ubi: UBI device description object
* @pnum: physical eraseblock to return
* @torture: if this physical eraseblock has to be tortured
@@ -1175,11 +1176,11 @@ retry:
/*
* User is putting the physical eraseblock which was selected
* as the target the data is moved to. It may happen if the EBA
- * unit already re-mapped the LEB in 'ubi_eba_copy_leb()' but
- * the WL unit has not put the PEB to the "used" tree yet, but
- * it is about to do this. So we just set a flag which will
- * tell the WL worker that the PEB is not needed anymore and
- * should be scheduled for erasure.
+ * sub-system already re-mapped the LEB in 'ubi_eba_copy_leb()'
+ * but the WL sub-system has not put the PEB to the "used" tree
+ * yet, but it is about to do this. So we just set a flag which
+ * will tell the WL worker that the PEB is not needed anymore
+ * and should be scheduled for erasure.
*/
dbg_wl("PEB %d is the target of data moving", pnum);
ubi_assert(!ubi->move_to_put);
@@ -1229,7 +1230,7 @@ int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum)
{
struct ubi_wl_entry *e;
- ubi_msg("schedule PEB %d for scrubbing", pnum);
+ dbg_msg("schedule PEB %d for scrubbing", pnum);
retry:
spin_lock(&ubi->wl_lock);
@@ -1368,7 +1369,7 @@ int ubi_thread(void *u)
int err;
if (kthread_should_stop())
- goto out;
+ break;
if (try_to_freeze())
continue;
@@ -1403,7 +1404,6 @@ int ubi_thread(void *u)
cond_resched();
}
-out:
dbg_wl("background thread \"%s\" is killed", ubi->bgt_name);
return 0;
}
@@ -1426,8 +1426,7 @@ static void cancel_pending(struct ubi_device *ubi)
}
/**
- * ubi_wl_init_scan - initialize the wear-leveling unit using scanning
- * information.
+ * ubi_wl_init_scan - initialize the WL sub-system using scanning information.
* @ubi: UBI device description object
* @si: scanning information
*
@@ -1584,13 +1583,12 @@ static void protection_trees_destroy(struct ubi_device *ubi)
}
/**
- * ubi_wl_close - close the wear-leveling unit.
+ * ubi_wl_close - close the wear-leveling sub-system.
* @ubi: UBI device description object
*/
void ubi_wl_close(struct ubi_device *ubi)
{
- dbg_wl("close the UBI wear-leveling unit");
-
+ dbg_wl("close the WL sub-system");
cancel_pending(ubi);
protection_trees_destroy(ubi);
tree_destroy(&ubi->used);
@@ -1602,8 +1600,7 @@ void ubi_wl_close(struct ubi_device *ubi)
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
/**
- * paranoid_check_ec - make sure that the erase counter of a physical eraseblock
- * is correct.
+ * paranoid_check_ec - make sure that the erase counter of a PEB is correct.
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to check
* @ec: the erase counter to check
@@ -1644,13 +1641,12 @@ out_free:
}
/**
- * paranoid_check_in_wl_tree - make sure that a wear-leveling entry is present
- * in a WL RB-tree.
+ * paranoid_check_in_wl_tree - check that wear-leveling entry is in WL RB-tree.
* @e: the wear-leveling entry to check
* @root: the root of the tree
*
- * This function returns zero if @e is in the @root RB-tree and %1 if it
- * is not.
+ * This function returns zero if @e is in the @root RB-tree and %1 if it is
+ * not.
*/
static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
struct rb_root *root)
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index aabad8ce745..8db4e6b8948 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -1010,7 +1010,7 @@ static int __devinit vortex_probe1(struct device *gendev,
static int printed_version;
int retval, print_info;
struct vortex_chip_info * const vci = &vortex_info_tbl[chip_idx];
- char *print_name = "3c59x";
+ const char *print_name = "3c59x";
struct pci_dev *pdev = NULL;
struct eisa_device *edev = NULL;
DECLARE_MAC_BUF(mac);
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 75317a14ad1..8a5b0d293f7 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -98,7 +98,6 @@
#include <linux/compiler.h>
#include <linux/pci.h>
#include <linux/init.h>
-#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>
@@ -120,11 +119,6 @@
NETIF_MSG_LINK)
-/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */
-#ifdef CONFIG_8139TOO_PIO
-#define USE_IO_OPS 1
-#endif
-
/* define to 1, 2 or 3 to enable copious debugging info */
#define RTL8139_DEBUG 0
@@ -156,6 +150,13 @@
static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+/* Whether to use MMIO or PIO. Default to MMIO. */
+#ifdef CONFIG_8139TOO_PIO
+static int use_io = 1;
+#else
+static int use_io = 0;
+#endif
+
/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
The RTL chips use a 64 element hash table based on the Ethernet CRC. */
static int multicast_filter_limit = 32;
@@ -614,6 +615,8 @@ MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
+module_param(use_io, int, 0);
+MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO");
module_param(multicast_filter_limit, int, 0);
module_param_array(media, int, NULL, 0);
module_param_array(full_duplex, int, NULL, 0);
@@ -709,13 +712,8 @@ static void __rtl8139_cleanup_dev (struct net_device *dev)
assert (tp->pci_dev != NULL);
pdev = tp->pci_dev;
-#ifdef USE_IO_OPS
- if (tp->mmio_addr)
- ioport_unmap (tp->mmio_addr);
-#else
if (tp->mmio_addr)
pci_iounmap (pdev, tp->mmio_addr);
-#endif /* USE_IO_OPS */
/* it's ok to call this even if we have no regions to free */
pci_release_regions (pdev);
@@ -790,32 +788,33 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
DPRINTK("PIO region size == 0x%02X\n", pio_len);
DPRINTK("MMIO region size == 0x%02lX\n", mmio_len);
-#ifdef USE_IO_OPS
- /* make sure PCI base addr 0 is PIO */
- if (!(pio_flags & IORESOURCE_IO)) {
- dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n");
- rc = -ENODEV;
- goto err_out;
- }
- /* check for weird/broken PCI region reporting */
- if (pio_len < RTL_MIN_IO_SIZE) {
- dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n");
- rc = -ENODEV;
- goto err_out;
- }
-#else
- /* make sure PCI base addr 1 is MMIO */
- if (!(mmio_flags & IORESOURCE_MEM)) {
- dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n");
- rc = -ENODEV;
- goto err_out;
- }
- if (mmio_len < RTL_MIN_IO_SIZE) {
- dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n");
- rc = -ENODEV;
- goto err_out;
+retry:
+ if (use_io) {
+ /* make sure PCI base addr 0 is PIO */
+ if (!(pio_flags & IORESOURCE_IO)) {
+ dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n");
+ rc = -ENODEV;
+ goto err_out;
+ }
+ /* check for weird/broken PCI region reporting */
+ if (pio_len < RTL_MIN_IO_SIZE) {
+ dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n");
+ rc = -ENODEV;
+ goto err_out;
+ }
+ } else {
+ /* make sure PCI base addr 1 is MMIO */
+ if (!(mmio_flags & IORESOURCE_MEM)) {
+ dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n");
+ rc = -ENODEV;
+ goto err_out;
+ }
+ if (mmio_len < RTL_MIN_IO_SIZE) {
+ dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n");
+ rc = -ENODEV;
+ goto err_out;
+ }
}
-#endif
rc = pci_request_regions (pdev, DRV_NAME);
if (rc)
@@ -825,28 +824,28 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
/* enable PCI bus-mastering */
pci_set_master (pdev);
-#ifdef USE_IO_OPS
- ioaddr = ioport_map(pio_start, pio_len);
- if (!ioaddr) {
- dev_err(&pdev->dev, "cannot map PIO, aborting\n");
- rc = -EIO;
- goto err_out;
- }
- dev->base_addr = pio_start;
- tp->mmio_addr = ioaddr;
- tp->regs_len = pio_len;
-#else
- /* ioremap MMIO region */
- ioaddr = pci_iomap(pdev, 1, 0);
- if (ioaddr == NULL) {
- dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
- rc = -EIO;
- goto err_out;
+ if (use_io) {
+ ioaddr = pci_iomap(pdev, 0, 0);
+ if (!ioaddr) {
+ dev_err(&pdev->dev, "cannot map PIO, aborting\n");
+ rc = -EIO;
+ goto err_out;
+ }
+ dev->base_addr = pio_start;
+ tp->regs_len = pio_len;
+ } else {
+ /* ioremap MMIO region */
+ ioaddr = pci_iomap(pdev, 1, 0);
+ if (ioaddr == NULL) {
+ dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n");
+ pci_release_regions(pdev);
+ use_io = 1;
+ goto retry;
+ }
+ dev->base_addr = (long) ioaddr;
+ tp->regs_len = mmio_len;
}
- dev->base_addr = (long) ioaddr;
tp->mmio_addr = ioaddr;
- tp->regs_len = mmio_len;
-#endif /* USE_IO_OPS */
/* Bring old chips out of low-power mode. */
RTL_W8 (HltClk, 'R');
@@ -952,6 +951,14 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
"Use the \"8139cp\" driver for improved performance and stability.\n");
}
+ if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
+ pdev->device == PCI_DEVICE_ID_REALTEK_8139 &&
+ pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS &&
+ pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) {
+ printk(KERN_INFO "8139too: OQO Model 2 detected. Forcing PIO\n");
+ use_io = 1;
+ }
+
i = rtl8139_init_board (pdev, &dev);
if (i < 0)
return i;
@@ -2381,20 +2388,24 @@ static void rtl8139_set_msglevel(struct net_device *dev, u32 datum)
np->msg_enable = datum;
}
-/* TODO: we are too slack to do reg dumping for pio, for now */
-#ifdef CONFIG_8139TOO_PIO
-#define rtl8139_get_regs_len NULL
-#define rtl8139_get_regs NULL
-#else
static int rtl8139_get_regs_len(struct net_device *dev)
{
- struct rtl8139_private *np = netdev_priv(dev);
+ struct rtl8139_private *np;
+ /* TODO: we are too slack to do reg dumping for pio, for now */
+ if (use_io)
+ return 0;
+ np = netdev_priv(dev);
return np->regs_len;
}
static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf)
{
- struct rtl8139_private *np = netdev_priv(dev);
+ struct rtl8139_private *np;
+
+ /* TODO: we are too slack to do reg dumping for pio, for now */
+ if (use_io)
+ return;
+ np = netdev_priv(dev);
regs->version = RTL_REGS_VER;
@@ -2402,7 +2413,6 @@ static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs,
memcpy_fromio(regbuf, np->mmio_addr, regs->len);
spin_unlock_irq(&np->lock);
}
-#endif /* CONFIG_8139TOO_MMIO */
static int rtl8139_get_sset_count(struct net_device *dev, int sset)
{
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 3e5e64c33e1..fa533c27052 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1926,20 +1926,6 @@ config E1000
To compile this driver as a module, choose M here. The module
will be called e1000.
-config E1000_NAPI
- bool "Use Rx Polling (NAPI)"
- depends on E1000
- help
- NAPI is a new driver API designed to reduce CPU and interrupt load
- when the driver is receiving lots of packets from the card. It is
- still somewhat experimental and thus not yet enabled by default.
-
- If your estimated Rx load is 10kpps or more, or if the card will be
- deployed on potentially unfriendly networks (e.g. in a firewall),
- then say Y here.
-
- If in doubt, say N.
-
config E1000_DISABLE_PACKET_SPLIT
bool "Disable Packet Split for PCI express adapters"
depends on E1000
@@ -2304,6 +2290,17 @@ config ATL1
To compile this driver as a module, choose M here. The module
will be called atl1.
+config ATL1E
+ tristate "Atheros L1E Gigabit Ethernet support (EXPERIMENTAL)"
+ depends on PCI && EXPERIMENTAL
+ select CRC32
+ select MII
+ help
+ This driver supports the Atheros L1E gigabit ethernet adapter.
+
+ To compile this driver as a module, choose M here. The module
+ will be called atl1e.
+
endif # NETDEV_1000
#
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 4b17a9ab786..7629c901721 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_EHEA) += ehea/
obj-$(CONFIG_CAN) += can/
obj-$(CONFIG_BONDING) += bonding/
obj-$(CONFIG_ATL1) += atlx/
+obj-$(CONFIG_ATL1E) += atl1e/
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
obj-$(CONFIG_TEHUTI) += tehuti.o
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
index 1e39e78f177..ffae266e2d7 100644
--- a/drivers/net/arm/at91_ether.c
+++ b/drivers/net/arm/at91_ether.c
@@ -677,7 +677,7 @@ static void at91ether_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo
{
strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
- strlcpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info));
+ strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info));
}
static const struct ethtool_ops at91ether_ethtool_ops = {
@@ -820,7 +820,7 @@ static int at91ether_tx(struct sk_buff *skb, struct net_device *dev)
lp->skb = skb;
lp->skb_length = skb->len;
lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE);
- lp->stats.tx_bytes += skb->len;
+ dev->stats.tx_bytes += skb->len;
/* Set address of the data in the Transmit Address register */
at91_emac_write(AT91_EMAC_TAR, lp->skb_physaddr);
@@ -843,34 +843,33 @@ static int at91ether_tx(struct sk_buff *skb, struct net_device *dev)
*/
static struct net_device_stats *at91ether_stats(struct net_device *dev)
{
- struct at91_private *lp = netdev_priv(dev);
int ale, lenerr, seqe, lcol, ecol;
if (netif_running(dev)) {
- lp->stats.rx_packets += at91_emac_read(AT91_EMAC_OK); /* Good frames received */
+ dev->stats.rx_packets += at91_emac_read(AT91_EMAC_OK); /* Good frames received */
ale = at91_emac_read(AT91_EMAC_ALE);
- lp->stats.rx_frame_errors += ale; /* Alignment errors */
+ dev->stats.rx_frame_errors += ale; /* Alignment errors */
lenerr = at91_emac_read(AT91_EMAC_ELR) + at91_emac_read(AT91_EMAC_USF);
- lp->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */
+ dev->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */
seqe = at91_emac_read(AT91_EMAC_SEQE);
- lp->stats.rx_crc_errors += seqe; /* CRC error */
- lp->stats.rx_fifo_errors += at91_emac_read(AT91_EMAC_DRFC); /* Receive buffer not available */
- lp->stats.rx_errors += (ale + lenerr + seqe
+ dev->stats.rx_crc_errors += seqe; /* CRC error */
+ dev->stats.rx_fifo_errors += at91_emac_read(AT91_EMAC_DRFC); /* Receive buffer not available */
+ dev->stats.rx_errors += (ale + lenerr + seqe
+ at91_emac_read(AT91_EMAC_CDE) + at91_emac_read(AT91_EMAC_RJB));
- lp->stats.tx_packets += at91_emac_read(AT91_EMAC_FRA); /* Frames successfully transmitted */
- lp->stats.tx_fifo_errors += at91_emac_read(AT91_EMAC_TUE); /* Transmit FIFO underruns */
- lp->stats.tx_carrier_errors += at91_emac_read(AT91_EMAC_CSE); /* Carrier Sense errors */
- lp->stats.tx_heartbeat_errors += at91_emac_read(AT91_EMAC_SQEE);/* Heartbeat error */
+ dev->stats.tx_packets += at91_emac_read(AT91_EMAC_FRA); /* Frames successfully transmitted */
+ dev->stats.tx_fifo_errors += at91_emac_read(AT91_EMAC_TUE); /* Transmit FIFO underruns */
+ dev->stats.tx_carrier_errors += at91_emac_read(AT91_EMAC_CSE); /* Carrier Sense errors */
+ dev->stats.tx_heartbeat_errors += at91_emac_read(AT91_EMAC_SQEE);/* Heartbeat error */
lcol = at91_emac_read(AT91_EMAC_LCOL);
ecol = at91_emac_read(AT91_EMAC_ECOL);
- lp->stats.tx_window_errors += lcol; /* Late collisions */
- lp->stats.tx_aborted_errors += ecol; /* 16 collisions */
+ dev->stats.tx_window_errors += lcol; /* Late collisions */
+ dev->stats.tx_aborted_errors += ecol; /* 16 collisions */
- lp->stats.collisions += (at91_emac_read(AT91_EMAC_SCOL) + at91_emac_read(AT91_EMAC_MCOL) + lcol + ecol);
+ dev->stats.collisions += (at91_emac_read(AT91_EMAC_SCOL) + at91_emac_read(AT91_EMAC_MCOL) + lcol + ecol);
}
- return &lp->stats;
+ return &dev->stats;
}
/*
@@ -896,16 +895,16 @@ static void at91ether_rx(struct net_device *dev)
skb->protocol = eth_type_trans(skb, dev);
dev->last_rx = jiffies;
- lp->stats.rx_bytes += pktlen;
+ dev->stats.rx_bytes += pktlen;
netif_rx(skb);
}
else {
- lp->stats.rx_dropped += 1;
+ dev->stats.rx_dropped += 1;
printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
}
if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST)
- lp->stats.multicast++;
+ dev->stats.multicast++;
dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */
if (lp->rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */
@@ -934,7 +933,7 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
if (intstatus & AT91_EMAC_TCOM) { /* Transmit complete */
/* The TCOM bit is set even if the transmission failed. */
if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY))
- lp->stats.tx_errors += 1;
+ dev->stats.tx_errors += 1;
if (lp->skb) {
dev_kfree_skb_irq(lp->skb);
diff --git a/drivers/net/arm/at91_ether.h b/drivers/net/arm/at91_ether.h
index a38fd2d053a..353f4dab62b 100644
--- a/drivers/net/arm/at91_ether.h
+++ b/drivers/net/arm/at91_ether.h
@@ -84,7 +84,6 @@ struct recv_desc_bufs
struct at91_private
{
- struct net_device_stats stats;
struct mii_if_info mii; /* ethtool support */
struct at91_eth_data board_data; /* board-specific configuration */
struct clk *ether_clk; /* clock */
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index ecd8fc6146e..7a14980f347 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -848,7 +848,7 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
ep->res = request_mem_region(pdev->resource[0].start,
pdev->resource[0].end - pdev->resource[0].start + 1,
- pdev->dev.bus_id);
+ dev_name(&pdev->dev));
if (ep->res == NULL) {
dev_err(&pdev->dev, "Could not reserve memory region\n");
err = -ENOMEM;
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index e9d15eccad0..5c5f1e470d3 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -535,7 +535,7 @@ static int __init etherh_addr(char *addr, struct expansion_card *ec)
if (!ecard_readchunk(&cd, ec, 0xf5, 0)) {
printk(KERN_ERR "%s: unable to read podule description string\n",
- ec->dev.bus_id);
+ dev_name(&ec->dev));
goto no_addr;
}
@@ -554,7 +554,7 @@ static int __init etherh_addr(char *addr, struct expansion_card *ec)
}
printk(KERN_ERR "%s: unable to parse MAC address: %s\n",
- ec->dev.bus_id, cd.d.string);
+ dev_name(&ec->dev), cd.d.string);
no_addr:
return -ENODEV;
@@ -585,7 +585,7 @@ static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *i
{
strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
- strlcpy(info->bus_info, dev->dev.parent->bus_id,
+ strlcpy(info->bus_info, dev_name(dev->dev.parent),
sizeof(info->bus_info));
}
diff --git a/drivers/net/atl1e/Makefile b/drivers/net/atl1e/Makefile
new file mode 100644
index 00000000000..bc11be824e7
--- /dev/null
+++ b/drivers/net/atl1e/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ATL1E) += atl1e.o
+atl1e-objs += atl1e_main.o atl1e_hw.o atl1e_ethtool.o atl1e_param.o
diff --git a/drivers/net/atl1e/atl1e.h b/drivers/net/atl1e/atl1e.h
new file mode 100644
index 00000000000..b645fa0f3f6
--- /dev/null
+++ b/drivers/net/atl1e/atl1e.h
@@ -0,0 +1,503 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ * Copyright(c) 2007 xiong huang <xiong.huang@atheros.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _ATL1E_H_
+#define _ATL1E_H_
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/udp.h>
+#include <linux/mii.h>
+#include <linux/io.h>
+#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
+#include <linux/tcp.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/workqueue.h>
+#include <net/checksum.h>
+#include <net/ip6_checksum.h>
+
+#include "atl1e_hw.h"
+
+#define PCI_REG_COMMAND 0x04 /* PCI Command Register */
+#define CMD_IO_SPACE 0x0001
+#define CMD_MEMORY_SPACE 0x0002
+#define CMD_BUS_MASTER 0x0004
+
+#define BAR_0 0
+#define BAR_1 1
+#define BAR_5 5
+
+/* Wake Up Filter Control */
+#define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
+#define AT_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
+#define AT_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
+#define AT_WUFC_MC 0x00000008 /* Multicast Wakeup Enable */
+#define AT_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
+
+#define SPEED_0 0xffff
+#define HALF_DUPLEX 1
+#define FULL_DUPLEX 2
+
+/* Error Codes */
+#define AT_ERR_EEPROM 1
+#define AT_ERR_PHY 2
+#define AT_ERR_CONFIG 3
+#define AT_ERR_PARAM 4
+#define AT_ERR_MAC_TYPE 5
+#define AT_ERR_PHY_TYPE 6
+#define AT_ERR_PHY_SPEED 7
+#define AT_ERR_PHY_RES 8
+#define AT_ERR_TIMEOUT 9
+
+#define MAX_JUMBO_FRAME_SIZE 0x2000
+
+#define AT_VLAN_TAG_TO_TPD_TAG(_vlan, _tpd) \
+ _tpd = (((_vlan) << (4)) | (((_vlan) >> 13) & 7) |\
+ (((_vlan) >> 9) & 8))
+
+#define AT_TPD_TAG_TO_VLAN_TAG(_tpd, _vlan) \
+ _vlan = (((_tpd) >> 8) | (((_tpd) & 0x77) << 9) |\
+ (((_tdp) & 0x88) << 5))
+
+#define AT_MAX_RECEIVE_QUEUE 4
+#define AT_PAGE_NUM_PER_QUEUE 2
+
+#define AT_DMA_HI_ADDR_MASK 0xffffffff00000000ULL
+#define AT_DMA_LO_ADDR_MASK 0x00000000ffffffffULL
+
+#define AT_TX_WATCHDOG (5 * HZ)
+#define AT_MAX_INT_WORK 10
+#define AT_TWSI_EEPROM_TIMEOUT 100
+#define AT_HW_MAX_IDLE_DELAY 10
+#define AT_SUSPEND_LINK_TIMEOUT 28
+
+#define AT_REGS_LEN 75
+#define AT_EEPROM_LEN 512
+#define AT_ADV_MASK (ADVERTISE_10_HALF |\
+ ADVERTISE_10_FULL |\
+ ADVERTISE_100_HALF |\
+ ADVERTISE_100_FULL |\
+ ADVERTISE_1000_FULL)
+
+/* tpd word 2 */
+#define TPD_BUFLEN_MASK 0x3FFF
+#define TPD_BUFLEN_SHIFT 0
+#define TPD_DMAINT_MASK 0x0001
+#define TPD_DMAINT_SHIFT 14
+#define TPD_PKTNT_MASK 0x0001
+#define TPD_PKTINT_SHIFT 15
+#define TPD_VLANTAG_MASK 0xFFFF
+#define TPD_VLAN_SHIFT 16
+
+/* tpd word 3 bits 0:4 */
+#define TPD_EOP_MASK 0x0001
+#define TPD_EOP_SHIFT 0
+#define TPD_IP_VERSION_MASK 0x0001
+#define TPD_IP_VERSION_SHIFT 1 /* 0 : IPV4, 1 : IPV6 */
+#define TPD_INS_VL_TAG_MASK 0x0001
+#define TPD_INS_VL_TAG_SHIFT 2
+#define TPD_CC_SEGMENT_EN_MASK 0x0001
+#define TPD_CC_SEGMENT_EN_SHIFT 3
+#define TPD_SEGMENT_EN_MASK 0x0001
+#define TPD_SEGMENT_EN_SHIFT 4
+
+/* tdp word 3 bits 5:7 if ip version is 0 */
+#define TPD_IP_CSUM_MASK 0x0001
+#define TPD_IP_CSUM_SHIFT 5
+#define TPD_TCP_CSUM_MASK 0x0001
+#define TPD_TCP_CSUM_SHIFT 6
+#define TPD_UDP_CSUM_MASK 0x0001
+#define TPD_UDP_CSUM_SHIFT 7
+
+/* tdp word 3 bits 5:7 if ip version is 1 */
+#define TPD_V6_IPHLLO_MASK 0x0007
+#define TPD_V6_IPHLLO_SHIFT 7
+
+/* tpd word 3 bits 8:9 bit */
+#define TPD_VL_TAGGED_MASK 0x0001
+#define TPD_VL_TAGGED_SHIFT 8
+#define TPD_ETHTYPE_MASK 0x0001
+#define TPD_ETHTYPE_SHIFT 9
+
+/* tdp word 3 bits 10:13 if ip version is 0 */
+#define TDP_V4_IPHL_MASK 0x000F
+#define TPD_V4_IPHL_SHIFT 10
+
+/* tdp word 3 bits 10:13 if ip version is 1 */
+#define TPD_V6_IPHLHI_MASK 0x000F
+#define TPD_V6_IPHLHI_SHIFT 10
+
+/* tpd word 3 bit 14:31 if segment enabled */
+#define TPD_TCPHDRLEN_MASK 0x000F
+#define TPD_TCPHDRLEN_SHIFT 14
+#define TPD_HDRFLAG_MASK 0x0001
+#define TPD_HDRFLAG_SHIFT 18
+#define TPD_MSS_MASK 0x1FFF
+#define TPD_MSS_SHIFT 19
+
+/* tdp word 3 bit 16:31 if custom csum enabled */
+#define TPD_PLOADOFFSET_MASK 0x00FF
+#define TPD_PLOADOFFSET_SHIFT 16
+#define TPD_CCSUMOFFSET_MASK 0x00FF
+#define TPD_CCSUMOFFSET_SHIFT 24
+
+struct atl1e_tpd_desc {
+ __le64 buffer_addr;
+ __le32 word2;
+ __le32 word3;
+};
+
+/* how about 0x2000 */
+#define MAX_TX_BUF_LEN 0x2000
+#define MAX_TX_BUF_SHIFT 13
+/*#define MAX_TX_BUF_LEN 0x3000 */
+
+/* rrs word 1 bit 0:31 */
+#define RRS_RX_CSUM_MASK 0xFFFF
+#define RRS_RX_CSUM_SHIFT 0
+#define RRS_PKT_SIZE_MASK 0x3FFF
+#define RRS_PKT_SIZE_SHIFT 16
+#define RRS_CPU_NUM_MASK 0x0003
+#define RRS_CPU_NUM_SHIFT 30
+
+#define RRS_IS_RSS_IPV4 0x0001
+#define RRS_IS_RSS_IPV4_TCP 0x0002
+#define RRS_IS_RSS_IPV6 0x0004
+#define RRS_IS_RSS_IPV6_TCP 0x0008
+#define RRS_IS_IPV6 0x0010
+#define RRS_IS_IP_FRAG 0x0020
+#define RRS_IS_IP_DF 0x0040
+#define RRS_IS_802_3 0x0080
+#define RRS_IS_VLAN_TAG 0x0100
+#define RRS_IS_ERR_FRAME 0x0200
+#define RRS_IS_IPV4 0x0400
+#define RRS_IS_UDP 0x0800
+#define RRS_IS_TCP 0x1000
+#define RRS_IS_BCAST 0x2000
+#define RRS_IS_MCAST 0x4000
+#define RRS_IS_PAUSE 0x8000
+
+#define RRS_ERR_BAD_CRC 0x0001
+#define RRS_ERR_CODE 0x0002
+#define RRS_ERR_DRIBBLE 0x0004
+#define RRS_ERR_RUNT 0x0008
+#define RRS_ERR_RX_OVERFLOW 0x0010
+#define RRS_ERR_TRUNC 0x0020
+#define RRS_ERR_IP_CSUM 0x0040
+#define RRS_ERR_L4_CSUM 0x0080
+#define RRS_ERR_LENGTH 0x0100
+#define RRS_ERR_DES_ADDR 0x0200
+
+struct atl1e_recv_ret_status {
+ u16 seq_num;
+ u16 hash_lo;
+ __le32 word1;
+ u16 pkt_flag;
+ u16 err_flag;
+ u16 hash_hi;
+ u16 vtag;
+};
+
+enum atl1e_dma_req_block {
+ atl1e_dma_req_128 = 0,
+ atl1e_dma_req_256 = 1,
+ atl1e_dma_req_512 = 2,
+ atl1e_dma_req_1024 = 3,
+ atl1e_dma_req_2048 = 4,
+ atl1e_dma_req_4096 = 5
+};
+
+enum atl1e_rrs_type {
+ atl1e_rrs_disable = 0,
+ atl1e_rrs_ipv4 = 1,
+ atl1e_rrs_ipv4_tcp = 2,
+ atl1e_rrs_ipv6 = 4,
+ atl1e_rrs_ipv6_tcp = 8
+};
+
+enum atl1e_nic_type {
+ athr_l1e = 0,
+ athr_l2e_revA = 1,
+ athr_l2e_revB = 2
+};
+
+struct atl1e_hw_stats {
+ /* rx */
+ unsigned long rx_ok; /* The number of good packet received. */
+ unsigned long rx_bcast; /* The number of good broadcast packet received. */
+ unsigned long rx_mcast; /* The number of good multicast packet received. */
+ unsigned long rx_pause; /* The number of Pause packet received. */
+ unsigned long rx_ctrl; /* The number of Control packet received other than Pause frame. */
+ unsigned long rx_fcs_err; /* The number of packets with bad FCS. */
+ unsigned long rx_len_err; /* The number of packets with mismatch of length field and actual size. */
+ unsigned long rx_byte_cnt; /* The number of bytes of good packet received. FCS is NOT included. */
+ unsigned long rx_runt; /* The number of packets received that are less than 64 byte long and with good FCS. */
+ unsigned long rx_frag; /* The number of packets received that are less than 64 byte long and with bad FCS. */
+ unsigned long rx_sz_64; /* The number of good and bad packets received that are 64 byte long. */
+ unsigned long rx_sz_65_127; /* The number of good and bad packets received that are between 65 and 127-byte long. */
+ unsigned long rx_sz_128_255; /* The number of good and bad packets received that are between 128 and 255-byte long. */
+ unsigned long rx_sz_256_511; /* The number of good and bad packets received that are between 256 and 511-byte long. */
+ unsigned long rx_sz_512_1023; /* The number of good and bad packets received that are between 512 and 1023-byte long. */
+ unsigned long rx_sz_1024_1518; /* The number of good and bad packets received that are between 1024 and 1518-byte long. */
+ unsigned long rx_sz_1519_max; /* The number of good and bad packets received that are between 1519-byte and MTU. */
+ unsigned long rx_sz_ov; /* The number of good and bad packets received that are more than MTU size truncated by Selene. */
+ unsigned long rx_rxf_ov; /* The number of frame dropped due to occurrence of RX FIFO overflow. */
+ unsigned long rx_rrd_ov; /* The number of frame dropped due to occurrence of RRD overflow. */
+ unsigned long rx_align_err; /* Alignment Error */
+ unsigned long rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */
+ unsigned long rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */
+ unsigned long rx_err_addr; /* The number of packets dropped due to address filtering. */
+
+ /* tx */
+ unsigned long tx_ok; /* The number of good packet transmitted. */
+ unsigned long tx_bcast; /* The number of good broadcast packet transmitted. */
+ unsigned long tx_mcast; /* The number of good multicast packet transmitted. */
+ unsigned long tx_pause; /* The number of Pause packet transmitted. */
+ unsigned long tx_exc_defer; /* The number of packets transmitted with excessive deferral. */
+ unsigned long tx_ctrl; /* The number of packets transmitted is a control frame, excluding Pause frame. */
+ unsigned long tx_defer; /* The number of packets transmitted that is deferred. */
+ unsigned long tx_byte_cnt; /* The number of bytes of data transmitted. FCS is NOT included. */
+ unsigned long tx_sz_64; /* The number of good and bad packets transmitted that are 64 byte long. */
+ unsigned long tx_sz_65_127; /* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
+ unsigned long tx_sz_128_255; /* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
+ unsigned long tx_sz_256_511; /* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
+ unsigned long tx_sz_512_1023; /* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
+ unsigned long tx_sz_1024_1518; /* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
+ unsigned long tx_sz_1519_max; /* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
+ unsigned long tx_1_col; /* The number of packets subsequently transmitted successfully with a single prior collision. */
+ unsigned long tx_2_col; /* The number of packets subsequently transmitted successfully with multiple prior collisions. */
+ unsigned long tx_late_col; /* The number of packets transmitted with late collisions. */
+ unsigned long tx_abort_col; /* The number of transmit packets aborted due to excessive collisions. */
+ unsigned long tx_underrun; /* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
+ unsigned long tx_rd_eop; /* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
+ unsigned long tx_len_err; /* The number of transmit packets with length field does NOT match the actual frame size. */
+ unsigned long tx_trunc; /* The number of transmit packets truncated due to size exceeding MTU. */
+ unsigned long tx_bcast_byte; /* The byte count of broadcast packet transmitted, excluding FCS. */
+ unsigned long tx_mcast_byte; /* The byte count of multicast packet transmitted, excluding FCS. */
+};
+
+struct atl1e_hw {
+ u8 __iomem *hw_addr; /* inner register address */
+ resource_size_t mem_rang;
+ struct atl1e_adapter *adapter;
+ enum atl1e_nic_type nic_type;
+ u16 device_id;
+ u16 vendor_id;
+ u16 subsystem_id;
+ u16 subsystem_vendor_id;
+ u8 revision_id;
+ u16 pci_cmd_word;
+ u8 mac_addr[ETH_ALEN];
+ u8 perm_mac_addr[ETH_ALEN];
+ u8 preamble_len;
+ u16 max_frame_size;
+ u16 rx_jumbo_th;
+ u16 tx_jumbo_th;
+
+ u16 media_type;
+#define MEDIA_TYPE_AUTO_SENSOR 0
+#define MEDIA_TYPE_100M_FULL 1
+#define MEDIA_TYPE_100M_HALF 2
+#define MEDIA_TYPE_10M_FULL 3
+#define MEDIA_TYPE_10M_HALF 4
+
+ u16 autoneg_advertised;
+#define ADVERTISE_10_HALF 0x0001
+#define ADVERTISE_10_FULL 0x0002
+#define ADVERTISE_100_HALF 0x0004
+#define ADVERTISE_100_FULL 0x0008
+#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */
+#define ADVERTISE_1000_FULL 0x0020
+ u16 mii_autoneg_adv_reg;
+ u16 mii_1000t_ctrl_reg;
+
+ u16 imt; /* Interrupt Moderator timer ( 2us resolution) */
+ u16 ict; /* Interrupt Clear timer (2us resolution) */
+ u32 smb_timer;
+ u16 rrd_thresh; /* Threshold of number of RRD produced to trigger
+ interrupt request */
+ u16 tpd_thresh;
+ u16 rx_count_down; /* 2us resolution */
+ u16 tx_count_down;
+
+ u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. */
+ enum atl1e_rrs_type rrs_type;
+ u32 base_cpu;
+ u32 indirect_tab;
+
+ enum atl1e_dma_req_block dmar_block;
+ enum atl1e_dma_req_block dmaw_block;
+ u8 dmaw_dly_cnt;
+ u8 dmar_dly_cnt;
+
+ bool phy_configured;
+ bool re_autoneg;
+ bool emi_ca;
+};
+
+/*
+ * wrapper around a pointer to a socket buffer,
+ * so a DMA handle can be stored along with the buffer
+ */
+struct atl1e_tx_buffer {
+ struct sk_buff *skb;
+ u16 length;
+ dma_addr_t dma;
+};
+
+struct atl1e_rx_page {
+ dma_addr_t dma; /* receive rage DMA address */
+ u8 *addr; /* receive rage virtual address */
+ dma_addr_t write_offset_dma; /* the DMA address which contain the
+ receive data offset in the page */
+ u32 *write_offset_addr; /* the virtaul address which contain
+ the receive data offset in the page */
+ u32 read_offset; /* the offset where we have read */
+};
+
+struct atl1e_rx_page_desc {
+ struct atl1e_rx_page rx_page[AT_PAGE_NUM_PER_QUEUE];
+ u8 rx_using;
+ u16 rx_nxseq;
+};
+
+/* transmit packet descriptor (tpd) ring */
+struct atl1e_tx_ring {
+ struct atl1e_tpd_desc *desc; /* descriptor ring virtual address */
+ dma_addr_t dma; /* descriptor ring physical address */
+ u16 count; /* the count of transmit rings */
+ rwlock_t tx_lock;
+ u16 next_to_use;
+ atomic_t next_to_clean;
+ struct atl1e_tx_buffer *tx_buffer;
+ dma_addr_t cmb_dma;
+ u32 *cmb;
+};
+
+/* receive packet descriptor ring */
+struct atl1e_rx_ring {
+ void *desc;
+ dma_addr_t dma;
+ int size;
+ u32 page_size; /* bytes length of rxf page */
+ u32 real_page_size; /* real_page_size = page_size + jumbo + aliagn */
+ struct atl1e_rx_page_desc rx_page_desc[AT_MAX_RECEIVE_QUEUE];
+};
+
+/* board specific private data structure */
+struct atl1e_adapter {
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+ struct vlan_group *vlgrp;
+ struct napi_struct napi;
+ struct mii_if_info mii; /* MII interface info */
+ struct atl1e_hw hw;
+ struct atl1e_hw_stats hw_stats;
+ struct net_device_stats net_stats;
+
+ bool have_msi;
+ u32 wol;
+ u16 link_speed;
+ u16 link_duplex;
+
+ spinlock_t mdio_lock;
+ spinlock_t tx_lock;
+ atomic_t irq_sem;
+
+ struct work_struct reset_task;
+ struct work_struct link_chg_task;
+ struct timer_list watchdog_timer;
+ struct timer_list phy_config_timer;
+
+ /* All Descriptor memory */
+ dma_addr_t ring_dma;
+ void *ring_vir_addr;
+ int ring_size;
+
+ struct atl1e_tx_ring tx_ring;
+ struct atl1e_rx_ring rx_ring;
+ int num_rx_queues;
+ unsigned long flags;
+#define __AT_TESTING 0x0001
+#define __AT_RESETTING 0x0002
+#define __AT_DOWN 0x0003
+
+ u32 bd_number; /* board number;*/
+ u32 pci_state[16];
+ u32 *config_space;
+};
+
+#define AT_WRITE_REG(a, reg, value) ( \
+ writel((value), ((a)->hw_addr + reg)))
+
+#define AT_WRITE_FLUSH(a) (\
+ readl((a)->hw_addr))
+
+#define AT_READ_REG(a, reg) ( \
+ readl((a)->hw_addr + reg))
+
+#define AT_WRITE_REGB(a, reg, value) (\
+ writeb((value), ((a)->hw_addr + reg)))
+
+#define AT_READ_REGB(a, reg) (\
+ readb((a)->hw_addr + reg))
+
+#define AT_WRITE_REGW(a, reg, value) (\
+ writew((value), ((a)->hw_addr + reg)))
+
+#define AT_READ_REGW(a, reg) (\
+ readw((a)->hw_addr + reg))
+
+#define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \
+ writel((value), (((a)->hw_addr + reg) + ((offset) << 2))))
+
+#define AT_READ_REG_ARRAY(a, reg, offset) ( \
+ readl(((a)->hw_addr + reg) + ((offset) << 2)))
+
+extern char atl1e_driver_name[];
+extern char atl1e_driver_version[];
+
+extern void atl1e_check_options(struct atl1e_adapter *adapter);
+extern int atl1e_up(struct atl1e_adapter *adapter);
+extern void atl1e_down(struct atl1e_adapter *adapter);
+extern void atl1e_reinit_locked(struct atl1e_adapter *adapter);
+extern s32 atl1e_reset_hw(struct atl1e_hw *hw);
+extern void atl1e_set_ethtool_ops(struct net_device *netdev);
+#endif /* _ATL1_E_H_ */
diff --git a/drivers/net/atl1e/atl1e_ethtool.c b/drivers/net/atl1e/atl1e_ethtool.c
new file mode 100644
index 00000000000..cdc3b85b10b
--- /dev/null
+++ b/drivers/net/atl1e/atl1e_ethtool.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+
+#include "atl1e.h"
+
+static int atl1e_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw *hw = &adapter->hw;
+
+ ecmd->supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_Autoneg |
+ SUPPORTED_TP);
+ if (hw->nic_type == athr_l1e)
+ ecmd->supported |= SUPPORTED_1000baseT_Full;
+
+ ecmd->advertising = ADVERTISED_TP;
+
+ ecmd->advertising |= ADVERTISED_Autoneg;
+ ecmd->advertising |= hw->autoneg_advertised;
+
+ ecmd->port = PORT_TP;
+ ecmd->phy_address = 0;
+ ecmd->transceiver = XCVR_INTERNAL;
+
+ if (adapter->link_speed != SPEED_0) {
+ ecmd->speed = adapter->link_speed;
+ if (adapter->link_duplex == FULL_DUPLEX)
+ ecmd->duplex = DUPLEX_FULL;
+ else
+ ecmd->duplex = DUPLEX_HALF;
+ } else {
+ ecmd->speed = -1;
+ ecmd->duplex = -1;
+ }
+
+ ecmd->autoneg = AUTONEG_ENABLE;
+ return 0;
+}
+
+static int atl1e_set_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw *hw = &adapter->hw;
+
+ while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+ msleep(1);
+
+ if (ecmd->autoneg == AUTONEG_ENABLE) {
+ u16 adv4, adv9;
+
+ if ((ecmd->advertising&ADVERTISE_1000_FULL)) {
+ if (hw->nic_type == athr_l1e) {
+ hw->autoneg_advertised =
+ ecmd->advertising & AT_ADV_MASK;
+ } else {
+ clear_bit(__AT_RESETTING, &adapter->flags);
+ return -EINVAL;
+ }
+ } else if (ecmd->advertising&ADVERTISE_1000_HALF) {
+ clear_bit(__AT_RESETTING, &adapter->flags);
+ return -EINVAL;
+ } else {
+ hw->autoneg_advertised =
+ ecmd->advertising & AT_ADV_MASK;
+ }
+ ecmd->advertising = hw->autoneg_advertised |
+ ADVERTISED_TP | ADVERTISED_Autoneg;
+
+ adv4 = hw->mii_autoneg_adv_reg & ~MII_AR_SPEED_MASK;
+ adv9 = hw->mii_1000t_ctrl_reg & ~MII_AT001_CR_1000T_SPEED_MASK;
+ if (hw->autoneg_advertised & ADVERTISE_10_HALF)
+ adv4 |= MII_AR_10T_HD_CAPS;
+ if (hw->autoneg_advertised & ADVERTISE_10_FULL)
+ adv4 |= MII_AR_10T_FD_CAPS;
+ if (hw->autoneg_advertised & ADVERTISE_100_HALF)
+ adv4 |= MII_AR_100TX_HD_CAPS;
+ if (hw->autoneg_advertised & ADVERTISE_100_FULL)
+ adv4 |= MII_AR_100TX_FD_CAPS;
+ if (hw->autoneg_advertised & ADVERTISE_1000_FULL)
+ adv9 |= MII_AT001_CR_1000T_FD_CAPS;
+
+ if (adv4 != hw->mii_autoneg_adv_reg ||
+ adv9 != hw->mii_1000t_ctrl_reg) {
+ hw->mii_autoneg_adv_reg = adv4;
+ hw->mii_1000t_ctrl_reg = adv9;
+ hw->re_autoneg = true;
+ }
+
+ } else {
+ clear_bit(__AT_RESETTING, &adapter->flags);
+ return -EINVAL;
+ }
+
+ /* reset the link */
+
+ if (netif_running(adapter->netdev)) {
+ atl1e_down(adapter);
+ atl1e_up(adapter);
+ } else
+ atl1e_reset_hw(&adapter->hw);
+
+ clear_bit(__AT_RESETTING, &adapter->flags);
+ return 0;
+}
+
+static u32 atl1e_get_tx_csum(struct net_device *netdev)
+{
+ return (netdev->features & NETIF_F_HW_CSUM) != 0;
+}
+
+static u32 atl1e_get_msglevel(struct net_device *netdev)
+{
+#ifdef DBG
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+static void atl1e_set_msglevel(struct net_device *netdev, u32 data)
+{
+}
+
+static int atl1e_get_regs_len(struct net_device *netdev)
+{
+ return AT_REGS_LEN * sizeof(u32);
+}
+
+static void atl1e_get_regs(struct net_device *netdev,
+ struct ethtool_regs *regs, void *p)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw *hw = &adapter->hw;
+ u32 *regs_buff = p;
+ u16 phy_data;
+
+ memset(p, 0, AT_REGS_LEN * sizeof(u32));
+
+ regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
+
+ regs_buff[0] = AT_READ_REG(hw, REG_VPD_CAP);
+ regs_buff[1] = AT_READ_REG(hw, REG_SPI_FLASH_CTRL);
+ regs_buff[2] = AT_READ_REG(hw, REG_SPI_FLASH_CONFIG);
+ regs_buff[3] = AT_READ_REG(hw, REG_TWSI_CTRL);
+ regs_buff[4] = AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL);
+ regs_buff[5] = AT_READ_REG(hw, REG_MASTER_CTRL);
+ regs_buff[6] = AT_READ_REG(hw, REG_MANUAL_TIMER_INIT);
+ regs_buff[7] = AT_READ_REG(hw, REG_IRQ_MODU_TIMER_INIT);
+ regs_buff[8] = AT_READ_REG(hw, REG_GPHY_CTRL);
+ regs_buff[9] = AT_READ_REG(hw, REG_CMBDISDMA_TIMER);
+ regs_buff[10] = AT_READ_REG(hw, REG_IDLE_STATUS);
+ regs_buff[11] = AT_READ_REG(hw, REG_MDIO_CTRL);
+ regs_buff[12] = AT_READ_REG(hw, REG_SERDES_LOCK);
+ regs_buff[13] = AT_READ_REG(hw, REG_MAC_CTRL);
+ regs_buff[14] = AT_READ_REG(hw, REG_MAC_IPG_IFG);
+ regs_buff[15] = AT_READ_REG(hw, REG_MAC_STA_ADDR);
+ regs_buff[16] = AT_READ_REG(hw, REG_MAC_STA_ADDR+4);
+ regs_buff[17] = AT_READ_REG(hw, REG_RX_HASH_TABLE);
+ regs_buff[18] = AT_READ_REG(hw, REG_RX_HASH_TABLE+4);
+ regs_buff[19] = AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL);
+ regs_buff[20] = AT_READ_REG(hw, REG_MTU);
+ regs_buff[21] = AT_READ_REG(hw, REG_WOL_CTRL);
+ regs_buff[22] = AT_READ_REG(hw, REG_SRAM_TRD_ADDR);
+ regs_buff[23] = AT_READ_REG(hw, REG_SRAM_TRD_LEN);
+ regs_buff[24] = AT_READ_REG(hw, REG_SRAM_RXF_ADDR);
+ regs_buff[25] = AT_READ_REG(hw, REG_SRAM_RXF_LEN);
+ regs_buff[26] = AT_READ_REG(hw, REG_SRAM_TXF_ADDR);
+ regs_buff[27] = AT_READ_REG(hw, REG_SRAM_TXF_LEN);
+ regs_buff[28] = AT_READ_REG(hw, REG_SRAM_TCPH_ADDR);
+ regs_buff[29] = AT_READ_REG(hw, REG_SRAM_PKTH_ADDR);
+
+ atl1e_read_phy_reg(hw, MII_BMCR, &phy_data);
+ regs_buff[73] = (u32)phy_data;
+ atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
+ regs_buff[74] = (u32)phy_data;
+}
+
+static int atl1e_get_eeprom_len(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ if (!atl1e_check_eeprom_exist(&adapter->hw))
+ return AT_EEPROM_LEN;
+ else
+ return 0;
+}
+
+static int atl1e_get_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw *hw = &adapter->hw;
+ u32 *eeprom_buff;
+ int first_dword, last_dword;
+ int ret_val = 0;
+ int i;
+
+ if (eeprom->len == 0)
+ return -EINVAL;
+
+ if (atl1e_check_eeprom_exist(hw)) /* not exist */
+ return -EINVAL;
+
+ eeprom->magic = hw->vendor_id | (hw->device_id << 16);
+
+ first_dword = eeprom->offset >> 2;
+ last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
+
+ eeprom_buff = kmalloc(sizeof(u32) *
+ (last_dword - first_dword + 1), GFP_KERNEL);
+ if (eeprom_buff == NULL)
+ return -ENOMEM;
+
+ for (i = first_dword; i < last_dword; i++) {
+ if (!atl1e_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) {
+ kfree(eeprom_buff);
+ return -EIO;
+ }
+ }
+
+ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3),
+ eeprom->len);
+ kfree(eeprom_buff);
+
+ return ret_val;
+}
+
+static int atl1e_set_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw *hw = &adapter->hw;
+ u32 *eeprom_buff;
+ u32 *ptr;
+ int first_dword, last_dword;
+ int ret_val = 0;
+ int i;
+
+ if (eeprom->len == 0)
+ return -EOPNOTSUPP;
+
+ if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
+ return -EINVAL;
+
+ first_dword = eeprom->offset >> 2;
+ last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
+ eeprom_buff = kmalloc(AT_EEPROM_LEN, GFP_KERNEL);
+ if (eeprom_buff == NULL)
+ return -ENOMEM;
+
+ ptr = (u32 *)eeprom_buff;
+
+ if (eeprom->offset & 3) {
+ /* need read/modify/write of first changed EEPROM word */
+ /* only the second byte of the word is being modified */
+ if (!atl1e_read_eeprom(hw, first_dword * 4, &(eeprom_buff[0]))) {
+ ret_val = -EIO;
+ goto out;
+ }
+ ptr++;
+ }
+ if (((eeprom->offset + eeprom->len) & 3)) {
+ /* need read/modify/write of last changed EEPROM word */
+ /* only the first byte of the word is being modified */
+
+ if (!atl1e_read_eeprom(hw, last_dword * 4,
+ &(eeprom_buff[last_dword - first_dword]))) {
+ ret_val = -EIO;
+ goto out;
+ }
+ }
+
+ /* Device's eeprom is always little-endian, word addressable */
+ memcpy(ptr, bytes, eeprom->len);
+
+ for (i = 0; i < last_dword - first_dword + 1; i++) {
+ if (!atl1e_write_eeprom(hw, ((first_dword + i) * 4),
+ eeprom_buff[i])) {
+ ret_val = -EIO;
+ goto out;
+ }
+ }
+out:
+ kfree(eeprom_buff);
+ return ret_val;
+}
+
+static void atl1e_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ strncpy(drvinfo->driver, atl1e_driver_name, 32);
+ strncpy(drvinfo->version, atl1e_driver_version, 32);
+ strncpy(drvinfo->fw_version, "L1e", 32);
+ strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+ drvinfo->n_stats = 0;
+ drvinfo->testinfo_len = 0;
+ drvinfo->regdump_len = atl1e_get_regs_len(netdev);
+ drvinfo->eedump_len = atl1e_get_eeprom_len(netdev);
+}
+
+static void atl1e_get_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ wol->supported = WAKE_MAGIC | WAKE_PHY;
+ wol->wolopts = 0;
+
+ if (adapter->wol & AT_WUFC_EX)
+ wol->wolopts |= WAKE_UCAST;
+ if (adapter->wol & AT_WUFC_MC)
+ wol->wolopts |= WAKE_MCAST;
+ if (adapter->wol & AT_WUFC_BC)
+ wol->wolopts |= WAKE_BCAST;
+ if (adapter->wol & AT_WUFC_MAG)
+ wol->wolopts |= WAKE_MAGIC;
+ if (adapter->wol & AT_WUFC_LNKC)
+ wol->wolopts |= WAKE_PHY;
+
+ return;
+}
+
+static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE |
+ WAKE_MCAST | WAKE_BCAST | WAKE_MCAST))
+ return -EOPNOTSUPP;
+ /* these settings will always override what we currently have */
+ adapter->wol = 0;
+
+ if (wol->wolopts & WAKE_MAGIC)
+ adapter->wol |= AT_WUFC_MAG;
+ if (wol->wolopts & WAKE_PHY)
+ adapter->wol |= AT_WUFC_LNKC;
+
+ return 0;
+}
+
+static int atl1e_nway_reset(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ if (netif_running(netdev))
+ atl1e_reinit_locked(adapter);
+ return 0;
+}
+
+static struct ethtool_ops atl1e_ethtool_ops = {
+ .get_settings = atl1e_get_settings,
+ .set_settings = atl1e_set_settings,
+ .get_drvinfo = atl1e_get_drvinfo,
+ .get_regs_len = atl1e_get_regs_len,
+ .get_regs = atl1e_get_regs,
+ .get_wol = atl1e_get_wol,
+ .set_wol = atl1e_set_wol,
+ .get_msglevel = atl1e_get_msglevel,
+ .set_msglevel = atl1e_set_msglevel,
+ .nway_reset = atl1e_nway_reset,
+ .get_link = ethtool_op_get_link,
+ .get_eeprom_len = atl1e_get_eeprom_len,
+ .get_eeprom = atl1e_get_eeprom,
+ .set_eeprom = atl1e_set_eeprom,
+ .get_tx_csum = atl1e_get_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+#ifdef NETIF_F_TSO
+ .get_tso = ethtool_op_get_tso,
+#endif
+};
+
+void atl1e_set_ethtool_ops(struct net_device *netdev)
+{
+ SET_ETHTOOL_OPS(netdev, &atl1e_ethtool_ops);
+}
diff --git a/drivers/net/atl1e/atl1e_hw.c b/drivers/net/atl1e/atl1e_hw.c
new file mode 100644
index 00000000000..949e75358bf
--- /dev/null
+++ b/drivers/net/atl1e/atl1e_hw.c
@@ -0,0 +1,664 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+
+#include "atl1e.h"
+
+/*
+ * check_eeprom_exist
+ * return 0 if eeprom exist
+ */
+int atl1e_check_eeprom_exist(struct atl1e_hw *hw)
+{
+ u32 value;
+
+ value = AT_READ_REG(hw, REG_SPI_FLASH_CTRL);
+ if (value & SPI_FLASH_CTRL_EN_VPD) {
+ value &= ~SPI_FLASH_CTRL_EN_VPD;
+ AT_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);
+ }
+ value = AT_READ_REGW(hw, REG_PCIE_CAP_LIST);
+ return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
+}
+
+void atl1e_hw_set_mac_addr(struct atl1e_hw *hw)
+{
+ u32 value;
+ /*
+ * 00-0B-6A-F6-00-DC
+ * 0: 6AF600DC 1: 000B
+ * low dword
+ */
+ value = (((u32)hw->mac_addr[2]) << 24) |
+ (((u32)hw->mac_addr[3]) << 16) |
+ (((u32)hw->mac_addr[4]) << 8) |
+ (((u32)hw->mac_addr[5])) ;
+ AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
+ /* hight dword */
+ value = (((u32)hw->mac_addr[0]) << 8) |
+ (((u32)hw->mac_addr[1])) ;
+ AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
+}
+
+/*
+ * atl1e_get_permanent_address
+ * return 0 if get valid mac address,
+ */
+static int atl1e_get_permanent_address(struct atl1e_hw *hw)
+{
+ u32 addr[2];
+ u32 i;
+ u32 twsi_ctrl_data;
+ u8 eth_addr[ETH_ALEN];
+
+ if (is_valid_ether_addr(hw->perm_mac_addr))
+ return 0;
+
+ /* init */
+ addr[0] = addr[1] = 0;
+
+ if (!atl1e_check_eeprom_exist(hw)) {
+ /* eeprom exist */
+ twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
+ twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
+ AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
+ for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
+ msleep(10);
+ twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
+ if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
+ break;
+ }
+ if (i >= AT_TWSI_EEPROM_TIMEOUT)
+ return AT_ERR_TIMEOUT;
+ }
+
+ /* maybe MAC-address is from BIOS */
+ addr[0] = AT_READ_REG(hw, REG_MAC_STA_ADDR);
+ addr[1] = AT_READ_REG(hw, REG_MAC_STA_ADDR + 4);
+ *(u32 *) &eth_addr[2] = swab32(addr[0]);
+ *(u16 *) &eth_addr[0] = swab16(*(u16 *)&addr[1]);
+
+ if (is_valid_ether_addr(eth_addr)) {
+ memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+ return 0;
+ }
+
+ return AT_ERR_EEPROM;
+}
+
+bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value)
+{
+ return true;
+}
+
+bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value)
+{
+ int i;
+ u32 control;
+
+ if (offset & 3)
+ return false; /* address do not align */
+
+ AT_WRITE_REG(hw, REG_VPD_DATA, 0);
+ control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
+ AT_WRITE_REG(hw, REG_VPD_CAP, control);
+
+ for (i = 0; i < 10; i++) {
+ msleep(2);
+ control = AT_READ_REG(hw, REG_VPD_CAP);
+ if (control & VPD_CAP_VPD_FLAG)
+ break;
+ }
+ if (control & VPD_CAP_VPD_FLAG) {
+ *p_value = AT_READ_REG(hw, REG_VPD_DATA);
+ return true;
+ }
+ return false; /* timeout */
+}
+
+void atl1e_force_ps(struct atl1e_hw *hw)
+{
+ AT_WRITE_REGW(hw, REG_GPHY_CTRL,
+ GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
+}
+
+/*
+ * Reads the adapter's MAC address from the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+int atl1e_read_mac_addr(struct atl1e_hw *hw)
+{
+ int err = 0;
+
+ err = atl1e_get_permanent_address(hw);
+ if (err)
+ return AT_ERR_EEPROM;
+ memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
+ return 0;
+}
+
+/*
+ * atl1e_hash_mc_addr
+ * purpose
+ * set hash value for a multicast address
+ * hash calcu processing :
+ * 1. calcu 32bit CRC for multicast address
+ * 2. reverse crc with MSB to LSB
+ */
+u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr)
+{
+ u32 crc32;
+ u32 value = 0;
+ int i;
+
+ crc32 = ether_crc_le(6, mc_addr);
+ crc32 = ~crc32;
+ for (i = 0; i < 32; i++)
+ value |= (((crc32 >> i) & 1) << (31 - i));
+
+ return value;
+}
+
+/*
+ * Sets the bit in the multicast table corresponding to the hash value.
+ * hw - Struct containing variables accessed by shared code
+ * hash_value - Multicast address hash value
+ */
+void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value)
+{
+ u32 hash_bit, hash_reg;
+ u32 mta;
+
+ /*
+ * The HASH Table is a register array of 2 32-bit registers.
+ * It is treated like an array of 64 bits. We want to set
+ * bit BitArray[hash_value]. So we figure out what register
+ * the bit is in, read it, OR in the new bit, then write
+ * back the new value. The register is determined by the
+ * upper 7 bits of the hash value and the bit within that
+ * register are determined by the lower 5 bits of the value.
+ */
+ hash_reg = (hash_value >> 31) & 0x1;
+ hash_bit = (hash_value >> 26) & 0x1F;
+
+ mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);
+
+ mta |= (1 << hash_bit);
+
+ AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
+}
+/*
+ * Reads the value from a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ */
+int atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+ u32 val;
+ int i;
+
+ val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
+ MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
+ MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+ AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+
+ wmb();
+
+ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+ udelay(2);
+ val = AT_READ_REG(hw, REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ wmb();
+ }
+ if (!(val & (MDIO_START | MDIO_BUSY))) {
+ *phy_data = (u16)val;
+ return 0;
+ }
+
+ return AT_ERR_PHY;
+}
+
+/*
+ * Writes a value to a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ */
+int atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data)
+{
+ int i;
+ u32 val;
+
+ val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
+ (reg_addr&MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
+ MDIO_SUP_PREAMBLE |
+ MDIO_START |
+ MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+ AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+ wmb();
+
+ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+ udelay(2);
+ val = AT_READ_REG(hw, REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ wmb();
+ }
+
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ return 0;
+
+ return AT_ERR_PHY;
+}
+
+/*
+ * atl1e_init_pcie - init PCIE module
+ */
+static void atl1e_init_pcie(struct atl1e_hw *hw)
+{
+ u32 value;
+ /* comment 2lines below to save more power when sususpend
+ value = LTSSM_TEST_MODE_DEF;
+ AT_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value);
+ */
+
+ /* pcie flow control mode change */
+ value = AT_READ_REG(hw, 0x1008);
+ value |= 0x8000;
+ AT_WRITE_REG(hw, 0x1008, value);
+}
+/*
+ * Configures PHY autoneg and flow control advertisement settings
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw)
+{
+ s32 ret_val;
+ u16 mii_autoneg_adv_reg;
+ u16 mii_1000t_ctrl_reg;
+
+ if (0 != hw->mii_autoneg_adv_reg)
+ return 0;
+ /* Read the MII Auto-Neg Advertisement Register (Address 4/9). */
+ mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
+ mii_1000t_ctrl_reg = MII_AT001_CR_1000T_DEFAULT_CAP_MASK;
+
+ /*
+ * Need to parse autoneg_advertised and set up
+ * the appropriate PHY registers. First we will parse for
+ * autoneg_advertised software override. Since we can advertise
+ * a plethora of combinations, we need to check each bit
+ * individually.
+ */
+
+ /*
+ * First we clear all the 10/100 mb speed bits in the Auto-Neg
+ * Advertisement Register (Address 4) and the 1000 mb speed bits in
+ * the 1000Base-T control Register (Address 9).
+ */
+ mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
+ mii_1000t_ctrl_reg &= ~MII_AT001_CR_1000T_SPEED_MASK;
+
+ /*
+ * Need to parse MediaType and setup the
+ * appropriate PHY registers.
+ */
+ switch (hw->media_type) {
+ case MEDIA_TYPE_AUTO_SENSOR:
+ mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS |
+ MII_AR_10T_FD_CAPS |
+ MII_AR_100TX_HD_CAPS |
+ MII_AR_100TX_FD_CAPS);
+ hw->autoneg_advertised = ADVERTISE_10_HALF |
+ ADVERTISE_10_FULL |
+ ADVERTISE_100_HALF |
+ ADVERTISE_100_FULL;
+ if (hw->nic_type == athr_l1e) {
+ mii_1000t_ctrl_reg |=
+ MII_AT001_CR_1000T_FD_CAPS;
+ hw->autoneg_advertised |= ADVERTISE_1000_FULL;
+ }
+ break;
+
+ case MEDIA_TYPE_100M_FULL:
+ mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
+ hw->autoneg_advertised = ADVERTISE_100_FULL;
+ break;
+
+ case MEDIA_TYPE_100M_HALF:
+ mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
+ hw->autoneg_advertised = ADVERTISE_100_HALF;
+ break;
+
+ case MEDIA_TYPE_10M_FULL:
+ mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
+ hw->autoneg_advertised = ADVERTISE_10_FULL;
+ break;
+
+ default:
+ mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
+ hw->autoneg_advertised = ADVERTISE_10_HALF;
+ break;
+ }
+
+ /* flow control fixed to enable all */
+ mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
+
+ hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
+ hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
+
+ ret_val = atl1e_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
+ if (ret_val)
+ return ret_val;
+
+ if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
+ ret_val = atl1e_write_phy_reg(hw, MII_AT001_CR,
+ mii_1000t_ctrl_reg);
+ if (ret_val)
+ return ret_val;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Resets the PHY and make all config validate
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Sets bit 15 and 12 of the MII control regiser (for F001 bug)
+ */
+int atl1e_phy_commit(struct atl1e_hw *hw)
+{
+ struct atl1e_adapter *adapter = (struct atl1e_adapter *)hw->adapter;
+ struct pci_dev *pdev = adapter->pdev;
+ int ret_val;
+ u16 phy_data;
+
+ phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG;
+
+ ret_val = atl1e_write_phy_reg(hw, MII_BMCR, phy_data);
+ if (ret_val) {
+ u32 val;
+ int i;
+ /**************************************
+ * pcie serdes link may be down !
+ **************************************/
+ for (i = 0; i < 25; i++) {
+ msleep(1);
+ val = AT_READ_REG(hw, REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ }
+
+ if (0 != (val & (MDIO_START | MDIO_BUSY))) {
+ dev_err(&pdev->dev,
+ "pcie linkdown at least for 25ms\n");
+ return ret_val;
+ }
+
+ dev_err(&pdev->dev, "pcie linkup after %d ms\n", i);
+ }
+ return 0;
+}
+
+int atl1e_phy_init(struct atl1e_hw *hw)
+{
+ struct atl1e_adapter *adapter = (struct atl1e_adapter *)hw->adapter;
+ struct pci_dev *pdev = adapter->pdev;
+ s32 ret_val;
+ u16 phy_val;
+
+ if (hw->phy_configured) {
+ if (hw->re_autoneg) {
+ hw->re_autoneg = false;
+ return atl1e_restart_autoneg(hw);
+ }
+ return 0;
+ }
+
+ /* RESET GPHY Core */
+ AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT);
+ msleep(2);
+ AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |
+ GPHY_CTRL_EXT_RESET);
+ msleep(2);
+
+ /* patches */
+ /* p1. eable hibernation mode */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0xB);
+ if (ret_val)
+ return ret_val;
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0xBC00);
+ if (ret_val)
+ return ret_val;
+ /* p2. set Class A/B for all modes */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0);
+ if (ret_val)
+ return ret_val;
+ phy_val = 0x02ef;
+ /* remove Class AB */
+ /* phy_val = hw->emi_ca ? 0x02ef : 0x02df; */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, phy_val);
+ if (ret_val)
+ return ret_val;
+ /* p3. 10B ??? */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x12);
+ if (ret_val)
+ return ret_val;
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x4C04);
+ if (ret_val)
+ return ret_val;
+ /* p4. 1000T power */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x4);
+ if (ret_val)
+ return ret_val;
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x8BBB);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x5);
+ if (ret_val)
+ return ret_val;
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x2C46);
+ if (ret_val)
+ return ret_val;
+
+ msleep(1);
+
+ /*Enable PHY LinkChange Interrupt */
+ ret_val = atl1e_write_phy_reg(hw, MII_INT_CTRL, 0xC00);
+ if (ret_val) {
+ dev_err(&pdev->dev, "Error enable PHY linkChange Interrupt\n");
+ return ret_val;
+ }
+ /* setup AutoNeg parameters */
+ ret_val = atl1e_phy_setup_autoneg_adv(hw);
+ if (ret_val) {
+ dev_err(&pdev->dev, "Error Setting up Auto-Negotiation\n");
+ return ret_val;
+ }
+ /* SW.Reset & En-Auto-Neg to restart Auto-Neg*/
+ dev_dbg(&pdev->dev, "Restarting Auto-Neg");
+ ret_val = atl1e_phy_commit(hw);
+ if (ret_val) {
+ dev_err(&pdev->dev, "Error Resetting the phy");
+ return ret_val;
+ }
+
+ hw->phy_configured = true;
+
+ return 0;
+}
+
+/*
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ * hw - Struct containing variables accessed by shared code
+ * return : 0 or idle status (if error)
+ */
+int atl1e_reset_hw(struct atl1e_hw *hw)
+{
+ struct atl1e_adapter *adapter = (struct atl1e_adapter *)hw->adapter;
+ struct pci_dev *pdev = adapter->pdev;
+
+ u32 idle_status_data = 0;
+ u16 pci_cfg_cmd_word = 0;
+ int timeout = 0;
+
+ /* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */
+ pci_read_config_word(pdev, PCI_REG_COMMAND, &pci_cfg_cmd_word);
+ if ((pci_cfg_cmd_word & (CMD_IO_SPACE |
+ CMD_MEMORY_SPACE | CMD_BUS_MASTER))
+ != (CMD_IO_SPACE | CMD_MEMORY_SPACE | CMD_BUS_MASTER)) {
+ pci_cfg_cmd_word |= (CMD_IO_SPACE |
+ CMD_MEMORY_SPACE | CMD_BUS_MASTER);
+ pci_write_config_word(pdev, PCI_REG_COMMAND, pci_cfg_cmd_word);
+ }
+
+ /*
+ * Issue Soft Reset to the MAC. This will reset the chip's
+ * transmit, receive, DMA. It will not effect
+ * the current PCI configuration. The global reset bit is self-
+ * clearing, and should clear within a microsecond.
+ */
+ AT_WRITE_REG(hw, REG_MASTER_CTRL,
+ MASTER_CTRL_LED_MODE | MASTER_CTRL_SOFT_RST);
+ wmb();
+ msleep(1);
+
+ /* Wait at least 10ms for All module to be Idle */
+ for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
+ idle_status_data = AT_READ_REG(hw, REG_IDLE_STATUS);
+ if (idle_status_data == 0)
+ break;
+ msleep(1);
+ cpu_relax();
+ }
+
+ if (timeout >= AT_HW_MAX_IDLE_DELAY) {
+ dev_err(&pdev->dev,
+ "MAC state machine cann't be idle since"
+ " disabled for 10ms second\n");
+ return AT_ERR_TIMEOUT;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Performs basic configuration of the adapter.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * Assumes that the controller has previously been reset and is in a
+ * post-reset uninitialized state. Initializes multicast table,
+ * and Calls routines to setup link
+ * Leaves the transmit and receive units disabled and uninitialized.
+ */
+int atl1e_init_hw(struct atl1e_hw *hw)
+{
+ s32 ret_val = 0;
+
+ atl1e_init_pcie(hw);
+
+ /* Zero out the Multicast HASH table */
+ /* clear the old settings from the multicast hash table */
+ AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+ AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+ ret_val = atl1e_phy_init(hw);
+
+ return ret_val;
+}
+
+/*
+ * Detects the current speed and duplex settings of the hardware.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ */
+int atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex)
+{
+ int err;
+ u16 phy_data;
+
+ /* Read PHY Specific Status Register (17) */
+ err = atl1e_read_phy_reg(hw, MII_AT001_PSSR, &phy_data);
+ if (err)
+ return err;
+
+ if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED))
+ return AT_ERR_PHY_RES;
+
+ switch (phy_data & MII_AT001_PSSR_SPEED) {
+ case MII_AT001_PSSR_1000MBS:
+ *speed = SPEED_1000;
+ break;
+ case MII_AT001_PSSR_100MBS:
+ *speed = SPEED_100;
+ break;
+ case MII_AT001_PSSR_10MBS:
+ *speed = SPEED_10;
+ break;
+ default:
+ return AT_ERR_PHY_SPEED;
+ break;
+ }
+
+ if (phy_data & MII_AT001_PSSR_DPLX)
+ *duplex = FULL_DUPLEX;
+ else
+ *duplex = HALF_DUPLEX;
+
+ return 0;
+}
+
+int atl1e_restart_autoneg(struct atl1e_hw *hw)
+{
+ int err = 0;
+
+ err = atl1e_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
+ if (err)
+ return err;
+
+ if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
+ err = atl1e_write_phy_reg(hw, MII_AT001_CR,
+ hw->mii_1000t_ctrl_reg);
+ if (err)
+ return err;
+ }
+
+ err = atl1e_write_phy_reg(hw, MII_BMCR,
+ MII_CR_RESET | MII_CR_AUTO_NEG_EN |
+ MII_CR_RESTART_AUTO_NEG);
+ return err;
+}
+
diff --git a/drivers/net/atl1e/atl1e_hw.h b/drivers/net/atl1e/atl1e_hw.h
new file mode 100644
index 00000000000..5ea2f4d86cf
--- /dev/null
+++ b/drivers/net/atl1e/atl1e_hw.h
@@ -0,0 +1,793 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _ATHL1E_HW_H_
+#define _ATHL1E_HW_H_
+
+#include <linux/types.h>
+#include <linux/mii.h>
+
+struct atl1e_adapter;
+struct atl1e_hw;
+
+/* function prototype */
+s32 atl1e_reset_hw(struct atl1e_hw *hw);
+s32 atl1e_read_mac_addr(struct atl1e_hw *hw);
+s32 atl1e_init_hw(struct atl1e_hw *hw);
+s32 atl1e_phy_commit(struct atl1e_hw *hw);
+s32 atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex);
+u32 atl1e_auto_get_fc(struct atl1e_adapter *adapter, u16 duplex);
+u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr);
+void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value);
+s32 atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data);
+s32 atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data);
+s32 atl1e_validate_mdi_setting(struct atl1e_hw *hw);
+void atl1e_hw_set_mac_addr(struct atl1e_hw *hw);
+bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value);
+bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value);
+s32 atl1e_phy_enter_power_saving(struct atl1e_hw *hw);
+s32 atl1e_phy_leave_power_saving(struct atl1e_hw *hw);
+s32 atl1e_phy_init(struct atl1e_hw *hw);
+int atl1e_check_eeprom_exist(struct atl1e_hw *hw);
+void atl1e_force_ps(struct atl1e_hw *hw);
+s32 atl1e_restart_autoneg(struct atl1e_hw *hw);
+
+/* register definition */
+#define REG_PM_CTRLSTAT 0x44
+
+#define REG_PCIE_CAP_LIST 0x58
+
+#define REG_DEVICE_CAP 0x5C
+#define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7
+#define DEVICE_CAP_MAX_PAYLOAD_SHIFT 0
+
+#define REG_DEVICE_CTRL 0x60
+#define DEVICE_CTRL_MAX_PAYLOAD_MASK 0x7
+#define DEVICE_CTRL_MAX_PAYLOAD_SHIFT 5
+#define DEVICE_CTRL_MAX_RREQ_SZ_MASK 0x7
+#define DEVICE_CTRL_MAX_RREQ_SZ_SHIFT 12
+
+#define REG_VPD_CAP 0x6C
+#define VPD_CAP_ID_MASK 0xff
+#define VPD_CAP_ID_SHIFT 0
+#define VPD_CAP_NEXT_PTR_MASK 0xFF
+#define VPD_CAP_NEXT_PTR_SHIFT 8
+#define VPD_CAP_VPD_ADDR_MASK 0x7FFF
+#define VPD_CAP_VPD_ADDR_SHIFT 16
+#define VPD_CAP_VPD_FLAG 0x80000000
+
+#define REG_VPD_DATA 0x70
+
+#define REG_SPI_FLASH_CTRL 0x200
+#define SPI_FLASH_CTRL_STS_NON_RDY 0x1
+#define SPI_FLASH_CTRL_STS_WEN 0x2
+#define SPI_FLASH_CTRL_STS_WPEN 0x80
+#define SPI_FLASH_CTRL_DEV_STS_MASK 0xFF
+#define SPI_FLASH_CTRL_DEV_STS_SHIFT 0
+#define SPI_FLASH_CTRL_INS_MASK 0x7
+#define SPI_FLASH_CTRL_INS_SHIFT 8
+#define SPI_FLASH_CTRL_START 0x800
+#define SPI_FLASH_CTRL_EN_VPD 0x2000
+#define SPI_FLASH_CTRL_LDSTART 0x8000
+#define SPI_FLASH_CTRL_CS_HI_MASK 0x3
+#define SPI_FLASH_CTRL_CS_HI_SHIFT 16
+#define SPI_FLASH_CTRL_CS_HOLD_MASK 0x3
+#define SPI_FLASH_CTRL_CS_HOLD_SHIFT 18
+#define SPI_FLASH_CTRL_CLK_LO_MASK 0x3
+#define SPI_FLASH_CTRL_CLK_LO_SHIFT 20
+#define SPI_FLASH_CTRL_CLK_HI_MASK 0x3
+#define SPI_FLASH_CTRL_CLK_HI_SHIFT 22
+#define SPI_FLASH_CTRL_CS_SETUP_MASK 0x3
+#define SPI_FLASH_CTRL_CS_SETUP_SHIFT 24
+#define SPI_FLASH_CTRL_EROM_PGSZ_MASK 0x3
+#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT 26
+#define SPI_FLASH_CTRL_WAIT_READY 0x10000000
+
+#define REG_SPI_ADDR 0x204
+
+#define REG_SPI_DATA 0x208
+
+#define REG_SPI_FLASH_CONFIG 0x20C
+#define SPI_FLASH_CONFIG_LD_ADDR_MASK 0xFFFFFF
+#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT 0
+#define SPI_FLASH_CONFIG_VPD_ADDR_MASK 0x3
+#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT 24
+#define SPI_FLASH_CONFIG_LD_EXIST 0x4000000
+
+
+#define REG_SPI_FLASH_OP_PROGRAM 0x210
+#define REG_SPI_FLASH_OP_SC_ERASE 0x211
+#define REG_SPI_FLASH_OP_CHIP_ERASE 0x212
+#define REG_SPI_FLASH_OP_RDID 0x213
+#define REG_SPI_FLASH_OP_WREN 0x214
+#define REG_SPI_FLASH_OP_RDSR 0x215
+#define REG_SPI_FLASH_OP_WRSR 0x216
+#define REG_SPI_FLASH_OP_READ 0x217
+
+#define REG_TWSI_CTRL 0x218
+#define TWSI_CTRL_LD_OFFSET_MASK 0xFF
+#define TWSI_CTRL_LD_OFFSET_SHIFT 0
+#define TWSI_CTRL_LD_SLV_ADDR_MASK 0x7
+#define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8
+#define TWSI_CTRL_SW_LDSTART 0x800
+#define TWSI_CTRL_HW_LDSTART 0x1000
+#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x0x7F
+#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15
+#define TWSI_CTRL_LD_EXIST 0x400000
+#define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3
+#define TWSI_CTRL_READ_FREQ_SEL_SHIFT 23
+#define TWSI_CTRL_FREQ_SEL_100K 0
+#define TWSI_CTRL_FREQ_SEL_200K 1
+#define TWSI_CTRL_FREQ_SEL_300K 2
+#define TWSI_CTRL_FREQ_SEL_400K 3
+#define TWSI_CTRL_SMB_SLV_ADDR
+#define TWSI_CTRL_WRITE_FREQ_SEL_MASK 0x3
+#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT 24
+
+
+#define REG_PCIE_DEV_MISC_CTRL 0x21C
+#define PCIE_DEV_MISC_CTRL_EXT_PIPE 0x2
+#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS 0x1
+#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST 0x4
+#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN 0x8
+#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN 0x10
+
+#define REG_PCIE_PHYMISC 0x1000
+#define PCIE_PHYMISC_FORCE_RCV_DET 0x4
+
+#define REG_LTSSM_TEST_MODE 0x12FC
+#define LTSSM_TEST_MODE_DEF 0xE000
+
+/* Selene Master Control Register */
+#define REG_MASTER_CTRL 0x1400
+#define MASTER_CTRL_SOFT_RST 0x1
+#define MASTER_CTRL_MTIMER_EN 0x2
+#define MASTER_CTRL_ITIMER_EN 0x4
+#define MASTER_CTRL_MANUAL_INT 0x8
+#define MASTER_CTRL_ITIMER2_EN 0x20
+#define MASTER_CTRL_INT_RDCLR 0x40
+#define MASTER_CTRL_LED_MODE 0x200
+#define MASTER_CTRL_REV_NUM_SHIFT 16
+#define MASTER_CTRL_REV_NUM_MASK 0xff
+#define MASTER_CTRL_DEV_ID_SHIFT 24
+#define MASTER_CTRL_DEV_ID_MASK 0xff
+
+/* Timer Initial Value Register */
+#define REG_MANUAL_TIMER_INIT 0x1404
+
+
+/* IRQ ModeratorTimer Initial Value Register */
+#define REG_IRQ_MODU_TIMER_INIT 0x1408 /* w */
+#define REG_IRQ_MODU_TIMER2_INIT 0x140A /* w */
+
+
+#define REG_GPHY_CTRL 0x140C
+#define GPHY_CTRL_EXT_RESET 1
+#define GPHY_CTRL_PIPE_MOD 2
+#define GPHY_CTRL_TEST_MODE_MASK 3
+#define GPHY_CTRL_TEST_MODE_SHIFT 2
+#define GPHY_CTRL_BERT_START 0x10
+#define GPHY_CTRL_GATE_25M_EN 0x20
+#define GPHY_CTRL_LPW_EXIT 0x40
+#define GPHY_CTRL_PHY_IDDQ 0x80
+#define GPHY_CTRL_PHY_IDDQ_DIS 0x100
+#define GPHY_CTRL_PCLK_SEL_DIS 0x200
+#define GPHY_CTRL_HIB_EN 0x400
+#define GPHY_CTRL_HIB_PULSE 0x800
+#define GPHY_CTRL_SEL_ANA_RST 0x1000
+#define GPHY_CTRL_PHY_PLL_ON 0x2000
+#define GPHY_CTRL_PWDOWN_HW 0x4000
+#define GPHY_CTRL_DEFAULT (\
+ GPHY_CTRL_PHY_PLL_ON |\
+ GPHY_CTRL_SEL_ANA_RST |\
+ GPHY_CTRL_HIB_PULSE |\
+ GPHY_CTRL_HIB_EN)
+
+#define GPHY_CTRL_PW_WOL_DIS (\
+ GPHY_CTRL_PHY_PLL_ON |\
+ GPHY_CTRL_SEL_ANA_RST |\
+ GPHY_CTRL_HIB_PULSE |\
+ GPHY_CTRL_HIB_EN |\
+ GPHY_CTRL_PWDOWN_HW |\
+ GPHY_CTRL_PCLK_SEL_DIS |\
+ GPHY_CTRL_PHY_IDDQ)
+
+/* IRQ Anti-Lost Timer Initial Value Register */
+#define REG_CMBDISDMA_TIMER 0x140E
+
+
+/* Block IDLE Status Register */
+#define REG_IDLE_STATUS 0x1410
+#define IDLE_STATUS_RXMAC 1 /* 1: RXMAC state machine is in non-IDLE state. 0: RXMAC is idling */
+#define IDLE_STATUS_TXMAC 2 /* 1: TXMAC state machine is in non-IDLE state. 0: TXMAC is idling */
+#define IDLE_STATUS_RXQ 4 /* 1: RXQ state machine is in non-IDLE state. 0: RXQ is idling */
+#define IDLE_STATUS_TXQ 8 /* 1: TXQ state machine is in non-IDLE state. 0: TXQ is idling */
+#define IDLE_STATUS_DMAR 0x10 /* 1: DMAR state machine is in non-IDLE state. 0: DMAR is idling */
+#define IDLE_STATUS_DMAW 0x20 /* 1: DMAW state machine is in non-IDLE state. 0: DMAW is idling */
+#define IDLE_STATUS_SMB 0x40 /* 1: SMB state machine is in non-IDLE state. 0: SMB is idling */
+#define IDLE_STATUS_CMB 0x80 /* 1: CMB state machine is in non-IDLE state. 0: CMB is idling */
+
+/* MDIO Control Register */
+#define REG_MDIO_CTRL 0x1414
+#define MDIO_DATA_MASK 0xffff /* On MDIO write, the 16-bit control data to write to PHY MII management register */
+#define MDIO_DATA_SHIFT 0 /* On MDIO read, the 16-bit status data that was read from the PHY MII management register*/
+#define MDIO_REG_ADDR_MASK 0x1f /* MDIO register address */
+#define MDIO_REG_ADDR_SHIFT 16
+#define MDIO_RW 0x200000 /* 1: read, 0: write */
+#define MDIO_SUP_PREAMBLE 0x400000 /* Suppress preamble */
+#define MDIO_START 0x800000 /* Write 1 to initiate the MDIO master. And this bit is self cleared after one cycle*/
+#define MDIO_CLK_SEL_SHIFT 24
+#define MDIO_CLK_25_4 0
+#define MDIO_CLK_25_6 2
+#define MDIO_CLK_25_8 3
+#define MDIO_CLK_25_10 4
+#define MDIO_CLK_25_14 5
+#define MDIO_CLK_25_20 6
+#define MDIO_CLK_25_28 7
+#define MDIO_BUSY 0x8000000
+#define MDIO_AP_EN 0x10000000
+#define MDIO_WAIT_TIMES 10
+
+/* MII PHY Status Register */
+#define REG_PHY_STATUS 0x1418
+#define PHY_STATUS_100M 0x20000
+#define PHY_STATUS_EMI_CA 0x40000
+
+/* BIST Control and Status Register0 (for the Packet Memory) */
+#define REG_BIST0_CTRL 0x141c
+#define BIST0_NOW 0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */
+/* BIST process and reset to zero when BIST is done */
+#define BIST0_SRAM_FAIL 0x2 /* 1: The SRAM failure is un-repairable because it has address */
+/* decoder failure or more than 1 cell stuck-to-x failure */
+#define BIST0_FUSE_FLAG 0x4 /* 1: Indicating one cell has been fixed */
+
+/* BIST Control and Status Register1(for the retry buffer of PCI Express) */
+#define REG_BIST1_CTRL 0x1420
+#define BIST1_NOW 0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */
+/* BIST process and reset to zero when BIST is done */
+#define BIST1_SRAM_FAIL 0x2 /* 1: The SRAM failure is un-repairable because it has address */
+/* decoder failure or more than 1 cell stuck-to-x failure.*/
+#define BIST1_FUSE_FLAG 0x4
+
+/* SerDes Lock Detect Control and Status Register */
+#define REG_SERDES_LOCK 0x1424
+#define SERDES_LOCK_DETECT 1 /* 1: SerDes lock detected . This signal comes from Analog SerDes */
+#define SERDES_LOCK_DETECT_EN 2 /* 1: Enable SerDes Lock detect function */
+
+/* MAC Control Register */
+#define REG_MAC_CTRL 0x1480
+#define MAC_CTRL_TX_EN 1 /* 1: Transmit Enable */
+#define MAC_CTRL_RX_EN 2 /* 1: Receive Enable */
+#define MAC_CTRL_TX_FLOW 4 /* 1: Transmit Flow Control Enable */
+#define MAC_CTRL_RX_FLOW 8 /* 1: Receive Flow Control Enable */
+#define MAC_CTRL_LOOPBACK 0x10 /* 1: Loop back at G/MII Interface */
+#define MAC_CTRL_DUPLX 0x20 /* 1: Full-duplex mode 0: Half-duplex mode */
+#define MAC_CTRL_ADD_CRC 0x40 /* 1: Instruct MAC to attach CRC on all egress Ethernet frames */
+#define MAC_CTRL_PAD 0x80 /* 1: Instruct MAC to pad short frames to 60-bytes, and then attach CRC. This bit has higher priority over CRC_EN */
+#define MAC_CTRL_LENCHK 0x100 /* 1: Instruct MAC to check if length field matches the real packet length */
+#define MAC_CTRL_HUGE_EN 0x200 /* 1: receive Jumbo frame enable */
+#define MAC_CTRL_PRMLEN_SHIFT 10 /* Preamble length */
+#define MAC_CTRL_PRMLEN_MASK 0xf
+#define MAC_CTRL_RMV_VLAN 0x4000 /* 1: to remove VLAN Tag automatically from all receive packets */
+#define MAC_CTRL_PROMIS_EN 0x8000 /* 1: Promiscuous Mode Enable */
+#define MAC_CTRL_TX_PAUSE 0x10000 /* 1: transmit test pause */
+#define MAC_CTRL_SCNT 0x20000 /* 1: shortcut slot time counter */
+#define MAC_CTRL_SRST_TX 0x40000 /* 1: synchronized reset Transmit MAC module */
+#define MAC_CTRL_TX_SIMURST 0x80000 /* 1: transmit simulation reset */
+#define MAC_CTRL_SPEED_SHIFT 20 /* 10: gigabit 01:10M/100M */
+#define MAC_CTRL_SPEED_MASK 0x300000
+#define MAC_CTRL_SPEED_1000 2
+#define MAC_CTRL_SPEED_10_100 1
+#define MAC_CTRL_DBG_TX_BKPRESURE 0x400000 /* 1: transmit maximum backoff (half-duplex test bit) */
+#define MAC_CTRL_TX_HUGE 0x800000 /* 1: transmit huge enable */
+#define MAC_CTRL_RX_CHKSUM_EN 0x1000000 /* 1: RX checksum enable */
+#define MAC_CTRL_MC_ALL_EN 0x2000000 /* 1: upload all multicast frame without error to system */
+#define MAC_CTRL_BC_EN 0x4000000 /* 1: upload all broadcast frame without error to system */
+#define MAC_CTRL_DBG 0x8000000 /* 1: upload all received frame to system (Debug Mode) */
+
+/* MAC IPG/IFG Control Register */
+#define REG_MAC_IPG_IFG 0x1484
+#define MAC_IPG_IFG_IPGT_SHIFT 0 /* Desired back to back inter-packet gap. The default is 96-bit time */
+#define MAC_IPG_IFG_IPGT_MASK 0x7f
+#define MAC_IPG_IFG_MIFG_SHIFT 8 /* Minimum number of IFG to enforce in between RX frames */
+#define MAC_IPG_IFG_MIFG_MASK 0xff /* Frame gap below such IFP is dropped */
+#define MAC_IPG_IFG_IPGR1_SHIFT 16 /* 64bit Carrier-Sense window */
+#define MAC_IPG_IFG_IPGR1_MASK 0x7f
+#define MAC_IPG_IFG_IPGR2_SHIFT 24 /* 96-bit IPG window */
+#define MAC_IPG_IFG_IPGR2_MASK 0x7f
+
+/* MAC STATION ADDRESS */
+#define REG_MAC_STA_ADDR 0x1488
+
+/* Hash table for multicast address */
+#define REG_RX_HASH_TABLE 0x1490
+
+
+/* MAC Half-Duplex Control Register */
+#define REG_MAC_HALF_DUPLX_CTRL 0x1498
+#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT 0 /* Collision Window */
+#define MAC_HALF_DUPLX_CTRL_LCOL_MASK 0x3ff
+#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12 /* Retransmission maximum, afterwards the packet will be discarded */
+#define MAC_HALF_DUPLX_CTRL_RETRY_MASK 0xf
+#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN 0x10000 /* 1: Allow the transmission of a packet which has been excessively deferred */
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_C 0x20000 /* 1: No back-off on collision, immediately start the retransmission */
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_P 0x40000 /* 1: No back-off on backpressure, immediately start the transmission after back pressure */
+#define MAC_HALF_DUPLX_CTRL_ABEBE 0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */
+#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT 20 /* Maximum binary exponential number */
+#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK 0xf
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24 /* IPG to start JAM for collision based flow control in half-duplex */
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK 0xf /* mode. In unit of 8-bit time */
+
+/* Maximum Frame Length Control Register */
+#define REG_MTU 0x149c
+
+/* Wake-On-Lan control register */
+#define REG_WOL_CTRL 0x14a0
+#define WOL_PATTERN_EN 0x00000001
+#define WOL_PATTERN_PME_EN 0x00000002
+#define WOL_MAGIC_EN 0x00000004
+#define WOL_MAGIC_PME_EN 0x00000008
+#define WOL_LINK_CHG_EN 0x00000010
+#define WOL_LINK_CHG_PME_EN 0x00000020
+#define WOL_PATTERN_ST 0x00000100
+#define WOL_MAGIC_ST 0x00000200
+#define WOL_LINKCHG_ST 0x00000400
+#define WOL_CLK_SWITCH_EN 0x00008000
+#define WOL_PT0_EN 0x00010000
+#define WOL_PT1_EN 0x00020000
+#define WOL_PT2_EN 0x00040000
+#define WOL_PT3_EN 0x00080000
+#define WOL_PT4_EN 0x00100000
+#define WOL_PT5_EN 0x00200000
+#define WOL_PT6_EN 0x00400000
+/* WOL Length ( 2 DWORD ) */
+#define REG_WOL_PATTERN_LEN 0x14a4
+#define WOL_PT_LEN_MASK 0x7f
+#define WOL_PT0_LEN_SHIFT 0
+#define WOL_PT1_LEN_SHIFT 8
+#define WOL_PT2_LEN_SHIFT 16
+#define WOL_PT3_LEN_SHIFT 24
+#define WOL_PT4_LEN_SHIFT 0
+#define WOL_PT5_LEN_SHIFT 8
+#define WOL_PT6_LEN_SHIFT 16
+
+/* Internal SRAM Partition Register */
+#define REG_SRAM_TRD_ADDR 0x1518
+#define REG_SRAM_TRD_LEN 0x151C
+#define REG_SRAM_RXF_ADDR 0x1520
+#define REG_SRAM_RXF_LEN 0x1524
+#define REG_SRAM_TXF_ADDR 0x1528
+#define REG_SRAM_TXF_LEN 0x152C
+#define REG_SRAM_TCPH_ADDR 0x1530
+#define REG_SRAM_PKTH_ADDR 0x1532
+
+/* Load Ptr Register */
+#define REG_LOAD_PTR 0x1534 /* Software sets this bit after the initialization of the head and tail */
+
+/*
+ * addresses of all descriptors, as well as the following descriptor
+ * control register, which triggers each function block to load the head
+ * pointer to prepare for the operation. This bit is then self-cleared
+ * after one cycle.
+ */
+
+/* Descriptor Control register */
+#define REG_RXF3_BASE_ADDR_HI 0x153C
+#define REG_DESC_BASE_ADDR_HI 0x1540
+#define REG_RXF0_BASE_ADDR_HI 0x1540 /* share with DESC BASE ADDR HI */
+#define REG_HOST_RXF0_PAGE0_LO 0x1544
+#define REG_HOST_RXF0_PAGE1_LO 0x1548
+#define REG_TPD_BASE_ADDR_LO 0x154C
+#define REG_RXF1_BASE_ADDR_HI 0x1550
+#define REG_RXF2_BASE_ADDR_HI 0x1554
+#define REG_HOST_RXFPAGE_SIZE 0x1558
+#define REG_TPD_RING_SIZE 0x155C
+/* RSS about */
+#define REG_RSS_KEY0 0x14B0
+#define REG_RSS_KEY1 0x14B4
+#define REG_RSS_KEY2 0x14B8
+#define REG_RSS_KEY3 0x14BC
+#define REG_RSS_KEY4 0x14C0
+#define REG_RSS_KEY5 0x14C4
+#define REG_RSS_KEY6 0x14C8
+#define REG_RSS_KEY7 0x14CC
+#define REG_RSS_KEY8 0x14D0
+#define REG_RSS_KEY9 0x14D4
+#define REG_IDT_TABLE4 0x14E0
+#define REG_IDT_TABLE5 0x14E4
+#define REG_IDT_TABLE6 0x14E8
+#define REG_IDT_TABLE7 0x14EC
+#define REG_IDT_TABLE0 0x1560
+#define REG_IDT_TABLE1 0x1564
+#define REG_IDT_TABLE2 0x1568
+#define REG_IDT_TABLE3 0x156C
+#define REG_IDT_TABLE REG_IDT_TABLE0
+#define REG_RSS_HASH_VALUE 0x1570
+#define REG_RSS_HASH_FLAG 0x1574
+#define REG_BASE_CPU_NUMBER 0x157C
+
+
+/* TXQ Control Register */
+#define REG_TXQ_CTRL 0x1580
+#define TXQ_CTRL_NUM_TPD_BURST_MASK 0xF
+#define TXQ_CTRL_NUM_TPD_BURST_SHIFT 0
+#define TXQ_CTRL_EN 0x20 /* 1: Enable TXQ */
+#define TXQ_CTRL_ENH_MODE 0x40 /* Performance enhancement mode, in which up to two back-to-back DMA read commands might be dispatched. */
+#define TXQ_CTRL_TXF_BURST_NUM_SHIFT 16 /* Number of data byte to read in a cache-aligned burst. Each SRAM entry is 8-byte in length. */
+#define TXQ_CTRL_TXF_BURST_NUM_MASK 0xffff
+
+/* Jumbo packet Threshold for task offload */
+#define REG_TX_EARLY_TH 0x1584 /* Jumbo frame threshold in QWORD unit. Packet greater than */
+/* JUMBO_TASK_OFFLOAD_THRESHOLD will not be task offloaded. */
+#define TX_TX_EARLY_TH_MASK 0x7ff
+#define TX_TX_EARLY_TH_SHIFT 0
+
+
+/* RXQ Control Register */
+#define REG_RXQ_CTRL 0x15A0
+#define RXQ_CTRL_PBA_ALIGN_32 0 /* rx-packet alignment */
+#define RXQ_CTRL_PBA_ALIGN_64 1
+#define RXQ_CTRL_PBA_ALIGN_128 2
+#define RXQ_CTRL_PBA_ALIGN_256 3
+#define RXQ_CTRL_Q1_EN 0x10
+#define RXQ_CTRL_Q2_EN 0x20
+#define RXQ_CTRL_Q3_EN 0x40
+#define RXQ_CTRL_IPV6_XSUM_VERIFY_EN 0x80
+#define RXQ_CTRL_HASH_TLEN_SHIFT 8
+#define RXQ_CTRL_HASH_TLEN_MASK 0xFF
+#define RXQ_CTRL_HASH_TYPE_IPV4 0x10000
+#define RXQ_CTRL_HASH_TYPE_IPV4_TCP 0x20000
+#define RXQ_CTRL_HASH_TYPE_IPV6 0x40000
+#define RXQ_CTRL_HASH_TYPE_IPV6_TCP 0x80000
+#define RXQ_CTRL_RSS_MODE_DISABLE 0
+#define RXQ_CTRL_RSS_MODE_SQSINT 0x4000000
+#define RXQ_CTRL_RSS_MODE_MQUESINT 0x8000000
+#define RXQ_CTRL_RSS_MODE_MQUEMINT 0xC000000
+#define RXQ_CTRL_NIP_QUEUE_SEL_TBL 0x10000000
+#define RXQ_CTRL_HASH_ENABLE 0x20000000
+#define RXQ_CTRL_CUT_THRU_EN 0x40000000
+#define RXQ_CTRL_EN 0x80000000
+
+/* Rx jumbo packet threshold and rrd retirement timer */
+#define REG_RXQ_JMBOSZ_RRDTIM 0x15A4
+/*
+ * Jumbo packet threshold for non-VLAN packet, in QWORD (64-bit) unit.
+ * When the packet length greater than or equal to this value, RXQ
+ * shall start cut-through forwarding of the received packet.
+ */
+#define RXQ_JMBOSZ_TH_MASK 0x7ff
+#define RXQ_JMBOSZ_TH_SHIFT 0 /* RRD retirement timer. Decrement by 1 after every 512ns passes*/
+#define RXQ_JMBO_LKAH_MASK 0xf
+#define RXQ_JMBO_LKAH_SHIFT 11
+
+/* RXF flow control register */
+#define REG_RXQ_RXF_PAUSE_THRESH 0x15A8
+#define RXQ_RXF_PAUSE_TH_HI_SHIFT 0
+#define RXQ_RXF_PAUSE_TH_HI_MASK 0xfff
+#define RXQ_RXF_PAUSE_TH_LO_SHIFT 16
+#define RXQ_RXF_PAUSE_TH_LO_MASK 0xfff
+
+
+/* DMA Engine Control Register */
+#define REG_DMA_CTRL 0x15C0
+#define DMA_CTRL_DMAR_IN_ORDER 0x1
+#define DMA_CTRL_DMAR_ENH_ORDER 0x2
+#define DMA_CTRL_DMAR_OUT_ORDER 0x4
+#define DMA_CTRL_RCB_VALUE 0x8
+#define DMA_CTRL_DMAR_BURST_LEN_SHIFT 4
+#define DMA_CTRL_DMAR_BURST_LEN_MASK 7
+#define DMA_CTRL_DMAW_BURST_LEN_SHIFT 7
+#define DMA_CTRL_DMAW_BURST_LEN_MASK 7
+#define DMA_CTRL_DMAR_REQ_PRI 0x400
+#define DMA_CTRL_DMAR_DLY_CNT_MASK 0x1F
+#define DMA_CTRL_DMAR_DLY_CNT_SHIFT 11
+#define DMA_CTRL_DMAW_DLY_CNT_MASK 0xF
+#define DMA_CTRL_DMAW_DLY_CNT_SHIFT 16
+#define DMA_CTRL_TXCMB_EN 0x100000
+#define DMA_CTRL_RXCMB_EN 0x200000
+
+
+/* CMB/SMB Control Register */
+#define REG_SMB_STAT_TIMER 0x15C4
+#define REG_TRIG_RRD_THRESH 0x15CA
+#define REG_TRIG_TPD_THRESH 0x15C8
+#define REG_TRIG_TXTIMER 0x15CC
+#define REG_TRIG_RXTIMER 0x15CE
+
+/* HOST RXF Page 1,2,3 address */
+#define REG_HOST_RXF1_PAGE0_LO 0x15D0
+#define REG_HOST_RXF1_PAGE1_LO 0x15D4
+#define REG_HOST_RXF2_PAGE0_LO 0x15D8
+#define REG_HOST_RXF2_PAGE1_LO 0x15DC
+#define REG_HOST_RXF3_PAGE0_LO 0x15E0
+#define REG_HOST_RXF3_PAGE1_LO 0x15E4
+
+/* Mail box */
+#define REG_MB_RXF1_RADDR 0x15B4
+#define REG_MB_RXF2_RADDR 0x15B8
+#define REG_MB_RXF3_RADDR 0x15BC
+#define REG_MB_TPD_PROD_IDX 0x15F0
+
+/* RXF-Page 0-3 PageNo & Valid bit */
+#define REG_HOST_RXF0_PAGE0_VLD 0x15F4
+#define HOST_RXF_VALID 1
+#define HOST_RXF_PAGENO_SHIFT 1
+#define HOST_RXF_PAGENO_MASK 0x7F
+#define REG_HOST_RXF0_PAGE1_VLD 0x15F5
+#define REG_HOST_RXF1_PAGE0_VLD 0x15F6
+#define REG_HOST_RXF1_PAGE1_VLD 0x15F7
+#define REG_HOST_RXF2_PAGE0_VLD 0x15F8
+#define REG_HOST_RXF2_PAGE1_VLD 0x15F9
+#define REG_HOST_RXF3_PAGE0_VLD 0x15FA
+#define REG_HOST_RXF3_PAGE1_VLD 0x15FB
+
+/* Interrupt Status Register */
+#define REG_ISR 0x1600
+#define ISR_SMB 1
+#define ISR_TIMER 2 /* Interrupt when Timer is counted down to zero */
+/*
+ * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set
+ * in Table 51 Selene Master Control Register (Offset 0x1400).
+ */
+#define ISR_MANUAL 4
+#define ISR_HW_RXF_OV 8 /* RXF overflow interrupt */
+#define ISR_HOST_RXF0_OV 0x10
+#define ISR_HOST_RXF1_OV 0x20
+#define ISR_HOST_RXF2_OV 0x40
+#define ISR_HOST_RXF3_OV 0x80
+#define ISR_TXF_UN 0x100
+#define ISR_RX0_PAGE_FULL 0x200
+#define ISR_DMAR_TO_RST 0x400
+#define ISR_DMAW_TO_RST 0x800
+#define ISR_GPHY 0x1000
+#define ISR_TX_CREDIT 0x2000
+#define ISR_GPHY_LPW 0x4000 /* GPHY low power state interrupt */
+#define ISR_RX_PKT 0x10000 /* One packet received, triggered by RFD */
+#define ISR_TX_PKT 0x20000 /* One packet transmitted, triggered by TPD */
+#define ISR_TX_DMA 0x40000
+#define ISR_RX_PKT_1 0x80000
+#define ISR_RX_PKT_2 0x100000
+#define ISR_RX_PKT_3 0x200000
+#define ISR_MAC_RX 0x400000
+#define ISR_MAC_TX 0x800000
+#define ISR_UR_DETECTED 0x1000000
+#define ISR_FERR_DETECTED 0x2000000
+#define ISR_NFERR_DETECTED 0x4000000
+#define ISR_CERR_DETECTED 0x8000000
+#define ISR_PHY_LINKDOWN 0x10000000
+#define ISR_DIS_INT 0x80000000
+
+
+/* Interrupt Mask Register */
+#define REG_IMR 0x1604
+
+
+#define IMR_NORMAL_MASK (\
+ ISR_SMB |\
+ ISR_TXF_UN |\
+ ISR_HW_RXF_OV |\
+ ISR_HOST_RXF0_OV|\
+ ISR_MANUAL |\
+ ISR_GPHY |\
+ ISR_GPHY_LPW |\
+ ISR_DMAR_TO_RST |\
+ ISR_DMAW_TO_RST |\
+ ISR_PHY_LINKDOWN|\
+ ISR_RX_PKT |\
+ ISR_TX_PKT)
+
+#define ISR_TX_EVENT (ISR_TXF_UN | ISR_TX_PKT)
+#define ISR_RX_EVENT (ISR_HOST_RXF0_OV | ISR_HW_RXF_OV | ISR_RX_PKT)
+
+#define REG_MAC_RX_STATUS_BIN 0x1700
+#define REG_MAC_RX_STATUS_END 0x175c
+#define REG_MAC_TX_STATUS_BIN 0x1760
+#define REG_MAC_TX_STATUS_END 0x17c0
+
+/* Hardware Offset Register */
+#define REG_HOST_RXF0_PAGEOFF 0x1800
+#define REG_TPD_CONS_IDX 0x1804
+#define REG_HOST_RXF1_PAGEOFF 0x1808
+#define REG_HOST_RXF2_PAGEOFF 0x180C
+#define REG_HOST_RXF3_PAGEOFF 0x1810
+
+/* RXF-Page 0-3 Offset DMA Address */
+#define REG_HOST_RXF0_MB0_LO 0x1820
+#define REG_HOST_RXF0_MB1_LO 0x1824
+#define REG_HOST_RXF1_MB0_LO 0x1828
+#define REG_HOST_RXF1_MB1_LO 0x182C
+#define REG_HOST_RXF2_MB0_LO 0x1830
+#define REG_HOST_RXF2_MB1_LO 0x1834
+#define REG_HOST_RXF3_MB0_LO 0x1838
+#define REG_HOST_RXF3_MB1_LO 0x183C
+
+/* Tpd CMB DMA Address */
+#define REG_HOST_TX_CMB_LO 0x1840
+#define REG_HOST_SMB_ADDR_LO 0x1844
+
+/* DEBUG ADDR */
+#define REG_DEBUG_DATA0 0x1900
+#define REG_DEBUG_DATA1 0x1904
+
+/***************************** MII definition ***************************************/
+/* PHY Common Register */
+#define MII_BMCR 0x00
+#define MII_BMSR 0x01
+#define MII_PHYSID1 0x02
+#define MII_PHYSID2 0x03
+#define MII_ADVERTISE 0x04
+#define MII_LPA 0x05
+#define MII_EXPANSION 0x06
+#define MII_AT001_CR 0x09
+#define MII_AT001_SR 0x0A
+#define MII_AT001_ESR 0x0F
+#define MII_AT001_PSCR 0x10
+#define MII_AT001_PSSR 0x11
+#define MII_INT_CTRL 0x12
+#define MII_INT_STATUS 0x13
+#define MII_SMARTSPEED 0x14
+#define MII_RERRCOUNTER 0x15
+#define MII_SREVISION 0x16
+#define MII_RESV1 0x17
+#define MII_LBRERROR 0x18
+#define MII_PHYADDR 0x19
+#define MII_RESV2 0x1a
+#define MII_TPISTATUS 0x1b
+#define MII_NCONFIG 0x1c
+
+#define MII_DBG_ADDR 0x1D
+#define MII_DBG_DATA 0x1E
+
+
+/* PHY Control Register */
+#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
+#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
+#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN 0x0800 /* Power down */
+#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
+#define MII_CR_SPEED_MASK 0x2040
+#define MII_CR_SPEED_1000 0x0040
+#define MII_CR_SPEED_100 0x2000
+#define MII_CR_SPEED_10 0x0000
+
+
+/* PHY Status Register */
+#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
+#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
+#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
+#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
+#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
+#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
+
+/* Link partner ability register. */
+#define MII_LPA_SLCT 0x001f /* Same as advertise selector */
+#define MII_LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
+#define MII_LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
+#define MII_LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
+#define MII_LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
+#define MII_LPA_100BASE4 0x0200 /* 100BASE-T4 */
+#define MII_LPA_PAUSE 0x0400 /* PAUSE */
+#define MII_LPA_ASYPAUSE 0x0800 /* Asymmetrical PAUSE */
+#define MII_LPA_RFAULT 0x2000 /* Link partner faulted */
+#define MII_LPA_LPACK 0x4000 /* Link partner acked us */
+#define MII_LPA_NPAGE 0x8000 /* Next page bit */
+
+/* Autoneg Advertisement Register */
+#define MII_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */
+#define MII_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
+#define MII_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
+#define MII_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
+#define MII_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
+#define MII_AR_100T4_CAPS 0x0200 /* 100T4 Capable */
+#define MII_AR_PAUSE 0x0400 /* Pause operation desired */
+#define MII_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
+#define MII_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */
+#define MII_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */
+#define MII_AR_SPEED_MASK 0x01E0
+#define MII_AR_DEFAULT_CAP_MASK 0x0DE0
+
+/* 1000BASE-T Control Register */
+#define MII_AT001_CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
+#define MII_AT001_CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
+#define MII_AT001_CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */
+/* 0=DTE device */
+#define MII_AT001_CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */
+/* 0=Configure PHY as Slave */
+#define MII_AT001_CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */
+/* 0=Automatic Master/Slave config */
+#define MII_AT001_CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
+#define MII_AT001_CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */
+#define MII_AT001_CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */
+#define MII_AT001_CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */
+#define MII_AT001_CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */
+#define MII_AT001_CR_1000T_SPEED_MASK 0x0300
+#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK 0x0300
+
+/* 1000BASE-T Status Register */
+#define MII_AT001_SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */
+#define MII_AT001_SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */
+#define MII_AT001_SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
+#define MII_AT001_SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */
+#define MII_AT001_SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */
+#define MII_AT001_SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */
+#define MII_AT001_SR_1000T_REMOTE_RX_STATUS_SHIFT 12
+#define MII_AT001_SR_1000T_LOCAL_RX_STATUS_SHIFT 13
+
+/* Extended Status Register */
+#define MII_AT001_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
+#define MII_AT001_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
+#define MII_AT001_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
+#define MII_AT001_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
+
+/* AT001 PHY Specific Control Register */
+#define MII_AT001_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */
+#define MII_AT001_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */
+#define MII_AT001_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */
+#define MII_AT001_PSCR_MAC_POWERDOWN 0x0008
+#define MII_AT001_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low,
+ * 0=CLK125 toggling
+ */
+#define MII_AT001_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */
+/* Manual MDI configuration */
+#define MII_AT001_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */
+#define MII_AT001_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover,
+ * 100BASE-TX/10BASE-T:
+ * MDI Mode
+ */
+#define MII_AT001_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled
+ * all speeds.
+ */
+#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE 0x0080
+/* 1=Enable Extended 10BASE-T distance
+ * (Lower 10BASE-T RX Threshold)
+ * 0=Normal 10BASE-T RX Threshold */
+#define MII_AT001_PSCR_MII_5BIT_ENABLE 0x0100
+/* 1=5-Bit interface in 100BASE-TX
+ * 0=MII interface in 100BASE-TX */
+#define MII_AT001_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */
+#define MII_AT001_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */
+#define MII_AT001_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
+#define MII_AT001_PSCR_POLARITY_REVERSAL_SHIFT 1
+#define MII_AT001_PSCR_AUTO_X_MODE_SHIFT 5
+#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
+/* AT001 PHY Specific Status Register */
+#define MII_AT001_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */
+#define MII_AT001_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */
+#define MII_AT001_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */
+#define MII_AT001_PSSR_10MBS 0x0000 /* 00=10Mbs */
+#define MII_AT001_PSSR_100MBS 0x4000 /* 01=100Mbs */
+#define MII_AT001_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
+
+#endif /*_ATHL1E_HW_H_*/
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
new file mode 100644
index 00000000000..35264c244cf
--- /dev/null
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -0,0 +1,2599 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "atl1e.h"
+
+#define DRV_VERSION "1.0.0.7-NAPI"
+
+char atl1e_driver_name[] = "ATL1E";
+char atl1e_driver_version[] = DRV_VERSION;
+#define PCI_DEVICE_ID_ATTANSIC_L1E 0x1026
+/*
+ * atl1e_pci_tbl - PCI Device ID Table
+ *
+ * Wildcard entries (PCI_ANY_ID) should come last
+ * Last entry must be all 0s
+ *
+ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
+ * Class, Class Mask, private data (not used) }
+ */
+static struct pci_device_id atl1e_pci_tbl[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1E)},
+ /* required last entry */
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, atl1e_pci_tbl);
+
+MODULE_AUTHOR("Atheros Corporation, <xiong.huang@atheros.com>, Jie Yang <jie.yang@atheros.com>");
+MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+static inline void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter);
+
+static const u16
+atl1e_rx_page_vld_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] =
+{
+ {REG_HOST_RXF0_PAGE0_VLD, REG_HOST_RXF0_PAGE1_VLD},
+ {REG_HOST_RXF1_PAGE0_VLD, REG_HOST_RXF1_PAGE1_VLD},
+ {REG_HOST_RXF2_PAGE0_VLD, REG_HOST_RXF2_PAGE1_VLD},
+ {REG_HOST_RXF3_PAGE0_VLD, REG_HOST_RXF3_PAGE1_VLD}
+};
+
+static const u16 atl1e_rx_page_hi_addr_regs[AT_MAX_RECEIVE_QUEUE] =
+{
+ REG_RXF0_BASE_ADDR_HI,
+ REG_RXF1_BASE_ADDR_HI,
+ REG_RXF2_BASE_ADDR_HI,
+ REG_RXF3_BASE_ADDR_HI
+};
+
+static const u16
+atl1e_rx_page_lo_addr_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] =
+{
+ {REG_HOST_RXF0_PAGE0_LO, REG_HOST_RXF0_PAGE1_LO},
+ {REG_HOST_RXF1_PAGE0_LO, REG_HOST_RXF1_PAGE1_LO},
+ {REG_HOST_RXF2_PAGE0_LO, REG_HOST_RXF2_PAGE1_LO},
+ {REG_HOST_RXF3_PAGE0_LO, REG_HOST_RXF3_PAGE1_LO}
+};
+
+static const u16
+atl1e_rx_page_write_offset_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] =
+{
+ {REG_HOST_RXF0_MB0_LO, REG_HOST_RXF0_MB1_LO},
+ {REG_HOST_RXF1_MB0_LO, REG_HOST_RXF1_MB1_LO},
+ {REG_HOST_RXF2_MB0_LO, REG_HOST_RXF2_MB1_LO},
+ {REG_HOST_RXF3_MB0_LO, REG_HOST_RXF3_MB1_LO}
+};
+
+static const u16 atl1e_pay_load_size[] = {
+ 128, 256, 512, 1024, 2048, 4096,
+};
+
+/*
+ * atl1e_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_enable(struct atl1e_adapter *adapter)
+{
+ if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
+ AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+ AT_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK);
+ AT_WRITE_FLUSH(&adapter->hw);
+ }
+}
+
+/*
+ * atl1e_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_disable(struct atl1e_adapter *adapter)
+{
+ atomic_inc(&adapter->irq_sem);
+ AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
+ AT_WRITE_FLUSH(&adapter->hw);
+ synchronize_irq(adapter->pdev->irq);
+}
+
+/*
+ * atl1e_irq_reset - reset interrupt confiure on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_reset(struct atl1e_adapter *adapter)
+{
+ atomic_set(&adapter->irq_sem, 0);
+ AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+ AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
+ AT_WRITE_FLUSH(&adapter->hw);
+}
+
+/*
+ * atl1e_phy_config - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1e_phy_config(unsigned long data)
+{
+ struct atl1e_adapter *adapter = (struct atl1e_adapter *) data;
+ struct atl1e_hw *hw = &adapter->hw;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->mdio_lock, flags);
+ atl1e_restart_autoneg(hw);
+ spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+}
+
+void atl1e_reinit_locked(struct atl1e_adapter *adapter)
+{
+
+ WARN_ON(in_interrupt());
+ while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+ msleep(1);
+ atl1e_down(adapter);
+ atl1e_up(adapter);
+ clear_bit(__AT_RESETTING, &adapter->flags);
+}
+
+static void atl1e_reset_task(struct work_struct *work)
+{
+ struct atl1e_adapter *adapter;
+ adapter = container_of(work, struct atl1e_adapter, reset_task);
+
+ atl1e_reinit_locked(adapter);
+}
+
+static int atl1e_check_link(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ int err = 0;
+ u16 speed, duplex, phy_data;
+
+ /* MII_BMSR must read twise */
+ atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
+ atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
+ if ((phy_data & BMSR_LSTATUS) == 0) {
+ /* link down */
+ if (netif_carrier_ok(netdev)) { /* old link state: Up */
+ u32 value;
+ /* disable rx */
+ value = AT_READ_REG(hw, REG_MAC_CTRL);
+ value &= ~MAC_CTRL_RX_EN;
+ AT_WRITE_REG(hw, REG_MAC_CTRL, value);
+ adapter->link_speed = SPEED_0;
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+ } else {
+ /* Link Up */
+ err = atl1e_get_speed_and_duplex(hw, &speed, &duplex);
+ if (unlikely(err))
+ return err;
+
+ /* link result is our setting */
+ if (adapter->link_speed != speed ||
+ adapter->link_duplex != duplex) {
+ adapter->link_speed = speed;
+ adapter->link_duplex = duplex;
+ atl1e_setup_mac_ctrl(adapter);
+ dev_info(&pdev->dev,
+ "%s: %s NIC Link is Up<%d Mbps %s>\n",
+ atl1e_driver_name, netdev->name,
+ adapter->link_speed,
+ adapter->link_duplex == FULL_DUPLEX ?
+ "Full Duplex" : "Half Duplex");
+ }
+
+ if (!netif_carrier_ok(netdev)) {
+ /* Link down -> Up */
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
+ }
+ }
+ return 0;
+}
+
+/*
+ * atl1e_link_chg_task - deal with link change event Out of interrupt context
+ * @netdev: network interface device structure
+ */
+static void atl1e_link_chg_task(struct work_struct *work)
+{
+ struct atl1e_adapter *adapter;
+ unsigned long flags;
+
+ adapter = container_of(work, struct atl1e_adapter, link_chg_task);
+ spin_lock_irqsave(&adapter->mdio_lock, flags);
+ atl1e_check_link(adapter);
+ spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+}
+
+static void atl1e_link_chg_event(struct atl1e_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ u16 phy_data = 0;
+ u16 link_up = 0;
+
+ spin_lock(&adapter->mdio_lock);
+ atl1e_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+ atl1e_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+ spin_unlock(&adapter->mdio_lock);
+ link_up = phy_data & BMSR_LSTATUS;
+ /* notify upper layer link down ASAP */
+ if (!link_up) {
+ if (netif_carrier_ok(netdev)) {
+ /* old link state: Up */
+ dev_info(&pdev->dev, "%s: %s NIC Link is Down\n",
+ atl1e_driver_name, netdev->name);
+ adapter->link_speed = SPEED_0;
+ netif_stop_queue(netdev);
+ }
+ }
+ schedule_work(&adapter->link_chg_task);
+}
+
+static void atl1e_del_timer(struct atl1e_adapter *adapter)
+{
+ del_timer_sync(&adapter->phy_config_timer);
+}
+
+static void atl1e_cancel_work(struct atl1e_adapter *adapter)
+{
+ cancel_work_sync(&adapter->reset_task);
+ cancel_work_sync(&adapter->link_chg_task);
+}
+
+/*
+ * atl1e_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ */
+static void atl1e_tx_timeout(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ /* Do the reset outside of interrupt context */
+ schedule_work(&adapter->reset_task);
+}
+
+/*
+ * atl1e_set_multi - Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated. This routine is
+ * responsible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ */
+static void atl1e_set_multi(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw *hw = &adapter->hw;
+ struct dev_mc_list *mc_ptr;
+ u32 mac_ctrl_data = 0;
+ u32 hash_value;
+
+ /* Check for Promiscuous and All Multicast modes */
+ mac_ctrl_data = AT_READ_REG(hw, REG_MAC_CTRL);
+
+ if (netdev->flags & IFF_PROMISC) {
+ mac_ctrl_data |= MAC_CTRL_PROMIS_EN;
+ } else if (netdev->flags & IFF_ALLMULTI) {
+ mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;
+ mac_ctrl_data &= ~MAC_CTRL_PROMIS_EN;
+ } else {
+ mac_ctrl_data &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+ }
+
+ AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+
+ /* clear the old settings from the multicast hash table */
+ AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+ AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+ /* comoute mc addresses' hash value ,and put it into hash table */
+ for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
+ hash_value = atl1e_hash_mc_addr(hw, mc_ptr->dmi_addr);
+ atl1e_hash_set(hw, hash_value);
+ }
+}
+
+static void atl1e_vlan_rx_register(struct net_device *netdev,
+ struct vlan_group *grp)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct pci_dev *pdev = adapter->pdev;
+ u32 mac_ctrl_data = 0;
+
+ dev_dbg(&pdev->dev, "atl1e_vlan_rx_register\n");
+
+ atl1e_irq_disable(adapter);
+
+ adapter->vlgrp = grp;
+ mac_ctrl_data = AT_READ_REG(&adapter->hw, REG_MAC_CTRL);
+
+ if (grp) {
+ /* enable VLAN tag insert/strip */
+ mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+ } else {
+ /* disable VLAN tag insert/strip */
+ mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN;
+ }
+
+ AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data);
+ atl1e_irq_enable(adapter);
+}
+
+static void atl1e_restore_vlan(struct atl1e_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+
+ dev_dbg(&pdev->dev, "atl1e_restore_vlan !");
+ atl1e_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+}
+/*
+ * atl1e_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1e_set_mac_addr(struct net_device *netdev, void *p)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ if (netif_running(netdev))
+ return -EBUSY;
+
+ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+ memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+
+ atl1e_hw_set_mac_addr(&adapter->hw);
+
+ return 0;
+}
+
+/*
+ * atl1e_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1e_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ int old_mtu = netdev->mtu;
+ int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+
+ if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
+ (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+ dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
+ return -EINVAL;
+ }
+ /* set MTU */
+ if (old_mtu != new_mtu && netif_running(netdev)) {
+ while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+ msleep(1);
+ netdev->mtu = new_mtu;
+ adapter->hw.max_frame_size = new_mtu;
+ adapter->hw.rx_jumbo_th = (max_frame + 7) >> 3;
+ atl1e_down(adapter);
+ atl1e_up(adapter);
+ clear_bit(__AT_RESETTING, &adapter->flags);
+ }
+ return 0;
+}
+
+/*
+ * caller should hold mdio_lock
+ */
+static int atl1e_mdio_read(struct net_device *netdev, int phy_id, int reg_num)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ u16 result;
+
+ atl1e_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result);
+ return result;
+}
+
+static void atl1e_mdio_write(struct net_device *netdev, int phy_id,
+ int reg_num, int val)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ atl1e_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val);
+}
+
+/*
+ * atl1e_mii_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1e_mii_ioctl(struct net_device *netdev,
+ struct ifreq *ifr, int cmd)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct pci_dev *pdev = adapter->pdev;
+ struct mii_ioctl_data *data = if_mii(ifr);
+ unsigned long flags;
+ int retval = 0;
+
+ if (!netif_running(netdev))
+ return -EINVAL;
+
+ spin_lock_irqsave(&adapter->mdio_lock, flags);
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ data->phy_id = 0;
+ break;
+
+ case SIOCGMIIREG:
+ if (!capable(CAP_NET_ADMIN)) {
+ retval = -EPERM;
+ goto out;
+ }
+ if (atl1e_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+ &data->val_out)) {
+ retval = -EIO;
+ goto out;
+ }
+ break;
+
+ case SIOCSMIIREG:
+ if (!capable(CAP_NET_ADMIN)) {
+ retval = -EPERM;
+ goto out;
+ }
+ if (data->reg_num & ~(0x1F)) {
+ retval = -EFAULT;
+ goto out;
+ }
+
+ dev_dbg(&pdev->dev, "<atl1e_mii_ioctl> write %x %x",
+ data->reg_num, data->val_in);
+ if (atl1e_write_phy_reg(&adapter->hw,
+ data->reg_num, data->val_in)) {
+ retval = -EIO;
+ goto out;
+ }
+ break;
+
+ default:
+ retval = -EOPNOTSUPP;
+ break;
+ }
+out:
+ spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+ return retval;
+
+}
+
+/*
+ * atl1e_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ case SIOCGMIIREG:
+ case SIOCSMIIREG:
+ return atl1e_mii_ioctl(netdev, ifr, cmd);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static void atl1e_setup_pcicmd(struct pci_dev *pdev)
+{
+ u16 cmd;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+ cmd &= ~(PCI_COMMAND_INTX_DISABLE | PCI_COMMAND_IO);
+ cmd |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+
+ /*
+ * some motherboards BIOS(PXE/EFI) driver may set PME
+ * while they transfer control to OS (Windows/Linux)
+ * so we should clear this bit before NIC work normally
+ */
+ pci_write_config_dword(pdev, REG_PM_CTRLSTAT, 0);
+ msleep(1);
+}
+
+/*
+ * atl1e_alloc_queues - Allocate memory for all rings
+ * @adapter: board private structure to initialize
+ *
+ */
+static int __devinit atl1e_alloc_queues(struct atl1e_adapter *adapter)
+{
+ return 0;
+}
+
+/*
+ * atl1e_sw_init - Initialize general software structures (struct atl1e_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * atl1e_sw_init initializes the Adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ */
+static int __devinit atl1e_sw_init(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = &adapter->hw;
+ struct pci_dev *pdev = adapter->pdev;
+ u32 phy_status_data = 0;
+
+ adapter->wol = 0;
+ adapter->link_speed = SPEED_0; /* hardware init */
+ adapter->link_duplex = FULL_DUPLEX;
+ adapter->num_rx_queues = 1;
+
+ /* PCI config space info */
+ hw->vendor_id = pdev->vendor;
+ hw->device_id = pdev->device;
+ hw->subsystem_vendor_id = pdev->subsystem_vendor;
+ hw->subsystem_id = pdev->subsystem_device;
+
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
+ pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
+
+ phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS);
+ /* nic type */
+ if (hw->revision_id >= 0xF0) {
+ hw->nic_type = athr_l2e_revB;
+ } else {
+ if (phy_status_data & PHY_STATUS_100M)
+ hw->nic_type = athr_l1e;
+ else
+ hw->nic_type = athr_l2e_revA;
+ }
+
+ phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS);
+
+ if (phy_status_data & PHY_STATUS_EMI_CA)
+ hw->emi_ca = true;
+ else
+ hw->emi_ca = false;
+
+ hw->phy_configured = false;
+ hw->preamble_len = 7;
+ hw->max_frame_size = adapter->netdev->mtu;
+ hw->rx_jumbo_th = (hw->max_frame_size + ETH_HLEN +
+ VLAN_HLEN + ETH_FCS_LEN + 7) >> 3;
+
+ hw->rrs_type = atl1e_rrs_disable;
+ hw->indirect_tab = 0;
+ hw->base_cpu = 0;
+
+ /* need confirm */
+
+ hw->ict = 50000; /* 100ms */
+ hw->smb_timer = 200000; /* 200ms */
+ hw->tpd_burst = 5;
+ hw->rrd_thresh = 1;
+ hw->tpd_thresh = adapter->tx_ring.count / 2;
+ hw->rx_count_down = 4; /* 2us resolution */
+ hw->tx_count_down = hw->imt * 4 / 3;
+ hw->dmar_block = atl1e_dma_req_1024;
+ hw->dmaw_block = atl1e_dma_req_1024;
+ hw->dmar_dly_cnt = 15;
+ hw->dmaw_dly_cnt = 4;
+
+ if (atl1e_alloc_queues(adapter)) {
+ dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
+ return -ENOMEM;
+ }
+
+ atomic_set(&adapter->irq_sem, 1);
+ spin_lock_init(&adapter->mdio_lock);
+ spin_lock_init(&adapter->tx_lock);
+
+ set_bit(__AT_DOWN, &adapter->flags);
+
+ return 0;
+}
+
+/*
+ * atl1e_clean_tx_ring - Free Tx-skb
+ * @adapter: board private structure
+ */
+static void atl1e_clean_tx_ring(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = (struct atl1e_tx_ring *)
+ &adapter->tx_ring;
+ struct atl1e_tx_buffer *tx_buffer = NULL;
+ struct pci_dev *pdev = adapter->pdev;
+ u16 index, ring_count;
+
+ if (tx_ring->desc == NULL || tx_ring->tx_buffer == NULL)
+ return;
+
+ ring_count = tx_ring->count;
+ /* first unmmap dma */
+ for (index = 0; index < ring_count; index++) {
+ tx_buffer = &tx_ring->tx_buffer[index];
+ if (tx_buffer->dma) {
+ pci_unmap_page(pdev, tx_buffer->dma,
+ tx_buffer->length, PCI_DMA_TODEVICE);
+ tx_buffer->dma = 0;
+ }
+ }
+ /* second free skb */
+ for (index = 0; index < ring_count; index++) {
+ tx_buffer = &tx_ring->tx_buffer[index];
+ if (tx_buffer->skb) {
+ dev_kfree_skb_any(tx_buffer->skb);
+ tx_buffer->skb = NULL;
+ }
+ }
+ /* Zero out Tx-buffers */
+ memset(tx_ring->desc, 0, sizeof(struct atl1e_tpd_desc) *
+ ring_count);
+ memset(tx_ring->tx_buffer, 0, sizeof(struct atl1e_tx_buffer) *
+ ring_count);
+}
+
+/*
+ * atl1e_clean_rx_ring - Free rx-reservation skbs
+ * @adapter: board private structure
+ */
+static void atl1e_clean_rx_ring(struct atl1e_adapter *adapter)
+{
+ struct atl1e_rx_ring *rx_ring =
+ (struct atl1e_rx_ring *)&adapter->rx_ring;
+ struct atl1e_rx_page_desc *rx_page_desc = rx_ring->rx_page_desc;
+ u16 i, j;
+
+
+ if (adapter->ring_vir_addr == NULL)
+ return;
+ /* Zero out the descriptor ring */
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ if (rx_page_desc[i].rx_page[j].addr != NULL) {
+ memset(rx_page_desc[i].rx_page[j].addr, 0,
+ rx_ring->real_page_size);
+ }
+ }
+ }
+}
+
+static void atl1e_cal_ring_size(struct atl1e_adapter *adapter, u32 *ring_size)
+{
+ *ring_size = ((u32)(adapter->tx_ring.count *
+ sizeof(struct atl1e_tpd_desc) + 7
+ /* tx ring, qword align */
+ + adapter->rx_ring.real_page_size * AT_PAGE_NUM_PER_QUEUE *
+ adapter->num_rx_queues + 31
+ /* rx ring, 32 bytes align */
+ + (1 + AT_PAGE_NUM_PER_QUEUE * adapter->num_rx_queues) *
+ sizeof(u32) + 3));
+ /* tx, rx cmd, dword align */
+}
+
+static void atl1e_init_ring_resources(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = NULL;
+ struct atl1e_rx_ring *rx_ring = NULL;
+
+ tx_ring = &adapter->tx_ring;
+ rx_ring = &adapter->rx_ring;
+
+ rx_ring->real_page_size = adapter->rx_ring.page_size
+ + adapter->hw.max_frame_size
+ + ETH_HLEN + VLAN_HLEN
+ + ETH_FCS_LEN;
+ rx_ring->real_page_size = roundup(rx_ring->real_page_size, 32);
+ atl1e_cal_ring_size(adapter, &adapter->ring_size);
+
+ adapter->ring_vir_addr = NULL;
+ adapter->rx_ring.desc = NULL;
+ rwlock_init(&adapter->tx_ring.tx_lock);
+
+ return;
+}
+
+/*
+ * Read / Write Ptr Initialize:
+ */
+static void atl1e_init_ring_ptrs(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = NULL;
+ struct atl1e_rx_ring *rx_ring = NULL;
+ struct atl1e_rx_page_desc *rx_page_desc = NULL;
+ int i, j;
+
+ tx_ring = &adapter->tx_ring;
+ rx_ring = &adapter->rx_ring;
+ rx_page_desc = rx_ring->rx_page_desc;
+
+ tx_ring->next_to_use = 0;
+ atomic_set(&tx_ring->next_to_clean, 0);
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ rx_page_desc[i].rx_using = 0;
+ rx_page_desc[i].rx_nxseq = 0;
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ *rx_page_desc[i].rx_page[j].write_offset_addr = 0;
+ rx_page_desc[i].rx_page[j].read_offset = 0;
+ }
+ }
+}
+
+/*
+ * atl1e_free_ring_resources - Free Tx / RX descriptor Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ */
+static void atl1e_free_ring_resources(struct atl1e_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+
+ atl1e_clean_tx_ring(adapter);
+ atl1e_clean_rx_ring(adapter);
+
+ if (adapter->ring_vir_addr) {
+ pci_free_consistent(pdev, adapter->ring_size,
+ adapter->ring_vir_addr, adapter->ring_dma);
+ adapter->ring_vir_addr = NULL;
+ }
+
+ if (adapter->tx_ring.tx_buffer) {
+ kfree(adapter->tx_ring.tx_buffer);
+ adapter->tx_ring.tx_buffer = NULL;
+ }
+}
+
+/*
+ * atl1e_setup_mem_resources - allocate Tx / RX descriptor resources
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ */
+static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ struct atl1e_tx_ring *tx_ring;
+ struct atl1e_rx_ring *rx_ring;
+ struct atl1e_rx_page_desc *rx_page_desc;
+ int size, i, j;
+ u32 offset = 0;
+ int err = 0;
+
+ if (adapter->ring_vir_addr != NULL)
+ return 0; /* alloced already */
+
+ tx_ring = &adapter->tx_ring;
+ rx_ring = &adapter->rx_ring;
+
+ /* real ring DMA buffer */
+
+ size = adapter->ring_size;
+ adapter->ring_vir_addr = pci_alloc_consistent(pdev,
+ adapter->ring_size, &adapter->ring_dma);
+
+ if (adapter->ring_vir_addr == NULL) {
+ dev_err(&pdev->dev, "pci_alloc_consistent failed, "
+ "size = D%d", size);
+ return -ENOMEM;
+ }
+
+ memset(adapter->ring_vir_addr, 0, adapter->ring_size);
+
+ rx_page_desc = rx_ring->rx_page_desc;
+
+ /* Init TPD Ring */
+ tx_ring->dma = roundup(adapter->ring_dma, 8);
+ offset = tx_ring->dma - adapter->ring_dma;
+ tx_ring->desc = (struct atl1e_tpd_desc *)
+ (adapter->ring_vir_addr + offset);
+ size = sizeof(struct atl1e_tx_buffer) * (tx_ring->count);
+ tx_ring->tx_buffer = kzalloc(size, GFP_KERNEL);
+ if (tx_ring->tx_buffer == NULL) {
+ dev_err(&pdev->dev, "kzalloc failed , size = D%d", size);
+ err = -ENOMEM;
+ goto failed;
+ }
+
+ /* Init RXF-Pages */
+ offset += (sizeof(struct atl1e_tpd_desc) * tx_ring->count);
+ offset = roundup(offset, 32);
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ rx_page_desc[i].rx_page[j].dma =
+ adapter->ring_dma + offset;
+ rx_page_desc[i].rx_page[j].addr =
+ adapter->ring_vir_addr + offset;
+ offset += rx_ring->real_page_size;
+ }
+ }
+
+ /* Init CMB dma address */
+ tx_ring->cmb_dma = adapter->ring_dma + offset;
+ tx_ring->cmb = (u32 *)(adapter->ring_vir_addr + offset);
+ offset += sizeof(u32);
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ rx_page_desc[i].rx_page[j].write_offset_dma =
+ adapter->ring_dma + offset;
+ rx_page_desc[i].rx_page[j].write_offset_addr =
+ adapter->ring_vir_addr + offset;
+ offset += sizeof(u32);
+ }
+ }
+
+ if (unlikely(offset > adapter->ring_size)) {
+ dev_err(&pdev->dev, "offset(%d) > ring size(%d) !!\n",
+ offset, adapter->ring_size);
+ err = -1;
+ goto failed;
+ }
+
+ return 0;
+failed:
+ if (adapter->ring_vir_addr != NULL) {
+ pci_free_consistent(pdev, adapter->ring_size,
+ adapter->ring_vir_addr, adapter->ring_dma);
+ adapter->ring_vir_addr = NULL;
+ }
+ return err;
+}
+
+static inline void atl1e_configure_des_ring(const struct atl1e_adapter *adapter)
+{
+
+ struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
+ struct atl1e_rx_ring *rx_ring =
+ (struct atl1e_rx_ring *)&adapter->rx_ring;
+ struct atl1e_tx_ring *tx_ring =
+ (struct atl1e_tx_ring *)&adapter->tx_ring;
+ struct atl1e_rx_page_desc *rx_page_desc = NULL;
+ int i, j;
+
+ AT_WRITE_REG(hw, REG_DESC_BASE_ADDR_HI,
+ (u32)((adapter->ring_dma & AT_DMA_HI_ADDR_MASK) >> 32));
+ AT_WRITE_REG(hw, REG_TPD_BASE_ADDR_LO,
+ (u32)((tx_ring->dma) & AT_DMA_LO_ADDR_MASK));
+ AT_WRITE_REG(hw, REG_TPD_RING_SIZE, (u16)(tx_ring->count));
+ AT_WRITE_REG(hw, REG_HOST_TX_CMB_LO,
+ (u32)((tx_ring->cmb_dma) & AT_DMA_LO_ADDR_MASK));
+
+ rx_page_desc = rx_ring->rx_page_desc;
+ /* RXF Page Physical address / Page Length */
+ for (i = 0; i < AT_MAX_RECEIVE_QUEUE; i++) {
+ AT_WRITE_REG(hw, atl1e_rx_page_hi_addr_regs[i],
+ (u32)((adapter->ring_dma &
+ AT_DMA_HI_ADDR_MASK) >> 32));
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ u32 page_phy_addr;
+ u32 offset_phy_addr;
+
+ page_phy_addr = rx_page_desc[i].rx_page[j].dma;
+ offset_phy_addr =
+ rx_page_desc[i].rx_page[j].write_offset_dma;
+
+ AT_WRITE_REG(hw, atl1e_rx_page_lo_addr_regs[i][j],
+ page_phy_addr & AT_DMA_LO_ADDR_MASK);
+ AT_WRITE_REG(hw, atl1e_rx_page_write_offset_regs[i][j],
+ offset_phy_addr & AT_DMA_LO_ADDR_MASK);
+ AT_WRITE_REGB(hw, atl1e_rx_page_vld_regs[i][j], 1);
+ }
+ }
+ /* Page Length */
+ AT_WRITE_REG(hw, REG_HOST_RXFPAGE_SIZE, rx_ring->page_size);
+ /* Load all of base address above */
+ AT_WRITE_REG(hw, REG_LOAD_PTR, 1);
+
+ return;
+}
+
+static inline void atl1e_configure_tx(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
+ u32 dev_ctrl_data = 0;
+ u32 max_pay_load = 0;
+ u32 jumbo_thresh = 0;
+ u32 extra_size = 0; /* Jumbo frame threshold in QWORD unit */
+
+ /* configure TXQ param */
+ if (hw->nic_type != athr_l2e_revB) {
+ extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
+ if (hw->max_frame_size <= 1500) {
+ jumbo_thresh = hw->max_frame_size + extra_size;
+ } else if (hw->max_frame_size < 6*1024) {
+ jumbo_thresh =
+ (hw->max_frame_size + extra_size) * 2 / 3;
+ } else {
+ jumbo_thresh = (hw->max_frame_size + extra_size) / 2;
+ }
+ AT_WRITE_REG(hw, REG_TX_EARLY_TH, (jumbo_thresh + 7) >> 3);
+ }
+
+ dev_ctrl_data = AT_READ_REG(hw, REG_DEVICE_CTRL);
+
+ max_pay_load = ((dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT)) &
+ DEVICE_CTRL_MAX_PAYLOAD_MASK;
+
+ hw->dmaw_block = min(max_pay_load, hw->dmaw_block);
+
+ max_pay_load = ((dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT)) &
+ DEVICE_CTRL_MAX_RREQ_SZ_MASK;
+ hw->dmar_block = min(max_pay_load, hw->dmar_block);
+
+ if (hw->nic_type != athr_l2e_revB)
+ AT_WRITE_REGW(hw, REG_TXQ_CTRL + 2,
+ atl1e_pay_load_size[hw->dmar_block]);
+ /* enable TXQ */
+ AT_WRITE_REGW(hw, REG_TXQ_CTRL,
+ (((u16)hw->tpd_burst & TXQ_CTRL_NUM_TPD_BURST_MASK)
+ << TXQ_CTRL_NUM_TPD_BURST_SHIFT)
+ | TXQ_CTRL_ENH_MODE | TXQ_CTRL_EN);
+ return;
+}
+
+static inline void atl1e_configure_rx(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
+ u32 rxf_len = 0;
+ u32 rxf_low = 0;
+ u32 rxf_high = 0;
+ u32 rxf_thresh_data = 0;
+ u32 rxq_ctrl_data = 0;
+
+ if (hw->nic_type != athr_l2e_revB) {
+ AT_WRITE_REGW(hw, REG_RXQ_JMBOSZ_RRDTIM,
+ (u16)((hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK) <<
+ RXQ_JMBOSZ_TH_SHIFT |
+ (1 & RXQ_JMBO_LKAH_MASK) <<
+ RXQ_JMBO_LKAH_SHIFT));
+
+ rxf_len = AT_READ_REG(hw, REG_SRAM_RXF_LEN);
+ rxf_high = rxf_len * 4 / 5;
+ rxf_low = rxf_len / 5;
+ rxf_thresh_data = ((rxf_high & RXQ_RXF_PAUSE_TH_HI_MASK)
+ << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+ ((rxf_low & RXQ_RXF_PAUSE_TH_LO_MASK)
+ << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+
+ AT_WRITE_REG(hw, REG_RXQ_RXF_PAUSE_THRESH, rxf_thresh_data);
+ }
+
+ /* RRS */
+ AT_WRITE_REG(hw, REG_IDT_TABLE, hw->indirect_tab);
+ AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, hw->base_cpu);
+
+ if (hw->rrs_type & atl1e_rrs_ipv4)
+ rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV4;
+
+ if (hw->rrs_type & atl1e_rrs_ipv4_tcp)
+ rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV4_TCP;
+
+ if (hw->rrs_type & atl1e_rrs_ipv6)
+ rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV6;
+
+ if (hw->rrs_type & atl1e_rrs_ipv6_tcp)
+ rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV6_TCP;
+
+ if (hw->rrs_type != atl1e_rrs_disable)
+ rxq_ctrl_data |=
+ (RXQ_CTRL_HASH_ENABLE | RXQ_CTRL_RSS_MODE_MQUESINT);
+
+ rxq_ctrl_data |= RXQ_CTRL_IPV6_XSUM_VERIFY_EN | RXQ_CTRL_PBA_ALIGN_32 |
+ RXQ_CTRL_CUT_THRU_EN | RXQ_CTRL_EN;
+
+ AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data);
+ return;
+}
+
+static inline void atl1e_configure_dma(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = &adapter->hw;
+ u32 dma_ctrl_data = 0;
+
+ dma_ctrl_data = DMA_CTRL_RXCMB_EN;
+ dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+ << DMA_CTRL_DMAR_BURST_LEN_SHIFT;
+ dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
+ << DMA_CTRL_DMAW_BURST_LEN_SHIFT;
+ dma_ctrl_data |= DMA_CTRL_DMAR_REQ_PRI | DMA_CTRL_DMAR_OUT_ORDER;
+ dma_ctrl_data |= (((u32)hw->dmar_dly_cnt) & DMA_CTRL_DMAR_DLY_CNT_MASK)
+ << DMA_CTRL_DMAR_DLY_CNT_SHIFT;
+ dma_ctrl_data |= (((u32)hw->dmaw_dly_cnt) & DMA_CTRL_DMAW_DLY_CNT_MASK)
+ << DMA_CTRL_DMAW_DLY_CNT_SHIFT;
+
+ AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data);
+ return;
+}
+
+static inline void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter)
+{
+ u32 value;
+ struct atl1e_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+
+ /* Config MAC CTRL Register */
+ value = MAC_CTRL_TX_EN |
+ MAC_CTRL_RX_EN ;
+
+ if (FULL_DUPLEX == adapter->link_duplex)
+ value |= MAC_CTRL_DUPLX;
+
+ value |= ((u32)((SPEED_1000 == adapter->link_speed) ?
+ MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
+ MAC_CTRL_SPEED_SHIFT);
+ value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+
+ value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+ value |= (((u32)adapter->hw.preamble_len &
+ MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
+
+ if (adapter->vlgrp)
+ value |= MAC_CTRL_RMV_VLAN;
+
+ value |= MAC_CTRL_BC_EN;
+ if (netdev->flags & IFF_PROMISC)
+ value |= MAC_CTRL_PROMIS_EN;
+ if (netdev->flags & IFF_ALLMULTI)
+ value |= MAC_CTRL_MC_ALL_EN;
+
+ AT_WRITE_REG(hw, REG_MAC_CTRL, value);
+}
+
+/*
+ * atl1e_configure - Configure Transmit&Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx /Rx unit of the MAC after a reset.
+ */
+static int atl1e_configure(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = &adapter->hw;
+ struct pci_dev *pdev = adapter->pdev;
+
+ u32 intr_status_data = 0;
+
+ /* clear interrupt status */
+ AT_WRITE_REG(hw, REG_ISR, ~0);
+
+ /* 1. set MAC Address */
+ atl1e_hw_set_mac_addr(hw);
+
+ /* 2. Init the Multicast HASH table done by set_muti */
+
+ /* 3. Clear any WOL status */
+ AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+
+ /* 4. Descripter Ring BaseMem/Length/Read ptr/Write ptr
+ * TPD Ring/SMB/RXF0 Page CMBs, they use the same
+ * High 32bits memory */
+ atl1e_configure_des_ring(adapter);
+
+ /* 5. set Interrupt Moderator Timer */
+ AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER_INIT, hw->imt);
+ AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER2_INIT, hw->imt);
+ AT_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_LED_MODE |
+ MASTER_CTRL_ITIMER_EN | MASTER_CTRL_ITIMER2_EN);
+
+ /* 6. rx/tx threshold to trig interrupt */
+ AT_WRITE_REGW(hw, REG_TRIG_RRD_THRESH, hw->rrd_thresh);
+ AT_WRITE_REGW(hw, REG_TRIG_TPD_THRESH, hw->tpd_thresh);
+ AT_WRITE_REGW(hw, REG_TRIG_RXTIMER, hw->rx_count_down);
+ AT_WRITE_REGW(hw, REG_TRIG_TXTIMER, hw->tx_count_down);
+
+ /* 7. set Interrupt Clear Timer */
+ AT_WRITE_REGW(hw, REG_CMBDISDMA_TIMER, hw->ict);
+
+ /* 8. set MTU */
+ AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN +
+ VLAN_HLEN + ETH_FCS_LEN);
+
+ /* 9. config TXQ early tx threshold */
+ atl1e_configure_tx(adapter);
+
+ /* 10. config RXQ */
+ atl1e_configure_rx(adapter);
+
+ /* 11. config DMA Engine */
+ atl1e_configure_dma(adapter);
+
+ /* 12. smb timer to trig interrupt */
+ AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, hw->smb_timer);
+
+ intr_status_data = AT_READ_REG(hw, REG_ISR);
+ if (unlikely((intr_status_data & ISR_PHY_LINKDOWN) != 0)) {
+ dev_err(&pdev->dev, "atl1e_configure failed,"
+ "PCIE phy link down\n");
+ return -1;
+ }
+
+ AT_WRITE_REG(hw, REG_ISR, 0x7fffffff);
+ return 0;
+}
+
+/*
+ * atl1e_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ *
+ * Returns the address of the device statistics structure.
+ * The statistics are actually updated from the timer callback.
+ */
+static struct net_device_stats *atl1e_get_stats(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw_stats *hw_stats = &adapter->hw_stats;
+ struct net_device_stats *net_stats = &adapter->net_stats;
+
+ net_stats->rx_packets = hw_stats->rx_ok;
+ net_stats->tx_packets = hw_stats->tx_ok;
+ net_stats->rx_bytes = hw_stats->rx_byte_cnt;
+ net_stats->tx_bytes = hw_stats->tx_byte_cnt;
+ net_stats->multicast = hw_stats->rx_mcast;
+ net_stats->collisions = hw_stats->tx_1_col +
+ hw_stats->tx_2_col * 2 +
+ hw_stats->tx_late_col + hw_stats->tx_abort_col;
+
+ net_stats->rx_errors = hw_stats->rx_frag + hw_stats->rx_fcs_err +
+ hw_stats->rx_len_err + hw_stats->rx_sz_ov +
+ hw_stats->rx_rrd_ov + hw_stats->rx_align_err;
+ net_stats->rx_fifo_errors = hw_stats->rx_rxf_ov;
+ net_stats->rx_length_errors = hw_stats->rx_len_err;
+ net_stats->rx_crc_errors = hw_stats->rx_fcs_err;
+ net_stats->rx_frame_errors = hw_stats->rx_align_err;
+ net_stats->rx_over_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov;
+
+ net_stats->rx_missed_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov;
+
+ net_stats->tx_errors = hw_stats->tx_late_col + hw_stats->tx_abort_col +
+ hw_stats->tx_underrun + hw_stats->tx_trunc;
+ net_stats->tx_fifo_errors = hw_stats->tx_underrun;
+ net_stats->tx_aborted_errors = hw_stats->tx_abort_col;
+ net_stats->tx_window_errors = hw_stats->tx_late_col;
+
+ return &adapter->net_stats;
+}
+
+static void atl1e_update_hw_stats(struct atl1e_adapter *adapter)
+{
+ u16 hw_reg_addr = 0;
+ unsigned long *stats_item = NULL;
+
+ /* update rx status */
+ hw_reg_addr = REG_MAC_RX_STATUS_BIN;
+ stats_item = &adapter->hw_stats.rx_ok;
+ while (hw_reg_addr <= REG_MAC_RX_STATUS_END) {
+ *stats_item += AT_READ_REG(&adapter->hw, hw_reg_addr);
+ stats_item++;
+ hw_reg_addr += 4;
+ }
+ /* update tx status */
+ hw_reg_addr = REG_MAC_TX_STATUS_BIN;
+ stats_item = &adapter->hw_stats.tx_ok;
+ while (hw_reg_addr <= REG_MAC_TX_STATUS_END) {
+ *stats_item += AT_READ_REG(&adapter->hw, hw_reg_addr);
+ stats_item++;
+ hw_reg_addr += 4;
+ }
+}
+
+static inline void atl1e_clear_phy_int(struct atl1e_adapter *adapter)
+{
+ u16 phy_data;
+
+ spin_lock(&adapter->mdio_lock);
+ atl1e_read_phy_reg(&adapter->hw, MII_INT_STATUS, &phy_data);
+ spin_unlock(&adapter->mdio_lock);
+}
+
+static bool atl1e_clean_tx_irq(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = (struct atl1e_tx_ring *)
+ &adapter->tx_ring;
+ struct atl1e_tx_buffer *tx_buffer = NULL;
+ u16 hw_next_to_clean = AT_READ_REGW(&adapter->hw, REG_TPD_CONS_IDX);
+ u16 next_to_clean = atomic_read(&tx_ring->next_to_clean);
+
+ while (next_to_clean != hw_next_to_clean) {
+ tx_buffer = &tx_ring->tx_buffer[next_to_clean];
+ if (tx_buffer->dma) {
+ pci_unmap_page(adapter->pdev, tx_buffer->dma,
+ tx_buffer->length, PCI_DMA_TODEVICE);
+ tx_buffer->dma = 0;
+ }
+
+ if (tx_buffer->skb) {
+ dev_kfree_skb_irq(tx_buffer->skb);
+ tx_buffer->skb = NULL;
+ }
+
+ if (++next_to_clean == tx_ring->count)
+ next_to_clean = 0;
+ }
+
+ atomic_set(&tx_ring->next_to_clean, next_to_clean);
+
+ if (netif_queue_stopped(adapter->netdev) &&
+ netif_carrier_ok(adapter->netdev)) {
+ netif_wake_queue(adapter->netdev);
+ }
+
+ return true;
+}
+
+/*
+ * atl1e_intr - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
+ */
+static irqreturn_t atl1e_intr(int irq, void *data)
+{
+ struct net_device *netdev = data;
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct pci_dev *pdev = adapter->pdev;
+ struct atl1e_hw *hw = &adapter->hw;
+ int max_ints = AT_MAX_INT_WORK;
+ int handled = IRQ_NONE;
+ u32 status;
+
+ do {
+ status = AT_READ_REG(hw, REG_ISR);
+ if ((status & IMR_NORMAL_MASK) == 0 ||
+ (status & ISR_DIS_INT) != 0) {
+ if (max_ints != AT_MAX_INT_WORK)
+ handled = IRQ_HANDLED;
+ break;
+ }
+ /* link event */
+ if (status & ISR_GPHY)
+ atl1e_clear_phy_int(adapter);
+ /* Ack ISR */
+ AT_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT);
+
+ handled = IRQ_HANDLED;
+ /* check if PCIE PHY Link down */
+ if (status & ISR_PHY_LINKDOWN) {
+ dev_err(&pdev->dev,
+ "pcie phy linkdown %x\n", status);
+ if (netif_running(adapter->netdev)) {
+ /* reset MAC */
+ atl1e_irq_reset(adapter);
+ schedule_work(&adapter->reset_task);
+ break;
+ }
+ }
+
+ /* check if DMA read/write error */
+ if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
+ dev_err(&pdev->dev,
+ "PCIE DMA RW error (status = 0x%x)\n",
+ status);
+ atl1e_irq_reset(adapter);
+ schedule_work(&adapter->reset_task);
+ break;
+ }
+
+ if (status & ISR_SMB)
+ atl1e_update_hw_stats(adapter);
+
+ /* link event */
+ if (status & (ISR_GPHY | ISR_MANUAL)) {
+ adapter->net_stats.tx_carrier_errors++;
+ atl1e_link_chg_event(adapter);
+ break;
+ }
+
+ /* transmit event */
+ if (status & ISR_TX_EVENT)
+ atl1e_clean_tx_irq(adapter);
+
+ if (status & ISR_RX_EVENT) {
+ /*
+ * disable rx interrupts, without
+ * the synchronize_irq bit
+ */
+ AT_WRITE_REG(hw, REG_IMR,
+ IMR_NORMAL_MASK & ~ISR_RX_EVENT);
+ AT_WRITE_FLUSH(hw);
+ if (likely(netif_rx_schedule_prep(netdev,
+ &adapter->napi)))
+ __netif_rx_schedule(netdev, &adapter->napi);
+ }
+ } while (--max_ints > 0);
+ /* re-enable Interrupt*/
+ AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+
+ return handled;
+}
+
+static inline void atl1e_rx_checksum(struct atl1e_adapter *adapter,
+ struct sk_buff *skb, struct atl1e_recv_ret_status *prrs)
+{
+ u8 *packet = (u8 *)(prrs + 1);
+ struct iphdr *iph;
+ u16 head_len = ETH_HLEN;
+ u16 pkt_flags;
+ u16 err_flags;
+
+ skb->ip_summed = CHECKSUM_NONE;
+ pkt_flags = prrs->pkt_flag;
+ err_flags = prrs->err_flag;
+ if (((pkt_flags & RRS_IS_IPV4) || (pkt_flags & RRS_IS_IPV6)) &&
+ ((pkt_flags & RRS_IS_TCP) || (pkt_flags & RRS_IS_UDP))) {
+ if (pkt_flags & RRS_IS_IPV4) {
+ if (pkt_flags & RRS_IS_802_3)
+ head_len += 8;
+ iph = (struct iphdr *) (packet + head_len);
+ if (iph->frag_off != 0 && !(pkt_flags & RRS_IS_IP_DF))
+ goto hw_xsum;
+ }
+ if (!(err_flags & (RRS_ERR_IP_CSUM | RRS_ERR_L4_CSUM))) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ return;
+ }
+ }
+
+hw_xsum :
+ return;
+}
+
+static struct atl1e_rx_page *atl1e_get_rx_page(struct atl1e_adapter *adapter,
+ u8 que)
+{
+ struct atl1e_rx_page_desc *rx_page_desc =
+ (struct atl1e_rx_page_desc *) adapter->rx_ring.rx_page_desc;
+ u8 rx_using = rx_page_desc[que].rx_using;
+
+ return (struct atl1e_rx_page *)&(rx_page_desc[que].rx_page[rx_using]);
+}
+
+static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que,
+ int *work_done, int work_to_do)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ struct net_device *netdev = adapter->netdev;
+ struct atl1e_rx_ring *rx_ring = (struct atl1e_rx_ring *)
+ &adapter->rx_ring;
+ struct atl1e_rx_page_desc *rx_page_desc =
+ (struct atl1e_rx_page_desc *) rx_ring->rx_page_desc;
+ struct sk_buff *skb = NULL;
+ struct atl1e_rx_page *rx_page = atl1e_get_rx_page(adapter, que);
+ u32 packet_size, write_offset;
+ struct atl1e_recv_ret_status *prrs;
+
+ write_offset = *(rx_page->write_offset_addr);
+ if (likely(rx_page->read_offset < write_offset)) {
+ do {
+ if (*work_done >= work_to_do)
+ break;
+ (*work_done)++;
+ /* get new packet's rrs */
+ prrs = (struct atl1e_recv_ret_status *) (rx_page->addr +
+ rx_page->read_offset);
+ /* check sequence number */
+ if (prrs->seq_num != rx_page_desc[que].rx_nxseq) {
+ dev_err(&pdev->dev,
+ "rx sequence number"
+ " error (rx=%d) (expect=%d)\n",
+ prrs->seq_num,
+ rx_page_desc[que].rx_nxseq);
+ rx_page_desc[que].rx_nxseq++;
+ /* just for debug use */
+ AT_WRITE_REG(&adapter->hw, REG_DEBUG_DATA0,
+ (((u32)prrs->seq_num) << 16) |
+ rx_page_desc[que].rx_nxseq);
+ goto fatal_err;
+ }
+ rx_page_desc[que].rx_nxseq++;
+
+ /* error packet */
+ if (prrs->pkt_flag & RRS_IS_ERR_FRAME) {
+ if (prrs->err_flag & (RRS_ERR_BAD_CRC |
+ RRS_ERR_DRIBBLE | RRS_ERR_CODE |
+ RRS_ERR_TRUNC)) {
+ /* hardware error, discard this packet*/
+ dev_err(&pdev->dev,
+ "rx packet desc error %x\n",
+ *((u32 *)prrs + 1));
+ goto skip_pkt;
+ }
+ }
+
+ packet_size = ((prrs->word1 >> RRS_PKT_SIZE_SHIFT) &
+ RRS_PKT_SIZE_MASK) - 4; /* CRC */
+ skb = netdev_alloc_skb(netdev,
+ packet_size + NET_IP_ALIGN);
+ if (skb == NULL) {
+ dev_warn(&pdev->dev, "%s: Memory squeeze,"
+ "deferring packet.\n", netdev->name);
+ goto skip_pkt;
+ }
+ skb_reserve(skb, NET_IP_ALIGN);
+ skb->dev = netdev;
+ memcpy(skb->data, (u8 *)(prrs + 1), packet_size);
+ skb_put(skb, packet_size);
+ skb->protocol = eth_type_trans(skb, netdev);
+ atl1e_rx_checksum(adapter, skb, prrs);
+
+ if (unlikely(adapter->vlgrp &&
+ (prrs->pkt_flag & RRS_IS_VLAN_TAG))) {
+ u16 vlan_tag = (prrs->vtag >> 4) |
+ ((prrs->vtag & 7) << 13) |
+ ((prrs->vtag & 8) << 9);
+ dev_dbg(&pdev->dev,
+ "RXD VLAN TAG<RRD>=0x%04x\n",
+ prrs->vtag);
+ vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
+ vlan_tag);
+ } else {
+ netif_receive_skb(skb);
+ }
+
+ netdev->last_rx = jiffies;
+skip_pkt:
+ /* skip current packet whether it's ok or not. */
+ rx_page->read_offset +=
+ (((u32)((prrs->word1 >> RRS_PKT_SIZE_SHIFT) &
+ RRS_PKT_SIZE_MASK) +
+ sizeof(struct atl1e_recv_ret_status) + 31) &
+ 0xFFFFFFE0);
+
+ if (rx_page->read_offset >= rx_ring->page_size) {
+ /* mark this page clean */
+ u16 reg_addr;
+ u8 rx_using;
+
+ rx_page->read_offset =
+ *(rx_page->write_offset_addr) = 0;
+ rx_using = rx_page_desc[que].rx_using;
+ reg_addr =
+ atl1e_rx_page_vld_regs[que][rx_using];
+ AT_WRITE_REGB(&adapter->hw, reg_addr, 1);
+ rx_page_desc[que].rx_using ^= 1;
+ rx_page = atl1e_get_rx_page(adapter, que);
+ }
+ write_offset = *(rx_page->write_offset_addr);
+ } while (rx_page->read_offset < write_offset);
+ }
+
+ return;
+
+fatal_err:
+ if (!test_bit(__AT_DOWN, &adapter->flags))
+ schedule_work(&adapter->reset_task);
+}
+
+/*
+ * atl1e_clean - NAPI Rx polling callback
+ * @adapter: board private structure
+ */
+static int atl1e_clean(struct napi_struct *napi, int budget)
+{
+ struct atl1e_adapter *adapter =
+ container_of(napi, struct atl1e_adapter, napi);
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ u32 imr_data;
+ int work_done = 0;
+
+ /* Keep link state information with original netdev */
+ if (!netif_carrier_ok(adapter->netdev))
+ goto quit_polling;
+
+ atl1e_clean_rx_irq(adapter, 0, &work_done, budget);
+
+ /* If no Tx and not enough Rx work done, exit the polling mode */
+ if (work_done < budget) {
+quit_polling:
+ netif_rx_complete(netdev, napi);
+ imr_data = AT_READ_REG(&adapter->hw, REG_IMR);
+ AT_WRITE_REG(&adapter->hw, REG_IMR, imr_data | ISR_RX_EVENT);
+ /* test debug */
+ if (test_bit(__AT_DOWN, &adapter->flags)) {
+ atomic_dec(&adapter->irq_sem);
+ dev_err(&pdev->dev,
+ "atl1e_clean is called when AT_DOWN\n");
+ }
+ /* reenable RX intr */
+ /*atl1e_irq_enable(adapter); */
+
+ }
+ return work_done;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+
+/*
+ * 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.
+ */
+static void atl1e_netpoll(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ disable_irq(adapter->pdev->irq);
+ atl1e_intr(adapter->pdev->irq, netdev);
+ enable_irq(adapter->pdev->irq);
+}
+#endif
+
+static inline u16 atl1e_tpd_avail(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+ u16 next_to_use = 0;
+ u16 next_to_clean = 0;
+
+ next_to_clean = atomic_read(&tx_ring->next_to_clean);
+ next_to_use = tx_ring->next_to_use;
+
+ return (u16)(next_to_clean > next_to_use) ?
+ (next_to_clean - next_to_use - 1) :
+ (tx_ring->count + next_to_clean - next_to_use - 1);
+}
+
+/*
+ * get next usable tpd
+ * Note: should call atl1e_tdp_avail to make sure
+ * there is enough tpd to use
+ */
+static struct atl1e_tpd_desc *atl1e_get_tpd(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+ u16 next_to_use = 0;
+
+ next_to_use = tx_ring->next_to_use;
+ if (++tx_ring->next_to_use == tx_ring->count)
+ tx_ring->next_to_use = 0;
+
+ memset(&tx_ring->desc[next_to_use], 0, sizeof(struct atl1e_tpd_desc));
+ return (struct atl1e_tpd_desc *)&tx_ring->desc[next_to_use];
+}
+
+static struct atl1e_tx_buffer *
+atl1e_get_tx_buffer(struct atl1e_adapter *adapter, struct atl1e_tpd_desc *tpd)
+{
+ struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+
+ return &tx_ring->tx_buffer[tpd - tx_ring->desc];
+}
+
+/* Calculate the transmit packet descript needed*/
+static u16 atl1e_cal_tdp_req(const struct sk_buff *skb)
+{
+ int i = 0;
+ u16 tpd_req = 1;
+ u16 fg_size = 0;
+ u16 proto_hdr_len = 0;
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ fg_size = skb_shinfo(skb)->frags[i].size;
+ tpd_req += ((fg_size + MAX_TX_BUF_LEN - 1) >> MAX_TX_BUF_SHIFT);
+ }
+
+ if (skb_is_gso(skb)) {
+ if (skb->protocol == ntohs(ETH_P_IP) ||
+ (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6)) {
+ proto_hdr_len = skb_transport_offset(skb) +
+ tcp_hdrlen(skb);
+ if (proto_hdr_len < skb_headlen(skb)) {
+ tpd_req += ((skb_headlen(skb) - proto_hdr_len +
+ MAX_TX_BUF_LEN - 1) >>
+ MAX_TX_BUF_SHIFT);
+ }
+ }
+
+ }
+ return tpd_req;
+}
+
+static int atl1e_tso_csum(struct atl1e_adapter *adapter,
+ struct sk_buff *skb, struct atl1e_tpd_desc *tpd)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ u8 hdr_len;
+ u32 real_len;
+ unsigned short offload_type;
+ int err;
+
+ if (skb_is_gso(skb)) {
+ if (skb_header_cloned(skb)) {
+ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+ if (unlikely(err))
+ return -1;
+ }
+ offload_type = skb_shinfo(skb)->gso_type;
+
+ if (offload_type & SKB_GSO_TCPV4) {
+ real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
+ + ntohs(ip_hdr(skb)->tot_len));
+
+ if (real_len < skb->len)
+ pskb_trim(skb, real_len);
+
+ hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
+ if (unlikely(skb->len == hdr_len)) {
+ /* only xsum need */
+ dev_warn(&pdev->dev,
+ "IPV4 tso with zero data??\n");
+ goto check_sum;
+ } else {
+ ip_hdr(skb)->check = 0;
+ ip_hdr(skb)->tot_len = 0;
+ tcp_hdr(skb)->check = ~csum_tcpudp_magic(
+ ip_hdr(skb)->saddr,
+ ip_hdr(skb)->daddr,
+ 0, IPPROTO_TCP, 0);
+ tpd->word3 |= (ip_hdr(skb)->ihl &
+ TDP_V4_IPHL_MASK) <<
+ TPD_V4_IPHL_SHIFT;
+ tpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
+ TPD_TCPHDRLEN_MASK) <<
+ TPD_TCPHDRLEN_SHIFT;
+ tpd->word3 |= ((skb_shinfo(skb)->gso_size) &
+ TPD_MSS_MASK) << TPD_MSS_SHIFT;
+ tpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT;
+ }
+ return 0;
+ }
+
+ if (offload_type & SKB_GSO_TCPV6) {
+ real_len = (((unsigned char *)ipv6_hdr(skb) - skb->data)
+ + ntohs(ipv6_hdr(skb)->payload_len));
+ if (real_len < skb->len)
+ pskb_trim(skb, real_len);
+
+ /* check payload == 0 byte ? */
+ hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
+ if (unlikely(skb->len == hdr_len)) {
+ /* only xsum need */
+ dev_warn(&pdev->dev,
+ "IPV6 tso with zero data??\n");
+ goto check_sum;
+ } else {
+ tcp_hdr(skb)->check = ~csum_ipv6_magic(
+ &ipv6_hdr(skb)->saddr,
+ &ipv6_hdr(skb)->daddr,
+ 0, IPPROTO_TCP, 0);
+ tpd->word3 |= 1 << TPD_IP_VERSION_SHIFT;
+ hdr_len >>= 1;
+ tpd->word3 |= (hdr_len & TPD_V6_IPHLLO_MASK) <<
+ TPD_V6_IPHLLO_SHIFT;
+ tpd->word3 |= ((hdr_len >> 3) &
+ TPD_V6_IPHLHI_MASK) <<
+ TPD_V6_IPHLHI_SHIFT;
+ tpd->word3 |= (tcp_hdrlen(skb) >> 2 &
+ TPD_TCPHDRLEN_MASK) <<
+ TPD_TCPHDRLEN_SHIFT;
+ tpd->word3 |= ((skb_shinfo(skb)->gso_size) &
+ TPD_MSS_MASK) << TPD_MSS_SHIFT;
+ tpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT;
+ }
+ }
+ return 0;
+ }
+
+check_sum:
+ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+ u8 css, cso;
+
+ cso = skb_transport_offset(skb);
+ if (unlikely(cso & 0x1)) {
+ dev_err(&adapter->pdev->dev,
+ "pay load offset should not ant event number\n");
+ return -1;
+ } else {
+ css = cso + skb->csum_offset;
+ tpd->word3 |= (cso & TPD_PLOADOFFSET_MASK) <<
+ TPD_PLOADOFFSET_SHIFT;
+ tpd->word3 |= (css & TPD_CCSUMOFFSET_MASK) <<
+ TPD_CCSUMOFFSET_SHIFT;
+ tpd->word3 |= 1 << TPD_CC_SEGMENT_EN_SHIFT;
+ }
+ }
+
+ return 0;
+}
+
+static void atl1e_tx_map(struct atl1e_adapter *adapter,
+ struct sk_buff *skb, struct atl1e_tpd_desc *tpd)
+{
+ struct atl1e_tpd_desc *use_tpd = NULL;
+ struct atl1e_tx_buffer *tx_buffer = NULL;
+ u16 buf_len = skb->len - skb->data_len;
+ u16 map_len = 0;
+ u16 mapped_len = 0;
+ u16 hdr_len = 0;
+ u16 nr_frags;
+ u16 f;
+ int segment;
+
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ segment = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK;
+ if (segment) {
+ /* TSO */
+ map_len = hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+ use_tpd = tpd;
+
+ tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd);
+ tx_buffer->length = map_len;
+ tx_buffer->dma = pci_map_single(adapter->pdev,
+ skb->data, hdr_len, PCI_DMA_TODEVICE);
+ mapped_len += map_len;
+ use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
+ use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
+ ((cpu_to_le32(tx_buffer->length) &
+ TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT);
+ }
+
+ while (mapped_len < buf_len) {
+ /* mapped_len == 0, means we should use the first tpd,
+ which is given by caller */
+ if (mapped_len == 0) {
+ use_tpd = tpd;
+ } else {
+ use_tpd = atl1e_get_tpd(adapter);
+ memcpy(use_tpd, tpd, sizeof(struct atl1e_tpd_desc));
+ }
+ tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd);
+ tx_buffer->skb = NULL;
+
+ tx_buffer->length = map_len =
+ ((buf_len - mapped_len) >= MAX_TX_BUF_LEN) ?
+ MAX_TX_BUF_LEN : (buf_len - mapped_len);
+ tx_buffer->dma =
+ pci_map_single(adapter->pdev, skb->data + mapped_len,
+ map_len, PCI_DMA_TODEVICE);
+ mapped_len += map_len;
+ use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
+ use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
+ ((cpu_to_le32(tx_buffer->length) &
+ TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT);
+ }
+
+ for (f = 0; f < nr_frags; f++) {
+ struct skb_frag_struct *frag;
+ u16 i;
+ u16 seg_num;
+
+ frag = &skb_shinfo(skb)->frags[f];
+ buf_len = frag->size;
+
+ seg_num = (buf_len + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+ for (i = 0; i < seg_num; i++) {
+ use_tpd = atl1e_get_tpd(adapter);
+ memcpy(use_tpd, tpd, sizeof(struct atl1e_tpd_desc));
+
+ tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd);
+ if (tx_buffer->skb)
+ BUG();
+
+ tx_buffer->skb = NULL;
+ tx_buffer->length =
+ (buf_len > MAX_TX_BUF_LEN) ?
+ MAX_TX_BUF_LEN : buf_len;
+ buf_len -= tx_buffer->length;
+
+ tx_buffer->dma =
+ pci_map_page(adapter->pdev, frag->page,
+ frag->page_offset +
+ (i * MAX_TX_BUF_LEN),
+ tx_buffer->length,
+ PCI_DMA_TODEVICE);
+ use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
+ use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
+ ((cpu_to_le32(tx_buffer->length) &
+ TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT);
+ }
+ }
+
+ if ((tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK)
+ /* note this one is a tcp header */
+ tpd->word3 |= 1 << TPD_HDRFLAG_SHIFT;
+ /* The last tpd */
+
+ use_tpd->word3 |= 1 << TPD_EOP_SHIFT;
+ /* The last buffer info contain the skb address,
+ so it will be free after unmap */
+ tx_buffer->skb = skb;
+}
+
+static void atl1e_tx_queue(struct atl1e_adapter *adapter, u16 count,
+ struct atl1e_tpd_desc *tpd)
+{
+ struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+ /* Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64). */
+ wmb();
+ AT_WRITE_REG(&adapter->hw, REG_MB_TPD_PROD_IDX, tx_ring->next_to_use);
+}
+
+static int atl1e_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ unsigned long flags;
+ u16 tpd_req = 1;
+ struct atl1e_tpd_desc *tpd;
+
+ if (test_bit(__AT_DOWN, &adapter->flags)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ if (unlikely(skb->len <= 0)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+ tpd_req = atl1e_cal_tdp_req(skb);
+ if (!spin_trylock_irqsave(&adapter->tx_lock, flags))
+ return NETDEV_TX_LOCKED;
+
+ if (atl1e_tpd_avail(adapter) < tpd_req) {
+ /* no enough descriptor, just stop queue */
+ netif_stop_queue(netdev);
+ spin_unlock_irqrestore(&adapter->tx_lock, flags);
+ return NETDEV_TX_BUSY;
+ }
+
+ tpd = atl1e_get_tpd(adapter);
+
+ if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
+ u16 vlan_tag = vlan_tx_tag_get(skb);
+ u16 atl1e_vlan_tag;
+
+ tpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT;
+ AT_VLAN_TAG_TO_TPD_TAG(vlan_tag, atl1e_vlan_tag);
+ tpd->word2 |= (atl1e_vlan_tag & TPD_VLANTAG_MASK) <<
+ TPD_VLAN_SHIFT;
+ }
+
+ if (skb->protocol == ntohs(ETH_P_8021Q))
+ tpd->word3 |= 1 << TPD_VL_TAGGED_SHIFT;
+
+ if (skb_network_offset(skb) != ETH_HLEN)
+ tpd->word3 |= 1 << TPD_ETHTYPE_SHIFT; /* 802.3 frame */
+
+ /* do TSO and check sum */
+ if (atl1e_tso_csum(adapter, skb, tpd) != 0) {
+ spin_unlock_irqrestore(&adapter->tx_lock, flags);
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ atl1e_tx_map(adapter, skb, tpd);
+ atl1e_tx_queue(adapter, tpd_req, tpd);
+
+ netdev->trans_start = jiffies;
+ spin_unlock_irqrestore(&adapter->tx_lock, flags);
+ return NETDEV_TX_OK;
+}
+
+static void atl1e_free_irq(struct atl1e_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ free_irq(adapter->pdev->irq, netdev);
+
+ if (adapter->have_msi)
+ pci_disable_msi(adapter->pdev);
+}
+
+static int atl1e_request_irq(struct atl1e_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ struct net_device *netdev = adapter->netdev;
+ int flags = 0;
+ int err = 0;
+
+ adapter->have_msi = true;
+ err = pci_enable_msi(adapter->pdev);
+ if (err) {
+ dev_dbg(&pdev->dev,
+ "Unable to allocate MSI interrupt Error: %d\n", err);
+ adapter->have_msi = false;
+ } else
+ netdev->irq = pdev->irq;
+
+
+ if (!adapter->have_msi)
+ flags |= IRQF_SHARED;
+ err = request_irq(adapter->pdev->irq, &atl1e_intr, flags,
+ netdev->name, netdev);
+ if (err) {
+ dev_dbg(&pdev->dev,
+ "Unable to allocate interrupt Error: %d\n", err);
+ if (adapter->have_msi)
+ pci_disable_msi(adapter->pdev);
+ return err;
+ }
+ dev_dbg(&pdev->dev, "atl1e_request_irq OK\n");
+ return err;
+}
+
+int atl1e_up(struct atl1e_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int err = 0;
+ u32 val;
+
+ /* hardware has been reset, we need to reload some things */
+ err = atl1e_init_hw(&adapter->hw);
+ if (err) {
+ err = -EIO;
+ return err;
+ }
+ atl1e_init_ring_ptrs(adapter);
+ atl1e_set_multi(netdev);
+ atl1e_restore_vlan(adapter);
+
+ if (atl1e_configure(adapter)) {
+ err = -EIO;
+ goto err_up;
+ }
+
+ clear_bit(__AT_DOWN, &adapter->flags);
+ napi_enable(&adapter->napi);
+ atl1e_irq_enable(adapter);
+ val = AT_READ_REG(&adapter->hw, REG_MASTER_CTRL);
+ AT_WRITE_REG(&adapter->hw, REG_MASTER_CTRL,
+ val | MASTER_CTRL_MANUAL_INT);
+
+err_up:
+ return err;
+}
+
+void atl1e_down(struct atl1e_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ /* signal that we're down so the interrupt handler does not
+ * reschedule our watchdog timer */
+ set_bit(__AT_DOWN, &adapter->flags);
+
+#ifdef NETIF_F_LLTX
+ netif_stop_queue(netdev);
+#else
+ netif_tx_disable(netdev);
+#endif
+
+ /* reset MAC to disable all RX/TX */
+ atl1e_reset_hw(&adapter->hw);
+ msleep(1);
+
+ napi_disable(&adapter->napi);
+ atl1e_del_timer(adapter);
+ atl1e_irq_disable(adapter);
+
+ netif_carrier_off(netdev);
+ adapter->link_speed = SPEED_0;
+ adapter->link_duplex = -1;
+ atl1e_clean_tx_ring(adapter);
+ atl1e_clean_rx_ring(adapter);
+}
+
+/*
+ * atl1e_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP). At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ */
+static int atl1e_open(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ int err;
+
+ /* disallow open during test */
+ if (test_bit(__AT_TESTING, &adapter->flags))
+ return -EBUSY;
+
+ /* allocate rx/tx dma buffer & descriptors */
+ atl1e_init_ring_resources(adapter);
+ err = atl1e_setup_ring_resources(adapter);
+ if (unlikely(err))
+ return err;
+
+ err = atl1e_request_irq(adapter);
+ if (unlikely(err))
+ goto err_req_irq;
+
+ err = atl1e_up(adapter);
+ if (unlikely(err))
+ goto err_up;
+
+ return 0;
+
+err_up:
+ atl1e_free_irq(adapter);
+err_req_irq:
+ atl1e_free_ring_resources(adapter);
+ atl1e_reset_hw(&adapter->hw);
+
+ return err;
+}
+
+/*
+ * atl1e_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS. The hardware is still under the drivers control, but
+ * needs to be disabled. A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ */
+static int atl1e_close(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
+ atl1e_down(adapter);
+ atl1e_free_irq(adapter);
+ atl1e_free_ring_resources(adapter);
+
+ return 0;
+}
+
+static int atl1e_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw *hw = &adapter->hw;
+ u32 ctrl = 0;
+ u32 mac_ctrl_data = 0;
+ u32 wol_ctrl_data = 0;
+ u16 mii_advertise_data = 0;
+ u16 mii_bmsr_data = 0;
+ u16 mii_intr_status_data = 0;
+ u32 wufc = adapter->wol;
+ u32 i;
+#ifdef CONFIG_PM
+ int retval = 0;
+#endif
+
+ if (netif_running(netdev)) {
+ WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
+ atl1e_down(adapter);
+ }
+ netif_device_detach(netdev);
+
+#ifdef CONFIG_PM
+ retval = pci_save_state(pdev);
+ if (retval)
+ return retval;
+#endif
+
+ if (wufc) {
+ /* get link status */
+ atl1e_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
+ atl1e_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
+
+ mii_advertise_data = MII_AR_10T_HD_CAPS;
+
+ if ((atl1e_write_phy_reg(hw, MII_AT001_CR, 0) != 0) ||
+ (atl1e_write_phy_reg(hw,
+ MII_ADVERTISE, mii_advertise_data) != 0) ||
+ (atl1e_phy_commit(hw)) != 0) {
+ dev_dbg(&pdev->dev, "set phy register failed\n");
+ goto wol_dis;
+ }
+
+ hw->phy_configured = false; /* re-init PHY when resume */
+
+ /* turn on magic packet wol */
+ if (wufc & AT_WUFC_MAG)
+ wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
+
+ if (wufc & AT_WUFC_LNKC) {
+ /* if orignal link status is link, just wait for retrive link */
+ if (mii_bmsr_data & BMSR_LSTATUS) {
+ for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) {
+ msleep(100);
+ atl1e_read_phy_reg(hw, MII_BMSR,
+ (u16 *)&mii_bmsr_data);
+ if (mii_bmsr_data & BMSR_LSTATUS)
+ break;
+ }
+
+ if ((mii_bmsr_data & BMSR_LSTATUS) == 0)
+ dev_dbg(&pdev->dev,
+ "%s: Link may change"
+ "when suspend\n",
+ atl1e_driver_name);
+ }
+ wol_ctrl_data |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
+ /* only link up can wake up */
+ if (atl1e_write_phy_reg(hw, MII_INT_CTRL, 0x400) != 0) {
+ dev_dbg(&pdev->dev, "%s: read write phy "
+ "register failed.\n",
+ atl1e_driver_name);
+ goto wol_dis;
+ }
+ }
+ /* clear phy interrupt */
+ atl1e_read_phy_reg(hw, MII_INT_STATUS, &mii_intr_status_data);
+ /* Config MAC Ctrl register */
+ mac_ctrl_data = MAC_CTRL_RX_EN;
+ /* set to 10/100M halt duplex */
+ mac_ctrl_data |= MAC_CTRL_SPEED_10_100 << MAC_CTRL_SPEED_SHIFT;
+ mac_ctrl_data |= (((u32)adapter->hw.preamble_len &
+ MAC_CTRL_PRMLEN_MASK) <<
+ MAC_CTRL_PRMLEN_SHIFT);
+
+ if (adapter->vlgrp)
+ mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+
+ /* magic packet maybe Broadcast&multicast&Unicast frame */
+ if (wufc & AT_WUFC_MAG)
+ mac_ctrl_data |= MAC_CTRL_BC_EN;
+
+ dev_dbg(&pdev->dev,
+ "%s: suspend MAC=0x%x\n",
+ atl1e_driver_name, mac_ctrl_data);
+
+ AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);
+ AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+ /* pcie patch */
+ ctrl = AT_READ_REG(hw, REG_PCIE_PHYMISC);
+ ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
+ AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
+ goto suspend_exit;
+ }
+wol_dis:
+
+ /* WOL disabled */
+ AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+
+ /* pcie patch */
+ ctrl = AT_READ_REG(hw, REG_PCIE_PHYMISC);
+ ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
+ AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
+
+ atl1e_force_ps(hw);
+ hw->phy_configured = false; /* re-init PHY when resume */
+
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+
+suspend_exit:
+
+ if (netif_running(netdev))
+ atl1e_free_irq(adapter);
+
+ pci_disable_device(pdev);
+
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int atl1e_resume(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ u32 err;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "ATL1e: Cannot enable PCI"
+ " device from suspend\n");
+ return err;
+ }
+
+ pci_set_master(pdev);
+
+ AT_READ_REG(&adapter->hw, REG_WOL_CTRL); /* clear WOL status */
+
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+
+ AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
+
+ if (netif_running(netdev))
+ err = atl1e_request_irq(adapter);
+ if (err)
+ return err;
+
+ atl1e_reset_hw(&adapter->hw);
+
+ if (netif_running(netdev))
+ atl1e_up(adapter);
+
+ netif_device_attach(netdev);
+
+ return 0;
+}
+#endif
+
+static void atl1e_shutdown(struct pci_dev *pdev)
+{
+ atl1e_suspend(pdev, PMSG_SUSPEND);
+}
+
+static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
+{
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+ pci_set_drvdata(pdev, netdev);
+
+ netdev->irq = pdev->irq;
+ netdev->open = &atl1e_open;
+ netdev->stop = &atl1e_close;
+ netdev->hard_start_xmit = &atl1e_xmit_frame;
+ netdev->get_stats = &atl1e_get_stats;
+ netdev->set_multicast_list = &atl1e_set_multi;
+ netdev->set_mac_address = &atl1e_set_mac_addr;
+ netdev->change_mtu = &atl1e_change_mtu;
+ netdev->do_ioctl = &atl1e_ioctl;
+ netdev->tx_timeout = &atl1e_tx_timeout;
+ netdev->watchdog_timeo = AT_TX_WATCHDOG;
+ netdev->vlan_rx_register = atl1e_vlan_rx_register;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ netdev->poll_controller = atl1e_netpoll;
+#endif
+ atl1e_set_ethtool_ops(netdev);
+
+ netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM |
+ NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ netdev->features |= NETIF_F_LLTX;
+ netdev->features |= NETIF_F_TSO;
+ netdev->features |= NETIF_F_TSO6;
+
+ return 0;
+}
+
+/*
+ * atl1e_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in atl1e_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * atl1e_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ */
+static int __devinit atl1e_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct net_device *netdev;
+ struct atl1e_adapter *adapter = NULL;
+ static int cards_found;
+
+ int err = 0;
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "cannot enable PCI device\n");
+ return err;
+ }
+
+ /*
+ * The atl1e chip can DMA to 64-bit addresses, but it uses a single
+ * shared register for the high 32 bits, so only a single, aligned,
+ * 4 GB physical address range can be used at a time.
+ *
+ * Supporting 64-bit DMA on this hardware is more trouble than it's
+ * worth. It is far easier to limit to 32-bit DMA than update
+ * various kernel subsystems to support the mechanics required by a
+ * fixed-high-32-bit system.
+ */
+ if ((pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) ||
+ (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) != 0)) {
+ dev_err(&pdev->dev, "No usable DMA configuration,aborting\n");
+ goto err_dma;
+ }
+
+ err = pci_request_regions(pdev, atl1e_driver_name);
+ if (err) {
+ dev_err(&pdev->dev, "cannot obtain PCI resources\n");
+ goto err_pci_reg;
+ }
+
+ pci_set_master(pdev);
+
+ netdev = alloc_etherdev(sizeof(struct atl1e_adapter));
+ if (netdev == NULL) {
+ err = -ENOMEM;
+ dev_err(&pdev->dev, "etherdev alloc failed\n");
+ goto err_alloc_etherdev;
+ }
+
+ err = atl1e_init_netdev(netdev, pdev);
+ if (err) {
+ dev_err(&pdev->dev, "init netdevice failed\n");
+ goto err_init_netdev;
+ }
+ adapter = netdev_priv(netdev);
+ adapter->bd_number = cards_found;
+ adapter->netdev = netdev;
+ adapter->pdev = pdev;
+ adapter->hw.adapter = adapter;
+ adapter->hw.hw_addr = pci_iomap(pdev, BAR_0, 0);
+ if (!adapter->hw.hw_addr) {
+ err = -EIO;
+ dev_err(&pdev->dev, "cannot map device registers\n");
+ goto err_ioremap;
+ }
+ netdev->base_addr = (unsigned long)adapter->hw.hw_addr;
+
+ /* init mii data */
+ adapter->mii.dev = netdev;
+ adapter->mii.mdio_read = atl1e_mdio_read;
+ adapter->mii.mdio_write = atl1e_mdio_write;
+ adapter->mii.phy_id_mask = 0x1f;
+ adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK;
+
+ netif_napi_add(netdev, &adapter->napi, atl1e_clean, 64);
+
+ init_timer(&adapter->phy_config_timer);
+ adapter->phy_config_timer.function = &atl1e_phy_config;
+ adapter->phy_config_timer.data = (unsigned long) adapter;
+
+ /* get user settings */
+ atl1e_check_options(adapter);
+ /*
+ * Mark all PCI regions associated with PCI device
+ * pdev as being reserved by owner atl1e_driver_name
+ * Enables bus-mastering on the device and calls
+ * pcibios_set_master to do the needed arch specific settings
+ */
+ atl1e_setup_pcicmd(pdev);
+ /* setup the private structure */
+ err = atl1e_sw_init(adapter);
+ if (err) {
+ dev_err(&pdev->dev, "net device private data init failed\n");
+ goto err_sw_init;
+ }
+
+ /* Init GPHY as early as possible due to power saving issue */
+ spin_lock(&adapter->mdio_lock);
+ atl1e_phy_init(&adapter->hw);
+ spin_unlock(&adapter->mdio_lock);
+ /* reset the controller to
+ * put the device in a known good starting state */
+ err = atl1e_reset_hw(&adapter->hw);
+ if (err) {
+ err = -EIO;
+ goto err_reset;
+ }
+
+ if (atl1e_read_mac_addr(&adapter->hw) != 0) {
+ err = -EIO;
+ dev_err(&pdev->dev, "get mac address failed\n");
+ goto err_eeprom;
+ }
+
+ memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+ memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
+ dev_dbg(&pdev->dev, "mac address : %02x-%02x-%02x-%02x-%02x-%02x\n",
+ adapter->hw.mac_addr[0], adapter->hw.mac_addr[1],
+ adapter->hw.mac_addr[2], adapter->hw.mac_addr[3],
+ adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]);
+
+ INIT_WORK(&adapter->reset_task, atl1e_reset_task);
+ INIT_WORK(&adapter->link_chg_task, atl1e_link_chg_task);
+ err = register_netdev(netdev);
+ if (err) {
+ dev_err(&pdev->dev, "register netdevice failed\n");
+ goto err_register;
+ }
+
+ /* assume we have no link for now */
+ netif_stop_queue(netdev);
+ netif_carrier_off(netdev);
+
+ cards_found++;
+
+ return 0;
+
+err_reset:
+err_register:
+err_sw_init:
+err_eeprom:
+ iounmap(adapter->hw.hw_addr);
+err_init_netdev:
+err_ioremap:
+ free_netdev(netdev);
+err_alloc_etherdev:
+ pci_release_regions(pdev);
+err_pci_reg:
+err_dma:
+ pci_disable_device(pdev);
+ return err;
+}
+
+/*
+ * atl1e_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * atl1e_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device. The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ */
+static void __devexit atl1e_remove(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ /*
+ * flush_scheduled work may reschedule our watchdog task, so
+ * explicitly disable watchdog tasks from being rescheduled
+ */
+ set_bit(__AT_DOWN, &adapter->flags);
+
+ atl1e_del_timer(adapter);
+ atl1e_cancel_work(adapter);
+
+ unregister_netdev(netdev);
+ atl1e_free_ring_resources(adapter);
+ atl1e_force_ps(&adapter->hw);
+ iounmap(adapter->hw.hw_addr);
+ pci_release_regions(pdev);
+ free_netdev(netdev);
+ pci_disable_device(pdev);
+}
+
+/*
+ * atl1e_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci connection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t
+atl1e_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1e_adapter *adapter = netdev->priv;
+
+ netif_device_detach(netdev);
+
+ if (netif_running(netdev))
+ atl1e_down(adapter);
+
+ pci_disable_device(pdev);
+
+ /* Request a slot slot reset. */
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/*
+ * atl1e_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot. Implementation
+ * resembles the first-half of the e1000_resume routine.
+ */
+static pci_ers_result_t atl1e_io_slot_reset(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1e_adapter *adapter = netdev->priv;
+
+ if (pci_enable_device(pdev)) {
+ dev_err(&pdev->dev,
+ "ATL1e: Cannot re-enable PCI device after reset.\n");
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+ pci_set_master(pdev);
+
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+
+ atl1e_reset_hw(&adapter->hw);
+
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+/*
+ * atl1e_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells us that
+ * its OK to resume normal operation. Implementation resembles the
+ * second-half of the atl1e_resume routine.
+ */
+static void atl1e_io_resume(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1e_adapter *adapter = netdev->priv;
+
+ if (netif_running(netdev)) {
+ if (atl1e_up(adapter)) {
+ dev_err(&pdev->dev,
+ "ATL1e: can't bring device back up after reset\n");
+ return;
+ }
+ }
+
+ netif_device_attach(netdev);
+}
+
+static struct pci_error_handlers atl1e_err_handler = {
+ .error_detected = atl1e_io_error_detected,
+ .slot_reset = atl1e_io_slot_reset,
+ .resume = atl1e_io_resume,
+};
+
+static struct pci_driver atl1e_driver = {
+ .name = atl1e_driver_name,
+ .id_table = atl1e_pci_tbl,
+ .probe = atl1e_probe,
+ .remove = __devexit_p(atl1e_remove),
+ /* Power Managment Hooks */
+#ifdef CONFIG_PM
+ .suspend = atl1e_suspend,
+ .resume = atl1e_resume,
+#endif
+ .shutdown = atl1e_shutdown,
+ .err_handler = &atl1e_err_handler
+};
+
+/*
+ * atl1e_init_module - Driver Registration Routine
+ *
+ * atl1e_init_module is the first routine called when the driver is
+ * loaded. All it does is register with the PCI subsystem.
+ */
+static int __init atl1e_init_module(void)
+{
+ return pci_register_driver(&atl1e_driver);
+}
+
+/*
+ * atl1e_exit_module - Driver Exit Cleanup Routine
+ *
+ * atl1e_exit_module is called just before the driver is removed
+ * from memory.
+ */
+static void __exit atl1e_exit_module(void)
+{
+ pci_unregister_driver(&atl1e_driver);
+}
+
+module_init(atl1e_init_module);
+module_exit(atl1e_exit_module);
diff --git a/drivers/net/atl1e/atl1e_param.c b/drivers/net/atl1e/atl1e_param.c
new file mode 100644
index 00000000000..f72abb34b0c
--- /dev/null
+++ b/drivers/net/atl1e/atl1e_param.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/netdevice.h>
+
+#include "atl1e.h"
+
+/* This is the only thing that needs to be changed to adjust the
+ * maximum number of ports that the driver can manage.
+ */
+
+#define ATL1E_MAX_NIC 32
+
+#define OPTION_UNSET -1
+#define OPTION_DISABLED 0
+#define OPTION_ENABLED 1
+
+/* All parameters are treated the same, as an integer array of values.
+ * This macro just reduces the need to repeat the same declaration code
+ * over and over (plus this helps to avoid typo bugs).
+ */
+#define ATL1E_PARAM_INIT { [0 ... ATL1E_MAX_NIC] = OPTION_UNSET }
+
+#define ATL1E_PARAM(x, desc) \
+ static int __devinitdata x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \
+ static int num_##x; \
+ module_param_array_named(x, x, int, &num_##x, 0); \
+ MODULE_PARM_DESC(x, desc);
+
+/* Transmit Memory count
+ *
+ * Valid Range: 64-2048
+ *
+ * Default Value: 128
+ */
+#define ATL1E_MIN_TX_DESC_CNT 32
+#define ATL1E_MAX_TX_DESC_CNT 1020
+#define ATL1E_DEFAULT_TX_DESC_CNT 128
+ATL1E_PARAM(tx_desc_cnt, "Transmit description count");
+
+/* Receive Memory Block Count
+ *
+ * Valid Range: 16-512
+ *
+ * Default Value: 128
+ */
+#define ATL1E_MIN_RX_MEM_SIZE 8 /* 8KB */
+#define ATL1E_MAX_RX_MEM_SIZE 1024 /* 1MB */
+#define ATL1E_DEFAULT_RX_MEM_SIZE 256 /* 128KB */
+ATL1E_PARAM(rx_mem_size, "memory size of rx buffer(KB)");
+
+/* User Specified MediaType Override
+ *
+ * Valid Range: 0-5
+ * - 0 - auto-negotiate at all supported speeds
+ * - 1 - only link at 100Mbps Full Duplex
+ * - 2 - only link at 100Mbps Half Duplex
+ * - 3 - only link at 10Mbps Full Duplex
+ * - 4 - only link at 10Mbps Half Duplex
+ * Default Value: 0
+ */
+
+ATL1E_PARAM(media_type, "MediaType Select");
+
+/* Interrupt Moderate Timer in units of 2 us
+ *
+ * Valid Range: 10-65535
+ *
+ * Default Value: 45000(90ms)
+ */
+#define INT_MOD_DEFAULT_CNT 100 /* 200us */
+#define INT_MOD_MAX_CNT 65000
+#define INT_MOD_MIN_CNT 50
+ATL1E_PARAM(int_mod_timer, "Interrupt Moderator Timer");
+
+#define AUTONEG_ADV_DEFAULT 0x2F
+#define AUTONEG_ADV_MASK 0x2F
+#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
+
+#define FLASH_VENDOR_DEFAULT 0
+#define FLASH_VENDOR_MIN 0
+#define FLASH_VENDOR_MAX 2
+
+struct atl1e_option {
+ enum { enable_option, range_option, list_option } type;
+ char *name;
+ char *err;
+ int def;
+ union {
+ struct { /* range_option info */
+ int min;
+ int max;
+ } r;
+ struct { /* list_option info */
+ int nr;
+ struct atl1e_opt_list { int i; char *str; } *p;
+ } l;
+ } arg;
+};
+
+static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt, struct pci_dev *pdev)
+{
+ if (*value == OPTION_UNSET) {
+ *value = opt->def;
+ return 0;
+ }
+
+ switch (opt->type) {
+ case enable_option:
+ switch (*value) {
+ case OPTION_ENABLED:
+ dev_info(&pdev->dev, "%s Enabled\n", opt->name);
+ return 0;
+ case OPTION_DISABLED:
+ dev_info(&pdev->dev, "%s Disabled\n", opt->name);
+ return 0;
+ }
+ break;
+ case range_option:
+ if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+ dev_info(&pdev->dev, "%s set to %i\n", opt->name, *value);
+ return 0;
+ }
+ break;
+ case list_option:{
+ int i;
+ struct atl1e_opt_list *ent;
+
+ for (i = 0; i < opt->arg.l.nr; i++) {
+ ent = &opt->arg.l.p[i];
+ if (*value == ent->i) {
+ if (ent->str[0] != '\0')
+ dev_info(&pdev->dev, "%s\n",
+ ent->str);
+ return 0;
+ }
+ }
+ break;
+ }
+ default:
+ BUG();
+ }
+
+ dev_info(&pdev->dev, "Invalid %s specified (%i) %s\n",
+ opt->name, *value, opt->err);
+ *value = opt->def;
+ return -1;
+}
+
+/*
+ * atl1e_check_options - Range Checking for Command Line Parameters
+ * @adapter: board private structure
+ *
+ * This routine checks all command line parameters for valid user
+ * input. If an invalid value is given, or if no user specified
+ * value exists, a default value is used. The final value is stored
+ * in a variable in the adapter structure.
+ */
+void __devinit atl1e_check_options(struct atl1e_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ int bd = adapter->bd_number;
+ if (bd >= ATL1E_MAX_NIC) {
+ dev_notice(&pdev->dev, "no configuration for board #%i\n", bd);
+ dev_notice(&pdev->dev, "Using defaults for all values\n");
+ }
+
+ { /* Transmit Ring Size */
+ struct atl1e_option opt = {
+ .type = range_option,
+ .name = "Transmit Ddescription Count",
+ .err = "using default of "
+ __MODULE_STRING(ATL1E_DEFAULT_TX_DESC_CNT),
+ .def = ATL1E_DEFAULT_TX_DESC_CNT,
+ .arg = { .r = { .min = ATL1E_MIN_TX_DESC_CNT,
+ .max = ATL1E_MAX_TX_DESC_CNT} }
+ };
+ int val;
+ if (num_tx_desc_cnt > bd) {
+ val = tx_desc_cnt[bd];
+ atl1e_validate_option(&val, &opt, pdev);
+ adapter->tx_ring.count = (u16) val & 0xFFFC;
+ } else
+ adapter->tx_ring.count = (u16)opt.def;
+ }
+
+ { /* Receive Memory Block Count */
+ struct atl1e_option opt = {
+ .type = range_option,
+ .name = "Memory size of rx buffer(KB)",
+ .err = "using default of "
+ __MODULE_STRING(ATL1E_DEFAULT_RX_MEM_SIZE),
+ .def = ATL1E_DEFAULT_RX_MEM_SIZE,
+ .arg = { .r = { .min = ATL1E_MIN_RX_MEM_SIZE,
+ .max = ATL1E_MAX_RX_MEM_SIZE} }
+ };
+ int val;
+ if (num_rx_mem_size > bd) {
+ val = rx_mem_size[bd];
+ atl1e_validate_option(&val, &opt, pdev);
+ adapter->rx_ring.page_size = (u32)val * 1024;
+ } else {
+ adapter->rx_ring.page_size = (u32)opt.def * 1024;
+ }
+ }
+
+ { /* Interrupt Moderate Timer */
+ struct atl1e_option opt = {
+ .type = range_option,
+ .name = "Interrupt Moderate Timer",
+ .err = "using default of "
+ __MODULE_STRING(INT_MOD_DEFAULT_CNT),
+ .def = INT_MOD_DEFAULT_CNT,
+ .arg = { .r = { .min = INT_MOD_MIN_CNT,
+ .max = INT_MOD_MAX_CNT} }
+ } ;
+ int val;
+ if (num_int_mod_timer > bd) {
+ val = int_mod_timer[bd];
+ atl1e_validate_option(&val, &opt, pdev);
+ adapter->hw.imt = (u16) val;
+ } else
+ adapter->hw.imt = (u16)(opt.def);
+ }
+
+ { /* MediaType */
+ struct atl1e_option opt = {
+ .type = range_option,
+ .name = "Speed/Duplex Selection",
+ .err = "using default of "
+ __MODULE_STRING(MEDIA_TYPE_AUTO_SENSOR),
+ .def = MEDIA_TYPE_AUTO_SENSOR,
+ .arg = { .r = { .min = MEDIA_TYPE_AUTO_SENSOR,
+ .max = MEDIA_TYPE_10M_HALF} }
+ } ;
+ int val;
+ if (num_media_type > bd) {
+ val = media_type[bd];
+ atl1e_validate_option(&val, &opt, pdev);
+ adapter->hw.media_type = (u16) val;
+ } else
+ adapter->hw.media_type = (u16)(opt.def);
+
+ }
+}
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 3ab61e40e86..cb8be490e5a 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -911,9 +911,8 @@ au1000_adjust_link(struct net_device *dev)
if(phydev->link != aup->old_link) {
// link state changed
- if (phydev->link) // link went up
- netif_tx_schedule_all(dev);
- else { // link went down
+ if (!phydev->link) {
+ /* link went down */
aup->old_speed = 0;
aup->old_duplex = -1;
}
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index a6a3da89f59..a8ec60e1ed7 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -357,7 +357,6 @@ static void bfin_mac_adjust_link(struct net_device *dev)
if (!lp->old_link) {
new_state = 1;
lp->old_link = 1;
- netif_tx_schedule_all(dev);
}
} else if (lp->old_link) {
new_state = 1;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 9737c06045d..a641eeaa2a2 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -5041,6 +5041,7 @@ static int bond_check_params(struct bond_params *params)
}
static struct lock_class_key bonding_netdev_xmit_lock_key;
+static struct lock_class_key bonding_netdev_addr_lock_key;
static void bond_set_lockdep_class_one(struct net_device *dev,
struct netdev_queue *txq,
@@ -5052,6 +5053,8 @@ static void bond_set_lockdep_class_one(struct net_device *dev,
static void bond_set_lockdep_class(struct net_device *dev)
{
+ lockdep_set_class(&dev->addr_list_lock,
+ &bonding_netdev_addr_lock_key);
netdev_for_each_tx_queue(dev, bond_set_lockdep_class_one, NULL);
}
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index fbd4280c102..a7800e55909 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -945,10 +945,8 @@ static void cpmac_adjust_link(struct net_device *dev)
if (!priv->oldlink) {
new_state = 1;
priv->oldlink = 1;
- netif_tx_schedule_all(dev);
}
} else if (priv->oldlink) {
- netif_tx_stop_all_queues(dev);
new_state = 1;
priv->oldlink = 0;
priv->oldspeed = 0;
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 952e10d686e..0b0f1c407a7 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -888,19 +888,22 @@ dm9000_rx(struct net_device *dev)
dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);
}
- if (rxhdr.RxStatus & 0xbf) {
+ /* rxhdr.RxStatus is identical to RSR register. */
+ if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE |
+ RSR_PLE | RSR_RWTO |
+ RSR_LCS | RSR_RF)) {
GoodPacket = false;
- if (rxhdr.RxStatus & 0x01) {
+ if (rxhdr.RxStatus & RSR_FOE) {
if (netif_msg_rx_err(db))
dev_dbg(db->dev, "fifo error\n");
dev->stats.rx_fifo_errors++;
}
- if (rxhdr.RxStatus & 0x02) {
+ if (rxhdr.RxStatus & RSR_CE) {
if (netif_msg_rx_err(db))
dev_dbg(db->dev, "crc error\n");
dev->stats.rx_crc_errors++;
}
- if (rxhdr.RxStatus & 0x80) {
+ if (rxhdr.RxStatus & RSR_RF) {
if (netif_msg_rx_err(db))
dev_dbg(db->dev, "length error\n");
dev->stats.rx_length_errors++;
@@ -1067,7 +1070,7 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
/* Fill the phyxcer register into REG_0C */
iow(db, DM9000_EPAR, DM9000_PHY | reg);
- iow(db, DM9000_EPCR, 0xc); /* Issue phyxcer read command */
+ iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS); /* Issue phyxcer read command */
writeb(reg_save, db->io_addr);
spin_unlock_irqrestore(&db->lock,flags);
@@ -1118,7 +1121,7 @@ dm9000_phy_write(struct net_device *dev,
iow(db, DM9000_EPDRL, value);
iow(db, DM9000_EPDRH, value >> 8);
- iow(db, DM9000_EPCR, 0xa); /* Issue phyxcer write command */
+ iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW); /* Issue phyxcer write command */
writeb(reg_save, db->io_addr);
spin_unlock_irqrestore(&db->lock, flags);
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 31feae1ea39..19e317eaf5b 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -90,10 +90,13 @@ struct e1000_adapter;
#define E1000_ERR(args...) printk(KERN_ERR "e1000: " args)
#define PFX "e1000: "
-#define DPRINTK(nlevel, klevel, fmt, args...) \
- (void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \
- printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \
- __FUNCTION__ , ## args))
+
+#define DPRINTK(nlevel, klevel, fmt, args...) \
+do { \
+ if (NETIF_MSG_##nlevel & adapter->msg_enable) \
+ printk(KERN_##klevel PFX "%s: %s: " fmt, \
+ adapter->netdev->name, __func__, ##args); \
+} while (0)
#define E1000_MAX_INTR 10
@@ -151,9 +154,9 @@ struct e1000_adapter;
#define E1000_MASTER_SLAVE e1000_ms_hw_default
#endif
-#define E1000_MNG_VLAN_NONE -1
+#define E1000_MNG_VLAN_NONE (-1)
/* Number of packet split data buffers (not including the header buffer) */
-#define PS_PAGE_BUFFERS MAX_PS_BUFFERS-1
+#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1)
/* wrapper around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer */
@@ -165,9 +168,13 @@ struct e1000_buffer {
u16 next_to_watch;
};
+struct e1000_ps_page {
+ struct page *ps_page[PS_PAGE_BUFFERS];
+};
-struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
-struct e1000_ps_page_dma { u64 ps_page_dma[PS_PAGE_BUFFERS]; };
+struct e1000_ps_page_dma {
+ u64 ps_page_dma[PS_PAGE_BUFFERS];
+};
struct e1000_tx_ring {
/* pointer to the descriptor ring memory */
@@ -217,13 +224,13 @@ struct e1000_rx_ring {
u16 rdt;
};
-#define E1000_DESC_UNUSED(R) \
- ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
- (R)->next_to_clean - (R)->next_to_use - 1)
+#define E1000_DESC_UNUSED(R) \
+ ((((R)->next_to_clean > (R)->next_to_use) \
+ ? 0 : (R)->count) + (R)->next_to_clean - (R)->next_to_use - 1)
-#define E1000_RX_DESC_PS(R, i) \
+#define E1000_RX_DESC_PS(R, i) \
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
-#define E1000_RX_DESC_EXT(R, i) \
+#define E1000_RX_DESC_EXT(R, i) \
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
@@ -246,9 +253,7 @@ struct e1000_adapter {
u16 link_speed;
u16 link_duplex;
spinlock_t stats_lock;
-#ifdef CONFIG_E1000_NAPI
spinlock_t tx_queue_lock;
-#endif
unsigned int total_tx_bytes;
unsigned int total_tx_packets;
unsigned int total_rx_bytes;
@@ -286,22 +291,16 @@ struct e1000_adapter {
bool detect_tx_hung;
/* RX */
-#ifdef CONFIG_E1000_NAPI
- bool (*clean_rx) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int *work_done, int work_to_do);
-#else
- bool (*clean_rx) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
-#endif
- void (*alloc_rx_buf) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int cleaned_count);
+ bool (*clean_rx)(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do);
+ void (*alloc_rx_buf)(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count);
struct e1000_rx_ring *rx_ring; /* One per active queue */
-#ifdef CONFIG_E1000_NAPI
struct napi_struct napi;
struct net_device *polling_netdev; /* One per active queue */
-#endif
+
int num_tx_queues;
int num_rx_queues;
@@ -317,7 +316,6 @@ struct e1000_adapter {
u64 gorcl_old;
u16 rx_ps_bsize0;
-
/* OS defined structs */
struct net_device *netdev;
struct pci_dev *pdev;
@@ -342,6 +340,10 @@ struct e1000_adapter {
bool quad_port_a;
unsigned long flags;
u32 eeprom_wol;
+
+ /* for ioport free */
+ int bars;
+ int need_ioport;
};
enum e1000_state_t {
@@ -353,9 +355,18 @@ enum e1000_state_t {
extern char e1000_driver_name[];
extern const char e1000_driver_version[];
+extern int e1000_up(struct e1000_adapter *adapter);
+extern void e1000_down(struct e1000_adapter *adapter);
+extern void e1000_reinit_locked(struct e1000_adapter *adapter);
+extern void e1000_reset(struct e1000_adapter *adapter);
+extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
+extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
+extern void e1000_update_stats(struct e1000_adapter *adapter);
extern void e1000_power_up_phy(struct e1000_adapter *);
extern void e1000_set_ethtool_ops(struct net_device *netdev);
extern void e1000_check_options(struct e1000_adapter *adapter);
-
#endif /* _E1000_H_ */
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index a3f6a9c72ec..6a3893acfe0 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -29,21 +29,8 @@
/* ethtool support for e1000 */
#include "e1000.h"
-
#include <asm/uaccess.h>
-extern int e1000_up(struct e1000_adapter *adapter);
-extern void e1000_down(struct e1000_adapter *adapter);
-extern void e1000_reinit_locked(struct e1000_adapter *adapter);
-extern void e1000_reset(struct e1000_adapter *adapter);
-extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
-extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
-extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_update_stats(struct e1000_adapter *adapter);
-
-
struct e1000_stats {
char stat_string[ETH_GSTRING_LEN];
int sizeof_stat;
@@ -112,8 +99,8 @@ static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
};
#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test)
-static int
-e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+static int e1000_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -162,7 +149,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->transceiver = XCVR_EXTERNAL;
}
- if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU) {
+ if (er32(STATUS) & E1000_STATUS_LU) {
e1000_get_speed_and_duplex(hw, &adapter->link_speed,
&adapter->link_duplex);
@@ -185,8 +172,8 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
return 0;
}
-static int
-e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+static int e1000_set_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -231,9 +218,8 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
return 0;
}
-static void
-e1000_get_pauseparam(struct net_device *netdev,
- struct ethtool_pauseparam *pause)
+static void e1000_get_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -251,9 +237,8 @@ e1000_get_pauseparam(struct net_device *netdev,
}
}
-static int
-e1000_set_pauseparam(struct net_device *netdev,
- struct ethtool_pauseparam *pause)
+static int e1000_set_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -289,15 +274,13 @@ e1000_set_pauseparam(struct net_device *netdev,
return retval;
}
-static u32
-e1000_get_rx_csum(struct net_device *netdev)
+static u32 e1000_get_rx_csum(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
return adapter->rx_csum;
}
-static int
-e1000_set_rx_csum(struct net_device *netdev, u32 data)
+static int e1000_set_rx_csum(struct net_device *netdev, u32 data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
adapter->rx_csum = data;
@@ -309,18 +292,17 @@ e1000_set_rx_csum(struct net_device *netdev, u32 data)
return 0;
}
-static u32
-e1000_get_tx_csum(struct net_device *netdev)
+static u32 e1000_get_tx_csum(struct net_device *netdev)
{
return (netdev->features & NETIF_F_HW_CSUM) != 0;
}
-static int
-e1000_set_tx_csum(struct net_device *netdev, u32 data)
+static int e1000_set_tx_csum(struct net_device *netdev, u32 data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
- if (adapter->hw.mac_type < e1000_82543) {
+ if (hw->mac_type < e1000_82543) {
if (!data)
return -EINVAL;
return 0;
@@ -334,12 +316,13 @@ e1000_set_tx_csum(struct net_device *netdev, u32 data)
return 0;
}
-static int
-e1000_set_tso(struct net_device *netdev, u32 data)
+static int e1000_set_tso(struct net_device *netdev, u32 data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if ((adapter->hw.mac_type < e1000_82544) ||
- (adapter->hw.mac_type == e1000_82547))
+ struct e1000_hw *hw = &adapter->hw;
+
+ if ((hw->mac_type < e1000_82544) ||
+ (hw->mac_type == e1000_82547))
return data ? -EINVAL : 0;
if (data)
@@ -357,30 +340,26 @@ e1000_set_tso(struct net_device *netdev, u32 data)
return 0;
}
-static u32
-e1000_get_msglevel(struct net_device *netdev)
+static u32 e1000_get_msglevel(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
return adapter->msg_enable;
}
-static void
-e1000_set_msglevel(struct net_device *netdev, u32 data)
+static void e1000_set_msglevel(struct net_device *netdev, u32 data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
adapter->msg_enable = data;
}
-static int
-e1000_get_regs_len(struct net_device *netdev)
+static int e1000_get_regs_len(struct net_device *netdev)
{
#define E1000_REGS_LEN 32
return E1000_REGS_LEN * sizeof(u32);
}
-static void
-e1000_get_regs(struct net_device *netdev,
- struct ethtool_regs *regs, void *p)
+static void e1000_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
+ void *p)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -391,22 +370,22 @@ e1000_get_regs(struct net_device *netdev,
regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
- regs_buff[0] = E1000_READ_REG(hw, CTRL);
- regs_buff[1] = E1000_READ_REG(hw, STATUS);
+ regs_buff[0] = er32(CTRL);
+ regs_buff[1] = er32(STATUS);
- regs_buff[2] = E1000_READ_REG(hw, RCTL);
- regs_buff[3] = E1000_READ_REG(hw, RDLEN);
- regs_buff[4] = E1000_READ_REG(hw, RDH);
- regs_buff[5] = E1000_READ_REG(hw, RDT);
- regs_buff[6] = E1000_READ_REG(hw, RDTR);
+ regs_buff[2] = er32(RCTL);
+ regs_buff[3] = er32(RDLEN);
+ regs_buff[4] = er32(RDH);
+ regs_buff[5] = er32(RDT);
+ regs_buff[6] = er32(RDTR);
- regs_buff[7] = E1000_READ_REG(hw, TCTL);
- regs_buff[8] = E1000_READ_REG(hw, TDLEN);
- regs_buff[9] = E1000_READ_REG(hw, TDH);
- regs_buff[10] = E1000_READ_REG(hw, TDT);
- regs_buff[11] = E1000_READ_REG(hw, TIDV);
+ regs_buff[7] = er32(TCTL);
+ regs_buff[8] = er32(TDLEN);
+ regs_buff[9] = er32(TDH);
+ regs_buff[10] = er32(TDT);
+ regs_buff[11] = er32(TIDV);
- regs_buff[12] = adapter->hw.phy_type; /* PHY type (IGP=1, M88=0) */
+ regs_buff[12] = hw->phy_type; /* PHY type (IGP=1, M88=0) */
if (hw->phy_type == e1000_phy_igp) {
e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
IGP01E1000_PHY_AGC_A);
@@ -464,20 +443,20 @@ e1000_get_regs(struct net_device *netdev,
if (hw->mac_type >= e1000_82540 &&
hw->mac_type < e1000_82571 &&
hw->media_type == e1000_media_type_copper) {
- regs_buff[26] = E1000_READ_REG(hw, MANC);
+ regs_buff[26] = er32(MANC);
}
}
-static int
-e1000_get_eeprom_len(struct net_device *netdev)
+static int e1000_get_eeprom_len(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- return adapter->hw.eeprom.word_size * 2;
+ struct e1000_hw *hw = &adapter->hw;
+
+ return hw->eeprom.word_size * 2;
}
-static int
-e1000_get_eeprom(struct net_device *netdev,
- struct ethtool_eeprom *eeprom, u8 *bytes)
+static int e1000_get_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *bytes)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -504,10 +483,12 @@ e1000_get_eeprom(struct net_device *netdev,
last_word - first_word + 1,
eeprom_buff);
else {
- for (i = 0; i < last_word - first_word + 1; i++)
- if ((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
- &eeprom_buff[i])))
+ for (i = 0; i < last_word - first_word + 1; i++) {
+ ret_val = e1000_read_eeprom(hw, first_word + i, 1,
+ &eeprom_buff[i]);
+ if (ret_val)
break;
+ }
}
/* Device's eeprom is always little-endian, word addressable */
@@ -521,9 +502,8 @@ e1000_get_eeprom(struct net_device *netdev,
return ret_val;
}
-static int
-e1000_set_eeprom(struct net_device *netdev,
- struct ethtool_eeprom *eeprom, u8 *bytes)
+static int e1000_set_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *bytes)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -584,11 +564,11 @@ e1000_set_eeprom(struct net_device *netdev,
return ret_val;
}
-static void
-e1000_get_drvinfo(struct net_device *netdev,
- struct ethtool_drvinfo *drvinfo)
+static void e1000_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
char firmware_version[32];
u16 eeprom_data;
@@ -597,8 +577,8 @@ e1000_get_drvinfo(struct net_device *netdev,
/* EEPROM image version # is reported as firmware version # for
* 8257{1|2|3} controllers */
- e1000_read_eeprom(&adapter->hw, 5, 1, &eeprom_data);
- switch (adapter->hw.mac_type) {
+ e1000_read_eeprom(hw, 5, 1, &eeprom_data);
+ switch (hw->mac_type) {
case e1000_82571:
case e1000_82572:
case e1000_82573:
@@ -619,12 +599,12 @@ e1000_get_drvinfo(struct net_device *netdev,
drvinfo->eedump_len = e1000_get_eeprom_len(netdev);
}
-static void
-e1000_get_ringparam(struct net_device *netdev,
- struct ethtool_ringparam *ring)
+static void e1000_get_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- e1000_mac_type mac_type = adapter->hw.mac_type;
+ struct e1000_hw *hw = &adapter->hw;
+ e1000_mac_type mac_type = hw->mac_type;
struct e1000_tx_ring *txdr = adapter->tx_ring;
struct e1000_rx_ring *rxdr = adapter->rx_ring;
@@ -640,12 +620,12 @@ e1000_get_ringparam(struct net_device *netdev,
ring->rx_jumbo_pending = 0;
}
-static int
-e1000_set_ringparam(struct net_device *netdev,
- struct ethtool_ringparam *ring)
+static int e1000_set_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- e1000_mac_type mac_type = adapter->hw.mac_type;
+ struct e1000_hw *hw = &adapter->hw;
+ e1000_mac_type mac_type = hw->mac_type;
struct e1000_tx_ring *txdr, *tx_old;
struct e1000_rx_ring *rxdr, *rx_old;
int i, err;
@@ -691,9 +671,11 @@ e1000_set_ringparam(struct net_device *netdev,
if (netif_running(adapter->netdev)) {
/* Try to get new resources before deleting old */
- if ((err = e1000_setup_all_rx_resources(adapter)))
+ err = e1000_setup_all_rx_resources(adapter);
+ if (err)
goto err_setup_rx;
- if ((err = e1000_setup_all_tx_resources(adapter)))
+ err = e1000_setup_all_tx_resources(adapter);
+ if (err)
goto err_setup_tx;
/* save the new, restore the old in order to free it,
@@ -707,7 +689,8 @@ e1000_set_ringparam(struct net_device *netdev,
kfree(rx_old);
adapter->rx_ring = rxdr;
adapter->tx_ring = txdr;
- if ((err = e1000_up(adapter)))
+ err = e1000_up(adapter);
+ if (err)
goto err_setup;
}
@@ -728,12 +711,13 @@ err_setup:
return err;
}
-static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data,
- int reg, u32 mask, u32 write)
+static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data, int reg,
+ u32 mask, u32 write)
{
+ struct e1000_hw *hw = &adapter->hw;
static const u32 test[] =
{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
- u8 __iomem *address = adapter->hw.hw_addr + reg;
+ u8 __iomem *address = hw->hw_addr + reg;
u32 read;
int i;
@@ -751,10 +735,11 @@ static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data,
return false;
}
-static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
- int reg, u32 mask, u32 write)
+static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data, int reg,
+ u32 mask, u32 write)
{
- u8 __iomem *address = adapter->hw.hw_addr + reg;
+ struct e1000_hw *hw = &adapter->hw;
+ u8 __iomem *address = hw->hw_addr + reg;
u32 read;
writel(write & mask, address);
@@ -772,7 +757,7 @@ static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
#define REG_PATTERN_TEST(reg, mask, write) \
do { \
if (reg_pattern_test(adapter, data, \
- (adapter->hw.mac_type >= e1000_82543) \
+ (hw->mac_type >= e1000_82543) \
? E1000_##reg : E1000_82542_##reg, \
mask, write)) \
return 1; \
@@ -781,22 +766,22 @@ static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
#define REG_SET_AND_CHECK(reg, mask, write) \
do { \
if (reg_set_and_check(adapter, data, \
- (adapter->hw.mac_type >= e1000_82543) \
+ (hw->mac_type >= e1000_82543) \
? E1000_##reg : E1000_82542_##reg, \
mask, write)) \
return 1; \
} while (0)
-static int
-e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
+static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
{
u32 value, before, after;
u32 i, toggle;
+ struct e1000_hw *hw = &adapter->hw;
/* The status register is Read Only, so a write should fail.
* Some bits that get toggled are ignored.
*/
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
/* there are several bits on newer hardware that are r/w */
case e1000_82571:
case e1000_82572:
@@ -812,10 +797,10 @@ e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
break;
}
- before = E1000_READ_REG(&adapter->hw, STATUS);
- value = (E1000_READ_REG(&adapter->hw, STATUS) & toggle);
- E1000_WRITE_REG(&adapter->hw, STATUS, toggle);
- after = E1000_READ_REG(&adapter->hw, STATUS) & toggle;
+ before = er32(STATUS);
+ value = (er32(STATUS) & toggle);
+ ew32(STATUS, toggle);
+ after = er32(STATUS) & toggle;
if (value != after) {
DPRINTK(DRV, ERR, "failed STATUS register test got: "
"0x%08X expected: 0x%08X\n", after, value);
@@ -823,9 +808,9 @@ e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
return 1;
}
/* restore previous status */
- E1000_WRITE_REG(&adapter->hw, STATUS, before);
+ ew32(STATUS, before);
- if (adapter->hw.mac_type != e1000_ich8lan) {
+ if (hw->mac_type != e1000_ich8lan) {
REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);
@@ -845,20 +830,20 @@ e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000);
- before = (adapter->hw.mac_type == e1000_ich8lan ?
+ before = (hw->mac_type == e1000_ich8lan ?
0x06C3B33E : 0x06DFB3FE);
REG_SET_AND_CHECK(RCTL, before, 0x003FFFFB);
REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
- if (adapter->hw.mac_type >= e1000_82543) {
+ if (hw->mac_type >= e1000_82543) {
REG_SET_AND_CHECK(RCTL, before, 0xFFFFFFFF);
REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
- if (adapter->hw.mac_type != e1000_ich8lan)
+ if (hw->mac_type != e1000_ich8lan)
REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);
REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
- value = (adapter->hw.mac_type == e1000_ich8lan ?
+ value = (hw->mac_type == e1000_ich8lan ?
E1000_RAR_ENTRIES_ICH8LAN : E1000_RAR_ENTRIES);
for (i = 0; i < value; i++) {
REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
@@ -874,7 +859,7 @@ e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
}
- value = (adapter->hw.mac_type == e1000_ich8lan ?
+ value = (hw->mac_type == e1000_ich8lan ?
E1000_MC_TBL_SIZE_ICH8LAN : E1000_MC_TBL_SIZE);
for (i = 0; i < value; i++)
REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
@@ -883,9 +868,9 @@ e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
return 0;
}
-static int
-e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
+static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
{
+ struct e1000_hw *hw = &adapter->hw;
u16 temp;
u16 checksum = 0;
u16 i;
@@ -893,7 +878,7 @@ e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
*data = 0;
/* Read and add up the contents of the EEPROM */
for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
- if ((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) {
+ if ((e1000_read_eeprom(hw, i, 1, &temp)) < 0) {
*data = 1;
break;
}
@@ -901,30 +886,30 @@ e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
}
/* If Checksum is not Correct return error else test passed */
- if ((checksum != (u16) EEPROM_SUM) && !(*data))
+ if ((checksum != (u16)EEPROM_SUM) && !(*data))
*data = 2;
return *data;
}
-static irqreturn_t
-e1000_test_intr(int irq, void *data)
+static irqreturn_t e1000_test_intr(int irq, void *data)
{
- struct net_device *netdev = (struct net_device *) data;
+ struct net_device *netdev = (struct net_device *)data;
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
- adapter->test_icr |= E1000_READ_REG(&adapter->hw, ICR);
+ adapter->test_icr |= er32(ICR);
return IRQ_HANDLED;
}
-static int
-e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
+static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
{
struct net_device *netdev = adapter->netdev;
u32 mask, i = 0;
bool shared_int = true;
u32 irq = adapter->pdev->irq;
+ struct e1000_hw *hw = &adapter->hw;
*data = 0;
@@ -942,13 +927,13 @@ e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
(shared_int ? "shared" : "unshared"));
/* Disable all the interrupts */
- E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);
+ ew32(IMC, 0xFFFFFFFF);
msleep(10);
/* Test each interrupt */
for (; i < 10; i++) {
- if (adapter->hw.mac_type == e1000_ich8lan && i == 8)
+ if (hw->mac_type == e1000_ich8lan && i == 8)
continue;
/* Interrupt to test */
@@ -962,8 +947,8 @@ e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
* test failed.
*/
adapter->test_icr = 0;
- E1000_WRITE_REG(&adapter->hw, IMC, mask);
- E1000_WRITE_REG(&adapter->hw, ICS, mask);
+ ew32(IMC, mask);
+ ew32(ICS, mask);
msleep(10);
if (adapter->test_icr & mask) {
@@ -979,8 +964,8 @@ e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
* test failed.
*/
adapter->test_icr = 0;
- E1000_WRITE_REG(&adapter->hw, IMS, mask);
- E1000_WRITE_REG(&adapter->hw, ICS, mask);
+ ew32(IMS, mask);
+ ew32(ICS, mask);
msleep(10);
if (!(adapter->test_icr & mask)) {
@@ -996,8 +981,8 @@ e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
* test failed.
*/
adapter->test_icr = 0;
- E1000_WRITE_REG(&adapter->hw, IMC, ~mask & 0x00007FFF);
- E1000_WRITE_REG(&adapter->hw, ICS, ~mask & 0x00007FFF);
+ ew32(IMC, ~mask & 0x00007FFF);
+ ew32(ICS, ~mask & 0x00007FFF);
msleep(10);
if (adapter->test_icr) {
@@ -1008,7 +993,7 @@ e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
}
/* Disable all the interrupts */
- E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);
+ ew32(IMC, 0xFFFFFFFF);
msleep(10);
/* Unhook test interrupt handler */
@@ -1017,8 +1002,7 @@ e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
return *data;
}
-static void
-e1000_free_desc_rings(struct e1000_adapter *adapter)
+static void e1000_free_desc_rings(struct e1000_adapter *adapter)
{
struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
@@ -1064,9 +1048,9 @@ e1000_free_desc_rings(struct e1000_adapter *adapter)
return;
}
-static int
-e1000_setup_desc_rings(struct e1000_adapter *adapter)
+static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
@@ -1078,41 +1062,39 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
if (!txdr->count)
txdr->count = E1000_DEFAULT_TXD;
- if (!(txdr->buffer_info = kcalloc(txdr->count,
- sizeof(struct e1000_buffer),
- GFP_KERNEL))) {
+ txdr->buffer_info = kcalloc(txdr->count, sizeof(struct e1000_buffer),
+ GFP_KERNEL);
+ if (!txdr->buffer_info) {
ret_val = 1;
goto err_nomem;
}
txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
txdr->size = ALIGN(txdr->size, 4096);
- if (!(txdr->desc = pci_alloc_consistent(pdev, txdr->size,
- &txdr->dma))) {
+ txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
+ if (!txdr->desc) {
ret_val = 2;
goto err_nomem;
}
memset(txdr->desc, 0, txdr->size);
txdr->next_to_use = txdr->next_to_clean = 0;
- E1000_WRITE_REG(&adapter->hw, TDBAL,
- ((u64) txdr->dma & 0x00000000FFFFFFFF));
- E1000_WRITE_REG(&adapter->hw, TDBAH, ((u64) txdr->dma >> 32));
- E1000_WRITE_REG(&adapter->hw, TDLEN,
- txdr->count * sizeof(struct e1000_tx_desc));
- E1000_WRITE_REG(&adapter->hw, TDH, 0);
- E1000_WRITE_REG(&adapter->hw, TDT, 0);
- E1000_WRITE_REG(&adapter->hw, TCTL,
- E1000_TCTL_PSP | E1000_TCTL_EN |
- E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
- E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT);
+ ew32(TDBAL, ((u64)txdr->dma & 0x00000000FFFFFFFF));
+ ew32(TDBAH, ((u64)txdr->dma >> 32));
+ ew32(TDLEN, txdr->count * sizeof(struct e1000_tx_desc));
+ ew32(TDH, 0);
+ ew32(TDT, 0);
+ ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN |
+ E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
+ E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT);
for (i = 0; i < txdr->count; i++) {
struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*txdr, i);
struct sk_buff *skb;
unsigned int size = 1024;
- if (!(skb = alloc_skb(size, GFP_KERNEL))) {
+ skb = alloc_skb(size, GFP_KERNEL);
+ if (!skb) {
ret_val = 3;
goto err_nomem;
}
@@ -1135,40 +1117,40 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
if (!rxdr->count)
rxdr->count = E1000_DEFAULT_RXD;
- if (!(rxdr->buffer_info = kcalloc(rxdr->count,
- sizeof(struct e1000_buffer),
- GFP_KERNEL))) {
+ rxdr->buffer_info = kcalloc(rxdr->count, sizeof(struct e1000_buffer),
+ GFP_KERNEL);
+ if (!rxdr->buffer_info) {
ret_val = 4;
goto err_nomem;
}
rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
- if (!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) {
+ rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
+ if (!rxdr->desc) {
ret_val = 5;
goto err_nomem;
}
memset(rxdr->desc, 0, rxdr->size);
rxdr->next_to_use = rxdr->next_to_clean = 0;
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
- E1000_WRITE_REG(&adapter->hw, RDBAL,
- ((u64) rxdr->dma & 0xFFFFFFFF));
- E1000_WRITE_REG(&adapter->hw, RDBAH, ((u64) rxdr->dma >> 32));
- E1000_WRITE_REG(&adapter->hw, RDLEN, rxdr->size);
- E1000_WRITE_REG(&adapter->hw, RDH, 0);
- E1000_WRITE_REG(&adapter->hw, RDT, 0);
+ rctl = er32(RCTL);
+ ew32(RCTL, rctl & ~E1000_RCTL_EN);
+ ew32(RDBAL, ((u64)rxdr->dma & 0xFFFFFFFF));
+ ew32(RDBAH, ((u64)rxdr->dma >> 32));
+ ew32(RDLEN, rxdr->size);
+ ew32(RDH, 0);
+ ew32(RDT, 0);
rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |
E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
- (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ (hw->mc_filter_type << E1000_RCTL_MO_SHIFT);
+ ew32(RCTL, rctl);
for (i = 0; i < rxdr->count; i++) {
struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i);
struct sk_buff *skb;
- if (!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN,
- GFP_KERNEL))) {
+ skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL);
+ if (!skb) {
ret_val = 6;
goto err_nomem;
}
@@ -1189,73 +1171,74 @@ err_nomem:
return ret_val;
}
-static void
-e1000_phy_disable_receiver(struct e1000_adapter *adapter)
+static void e1000_phy_disable_receiver(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
+
/* Write out to PHY registers 29 and 30 to disable the Receiver. */
- e1000_write_phy_reg(&adapter->hw, 29, 0x001F);
- e1000_write_phy_reg(&adapter->hw, 30, 0x8FFC);
- e1000_write_phy_reg(&adapter->hw, 29, 0x001A);
- e1000_write_phy_reg(&adapter->hw, 30, 0x8FF0);
+ e1000_write_phy_reg(hw, 29, 0x001F);
+ e1000_write_phy_reg(hw, 30, 0x8FFC);
+ e1000_write_phy_reg(hw, 29, 0x001A);
+ e1000_write_phy_reg(hw, 30, 0x8FF0);
}
-static void
-e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
+static void e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
u16 phy_reg;
/* Because we reset the PHY above, we need to re-force TX_CLK in the
* Extended PHY Specific Control Register to 25MHz clock. This
* value defaults back to a 2.5MHz clock when the PHY is reset.
*/
- e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
+ e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
phy_reg |= M88E1000_EPSCR_TX_CLK_25;
- e1000_write_phy_reg(&adapter->hw,
+ e1000_write_phy_reg(hw,
M88E1000_EXT_PHY_SPEC_CTRL, phy_reg);
/* In addition, because of the s/w reset above, we need to enable
* CRS on TX. This must be set for both full and half duplex
* operation.
*/
- e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
+ e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
phy_reg |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
- e1000_write_phy_reg(&adapter->hw,
+ e1000_write_phy_reg(hw,
M88E1000_PHY_SPEC_CTRL, phy_reg);
}
-static int
-e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
+static int e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
u32 ctrl_reg;
u16 phy_reg;
/* Setup the Device Control Register for PHY loopback test. */
- ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
+ ctrl_reg = er32(CTRL);
ctrl_reg |= (E1000_CTRL_ILOS | /* Invert Loss-Of-Signal */
E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
E1000_CTRL_SPD_1000 | /* Force Speed to 1000 */
E1000_CTRL_FD); /* Force Duplex to FULL */
- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg);
+ ew32(CTRL, ctrl_reg);
/* Read the PHY Specific Control Register (0x10) */
- e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
+ e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
/* Clear Auto-Crossover bits in PHY Specific Control Register
* (bits 6:5).
*/
phy_reg &= ~M88E1000_PSCR_AUTO_X_MODE;
- e1000_write_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, phy_reg);
+ e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_reg);
/* Perform software reset on the PHY */
- e1000_phy_reset(&adapter->hw);
+ e1000_phy_reset(hw);
/* Have to setup TX_CLK and TX_CRS after software reset */
e1000_phy_reset_clk_and_crs(adapter);
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8100);
+ e1000_write_phy_reg(hw, PHY_CTRL, 0x8100);
/* Wait for reset to complete. */
udelay(500);
@@ -1267,55 +1250,55 @@ e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
e1000_phy_disable_receiver(adapter);
/* Set the loopback bit in the PHY control register. */
- e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+ e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
phy_reg |= MII_CR_LOOPBACK;
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
+ e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
/* Setup TX_CLK and TX_CRS one more time. */
e1000_phy_reset_clk_and_crs(adapter);
/* Check Phy Configuration */
- e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+ e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
if (phy_reg != 0x4100)
return 9;
- e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
+ e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
if (phy_reg != 0x0070)
return 10;
- e1000_read_phy_reg(&adapter->hw, 29, &phy_reg);
+ e1000_read_phy_reg(hw, 29, &phy_reg);
if (phy_reg != 0x001A)
return 11;
return 0;
}
-static int
-e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
u32 ctrl_reg = 0;
u32 stat_reg = 0;
- adapter->hw.autoneg = false;
+ hw->autoneg = false;
- if (adapter->hw.phy_type == e1000_phy_m88) {
+ if (hw->phy_type == e1000_phy_m88) {
/* Auto-MDI/MDIX Off */
- e1000_write_phy_reg(&adapter->hw,
+ e1000_write_phy_reg(hw,
M88E1000_PHY_SPEC_CTRL, 0x0808);
/* reset to update Auto-MDI/MDIX */
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x9140);
+ e1000_write_phy_reg(hw, PHY_CTRL, 0x9140);
/* autoneg off */
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8140);
- } else if (adapter->hw.phy_type == e1000_phy_gg82563)
- e1000_write_phy_reg(&adapter->hw,
+ e1000_write_phy_reg(hw, PHY_CTRL, 0x8140);
+ } else if (hw->phy_type == e1000_phy_gg82563)
+ e1000_write_phy_reg(hw,
GG82563_PHY_KMRN_MODE_CTRL,
0x1CC);
- ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
+ ctrl_reg = er32(CTRL);
- if (adapter->hw.phy_type == e1000_phy_ife) {
+ if (hw->phy_type == e1000_phy_ife) {
/* force 100, set loopback */
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x6100);
+ e1000_write_phy_reg(hw, PHY_CTRL, 0x6100);
/* Now set up the MAC to the same speed/duplex as the PHY. */
ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
@@ -1325,10 +1308,10 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
E1000_CTRL_FD); /* Force Duplex to FULL */
} else {
/* force 1000, set loopback */
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x4140);
+ e1000_write_phy_reg(hw, PHY_CTRL, 0x4140);
/* Now set up the MAC to the same speed/duplex as the PHY. */
- ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
+ ctrl_reg = er32(CTRL);
ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
@@ -1336,23 +1319,23 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
E1000_CTRL_FD); /* Force Duplex to FULL */
}
- if (adapter->hw.media_type == e1000_media_type_copper &&
- adapter->hw.phy_type == e1000_phy_m88)
+ if (hw->media_type == e1000_media_type_copper &&
+ hw->phy_type == e1000_phy_m88)
ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
else {
/* Set the ILOS bit on the fiber Nic is half
* duplex link is detected. */
- stat_reg = E1000_READ_REG(&adapter->hw, STATUS);
+ stat_reg = er32(STATUS);
if ((stat_reg & E1000_STATUS_FD) == 0)
ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
}
- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg);
+ ew32(CTRL, ctrl_reg);
/* Disable the receiver on the PHY so when a cable is plugged in, the
* PHY does not begin to autoneg when a cable is reconnected to the NIC.
*/
- if (adapter->hw.phy_type == e1000_phy_m88)
+ if (hw->phy_type == e1000_phy_m88)
e1000_phy_disable_receiver(adapter);
udelay(500);
@@ -1360,15 +1343,15 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
return 0;
}
-static int
-e1000_set_phy_loopback(struct e1000_adapter *adapter)
+static int e1000_set_phy_loopback(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
u16 phy_reg = 0;
u16 count = 0;
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82543:
- if (adapter->hw.media_type == e1000_media_type_copper) {
+ if (hw->media_type == e1000_media_type_copper) {
/* Attempt to setup Loopback mode on Non-integrated PHY.
* Some PHY registers get corrupted at random, so
* attempt this 10 times.
@@ -1402,9 +1385,9 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
/* Default PHY loopback work is to read the MII
* control register and assert bit 14 (loopback mode).
*/
- e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+ e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
phy_reg |= MII_CR_LOOPBACK;
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
+ e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
return 0;
break;
}
@@ -1412,8 +1395,7 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
return 8;
}
-static int
-e1000_setup_loopback_test(struct e1000_adapter *adapter)
+static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u32 rctl;
@@ -1431,14 +1413,14 @@ e1000_setup_loopback_test(struct e1000_adapter *adapter)
case e1000_82572:
#define E1000_SERDES_LB_ON 0x410
e1000_set_phy_loopback(adapter);
- E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_ON);
+ ew32(SCTL, E1000_SERDES_LB_ON);
msleep(10);
return 0;
break;
default:
- rctl = E1000_READ_REG(hw, RCTL);
+ rctl = er32(RCTL);
rctl |= E1000_RCTL_LBM_TCVR;
- E1000_WRITE_REG(hw, RCTL, rctl);
+ ew32(RCTL, rctl);
return 0;
}
} else if (hw->media_type == e1000_media_type_copper)
@@ -1447,16 +1429,15 @@ e1000_setup_loopback_test(struct e1000_adapter *adapter)
return 7;
}
-static void
-e1000_loopback_cleanup(struct e1000_adapter *adapter)
+static void e1000_loopback_cleanup(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u32 rctl;
u16 phy_reg;
- rctl = E1000_READ_REG(hw, RCTL);
+ rctl = er32(RCTL);
rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
- E1000_WRITE_REG(hw, RCTL, rctl);
+ ew32(RCTL, rctl);
switch (hw->mac_type) {
case e1000_82571:
@@ -1464,7 +1445,7 @@ e1000_loopback_cleanup(struct e1000_adapter *adapter)
if (hw->media_type == e1000_media_type_fiber ||
hw->media_type == e1000_media_type_internal_serdes) {
#define E1000_SERDES_LB_OFF 0x400
- E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_OFF);
+ ew32(SCTL, E1000_SERDES_LB_OFF);
msleep(10);
break;
}
@@ -1489,8 +1470,8 @@ e1000_loopback_cleanup(struct e1000_adapter *adapter)
}
}
-static void
-e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
+static void e1000_create_lbtest_frame(struct sk_buff *skb,
+ unsigned int frame_size)
{
memset(skb->data, 0xFF, frame_size);
frame_size &= ~1;
@@ -1499,8 +1480,8 @@ e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);
}
-static int
-e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
+static int e1000_check_lbtest_frame(struct sk_buff *skb,
+ unsigned int frame_size)
{
frame_size &= ~1;
if (*(skb->data + 3) == 0xFF) {
@@ -1512,16 +1493,16 @@ e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
return 13;
}
-static int
-e1000_run_loopback_test(struct e1000_adapter *adapter)
+static int e1000_run_loopback_test(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
int i, j, k, l, lc, good_cnt, ret_val=0;
unsigned long time;
- E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1);
+ ew32(RDT, rxdr->count - 1);
/* Calculate the loop count based on the largest descriptor ring
* The idea is to wrap the largest ring a number of times using 64
@@ -1544,7 +1525,7 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
PCI_DMA_TODEVICE);
if (unlikely(++k == txdr->count)) k = 0;
}
- E1000_WRITE_REG(&adapter->hw, TDT, k);
+ ew32(TDT, k);
msleep(200);
time = jiffies; /* set the start time for the receive */
good_cnt = 0;
@@ -1577,21 +1558,24 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
return ret_val;
}
-static int
-e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
+static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
{
+ struct e1000_hw *hw = &adapter->hw;
+
/* PHY loopback cannot be performed if SoL/IDER
* sessions are active */
- if (e1000_check_phy_reset_block(&adapter->hw)) {
+ if (e1000_check_phy_reset_block(hw)) {
DPRINTK(DRV, ERR, "Cannot do PHY loopback test "
"when SoL/IDER is active.\n");
*data = 0;
goto out;
}
- if ((*data = e1000_setup_desc_rings(adapter)))
+ *data = e1000_setup_desc_rings(adapter);
+ if (*data)
goto out;
- if ((*data = e1000_setup_loopback_test(adapter)))
+ *data = e1000_setup_loopback_test(adapter);
+ if (*data)
goto err_loopback;
*data = e1000_run_loopback_test(adapter);
e1000_loopback_cleanup(adapter);
@@ -1602,38 +1586,37 @@ out:
return *data;
}
-static int
-e1000_link_test(struct e1000_adapter *adapter, u64 *data)
+static int e1000_link_test(struct e1000_adapter *adapter, u64 *data)
{
+ struct e1000_hw *hw = &adapter->hw;
*data = 0;
- if (adapter->hw.media_type == e1000_media_type_internal_serdes) {
+ if (hw->media_type == e1000_media_type_internal_serdes) {
int i = 0;
- adapter->hw.serdes_link_down = true;
+ hw->serdes_link_down = true;
/* On some blade server designs, link establishment
* could take as long as 2-3 minutes */
do {
- e1000_check_for_link(&adapter->hw);
- if (!adapter->hw.serdes_link_down)
+ e1000_check_for_link(hw);
+ if (!hw->serdes_link_down)
return *data;
msleep(20);
} while (i++ < 3750);
*data = 1;
} else {
- e1000_check_for_link(&adapter->hw);
- if (adapter->hw.autoneg) /* if auto_neg is set wait for it */
+ e1000_check_for_link(hw);
+ if (hw->autoneg) /* if auto_neg is set wait for it */
msleep(4000);
- if (!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
+ if (!(er32(STATUS) & E1000_STATUS_LU)) {
*data = 1;
}
}
return *data;
}
-static int
-e1000_get_sset_count(struct net_device *netdev, int sset)
+static int e1000_get_sset_count(struct net_device *netdev, int sset)
{
switch (sset) {
case ETH_SS_TEST:
@@ -1645,11 +1628,11 @@ e1000_get_sset_count(struct net_device *netdev, int sset)
}
}
-static void
-e1000_diag_test(struct net_device *netdev,
- struct ethtool_test *eth_test, u64 *data)
+static void e1000_diag_test(struct net_device *netdev,
+ struct ethtool_test *eth_test, u64 *data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
bool if_running = netif_running(netdev);
set_bit(__E1000_TESTING, &adapter->flags);
@@ -1657,9 +1640,9 @@ e1000_diag_test(struct net_device *netdev,
/* Offline tests */
/* save speed, duplex, autoneg settings */
- u16 autoneg_advertised = adapter->hw.autoneg_advertised;
- u8 forced_speed_duplex = adapter->hw.forced_speed_duplex;
- u8 autoneg = adapter->hw.autoneg;
+ u16 autoneg_advertised = hw->autoneg_advertised;
+ u8 forced_speed_duplex = hw->forced_speed_duplex;
+ u8 autoneg = hw->autoneg;
DPRINTK(HW, INFO, "offline testing starting\n");
@@ -1692,9 +1675,9 @@ e1000_diag_test(struct net_device *netdev,
eth_test->flags |= ETH_TEST_FL_FAILED;
/* restore speed, duplex, autoneg settings */
- adapter->hw.autoneg_advertised = autoneg_advertised;
- adapter->hw.forced_speed_duplex = forced_speed_duplex;
- adapter->hw.autoneg = autoneg;
+ hw->autoneg_advertised = autoneg_advertised;
+ hw->forced_speed_duplex = forced_speed_duplex;
+ hw->autoneg = autoneg;
e1000_reset(adapter);
clear_bit(__E1000_TESTING, &adapter->flags);
@@ -1717,7 +1700,8 @@ e1000_diag_test(struct net_device *netdev,
msleep_interruptible(4 * 1000);
}
-static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
+static int e1000_wol_exclusion(struct e1000_adapter *adapter,
+ struct ethtool_wolinfo *wol)
{
struct e1000_hw *hw = &adapter->hw;
int retval = 1; /* fail by default */
@@ -1742,7 +1726,7 @@ static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wol
case E1000_DEV_ID_82571EB_SERDES:
case E1000_DEV_ID_82571EB_COPPER:
/* Wake events not supported on port B */
- if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
+ if (er32(STATUS) & E1000_STATUS_FUNC_1) {
wol->supported = 0;
break;
}
@@ -1766,7 +1750,7 @@ static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wol
/* dual port cards only support WoL on port A from now on
* unless it was enabled in the eeprom for port B
* so exclude FUNC_1 ports from having WoL enabled */
- if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1 &&
+ if (er32(STATUS) & E1000_STATUS_FUNC_1 &&
!adapter->eeprom_wol) {
wol->supported = 0;
break;
@@ -1778,10 +1762,11 @@ static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wol
return retval;
}
-static void
-e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+static void e1000_get_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
wol->supported = WAKE_UCAST | WAKE_MCAST |
WAKE_BCAST | WAKE_MAGIC;
@@ -1793,7 +1778,7 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
return;
/* apply any specific unsupported masks here */
- switch (adapter->hw.device_id) {
+ switch (hw->device_id) {
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
/* KSP3 does not suppport UCAST wake-ups */
wol->supported &= ~WAKE_UCAST;
@@ -1818,8 +1803,7 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
return;
}
-static int
-e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -1863,61 +1847,60 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
/* bit defines for adapter->led_status */
#define E1000_LED_ON 0
-static void
-e1000_led_blink_callback(unsigned long data)
+static void e1000_led_blink_callback(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+ struct e1000_hw *hw = &adapter->hw;
if (test_and_change_bit(E1000_LED_ON, &adapter->led_status))
- e1000_led_off(&adapter->hw);
+ e1000_led_off(hw);
else
- e1000_led_on(&adapter->hw);
+ e1000_led_on(hw);
mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL);
}
-static int
-e1000_phys_id(struct net_device *netdev, u32 data)
+static int e1000_phys_id(struct net_device *netdev, u32 data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
if (!data)
data = INT_MAX;
- if (adapter->hw.mac_type < e1000_82571) {
+ if (hw->mac_type < e1000_82571) {
if (!adapter->blink_timer.function) {
init_timer(&adapter->blink_timer);
adapter->blink_timer.function = e1000_led_blink_callback;
- adapter->blink_timer.data = (unsigned long) adapter;
+ adapter->blink_timer.data = (unsigned long)adapter;
}
- e1000_setup_led(&adapter->hw);
+ e1000_setup_led(hw);
mod_timer(&adapter->blink_timer, jiffies);
msleep_interruptible(data * 1000);
del_timer_sync(&adapter->blink_timer);
- } else if (adapter->hw.phy_type == e1000_phy_ife) {
+ } else if (hw->phy_type == e1000_phy_ife) {
if (!adapter->blink_timer.function) {
init_timer(&adapter->blink_timer);
adapter->blink_timer.function = e1000_led_blink_callback;
- adapter->blink_timer.data = (unsigned long) adapter;
+ adapter->blink_timer.data = (unsigned long)adapter;
}
mod_timer(&adapter->blink_timer, jiffies);
msleep_interruptible(data * 1000);
del_timer_sync(&adapter->blink_timer);
e1000_write_phy_reg(&(adapter->hw), IFE_PHY_SPECIAL_CONTROL_LED, 0);
} else {
- e1000_blink_led_start(&adapter->hw);
+ e1000_blink_led_start(hw);
msleep_interruptible(data * 1000);
}
- e1000_led_off(&adapter->hw);
+ e1000_led_off(hw);
clear_bit(E1000_LED_ON, &adapter->led_status);
- e1000_cleanup_led(&adapter->hw);
+ e1000_cleanup_led(hw);
return 0;
}
-static int
-e1000_nway_reset(struct net_device *netdev)
+static int e1000_nway_reset(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
if (netif_running(netdev))
@@ -1925,9 +1908,8 @@ e1000_nway_reset(struct net_device *netdev)
return 0;
}
-static void
-e1000_get_ethtool_stats(struct net_device *netdev,
- struct ethtool_stats *stats, u64 *data)
+static void e1000_get_ethtool_stats(struct net_device *netdev,
+ struct ethtool_stats *stats, u64 *data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
int i;
@@ -1941,8 +1923,8 @@ e1000_get_ethtool_stats(struct net_device *netdev,
/* BUG_ON(i != E1000_STATS_LEN); */
}
-static void
-e1000_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
+static void e1000_get_strings(struct net_device *netdev, u32 stringset,
+ u8 *data)
{
u8 *p = data;
int i;
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 9a4b6cbddf2..9d6edf3e73f 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -42,48 +42,65 @@ static void e1000_release_software_semaphore(struct e1000_hw *hw);
static u8 e1000_arc_subsystem_valid(struct e1000_hw *hw);
static s32 e1000_check_downshift(struct e1000_hw *hw);
-static s32 e1000_check_polarity(struct e1000_hw *hw, e1000_rev_polarity *polarity);
+static s32 e1000_check_polarity(struct e1000_hw *hw,
+ e1000_rev_polarity *polarity);
static void e1000_clear_hw_cntrs(struct e1000_hw *hw);
static void e1000_clear_vfta(struct e1000_hw *hw);
static s32 e1000_commit_shadow_ram(struct e1000_hw *hw);
static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw,
- bool link_up);
+ bool link_up);
static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw);
static s32 e1000_detect_gig_phy(struct e1000_hw *hw);
static s32 e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank);
static s32 e1000_get_auto_rd_done(struct e1000_hw *hw);
-static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length, u16 *max_length);
+static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
+ u16 *max_length);
static s32 e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw);
static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw);
static s32 e1000_get_software_flag(struct e1000_hw *hw);
static s32 e1000_ich8_cycle_init(struct e1000_hw *hw);
static s32 e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout);
static s32 e1000_id_led_init(struct e1000_hw *hw);
-static s32 e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, u32 cnf_base_addr, u32 cnf_size);
+static s32 e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
+ u32 cnf_base_addr,
+ u32 cnf_size);
static s32 e1000_init_lcd_from_nvm(struct e1000_hw *hw);
static void e1000_init_rx_addrs(struct e1000_hw *hw);
static void e1000_initialize_hardware_bits(struct e1000_hw *hw);
static bool e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw);
static s32 e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
static s32 e1000_mng_enable_host_if(struct e1000_hw *hw);
-static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum);
-static s32 e1000_mng_write_cmd_header(struct e1000_hw* hw, struct e1000_host_mng_command_header* hdr);
+static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length,
+ u16 offset, u8 *sum);
+static s32 e1000_mng_write_cmd_header(struct e1000_hw* hw,
+ struct e1000_host_mng_command_header
+ *hdr);
static s32 e1000_mng_write_commit(struct e1000_hw *hw);
-static s32 e1000_phy_ife_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
-static s32 e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
-static s32 e1000_read_eeprom_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
-static s32 e1000_write_eeprom_eewr(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+static s32 e1000_phy_ife_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info);
+static s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info);
+static s32 e1000_read_eeprom_eerd(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
+static s32 e1000_write_eeprom_eewr(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
static s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd);
-static s32 e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
+static s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info);
static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw);
static s32 e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8 *data);
-static s32 e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte);
+static s32 e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index,
+ u8 byte);
static s32 e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte);
static s32 e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data);
-static s32 e1000_read_ich8_data(struct e1000_hw *hw, u32 index, u32 size, u16 *data);
-static s32 e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size, u16 data);
-static s32 e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
-static s32 e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+static s32 e1000_read_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
+ u16 *data);
+static s32 e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
+ u16 data);
+static s32 e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
+static s32 e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
static void e1000_release_software_flag(struct e1000_hw *hw);
static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
@@ -101,23 +118,21 @@ static s32 e1000_config_mac_to_phy(struct e1000_hw *hw);
static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data,
- u16 count);
+ u16 count);
static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw);
static s32 e1000_phy_reset_dsp(struct e1000_hw *hw);
static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset,
u16 words, u16 *data);
-static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw,
- u16 offset, u16 words,
- u16 *data);
+static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
+ u16 words, u16 *data);
static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw);
static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd);
static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd);
-static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data,
- u16 count);
+static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count);
static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
- u16 phy_data);
+ u16 phy_data);
static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw,u32 reg_addr,
- u16 *phy_data);
+ u16 *phy_data);
static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count);
static s32 e1000_acquire_eeprom(struct e1000_hw *hw);
static void e1000_release_eeprom(struct e1000_hw *hw);
@@ -127,8 +142,7 @@ static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw);
static s32 e1000_set_phy_mode(struct e1000_hw *hw);
static s32 e1000_host_if_read_cookie(struct e1000_hw *hw, u8 *buffer);
static u8 e1000_calculate_mng_checksum(char *buffer, u32 length);
-static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw,
- u16 duplex);
+static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex);
static s32 e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
/* IGP cable length table */
@@ -159,8 +173,7 @@ u16 e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static s32
-e1000_set_phy_type(struct e1000_hw *hw)
+static s32 e1000_set_phy_type(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_set_phy_type");
@@ -210,8 +223,7 @@ e1000_set_phy_type(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void
-e1000_phy_init_script(struct e1000_hw *hw)
+static void e1000_phy_init_script(struct e1000_hw *hw)
{
u32 ret_val;
u16 phy_saved_data;
@@ -306,8 +318,7 @@ e1000_phy_init_script(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_set_mac_type(struct e1000_hw *hw)
+s32 e1000_set_mac_type(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_set_mac_type");
@@ -474,8 +485,7 @@ e1000_set_mac_type(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
* **************************************************************************/
-void
-e1000_set_media_type(struct e1000_hw *hw)
+void e1000_set_media_type(struct e1000_hw *hw)
{
u32 status;
@@ -510,7 +520,7 @@ e1000_set_media_type(struct e1000_hw *hw)
hw->media_type = e1000_media_type_copper;
break;
default:
- status = E1000_READ_REG(hw, STATUS);
+ status = er32(STATUS);
if (status & E1000_STATUS_TBIMODE) {
hw->media_type = e1000_media_type_fiber;
/* tbi_compatibility not valid on fiber */
@@ -528,8 +538,7 @@ e1000_set_media_type(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_reset_hw(struct e1000_hw *hw)
+s32 e1000_reset_hw(struct e1000_hw *hw)
{
u32 ctrl;
u32 ctrl_ext;
@@ -559,15 +568,15 @@ e1000_reset_hw(struct e1000_hw *hw)
/* Clear interrupt mask to stop board from generating interrupts */
DEBUGOUT("Masking off all interrupts\n");
- E1000_WRITE_REG(hw, IMC, 0xffffffff);
+ ew32(IMC, 0xffffffff);
/* Disable the Transmit and Receive units. Then delay to allow
* any pending transactions to complete before we hit the MAC with
* the global reset.
*/
- E1000_WRITE_REG(hw, RCTL, 0);
- E1000_WRITE_REG(hw, TCTL, E1000_TCTL_PSP);
- E1000_WRITE_FLUSH(hw);
+ ew32(RCTL, 0);
+ ew32(TCTL, E1000_TCTL_PSP);
+ E1000_WRITE_FLUSH();
/* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
hw->tbi_compatibility_on = false;
@@ -577,11 +586,11 @@ e1000_reset_hw(struct e1000_hw *hw)
*/
msleep(10);
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
/* Must reset the PHY before resetting the MAC */
if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
- E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST));
+ ew32(CTRL, (ctrl | E1000_CTRL_PHY_RST));
msleep(5);
}
@@ -590,12 +599,12 @@ e1000_reset_hw(struct e1000_hw *hw)
if (hw->mac_type == e1000_82573) {
timeout = 10;
- extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+ extcnf_ctrl = er32(EXTCNF_CTRL);
extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
do {
- E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
- extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+ ew32(EXTCNF_CTRL, extcnf_ctrl);
+ extcnf_ctrl = er32(EXTCNF_CTRL);
if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
break;
@@ -610,9 +619,9 @@ e1000_reset_hw(struct e1000_hw *hw)
/* Workaround for ICH8 bit corruption issue in FIFO memory */
if (hw->mac_type == e1000_ich8lan) {
/* Set Tx and Rx buffer allocation to 8k apiece. */
- E1000_WRITE_REG(hw, PBA, E1000_PBA_8K);
+ ew32(PBA, E1000_PBA_8K);
/* Set Packet Buffer Size to 16k. */
- E1000_WRITE_REG(hw, PBS, E1000_PBS_16K);
+ ew32(PBS, E1000_PBS_16K);
}
/* Issue a global reset to the MAC. This will reset the chip's
@@ -636,7 +645,7 @@ e1000_reset_hw(struct e1000_hw *hw)
case e1000_82545_rev_3:
case e1000_82546_rev_3:
/* Reset is performed on a shadow of the control register */
- E1000_WRITE_REG(hw, CTRL_DUP, (ctrl | E1000_CTRL_RST));
+ ew32(CTRL_DUP, (ctrl | E1000_CTRL_RST));
break;
case e1000_ich8lan:
if (!hw->phy_reset_disable &&
@@ -649,11 +658,11 @@ e1000_reset_hw(struct e1000_hw *hw)
}
e1000_get_software_flag(hw);
- E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST));
+ ew32(CTRL, (ctrl | E1000_CTRL_RST));
msleep(5);
break;
default:
- E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST));
+ ew32(CTRL, (ctrl | E1000_CTRL_RST));
break;
}
@@ -668,10 +677,10 @@ e1000_reset_hw(struct e1000_hw *hw)
case e1000_82544:
/* Wait for reset to complete */
udelay(10);
- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext = er32(CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_EE_RST;
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH();
/* Wait for EEPROM reload */
msleep(2);
break;
@@ -685,10 +694,10 @@ e1000_reset_hw(struct e1000_hw *hw)
case e1000_82573:
if (!e1000_is_onboard_nvm_eeprom(hw)) {
udelay(10);
- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext = er32(CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_EE_RST;
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH();
}
/* fall through */
default:
@@ -701,27 +710,27 @@ e1000_reset_hw(struct e1000_hw *hw)
/* Disable HW ARPs on ASF enabled adapters */
if (hw->mac_type >= e1000_82540 && hw->mac_type <= e1000_82547_rev_2) {
- manc = E1000_READ_REG(hw, MANC);
+ manc = er32(MANC);
manc &= ~(E1000_MANC_ARP_EN);
- E1000_WRITE_REG(hw, MANC, manc);
+ ew32(MANC, manc);
}
if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
e1000_phy_init_script(hw);
/* Configure activity LED after PHY reset */
- led_ctrl = E1000_READ_REG(hw, LEDCTL);
+ led_ctrl = er32(LEDCTL);
led_ctrl &= IGP_ACTIVITY_LED_MASK;
led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
- E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
+ ew32(LEDCTL, led_ctrl);
}
/* Clear interrupt mask to stop board from generating interrupts */
DEBUGOUT("Masking off all interrupts\n");
- E1000_WRITE_REG(hw, IMC, 0xffffffff);
+ ew32(IMC, 0xffffffff);
/* Clear any pending interrupt events. */
- icr = E1000_READ_REG(hw, ICR);
+ icr = er32(ICR);
/* If MWI was previously enabled, reenable it. */
if (hw->mac_type == e1000_82542_rev2_0) {
@@ -730,9 +739,9 @@ e1000_reset_hw(struct e1000_hw *hw)
}
if (hw->mac_type == e1000_ich8lan) {
- u32 kab = E1000_READ_REG(hw, KABGTXD);
+ u32 kab = er32(KABGTXD);
kab |= E1000_KABGTXD_BGSQLBIAS;
- E1000_WRITE_REG(hw, KABGTXD, kab);
+ ew32(KABGTXD, kab);
}
return E1000_SUCCESS;
@@ -747,8 +756,7 @@ e1000_reset_hw(struct e1000_hw *hw)
* This function contains hardware limitation workarounds for PCI-E adapters
*
*****************************************************************************/
-static void
-e1000_initialize_hardware_bits(struct e1000_hw *hw)
+static void e1000_initialize_hardware_bits(struct e1000_hw *hw)
{
if ((hw->mac_type >= e1000_82571) && (!hw->initialize_hw_bits_disable)) {
/* Settings common to all PCI-express silicon */
@@ -758,22 +766,22 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
u32 reg_txdctl, reg_txdctl1;
/* link autonegotiation/sync workarounds */
- reg_tarc0 = E1000_READ_REG(hw, TARC0);
+ reg_tarc0 = er32(TARC0);
reg_tarc0 &= ~((1 << 30)|(1 << 29)|(1 << 28)|(1 << 27));
/* Enable not-done TX descriptor counting */
- reg_txdctl = E1000_READ_REG(hw, TXDCTL);
+ reg_txdctl = er32(TXDCTL);
reg_txdctl |= E1000_TXDCTL_COUNT_DESC;
- E1000_WRITE_REG(hw, TXDCTL, reg_txdctl);
- reg_txdctl1 = E1000_READ_REG(hw, TXDCTL1);
+ ew32(TXDCTL, reg_txdctl);
+ reg_txdctl1 = er32(TXDCTL1);
reg_txdctl1 |= E1000_TXDCTL_COUNT_DESC;
- E1000_WRITE_REG(hw, TXDCTL1, reg_txdctl1);
+ ew32(TXDCTL1, reg_txdctl1);
switch (hw->mac_type) {
case e1000_82571:
case e1000_82572:
/* Clear PHY TX compatible mode bits */
- reg_tarc1 = E1000_READ_REG(hw, TARC1);
+ reg_tarc1 = er32(TARC1);
reg_tarc1 &= ~((1 << 30)|(1 << 29));
/* link autonegotiation/sync workarounds */
@@ -783,25 +791,25 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
reg_tarc1 |= ((1 << 26)|(1 << 25)|(1 << 24));
/* Multiple read bit is reversed polarity */
- reg_tctl = E1000_READ_REG(hw, TCTL);
+ reg_tctl = er32(TCTL);
if (reg_tctl & E1000_TCTL_MULR)
reg_tarc1 &= ~(1 << 28);
else
reg_tarc1 |= (1 << 28);
- E1000_WRITE_REG(hw, TARC1, reg_tarc1);
+ ew32(TARC1, reg_tarc1);
break;
case e1000_82573:
- reg_ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ reg_ctrl_ext = er32(CTRL_EXT);
reg_ctrl_ext &= ~(1 << 23);
reg_ctrl_ext |= (1 << 22);
/* TX byte count fix */
- reg_ctrl = E1000_READ_REG(hw, CTRL);
+ reg_ctrl = er32(CTRL);
reg_ctrl &= ~(1 << 29);
- E1000_WRITE_REG(hw, CTRL_EXT, reg_ctrl_ext);
- E1000_WRITE_REG(hw, CTRL, reg_ctrl);
+ ew32(CTRL_EXT, reg_ctrl_ext);
+ ew32(CTRL, reg_ctrl);
break;
case e1000_80003es2lan:
/* improve small packet performace for fiber/serdes */
@@ -811,14 +819,14 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
}
/* Multiple read bit is reversed polarity */
- reg_tctl = E1000_READ_REG(hw, TCTL);
- reg_tarc1 = E1000_READ_REG(hw, TARC1);
+ reg_tctl = er32(TCTL);
+ reg_tarc1 = er32(TARC1);
if (reg_tctl & E1000_TCTL_MULR)
reg_tarc1 &= ~(1 << 28);
else
reg_tarc1 |= (1 << 28);
- E1000_WRITE_REG(hw, TARC1, reg_tarc1);
+ ew32(TARC1, reg_tarc1);
break;
case e1000_ich8lan:
/* Reduce concurrent DMA requests to 3 from 4 */
@@ -827,16 +835,16 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
(hw->device_id != E1000_DEV_ID_ICH8_IGP_M)))
reg_tarc0 |= ((1 << 29)|(1 << 28));
- reg_ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ reg_ctrl_ext = er32(CTRL_EXT);
reg_ctrl_ext |= (1 << 22);
- E1000_WRITE_REG(hw, CTRL_EXT, reg_ctrl_ext);
+ ew32(CTRL_EXT, reg_ctrl_ext);
/* workaround TX hang with TSO=on */
reg_tarc0 |= ((1 << 27)|(1 << 26)|(1 << 24)|(1 << 23));
/* Multiple read bit is reversed polarity */
- reg_tctl = E1000_READ_REG(hw, TCTL);
- reg_tarc1 = E1000_READ_REG(hw, TARC1);
+ reg_tctl = er32(TCTL);
+ reg_tarc1 = er32(TARC1);
if (reg_tctl & E1000_TCTL_MULR)
reg_tarc1 &= ~(1 << 28);
else
@@ -845,13 +853,13 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
/* workaround TX hang with TSO=on */
reg_tarc1 |= ((1 << 30)|(1 << 26)|(1 << 24));
- E1000_WRITE_REG(hw, TARC1, reg_tarc1);
+ ew32(TARC1, reg_tarc1);
break;
default:
break;
}
- E1000_WRITE_REG(hw, TARC0, reg_tarc0);
+ ew32(TARC0, reg_tarc0);
}
}
@@ -866,8 +874,7 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
* configuration and flow control settings. Clears all on-chip counters. Leaves
* the transmit and receive units disabled and uninitialized.
*****************************************************************************/
-s32
-e1000_init_hw(struct e1000_hw *hw)
+s32 e1000_init_hw(struct e1000_hw *hw)
{
u32 ctrl;
u32 i;
@@ -883,9 +890,9 @@ e1000_init_hw(struct e1000_hw *hw)
((hw->revision_id < 3) ||
((hw->device_id != E1000_DEV_ID_ICH8_IGP_M_AMT) &&
(hw->device_id != E1000_DEV_ID_ICH8_IGP_M)))) {
- reg_data = E1000_READ_REG(hw, STATUS);
+ reg_data = er32(STATUS);
reg_data &= ~0x80000000;
- E1000_WRITE_REG(hw, STATUS, reg_data);
+ ew32(STATUS, reg_data);
}
/* Initialize Identification LED */
@@ -906,7 +913,7 @@ e1000_init_hw(struct e1000_hw *hw)
/* VET hardcoded to standard value and VFTA removed in ICH8 LAN */
if (hw->mac_type != e1000_ich8lan) {
if (hw->mac_type < e1000_82545_rev_3)
- E1000_WRITE_REG(hw, VET, 0);
+ ew32(VET, 0);
e1000_clear_vfta(hw);
}
@@ -914,8 +921,8 @@ e1000_init_hw(struct e1000_hw *hw)
if (hw->mac_type == e1000_82542_rev2_0) {
DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
e1000_pci_clear_mwi(hw);
- E1000_WRITE_REG(hw, RCTL, E1000_RCTL_RST);
- E1000_WRITE_FLUSH(hw);
+ ew32(RCTL, E1000_RCTL_RST);
+ E1000_WRITE_FLUSH();
msleep(5);
}
@@ -926,8 +933,8 @@ e1000_init_hw(struct e1000_hw *hw)
/* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
if (hw->mac_type == e1000_82542_rev2_0) {
- E1000_WRITE_REG(hw, RCTL, 0);
- E1000_WRITE_FLUSH(hw);
+ ew32(RCTL, 0);
+ E1000_WRITE_FLUSH();
msleep(1);
if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
e1000_pci_set_mwi(hw);
@@ -942,7 +949,7 @@ e1000_init_hw(struct e1000_hw *hw)
E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
/* use write flush to prevent Memory Write Block (MWB) from
* occuring when accessing our register space */
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
}
/* Set the PCI priority bit correctly in the CTRL register. This
@@ -951,8 +958,8 @@ e1000_init_hw(struct e1000_hw *hw)
* 82542 and 82543 silicon.
*/
if (hw->dma_fairness && hw->mac_type <= e1000_82543) {
- ctrl = E1000_READ_REG(hw, CTRL);
- E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR);
+ ctrl = er32(CTRL);
+ ew32(CTRL, ctrl | E1000_CTRL_PRIOR);
}
switch (hw->mac_type) {
@@ -975,9 +982,9 @@ e1000_init_hw(struct e1000_hw *hw)
/* Set the transmit descriptor write-back policy */
if (hw->mac_type > e1000_82544) {
- ctrl = E1000_READ_REG(hw, TXDCTL);
+ ctrl = er32(TXDCTL);
ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
- E1000_WRITE_REG(hw, TXDCTL, ctrl);
+ ew32(TXDCTL, ctrl);
}
if (hw->mac_type == e1000_82573) {
@@ -989,21 +996,21 @@ e1000_init_hw(struct e1000_hw *hw)
break;
case e1000_80003es2lan:
/* Enable retransmit on late collisions */
- reg_data = E1000_READ_REG(hw, TCTL);
+ reg_data = er32(TCTL);
reg_data |= E1000_TCTL_RTLC;
- E1000_WRITE_REG(hw, TCTL, reg_data);
+ ew32(TCTL, reg_data);
/* Configure Gigabit Carry Extend Padding */
- reg_data = E1000_READ_REG(hw, TCTL_EXT);
+ reg_data = er32(TCTL_EXT);
reg_data &= ~E1000_TCTL_EXT_GCEX_MASK;
reg_data |= DEFAULT_80003ES2LAN_TCTL_EXT_GCEX;
- E1000_WRITE_REG(hw, TCTL_EXT, reg_data);
+ ew32(TCTL_EXT, reg_data);
/* Configure Transmit Inter-Packet Gap */
- reg_data = E1000_READ_REG(hw, TIPG);
+ reg_data = er32(TIPG);
reg_data &= ~E1000_TIPG_IPGT_MASK;
reg_data |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000;
- E1000_WRITE_REG(hw, TIPG, reg_data);
+ ew32(TIPG, reg_data);
reg_data = E1000_READ_REG_ARRAY(hw, FFLT, 0x0001);
reg_data &= ~0x00100000;
@@ -1012,17 +1019,17 @@ e1000_init_hw(struct e1000_hw *hw)
case e1000_82571:
case e1000_82572:
case e1000_ich8lan:
- ctrl = E1000_READ_REG(hw, TXDCTL1);
+ ctrl = er32(TXDCTL1);
ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
- E1000_WRITE_REG(hw, TXDCTL1, ctrl);
+ ew32(TXDCTL1, ctrl);
break;
}
if (hw->mac_type == e1000_82573) {
- u32 gcr = E1000_READ_REG(hw, GCR);
+ u32 gcr = er32(GCR);
gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
- E1000_WRITE_REG(hw, GCR, gcr);
+ ew32(GCR, gcr);
}
/* Clear all of the statistics registers (clear on read). It is
@@ -1039,11 +1046,11 @@ e1000_init_hw(struct e1000_hw *hw)
if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) {
- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext = er32(CTRL_EXT);
/* Relaxed ordering must be disabled to avoid a parity
* error crash in a PCI slot. */
ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ ew32(CTRL_EXT, ctrl_ext);
}
return ret_val;
@@ -1054,8 +1061,7 @@ e1000_init_hw(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code.
*****************************************************************************/
-static s32
-e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
+static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
{
u16 eeprom_data;
s32 ret_val;
@@ -1100,8 +1106,7 @@ e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
* established. Assumes the hardware has previously been reset and the
* transmitter and receiver are not enabled.
*****************************************************************************/
-s32
-e1000_setup_link(struct e1000_hw *hw)
+s32 e1000_setup_link(struct e1000_hw *hw)
{
u32 ctrl_ext;
s32 ret_val;
@@ -1176,7 +1181,7 @@ e1000_setup_link(struct e1000_hw *hw)
}
ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) <<
SWDPIO__EXT_SHIFT);
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ ew32(CTRL_EXT, ctrl_ext);
}
/* Call the necessary subroutine to configure the link. */
@@ -1193,12 +1198,12 @@ e1000_setup_link(struct e1000_hw *hw)
/* FCAL/H and FCT are hardcoded to standard values in e1000_ich8lan. */
if (hw->mac_type != e1000_ich8lan) {
- E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE);
- E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH);
- E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW);
+ ew32(FCT, FLOW_CONTROL_TYPE);
+ ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH);
+ ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW);
}
- E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time);
+ ew32(FCTTV, hw->fc_pause_time);
/* Set the flow control receive threshold registers. Normally,
* these registers will be set to a default threshold that may be
@@ -1207,18 +1212,18 @@ e1000_setup_link(struct e1000_hw *hw)
* registers will be set to 0.
*/
if (!(hw->fc & E1000_FC_TX_PAUSE)) {
- E1000_WRITE_REG(hw, FCRTL, 0);
- E1000_WRITE_REG(hw, FCRTH, 0);
+ ew32(FCRTL, 0);
+ ew32(FCRTH, 0);
} else {
/* We need to set up the Receive Threshold high and low water marks
* as well as (optionally) enabling the transmission of XON frames.
*/
if (hw->fc_send_xon) {
- E1000_WRITE_REG(hw, FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE));
- E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water);
+ ew32(FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE));
+ ew32(FCRTH, hw->fc_high_water);
} else {
- E1000_WRITE_REG(hw, FCRTL, hw->fc_low_water);
- E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water);
+ ew32(FCRTL, hw->fc_low_water);
+ ew32(FCRTH, hw->fc_high_water);
}
}
return ret_val;
@@ -1233,8 +1238,7 @@ e1000_setup_link(struct e1000_hw *hw)
* link. Assumes the hardware has been previously reset and the transmitter
* and receiver are not enabled.
*****************************************************************************/
-static s32
-e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
+static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
{
u32 ctrl;
u32 status;
@@ -1251,7 +1255,7 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
* loopback mode is disabled during initialization.
*/
if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572)
- E1000_WRITE_REG(hw, SCTL, E1000_DISABLE_SERDES_LOOPBACK);
+ ew32(SCTL, E1000_DISABLE_SERDES_LOOPBACK);
/* On adapters with a MAC newer than 82544, SWDP 1 will be
* set when the optics detect a signal. On older adapters, it will be
@@ -1259,7 +1263,7 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
* If we're on serdes media, adjust the output amplitude to value
* set in the EEPROM.
*/
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
if (hw->media_type == e1000_media_type_fiber)
signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
@@ -1330,9 +1334,9 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
*/
DEBUGOUT("Auto-negotiation enabled\n");
- E1000_WRITE_REG(hw, TXCW, txcw);
- E1000_WRITE_REG(hw, CTRL, ctrl);
- E1000_WRITE_FLUSH(hw);
+ ew32(TXCW, txcw);
+ ew32(CTRL, ctrl);
+ E1000_WRITE_FLUSH();
hw->txcw = txcw;
msleep(1);
@@ -1344,11 +1348,11 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
* For internal serdes, we just assume a signal is present, then poll.
*/
if (hw->media_type == e1000_media_type_internal_serdes ||
- (E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) {
+ (er32(CTRL) & E1000_CTRL_SWDPIN1) == signal) {
DEBUGOUT("Looking for Link\n");
for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
msleep(10);
- status = E1000_READ_REG(hw, STATUS);
+ status = er32(STATUS);
if (status & E1000_STATUS_LU) break;
}
if (i == (LINK_UP_TIMEOUT / 10)) {
@@ -1380,8 +1384,7 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_copper_link_preconfig(struct e1000_hw *hw)
+static s32 e1000_copper_link_preconfig(struct e1000_hw *hw)
{
u32 ctrl;
s32 ret_val;
@@ -1389,7 +1392,7 @@ e1000_copper_link_preconfig(struct e1000_hw *hw)
DEBUGFUNC("e1000_copper_link_preconfig");
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
/* With 82543, we need to force speed and duplex on the MAC equal to what
* the PHY speed and duplex configuration is. In addition, we need to
* perform a hardware reset on the PHY to take it out of reset.
@@ -1397,10 +1400,10 @@ e1000_copper_link_preconfig(struct e1000_hw *hw)
if (hw->mac_type > e1000_82543) {
ctrl |= E1000_CTRL_SLU;
ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
} else {
ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
ret_val = e1000_phy_hw_reset(hw);
if (ret_val)
return ret_val;
@@ -1440,8 +1443,7 @@ e1000_copper_link_preconfig(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*********************************************************************/
-static s32
-e1000_copper_link_igp_setup(struct e1000_hw *hw)
+static s32 e1000_copper_link_igp_setup(struct e1000_hw *hw)
{
u32 led_ctrl;
s32 ret_val;
@@ -1462,10 +1464,10 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
msleep(15);
if (hw->mac_type != e1000_ich8lan) {
/* Configure activity LED after PHY reset */
- led_ctrl = E1000_READ_REG(hw, LEDCTL);
+ led_ctrl = er32(LEDCTL);
led_ctrl &= IGP_ACTIVITY_LED_MASK;
led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
- E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
+ ew32(LEDCTL, led_ctrl);
}
/* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */
@@ -1587,8 +1589,7 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*********************************************************************/
-static s32
-e1000_copper_link_ggp_setup(struct e1000_hw *hw)
+static s32 e1000_copper_link_ggp_setup(struct e1000_hw *hw)
{
s32 ret_val;
u16 phy_data;
@@ -1679,9 +1680,9 @@ e1000_copper_link_ggp_setup(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- reg_data = E1000_READ_REG(hw, CTRL_EXT);
+ reg_data = er32(CTRL_EXT);
reg_data &= ~(E1000_CTRL_EXT_LINK_MODE_MASK);
- E1000_WRITE_REG(hw, CTRL_EXT, reg_data);
+ ew32(CTRL_EXT, reg_data);
ret_val = e1000_read_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
&phy_data);
@@ -1735,8 +1736,7 @@ e1000_copper_link_ggp_setup(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*********************************************************************/
-static s32
-e1000_copper_link_mgp_setup(struct e1000_hw *hw)
+static s32 e1000_copper_link_mgp_setup(struct e1000_hw *hw)
{
s32 ret_val;
u16 phy_data;
@@ -1839,8 +1839,7 @@ e1000_copper_link_mgp_setup(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*********************************************************************/
-static s32
-e1000_copper_link_autoneg(struct e1000_hw *hw)
+static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
{
s32 ret_val;
u16 phy_data;
@@ -1910,8 +1909,7 @@ e1000_copper_link_autoneg(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_copper_link_postconfig(struct e1000_hw *hw)
+static s32 e1000_copper_link_postconfig(struct e1000_hw *hw)
{
s32 ret_val;
DEBUGFUNC("e1000_copper_link_postconfig");
@@ -1948,8 +1946,7 @@ e1000_copper_link_postconfig(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_setup_copper_link(struct e1000_hw *hw)
+static s32 e1000_setup_copper_link(struct e1000_hw *hw)
{
s32 ret_val;
u16 i;
@@ -2062,8 +2059,7 @@ e1000_setup_copper_link(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex)
+static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex)
{
s32 ret_val = E1000_SUCCESS;
u32 tipg;
@@ -2078,10 +2074,10 @@ e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex)
return ret_val;
/* Configure Transmit Inter-Packet Gap */
- tipg = E1000_READ_REG(hw, TIPG);
+ tipg = er32(TIPG);
tipg &= ~E1000_TIPG_IPGT_MASK;
tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_10_100;
- E1000_WRITE_REG(hw, TIPG, tipg);
+ ew32(TIPG, tipg);
ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
@@ -2098,8 +2094,7 @@ e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex)
return ret_val;
}
-static s32
-e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
+static s32 e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
u16 reg_data;
@@ -2114,10 +2109,10 @@ e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
return ret_val;
/* Configure Transmit Inter-Packet Gap */
- tipg = E1000_READ_REG(hw, TIPG);
+ tipg = er32(TIPG);
tipg &= ~E1000_TIPG_IPGT_MASK;
tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000;
- E1000_WRITE_REG(hw, TIPG, tipg);
+ ew32(TIPG, tipg);
ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
@@ -2135,8 +2130,7 @@ e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-s32
-e1000_phy_setup_autoneg(struct e1000_hw *hw)
+s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
{
s32 ret_val;
u16 mii_autoneg_adv_reg;
@@ -2284,8 +2278,7 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_phy_force_speed_duplex(struct e1000_hw *hw)
+static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
{
u32 ctrl;
s32 ret_val;
@@ -2302,7 +2295,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
DEBUGOUT1("hw->fc = %d\n", hw->fc);
/* Read the Device Control Register. */
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
/* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */
ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
@@ -2357,7 +2350,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
e1000_config_collision_dist(hw);
/* Write the configured values back to the Device Control Reg. */
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
if ((hw->phy_type == e1000_phy_m88) ||
(hw->phy_type == e1000_phy_gg82563)) {
@@ -2535,8 +2528,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
* Link should have been established previously. Reads the speed and duplex
* information from the Device Status register.
******************************************************************************/
-void
-e1000_config_collision_dist(struct e1000_hw *hw)
+void e1000_config_collision_dist(struct e1000_hw *hw)
{
u32 tctl, coll_dist;
@@ -2547,13 +2539,13 @@ e1000_config_collision_dist(struct e1000_hw *hw)
else
coll_dist = E1000_COLLISION_DISTANCE;
- tctl = E1000_READ_REG(hw, TCTL);
+ tctl = er32(TCTL);
tctl &= ~E1000_TCTL_COLD;
tctl |= coll_dist << E1000_COLD_SHIFT;
- E1000_WRITE_REG(hw, TCTL, tctl);
- E1000_WRITE_FLUSH(hw);
+ ew32(TCTL, tctl);
+ E1000_WRITE_FLUSH();
}
/******************************************************************************
@@ -2565,8 +2557,7 @@ e1000_config_collision_dist(struct e1000_hw *hw)
* The contents of the PHY register containing the needed information need to
* be passed in.
******************************************************************************/
-static s32
-e1000_config_mac_to_phy(struct e1000_hw *hw)
+static s32 e1000_config_mac_to_phy(struct e1000_hw *hw)
{
u32 ctrl;
s32 ret_val;
@@ -2582,7 +2573,7 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
/* Read the Device Control Register and set the bits to Force Speed
* and Duplex.
*/
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
@@ -2609,7 +2600,7 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
ctrl |= E1000_CTRL_SPD_100;
/* Write the configured values back to the Device Control Reg. */
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
return E1000_SUCCESS;
}
@@ -2624,15 +2615,14 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
* by the PHY rather than the MAC. Software must also configure these
* bits when link is forced on a fiber connection.
*****************************************************************************/
-s32
-e1000_force_mac_fc(struct e1000_hw *hw)
+s32 e1000_force_mac_fc(struct e1000_hw *hw)
{
u32 ctrl;
DEBUGFUNC("e1000_force_mac_fc");
/* Get the current configuration of the Device Control Register */
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
/* Because we didn't get link via the internal auto-negotiation
* mechanism (we either forced link or we got link via PHY
@@ -2676,7 +2666,7 @@ e1000_force_mac_fc(struct e1000_hw *hw)
if (hw->mac_type == e1000_82542_rev2_0)
ctrl &= (~E1000_CTRL_TFCE);
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
return E1000_SUCCESS;
}
@@ -2691,8 +2681,7 @@ e1000_force_mac_fc(struct e1000_hw *hw)
* based on the flow control negotiated by the PHY. In TBI mode, the TFCE
* and RFCE bits will be automaticaly set to the negotiated flow control mode.
*****************************************************************************/
-static s32
-e1000_config_fc_after_link_up(struct e1000_hw *hw)
+static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw)
{
s32 ret_val;
u16 mii_status_reg;
@@ -2896,8 +2885,7 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
*
* Called by any function that needs to check the link status of the adapter.
*****************************************************************************/
-s32
-e1000_check_for_link(struct e1000_hw *hw)
+s32 e1000_check_for_link(struct e1000_hw *hw)
{
u32 rxcw = 0;
u32 ctrl;
@@ -2910,8 +2898,8 @@ e1000_check_for_link(struct e1000_hw *hw)
DEBUGFUNC("e1000_check_for_link");
- ctrl = E1000_READ_REG(hw, CTRL);
- status = E1000_READ_REG(hw, STATUS);
+ ctrl = er32(CTRL);
+ status = er32(STATUS);
/* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be
* set when the optics detect a signal. On older adapters, it will be
@@ -2919,7 +2907,7 @@ e1000_check_for_link(struct e1000_hw *hw)
*/
if ((hw->media_type == e1000_media_type_fiber) ||
(hw->media_type == e1000_media_type_internal_serdes)) {
- rxcw = E1000_READ_REG(hw, RXCW);
+ rxcw = er32(RXCW);
if (hw->media_type == e1000_media_type_fiber) {
signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
@@ -2965,11 +2953,11 @@ e1000_check_for_link(struct e1000_hw *hw)
(!hw->autoneg) &&
(hw->forced_speed_duplex == e1000_10_full ||
hw->forced_speed_duplex == e1000_10_half)) {
- E1000_WRITE_REG(hw, IMC, 0xffffffff);
+ ew32(IMC, 0xffffffff);
ret_val = e1000_polarity_reversal_workaround(hw);
- icr = E1000_READ_REG(hw, ICR);
- E1000_WRITE_REG(hw, ICS, (icr & ~E1000_ICS_LSC));
- E1000_WRITE_REG(hw, IMS, IMS_ENABLE_MASK);
+ icr = er32(ICR);
+ ew32(ICS, (icr & ~E1000_ICS_LSC));
+ ew32(IMS, IMS_ENABLE_MASK);
}
} else {
@@ -3034,9 +3022,9 @@ e1000_check_for_link(struct e1000_hw *hw)
*/
if (hw->tbi_compatibility_on) {
/* If we previously were in the mode, turn it off. */
- rctl = E1000_READ_REG(hw, RCTL);
+ rctl = er32(RCTL);
rctl &= ~E1000_RCTL_SBP;
- E1000_WRITE_REG(hw, RCTL, rctl);
+ ew32(RCTL, rctl);
hw->tbi_compatibility_on = false;
}
} else {
@@ -3047,9 +3035,9 @@ e1000_check_for_link(struct e1000_hw *hw)
*/
if (!hw->tbi_compatibility_on) {
hw->tbi_compatibility_on = true;
- rctl = E1000_READ_REG(hw, RCTL);
+ rctl = er32(RCTL);
rctl |= E1000_RCTL_SBP;
- E1000_WRITE_REG(hw, RCTL, rctl);
+ ew32(RCTL, rctl);
}
}
}
@@ -3073,12 +3061,12 @@ e1000_check_for_link(struct e1000_hw *hw)
DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
/* Disable auto-negotiation in the TXCW register */
- E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE));
+ ew32(TXCW, (hw->txcw & ~E1000_TXCW_ANE));
/* Force link-up and also force full-duplex. */
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
/* Configure Flow Control after forcing link up. */
ret_val = e1000_config_fc_after_link_up(hw);
@@ -3096,8 +3084,8 @@ e1000_check_for_link(struct e1000_hw *hw)
(hw->media_type == e1000_media_type_internal_serdes)) &&
(ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
- E1000_WRITE_REG(hw, TXCW, hw->txcw);
- E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
+ ew32(TXCW, hw->txcw);
+ ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
hw->serdes_link_down = false;
}
@@ -3105,10 +3093,10 @@ e1000_check_for_link(struct e1000_hw *hw)
* based on MAC synchronization for internal serdes media type.
*/
else if ((hw->media_type == e1000_media_type_internal_serdes) &&
- !(E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) {
+ !(E1000_TXCW_ANE & er32(TXCW))) {
/* SYNCH bit and IV bit are sticky. */
udelay(10);
- if (E1000_RXCW_SYNCH & E1000_READ_REG(hw, RXCW)) {
+ if (E1000_RXCW_SYNCH & er32(RXCW)) {
if (!(rxcw & E1000_RXCW_IV)) {
hw->serdes_link_down = false;
DEBUGOUT("SERDES: Link is up.\n");
@@ -3119,8 +3107,8 @@ e1000_check_for_link(struct e1000_hw *hw)
}
}
if ((hw->media_type == e1000_media_type_internal_serdes) &&
- (E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) {
- hw->serdes_link_down = !(E1000_STATUS_LU & E1000_READ_REG(hw, STATUS));
+ (E1000_TXCW_ANE & er32(TXCW))) {
+ hw->serdes_link_down = !(E1000_STATUS_LU & er32(STATUS));
}
return E1000_SUCCESS;
}
@@ -3132,10 +3120,7 @@ e1000_check_for_link(struct e1000_hw *hw)
* speed - Speed of the connection
* duplex - Duplex setting of the connection
*****************************************************************************/
-s32
-e1000_get_speed_and_duplex(struct e1000_hw *hw,
- u16 *speed,
- u16 *duplex)
+s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex)
{
u32 status;
s32 ret_val;
@@ -3144,7 +3129,7 @@ e1000_get_speed_and_duplex(struct e1000_hw *hw,
DEBUGFUNC("e1000_get_speed_and_duplex");
if (hw->mac_type >= e1000_82543) {
- status = E1000_READ_REG(hw, STATUS);
+ status = er32(STATUS);
if (status & E1000_STATUS_SPEED_1000) {
*speed = SPEED_1000;
DEBUGOUT("1000 Mbs, ");
@@ -3214,8 +3199,7 @@ e1000_get_speed_and_duplex(struct e1000_hw *hw,
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_wait_autoneg(struct e1000_hw *hw)
+static s32 e1000_wait_autoneg(struct e1000_hw *hw)
{
s32 ret_val;
u16 i;
@@ -3249,15 +3233,13 @@ e1000_wait_autoneg(struct e1000_hw *hw)
* hw - Struct containing variables accessed by shared code
* ctrl - Device control register's current value
******************************************************************************/
-static void
-e1000_raise_mdi_clk(struct e1000_hw *hw,
- u32 *ctrl)
+static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
{
/* Raise the clock input to the Management Data Clock (by setting the MDC
* bit), and then delay 10 microseconds.
*/
- E1000_WRITE_REG(hw, CTRL, (*ctrl | E1000_CTRL_MDC));
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL, (*ctrl | E1000_CTRL_MDC));
+ E1000_WRITE_FLUSH();
udelay(10);
}
@@ -3267,15 +3249,13 @@ e1000_raise_mdi_clk(struct e1000_hw *hw,
* hw - Struct containing variables accessed by shared code
* ctrl - Device control register's current value
******************************************************************************/
-static void
-e1000_lower_mdi_clk(struct e1000_hw *hw,
- u32 *ctrl)
+static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
{
/* Lower the clock input to the Management Data Clock (by clearing the MDC
* bit), and then delay 10 microseconds.
*/
- E1000_WRITE_REG(hw, CTRL, (*ctrl & ~E1000_CTRL_MDC));
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL, (*ctrl & ~E1000_CTRL_MDC));
+ E1000_WRITE_FLUSH();
udelay(10);
}
@@ -3288,10 +3268,7 @@ e1000_lower_mdi_clk(struct e1000_hw *hw,
*
* Bits are shifted out in MSB to LSB order.
******************************************************************************/
-static void
-e1000_shift_out_mdi_bits(struct e1000_hw *hw,
- u32 data,
- u16 count)
+static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count)
{
u32 ctrl;
u32 mask;
@@ -3303,7 +3280,7 @@ e1000_shift_out_mdi_bits(struct e1000_hw *hw,
mask = 0x01;
mask <<= (count - 1);
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
/* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
@@ -3319,8 +3296,8 @@ e1000_shift_out_mdi_bits(struct e1000_hw *hw,
else
ctrl &= ~E1000_CTRL_MDIO;
- E1000_WRITE_REG(hw, CTRL, ctrl);
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL, ctrl);
+ E1000_WRITE_FLUSH();
udelay(10);
@@ -3338,8 +3315,7 @@ e1000_shift_out_mdi_bits(struct e1000_hw *hw,
*
* Bits are shifted in in MSB to LSB order.
******************************************************************************/
-static u16
-e1000_shift_in_mdi_bits(struct e1000_hw *hw)
+static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw)
{
u32 ctrl;
u16 data = 0;
@@ -3352,14 +3328,14 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw)
* by raising the input to the Management Data Clock (setting the MDC bit),
* and then reading the value of the MDIO bit.
*/
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
/* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as input. */
ctrl &= ~E1000_CTRL_MDIO_DIR;
ctrl &= ~E1000_CTRL_MDIO;
- E1000_WRITE_REG(hw, CTRL, ctrl);
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL, ctrl);
+ E1000_WRITE_FLUSH();
/* Raise and Lower the clock before reading in the data. This accounts for
* the turnaround bits. The first clock occurred when we clocked out the
@@ -3371,7 +3347,7 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw)
for (data = 0, i = 0; i < 16; i++) {
data = data << 1;
e1000_raise_mdi_clk(hw, &ctrl);
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
/* Check to see if we shifted in a "1". */
if (ctrl & E1000_CTRL_MDIO)
data |= 1;
@@ -3384,8 +3360,7 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw)
return data;
}
-static s32
-e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask)
+static s32 e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask)
{
u32 swfw_sync = 0;
u32 swmask = mask;
@@ -3404,7 +3379,7 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask)
if (e1000_get_hw_eeprom_semaphore(hw))
return -E1000_ERR_SWFW_SYNC;
- swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC);
+ swfw_sync = er32(SW_FW_SYNC);
if (!(swfw_sync & (fwmask | swmask))) {
break;
}
@@ -3422,14 +3397,13 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask)
}
swfw_sync |= swmask;
- E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync);
+ ew32(SW_FW_SYNC, swfw_sync);
e1000_put_hw_eeprom_semaphore(hw);
return E1000_SUCCESS;
}
-static void
-e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask)
+static void e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask)
{
u32 swfw_sync;
u32 swmask = mask;
@@ -3451,9 +3425,9 @@ e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask)
while (e1000_get_hw_eeprom_semaphore(hw) != E1000_SUCCESS);
/* empty */
- swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC);
+ swfw_sync = er32(SW_FW_SYNC);
swfw_sync &= ~swmask;
- E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync);
+ ew32(SW_FW_SYNC, swfw_sync);
e1000_put_hw_eeprom_semaphore(hw);
}
@@ -3464,10 +3438,7 @@ e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask)
* hw - Struct containing variables accessed by shared code
* reg_addr - address of the PHY register to read
******************************************************************************/
-s32
-e1000_read_phy_reg(struct e1000_hw *hw,
- u32 reg_addr,
- u16 *phy_data)
+s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data)
{
u32 ret_val;
u16 swfw;
@@ -3475,7 +3446,7 @@ e1000_read_phy_reg(struct e1000_hw *hw,
DEBUGFUNC("e1000_read_phy_reg");
if ((hw->mac_type == e1000_80003es2lan) &&
- (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+ (er32(STATUS) & E1000_STATUS_FUNC_1)) {
swfw = E1000_SWFW_PHY1_SM;
} else {
swfw = E1000_SWFW_PHY0_SM;
@@ -3523,9 +3494,8 @@ e1000_read_phy_reg(struct e1000_hw *hw,
return ret_val;
}
-static s32
-e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
- u16 *phy_data)
+static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
+ u16 *phy_data)
{
u32 i;
u32 mdic = 0;
@@ -3547,12 +3517,12 @@ e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
(phy_addr << E1000_MDIC_PHY_SHIFT) |
(E1000_MDIC_OP_READ));
- E1000_WRITE_REG(hw, MDIC, mdic);
+ ew32(MDIC, mdic);
/* Poll the ready bit to see if the MDI read completed */
for (i = 0; i < 64; i++) {
udelay(50);
- mdic = E1000_READ_REG(hw, MDIC);
+ mdic = er32(MDIC);
if (mdic & E1000_MDIC_READY) break;
}
if (!(mdic & E1000_MDIC_READY)) {
@@ -3563,7 +3533,7 @@ e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
DEBUGOUT("MDI Error\n");
return -E1000_ERR_PHY;
}
- *phy_data = (u16) mdic;
+ *phy_data = (u16)mdic;
} else {
/* We must first send a preamble through the MDIO pin to signal the
* beginning of an MII instruction. This is done by sending 32
@@ -3603,9 +3573,7 @@ e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
* reg_addr - address of the PHY register to write
* data - data to write to the PHY
******************************************************************************/
-s32
-e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr,
- u16 phy_data)
+s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data)
{
u32 ret_val;
u16 swfw;
@@ -3613,7 +3581,7 @@ e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr,
DEBUGFUNC("e1000_write_phy_reg");
if ((hw->mac_type == e1000_80003es2lan) &&
- (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+ (er32(STATUS) & E1000_STATUS_FUNC_1)) {
swfw = E1000_SWFW_PHY1_SM;
} else {
swfw = E1000_SWFW_PHY0_SM;
@@ -3661,9 +3629,8 @@ e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr,
return ret_val;
}
-static s32
-e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
- u16 phy_data)
+static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
+ u16 phy_data)
{
u32 i;
u32 mdic = 0;
@@ -3681,17 +3648,17 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
* for the PHY register in the MDI Control register. The MAC will take
* care of interfacing with the PHY to send the desired data.
*/
- mdic = (((u32) phy_data) |
+ mdic = (((u32)phy_data) |
(reg_addr << E1000_MDIC_REG_SHIFT) |
(phy_addr << E1000_MDIC_PHY_SHIFT) |
(E1000_MDIC_OP_WRITE));
- E1000_WRITE_REG(hw, MDIC, mdic);
+ ew32(MDIC, mdic);
/* Poll the ready bit to see if the MDI read completed */
for (i = 0; i < 641; i++) {
udelay(5);
- mdic = E1000_READ_REG(hw, MDIC);
+ mdic = er32(MDIC);
if (mdic & E1000_MDIC_READY) break;
}
if (!(mdic & E1000_MDIC_READY)) {
@@ -3715,7 +3682,7 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) |
(PHY_OP_WRITE << 12) | (PHY_SOF << 14));
mdic <<= 16;
- mdic |= (u32) phy_data;
+ mdic |= (u32)phy_data;
e1000_shift_out_mdi_bits(hw, mdic, 32);
}
@@ -3723,17 +3690,14 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
return E1000_SUCCESS;
}
-static s32
-e1000_read_kmrn_reg(struct e1000_hw *hw,
- u32 reg_addr,
- u16 *data)
+static s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 reg_addr, u16 *data)
{
u32 reg_val;
u16 swfw;
DEBUGFUNC("e1000_read_kmrn_reg");
if ((hw->mac_type == e1000_80003es2lan) &&
- (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+ (er32(STATUS) & E1000_STATUS_FUNC_1)) {
swfw = E1000_SWFW_PHY1_SM;
} else {
swfw = E1000_SWFW_PHY0_SM;
@@ -3745,28 +3709,25 @@ e1000_read_kmrn_reg(struct e1000_hw *hw,
reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
E1000_KUMCTRLSTA_OFFSET) |
E1000_KUMCTRLSTA_REN;
- E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val);
+ ew32(KUMCTRLSTA, reg_val);
udelay(2);
/* Read the data returned */
- reg_val = E1000_READ_REG(hw, KUMCTRLSTA);
+ reg_val = er32(KUMCTRLSTA);
*data = (u16)reg_val;
e1000_swfw_sync_release(hw, swfw);
return E1000_SUCCESS;
}
-static s32
-e1000_write_kmrn_reg(struct e1000_hw *hw,
- u32 reg_addr,
- u16 data)
+static s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 reg_addr, u16 data)
{
u32 reg_val;
u16 swfw;
DEBUGFUNC("e1000_write_kmrn_reg");
if ((hw->mac_type == e1000_80003es2lan) &&
- (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+ (er32(STATUS) & E1000_STATUS_FUNC_1)) {
swfw = E1000_SWFW_PHY1_SM;
} else {
swfw = E1000_SWFW_PHY0_SM;
@@ -3776,7 +3737,7 @@ e1000_write_kmrn_reg(struct e1000_hw *hw,
reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
E1000_KUMCTRLSTA_OFFSET) | data;
- E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val);
+ ew32(KUMCTRLSTA, reg_val);
udelay(2);
e1000_swfw_sync_release(hw, swfw);
@@ -3788,8 +3749,7 @@ e1000_write_kmrn_reg(struct e1000_hw *hw,
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-s32
-e1000_phy_hw_reset(struct e1000_hw *hw)
+s32 e1000_phy_hw_reset(struct e1000_hw *hw)
{
u32 ctrl, ctrl_ext;
u32 led_ctrl;
@@ -3808,7 +3768,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
if (hw->mac_type > e1000_82543) {
if ((hw->mac_type == e1000_80003es2lan) &&
- (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+ (er32(STATUS) & E1000_STATUS_FUNC_1)) {
swfw = E1000_SWFW_PHY1_SM;
} else {
swfw = E1000_SWFW_PHY0_SM;
@@ -3823,17 +3783,17 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
* and deassert. For e1000_82571 hardware and later, we instead delay
* for 50us between and 10ms after the deassertion.
*/
- ctrl = E1000_READ_REG(hw, CTRL);
- E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
- E1000_WRITE_FLUSH(hw);
+ ctrl = er32(CTRL);
+ ew32(CTRL, ctrl | E1000_CTRL_PHY_RST);
+ E1000_WRITE_FLUSH();
if (hw->mac_type < e1000_82571)
msleep(10);
else
udelay(100);
- E1000_WRITE_REG(hw, CTRL, ctrl);
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL, ctrl);
+ E1000_WRITE_FLUSH();
if (hw->mac_type >= e1000_82571)
mdelay(10);
@@ -3843,24 +3803,24 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
/* Read the Extended Device Control Register, assert the PHY_RESET_DIR
* bit to put the PHY into reset. Then, take it out of reset.
*/
- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext = er32(CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR;
ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA;
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH();
msleep(10);
ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA;
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH();
}
udelay(150);
if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
/* Configure activity LED after PHY reset */
- led_ctrl = E1000_READ_REG(hw, LEDCTL);
+ led_ctrl = er32(LEDCTL);
led_ctrl &= IGP_ACTIVITY_LED_MASK;
led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
- E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
+ ew32(LEDCTL, led_ctrl);
}
/* Wait for FW to finish PHY configuration. */
@@ -3882,8 +3842,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
*
* Sets bit 15 of the MII Control register
******************************************************************************/
-s32
-e1000_phy_reset(struct e1000_hw *hw)
+s32 e1000_phy_reset(struct e1000_hw *hw)
{
s32 ret_val;
u16 phy_data;
@@ -3934,8 +3893,7 @@ e1000_phy_reset(struct e1000_hw *hw)
*
* hw - struct containing variables accessed by shared code
******************************************************************************/
-void
-e1000_phy_powerdown_workaround(struct e1000_hw *hw)
+void e1000_phy_powerdown_workaround(struct e1000_hw *hw)
{
s32 reg;
u16 phy_data;
@@ -3948,8 +3906,8 @@ e1000_phy_powerdown_workaround(struct e1000_hw *hw)
do {
/* Disable link */
- reg = E1000_READ_REG(hw, PHY_CTRL);
- E1000_WRITE_REG(hw, PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
+ reg = er32(PHY_CTRL);
+ ew32(PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
/* Write VR power-down enable - bits 9:8 should be 10b */
@@ -3964,8 +3922,8 @@ e1000_phy_powerdown_workaround(struct e1000_hw *hw)
break;
/* Issue PHY reset and repeat at most one more time */
- reg = E1000_READ_REG(hw, CTRL);
- E1000_WRITE_REG(hw, CTRL, reg | E1000_CTRL_PHY_RST);
+ reg = er32(CTRL);
+ ew32(CTRL, reg | E1000_CTRL_PHY_RST);
retry++;
} while (retry);
@@ -3987,8 +3945,7 @@ e1000_phy_powerdown_workaround(struct e1000_hw *hw)
*
* hw - struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
+static s32 e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
{
s32 ret_val;
s32 reg;
@@ -4024,8 +3981,8 @@ e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
mdelay(5);
}
/* Disable GigE link negotiation */
- reg = E1000_READ_REG(hw, PHY_CTRL);
- E1000_WRITE_REG(hw, PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
+ reg = er32(PHY_CTRL);
+ ew32(PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
/* unable to acquire PCS lock */
@@ -4040,8 +3997,7 @@ e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_detect_gig_phy(struct e1000_hw *hw)
+static s32 e1000_detect_gig_phy(struct e1000_hw *hw)
{
s32 phy_init_status, ret_val;
u16 phy_id_high, phy_id_low;
@@ -4076,14 +4032,14 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- hw->phy_id = (u32) (phy_id_high << 16);
+ hw->phy_id = (u32)(phy_id_high << 16);
udelay(20);
ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low);
if (ret_val)
return ret_val;
- hw->phy_id |= (u32) (phy_id_low & PHY_REVISION_MASK);
- hw->phy_revision = (u32) phy_id_low & ~PHY_REVISION_MASK;
+ hw->phy_id |= (u32)(phy_id_low & PHY_REVISION_MASK);
+ hw->phy_revision = (u32)phy_id_low & ~PHY_REVISION_MASK;
switch (hw->mac_type) {
case e1000_82543:
@@ -4136,8 +4092,7 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_phy_reset_dsp(struct e1000_hw *hw)
+static s32 e1000_phy_reset_dsp(struct e1000_hw *hw)
{
s32 ret_val;
DEBUGFUNC("e1000_phy_reset_dsp");
@@ -4163,9 +4118,8 @@ e1000_phy_reset_dsp(struct e1000_hw *hw)
* hw - Struct containing variables accessed by shared code
* phy_info - PHY information structure
******************************************************************************/
-static s32
-e1000_phy_igp_get_info(struct e1000_hw *hw,
- struct e1000_phy_info *phy_info)
+static s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
{
s32 ret_val;
u16 phy_data, min_length, max_length, average;
@@ -4240,9 +4194,8 @@ e1000_phy_igp_get_info(struct e1000_hw *hw,
* hw - Struct containing variables accessed by shared code
* phy_info - PHY information structure
******************************************************************************/
-static s32
-e1000_phy_ife_get_info(struct e1000_hw *hw,
- struct e1000_phy_info *phy_info)
+static s32 e1000_phy_ife_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
{
s32 ret_val;
u16 phy_data;
@@ -4290,9 +4243,8 @@ e1000_phy_ife_get_info(struct e1000_hw *hw,
* hw - Struct containing variables accessed by shared code
* phy_info - PHY information structure
******************************************************************************/
-static s32
-e1000_phy_m88_get_info(struct e1000_hw *hw,
- struct e1000_phy_info *phy_info)
+static s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
{
s32 ret_val;
u16 phy_data;
@@ -4369,9 +4321,7 @@ e1000_phy_m88_get_info(struct e1000_hw *hw,
* hw - Struct containing variables accessed by shared code
* phy_info - PHY information structure
******************************************************************************/
-s32
-e1000_phy_get_info(struct e1000_hw *hw,
- struct e1000_phy_info *phy_info)
+s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info)
{
s32 ret_val;
u16 phy_data;
@@ -4415,8 +4365,7 @@ e1000_phy_get_info(struct e1000_hw *hw,
return e1000_phy_m88_get_info(hw, phy_info);
}
-s32
-e1000_validate_mdi_setting(struct e1000_hw *hw)
+s32 e1000_validate_mdi_setting(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_validate_mdi_settings");
@@ -4436,11 +4385,10 @@ e1000_validate_mdi_setting(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_init_eeprom_params(struct e1000_hw *hw)
+s32 e1000_init_eeprom_params(struct e1000_hw *hw)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
- u32 eecd = E1000_READ_REG(hw, EECD);
+ u32 eecd = er32(EECD);
s32 ret_val = E1000_SUCCESS;
u16 eeprom_size;
@@ -4542,7 +4490,7 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
/* Ensure that the Autonomous FLASH update bit is cleared due to
* Flash update issue on parts which use a FLASH for NVM. */
eecd &= ~E1000_EECD_AUPDEN;
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
}
break;
case e1000_80003es2lan:
@@ -4626,16 +4574,14 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
* hw - Struct containing variables accessed by shared code
* eecd - EECD's current value
*****************************************************************************/
-static void
-e1000_raise_ee_clk(struct e1000_hw *hw,
- u32 *eecd)
+static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd)
{
/* Raise the clock input to the EEPROM (by setting the SK bit), and then
* wait <delay> microseconds.
*/
*eecd = *eecd | E1000_EECD_SK;
- E1000_WRITE_REG(hw, EECD, *eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, *eecd);
+ E1000_WRITE_FLUSH();
udelay(hw->eeprom.delay_usec);
}
@@ -4645,16 +4591,14 @@ e1000_raise_ee_clk(struct e1000_hw *hw,
* hw - Struct containing variables accessed by shared code
* eecd - EECD's current value
*****************************************************************************/
-static void
-e1000_lower_ee_clk(struct e1000_hw *hw,
- u32 *eecd)
+static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd)
{
/* Lower the clock input to the EEPROM (by clearing the SK bit), and then
* wait 50 microseconds.
*/
*eecd = *eecd & ~E1000_EECD_SK;
- E1000_WRITE_REG(hw, EECD, *eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, *eecd);
+ E1000_WRITE_FLUSH();
udelay(hw->eeprom.delay_usec);
}
@@ -4665,10 +4609,7 @@ e1000_lower_ee_clk(struct e1000_hw *hw,
* data - data to send to the EEPROM
* count - number of bits to shift out
*****************************************************************************/
-static void
-e1000_shift_out_ee_bits(struct e1000_hw *hw,
- u16 data,
- u16 count)
+static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
u32 eecd;
@@ -4679,7 +4620,7 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw,
* In order to do this, "data" must be broken down into bits.
*/
mask = 0x01 << (count - 1);
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
if (eeprom->type == e1000_eeprom_microwire) {
eecd &= ~E1000_EECD_DO;
} else if (eeprom->type == e1000_eeprom_spi) {
@@ -4696,8 +4637,8 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw,
if (data & mask)
eecd |= E1000_EECD_DI;
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(eeprom->delay_usec);
@@ -4710,7 +4651,7 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw,
/* We leave the "DI" bit set to "0" when we leave this routine. */
eecd &= ~E1000_EECD_DI;
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
}
/******************************************************************************
@@ -4718,9 +4659,7 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw,
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static u16
-e1000_shift_in_ee_bits(struct e1000_hw *hw,
- u16 count)
+static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count)
{
u32 eecd;
u32 i;
@@ -4733,7 +4672,7 @@ e1000_shift_in_ee_bits(struct e1000_hw *hw,
* always be clear.
*/
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
data = 0;
@@ -4742,7 +4681,7 @@ e1000_shift_in_ee_bits(struct e1000_hw *hw,
data = data << 1;
e1000_raise_ee_clk(hw, &eecd);
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
eecd &= ~(E1000_EECD_DI);
if (eecd & E1000_EECD_DO)
@@ -4762,8 +4701,7 @@ e1000_shift_in_ee_bits(struct e1000_hw *hw,
* Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
* function should be called before issuing a command to the EEPROM.
*****************************************************************************/
-static s32
-e1000_acquire_eeprom(struct e1000_hw *hw)
+static s32 e1000_acquire_eeprom(struct e1000_hw *hw)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
u32 eecd, i=0;
@@ -4772,23 +4710,23 @@ e1000_acquire_eeprom(struct e1000_hw *hw)
if (e1000_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM))
return -E1000_ERR_SWFW_SYNC;
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
if (hw->mac_type != e1000_82573) {
/* Request EEPROM Access */
if (hw->mac_type > e1000_82544) {
eecd |= E1000_EECD_REQ;
- E1000_WRITE_REG(hw, EECD, eecd);
- eecd = E1000_READ_REG(hw, EECD);
+ ew32(EECD, eecd);
+ eecd = er32(EECD);
while ((!(eecd & E1000_EECD_GNT)) &&
(i < E1000_EEPROM_GRANT_ATTEMPTS)) {
i++;
udelay(5);
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
}
if (!(eecd & E1000_EECD_GNT)) {
eecd &= ~E1000_EECD_REQ;
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
DEBUGOUT("Could not acquire EEPROM grant\n");
e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
return -E1000_ERR_EEPROM;
@@ -4801,15 +4739,15 @@ e1000_acquire_eeprom(struct e1000_hw *hw)
if (eeprom->type == e1000_eeprom_microwire) {
/* Clear SK and DI */
eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
/* Set CS */
eecd |= E1000_EECD_CS;
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
} else if (eeprom->type == e1000_eeprom_spi) {
/* Clear SK and CS */
eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
udelay(1);
}
@@ -4821,46 +4759,45 @@ e1000_acquire_eeprom(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void
-e1000_standby_eeprom(struct e1000_hw *hw)
+static void e1000_standby_eeprom(struct e1000_hw *hw)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
u32 eecd;
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
if (eeprom->type == e1000_eeprom_microwire) {
eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(eeprom->delay_usec);
/* Clock high */
eecd |= E1000_EECD_SK;
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(eeprom->delay_usec);
/* Select EEPROM */
eecd |= E1000_EECD_CS;
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(eeprom->delay_usec);
/* Clock low */
eecd &= ~E1000_EECD_SK;
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(eeprom->delay_usec);
} else if (eeprom->type == e1000_eeprom_spi) {
/* Toggle CS to flush commands */
eecd |= E1000_EECD_CS;
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(eeprom->delay_usec);
eecd &= ~E1000_EECD_CS;
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(eeprom->delay_usec);
}
}
@@ -4870,20 +4807,19 @@ e1000_standby_eeprom(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void
-e1000_release_eeprom(struct e1000_hw *hw)
+static void e1000_release_eeprom(struct e1000_hw *hw)
{
u32 eecd;
DEBUGFUNC("e1000_release_eeprom");
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
if (hw->eeprom.type == e1000_eeprom_spi) {
eecd |= E1000_EECD_CS; /* Pull CS high */
eecd &= ~E1000_EECD_SK; /* Lower SCK */
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
udelay(hw->eeprom.delay_usec);
} else if (hw->eeprom.type == e1000_eeprom_microwire) {
@@ -4892,25 +4828,25 @@ e1000_release_eeprom(struct e1000_hw *hw)
/* CS on Microwire is active-high */
eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
/* Rising edge of clock */
eecd |= E1000_EECD_SK;
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(hw->eeprom.delay_usec);
/* Falling edge of clock */
eecd &= ~E1000_EECD_SK;
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(hw->eeprom.delay_usec);
}
/* Stop requesting EEPROM access */
if (hw->mac_type > e1000_82544) {
eecd &= ~E1000_EECD_REQ;
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
}
e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
@@ -4921,8 +4857,7 @@ e1000_release_eeprom(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static s32
-e1000_spi_eeprom_ready(struct e1000_hw *hw)
+static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw)
{
u16 retry_count = 0;
u8 spi_stat_reg;
@@ -4967,11 +4902,7 @@ e1000_spi_eeprom_ready(struct e1000_hw *hw)
* data - word read from the EEPROM
* words - number of words to read
*****************************************************************************/
-s32
-e1000_read_eeprom(struct e1000_hw *hw,
- u16 offset,
- u16 words,
- u16 *data)
+s32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
u32 i = 0;
@@ -5068,11 +4999,8 @@ e1000_read_eeprom(struct e1000_hw *hw,
* data - word read from the EEPROM
* words - number of words to read
*****************************************************************************/
-static s32
-e1000_read_eeprom_eerd(struct e1000_hw *hw,
- u16 offset,
- u16 words,
- u16 *data)
+static s32 e1000_read_eeprom_eerd(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
{
u32 i, eerd = 0;
s32 error = 0;
@@ -5081,13 +5009,13 @@ e1000_read_eeprom_eerd(struct e1000_hw *hw,
eerd = ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) +
E1000_EEPROM_RW_REG_START;
- E1000_WRITE_REG(hw, EERD, eerd);
+ ew32(EERD, eerd);
error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_READ);
if (error) {
break;
}
- data[i] = (E1000_READ_REG(hw, EERD) >> E1000_EEPROM_RW_REG_DATA);
+ data[i] = (er32(EERD) >> E1000_EEPROM_RW_REG_DATA);
}
@@ -5102,11 +5030,8 @@ e1000_read_eeprom_eerd(struct e1000_hw *hw,
* data - word read from the EEPROM
* words - number of words to read
*****************************************************************************/
-static s32
-e1000_write_eeprom_eewr(struct e1000_hw *hw,
- u16 offset,
- u16 words,
- u16 *data)
+static s32 e1000_write_eeprom_eewr(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
{
u32 register_value = 0;
u32 i = 0;
@@ -5125,7 +5050,7 @@ e1000_write_eeprom_eewr(struct e1000_hw *hw,
break;
}
- E1000_WRITE_REG(hw, EEWR, register_value);
+ ew32(EEWR, register_value);
error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
@@ -5143,8 +5068,7 @@ e1000_write_eeprom_eewr(struct e1000_hw *hw,
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static s32
-e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
+static s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
{
u32 attempts = 100000;
u32 i, reg = 0;
@@ -5152,9 +5076,9 @@ e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
for (i = 0; i < attempts; i++) {
if (eerd == E1000_EEPROM_POLL_READ)
- reg = E1000_READ_REG(hw, EERD);
+ reg = er32(EERD);
else
- reg = E1000_READ_REG(hw, EEWR);
+ reg = er32(EEWR);
if (reg & E1000_EEPROM_RW_REG_DONE) {
done = E1000_SUCCESS;
@@ -5171,8 +5095,7 @@ e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
*
* hw - Struct containing variables accessed by shared code
****************************************************************************/
-static bool
-e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
+static bool e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
{
u32 eecd = 0;
@@ -5182,7 +5105,7 @@ e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
return false;
if (hw->mac_type == e1000_82573) {
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
/* Isolate bits 15 & 16 */
eecd = ((eecd >> 15) & 0x03);
@@ -5204,8 +5127,7 @@ e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
* If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
* valid.
*****************************************************************************/
-s32
-e1000_validate_eeprom_checksum(struct e1000_hw *hw)
+s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw)
{
u16 checksum = 0;
u16 i, eeprom_data;
@@ -5252,7 +5174,7 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
checksum += eeprom_data;
}
- if (checksum == (u16) EEPROM_SUM)
+ if (checksum == (u16)EEPROM_SUM)
return E1000_SUCCESS;
else {
DEBUGOUT("EEPROM Checksum Invalid\n");
@@ -5268,8 +5190,7 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
* Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
* Writes the difference to word offset 63 of the EEPROM.
*****************************************************************************/
-s32
-e1000_update_eeprom_checksum(struct e1000_hw *hw)
+s32 e1000_update_eeprom_checksum(struct e1000_hw *hw)
{
u32 ctrl_ext;
u16 checksum = 0;
@@ -5284,7 +5205,7 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
}
checksum += eeprom_data;
}
- checksum = (u16) EEPROM_SUM - checksum;
+ checksum = (u16)EEPROM_SUM - checksum;
if (e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
DEBUGOUT("EEPROM Write Error\n");
return -E1000_ERR_EEPROM;
@@ -5294,9 +5215,9 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
e1000_commit_shadow_ram(hw);
/* Reload the EEPROM, or else modifications will not appear
* until after next adapter reset. */
- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext = er32(CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_EE_RST;
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ ew32(CTRL_EXT, ctrl_ext);
msleep(10);
}
return E1000_SUCCESS;
@@ -5313,11 +5234,7 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
* If e1000_update_eeprom_checksum is not called after this function, the
* EEPROM will most likely contain an invalid checksum.
*****************************************************************************/
-s32
-e1000_write_eeprom(struct e1000_hw *hw,
- u16 offset,
- u16 words,
- u16 *data)
+s32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
s32 status = 0;
@@ -5370,11 +5287,8 @@ e1000_write_eeprom(struct e1000_hw *hw,
* data - pointer to array of 8 bit words to be written to the EEPROM
*
*****************************************************************************/
-static s32
-e1000_write_eeprom_spi(struct e1000_hw *hw,
- u16 offset,
- u16 words,
- u16 *data)
+static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
u16 widx = 0;
@@ -5436,11 +5350,8 @@ e1000_write_eeprom_spi(struct e1000_hw *hw,
* data - pointer to array of 16 bit words to be written to the EEPROM
*
*****************************************************************************/
-static s32
-e1000_write_eeprom_microwire(struct e1000_hw *hw,
- u16 offset,
- u16 words,
- u16 *data)
+static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
+ u16 words, u16 *data)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
u32 eecd;
@@ -5484,7 +5395,7 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
* If DO does not go high in 10 milliseconds, then error out.
*/
for (i = 0; i < 200; i++) {
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
if (eecd & E1000_EECD_DO) break;
udelay(50);
}
@@ -5523,8 +5434,7 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
* data - word read from the EEPROM
* words - number of words to read
*****************************************************************************/
-static s32
-e1000_commit_shadow_ram(struct e1000_hw *hw)
+static s32 e1000_commit_shadow_ram(struct e1000_hw *hw)
{
u32 attempts = 100000;
u32 eecd = 0;
@@ -5539,9 +5449,9 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
if (hw->mac_type == e1000_82573) {
/* The flop register will be used to determine if flash type is STM */
- flop = E1000_READ_REG(hw, FLOP);
+ flop = er32(FLOP);
for (i=0; i < attempts; i++) {
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
if ((eecd & E1000_EECD_FLUPD) == 0) {
break;
}
@@ -5554,14 +5464,14 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
/* If STM opcode located in bits 15:8 of flop, reset firmware */
if ((flop & 0xFF00) == E1000_STM_OPCODE) {
- E1000_WRITE_REG(hw, HICR, E1000_HICR_FW_RESET);
+ ew32(HICR, E1000_HICR_FW_RESET);
}
/* Perform the flash update */
- E1000_WRITE_REG(hw, EECD, eecd | E1000_EECD_FLUPD);
+ ew32(EECD, eecd | E1000_EECD_FLUPD);
for (i=0; i < attempts; i++) {
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
if ((eecd & E1000_EECD_FLUPD) == 0) {
break;
}
@@ -5577,7 +5487,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
/* We're writing to the opposite bank so if we're on bank 1,
* write to bank 0 etc. We also need to erase the segment that
* is going to be written */
- if (!(E1000_READ_REG(hw, EECD) & E1000_EECD_SEC1VAL)) {
+ if (!(er32(EECD) & E1000_EECD_SEC1VAL)) {
new_bank_offset = hw->flash_bank_size * 2;
old_bank_offset = 0;
e1000_erase_ich8_4k_segment(hw, 1);
@@ -5687,8 +5597,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_read_mac_addr(struct e1000_hw * hw)
+s32 e1000_read_mac_addr(struct e1000_hw *hw)
{
u16 offset;
u16 eeprom_data, i;
@@ -5701,8 +5610,8 @@ e1000_read_mac_addr(struct e1000_hw * hw)
DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM;
}
- hw->perm_mac_addr[i] = (u8) (eeprom_data & 0x00FF);
- hw->perm_mac_addr[i+1] = (u8) (eeprom_data >> 8);
+ hw->perm_mac_addr[i] = (u8)(eeprom_data & 0x00FF);
+ hw->perm_mac_addr[i+1] = (u8)(eeprom_data >> 8);
}
switch (hw->mac_type) {
@@ -5712,7 +5621,7 @@ e1000_read_mac_addr(struct e1000_hw * hw)
case e1000_82546_rev_3:
case e1000_82571:
case e1000_80003es2lan:
- if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+ if (er32(STATUS) & E1000_STATUS_FUNC_1)
hw->perm_mac_addr[5] ^= 0x01;
break;
}
@@ -5731,8 +5640,7 @@ e1000_read_mac_addr(struct e1000_hw * hw)
* of the receive addresss registers. Clears the multicast table. Assumes
* the receiver is in reset when the routine is called.
*****************************************************************************/
-static void
-e1000_init_rx_addrs(struct e1000_hw *hw)
+static void e1000_init_rx_addrs(struct e1000_hw *hw)
{
u32 i;
u32 rar_num;
@@ -5758,9 +5666,9 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
DEBUGOUT("Clearing RAR[1-15]\n");
for (i = 1; i < rar_num; i++) {
E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
}
}
@@ -5770,9 +5678,7 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
* hw - Struct containing variables accessed by shared code
* mc_addr - the multicast address to hash
*****************************************************************************/
-u32
-e1000_hash_mc_addr(struct e1000_hw *hw,
- u8 *mc_addr)
+u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
{
u32 hash_value = 0;
@@ -5787,37 +5693,37 @@ e1000_hash_mc_addr(struct e1000_hw *hw,
case 0:
if (hw->mac_type == e1000_ich8lan) {
/* [47:38] i.e. 0x158 for above example address */
- hash_value = ((mc_addr[4] >> 6) | (((u16) mc_addr[5]) << 2));
+ hash_value = ((mc_addr[4] >> 6) | (((u16)mc_addr[5]) << 2));
} else {
/* [47:36] i.e. 0x563 for above example address */
- hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+ hash_value = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
}
break;
case 1:
if (hw->mac_type == e1000_ich8lan) {
/* [46:37] i.e. 0x2B1 for above example address */
- hash_value = ((mc_addr[4] >> 5) | (((u16) mc_addr[5]) << 3));
+ hash_value = ((mc_addr[4] >> 5) | (((u16)mc_addr[5]) << 3));
} else {
/* [46:35] i.e. 0xAC6 for above example address */
- hash_value = ((mc_addr[4] >> 3) | (((u16) mc_addr[5]) << 5));
+ hash_value = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5));
}
break;
case 2:
if (hw->mac_type == e1000_ich8lan) {
/*[45:36] i.e. 0x163 for above example address */
- hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+ hash_value = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
} else {
/* [45:34] i.e. 0x5D8 for above example address */
- hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+ hash_value = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
}
break;
case 3:
if (hw->mac_type == e1000_ich8lan) {
/* [43:34] i.e. 0x18D for above example address */
- hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+ hash_value = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
} else {
/* [43:32] i.e. 0x634 for above example address */
- hash_value = ((mc_addr[4]) | (((u16) mc_addr[5]) << 8));
+ hash_value = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8));
}
break;
}
@@ -5835,9 +5741,7 @@ e1000_hash_mc_addr(struct e1000_hw *hw,
* hw - Struct containing variables accessed by shared code
* hash_value - Multicast address hash value
*****************************************************************************/
-void
-e1000_mta_set(struct e1000_hw *hw,
- u32 hash_value)
+void e1000_mta_set(struct e1000_hw *hw, u32 hash_value)
{
u32 hash_bit, hash_reg;
u32 mta;
@@ -5868,12 +5772,12 @@ e1000_mta_set(struct e1000_hw *hw,
if ((hw->mac_type == e1000_82544) && ((hash_reg & 0x1) == 1)) {
temp = E1000_READ_REG_ARRAY(hw, MTA, (hash_reg - 1));
E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
E1000_WRITE_REG_ARRAY(hw, MTA, (hash_reg - 1), temp);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
} else {
E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
}
}
@@ -5884,20 +5788,16 @@ e1000_mta_set(struct e1000_hw *hw,
* addr - Address to put into receive address register
* index - Receive address register to write
*****************************************************************************/
-void
-e1000_rar_set(struct e1000_hw *hw,
- u8 *addr,
- u32 index)
+void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
{
u32 rar_low, rar_high;
/* HW expects these in little endian so we reverse the byte order
* from network order (big endian) to little endian
*/
- rar_low = ((u32) addr[0] |
- ((u32) addr[1] << 8) |
- ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
- rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
+ rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) |
+ ((u32)addr[2] << 16) | ((u32)addr[3] << 24));
+ rar_high = ((u32)addr[4] | ((u32)addr[5] << 8));
/* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx
* unit hang.
@@ -5930,9 +5830,9 @@ e1000_rar_set(struct e1000_hw *hw,
}
E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
}
/******************************************************************************
@@ -5942,10 +5842,7 @@ e1000_rar_set(struct e1000_hw *hw,
* offset - Offset in VLAN filer table to write
* value - Value to write into VLAN filter table
*****************************************************************************/
-void
-e1000_write_vfta(struct e1000_hw *hw,
- u32 offset,
- u32 value)
+void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
{
u32 temp;
@@ -5955,12 +5852,12 @@ e1000_write_vfta(struct e1000_hw *hw,
if ((hw->mac_type == e1000_82544) && ((offset & 0x1) == 1)) {
temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1));
E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
} else {
E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
}
}
@@ -5969,8 +5866,7 @@ e1000_write_vfta(struct e1000_hw *hw,
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void
-e1000_clear_vfta(struct e1000_hw *hw)
+static void e1000_clear_vfta(struct e1000_hw *hw)
{
u32 offset;
u32 vfta_value = 0;
@@ -5999,12 +5895,11 @@ e1000_clear_vfta(struct e1000_hw *hw)
* manageability unit */
vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
E1000_WRITE_REG_ARRAY(hw, VFTA, offset, vfta_value);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
}
}
-static s32
-e1000_id_led_init(struct e1000_hw * hw)
+static s32 e1000_id_led_init(struct e1000_hw *hw)
{
u32 ledctl;
const u32 ledctl_mask = 0x000000FF;
@@ -6020,7 +5915,7 @@ e1000_id_led_init(struct e1000_hw * hw)
return E1000_SUCCESS;
}
- ledctl = E1000_READ_REG(hw, LEDCTL);
+ ledctl = er32(LEDCTL);
hw->ledctl_default = ledctl;
hw->ledctl_mode1 = hw->ledctl_default;
hw->ledctl_mode2 = hw->ledctl_default;
@@ -6086,8 +5981,7 @@ e1000_id_led_init(struct e1000_hw * hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_setup_led(struct e1000_hw *hw)
+s32 e1000_setup_led(struct e1000_hw *hw)
{
u32 ledctl;
s32 ret_val = E1000_SUCCESS;
@@ -6118,7 +6012,7 @@ e1000_setup_led(struct e1000_hw *hw)
/* Fall Through */
default:
if (hw->media_type == e1000_media_type_fiber) {
- ledctl = E1000_READ_REG(hw, LEDCTL);
+ ledctl = er32(LEDCTL);
/* Save current LEDCTL settings */
hw->ledctl_default = ledctl;
/* Turn off LED0 */
@@ -6127,9 +6021,9 @@ e1000_setup_led(struct e1000_hw *hw)
E1000_LEDCTL_LED0_MODE_MASK);
ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
E1000_LEDCTL_LED0_MODE_SHIFT);
- E1000_WRITE_REG(hw, LEDCTL, ledctl);
+ ew32(LEDCTL, ledctl);
} else if (hw->media_type == e1000_media_type_copper)
- E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1);
+ ew32(LEDCTL, hw->ledctl_mode1);
break;
}
@@ -6145,8 +6039,7 @@ e1000_setup_led(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_blink_led_start(struct e1000_hw *hw)
+s32 e1000_blink_led_start(struct e1000_hw *hw)
{
s16 i;
u32 ledctl_blink = 0;
@@ -6170,7 +6063,7 @@ e1000_blink_led_start(struct e1000_hw *hw)
ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << (i * 8));
}
- E1000_WRITE_REG(hw, LEDCTL, ledctl_blink);
+ ew32(LEDCTL, ledctl_blink);
return E1000_SUCCESS;
}
@@ -6180,8 +6073,7 @@ e1000_blink_led_start(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_cleanup_led(struct e1000_hw *hw)
+s32 e1000_cleanup_led(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
@@ -6210,7 +6102,7 @@ e1000_cleanup_led(struct e1000_hw *hw)
break;
}
/* Restore LEDCTL settings */
- E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default);
+ ew32(LEDCTL, hw->ledctl_default);
break;
}
@@ -6222,10 +6114,9 @@ e1000_cleanup_led(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_led_on(struct e1000_hw *hw)
+s32 e1000_led_on(struct e1000_hw *hw)
{
- u32 ctrl = E1000_READ_REG(hw, CTRL);
+ u32 ctrl = er32(CTRL);
DEBUGFUNC("e1000_led_on");
@@ -6257,13 +6148,13 @@ e1000_led_on(struct e1000_hw *hw)
e1000_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
(IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON));
} else if (hw->media_type == e1000_media_type_copper) {
- E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2);
+ ew32(LEDCTL, hw->ledctl_mode2);
return E1000_SUCCESS;
}
break;
}
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
return E1000_SUCCESS;
}
@@ -6273,10 +6164,9 @@ e1000_led_on(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_led_off(struct e1000_hw *hw)
+s32 e1000_led_off(struct e1000_hw *hw)
{
- u32 ctrl = E1000_READ_REG(hw, CTRL);
+ u32 ctrl = er32(CTRL);
DEBUGFUNC("e1000_led_off");
@@ -6308,13 +6198,13 @@ e1000_led_off(struct e1000_hw *hw)
e1000_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
(IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF));
} else if (hw->media_type == e1000_media_type_copper) {
- E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1);
+ ew32(LEDCTL, hw->ledctl_mode1);
return E1000_SUCCESS;
}
break;
}
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
return E1000_SUCCESS;
}
@@ -6324,98 +6214,97 @@ e1000_led_off(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void
-e1000_clear_hw_cntrs(struct e1000_hw *hw)
+static void e1000_clear_hw_cntrs(struct e1000_hw *hw)
{
volatile u32 temp;
- temp = E1000_READ_REG(hw, CRCERRS);
- temp = E1000_READ_REG(hw, SYMERRS);
- temp = E1000_READ_REG(hw, MPC);
- temp = E1000_READ_REG(hw, SCC);
- temp = E1000_READ_REG(hw, ECOL);
- temp = E1000_READ_REG(hw, MCC);
- temp = E1000_READ_REG(hw, LATECOL);
- temp = E1000_READ_REG(hw, COLC);
- temp = E1000_READ_REG(hw, DC);
- temp = E1000_READ_REG(hw, SEC);
- temp = E1000_READ_REG(hw, RLEC);
- temp = E1000_READ_REG(hw, XONRXC);
- temp = E1000_READ_REG(hw, XONTXC);
- temp = E1000_READ_REG(hw, XOFFRXC);
- temp = E1000_READ_REG(hw, XOFFTXC);
- temp = E1000_READ_REG(hw, FCRUC);
+ temp = er32(CRCERRS);
+ temp = er32(SYMERRS);
+ temp = er32(MPC);
+ temp = er32(SCC);
+ temp = er32(ECOL);
+ temp = er32(MCC);
+ temp = er32(LATECOL);
+ temp = er32(COLC);
+ temp = er32(DC);
+ temp = er32(SEC);
+ temp = er32(RLEC);
+ temp = er32(XONRXC);
+ temp = er32(XONTXC);
+ temp = er32(XOFFRXC);
+ temp = er32(XOFFTXC);
+ temp = er32(FCRUC);
if (hw->mac_type != e1000_ich8lan) {
- temp = E1000_READ_REG(hw, PRC64);
- temp = E1000_READ_REG(hw, PRC127);
- temp = E1000_READ_REG(hw, PRC255);
- temp = E1000_READ_REG(hw, PRC511);
- temp = E1000_READ_REG(hw, PRC1023);
- temp = E1000_READ_REG(hw, PRC1522);
- }
-
- temp = E1000_READ_REG(hw, GPRC);
- temp = E1000_READ_REG(hw, BPRC);
- temp = E1000_READ_REG(hw, MPRC);
- temp = E1000_READ_REG(hw, GPTC);
- temp = E1000_READ_REG(hw, GORCL);
- temp = E1000_READ_REG(hw, GORCH);
- temp = E1000_READ_REG(hw, GOTCL);
- temp = E1000_READ_REG(hw, GOTCH);
- temp = E1000_READ_REG(hw, RNBC);
- temp = E1000_READ_REG(hw, RUC);
- temp = E1000_READ_REG(hw, RFC);
- temp = E1000_READ_REG(hw, ROC);
- temp = E1000_READ_REG(hw, RJC);
- temp = E1000_READ_REG(hw, TORL);
- temp = E1000_READ_REG(hw, TORH);
- temp = E1000_READ_REG(hw, TOTL);
- temp = E1000_READ_REG(hw, TOTH);
- temp = E1000_READ_REG(hw, TPR);
- temp = E1000_READ_REG(hw, TPT);
+ temp = er32(PRC64);
+ temp = er32(PRC127);
+ temp = er32(PRC255);
+ temp = er32(PRC511);
+ temp = er32(PRC1023);
+ temp = er32(PRC1522);
+ }
+
+ temp = er32(GPRC);
+ temp = er32(BPRC);
+ temp = er32(MPRC);
+ temp = er32(GPTC);
+ temp = er32(GORCL);
+ temp = er32(GORCH);
+ temp = er32(GOTCL);
+ temp = er32(GOTCH);
+ temp = er32(RNBC);
+ temp = er32(RUC);
+ temp = er32(RFC);
+ temp = er32(ROC);
+ temp = er32(RJC);
+ temp = er32(TORL);
+ temp = er32(TORH);
+ temp = er32(TOTL);
+ temp = er32(TOTH);
+ temp = er32(TPR);
+ temp = er32(TPT);
if (hw->mac_type != e1000_ich8lan) {
- temp = E1000_READ_REG(hw, PTC64);
- temp = E1000_READ_REG(hw, PTC127);
- temp = E1000_READ_REG(hw, PTC255);
- temp = E1000_READ_REG(hw, PTC511);
- temp = E1000_READ_REG(hw, PTC1023);
- temp = E1000_READ_REG(hw, PTC1522);
+ temp = er32(PTC64);
+ temp = er32(PTC127);
+ temp = er32(PTC255);
+ temp = er32(PTC511);
+ temp = er32(PTC1023);
+ temp = er32(PTC1522);
}
- temp = E1000_READ_REG(hw, MPTC);
- temp = E1000_READ_REG(hw, BPTC);
+ temp = er32(MPTC);
+ temp = er32(BPTC);
if (hw->mac_type < e1000_82543) return;
- temp = E1000_READ_REG(hw, ALGNERRC);
- temp = E1000_READ_REG(hw, RXERRC);
- temp = E1000_READ_REG(hw, TNCRS);
- temp = E1000_READ_REG(hw, CEXTERR);
- temp = E1000_READ_REG(hw, TSCTC);
- temp = E1000_READ_REG(hw, TSCTFC);
+ temp = er32(ALGNERRC);
+ temp = er32(RXERRC);
+ temp = er32(TNCRS);
+ temp = er32(CEXTERR);
+ temp = er32(TSCTC);
+ temp = er32(TSCTFC);
if (hw->mac_type <= e1000_82544) return;
- temp = E1000_READ_REG(hw, MGTPRC);
- temp = E1000_READ_REG(hw, MGTPDC);
- temp = E1000_READ_REG(hw, MGTPTC);
+ temp = er32(MGTPRC);
+ temp = er32(MGTPDC);
+ temp = er32(MGTPTC);
if (hw->mac_type <= e1000_82547_rev_2) return;
- temp = E1000_READ_REG(hw, IAC);
- temp = E1000_READ_REG(hw, ICRXOC);
+ temp = er32(IAC);
+ temp = er32(ICRXOC);
if (hw->mac_type == e1000_ich8lan) return;
- temp = E1000_READ_REG(hw, ICRXPTC);
- temp = E1000_READ_REG(hw, ICRXATC);
- temp = E1000_READ_REG(hw, ICTXPTC);
- temp = E1000_READ_REG(hw, ICTXATC);
- temp = E1000_READ_REG(hw, ICTXQEC);
- temp = E1000_READ_REG(hw, ICTXQMTC);
- temp = E1000_READ_REG(hw, ICRXDMTC);
+ temp = er32(ICRXPTC);
+ temp = er32(ICRXATC);
+ temp = er32(ICTXPTC);
+ temp = er32(ICTXATC);
+ temp = er32(ICTXQEC);
+ temp = er32(ICTXQMTC);
+ temp = er32(ICRXDMTC);
}
/******************************************************************************
@@ -6428,8 +6317,7 @@ e1000_clear_hw_cntrs(struct e1000_hw *hw)
* current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio
* before calling this function.
*****************************************************************************/
-void
-e1000_reset_adaptive(struct e1000_hw *hw)
+void e1000_reset_adaptive(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_reset_adaptive");
@@ -6442,7 +6330,7 @@ e1000_reset_adaptive(struct e1000_hw *hw)
hw->ifs_ratio = IFS_RATIO;
}
hw->in_ifs_mode = false;
- E1000_WRITE_REG(hw, AIT, 0);
+ ew32(AIT, 0);
} else {
DEBUGOUT("Not in Adaptive IFS mode!\n");
}
@@ -6456,8 +6344,7 @@ e1000_reset_adaptive(struct e1000_hw *hw)
* tx_packets - Number of transmits since last callback
* total_collisions - Number of collisions since last callback
*****************************************************************************/
-void
-e1000_update_adaptive(struct e1000_hw *hw)
+void e1000_update_adaptive(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_update_adaptive");
@@ -6470,14 +6357,14 @@ e1000_update_adaptive(struct e1000_hw *hw)
hw->current_ifs_val = hw->ifs_min_val;
else
hw->current_ifs_val += hw->ifs_step_size;
- E1000_WRITE_REG(hw, AIT, hw->current_ifs_val);
+ ew32(AIT, hw->current_ifs_val);
}
}
} else {
if (hw->in_ifs_mode && (hw->tx_packet_delta <= MIN_NUM_XMITS)) {
hw->current_ifs_val = 0;
hw->in_ifs_mode = false;
- E1000_WRITE_REG(hw, AIT, 0);
+ ew32(AIT, 0);
}
}
} else {
@@ -6492,11 +6379,8 @@ e1000_update_adaptive(struct e1000_hw *hw)
* frame_len - The length of the frame in question
* mac_addr - The Ethernet destination address of the frame in question
*****************************************************************************/
-void
-e1000_tbi_adjust_stats(struct e1000_hw *hw,
- struct e1000_hw_stats *stats,
- u32 frame_len,
- u8 *mac_addr)
+void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats,
+ u32 frame_len, u8 *mac_addr)
{
u64 carry_bit;
@@ -6527,7 +6411,7 @@ e1000_tbi_adjust_stats(struct e1000_hw *hw,
* since the test for a multicast frame will test positive on
* a broadcast frame.
*/
- if ((mac_addr[0] == (u8) 0xff) && (mac_addr[1] == (u8) 0xff))
+ if ((mac_addr[0] == (u8)0xff) && (mac_addr[1] == (u8)0xff))
/* Broadcast packet */
stats->bprc++;
else if (*mac_addr & 0x01)
@@ -6570,8 +6454,7 @@ e1000_tbi_adjust_stats(struct e1000_hw *hw,
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void
-e1000_get_bus_info(struct e1000_hw *hw)
+void e1000_get_bus_info(struct e1000_hw *hw)
{
s32 ret_val;
u16 pci_ex_link_status;
@@ -6605,7 +6488,7 @@ e1000_get_bus_info(struct e1000_hw *hw)
hw->bus_width = e1000_bus_width_pciex_1;
break;
default:
- status = E1000_READ_REG(hw, STATUS);
+ status = er32(STATUS);
hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
e1000_bus_type_pcix : e1000_bus_type_pci;
@@ -6645,10 +6528,7 @@ e1000_get_bus_info(struct e1000_hw *hw)
* offset - offset to write to
* value - value to write
*****************************************************************************/
-static void
-e1000_write_reg_io(struct e1000_hw *hw,
- u32 offset,
- u32 value)
+static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value)
{
unsigned long io_addr = hw->io_base;
unsigned long io_data = hw->io_base + 4;
@@ -6672,10 +6552,8 @@ e1000_write_reg_io(struct e1000_hw *hw,
* register to the minimum and maximum range.
* For IGP phy's, the function calculates the range by the AGC registers.
*****************************************************************************/
-static s32
-e1000_get_cable_length(struct e1000_hw *hw,
- u16 *min_length,
- u16 *max_length)
+static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
+ u16 *max_length)
{
s32 ret_val;
u16 agc_value = 0;
@@ -6863,9 +6741,8 @@ e1000_get_cable_length(struct e1000_hw *hw,
* return 0. If the link speed is 1000 Mbps the polarity status is in the
* IGP01E1000_PHY_PCS_INIT_REG.
*****************************************************************************/
-static s32
-e1000_check_polarity(struct e1000_hw *hw,
- e1000_rev_polarity *polarity)
+static s32 e1000_check_polarity(struct e1000_hw *hw,
+ e1000_rev_polarity *polarity)
{
s32 ret_val;
u16 phy_data;
@@ -6939,8 +6816,7 @@ e1000_check_polarity(struct e1000_hw *hw,
* Link Health register. In IGP this bit is latched high, so the driver must
* read it immediately after link is established.
*****************************************************************************/
-static s32
-e1000_check_downshift(struct e1000_hw *hw)
+static s32 e1000_check_downshift(struct e1000_hw *hw)
{
s32 ret_val;
u16 phy_data;
@@ -6985,9 +6861,7 @@ e1000_check_downshift(struct e1000_hw *hw)
*
****************************************************************************/
-static s32
-e1000_config_dsp_after_link_change(struct e1000_hw *hw,
- bool link_up)
+static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
{
s32 ret_val;
u16 phy_data, phy_saved_data, speed, duplex, i;
@@ -7173,8 +7047,7 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
*
* hw - Struct containing variables accessed by shared code
****************************************************************************/
-static s32
-e1000_set_phy_mode(struct e1000_hw *hw)
+static s32 e1000_set_phy_mode(struct e1000_hw *hw)
{
s32 ret_val;
u16 eeprom_data;
@@ -7218,9 +7091,7 @@ e1000_set_phy_mode(struct e1000_hw *hw)
*
****************************************************************************/
-static s32
-e1000_set_d3_lplu_state(struct e1000_hw *hw,
- bool active)
+static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active)
{
u32 phy_ctrl = 0;
s32 ret_val;
@@ -7242,7 +7113,7 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw,
/* MAC writes into PHY register based on the state transition
* and start auto-negotiation. SW driver can overwrite the settings
* in CSR PHY power control E1000_PHY_CTRL register. */
- phy_ctrl = E1000_READ_REG(hw, PHY_CTRL);
+ phy_ctrl = er32(PHY_CTRL);
} else {
ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
if (ret_val)
@@ -7259,7 +7130,7 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw,
} else {
if (hw->mac_type == e1000_ich8lan) {
phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU;
- E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+ ew32(PHY_CTRL, phy_ctrl);
} else {
phy_data &= ~IGP02E1000_PM_D3_LPLU;
ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
@@ -7310,7 +7181,7 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw,
} else {
if (hw->mac_type == e1000_ich8lan) {
phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU;
- E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+ ew32(PHY_CTRL, phy_ctrl);
} else {
phy_data |= IGP02E1000_PM_D3_LPLU;
ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
@@ -7348,9 +7219,7 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw,
*
****************************************************************************/
-static s32
-e1000_set_d0_lplu_state(struct e1000_hw *hw,
- bool active)
+static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
{
u32 phy_ctrl = 0;
s32 ret_val;
@@ -7361,7 +7230,7 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw,
return E1000_SUCCESS;
if (hw->mac_type == e1000_ich8lan) {
- phy_ctrl = E1000_READ_REG(hw, PHY_CTRL);
+ phy_ctrl = er32(PHY_CTRL);
} else {
ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
if (ret_val)
@@ -7371,7 +7240,7 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw,
if (!active) {
if (hw->mac_type == e1000_ich8lan) {
phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
- E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+ ew32(PHY_CTRL, phy_ctrl);
} else {
phy_data &= ~IGP02E1000_PM_D0_LPLU;
ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
@@ -7412,7 +7281,7 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw,
if (hw->mac_type == e1000_ich8lan) {
phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;
- E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+ ew32(PHY_CTRL, phy_ctrl);
} else {
phy_data |= IGP02E1000_PM_D0_LPLU;
ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
@@ -7439,8 +7308,7 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw,
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static s32
-e1000_set_vco_speed(struct e1000_hw *hw)
+static s32 e1000_set_vco_speed(struct e1000_hw *hw)
{
s32 ret_val;
u16 default_page = 0;
@@ -7503,8 +7371,7 @@ e1000_set_vco_speed(struct e1000_hw *hw)
*
* returns: - E1000_SUCCESS .
****************************************************************************/
-static s32
-e1000_host_if_read_cookie(struct e1000_hw * hw, u8 *buffer)
+static s32 e1000_host_if_read_cookie(struct e1000_hw *hw, u8 *buffer)
{
u8 i;
u32 offset = E1000_MNG_DHCP_COOKIE_OFFSET;
@@ -7514,7 +7381,7 @@ e1000_host_if_read_cookie(struct e1000_hw * hw, u8 *buffer)
offset = (offset >> 2);
for (i = 0; i < length; i++) {
- *((u32 *) buffer + i) =
+ *((u32 *)buffer + i) =
E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset + i);
}
return E1000_SUCCESS;
@@ -7530,21 +7397,20 @@ e1000_host_if_read_cookie(struct e1000_hw * hw, u8 *buffer)
* timeout
* - E1000_SUCCESS for success.
****************************************************************************/
-static s32
-e1000_mng_enable_host_if(struct e1000_hw * hw)
+static s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
{
u32 hicr;
u8 i;
/* Check that the host interface is enabled. */
- hicr = E1000_READ_REG(hw, HICR);
+ hicr = er32(HICR);
if ((hicr & E1000_HICR_EN) == 0) {
DEBUGOUT("E1000_HOST_EN bit disabled.\n");
return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
/* check the previous command is completed */
for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
- hicr = E1000_READ_REG(hw, HICR);
+ hicr = er32(HICR);
if (!(hicr & E1000_HICR_C))
break;
mdelay(1);
@@ -7564,9 +7430,8 @@ e1000_mng_enable_host_if(struct e1000_hw * hw)
*
* returns - E1000_SUCCESS for success.
****************************************************************************/
-static s32
-e1000_mng_host_if_write(struct e1000_hw * hw, u8 *buffer,
- u16 length, u16 offset, u8 *sum)
+static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length,
+ u16 offset, u8 *sum)
{
u8 *tmp;
u8 *bufptr = buffer;
@@ -7632,9 +7497,8 @@ e1000_mng_host_if_write(struct e1000_hw * hw, u8 *buffer,
*
* returns - E1000_SUCCESS for success.
****************************************************************************/
-static s32
-e1000_mng_write_cmd_header(struct e1000_hw * hw,
- struct e1000_host_mng_command_header * hdr)
+static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
+ struct e1000_host_mng_command_header *hdr)
{
u16 i;
u8 sum;
@@ -7648,7 +7512,7 @@ e1000_mng_write_cmd_header(struct e1000_hw * hw,
sum = hdr->checksum;
hdr->checksum = 0;
- buffer = (u8 *) hdr;
+ buffer = (u8 *)hdr;
i = length;
while (i--)
sum += buffer[i];
@@ -7658,8 +7522,8 @@ e1000_mng_write_cmd_header(struct e1000_hw * hw,
length >>= 2;
/* The device driver writes the relevant command block into the ram area. */
for (i = 0; i < length; i++) {
- E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((u32 *) hdr + i));
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((u32 *)hdr + i));
+ E1000_WRITE_FLUSH();
}
return E1000_SUCCESS;
@@ -7672,14 +7536,13 @@ e1000_mng_write_cmd_header(struct e1000_hw * hw,
*
* returns - E1000_SUCCESS for success.
****************************************************************************/
-static s32
-e1000_mng_write_commit(struct e1000_hw * hw)
+static s32 e1000_mng_write_commit(struct e1000_hw *hw)
{
u32 hicr;
- hicr = E1000_READ_REG(hw, HICR);
+ hicr = er32(HICR);
/* Setting this bit tells the ARC that a new command is pending. */
- E1000_WRITE_REG(hw, HICR, hicr | E1000_HICR_C);
+ ew32(HICR, hicr | E1000_HICR_C);
return E1000_SUCCESS;
}
@@ -7690,12 +7553,11 @@ e1000_mng_write_commit(struct e1000_hw * hw)
*
* returns - true when the mode is IAMT or false.
****************************************************************************/
-bool
-e1000_check_mng_mode(struct e1000_hw *hw)
+bool e1000_check_mng_mode(struct e1000_hw *hw)
{
u32 fwsm;
- fwsm = E1000_READ_REG(hw, FWSM);
+ fwsm = er32(FWSM);
if (hw->mac_type == e1000_ich8lan) {
if ((fwsm & E1000_FWSM_MODE_MASK) ==
@@ -7712,9 +7574,7 @@ e1000_check_mng_mode(struct e1000_hw *hw)
/*****************************************************************************
* This function writes the dhcp info .
****************************************************************************/
-s32
-e1000_mng_write_dhcp_info(struct e1000_hw * hw, u8 *buffer,
- u16 length)
+s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length)
{
s32 ret_val;
struct e1000_host_mng_command_header hdr;
@@ -7744,8 +7604,7 @@ e1000_mng_write_dhcp_info(struct e1000_hw * hw, u8 *buffer,
*
* returns - checksum of buffer contents.
****************************************************************************/
-static u8
-e1000_calculate_mng_checksum(char *buffer, u32 length)
+static u8 e1000_calculate_mng_checksum(char *buffer, u32 length)
{
u8 sum = 0;
u32 i;
@@ -7756,7 +7615,7 @@ e1000_calculate_mng_checksum(char *buffer, u32 length)
for (i=0; i < length; i++)
sum += buffer[i];
- return (u8) (0 - sum);
+ return (u8)(0 - sum);
}
/*****************************************************************************
@@ -7764,8 +7623,7 @@ e1000_calculate_mng_checksum(char *buffer, u32 length)
*
* returns - true for packet filtering or false.
****************************************************************************/
-bool
-e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
{
/* called in init as well as watchdog timer functions */
@@ -7806,21 +7664,20 @@ e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
* returns: - true/false
*
*****************************************************************************/
-u32
-e1000_enable_mng_pass_thru(struct e1000_hw *hw)
+u32 e1000_enable_mng_pass_thru(struct e1000_hw *hw)
{
u32 manc;
u32 fwsm, factps;
if (hw->asf_firmware_present) {
- manc = E1000_READ_REG(hw, MANC);
+ manc = er32(MANC);
if (!(manc & E1000_MANC_RCV_TCO_EN) ||
!(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
return false;
if (e1000_arc_subsystem_valid(hw)) {
- fwsm = E1000_READ_REG(hw, FWSM);
- factps = E1000_READ_REG(hw, FACTPS);
+ fwsm = er32(FWSM);
+ factps = er32(FACTPS);
if ((((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT) ==
e1000_mng_mode_pt) && !(factps & E1000_FACTPS_MNGCG))
@@ -7832,8 +7689,7 @@ e1000_enable_mng_pass_thru(struct e1000_hw *hw)
return false;
}
-static s32
-e1000_polarity_reversal_workaround(struct e1000_hw *hw)
+static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw)
{
s32 ret_val;
u16 mii_status_reg;
@@ -7926,8 +7782,7 @@ e1000_polarity_reversal_workaround(struct e1000_hw *hw)
* returns: - none.
*
***************************************************************************/
-static void
-e1000_set_pci_express_master_disable(struct e1000_hw *hw)
+static void e1000_set_pci_express_master_disable(struct e1000_hw *hw)
{
u32 ctrl;
@@ -7936,9 +7791,9 @@ e1000_set_pci_express_master_disable(struct e1000_hw *hw)
if (hw->bus_type != e1000_bus_type_pci_express)
return;
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
ctrl |= E1000_CTRL_GIO_MASTER_DISABLE;
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
}
/*******************************************************************************
@@ -7952,8 +7807,7 @@ e1000_set_pci_express_master_disable(struct e1000_hw *hw)
* E1000_SUCCESS master requests disabled.
*
******************************************************************************/
-s32
-e1000_disable_pciex_master(struct e1000_hw *hw)
+s32 e1000_disable_pciex_master(struct e1000_hw *hw)
{
s32 timeout = MASTER_DISABLE_TIMEOUT; /* 80ms */
@@ -7965,7 +7819,7 @@ e1000_disable_pciex_master(struct e1000_hw *hw)
e1000_set_pci_express_master_disable(hw);
while (timeout) {
- if (!(E1000_READ_REG(hw, STATUS) & E1000_STATUS_GIO_MASTER_ENABLE))
+ if (!(er32(STATUS) & E1000_STATUS_GIO_MASTER_ENABLE))
break;
else
udelay(100);
@@ -7990,8 +7844,7 @@ e1000_disable_pciex_master(struct e1000_hw *hw)
* E1000_SUCCESS at any other case.
*
******************************************************************************/
-static s32
-e1000_get_auto_rd_done(struct e1000_hw *hw)
+static s32 e1000_get_auto_rd_done(struct e1000_hw *hw)
{
s32 timeout = AUTO_READ_DONE_TIMEOUT;
@@ -8007,7 +7860,7 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
case e1000_80003es2lan:
case e1000_ich8lan:
while (timeout) {
- if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD)
+ if (er32(EECD) & E1000_EECD_AUTO_RD)
break;
else msleep(1);
timeout--;
@@ -8038,8 +7891,7 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
* E1000_SUCCESS at any other case.
*
***************************************************************************/
-static s32
-e1000_get_phy_cfg_done(struct e1000_hw *hw)
+static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw)
{
s32 timeout = PHY_CFG_TIMEOUT;
u32 cfg_mask = E1000_EEPROM_CFG_DONE;
@@ -8052,13 +7904,13 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
break;
case e1000_80003es2lan:
/* Separate *_CFG_DONE_* bit for each port */
- if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+ if (er32(STATUS) & E1000_STATUS_FUNC_1)
cfg_mask = E1000_EEPROM_CFG_DONE_PORT_1;
/* Fall Through */
case e1000_82571:
case e1000_82572:
while (timeout) {
- if (E1000_READ_REG(hw, EEMNGCTL) & cfg_mask)
+ if (er32(EEMNGCTL) & cfg_mask)
break;
else
msleep(1);
@@ -8085,8 +7937,7 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
* E1000_SUCCESS at any other case.
*
***************************************************************************/
-static s32
-e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
+static s32 e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
{
s32 timeout;
u32 swsm;
@@ -8105,11 +7956,11 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
/* Get the FW semaphore. */
timeout = hw->eeprom.word_size + 1;
while (timeout) {
- swsm = E1000_READ_REG(hw, SWSM);
+ swsm = er32(SWSM);
swsm |= E1000_SWSM_SWESMBI;
- E1000_WRITE_REG(hw, SWSM, swsm);
+ ew32(SWSM, swsm);
/* if we managed to set the bit we got the semaphore. */
- swsm = E1000_READ_REG(hw, SWSM);
+ swsm = er32(SWSM);
if (swsm & E1000_SWSM_SWESMBI)
break;
@@ -8135,8 +7986,7 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
* returns: - None.
*
***************************************************************************/
-static void
-e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
+static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
{
u32 swsm;
@@ -8145,13 +7995,13 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
if (!hw->eeprom_semaphore_present)
return;
- swsm = E1000_READ_REG(hw, SWSM);
+ swsm = er32(SWSM);
if (hw->mac_type == e1000_80003es2lan) {
/* Release both semaphores. */
swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
} else
swsm &= ~(E1000_SWSM_SWESMBI);
- E1000_WRITE_REG(hw, SWSM, swsm);
+ ew32(SWSM, swsm);
}
/***************************************************************************
@@ -8164,8 +8014,7 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
* E1000_SUCCESS at any other case.
*
***************************************************************************/
-static s32
-e1000_get_software_semaphore(struct e1000_hw *hw)
+static s32 e1000_get_software_semaphore(struct e1000_hw *hw)
{
s32 timeout = hw->eeprom.word_size + 1;
u32 swsm;
@@ -8177,7 +8026,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
}
while (timeout) {
- swsm = E1000_READ_REG(hw, SWSM);
+ swsm = er32(SWSM);
/* If SMBI bit cleared, it is now set and we hold the semaphore */
if (!(swsm & E1000_SWSM_SMBI))
break;
@@ -8200,8 +8049,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
* hw: Struct containing variables accessed by shared code
*
***************************************************************************/
-static void
-e1000_release_software_semaphore(struct e1000_hw *hw)
+static void e1000_release_software_semaphore(struct e1000_hw *hw)
{
u32 swsm;
@@ -8211,10 +8059,10 @@ e1000_release_software_semaphore(struct e1000_hw *hw)
return;
}
- swsm = E1000_READ_REG(hw, SWSM);
+ swsm = er32(SWSM);
/* Release the SW semaphores.*/
swsm &= ~E1000_SWSM_SMBI;
- E1000_WRITE_REG(hw, SWSM, swsm);
+ ew32(SWSM, swsm);
}
/******************************************************************************
@@ -8228,26 +8076,24 @@ e1000_release_software_semaphore(struct e1000_hw *hw)
* E1000_SUCCESS
*
*****************************************************************************/
-s32
-e1000_check_phy_reset_block(struct e1000_hw *hw)
+s32 e1000_check_phy_reset_block(struct e1000_hw *hw)
{
u32 manc = 0;
u32 fwsm = 0;
if (hw->mac_type == e1000_ich8lan) {
- fwsm = E1000_READ_REG(hw, FWSM);
+ fwsm = er32(FWSM);
return (fwsm & E1000_FWSM_RSPCIPHY) ? E1000_SUCCESS
: E1000_BLK_PHY_RESET;
}
if (hw->mac_type > e1000_82547_rev_2)
- manc = E1000_READ_REG(hw, MANC);
+ manc = er32(MANC);
return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ?
E1000_BLK_PHY_RESET : E1000_SUCCESS;
}
-static u8
-e1000_arc_subsystem_valid(struct e1000_hw *hw)
+static u8 e1000_arc_subsystem_valid(struct e1000_hw *hw)
{
u32 fwsm;
@@ -8261,7 +8107,7 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
case e1000_82572:
case e1000_82573:
case e1000_80003es2lan:
- fwsm = E1000_READ_REG(hw, FWSM);
+ fwsm = er32(FWSM);
if ((fwsm & E1000_FWSM_MODE_MASK) != 0)
return true;
break;
@@ -8283,8 +8129,7 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
* returns: E1000_SUCCESS
*
*****************************************************************************/
-static s32
-e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop)
+static s32 e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop)
{
u32 gcr_reg = 0;
@@ -8297,19 +8142,19 @@ e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop)
return E1000_SUCCESS;
if (no_snoop) {
- gcr_reg = E1000_READ_REG(hw, GCR);
+ gcr_reg = er32(GCR);
gcr_reg &= ~(PCI_EX_NO_SNOOP_ALL);
gcr_reg |= no_snoop;
- E1000_WRITE_REG(hw, GCR, gcr_reg);
+ ew32(GCR, gcr_reg);
}
if (hw->mac_type == e1000_ich8lan) {
u32 ctrl_ext;
- E1000_WRITE_REG(hw, GCR, PCI_EX_82566_SNOOP_ALL);
+ ew32(GCR, PCI_EX_82566_SNOOP_ALL);
- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext = er32(CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ ew32(CTRL_EXT, ctrl_ext);
}
return E1000_SUCCESS;
@@ -8324,8 +8169,7 @@ e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop)
* hw: Struct containing variables accessed by shared code
*
***************************************************************************/
-static s32
-e1000_get_software_flag(struct e1000_hw *hw)
+static s32 e1000_get_software_flag(struct e1000_hw *hw)
{
s32 timeout = PHY_CFG_TIMEOUT;
u32 extcnf_ctrl;
@@ -8334,11 +8178,11 @@ e1000_get_software_flag(struct e1000_hw *hw)
if (hw->mac_type == e1000_ich8lan) {
while (timeout) {
- extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+ extcnf_ctrl = er32(EXTCNF_CTRL);
extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
- E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
+ ew32(EXTCNF_CTRL, extcnf_ctrl);
- extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+ extcnf_ctrl = er32(EXTCNF_CTRL);
if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)
break;
mdelay(1);
@@ -8363,17 +8207,16 @@ e1000_get_software_flag(struct e1000_hw *hw)
* hw: Struct containing variables accessed by shared code
*
***************************************************************************/
-static void
-e1000_release_software_flag(struct e1000_hw *hw)
+static void e1000_release_software_flag(struct e1000_hw *hw)
{
u32 extcnf_ctrl;
DEBUGFUNC("e1000_release_software_flag");
if (hw->mac_type == e1000_ich8lan) {
- extcnf_ctrl= E1000_READ_REG(hw, EXTCNF_CTRL);
+ extcnf_ctrl= er32(EXTCNF_CTRL);
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
- E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
+ ew32(EXTCNF_CTRL, extcnf_ctrl);
}
return;
@@ -8388,9 +8231,8 @@ e1000_release_software_flag(struct e1000_hw *hw)
* data - word read from the EEPROM
* words - number of words to read
*****************************************************************************/
-static s32
-e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data)
+static s32 e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
{
s32 error = E1000_SUCCESS;
u32 flash_bank = 0;
@@ -8405,7 +8247,7 @@ e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
* to be updated with each read.
*/
/* Value of bit 22 corresponds to the flash bank we're on. */
- flash_bank = (E1000_READ_REG(hw, EECD) & E1000_EECD_SEC1VAL) ? 1 : 0;
+ flash_bank = (er32(EECD) & E1000_EECD_SEC1VAL) ? 1 : 0;
/* Adjust offset appropriately if we're on bank 1 - adjust for word size */
bank_offset = flash_bank * (hw->flash_bank_size * 2);
@@ -8444,9 +8286,8 @@ e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
* words - number of words to write
* data - words to write to the EEPROM
*****************************************************************************/
-static s32
-e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data)
+static s32 e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
{
u32 i = 0;
s32 error = E1000_SUCCESS;
@@ -8491,8 +8332,7 @@ e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
*
* hw - The pointer to the hw structure
****************************************************************************/
-static s32
-e1000_ich8_cycle_init(struct e1000_hw *hw)
+static s32 e1000_ich8_cycle_init(struct e1000_hw *hw)
{
union ich8_hws_flash_status hsfsts;
s32 error = E1000_ERR_EEPROM;
@@ -8558,8 +8398,7 @@ e1000_ich8_cycle_init(struct e1000_hw *hw)
*
* hw - The pointer to the hw structure
****************************************************************************/
-static s32
-e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout)
+static s32 e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout)
{
union ich8_hws_flash_ctrl hsflctl;
union ich8_hws_flash_status hsfsts;
@@ -8593,9 +8432,8 @@ e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout)
* size - Size of data to read, 1=byte 2=word
* data - Pointer to the word to store the value read.
*****************************************************************************/
-static s32
-e1000_read_ich8_data(struct e1000_hw *hw, u32 index,
- u32 size, u16* data)
+static s32 e1000_read_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
+ u16 *data)
{
union ich8_hws_flash_status hsfsts;
union ich8_hws_flash_ctrl hsflctl;
@@ -8672,9 +8510,8 @@ e1000_read_ich8_data(struct e1000_hw *hw, u32 index,
* size - Size of data to read, 1=byte 2=word
* data - The byte(s) to write to the NVM.
*****************************************************************************/
-static s32
-e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
- u16 data)
+static s32 e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
+ u16 data)
{
union ich8_hws_flash_status hsfsts;
union ich8_hws_flash_ctrl hsflctl;
@@ -8747,8 +8584,7 @@ e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
* index - The index of the byte to read.
* data - Pointer to a byte to store the value read.
*****************************************************************************/
-static s32
-e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8* data)
+static s32 e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8 *data)
{
s32 status = E1000_SUCCESS;
u16 word = 0;
@@ -8770,8 +8606,7 @@ e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8* data)
* index - The index of the byte to write.
* byte - The byte to write to the NVM.
*****************************************************************************/
-static s32
-e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte)
+static s32 e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte)
{
s32 error = E1000_SUCCESS;
s32 program_retries = 0;
@@ -8803,8 +8638,7 @@ e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte)
* index - The index of the byte to read.
* data - The byte to write to the NVM.
*****************************************************************************/
-static s32
-e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 data)
+static s32 e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 data)
{
s32 status = E1000_SUCCESS;
u16 word = (u16)data;
@@ -8821,8 +8655,7 @@ e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 data)
* index - The starting byte index of the word to read.
* data - Pointer to a word to store the value read.
*****************************************************************************/
-static s32
-e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data)
+static s32 e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data)
{
s32 status = E1000_SUCCESS;
status = e1000_read_ich8_data(hw, index, 2, data);
@@ -8840,8 +8673,7 @@ e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data)
* amount of NVM used in each bank is a *minimum* of 4 KBytes, but in fact the
* bank size may be 4, 8 or 64 KBytes
*****************************************************************************/
-static s32
-e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank)
+static s32 e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank)
{
union ich8_hws_flash_status hsfsts;
union ich8_hws_flash_ctrl hsflctl;
@@ -8930,9 +8762,9 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank)
return error;
}
-static s32
-e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
- u32 cnf_base_addr, u32 cnf_size)
+static s32 e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
+ u32 cnf_base_addr,
+ u32 cnf_size)
{
u32 ret_val = E1000_SUCCESS;
u16 word_addr, reg_data, reg_addr;
@@ -8972,8 +8804,7 @@ e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
*
* hw: Struct containing variables accessed by shared code
*****************************************************************************/
-static s32
-e1000_init_lcd_from_nvm(struct e1000_hw *hw)
+static s32 e1000_init_lcd_from_nvm(struct e1000_hw *hw)
{
u32 reg_data, cnf_base_addr, cnf_size, ret_val, loop;
@@ -8981,32 +8812,32 @@ e1000_init_lcd_from_nvm(struct e1000_hw *hw)
return E1000_SUCCESS;
/* Check if SW needs configure the PHY */
- reg_data = E1000_READ_REG(hw, FEXTNVM);
+ reg_data = er32(FEXTNVM);
if (!(reg_data & FEXTNVM_SW_CONFIG))
return E1000_SUCCESS;
/* Wait for basic configuration completes before proceeding*/
loop = 0;
do {
- reg_data = E1000_READ_REG(hw, STATUS) & E1000_STATUS_LAN_INIT_DONE;
+ reg_data = er32(STATUS) & E1000_STATUS_LAN_INIT_DONE;
udelay(100);
loop++;
} while ((!reg_data) && (loop < 50));
/* Clear the Init Done bit for the next init event */
- reg_data = E1000_READ_REG(hw, STATUS);
+ reg_data = er32(STATUS);
reg_data &= ~E1000_STATUS_LAN_INIT_DONE;
- E1000_WRITE_REG(hw, STATUS, reg_data);
+ ew32(STATUS, reg_data);
/* Make sure HW does not configure LCD from PHY extended configuration
before SW configuration */
- reg_data = E1000_READ_REG(hw, EXTCNF_CTRL);
+ reg_data = er32(EXTCNF_CTRL);
if ((reg_data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) == 0x0000) {
- reg_data = E1000_READ_REG(hw, EXTCNF_SIZE);
+ reg_data = er32(EXTCNF_SIZE);
cnf_size = reg_data & E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH;
cnf_size >>= 16;
if (cnf_size) {
- reg_data = E1000_READ_REG(hw, EXTCNF_CTRL);
+ reg_data = er32(EXTCNF_CTRL);
cnf_base_addr = reg_data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER;
/* cnf_base_addr is in DWORD */
cnf_base_addr >>= 16;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index cf12b05cd01..ad6da7b67e5 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -31,12 +31,7 @@
char e1000_driver_name[] = "e1000";
static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
-#ifndef CONFIG_E1000_NAPI
-#define DRIVERNAPI
-#else
-#define DRIVERNAPI "-NAPI"
-#endif
-#define DRV_VERSION "7.3.20-k2"DRIVERNAPI
+#define DRV_VERSION "7.3.20-k3-NAPI"
const char e1000_driver_version[] = DRV_VERSION;
static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
@@ -138,7 +133,6 @@ static irqreturn_t e1000_intr(int irq, void *data);
static irqreturn_t e1000_intr_msi(int irq, void *data);
static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
struct e1000_tx_ring *tx_ring);
-#ifdef CONFIG_E1000_NAPI
static int e1000_clean(struct napi_struct *napi, int budget);
static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring,
@@ -146,12 +140,6 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring,
int *work_done, int work_to_do);
-#else
-static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
-static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
-#endif
static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring,
int cleaned_count);
@@ -232,8 +220,7 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
* loaded. All it does is register with the PCI subsystem.
**/
-static int __init
-e1000_init_module(void)
+static int __init e1000_init_module(void)
{
int ret;
printk(KERN_INFO "%s - version %s\n",
@@ -261,8 +248,7 @@ module_init(e1000_init_module);
* from memory.
**/
-static void __exit
-e1000_exit_module(void)
+static void __exit e1000_exit_module(void)
{
pci_unregister_driver(&e1000_driver);
}
@@ -271,12 +257,13 @@ module_exit(e1000_exit_module);
static int e1000_request_irq(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
irq_handler_t handler = e1000_intr;
int irq_flags = IRQF_SHARED;
int err;
- if (adapter->hw.mac_type >= e1000_82571) {
+ if (hw->mac_type >= e1000_82571) {
adapter->have_msi = !pci_enable_msi(adapter->pdev);
if (adapter->have_msi) {
handler = e1000_intr_msi;
@@ -311,11 +298,12 @@ static void e1000_free_irq(struct e1000_adapter *adapter)
* @adapter: board private structure
**/
-static void
-e1000_irq_disable(struct e1000_adapter *adapter)
+static void e1000_irq_disable(struct e1000_adapter *adapter)
{
- E1000_WRITE_REG(&adapter->hw, IMC, ~0);
- E1000_WRITE_FLUSH(&adapter->hw);
+ struct e1000_hw *hw = &adapter->hw;
+
+ ew32(IMC, ~0);
+ E1000_WRITE_FLUSH();
synchronize_irq(adapter->pdev->irq);
}
@@ -324,22 +312,23 @@ e1000_irq_disable(struct e1000_adapter *adapter)
* @adapter: board private structure
**/
-static void
-e1000_irq_enable(struct e1000_adapter *adapter)
+static void e1000_irq_enable(struct e1000_adapter *adapter)
{
- E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
- E1000_WRITE_FLUSH(&adapter->hw);
+ struct e1000_hw *hw = &adapter->hw;
+
+ ew32(IMS, IMS_ENABLE_MASK);
+ E1000_WRITE_FLUSH();
}
-static void
-e1000_update_mng_vlan(struct e1000_adapter *adapter)
+static void e1000_update_mng_vlan(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
- u16 vid = adapter->hw.mng_cookie.vlan_id;
+ u16 vid = hw->mng_cookie.vlan_id;
u16 old_vid = adapter->mng_vlan_id;
if (adapter->vlgrp) {
if (!vlan_group_get_device(adapter->vlgrp, vid)) {
- if (adapter->hw.mng_cookie.status &
+ if (hw->mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
e1000_vlan_rx_add_vid(netdev, vid);
adapter->mng_vlan_id = vid;
@@ -366,26 +355,24 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
*
**/
-static void
-e1000_release_hw_control(struct e1000_adapter *adapter)
+static void e1000_release_hw_control(struct e1000_adapter *adapter)
{
u32 ctrl_ext;
u32 swsm;
+ struct e1000_hw *hw = &adapter->hw;
/* Let firmware taken over control of h/w */
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82573:
- swsm = E1000_READ_REG(&adapter->hw, SWSM);
- E1000_WRITE_REG(&adapter->hw, SWSM,
- swsm & ~E1000_SWSM_DRV_LOAD);
+ swsm = er32(SWSM);
+ ew32(SWSM, swsm & ~E1000_SWSM_DRV_LOAD);
break;
case e1000_82571:
case e1000_82572:
case e1000_80003es2lan:
case e1000_ich8lan:
- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
- E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
- ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+ ctrl_ext = er32(CTRL_EXT);
+ ew32(CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
break;
default:
break;
@@ -403,37 +390,36 @@ e1000_release_hw_control(struct e1000_adapter *adapter)
*
**/
-static void
-e1000_get_hw_control(struct e1000_adapter *adapter)
+static void e1000_get_hw_control(struct e1000_adapter *adapter)
{
u32 ctrl_ext;
u32 swsm;
+ struct e1000_hw *hw = &adapter->hw;
/* Let firmware know the driver has taken over */
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82573:
- swsm = E1000_READ_REG(&adapter->hw, SWSM);
- E1000_WRITE_REG(&adapter->hw, SWSM,
- swsm | E1000_SWSM_DRV_LOAD);
+ swsm = er32(SWSM);
+ ew32(SWSM, swsm | E1000_SWSM_DRV_LOAD);
break;
case e1000_82571:
case e1000_82572:
case e1000_80003es2lan:
case e1000_ich8lan:
- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
- E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
- ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+ ctrl_ext = er32(CTRL_EXT);
+ ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
break;
default:
break;
}
}
-static void
-e1000_init_manageability(struct e1000_adapter *adapter)
+static void e1000_init_manageability(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
+
if (adapter->en_mng_pt) {
- u32 manc = E1000_READ_REG(&adapter->hw, MANC);
+ u32 manc = er32(MANC);
/* disable hardware interception of ARP */
manc &= ~(E1000_MANC_ARP_EN);
@@ -441,37 +427,38 @@ e1000_init_manageability(struct e1000_adapter *adapter)
/* enable receiving management packets to the host */
/* this will probably generate destination unreachable messages
* from the host OS, but the packets will be handled on SMBUS */
- if (adapter->hw.has_manc2h) {
- u32 manc2h = E1000_READ_REG(&adapter->hw, MANC2H);
+ if (hw->has_manc2h) {
+ u32 manc2h = er32(MANC2H);
manc |= E1000_MANC_EN_MNG2HOST;
#define E1000_MNG2HOST_PORT_623 (1 << 5)
#define E1000_MNG2HOST_PORT_664 (1 << 6)
manc2h |= E1000_MNG2HOST_PORT_623;
manc2h |= E1000_MNG2HOST_PORT_664;
- E1000_WRITE_REG(&adapter->hw, MANC2H, manc2h);
+ ew32(MANC2H, manc2h);
}
- E1000_WRITE_REG(&adapter->hw, MANC, manc);
+ ew32(MANC, manc);
}
}
-static void
-e1000_release_manageability(struct e1000_adapter *adapter)
+static void e1000_release_manageability(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
+
if (adapter->en_mng_pt) {
- u32 manc = E1000_READ_REG(&adapter->hw, MANC);
+ u32 manc = er32(MANC);
/* re-enable hardware interception of ARP */
manc |= E1000_MANC_ARP_EN;
- if (adapter->hw.has_manc2h)
+ if (hw->has_manc2h)
manc &= ~E1000_MANC_EN_MNG2HOST;
/* don't explicitly have to mess with MANC2H since
* MANC has an enable disable that gates MANC2H */
- E1000_WRITE_REG(&adapter->hw, MANC, manc);
+ ew32(MANC, manc);
}
}
@@ -506,18 +493,19 @@ static void e1000_configure(struct e1000_adapter *adapter)
int e1000_up(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
+
/* hardware has been reset, we need to reload some things */
e1000_configure(adapter);
clear_bit(__E1000_DOWN, &adapter->flags);
-#ifdef CONFIG_E1000_NAPI
napi_enable(&adapter->napi);
-#endif
+
e1000_irq_enable(adapter);
/* fire a link change interrupt to start the watchdog */
- E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_LSC);
+ ew32(ICS, E1000_ICS_LSC);
return 0;
}
@@ -533,30 +521,33 @@ int e1000_up(struct e1000_adapter *adapter)
void e1000_power_up_phy(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
u16 mii_reg = 0;
/* Just clear the power down bit to wake the phy back up */
- if (adapter->hw.media_type == e1000_media_type_copper) {
+ if (hw->media_type == e1000_media_type_copper) {
/* according to the manual, the phy will retain its
* settings across a power-down/up cycle */
- e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
+ e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
mii_reg &= ~MII_CR_POWER_DOWN;
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg);
+ e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
}
}
static void e1000_power_down_phy(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
+
/* Power down the PHY so no link is implied when interface is down *
* The PHY cannot be powered down if any of the following is true *
* (a) WoL is enabled
* (b) AMT is active
* (c) SoL/IDER session is active */
- if (!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
- adapter->hw.media_type == e1000_media_type_copper) {
+ if (!adapter->wol && hw->mac_type >= e1000_82540 &&
+ hw->media_type == e1000_media_type_copper) {
u16 mii_reg = 0;
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82540:
case e1000_82545:
case e1000_82545_rev_3:
@@ -566,8 +557,7 @@ static void e1000_power_down_phy(struct e1000_adapter *adapter)
case e1000_82541_rev_2:
case e1000_82547:
case e1000_82547_rev_2:
- if (E1000_READ_REG(&adapter->hw, MANC) &
- E1000_MANC_SMBUS_EN)
+ if (er32(MANC) & E1000_MANC_SMBUS_EN)
goto out;
break;
case e1000_82571:
@@ -575,24 +565,23 @@ static void e1000_power_down_phy(struct e1000_adapter *adapter)
case e1000_82573:
case e1000_80003es2lan:
case e1000_ich8lan:
- if (e1000_check_mng_mode(&adapter->hw) ||
- e1000_check_phy_reset_block(&adapter->hw))
+ if (e1000_check_mng_mode(hw) ||
+ e1000_check_phy_reset_block(hw))
goto out;
break;
default:
goto out;
}
- e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
+ e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
mii_reg |= MII_CR_POWER_DOWN;
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg);
+ e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
mdelay(1);
}
out:
return;
}
-void
-e1000_down(struct e1000_adapter *adapter)
+void e1000_down(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@@ -600,9 +589,8 @@ e1000_down(struct e1000_adapter *adapter)
* reschedule our watchdog timer */
set_bit(__E1000_DOWN, &adapter->flags);
-#ifdef CONFIG_E1000_NAPI
napi_disable(&adapter->napi);
-#endif
+
e1000_irq_disable(adapter);
del_timer_sync(&adapter->tx_fifo_stall_timer);
@@ -620,8 +608,7 @@ e1000_down(struct e1000_adapter *adapter)
e1000_clean_all_rx_rings(adapter);
}
-void
-e1000_reinit_locked(struct e1000_adapter *adapter)
+void e1000_reinit_locked(struct e1000_adapter *adapter)
{
WARN_ON(in_interrupt());
while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
@@ -631,9 +618,9 @@ e1000_reinit_locked(struct e1000_adapter *adapter)
clear_bit(__E1000_RESETTING, &adapter->flags);
}
-void
-e1000_reset(struct e1000_adapter *adapter)
+void e1000_reset(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
u32 pba = 0, tx_space, min_tx_space, min_rx_space;
u16 fc_high_water_mark = E1000_FC_HIGH_DIFF;
bool legacy_pba_adjust = false;
@@ -642,7 +629,7 @@ e1000_reset(struct e1000_adapter *adapter)
* To take effect CTRL.RST is required.
*/
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
case e1000_82543:
@@ -683,16 +670,16 @@ e1000_reset(struct e1000_adapter *adapter)
if (adapter->netdev->mtu > E1000_RXBUFFER_8192)
pba -= 8; /* allocate more FIFO for Tx */
- if (adapter->hw.mac_type == e1000_82547) {
+ if (hw->mac_type == e1000_82547) {
adapter->tx_fifo_head = 0;
adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
adapter->tx_fifo_size =
(E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
atomic_set(&adapter->tx_fifo_stall, 0);
}
- } else if (adapter->hw.max_frame_size > MAXIMUM_ETHERNET_FRAME_SIZE) {
+ } else if (hw->max_frame_size > MAXIMUM_ETHERNET_FRAME_SIZE) {
/* adjust PBA for jumbo frames */
- E1000_WRITE_REG(&adapter->hw, PBA, pba);
+ ew32(PBA, pba);
/* To maintain wire speed transmits, the Tx FIFO should be
* large enough to accomodate two full transmit packets,
@@ -700,7 +687,7 @@ e1000_reset(struct e1000_adapter *adapter)
* the Rx FIFO should be large enough to accomodate at least
* one full receive packet and is similarly rounded up and
* expressed in KB. */
- pba = E1000_READ_REG(&adapter->hw, PBA);
+ pba = er32(PBA);
/* upper 16 bits has Tx packet buffer allocation size in KB */
tx_space = pba >> 16;
/* lower 16 bits has Rx packet buffer allocation size in KB */
@@ -723,7 +710,7 @@ e1000_reset(struct e1000_adapter *adapter)
pba = pba - (min_tx_space - tx_space);
/* PCI/PCIx hardware has PBA alignment constraints */
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82545 ... e1000_82546_rev_3:
pba &= ~(E1000_PBA_8K - 1);
break;
@@ -734,7 +721,7 @@ e1000_reset(struct e1000_adapter *adapter)
/* if short on rx space, rx wins and must trump tx
* adjustment or use Early Receive if available */
if (pba < min_rx_space) {
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82573:
/* ERT enabled in e1000_configure_rx */
break;
@@ -746,7 +733,7 @@ e1000_reset(struct e1000_adapter *adapter)
}
}
- E1000_WRITE_REG(&adapter->hw, PBA, pba);
+ ew32(PBA, pba);
/* flow control settings */
/* Set the FC high water mark to 90% of the FIFO size.
@@ -759,54 +746,54 @@ e1000_reset(struct e1000_adapter *adapter)
if (pba < E1000_PBA_16K)
fc_high_water_mark = (pba * 1024) - 1600;
- adapter->hw.fc_high_water = fc_high_water_mark;
- adapter->hw.fc_low_water = fc_high_water_mark - 8;
- if (adapter->hw.mac_type == e1000_80003es2lan)
- adapter->hw.fc_pause_time = 0xFFFF;
+ hw->fc_high_water = fc_high_water_mark;
+ hw->fc_low_water = fc_high_water_mark - 8;
+ if (hw->mac_type == e1000_80003es2lan)
+ hw->fc_pause_time = 0xFFFF;
else
- adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME;
- adapter->hw.fc_send_xon = 1;
- adapter->hw.fc = adapter->hw.original_fc;
+ hw->fc_pause_time = E1000_FC_PAUSE_TIME;
+ hw->fc_send_xon = 1;
+ hw->fc = hw->original_fc;
/* Allow time for pending master requests to run */
- e1000_reset_hw(&adapter->hw);
- if (adapter->hw.mac_type >= e1000_82544)
- E1000_WRITE_REG(&adapter->hw, WUC, 0);
+ e1000_reset_hw(hw);
+ if (hw->mac_type >= e1000_82544)
+ ew32(WUC, 0);
- if (e1000_init_hw(&adapter->hw))
+ if (e1000_init_hw(hw))
DPRINTK(PROBE, ERR, "Hardware Error\n");
e1000_update_mng_vlan(adapter);
/* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */
- if (adapter->hw.mac_type >= e1000_82544 &&
- adapter->hw.mac_type <= e1000_82547_rev_2 &&
- adapter->hw.autoneg == 1 &&
- adapter->hw.autoneg_advertised == ADVERTISE_1000_FULL) {
- u32 ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+ if (hw->mac_type >= e1000_82544 &&
+ hw->mac_type <= e1000_82547_rev_2 &&
+ hw->autoneg == 1 &&
+ hw->autoneg_advertised == ADVERTISE_1000_FULL) {
+ u32 ctrl = er32(CTRL);
/* clear phy power management bit if we are in gig only mode,
* which if enabled will attempt negotiation to 100Mb, which
* can cause a loss of link at power off or driver unload */
ctrl &= ~E1000_CTRL_SWDPIN3;
- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
}
/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
- E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE);
+ ew32(VET, ETHERNET_IEEE_VLAN_TYPE);
- e1000_reset_adaptive(&adapter->hw);
- e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
+ e1000_reset_adaptive(hw);
+ e1000_phy_get_info(hw, &adapter->phy_info);
if (!adapter->smart_power_down &&
- (adapter->hw.mac_type == e1000_82571 ||
- adapter->hw.mac_type == e1000_82572)) {
+ (hw->mac_type == e1000_82571 ||
+ hw->mac_type == e1000_82572)) {
u16 phy_data = 0;
/* speed up time to link by disabling smart power down, ignore
* the return value of this function because there is nothing
* different we would do if it failed */
- e1000_read_phy_reg(&adapter->hw, IGP02E1000_PHY_POWER_MGMT,
+ e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
&phy_data);
phy_data &= ~IGP02E1000_PM_SPD;
- e1000_write_phy_reg(&adapter->hw, IGP02E1000_PHY_POWER_MGMT,
+ e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
phy_data);
}
@@ -865,13 +852,49 @@ static void e1000_dump_eeprom(struct e1000_adapter *adapter)
printk(KERN_ERR "to enable this network device.\n");
printk(KERN_ERR "Please inspect the EEPROM dump and report the issue "
"to your hardware vendor\n");
- printk(KERN_ERR "or Intel Customer Support: linux-nics@intel.com\n");
+ printk(KERN_ERR "or Intel Customer Support.\n");
printk(KERN_ERR "/*********************/\n");
kfree(data);
}
/**
+ * e1000_is_need_ioport - determine if an adapter needs ioport resources or not
+ * @pdev: PCI device information struct
+ *
+ * Return true if an adapter needs ioport resources
+ **/
+static int e1000_is_need_ioport(struct pci_dev *pdev)
+{
+ switch (pdev->device) {
+ case E1000_DEV_ID_82540EM:
+ case E1000_DEV_ID_82540EM_LOM:
+ case E1000_DEV_ID_82540EP:
+ case E1000_DEV_ID_82540EP_LOM:
+ case E1000_DEV_ID_82540EP_LP:
+ case E1000_DEV_ID_82541EI:
+ case E1000_DEV_ID_82541EI_MOBILE:
+ case E1000_DEV_ID_82541ER:
+ case E1000_DEV_ID_82541ER_LOM:
+ case E1000_DEV_ID_82541GI:
+ case E1000_DEV_ID_82541GI_LF:
+ case E1000_DEV_ID_82541GI_MOBILE:
+ case E1000_DEV_ID_82544EI_COPPER:
+ case E1000_DEV_ID_82544EI_FIBER:
+ case E1000_DEV_ID_82544GC_COPPER:
+ case E1000_DEV_ID_82544GC_LOM:
+ case E1000_DEV_ID_82545EM_COPPER:
+ case E1000_DEV_ID_82545EM_FIBER:
+ case E1000_DEV_ID_82546EB_COPPER:
+ case E1000_DEV_ID_82546EB_FIBER:
+ case E1000_DEV_ID_82546EB_QUAD_COPPER:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
* e1000_probe - Device Initialization Routine
* @pdev: PCI device information struct
* @ent: entry in e1000_pci_tbl
@@ -882,37 +905,51 @@ static void e1000_dump_eeprom(struct e1000_adapter *adapter)
* The OS initialization, configuring of the adapter private structure,
* and a hardware reset occur.
**/
-
-static int __devinit
-e1000_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int __devinit e1000_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct net_device *netdev;
struct e1000_adapter *adapter;
+ struct e1000_hw *hw;
static int cards_found = 0;
static int global_quad_port_a = 0; /* global ksp3 port a indication */
int i, err, pci_using_dac;
u16 eeprom_data = 0;
u16 eeprom_apme_mask = E1000_EEPROM_APME;
+ int bars, need_ioport;
DECLARE_MAC_BUF(mac);
- if ((err = pci_enable_device(pdev)))
+ /* do not allocate ioport bars when not needed */
+ need_ioport = e1000_is_need_ioport(pdev);
+ if (need_ioport) {
+ bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
+ err = pci_enable_device(pdev);
+ } else {
+ bars = pci_select_bars(pdev, IORESOURCE_MEM);
+ err = pci_enable_device(pdev);
+ }
+ if (err)
return err;
- if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) &&
- !(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) {
+ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK) &&
+ !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
pci_using_dac = 1;
} else {
- if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) &&
- (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) {
- E1000_ERR("No usable DMA configuration, aborting\n");
- goto err_dma;
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ E1000_ERR("No usable DMA configuration, "
+ "aborting\n");
+ goto err_dma;
+ }
}
pci_using_dac = 0;
}
- if ((err = pci_request_regions(pdev, e1000_driver_name)))
+ err = pci_request_selected_regions(pdev, bars, e1000_driver_name);
+ if (err)
goto err_pci_reg;
pci_set_master(pdev);
@@ -928,21 +965,27 @@ e1000_probe(struct pci_dev *pdev,
adapter = netdev_priv(netdev);
adapter->netdev = netdev;
adapter->pdev = pdev;
- adapter->hw.back = adapter;
adapter->msg_enable = (1 << debug) - 1;
+ adapter->bars = bars;
+ adapter->need_ioport = need_ioport;
+
+ hw = &adapter->hw;
+ hw->back = adapter;
err = -EIO;
- adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, BAR_0),
- pci_resource_len(pdev, BAR_0));
- if (!adapter->hw.hw_addr)
+ hw->hw_addr = ioremap(pci_resource_start(pdev, BAR_0),
+ pci_resource_len(pdev, BAR_0));
+ if (!hw->hw_addr)
goto err_ioremap;
- for (i = BAR_1; i <= BAR_5; i++) {
- if (pci_resource_len(pdev, i) == 0)
- continue;
- if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
- adapter->hw.io_base = pci_resource_start(pdev, i);
- break;
+ if (adapter->need_ioport) {
+ for (i = BAR_1; i <= BAR_5; i++) {
+ if (pci_resource_len(pdev, i) == 0)
+ continue;
+ if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+ hw->io_base = pci_resource_start(pdev, i);
+ break;
+ }
}
}
@@ -957,9 +1000,7 @@ e1000_probe(struct pci_dev *pdev,
e1000_set_ethtool_ops(netdev);
netdev->tx_timeout = &e1000_tx_timeout;
netdev->watchdog_timeo = 5 * HZ;
-#ifdef CONFIG_E1000_NAPI
netif_napi_add(netdev, &adapter->napi, e1000_clean, 64);
-#endif
netdev->vlan_rx_register = e1000_vlan_rx_register;
netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid;
netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid;
@@ -972,49 +1013,50 @@ e1000_probe(struct pci_dev *pdev,
/* setup the private structure */
- if ((err = e1000_sw_init(adapter)))
+ err = e1000_sw_init(adapter);
+ if (err)
goto err_sw_init;
err = -EIO;
/* Flash BAR mapping must happen after e1000_sw_init
* because it depends on mac_type */
- if ((adapter->hw.mac_type == e1000_ich8lan) &&
+ if ((hw->mac_type == e1000_ich8lan) &&
(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
- adapter->hw.flash_address =
+ hw->flash_address =
ioremap(pci_resource_start(pdev, 1),
pci_resource_len(pdev, 1));
- if (!adapter->hw.flash_address)
+ if (!hw->flash_address)
goto err_flashmap;
}
- if (e1000_check_phy_reset_block(&adapter->hw))
+ if (e1000_check_phy_reset_block(hw))
DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
- if (adapter->hw.mac_type >= e1000_82543) {
+ if (hw->mac_type >= e1000_82543) {
netdev->features = NETIF_F_SG |
NETIF_F_HW_CSUM |
NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER;
- if (adapter->hw.mac_type == e1000_ich8lan)
+ if (hw->mac_type == e1000_ich8lan)
netdev->features &= ~NETIF_F_HW_VLAN_FILTER;
}
- if ((adapter->hw.mac_type >= e1000_82544) &&
- (adapter->hw.mac_type != e1000_82547))
+ if ((hw->mac_type >= e1000_82544) &&
+ (hw->mac_type != e1000_82547))
netdev->features |= NETIF_F_TSO;
- if (adapter->hw.mac_type > e1000_82547_rev_2)
+ if (hw->mac_type > e1000_82547_rev_2)
netdev->features |= NETIF_F_TSO6;
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
netdev->features |= NETIF_F_LLTX;
- adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
+ adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw);
/* initialize eeprom parameters */
- if (e1000_init_eeprom_params(&adapter->hw)) {
+ if (e1000_init_eeprom_params(hw)) {
E1000_ERR("EEPROM initialization failed\n");
goto err_eeprom;
}
@@ -1022,10 +1064,10 @@ e1000_probe(struct pci_dev *pdev,
/* before reading the EEPROM, reset the controller to
* put the device in a known good starting state */
- e1000_reset_hw(&adapter->hw);
+ e1000_reset_hw(hw);
/* make sure the EEPROM is good */
- if (e1000_validate_eeprom_checksum(&adapter->hw) < 0) {
+ if (e1000_validate_eeprom_checksum(hw) < 0) {
DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n");
e1000_dump_eeprom(adapter);
/*
@@ -1036,24 +1078,24 @@ e1000_probe(struct pci_dev *pdev,
* interface after manually setting a hw addr using
* `ip set address`
*/
- memset(adapter->hw.mac_addr, 0, netdev->addr_len);
+ memset(hw->mac_addr, 0, netdev->addr_len);
} else {
/* copy the MAC address out of the EEPROM */
- if (e1000_read_mac_addr(&adapter->hw))
+ if (e1000_read_mac_addr(hw))
DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
}
/* don't block initalization here due to bad MAC address */
- memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
- memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
+ memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len);
+ memcpy(netdev->perm_addr, hw->mac_addr, netdev->addr_len);
if (!is_valid_ether_addr(netdev->perm_addr))
DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
- e1000_get_bus_info(&adapter->hw);
+ e1000_get_bus_info(hw);
init_timer(&adapter->tx_fifo_stall_timer);
adapter->tx_fifo_stall_timer.function = &e1000_82547_tx_fifo_stall;
- adapter->tx_fifo_stall_timer.data = (unsigned long) adapter;
+ adapter->tx_fifo_stall_timer.data = (unsigned long)adapter;
init_timer(&adapter->watchdog_timer);
adapter->watchdog_timer.function = &e1000_watchdog;
@@ -1061,7 +1103,7 @@ e1000_probe(struct pci_dev *pdev,
init_timer(&adapter->phy_info_timer);
adapter->phy_info_timer.function = &e1000_update_phy_info;
- adapter->phy_info_timer.data = (unsigned long) adapter;
+ adapter->phy_info_timer.data = (unsigned long)adapter;
INIT_WORK(&adapter->reset_task, e1000_reset_task);
@@ -1072,18 +1114,18 @@ e1000_probe(struct pci_dev *pdev,
* enable the ACPI Magic Packet filter
*/
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
case e1000_82543:
break;
case e1000_82544:
- e1000_read_eeprom(&adapter->hw,
+ e1000_read_eeprom(hw,
EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
eeprom_apme_mask = E1000_EEPROM_82544_APM;
break;
case e1000_ich8lan:
- e1000_read_eeprom(&adapter->hw,
+ e1000_read_eeprom(hw,
EEPROM_INIT_CONTROL1_REG, 1, &eeprom_data);
eeprom_apme_mask = E1000_EEPROM_ICH8_APME;
break;
@@ -1091,14 +1133,14 @@ e1000_probe(struct pci_dev *pdev,
case e1000_82546_rev_3:
case e1000_82571:
case e1000_80003es2lan:
- if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1){
- e1000_read_eeprom(&adapter->hw,
+ if (er32(STATUS) & E1000_STATUS_FUNC_1){
+ e1000_read_eeprom(hw,
EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
break;
}
/* Fall Through */
default:
- e1000_read_eeprom(&adapter->hw,
+ e1000_read_eeprom(hw,
EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
break;
}
@@ -1117,7 +1159,7 @@ e1000_probe(struct pci_dev *pdev,
case E1000_DEV_ID_82571EB_FIBER:
/* Wake events only supported on port A for dual fiber
* regardless of eeprom setting */
- if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
+ if (er32(STATUS) & E1000_STATUS_FUNC_1)
adapter->eeprom_wol = 0;
break;
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
@@ -1140,8 +1182,6 @@ e1000_probe(struct pci_dev *pdev,
adapter->wol = adapter->eeprom_wol;
/* print bus type/speed/width info */
- {
- struct e1000_hw *hw = &adapter->hw;
DPRINTK(PROBE, INFO, "(PCI%s:%s:%s) ",
((hw->bus_type == e1000_bus_type_pcix) ? "-X" :
(hw->bus_type == e1000_bus_type_pci_express ? " Express":"")),
@@ -1154,11 +1194,10 @@ e1000_probe(struct pci_dev *pdev,
(hw->bus_width == e1000_bus_width_pciex_4) ? "Width x4" :
(hw->bus_width == e1000_bus_width_pciex_1) ? "Width x1" :
"32-bit"));
- }
printk("%s\n", print_mac(mac, netdev->dev_addr));
- if (adapter->hw.bus_type == e1000_bus_type_pci_express) {
+ if (hw->bus_type == e1000_bus_type_pci_express) {
DPRINTK(PROBE, WARNING, "This device (id %04x:%04x) will no "
"longer be supported by this driver in the future.\n",
pdev->vendor, pdev->device);
@@ -1173,8 +1212,8 @@ e1000_probe(struct pci_dev *pdev,
* DRV_LOAD until the interface is up. For all other cases,
* let the f/w know that the h/w is now under the control
* of the driver. */
- if (adapter->hw.mac_type != e1000_82573 ||
- !e1000_check_mng_mode(&adapter->hw))
+ if (hw->mac_type != e1000_82573 ||
+ !e1000_check_mng_mode(hw))
e1000_get_hw_control(adapter);
/* tell the stack to leave us alone until e1000_open() is called */
@@ -1182,7 +1221,8 @@ e1000_probe(struct pci_dev *pdev,
netif_stop_queue(netdev);
strcpy(netdev->name, "eth%d");
- if ((err = register_netdev(netdev)))
+ err = register_netdev(netdev);
+ if (err)
goto err_register;
DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");
@@ -1193,28 +1233,24 @@ e1000_probe(struct pci_dev *pdev,
err_register:
e1000_release_hw_control(adapter);
err_eeprom:
- if (!e1000_check_phy_reset_block(&adapter->hw))
- e1000_phy_hw_reset(&adapter->hw);
+ if (!e1000_check_phy_reset_block(hw))
+ e1000_phy_hw_reset(hw);
- if (adapter->hw.flash_address)
- iounmap(adapter->hw.flash_address);
+ if (hw->flash_address)
+ iounmap(hw->flash_address);
err_flashmap:
-#ifdef CONFIG_E1000_NAPI
for (i = 0; i < adapter->num_rx_queues; i++)
dev_put(&adapter->polling_netdev[i]);
-#endif
kfree(adapter->tx_ring);
kfree(adapter->rx_ring);
-#ifdef CONFIG_E1000_NAPI
kfree(adapter->polling_netdev);
-#endif
err_sw_init:
- iounmap(adapter->hw.hw_addr);
+ iounmap(hw->hw_addr);
err_ioremap:
free_netdev(netdev);
err_alloc_etherdev:
- pci_release_regions(pdev);
+ pci_release_selected_regions(pdev, bars);
err_pci_reg:
err_dma:
pci_disable_device(pdev);
@@ -1231,14 +1267,12 @@ err_dma:
* memory.
**/
-static void __devexit
-e1000_remove(struct pci_dev *pdev)
+static void __devexit e1000_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
-#ifdef CONFIG_E1000_NAPI
+ struct e1000_hw *hw = &adapter->hw;
int i;
-#endif
cancel_work_sync(&adapter->reset_task);
@@ -1248,26 +1282,22 @@ e1000_remove(struct pci_dev *pdev)
* would have already happened in close and is redundant. */
e1000_release_hw_control(adapter);
-#ifdef CONFIG_E1000_NAPI
for (i = 0; i < adapter->num_rx_queues; i++)
dev_put(&adapter->polling_netdev[i]);
-#endif
unregister_netdev(netdev);
- if (!e1000_check_phy_reset_block(&adapter->hw))
- e1000_phy_hw_reset(&adapter->hw);
+ if (!e1000_check_phy_reset_block(hw))
+ e1000_phy_hw_reset(hw);
kfree(adapter->tx_ring);
kfree(adapter->rx_ring);
-#ifdef CONFIG_E1000_NAPI
kfree(adapter->polling_netdev);
-#endif
- iounmap(adapter->hw.hw_addr);
- if (adapter->hw.flash_address)
- iounmap(adapter->hw.flash_address);
- pci_release_regions(pdev);
+ iounmap(hw->hw_addr);
+ if (hw->flash_address)
+ iounmap(hw->flash_address);
+ pci_release_selected_regions(pdev, adapter->bars);
free_netdev(netdev);
@@ -1283,15 +1313,12 @@ e1000_remove(struct pci_dev *pdev)
* OS network device settings (MTU size).
**/
-static int __devinit
-e1000_sw_init(struct e1000_adapter *adapter)
+static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
-#ifdef CONFIG_E1000_NAPI
int i;
-#endif
/* PCI config space info */
@@ -1349,14 +1376,12 @@ e1000_sw_init(struct e1000_adapter *adapter)
return -ENOMEM;
}
-#ifdef CONFIG_E1000_NAPI
for (i = 0; i < adapter->num_rx_queues; i++) {
adapter->polling_netdev[i].priv = adapter;
dev_hold(&adapter->polling_netdev[i]);
set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state);
}
spin_lock_init(&adapter->tx_queue_lock);
-#endif
/* Explicitly disable IRQ since the NIC can be in any state. */
e1000_irq_disable(adapter);
@@ -1377,8 +1402,7 @@ e1000_sw_init(struct e1000_adapter *adapter)
* intended for Multiqueue, but should work fine with a single queue.
**/
-static int __devinit
-e1000_alloc_queues(struct e1000_adapter *adapter)
+static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
{
adapter->tx_ring = kcalloc(adapter->num_tx_queues,
sizeof(struct e1000_tx_ring), GFP_KERNEL);
@@ -1392,7 +1416,6 @@ e1000_alloc_queues(struct e1000_adapter *adapter)
return -ENOMEM;
}
-#ifdef CONFIG_E1000_NAPI
adapter->polling_netdev = kcalloc(adapter->num_rx_queues,
sizeof(struct net_device),
GFP_KERNEL);
@@ -1401,7 +1424,6 @@ e1000_alloc_queues(struct e1000_adapter *adapter)
kfree(adapter->rx_ring);
return -ENOMEM;
}
-#endif
return E1000_SUCCESS;
}
@@ -1419,10 +1441,10 @@ e1000_alloc_queues(struct e1000_adapter *adapter)
* and the stack is notified that the interface is ready.
**/
-static int
-e1000_open(struct net_device *netdev)
+static int e1000_open(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
int err;
/* disallow open during test */
@@ -1442,15 +1464,15 @@ e1000_open(struct net_device *netdev)
e1000_power_up_phy(adapter);
adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
- if ((adapter->hw.mng_cookie.status &
+ if ((hw->mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
e1000_update_mng_vlan(adapter);
}
/* If AMT is enabled, let the firmware know that the network
* interface is now open */
- if (adapter->hw.mac_type == e1000_82573 &&
- e1000_check_mng_mode(&adapter->hw))
+ if (hw->mac_type == e1000_82573 &&
+ e1000_check_mng_mode(hw))
e1000_get_hw_control(adapter);
/* before we allocate an interrupt, we must be ready to handle it.
@@ -1466,16 +1488,14 @@ e1000_open(struct net_device *netdev)
/* From here on the code is the same as e1000_up() */
clear_bit(__E1000_DOWN, &adapter->flags);
-#ifdef CONFIG_E1000_NAPI
napi_enable(&adapter->napi);
-#endif
e1000_irq_enable(adapter);
netif_start_queue(netdev);
/* fire a link status change interrupt to start the watchdog */
- E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_LSC);
+ ew32(ICS, E1000_ICS_LSC);
return E1000_SUCCESS;
@@ -1503,10 +1523,10 @@ err_setup_tx:
* hardware, and all transmit and receive resources are freed.
**/
-static int
-e1000_close(struct net_device *netdev)
+static int e1000_close(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
e1000_down(adapter);
@@ -1518,7 +1538,7 @@ e1000_close(struct net_device *netdev)
/* kill manageability vlan ID if supported, but not if a vlan with
* the same ID is registered on the host OS (let 8021q kill it) */
- if ((adapter->hw.mng_cookie.status &
+ if ((hw->mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
!(adapter->vlgrp &&
vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) {
@@ -1527,8 +1547,8 @@ e1000_close(struct net_device *netdev)
/* If AMT is enabled, let the firmware know that the network
* interface is now closed */
- if (adapter->hw.mac_type == e1000_82573 &&
- e1000_check_mng_mode(&adapter->hw))
+ if (hw->mac_type == e1000_82573 &&
+ e1000_check_mng_mode(hw))
e1000_release_hw_control(adapter);
return 0;
@@ -1540,17 +1560,17 @@ e1000_close(struct net_device *netdev)
* @start: address of beginning of memory
* @len: length of memory
**/
-static bool
-e1000_check_64k_bound(struct e1000_adapter *adapter,
- void *start, unsigned long len)
+static bool e1000_check_64k_bound(struct e1000_adapter *adapter, void *start,
+ unsigned long len)
{
- unsigned long begin = (unsigned long) start;
+ struct e1000_hw *hw = &adapter->hw;
+ unsigned long begin = (unsigned long)start;
unsigned long end = begin + len;
/* First rev 82545 and 82546 need to not allow any memory
* write location to cross 64k boundary due to errata 23 */
- if (adapter->hw.mac_type == e1000_82545 ||
- adapter->hw.mac_type == e1000_82546) {
+ if (hw->mac_type == e1000_82545 ||
+ hw->mac_type == e1000_82546) {
return ((begin ^ (end - 1)) >> 16) != 0 ? false : true;
}
@@ -1565,9 +1585,8 @@ e1000_check_64k_bound(struct e1000_adapter *adapter,
* Return 0 on success, negative on failure
**/
-static int
-e1000_setup_tx_resources(struct e1000_adapter *adapter,
- struct e1000_tx_ring *txdr)
+static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *txdr)
{
struct pci_dev *pdev = adapter->pdev;
int size;
@@ -1641,8 +1660,7 @@ setup_tx_desc_die:
* Return 0 on success, negative on failure
**/
-int
-e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
+int e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
{
int i, err = 0;
@@ -1668,8 +1686,7 @@ e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
* Configure the Tx unit of the MAC after a reset.
**/
-static void
-e1000_configure_tx(struct e1000_adapter *adapter)
+static void e1000_configure_tx(struct e1000_adapter *adapter)
{
u64 tdba;
struct e1000_hw *hw = &adapter->hw;
@@ -1684,18 +1701,18 @@ e1000_configure_tx(struct e1000_adapter *adapter)
tdba = adapter->tx_ring[0].dma;
tdlen = adapter->tx_ring[0].count *
sizeof(struct e1000_tx_desc);
- E1000_WRITE_REG(hw, TDLEN, tdlen);
- E1000_WRITE_REG(hw, TDBAH, (tdba >> 32));
- E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
- E1000_WRITE_REG(hw, TDT, 0);
- E1000_WRITE_REG(hw, TDH, 0);
+ ew32(TDLEN, tdlen);
+ ew32(TDBAH, (tdba >> 32));
+ ew32(TDBAL, (tdba & 0x00000000ffffffffULL));
+ ew32(TDT, 0);
+ ew32(TDH, 0);
adapter->tx_ring[0].tdh = ((hw->mac_type >= e1000_82543) ? E1000_TDH : E1000_82542_TDH);
adapter->tx_ring[0].tdt = ((hw->mac_type >= e1000_82543) ? E1000_TDT : E1000_82542_TDT);
break;
}
/* Set the default values for the Tx Inter Packet Gap timer */
- if (adapter->hw.mac_type <= e1000_82547_rev_2 &&
+ if (hw->mac_type <= e1000_82547_rev_2 &&
(hw->media_type == e1000_media_type_fiber ||
hw->media_type == e1000_media_type_internal_serdes))
tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
@@ -1720,34 +1737,34 @@ e1000_configure_tx(struct e1000_adapter *adapter)
}
tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT;
tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT;
- E1000_WRITE_REG(hw, TIPG, tipg);
+ ew32(TIPG, tipg);
/* Set the Tx Interrupt Delay register */
- E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay);
+ ew32(TIDV, adapter->tx_int_delay);
if (hw->mac_type >= e1000_82540)
- E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay);
+ ew32(TADV, adapter->tx_abs_int_delay);
/* Program the Transmit Control Register */
- tctl = E1000_READ_REG(hw, TCTL);
+ tctl = er32(TCTL);
tctl &= ~E1000_TCTL_CT;
tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572) {
- tarc = E1000_READ_REG(hw, TARC0);
+ tarc = er32(TARC0);
/* set the speed mode bit, we'll clear it if we're not at
* gigabit link later */
tarc |= (1 << 21);
- E1000_WRITE_REG(hw, TARC0, tarc);
+ ew32(TARC0, tarc);
} else if (hw->mac_type == e1000_80003es2lan) {
- tarc = E1000_READ_REG(hw, TARC0);
+ tarc = er32(TARC0);
tarc |= 1;
- E1000_WRITE_REG(hw, TARC0, tarc);
- tarc = E1000_READ_REG(hw, TARC1);
+ ew32(TARC0, tarc);
+ tarc = er32(TARC1);
tarc |= 1;
- E1000_WRITE_REG(hw, TARC1, tarc);
+ ew32(TARC1, tarc);
}
e1000_config_collision_dist(hw);
@@ -1770,7 +1787,7 @@ e1000_configure_tx(struct e1000_adapter *adapter)
hw->bus_type == e1000_bus_type_pcix)
adapter->pcix_82544 = 1;
- E1000_WRITE_REG(hw, TCTL, tctl);
+ ew32(TCTL, tctl);
}
@@ -1782,10 +1799,10 @@ e1000_configure_tx(struct e1000_adapter *adapter)
* Returns 0 on success, negative on failure
**/
-static int
-e1000_setup_rx_resources(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rxdr)
+static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rxdr)
{
+ struct e1000_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
int size, desc_len;
@@ -1818,7 +1835,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter,
return -ENOMEM;
}
- if (adapter->hw.mac_type <= e1000_82547_rev_2)
+ if (hw->mac_type <= e1000_82547_rev_2)
desc_len = sizeof(struct e1000_rx_desc);
else
desc_len = sizeof(union e1000_rx_desc_packet_split);
@@ -1887,8 +1904,7 @@ setup_rx_desc_die:
* Return 0 on success, negative on failure
**/
-int
-e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
+int e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
{
int i, err = 0;
@@ -1913,24 +1929,24 @@ e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
**/
#define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \
(((S) & (PAGE_SIZE - 1)) ? 1 : 0))
-static void
-e1000_setup_rctl(struct e1000_adapter *adapter)
+static void e1000_setup_rctl(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
u32 rctl, rfctl;
u32 psrctl = 0;
#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
u32 pages = 0;
#endif
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl = er32(RCTL);
rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
rctl |= E1000_RCTL_EN | E1000_RCTL_BAM |
E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
- (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
+ (hw->mc_filter_type << E1000_RCTL_MO_SHIFT);
- if (adapter->hw.tbi_compatibility_on == 1)
+ if (hw->tbi_compatibility_on == 1)
rctl |= E1000_RCTL_SBP;
else
rctl &= ~E1000_RCTL_SBP;
@@ -1983,7 +1999,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
/* allocations using alloc_page take too long for regular MTU
* so only enable packet split for jumbo frames */
pages = PAGE_USE_COUNT(adapter->netdev->mtu);
- if ((adapter->hw.mac_type >= e1000_82571) && (pages <= 3) &&
+ if ((hw->mac_type >= e1000_82571) && (pages <= 3) &&
PAGE_SIZE <= 16384 && (rctl & E1000_RCTL_LPE))
adapter->rx_ps_pages = pages;
else
@@ -1991,14 +2007,14 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
#endif
if (adapter->rx_ps_pages) {
/* Configure extra packet-split registers */
- rfctl = E1000_READ_REG(&adapter->hw, RFCTL);
+ rfctl = er32(RFCTL);
rfctl |= E1000_RFCTL_EXTEN;
/* disable packet split support for IPv6 extension headers,
* because some malformed IPv6 headers can hang the RX */
rfctl |= (E1000_RFCTL_IPV6_EX_DIS |
E1000_RFCTL_NEW_IPV6_EXT_DIS);
- E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl);
+ ew32(RFCTL, rfctl);
rctl |= E1000_RCTL_DTYP_PS;
@@ -2018,10 +2034,10 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
break;
}
- E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl);
+ ew32(PSRCTL, psrctl);
}
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ ew32(RCTL, rctl);
}
/**
@@ -2031,8 +2047,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
* Configure the Rx unit of the MAC after a reset.
**/
-static void
-e1000_configure_rx(struct e1000_adapter *adapter)
+static void e1000_configure_rx(struct e1000_adapter *adapter)
{
u64 rdba;
struct e1000_hw *hw = &adapter->hw;
@@ -2052,30 +2067,27 @@ e1000_configure_rx(struct e1000_adapter *adapter)
}
/* disable receives while setting up the descriptors */
- rctl = E1000_READ_REG(hw, RCTL);
- E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
+ rctl = er32(RCTL);
+ ew32(RCTL, rctl & ~E1000_RCTL_EN);
/* set the Receive Delay Timer Register */
- E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay);
+ ew32(RDTR, adapter->rx_int_delay);
if (hw->mac_type >= e1000_82540) {
- E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay);
+ ew32(RADV, adapter->rx_abs_int_delay);
if (adapter->itr_setting != 0)
- E1000_WRITE_REG(hw, ITR,
- 1000000000 / (adapter->itr * 256));
+ ew32(ITR, 1000000000 / (adapter->itr * 256));
}
if (hw->mac_type >= e1000_82571) {
- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext = er32(CTRL_EXT);
/* Reset delay timers after every interrupt */
ctrl_ext |= E1000_CTRL_EXT_INT_TIMER_CLR;
-#ifdef CONFIG_E1000_NAPI
/* Auto-Mask interrupts upon ICR access */
ctrl_ext |= E1000_CTRL_EXT_IAME;
- E1000_WRITE_REG(hw, IAM, 0xffffffff);
-#endif
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH(hw);
+ ew32(IAM, 0xffffffff);
+ ew32(CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH();
}
/* Setup the HW Rx Head and Tail Descriptor Pointers and
@@ -2084,11 +2096,11 @@ e1000_configure_rx(struct e1000_adapter *adapter)
case 1:
default:
rdba = adapter->rx_ring[0].dma;
- E1000_WRITE_REG(hw, RDLEN, rdlen);
- E1000_WRITE_REG(hw, RDBAH, (rdba >> 32));
- E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
- E1000_WRITE_REG(hw, RDT, 0);
- E1000_WRITE_REG(hw, RDH, 0);
+ ew32(RDLEN, rdlen);
+ ew32(RDBAH, (rdba >> 32));
+ ew32(RDBAL, (rdba & 0x00000000ffffffffULL));
+ ew32(RDT, 0);
+ ew32(RDH, 0);
adapter->rx_ring[0].rdh = ((hw->mac_type >= e1000_82543) ? E1000_RDH : E1000_82542_RDH);
adapter->rx_ring[0].rdt = ((hw->mac_type >= e1000_82543) ? E1000_RDT : E1000_82542_RDT);
break;
@@ -2096,7 +2108,7 @@ e1000_configure_rx(struct e1000_adapter *adapter)
/* Enable 82543 Receive Checksum Offload for TCP and UDP */
if (hw->mac_type >= e1000_82543) {
- rxcsum = E1000_READ_REG(hw, RXCSUM);
+ rxcsum = er32(RXCSUM);
if (adapter->rx_csum) {
rxcsum |= E1000_RXCSUM_TUOFL;
@@ -2110,17 +2122,17 @@ e1000_configure_rx(struct e1000_adapter *adapter)
rxcsum &= ~E1000_RXCSUM_TUOFL;
/* don't need to clear IPPCSE as it defaults to 0 */
}
- E1000_WRITE_REG(hw, RXCSUM, rxcsum);
+ ew32(RXCSUM, rxcsum);
}
/* enable early receives on 82573, only takes effect if using > 2048
* byte total frame size. for example only for jumbo frames */
#define E1000_ERT_2048 0x100
if (hw->mac_type == e1000_82573)
- E1000_WRITE_REG(hw, ERT, E1000_ERT_2048);
+ ew32(ERT, E1000_ERT_2048);
/* Enable Receives */
- E1000_WRITE_REG(hw, RCTL, rctl);
+ ew32(RCTL, rctl);
}
/**
@@ -2131,9 +2143,8 @@ e1000_configure_rx(struct e1000_adapter *adapter)
* Free all transmit software resources
**/
-static void
-e1000_free_tx_resources(struct e1000_adapter *adapter,
- struct e1000_tx_ring *tx_ring)
+static void e1000_free_tx_resources(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring)
{
struct pci_dev *pdev = adapter->pdev;
@@ -2154,8 +2165,7 @@ e1000_free_tx_resources(struct e1000_adapter *adapter,
* Free all transmit software resources
**/
-void
-e1000_free_all_tx_resources(struct e1000_adapter *adapter)
+void e1000_free_all_tx_resources(struct e1000_adapter *adapter)
{
int i;
@@ -2163,9 +2173,8 @@ e1000_free_all_tx_resources(struct e1000_adapter *adapter)
e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
}
-static void
-e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
- struct e1000_buffer *buffer_info)
+static void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
+ struct e1000_buffer *buffer_info)
{
if (buffer_info->dma) {
pci_unmap_page(adapter->pdev,
@@ -2187,10 +2196,10 @@ e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
* @tx_ring: ring to be cleaned
**/
-static void
-e1000_clean_tx_ring(struct e1000_adapter *adapter,
- struct e1000_tx_ring *tx_ring)
+static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring)
{
+ struct e1000_hw *hw = &adapter->hw;
struct e1000_buffer *buffer_info;
unsigned long size;
unsigned int i;
@@ -2213,8 +2222,8 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter,
tx_ring->next_to_clean = 0;
tx_ring->last_tx_tso = 0;
- writel(0, adapter->hw.hw_addr + tx_ring->tdh);
- writel(0, adapter->hw.hw_addr + tx_ring->tdt);
+ writel(0, hw->hw_addr + tx_ring->tdh);
+ writel(0, hw->hw_addr + tx_ring->tdt);
}
/**
@@ -2222,8 +2231,7 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter,
* @adapter: board private structure
**/
-static void
-e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
+static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
{
int i;
@@ -2239,9 +2247,8 @@ e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
* Free all receive software resources
**/
-static void
-e1000_free_rx_resources(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
+static void e1000_free_rx_resources(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring)
{
struct pci_dev *pdev = adapter->pdev;
@@ -2266,8 +2273,7 @@ e1000_free_rx_resources(struct e1000_adapter *adapter,
* Free all receive software resources
**/
-void
-e1000_free_all_rx_resources(struct e1000_adapter *adapter)
+void e1000_free_all_rx_resources(struct e1000_adapter *adapter)
{
int i;
@@ -2281,10 +2287,10 @@ e1000_free_all_rx_resources(struct e1000_adapter *adapter)
* @rx_ring: ring to free buffers from
**/
-static void
-e1000_clean_rx_ring(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
+static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring)
{
+ struct e1000_hw *hw = &adapter->hw;
struct e1000_buffer *buffer_info;
struct e1000_ps_page *ps_page;
struct e1000_ps_page_dma *ps_page_dma;
@@ -2331,8 +2337,8 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter,
rx_ring->next_to_clean = 0;
rx_ring->next_to_use = 0;
- writel(0, adapter->hw.hw_addr + rx_ring->rdh);
- writel(0, adapter->hw.hw_addr + rx_ring->rdt);
+ writel(0, hw->hw_addr + rx_ring->rdh);
+ writel(0, hw->hw_addr + rx_ring->rdt);
}
/**
@@ -2340,8 +2346,7 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter,
* @adapter: board private structure
**/
-static void
-e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
+static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
{
int i;
@@ -2352,38 +2357,38 @@ e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
/* The 82542 2.0 (revision 2) needs to have the receive unit in reset
* and memory write and invalidate disabled for certain operations
*/
-static void
-e1000_enter_82542_rst(struct e1000_adapter *adapter)
+static void e1000_enter_82542_rst(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
u32 rctl;
- e1000_pci_clear_mwi(&adapter->hw);
+ e1000_pci_clear_mwi(hw);
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl = er32(RCTL);
rctl |= E1000_RCTL_RST;
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
- E1000_WRITE_FLUSH(&adapter->hw);
+ ew32(RCTL, rctl);
+ E1000_WRITE_FLUSH();
mdelay(5);
if (netif_running(netdev))
e1000_clean_all_rx_rings(adapter);
}
-static void
-e1000_leave_82542_rst(struct e1000_adapter *adapter)
+static void e1000_leave_82542_rst(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
u32 rctl;
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl = er32(RCTL);
rctl &= ~E1000_RCTL_RST;
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
- E1000_WRITE_FLUSH(&adapter->hw);
+ ew32(RCTL, rctl);
+ E1000_WRITE_FLUSH();
mdelay(5);
- if (adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE)
- e1000_pci_set_mwi(&adapter->hw);
+ if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
+ e1000_pci_set_mwi(hw);
if (netif_running(netdev)) {
/* No need to loop, because 82542 supports only 1 queue */
@@ -2401,10 +2406,10 @@ e1000_leave_82542_rst(struct e1000_adapter *adapter)
* Returns 0 on success, negative on failure
**/
-static int
-e1000_set_mac(struct net_device *netdev, void *p)
+static int e1000_set_mac(struct net_device *netdev, void *p)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
@@ -2412,19 +2417,19 @@ e1000_set_mac(struct net_device *netdev, void *p)
/* 82542 2.0 needs to be in reset to write receive address registers */
- if (adapter->hw.mac_type == e1000_82542_rev2_0)
+ if (hw->mac_type == e1000_82542_rev2_0)
e1000_enter_82542_rst(adapter);
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
- memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+ memcpy(hw->mac_addr, addr->sa_data, netdev->addr_len);
- e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
+ e1000_rar_set(hw, hw->mac_addr, 0);
/* With 82571 controllers, LAA may be overwritten (with the default)
* due to controller reset from the other port. */
- if (adapter->hw.mac_type == e1000_82571) {
+ if (hw->mac_type == e1000_82571) {
/* activate the work around */
- adapter->hw.laa_is_present = 1;
+ hw->laa_is_present = 1;
/* Hold a copy of the LAA in RAR[14] This is done so that
* between the time RAR[0] gets clobbered and the time it
@@ -2432,11 +2437,11 @@ e1000_set_mac(struct net_device *netdev, void *p)
* of the RARs and no incoming packets directed to this port
* are dropped. Eventaully the LAA will be in RAR[0] and
* RAR[14] */
- e1000_rar_set(&adapter->hw, adapter->hw.mac_addr,
+ e1000_rar_set(hw, hw->mac_addr,
E1000_RAR_ENTRIES - 1);
}
- if (adapter->hw.mac_type == e1000_82542_rev2_0)
+ if (hw->mac_type == e1000_82542_rev2_0)
e1000_leave_82542_rst(adapter);
return 0;
@@ -2452,8 +2457,7 @@ e1000_set_mac(struct net_device *netdev, void *p)
* promiscuous mode, and all-multi behavior.
**/
-static void
-e1000_set_rx_mode(struct net_device *netdev)
+static void e1000_set_rx_mode(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -2466,16 +2470,16 @@ e1000_set_rx_mode(struct net_device *netdev)
E1000_NUM_MTA_REGISTERS_ICH8LAN :
E1000_NUM_MTA_REGISTERS;
- if (adapter->hw.mac_type == e1000_ich8lan)
+ if (hw->mac_type == e1000_ich8lan)
rar_entries = E1000_RAR_ENTRIES_ICH8LAN;
/* reserve RAR[14] for LAA over-write work-around */
- if (adapter->hw.mac_type == e1000_82571)
+ if (hw->mac_type == e1000_82571)
rar_entries--;
/* Check for Promiscuous and All Multicast modes */
- rctl = E1000_READ_REG(hw, RCTL);
+ rctl = er32(RCTL);
if (netdev->flags & IFF_PROMISC) {
rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
@@ -2498,7 +2502,7 @@ e1000_set_rx_mode(struct net_device *netdev)
uc_ptr = netdev->uc_list;
}
- E1000_WRITE_REG(hw, RCTL, rctl);
+ ew32(RCTL, rctl);
/* 82542 2.0 needs to be in reset to write receive address registers */
@@ -2524,9 +2528,9 @@ e1000_set_rx_mode(struct net_device *netdev)
mc_ptr = mc_ptr->next;
} else {
E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
}
}
WARN_ON(uc_ptr != NULL);
@@ -2535,7 +2539,7 @@ e1000_set_rx_mode(struct net_device *netdev)
for (i = 0; i < mta_reg_count; i++) {
E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
}
/* load any remaining addresses into the hash table */
@@ -2552,11 +2556,11 @@ e1000_set_rx_mode(struct net_device *netdev)
/* Need to wait a few seconds after link up to get diagnostic information from
* the phy */
-static void
-e1000_update_phy_info(unsigned long data)
+static void e1000_update_phy_info(unsigned long data)
{
- struct e1000_adapter *adapter = (struct e1000_adapter *) data;
- e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
+ struct e1000_adapter *adapter = (struct e1000_adapter *)data;
+ struct e1000_hw *hw = &adapter->hw;
+ e1000_phy_get_info(hw, &adapter->phy_info);
}
/**
@@ -2564,33 +2568,25 @@ e1000_update_phy_info(unsigned long data)
* @data: pointer to adapter cast into an unsigned long
**/
-static void
-e1000_82547_tx_fifo_stall(unsigned long data)
+static void e1000_82547_tx_fifo_stall(unsigned long data)
{
- struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+ struct e1000_adapter *adapter = (struct e1000_adapter *)data;
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
u32 tctl;
if (atomic_read(&adapter->tx_fifo_stall)) {
- if ((E1000_READ_REG(&adapter->hw, TDT) ==
- E1000_READ_REG(&adapter->hw, TDH)) &&
- (E1000_READ_REG(&adapter->hw, TDFT) ==
- E1000_READ_REG(&adapter->hw, TDFH)) &&
- (E1000_READ_REG(&adapter->hw, TDFTS) ==
- E1000_READ_REG(&adapter->hw, TDFHS))) {
- tctl = E1000_READ_REG(&adapter->hw, TCTL);
- E1000_WRITE_REG(&adapter->hw, TCTL,
- tctl & ~E1000_TCTL_EN);
- E1000_WRITE_REG(&adapter->hw, TDFT,
- adapter->tx_head_addr);
- E1000_WRITE_REG(&adapter->hw, TDFH,
- adapter->tx_head_addr);
- E1000_WRITE_REG(&adapter->hw, TDFTS,
- adapter->tx_head_addr);
- E1000_WRITE_REG(&adapter->hw, TDFHS,
- adapter->tx_head_addr);
- E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
- E1000_WRITE_FLUSH(&adapter->hw);
+ if ((er32(TDT) == er32(TDH)) &&
+ (er32(TDFT) == er32(TDFH)) &&
+ (er32(TDFTS) == er32(TDFHS))) {
+ tctl = er32(TCTL);
+ ew32(TCTL, tctl & ~E1000_TCTL_EN);
+ ew32(TDFT, adapter->tx_head_addr);
+ ew32(TDFH, adapter->tx_head_addr);
+ ew32(TDFTS, adapter->tx_head_addr);
+ ew32(TDFHS, adapter->tx_head_addr);
+ ew32(TCTL, tctl);
+ E1000_WRITE_FLUSH();
adapter->tx_fifo_head = 0;
atomic_set(&adapter->tx_fifo_stall, 0);
@@ -2605,45 +2601,45 @@ e1000_82547_tx_fifo_stall(unsigned long data)
* e1000_watchdog - Timer Call-back
* @data: pointer to adapter cast into an unsigned long
**/
-static void
-e1000_watchdog(unsigned long data)
+static void e1000_watchdog(unsigned long data)
{
- struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+ struct e1000_adapter *adapter = (struct e1000_adapter *)data;
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct e1000_tx_ring *txdr = adapter->tx_ring;
u32 link, tctl;
s32 ret_val;
- ret_val = e1000_check_for_link(&adapter->hw);
+ ret_val = e1000_check_for_link(hw);
if ((ret_val == E1000_ERR_PHY) &&
- (adapter->hw.phy_type == e1000_phy_igp_3) &&
- (E1000_READ_REG(&adapter->hw, CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) {
+ (hw->phy_type == e1000_phy_igp_3) &&
+ (er32(CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) {
/* See e1000_kumeran_lock_loss_workaround() */
DPRINTK(LINK, INFO,
"Gigabit has been disabled, downgrading speed\n");
}
- if (adapter->hw.mac_type == e1000_82573) {
- e1000_enable_tx_pkt_filtering(&adapter->hw);
- if (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)
+ if (hw->mac_type == e1000_82573) {
+ e1000_enable_tx_pkt_filtering(hw);
+ if (adapter->mng_vlan_id != hw->mng_cookie.vlan_id)
e1000_update_mng_vlan(adapter);
}
- if ((adapter->hw.media_type == e1000_media_type_internal_serdes) &&
- !(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE))
- link = !adapter->hw.serdes_link_down;
+ if ((hw->media_type == e1000_media_type_internal_serdes) &&
+ !(er32(TXCW) & E1000_TXCW_ANE))
+ link = !hw->serdes_link_down;
else
- link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU;
+ link = er32(STATUS) & E1000_STATUS_LU;
if (link) {
if (!netif_carrier_ok(netdev)) {
u32 ctrl;
bool txb2b = true;
- e1000_get_speed_and_duplex(&adapter->hw,
+ e1000_get_speed_and_duplex(hw,
&adapter->link_speed,
&adapter->link_duplex);
- ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+ ctrl = er32(CTRL);
DPRINTK(LINK, INFO, "NIC Link is Up %d Mbps %s, "
"Flow Control: %s\n",
adapter->link_speed,
@@ -2671,19 +2667,19 @@ e1000_watchdog(unsigned long data)
break;
}
- if ((adapter->hw.mac_type == e1000_82571 ||
- adapter->hw.mac_type == e1000_82572) &&
+ if ((hw->mac_type == e1000_82571 ||
+ hw->mac_type == e1000_82572) &&
!txb2b) {
u32 tarc0;
- tarc0 = E1000_READ_REG(&adapter->hw, TARC0);
+ tarc0 = er32(TARC0);
tarc0 &= ~(1 << 21);
- E1000_WRITE_REG(&adapter->hw, TARC0, tarc0);
+ ew32(TARC0, tarc0);
}
/* disable TSO for pcie and 10/100 speeds, to avoid
* some hardware issues */
if (!adapter->tso_force &&
- adapter->hw.bus_type == e1000_bus_type_pci_express){
+ hw->bus_type == e1000_bus_type_pci_express){
switch (adapter->link_speed) {
case SPEED_10:
case SPEED_100:
@@ -2704,9 +2700,9 @@ e1000_watchdog(unsigned long data)
/* enable transmits in the hardware, need to do this
* after setting TARC0 */
- tctl = E1000_READ_REG(&adapter->hw, TCTL);
+ tctl = er32(TCTL);
tctl |= E1000_TCTL_EN;
- E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
+ ew32(TCTL, tctl);
netif_carrier_on(netdev);
netif_wake_queue(netdev);
@@ -2714,10 +2710,9 @@ e1000_watchdog(unsigned long data)
adapter->smartspeed = 0;
} else {
/* make sure the receive unit is started */
- if (adapter->hw.rx_needs_kicking) {
- struct e1000_hw *hw = &adapter->hw;
- u32 rctl = E1000_READ_REG(hw, RCTL);
- E1000_WRITE_REG(hw, RCTL, rctl | E1000_RCTL_EN);
+ if (hw->rx_needs_kicking) {
+ u32 rctl = er32(RCTL);
+ ew32(RCTL, rctl | E1000_RCTL_EN);
}
}
} else {
@@ -2734,7 +2729,7 @@ e1000_watchdog(unsigned long data)
* disable receives in the ISR and
* reset device here in the watchdog
*/
- if (adapter->hw.mac_type == e1000_80003es2lan)
+ if (hw->mac_type == e1000_80003es2lan)
/* reset device */
schedule_work(&adapter->reset_task);
}
@@ -2744,9 +2739,9 @@ e1000_watchdog(unsigned long data)
e1000_update_stats(adapter);
- adapter->hw.tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
+ hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
adapter->tpt_old = adapter->stats.tpt;
- adapter->hw.collision_delta = adapter->stats.colc - adapter->colc_old;
+ hw->collision_delta = adapter->stats.colc - adapter->colc_old;
adapter->colc_old = adapter->stats.colc;
adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
@@ -2754,7 +2749,7 @@ e1000_watchdog(unsigned long data)
adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
adapter->gotcl_old = adapter->stats.gotcl;
- e1000_update_adaptive(&adapter->hw);
+ e1000_update_adaptive(hw);
if (!netif_carrier_ok(netdev)) {
if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
@@ -2768,15 +2763,15 @@ e1000_watchdog(unsigned long data)
}
/* Cause software interrupt to ensure rx ring is cleaned */
- E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
+ ew32(ICS, E1000_ICS_RXDMT0);
/* Force detection of hung controller every watchdog period */
adapter->detect_tx_hung = true;
/* With 82571 controllers, LAA may be overwritten due to controller
* reset from the other port. Set the appropriate LAA in RAR[0] */
- if (adapter->hw.mac_type == e1000_82571 && adapter->hw.laa_is_present)
- e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
+ if (hw->mac_type == e1000_82571 && hw->laa_is_present)
+ e1000_rar_set(hw, hw->mac_addr, 0);
/* Reset the timer */
mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * HZ));
@@ -2806,9 +2801,7 @@ enum latency_range {
* @bytes: the number of bytes during this measurement interval
**/
static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
- u16 itr_setting,
- int packets,
- int bytes)
+ u16 itr_setting, int packets, int bytes)
{
unsigned int retval = itr_setting;
struct e1000_hw *hw = &adapter->hw;
@@ -2913,7 +2906,7 @@ set_itr_now:
min(adapter->itr + (new_itr >> 2), new_itr) :
new_itr;
adapter->itr = new_itr;
- E1000_WRITE_REG(hw, ITR, 1000000000 / (new_itr * 256));
+ ew32(ITR, 1000000000 / (new_itr * 256));
}
return;
@@ -2926,9 +2919,8 @@ set_itr_now:
#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000
#define E1000_TX_FLAGS_VLAN_SHIFT 16
-static int
-e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
- struct sk_buff *skb)
+static int e1000_tso(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
{
struct e1000_context_desc *context_desc;
struct e1000_buffer *buffer_info;
@@ -2999,9 +2991,8 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
return false;
}
-static bool
-e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
- struct sk_buff *skb)
+static bool e1000_tx_csum(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
{
struct e1000_context_desc *context_desc;
struct e1000_buffer *buffer_info;
@@ -3038,11 +3029,13 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
#define E1000_MAX_TXD_PWR 12
#define E1000_MAX_DATA_PER_TXD (1<<E1000_MAX_TXD_PWR)
-static int
-e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
- struct sk_buff *skb, unsigned int first, unsigned int max_per_txd,
- unsigned int nr_frags, unsigned int mss)
+static int e1000_tx_map(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring,
+ struct sk_buff *skb, unsigned int first,
+ unsigned int max_per_txd, unsigned int nr_frags,
+ unsigned int mss)
{
+ struct e1000_hw *hw = &adapter->hw;
struct e1000_buffer *buffer_info;
unsigned int len = skb->len;
unsigned int offset = 0, size, count = 0, i;
@@ -3073,7 +3066,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
* The fix is to make sure that the first descriptor of a
* packet is smaller than 2048 - 16 - 16 (or 2016) bytes
*/
- if (unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
+ if (unlikely((hw->bus_type == e1000_bus_type_pcix) &&
(size > 2015) && count == 0))
size = 2015;
@@ -3145,10 +3138,11 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
return count;
}
-static void
-e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
- int tx_flags, int count)
+static void e1000_tx_queue(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring, int tx_flags,
+ int count)
{
+ struct e1000_hw *hw = &adapter->hw;
struct e1000_tx_desc *tx_desc = NULL;
struct e1000_buffer *buffer_info;
u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
@@ -3194,7 +3188,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
wmb();
tx_ring->next_to_use = i;
- writel(i, adapter->hw.hw_addr + tx_ring->tdt);
+ writel(i, hw->hw_addr + tx_ring->tdt);
/* we need this if more than one processor can write to our tail
* at a time, it syncronizes IO on IA64/Altix systems */
mmiowb();
@@ -3212,8 +3206,8 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
#define E1000_FIFO_HDR 0x10
#define E1000_82547_PAD_LEN 0x3E0
-static int
-e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb)
+static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
+ struct sk_buff *skb)
{
u32 fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
u32 skb_fifo_len = skb->len + E1000_FIFO_HDR;
@@ -3239,19 +3233,19 @@ no_fifo_stall_required:
}
#define MINIMUM_DHCP_PACKET_SIZE 282
-static int
-e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
+static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter,
+ struct sk_buff *skb)
{
struct e1000_hw *hw = &adapter->hw;
u16 length, offset;
if (vlan_tx_tag_present(skb)) {
- if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
- ( adapter->hw.mng_cookie.status &
+ if (!((vlan_tx_tag_get(skb) == hw->mng_cookie.vlan_id) &&
+ ( hw->mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) )
return 0;
}
if (skb->len > MINIMUM_DHCP_PACKET_SIZE) {
- struct ethhdr *eth = (struct ethhdr *) skb->data;
+ struct ethhdr *eth = (struct ethhdr *)skb->data;
if ((htons(ETH_P_IP) == eth->h_proto)) {
const struct iphdr *ip =
(struct iphdr *)((u8 *)skb->data+14);
@@ -3304,10 +3298,10 @@ static int e1000_maybe_stop_tx(struct net_device *netdev,
}
#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 )
-static int
-e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
struct e1000_tx_ring *tx_ring;
unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
@@ -3333,7 +3327,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* 82571 and newer doesn't need the workaround that limited descriptor
* length to 4kB */
- if (adapter->hw.mac_type >= e1000_82571)
+ if (hw->mac_type >= e1000_82571)
max_per_txd = 8192;
mss = skb_shinfo(skb)->gso_size;
@@ -3353,7 +3347,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
* frags into skb->data */
hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
if (skb->data_len && hdr_len == len) {
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
unsigned int pull_size;
case e1000_82544:
/* Make sure we have room to chop off 4 bytes,
@@ -3402,7 +3396,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* work-around for errata 10 and it applies to all controllers
* in PCI-X mode, so add one more descriptor to the count
*/
- if (unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
+ if (unlikely((hw->bus_type == e1000_bus_type_pcix) &&
(len > 2015)))
count++;
@@ -3414,8 +3408,8 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
count += nr_frags;
- if (adapter->hw.tx_pkt_filtering &&
- (adapter->hw.mac_type == e1000_82573))
+ if (hw->tx_pkt_filtering &&
+ (hw->mac_type == e1000_82573))
e1000_transfer_dhcp_info(adapter, skb);
if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags))
@@ -3429,7 +3423,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_BUSY;
}
- if (unlikely(adapter->hw.mac_type == e1000_82547)) {
+ if (unlikely(hw->mac_type == e1000_82547)) {
if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
netif_stop_queue(netdev);
mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1);
@@ -3482,8 +3476,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
* @netdev: network interface device structure
**/
-static void
-e1000_tx_timeout(struct net_device *netdev)
+static void e1000_tx_timeout(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -3492,8 +3485,7 @@ e1000_tx_timeout(struct net_device *netdev)
schedule_work(&adapter->reset_task);
}
-static void
-e1000_reset_task(struct work_struct *work)
+static void e1000_reset_task(struct work_struct *work)
{
struct e1000_adapter *adapter =
container_of(work, struct e1000_adapter, reset_task);
@@ -3509,8 +3501,7 @@ e1000_reset_task(struct work_struct *work)
* The statistics are actually updated from the timer callback.
**/
-static struct net_device_stats *
-e1000_get_stats(struct net_device *netdev)
+static struct net_device_stats *e1000_get_stats(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -3526,10 +3517,10 @@ e1000_get_stats(struct net_device *netdev)
* Returns 0 on success, negative on failure
**/
-static int
-e1000_change_mtu(struct net_device *netdev, int new_mtu)
+static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
u16 eeprom_data = 0;
@@ -3540,7 +3531,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
}
/* Adapter-specific max frame size limits. */
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_undefined ... e1000_82542_rev2_1:
case e1000_ich8lan:
if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
@@ -3552,9 +3543,9 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
/* Jumbo Frames not supported if:
* - this is not an 82573L device
* - ASPM is enabled in any way (0x1A bits 3:2) */
- e1000_read_eeprom(&adapter->hw, EEPROM_INIT_3GIO_3, 1,
+ e1000_read_eeprom(hw, EEPROM_INIT_3GIO_3, 1,
&eeprom_data);
- if ((adapter->hw.device_id != E1000_DEV_ID_82573L) ||
+ if ((hw->device_id != E1000_DEV_ID_82573L) ||
(eeprom_data & EEPROM_WORD1A_ASPM_MASK)) {
if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
DPRINTK(PROBE, ERR,
@@ -3601,13 +3592,13 @@ 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 */
- if (!adapter->hw.tbi_compatibility_on &&
+ if (!hw->tbi_compatibility_on &&
((max_frame == MAXIMUM_ETHERNET_FRAME_SIZE) ||
(max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
netdev->mtu = new_mtu;
- adapter->hw.max_frame_size = max_frame;
+ hw->max_frame_size = max_frame;
if (netif_running(netdev))
e1000_reinit_locked(adapter);
@@ -3620,8 +3611,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
* @adapter: board private structure
**/
-void
-e1000_update_stats(struct e1000_adapter *adapter)
+void e1000_update_stats(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
@@ -3646,89 +3636,89 @@ e1000_update_stats(struct e1000_adapter *adapter)
* be written while holding adapter->stats_lock
*/
- adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS);
- adapter->stats.gprc += E1000_READ_REG(hw, GPRC);
- adapter->stats.gorcl += E1000_READ_REG(hw, GORCL);
- adapter->stats.gorch += E1000_READ_REG(hw, GORCH);
- adapter->stats.bprc += E1000_READ_REG(hw, BPRC);
- adapter->stats.mprc += E1000_READ_REG(hw, MPRC);
- adapter->stats.roc += E1000_READ_REG(hw, ROC);
-
- if (adapter->hw.mac_type != e1000_ich8lan) {
- adapter->stats.prc64 += E1000_READ_REG(hw, PRC64);
- adapter->stats.prc127 += E1000_READ_REG(hw, PRC127);
- adapter->stats.prc255 += E1000_READ_REG(hw, PRC255);
- adapter->stats.prc511 += E1000_READ_REG(hw, PRC511);
- adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023);
- adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522);
- }
-
- adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS);
- adapter->stats.mpc += E1000_READ_REG(hw, MPC);
- adapter->stats.scc += E1000_READ_REG(hw, SCC);
- adapter->stats.ecol += E1000_READ_REG(hw, ECOL);
- adapter->stats.mcc += E1000_READ_REG(hw, MCC);
- adapter->stats.latecol += E1000_READ_REG(hw, LATECOL);
- adapter->stats.dc += E1000_READ_REG(hw, DC);
- adapter->stats.sec += E1000_READ_REG(hw, SEC);
- adapter->stats.rlec += E1000_READ_REG(hw, RLEC);
- adapter->stats.xonrxc += E1000_READ_REG(hw, XONRXC);
- adapter->stats.xontxc += E1000_READ_REG(hw, XONTXC);
- adapter->stats.xoffrxc += E1000_READ_REG(hw, XOFFRXC);
- adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC);
- adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC);
- adapter->stats.gptc += E1000_READ_REG(hw, GPTC);
- adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL);
- adapter->stats.gotch += E1000_READ_REG(hw, GOTCH);
- adapter->stats.rnbc += E1000_READ_REG(hw, RNBC);
- adapter->stats.ruc += E1000_READ_REG(hw, RUC);
- adapter->stats.rfc += E1000_READ_REG(hw, RFC);
- adapter->stats.rjc += E1000_READ_REG(hw, RJC);
- adapter->stats.torl += E1000_READ_REG(hw, TORL);
- adapter->stats.torh += E1000_READ_REG(hw, TORH);
- adapter->stats.totl += E1000_READ_REG(hw, TOTL);
- adapter->stats.toth += E1000_READ_REG(hw, TOTH);
- adapter->stats.tpr += E1000_READ_REG(hw, TPR);
-
- if (adapter->hw.mac_type != e1000_ich8lan) {
- adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64);
- adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127);
- adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255);
- adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511);
- adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023);
- adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522);
- }
-
- adapter->stats.mptc += E1000_READ_REG(hw, MPTC);
- adapter->stats.bptc += E1000_READ_REG(hw, BPTC);
+ adapter->stats.crcerrs += er32(CRCERRS);
+ adapter->stats.gprc += er32(GPRC);
+ adapter->stats.gorcl += er32(GORCL);
+ adapter->stats.gorch += er32(GORCH);
+ adapter->stats.bprc += er32(BPRC);
+ adapter->stats.mprc += er32(MPRC);
+ adapter->stats.roc += er32(ROC);
+
+ if (hw->mac_type != e1000_ich8lan) {
+ adapter->stats.prc64 += er32(PRC64);
+ adapter->stats.prc127 += er32(PRC127);
+ adapter->stats.prc255 += er32(PRC255);
+ adapter->stats.prc511 += er32(PRC511);
+ adapter->stats.prc1023 += er32(PRC1023);
+ adapter->stats.prc1522 += er32(PRC1522);
+ }
+
+ adapter->stats.symerrs += er32(SYMERRS);
+ adapter->stats.mpc += er32(MPC);
+ adapter->stats.scc += er32(SCC);
+ adapter->stats.ecol += er32(ECOL);
+ adapter->stats.mcc += er32(MCC);
+ adapter->stats.latecol += er32(LATECOL);
+ adapter->stats.dc += er32(DC);
+ adapter->stats.sec += er32(SEC);
+ adapter->stats.rlec += er32(RLEC);
+ adapter->stats.xonrxc += er32(XONRXC);
+ adapter->stats.xontxc += er32(XONTXC);
+ adapter->stats.xoffrxc += er32(XOFFRXC);
+ adapter->stats.xofftxc += er32(XOFFTXC);
+ adapter->stats.fcruc += er32(FCRUC);
+ adapter->stats.gptc += er32(GPTC);
+ adapter->stats.gotcl += er32(GOTCL);
+ adapter->stats.gotch += er32(GOTCH);
+ adapter->stats.rnbc += er32(RNBC);
+ adapter->stats.ruc += er32(RUC);
+ adapter->stats.rfc += er32(RFC);
+ adapter->stats.rjc += er32(RJC);
+ adapter->stats.torl += er32(TORL);
+ adapter->stats.torh += er32(TORH);
+ adapter->stats.totl += er32(TOTL);
+ adapter->stats.toth += er32(TOTH);
+ adapter->stats.tpr += er32(TPR);
+
+ if (hw->mac_type != e1000_ich8lan) {
+ adapter->stats.ptc64 += er32(PTC64);
+ adapter->stats.ptc127 += er32(PTC127);
+ adapter->stats.ptc255 += er32(PTC255);
+ adapter->stats.ptc511 += er32(PTC511);
+ adapter->stats.ptc1023 += er32(PTC1023);
+ adapter->stats.ptc1522 += er32(PTC1522);
+ }
+
+ adapter->stats.mptc += er32(MPTC);
+ adapter->stats.bptc += er32(BPTC);
/* used for adaptive IFS */
- hw->tx_packet_delta = E1000_READ_REG(hw, TPT);
+ hw->tx_packet_delta = er32(TPT);
adapter->stats.tpt += hw->tx_packet_delta;
- hw->collision_delta = E1000_READ_REG(hw, COLC);
+ hw->collision_delta = er32(COLC);
adapter->stats.colc += hw->collision_delta;
if (hw->mac_type >= e1000_82543) {
- adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC);
- adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC);
- adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS);
- adapter->stats.cexterr += E1000_READ_REG(hw, CEXTERR);
- adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC);
- adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC);
+ adapter->stats.algnerrc += er32(ALGNERRC);
+ adapter->stats.rxerrc += er32(RXERRC);
+ adapter->stats.tncrs += er32(TNCRS);
+ adapter->stats.cexterr += er32(CEXTERR);
+ adapter->stats.tsctc += er32(TSCTC);
+ adapter->stats.tsctfc += er32(TSCTFC);
}
if (hw->mac_type > e1000_82547_rev_2) {
- adapter->stats.iac += E1000_READ_REG(hw, IAC);
- adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC);
-
- if (adapter->hw.mac_type != e1000_ich8lan) {
- adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC);
- adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC);
- adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC);
- adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC);
- adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC);
- adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC);
- adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC);
+ adapter->stats.iac += er32(IAC);
+ adapter->stats.icrxoc += er32(ICRXOC);
+
+ if (hw->mac_type != e1000_ich8lan) {
+ adapter->stats.icrxptc += er32(ICRXPTC);
+ adapter->stats.icrxatc += er32(ICRXATC);
+ adapter->stats.ictxptc += er32(ICTXPTC);
+ adapter->stats.ictxatc += er32(ICTXATC);
+ adapter->stats.ictxqec += er32(ICTXQEC);
+ adapter->stats.ictxqmtc += er32(ICTXQMTC);
+ adapter->stats.icrxdmtc += er32(ICRXDMTC);
}
}
@@ -3756,7 +3746,7 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->net_stats.tx_aborted_errors = adapter->stats.ecol;
adapter->net_stats.tx_window_errors = adapter->stats.latecol;
adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs;
- if (adapter->hw.bad_tx_carr_stats_fd &&
+ if (hw->bad_tx_carr_stats_fd &&
adapter->link_duplex == FULL_DUPLEX) {
adapter->net_stats.tx_carrier_errors = 0;
adapter->stats.tncrs = 0;
@@ -3779,10 +3769,10 @@ e1000_update_stats(struct e1000_adapter *adapter)
}
/* Management Stats */
- if (adapter->hw.has_smbus) {
- adapter->stats.mgptc += E1000_READ_REG(hw, MGTPTC);
- adapter->stats.mgprc += E1000_READ_REG(hw, MGTPRC);
- adapter->stats.mgpdc += E1000_READ_REG(hw, MGTPDC);
+ if (hw->has_smbus) {
+ adapter->stats.mgptc += er32(MGTPTC);
+ adapter->stats.mgprc += er32(MGTPRC);
+ adapter->stats.mgpdc += er32(MGTPDC);
}
spin_unlock_irqrestore(&adapter->stats_lock, flags);
@@ -3794,16 +3784,12 @@ e1000_update_stats(struct e1000_adapter *adapter)
* @data: pointer to a network interface device structure
**/
-static irqreturn_t
-e1000_intr_msi(int irq, void *data)
+static irqreturn_t e1000_intr_msi(int irq, void *data)
{
struct net_device *netdev = data;
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
-#ifndef CONFIG_E1000_NAPI
- int i;
-#endif
- u32 icr = E1000_READ_REG(hw, ICR);
+ u32 icr = er32(ICR);
/* in NAPI mode read ICR disables interrupts using IAM */
@@ -3813,17 +3799,16 @@ e1000_intr_msi(int irq, void *data)
* link down event; disable receives here in the ISR and reset
* adapter in watchdog */
if (netif_carrier_ok(netdev) &&
- (adapter->hw.mac_type == e1000_80003es2lan)) {
+ (hw->mac_type == e1000_80003es2lan)) {
/* disable receives */
- u32 rctl = E1000_READ_REG(hw, RCTL);
- E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
+ u32 rctl = er32(RCTL);
+ ew32(RCTL, rctl & ~E1000_RCTL_EN);
}
/* guard against interrupt when we're going down */
if (!test_bit(__E1000_DOWN, &adapter->flags))
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
-#ifdef CONFIG_E1000_NAPI
if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) {
adapter->total_tx_bytes = 0;
adapter->total_tx_packets = 0;
@@ -3832,20 +3817,6 @@ e1000_intr_msi(int irq, void *data)
__netif_rx_schedule(netdev, &adapter->napi);
} else
e1000_irq_enable(adapter);
-#else
- adapter->total_tx_bytes = 0;
- adapter->total_rx_bytes = 0;
- adapter->total_tx_packets = 0;
- adapter->total_rx_packets = 0;
-
- for (i = 0; i < E1000_MAX_INTR; i++)
- if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
- !e1000_clean_tx_irq(adapter, adapter->tx_ring)))
- break;
-
- if (likely(adapter->itr_setting & 3))
- e1000_set_itr(adapter);
-#endif
return IRQ_HANDLED;
}
@@ -3856,20 +3827,16 @@ e1000_intr_msi(int irq, void *data)
* @data: pointer to a network interface device structure
**/
-static irqreturn_t
-e1000_intr(int irq, void *data)
+static irqreturn_t e1000_intr(int irq, void *data)
{
struct net_device *netdev = data;
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- u32 rctl, icr = E1000_READ_REG(hw, ICR);
-#ifndef CONFIG_E1000_NAPI
- int i;
-#endif
+ u32 rctl, icr = er32(ICR);
+
if (unlikely(!icr))
return IRQ_NONE; /* Not our interrupt */
-#ifdef CONFIG_E1000_NAPI
/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
* not set, then the adapter didn't send an interrupt */
if (unlikely(hw->mac_type >= e1000_82571 &&
@@ -3878,7 +3845,6 @@ e1000_intr(int irq, void *data)
/* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No
* need for the IMC write */
-#endif
if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
hw->get_link_status = 1;
@@ -3888,21 +3854,20 @@ e1000_intr(int irq, void *data)
* reset adapter in watchdog
*/
if (netif_carrier_ok(netdev) &&
- (adapter->hw.mac_type == e1000_80003es2lan)) {
+ (hw->mac_type == e1000_80003es2lan)) {
/* disable receives */
- rctl = E1000_READ_REG(hw, RCTL);
- E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
+ rctl = er32(RCTL);
+ ew32(RCTL, rctl & ~E1000_RCTL_EN);
}
/* guard against interrupt when we're going down */
if (!test_bit(__E1000_DOWN, &adapter->flags))
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
-#ifdef CONFIG_E1000_NAPI
if (unlikely(hw->mac_type < e1000_82571)) {
/* disable interrupts, without the synchronize_irq bit */
- E1000_WRITE_REG(hw, IMC, ~0);
- E1000_WRITE_FLUSH(hw);
+ ew32(IMC, ~0);
+ E1000_WRITE_FLUSH();
}
if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) {
adapter->total_tx_bytes = 0;
@@ -3914,48 +3879,15 @@ e1000_intr(int irq, void *data)
/* this really should not happen! if it does it is basically a
* bug, but not a hard error, so enable ints and continue */
e1000_irq_enable(adapter);
-#else
- /* Writing IMC and IMS is needed for 82547.
- * Due to Hub Link bus being occupied, an interrupt
- * de-assertion message is not able to be sent.
- * When an interrupt assertion message is generated later,
- * two messages are re-ordered and sent out.
- * That causes APIC to think 82547 is in de-assertion
- * state, while 82547 is in assertion state, resulting
- * in dead lock. Writing IMC forces 82547 into
- * de-assertion state.
- */
- if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
- E1000_WRITE_REG(hw, IMC, ~0);
-
- adapter->total_tx_bytes = 0;
- adapter->total_rx_bytes = 0;
- adapter->total_tx_packets = 0;
- adapter->total_rx_packets = 0;
- for (i = 0; i < E1000_MAX_INTR; i++)
- if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
- !e1000_clean_tx_irq(adapter, adapter->tx_ring)))
- break;
-
- if (likely(adapter->itr_setting & 3))
- e1000_set_itr(adapter);
-
- if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
- e1000_irq_enable(adapter);
-
-#endif
return IRQ_HANDLED;
}
-#ifdef CONFIG_E1000_NAPI
/**
* e1000_clean - NAPI Rx polling callback
* @adapter: board private structure
**/
-
-static int
-e1000_clean(struct napi_struct *napi, int budget)
+static int e1000_clean(struct napi_struct *napi, int budget)
{
struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi);
struct net_device *poll_dev = adapter->netdev;
@@ -3991,23 +3923,19 @@ e1000_clean(struct napi_struct *napi, int budget)
return work_done;
}
-#endif
/**
* e1000_clean_tx_irq - Reclaim resources after transmit completes
* @adapter: board private structure
**/
-
-static bool
-e1000_clean_tx_irq(struct e1000_adapter *adapter,
- struct e1000_tx_ring *tx_ring)
+static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring)
{
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct e1000_tx_desc *tx_desc, *eop_desc;
struct e1000_buffer *buffer_info;
unsigned int i, eop;
-#ifdef CONFIG_E1000_NAPI
unsigned int count = 0;
-#endif
bool cleaned = false;
unsigned int total_tx_bytes=0, total_tx_packets=0;
@@ -4039,11 +3967,10 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
-#ifdef CONFIG_E1000_NAPI
#define E1000_TX_WEIGHT 64
/* weight of a sort for tx, to avoid endless transmit cleanup */
- if (count++ == E1000_TX_WEIGHT) break;
-#endif
+ if (count++ == E1000_TX_WEIGHT)
+ break;
}
tx_ring->next_to_clean = i;
@@ -4068,8 +3995,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
if (tx_ring->buffer_info[eop].dma &&
time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
(adapter->tx_timeout_factor * HZ))
- && !(E1000_READ_REG(&adapter->hw, STATUS) &
- E1000_STATUS_TXOFF)) {
+ && !(er32(STATUS) & E1000_STATUS_TXOFF)) {
/* detected Tx unit hang */
DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
@@ -4085,8 +4011,8 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
" next_to_watch.status <%x>\n",
(unsigned long)((tx_ring - adapter->tx_ring) /
sizeof(struct e1000_tx_ring)),
- readl(adapter->hw.hw_addr + tx_ring->tdh),
- readl(adapter->hw.hw_addr + tx_ring->tdt),
+ readl(hw->hw_addr + tx_ring->tdh),
+ readl(hw->hw_addr + tx_ring->tdt),
tx_ring->next_to_use,
tx_ring->next_to_clean,
tx_ring->buffer_info[eop].time_stamp,
@@ -4111,17 +4037,16 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
* @sk_buff: socket buffer with received data
**/
-static void
-e1000_rx_checksum(struct e1000_adapter *adapter,
- u32 status_err, u32 csum,
- struct sk_buff *skb)
+static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
+ u32 csum, struct sk_buff *skb)
{
+ struct e1000_hw *hw = &adapter->hw;
u16 status = (u16)status_err;
u8 errors = (u8)(status_err >> 24);
skb->ip_summed = CHECKSUM_NONE;
/* 82543 or newer only */
- if (unlikely(adapter->hw.mac_type < e1000_82543)) return;
+ if (unlikely(hw->mac_type < e1000_82543)) return;
/* Ignore Checksum bit is set */
if (unlikely(status & E1000_RXD_STAT_IXSM)) return;
/* TCP/UDP checksum error bit is set */
@@ -4131,7 +4056,7 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
return;
}
/* TCP/UDP Checksum has not been calculated */
- if (adapter->hw.mac_type <= e1000_82547_rev_2) {
+ if (hw->mac_type <= e1000_82547_rev_2) {
if (!(status & E1000_RXD_STAT_TCPCS))
return;
} else {
@@ -4142,7 +4067,7 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
if (likely(status & E1000_RXD_STAT_TCPCS)) {
/* TCP checksum is good */
skb->ip_summed = CHECKSUM_UNNECESSARY;
- } else if (adapter->hw.mac_type > e1000_82547_rev_2) {
+ } else if (hw->mac_type > e1000_82547_rev_2) {
/* IP fragment with UDP payload */
/* Hardware complements the payload checksum, so we undo it
* and then put the value in host order for further stack use.
@@ -4158,17 +4083,11 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
* e1000_clean_rx_irq - Send received data up the network stack; legacy
* @adapter: board private structure
**/
-
-static bool
-#ifdef CONFIG_E1000_NAPI
-e1000_clean_rx_irq(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int *work_done, int work_to_do)
-#else
-e1000_clean_rx_irq(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
-#endif
+static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do)
{
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct e1000_rx_desc *rx_desc, *next_rxd;
@@ -4189,11 +4108,10 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
struct sk_buff *skb;
u8 status;
-#ifdef CONFIG_E1000_NAPI
if (*work_done >= work_to_do)
break;
(*work_done)++;
-#endif
+
status = rx_desc->status;
skb = buffer_info->skb;
buffer_info->skb = NULL;
@@ -4226,11 +4144,10 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
last_byte = *(skb->data + length - 1);
- if (TBI_ACCEPT(&adapter->hw, status,
- rx_desc->errors, length, last_byte)) {
+ if (TBI_ACCEPT(hw, status, rx_desc->errors, length,
+ last_byte)) {
spin_lock_irqsave(&adapter->stats_lock, flags);
- e1000_tbi_adjust_stats(&adapter->hw,
- &adapter->stats,
+ e1000_tbi_adjust_stats(hw, &adapter->stats,
length, skb->data);
spin_unlock_irqrestore(&adapter->stats_lock,
flags);
@@ -4280,7 +4197,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
le16_to_cpu(rx_desc->csum), skb);
skb->protocol = eth_type_trans(skb, netdev);
-#ifdef CONFIG_E1000_NAPI
+
if (unlikely(adapter->vlgrp &&
(status & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
@@ -4288,15 +4205,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
} else {
netif_receive_skb(skb);
}
-#else /* CONFIG_E1000_NAPI */
- if (unlikely(adapter->vlgrp &&
- (status & E1000_RXD_STAT_VP))) {
- vlan_hwaccel_rx(skb, adapter->vlgrp,
- le16_to_cpu(rx_desc->special));
- } else {
- netif_rx(skb);
- }
-#endif /* CONFIG_E1000_NAPI */
+
netdev->last_rx = jiffies;
next_desc:
@@ -4330,15 +4239,9 @@ next_desc:
* @adapter: board private structure
**/
-static bool
-#ifdef CONFIG_E1000_NAPI
-e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int *work_done, int work_to_do)
-#else
-e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
-#endif
+static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do)
{
union e1000_rx_desc_packet_split *rx_desc, *next_rxd;
struct net_device *netdev = adapter->netdev;
@@ -4361,11 +4264,11 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
while (staterr & E1000_RXD_STAT_DD) {
ps_page = &rx_ring->ps_page[i];
ps_page_dma = &rx_ring->ps_page_dma[i];
-#ifdef CONFIG_E1000_NAPI
+
if (unlikely(*work_done >= work_to_do))
break;
(*work_done)++;
-#endif
+
skb = buffer_info->skb;
/* in the packet split case this is header only */
@@ -4438,7 +4341,8 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
}
for (j = 0; j < adapter->rx_ps_pages; j++) {
- if (!(length= le16_to_cpu(rx_desc->wb.upper.length[j])))
+ length = le16_to_cpu(rx_desc->wb.upper.length[j]);
+ if (!length)
break;
pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j],
PAGE_SIZE, PCI_DMA_FROMDEVICE);
@@ -4466,21 +4370,14 @@ copydone:
if (likely(rx_desc->wb.upper.header_status &
cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP)))
adapter->rx_hdr_split++;
-#ifdef CONFIG_E1000_NAPI
+
if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
le16_to_cpu(rx_desc->wb.middle.vlan));
} else {
netif_receive_skb(skb);
}
-#else /* CONFIG_E1000_NAPI */
- if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
- vlan_hwaccel_rx(skb, adapter->vlgrp,
- le16_to_cpu(rx_desc->wb.middle.vlan));
- } else {
- netif_rx(skb);
- }
-#endif /* CONFIG_E1000_NAPI */
+
netdev->last_rx = jiffies;
next_desc:
@@ -4517,11 +4414,11 @@ next_desc:
* @adapter: address of board private structure
**/
-static void
-e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int cleaned_count)
+static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count)
{
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct e1000_rx_desc *rx_desc;
@@ -4619,7 +4516,7 @@ map_skb:
* applicable for weak-ordered memory model archs,
* such as IA-64). */
wmb();
- writel(i, adapter->hw.hw_addr + rx_ring->rdt);
+ writel(i, hw->hw_addr + rx_ring->rdt);
}
}
@@ -4628,11 +4525,11 @@ map_skb:
* @adapter: address of board private structure
**/
-static void
-e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int cleaned_count)
+static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count)
{
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
union e1000_rx_desc_packet_split *rx_desc;
@@ -4717,7 +4614,7 @@ no_buffers:
* descriptors are 32 bytes...so we increment tail
* twice as much.
*/
- writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
+ writel(i<<1, hw->hw_addr + rx_ring->rdt);
}
}
@@ -4726,49 +4623,49 @@ no_buffers:
* @adapter:
**/
-static void
-e1000_smartspeed(struct e1000_adapter *adapter)
+static void e1000_smartspeed(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
u16 phy_status;
u16 phy_ctrl;
- if ((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg ||
- !(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL))
+ if ((hw->phy_type != e1000_phy_igp) || !hw->autoneg ||
+ !(hw->autoneg_advertised & ADVERTISE_1000_FULL))
return;
if (adapter->smartspeed == 0) {
/* If Master/Slave config fault is asserted twice,
* we assume back-to-back */
- e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
+ e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status);
if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
- e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
+ e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status);
if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
- e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
+ e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl);
if (phy_ctrl & CR_1000T_MS_ENABLE) {
phy_ctrl &= ~CR_1000T_MS_ENABLE;
- e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL,
+ e1000_write_phy_reg(hw, PHY_1000T_CTRL,
phy_ctrl);
adapter->smartspeed++;
- if (!e1000_phy_setup_autoneg(&adapter->hw) &&
- !e1000_read_phy_reg(&adapter->hw, PHY_CTRL,
+ if (!e1000_phy_setup_autoneg(hw) &&
+ !e1000_read_phy_reg(hw, PHY_CTRL,
&phy_ctrl)) {
phy_ctrl |= (MII_CR_AUTO_NEG_EN |
MII_CR_RESTART_AUTO_NEG);
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL,
+ e1000_write_phy_reg(hw, PHY_CTRL,
phy_ctrl);
}
}
return;
} else if (adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
/* If still no link, perhaps using 2/3 pair cable */
- e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
+ e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl);
phy_ctrl |= CR_1000T_MS_ENABLE;
- e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl);
- if (!e1000_phy_setup_autoneg(&adapter->hw) &&
- !e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) {
+ e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_ctrl);
+ if (!e1000_phy_setup_autoneg(hw) &&
+ !e1000_read_phy_reg(hw, PHY_CTRL, &phy_ctrl)) {
phy_ctrl |= (MII_CR_AUTO_NEG_EN |
MII_CR_RESTART_AUTO_NEG);
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_ctrl);
+ e1000_write_phy_reg(hw, PHY_CTRL, phy_ctrl);
}
}
/* Restart process after E1000_SMARTSPEED_MAX iterations */
@@ -4783,8 +4680,7 @@ e1000_smartspeed(struct e1000_adapter *adapter)
* @cmd:
**/
-static int
-e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
switch (cmd) {
case SIOCGMIIPHY:
@@ -4803,28 +4699,29 @@ e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
* @cmd:
**/
-static int
-e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
+ int cmd)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
struct mii_ioctl_data *data = if_mii(ifr);
int retval;
u16 mii_reg;
u16 spddplx;
unsigned long flags;
- if (adapter->hw.media_type != e1000_media_type_copper)
+ if (hw->media_type != e1000_media_type_copper)
return -EOPNOTSUPP;
switch (cmd) {
case SIOCGMIIPHY:
- data->phy_id = adapter->hw.phy_addr;
+ data->phy_id = hw->phy_addr;
break;
case SIOCGMIIREG:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
spin_lock_irqsave(&adapter->stats_lock, flags);
- if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+ if (e1000_read_phy_reg(hw, data->reg_num & 0x1F,
&data->val_out)) {
spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
@@ -4838,20 +4735,20 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
return -EFAULT;
mii_reg = data->val_in;
spin_lock_irqsave(&adapter->stats_lock, flags);
- if (e1000_write_phy_reg(&adapter->hw, data->reg_num,
+ if (e1000_write_phy_reg(hw, data->reg_num,
mii_reg)) {
spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
}
spin_unlock_irqrestore(&adapter->stats_lock, flags);
- if (adapter->hw.media_type == e1000_media_type_copper) {
+ if (hw->media_type == e1000_media_type_copper) {
switch (data->reg_num) {
case PHY_CTRL:
if (mii_reg & MII_CR_POWER_DOWN)
break;
if (mii_reg & MII_CR_AUTO_NEG_EN) {
- adapter->hw.autoneg = 1;
- adapter->hw.autoneg_advertised = 0x2F;
+ hw->autoneg = 1;
+ hw->autoneg_advertised = 0x2F;
} else {
if (mii_reg & 0x40)
spddplx = SPEED_1000;
@@ -4874,7 +4771,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
break;
case M88E1000_PHY_SPEC_CTRL:
case M88E1000_EXT_PHY_SPEC_CTRL:
- if (e1000_phy_reset(&adapter->hw))
+ if (e1000_phy_reset(hw))
return -EIO;
break;
}
@@ -4897,8 +4794,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
return E1000_SUCCESS;
}
-void
-e1000_pci_set_mwi(struct e1000_hw *hw)
+void e1000_pci_set_mwi(struct e1000_hw *hw)
{
struct e1000_adapter *adapter = hw->back;
int ret_val = pci_set_mwi(adapter->pdev);
@@ -4907,30 +4803,26 @@ e1000_pci_set_mwi(struct e1000_hw *hw)
DPRINTK(PROBE, ERR, "Error in setting MWI\n");
}
-void
-e1000_pci_clear_mwi(struct e1000_hw *hw)
+void e1000_pci_clear_mwi(struct e1000_hw *hw)
{
struct e1000_adapter *adapter = hw->back;
pci_clear_mwi(adapter->pdev);
}
-int
-e1000_pcix_get_mmrbc(struct e1000_hw *hw)
+int e1000_pcix_get_mmrbc(struct e1000_hw *hw)
{
struct e1000_adapter *adapter = hw->back;
return pcix_get_mmrbc(adapter->pdev);
}
-void
-e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc)
+void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc)
{
struct e1000_adapter *adapter = hw->back;
pcix_set_mmrbc(adapter->pdev, mmrbc);
}
-s32
-e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
+s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
{
struct e1000_adapter *adapter = hw->back;
u16 cap_offset;
@@ -4944,16 +4836,16 @@ e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
return E1000_SUCCESS;
}
-void
-e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value)
+void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value)
{
outl(value, port);
}
-static void
-e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+static void e1000_vlan_rx_register(struct net_device *netdev,
+ struct vlan_group *grp)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
u32 ctrl, rctl;
if (!test_bit(__E1000_DOWN, &adapter->flags))
@@ -4962,22 +4854,22 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
if (grp) {
/* enable VLAN tag insert/strip */
- ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+ ctrl = er32(CTRL);
ctrl |= E1000_CTRL_VME;
- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
if (adapter->hw.mac_type != e1000_ich8lan) {
/* enable VLAN receive filtering */
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl = er32(RCTL);
rctl &= ~E1000_RCTL_CFIEN;
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ ew32(RCTL, rctl);
e1000_update_mng_vlan(adapter);
}
} else {
/* disable VLAN tag insert/strip */
- ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+ ctrl = er32(CTRL);
ctrl &= ~E1000_CTRL_VME;
- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
if (adapter->hw.mac_type != e1000_ich8lan) {
if (adapter->mng_vlan_id !=
@@ -4993,27 +4885,27 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
e1000_irq_enable(adapter);
}
-static void
-e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
u32 vfta, index;
- if ((adapter->hw.mng_cookie.status &
+ if ((hw->mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
(vid == adapter->mng_vlan_id))
return;
/* add VID to filter table */
index = (vid >> 5) & 0x7F;
- vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+ vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
vfta |= (1 << (vid & 0x1F));
- e1000_write_vfta(&adapter->hw, index, vfta);
+ e1000_write_vfta(hw, index, vfta);
}
-static void
-e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
u32 vfta, index;
if (!test_bit(__E1000_DOWN, &adapter->flags))
@@ -5022,7 +4914,7 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
if (!test_bit(__E1000_DOWN, &adapter->flags))
e1000_irq_enable(adapter);
- if ((adapter->hw.mng_cookie.status &
+ if ((hw->mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
(vid == adapter->mng_vlan_id)) {
/* release control to f/w */
@@ -5032,13 +4924,12 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
/* remove VID from filter table */
index = (vid >> 5) & 0x7F;
- vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+ vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
vfta &= ~(1 << (vid & 0x1F));
- e1000_write_vfta(&adapter->hw, index, vfta);
+ e1000_write_vfta(hw, index, vfta);
}
-static void
-e1000_restore_vlan(struct e1000_adapter *adapter)
+static void e1000_restore_vlan(struct e1000_adapter *adapter)
{
e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp);
@@ -5052,13 +4943,14 @@ e1000_restore_vlan(struct e1000_adapter *adapter)
}
}
-int
-e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
+int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
{
- adapter->hw.autoneg = 0;
+ struct e1000_hw *hw = &adapter->hw;
+
+ hw->autoneg = 0;
/* Fiber NICs only allow 1000 gbps Full duplex */
- if ((adapter->hw.media_type == e1000_media_type_fiber) &&
+ if ((hw->media_type == e1000_media_type_fiber) &&
spddplx != (SPEED_1000 + DUPLEX_FULL)) {
DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n");
return -EINVAL;
@@ -5066,20 +4958,20 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
switch (spddplx) {
case SPEED_10 + DUPLEX_HALF:
- adapter->hw.forced_speed_duplex = e1000_10_half;
+ hw->forced_speed_duplex = e1000_10_half;
break;
case SPEED_10 + DUPLEX_FULL:
- adapter->hw.forced_speed_duplex = e1000_10_full;
+ hw->forced_speed_duplex = e1000_10_full;
break;
case SPEED_100 + DUPLEX_HALF:
- adapter->hw.forced_speed_duplex = e1000_100_half;
+ hw->forced_speed_duplex = e1000_100_half;
break;
case SPEED_100 + DUPLEX_FULL:
- adapter->hw.forced_speed_duplex = e1000_100_full;
+ hw->forced_speed_duplex = e1000_100_full;
break;
case SPEED_1000 + DUPLEX_FULL:
- adapter->hw.autoneg = 1;
- adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
+ hw->autoneg = 1;
+ hw->autoneg_advertised = ADVERTISE_1000_FULL;
break;
case SPEED_1000 + DUPLEX_HALF: /* not supported */
default:
@@ -5089,11 +4981,11 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
return 0;
}
-static int
-e1000_suspend(struct pci_dev *pdev, pm_message_t state)
+static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
u32 ctrl, ctrl_ext, rctl, status;
u32 wufc = adapter->wol;
#ifdef CONFIG_PM
@@ -5113,7 +5005,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
return retval;
#endif
- status = E1000_READ_REG(&adapter->hw, STATUS);
+ status = er32(STATUS);
if (status & E1000_STATUS_LU)
wufc &= ~E1000_WUFC_LNKC;
@@ -5123,40 +5015,40 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
/* turn on all-multi mode if wake on multicast is enabled */
if (wufc & E1000_WUFC_MC) {
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl = er32(RCTL);
rctl |= E1000_RCTL_MPE;
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ ew32(RCTL, rctl);
}
- if (adapter->hw.mac_type >= e1000_82540) {
- ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+ if (hw->mac_type >= e1000_82540) {
+ ctrl = er32(CTRL);
/* advertise wake from D3Cold */
#define E1000_CTRL_ADVD3WUC 0x00100000
/* phy power management enable */
#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000
ctrl |= E1000_CTRL_ADVD3WUC |
E1000_CTRL_EN_PHY_PWR_MGMT;
- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
}
- if (adapter->hw.media_type == e1000_media_type_fiber ||
- adapter->hw.media_type == e1000_media_type_internal_serdes) {
+ if (hw->media_type == e1000_media_type_fiber ||
+ hw->media_type == e1000_media_type_internal_serdes) {
/* keep the laser running in D3 */
- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+ ctrl_ext = er32(CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext);
+ ew32(CTRL_EXT, ctrl_ext);
}
/* Allow time for pending master requests to run */
- e1000_disable_pciex_master(&adapter->hw);
+ e1000_disable_pciex_master(hw);
- E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN);
- E1000_WRITE_REG(&adapter->hw, WUFC, wufc);
+ ew32(WUC, E1000_WUC_PME_EN);
+ ew32(WUFC, wufc);
pci_enable_wake(pdev, PCI_D3hot, 1);
pci_enable_wake(pdev, PCI_D3cold, 1);
} else {
- E1000_WRITE_REG(&adapter->hw, WUC, 0);
- E1000_WRITE_REG(&adapter->hw, WUFC, 0);
+ ew32(WUC, 0);
+ ew32(WUFC, 0);
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0);
}
@@ -5169,8 +5061,8 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
pci_enable_wake(pdev, PCI_D3cold, 1);
}
- if (adapter->hw.phy_type == e1000_phy_igp_3)
- e1000_phy_powerdown_workaround(&adapter->hw);
+ if (hw->phy_type == e1000_phy_igp_3)
+ e1000_phy_powerdown_workaround(hw);
if (netif_running(netdev))
e1000_free_irq(adapter);
@@ -5187,16 +5079,21 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
}
#ifdef CONFIG_PM
-static int
-e1000_resume(struct pci_dev *pdev)
+static int e1000_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
u32 err;
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
- if ((err = pci_enable_device(pdev))) {
+
+ if (adapter->need_ioport)
+ err = pci_enable_device(pdev);
+ else
+ err = pci_enable_device_mem(pdev);
+ if (err) {
printk(KERN_ERR "e1000: Cannot enable PCI device from suspend\n");
return err;
}
@@ -5205,12 +5102,15 @@ e1000_resume(struct pci_dev *pdev)
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0);
- if (netif_running(netdev) && (err = e1000_request_irq(adapter)))
- return err;
+ if (netif_running(netdev)) {
+ err = e1000_request_irq(adapter);
+ if (err)
+ return err;
+ }
e1000_power_up_phy(adapter);
e1000_reset(adapter);
- E1000_WRITE_REG(&adapter->hw, WUS, ~0);
+ ew32(WUS, ~0);
e1000_init_manageability(adapter);
@@ -5223,8 +5123,8 @@ e1000_resume(struct pci_dev *pdev)
* DRV_LOAD until the interface is up. For all other cases,
* let the f/w know that the h/w is now under the control
* of the driver. */
- if (adapter->hw.mac_type != e1000_82573 ||
- !e1000_check_mng_mode(&adapter->hw))
+ if (hw->mac_type != e1000_82573 ||
+ !e1000_check_mng_mode(hw))
e1000_get_hw_control(adapter);
return 0;
@@ -5242,16 +5142,12 @@ static void e1000_shutdown(struct pci_dev *pdev)
* without having to re-enable interrupts. It's not called while
* the interrupt routine is executing.
*/
-static void
-e1000_netpoll(struct net_device *netdev)
+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);
-#ifndef CONFIG_E1000_NAPI
- adapter->clean_rx(adapter, adapter->rx_ring);
-#endif
enable_irq(adapter->pdev->irq);
}
#endif
@@ -5264,7 +5160,8 @@ e1000_netpoll(struct net_device *netdev)
* This function is called after a PCI bus error affecting
* this device has been detected.
*/
-static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
@@ -5290,8 +5187,14 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_hw *hw = &adapter->hw;
+ int err;
- if (pci_enable_device(pdev)) {
+ if (adapter->need_ioport)
+ err = pci_enable_device(pdev);
+ else
+ err = pci_enable_device_mem(pdev);
+ if (err) {
printk(KERN_ERR "e1000: Cannot re-enable PCI device after reset.\n");
return PCI_ERS_RESULT_DISCONNECT;
}
@@ -5301,7 +5204,7 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
pci_enable_wake(pdev, PCI_D3cold, 0);
e1000_reset(adapter);
- E1000_WRITE_REG(&adapter->hw, WUS, ~0);
+ ew32(WUS, ~0);
return PCI_ERS_RESULT_RECOVERED;
}
@@ -5318,6 +5221,7 @@ static void e1000_io_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_hw *hw = &adapter->hw;
e1000_init_manageability(adapter);
@@ -5334,8 +5238,8 @@ static void e1000_io_resume(struct pci_dev *pdev)
* DRV_LOAD until the interface is up. For all other cases,
* let the f/w know that the h/w is now under the control
* of the driver. */
- if (adapter->hw.mac_type != e1000_82573 ||
- !e1000_check_mng_mode(&adapter->hw))
+ if (hw->mac_type != e1000_82573 ||
+ !e1000_check_mng_mode(hw))
e1000_get_hw_control(adapter);
}
diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
index 365626d3177..d9298522f5a 100644
--- a/drivers/net/e1000/e1000_osdep.h
+++ b/drivers/net/e1000/e1000_osdep.h
@@ -55,13 +55,13 @@
#define DEBUGOUT7 DEBUGOUT3
-#define E1000_WRITE_REG(a, reg, value) ( \
- writel((value), ((a)->hw_addr + \
- (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg))))
+#define er32(reg) \
+ (readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
+ ? E1000_##reg : E1000_82542_##reg)))
-#define E1000_READ_REG(a, reg) ( \
- readl((a)->hw_addr + \
- (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg)))
+#define ew32(reg, value) \
+ (writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
+ ? E1000_##reg : E1000_82542_##reg))))
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
writel((value), ((a)->hw_addr + \
@@ -96,7 +96,7 @@
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
(offset)))
-#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS)
+#define E1000_WRITE_FLUSH() er32(STATUS)
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
writel((value), ((a)->flash_address + reg)))
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index e6565ce686b..b9f90a5d3d4 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -213,10 +213,9 @@ struct e1000_option {
} arg;
};
-static int __devinit
-e1000_validate_option(unsigned int *value,
- const struct e1000_option *opt,
- struct e1000_adapter *adapter)
+static int __devinit e1000_validate_option(unsigned int *value,
+ const struct e1000_option *opt,
+ struct e1000_adapter *adapter)
{
if (*value == OPTION_UNSET) {
*value = opt->def;
@@ -278,8 +277,7 @@ static void e1000_check_copper_options(struct e1000_adapter *adapter);
* in a variable in the adapter structure.
**/
-void __devinit
-e1000_check_options(struct e1000_adapter *adapter)
+void __devinit e1000_check_options(struct e1000_adapter *adapter)
{
int bd = adapter->bd_number;
if (bd >= E1000_MAX_NIC) {
@@ -551,8 +549,7 @@ e1000_check_options(struct e1000_adapter *adapter)
* Handles speed and duplex options on fiber adapters
**/
-static void __devinit
-e1000_check_fiber_options(struct e1000_adapter *adapter)
+static void __devinit e1000_check_fiber_options(struct e1000_adapter *adapter)
{
int bd = adapter->bd_number;
if (num_Speed > bd) {
@@ -579,8 +576,7 @@ e1000_check_fiber_options(struct e1000_adapter *adapter)
* Handles speed and duplex options on copper adapters
**/
-static void __devinit
-e1000_check_copper_options(struct e1000_adapter *adapter)
+static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter)
{
unsigned int speed, dplx, an;
int bd = adapter->bd_number;
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 869544b8c05..9c0f56b3c51 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -4067,8 +4067,6 @@ static void e1000_netpoll(struct net_device *netdev)
disable_irq(adapter->pdev->irq);
e1000_intr(adapter->pdev->irq, netdev);
- e1000_clean_tx_irq(adapter);
-
enable_irq(adapter->pdev->irq);
}
#endif
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 32a4f17d35f..ecd5c71a7a8 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -2,12 +2,6 @@
* Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
* Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
*
- * This version of the driver is specific to the FADS implementation,
- * since the board contains control registers external to the processor
- * for the control of the LevelOne LXT970 transceiver. The MPC860T manual
- * describes connections using the internal parallel port I/O, which
- * is basically all of Port D.
- *
* Right now, I am very wasteful with the buffers. I allocate memory
* pages and then divide them into 2K frame buffers. This way I know I
* have buffers large enough to hold one frame within one buffer descriptor.
@@ -49,17 +43,9 @@
#include <asm/pgtable.h>
#include <asm/cacheflush.h>
-#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \
- defined(CONFIG_M5272) || defined(CONFIG_M528x) || \
- defined(CONFIG_M520x) || defined(CONFIG_M532x)
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#include "fec.h"
-#else
-#include <asm/8xx_immap.h>
-#include <asm/mpc8xx.h>
-#include "commproc.h"
-#endif
#if defined(CONFIG_FEC2)
#define FEC_MAX_PORTS 2
@@ -67,7 +53,7 @@
#define FEC_MAX_PORTS 1
#endif
-#if defined(CONFIG_FADS) || defined(CONFIG_RPXCLASSIC) || defined(CONFIG_M5272)
+#if defined(CONFIG_M5272)
#define HAVE_mii_link_interrupt
#endif
@@ -1235,14 +1221,9 @@ static phy_info_t const * const phy_info[] = {
/* ------------------------------------------------------------------------- */
#ifdef HAVE_mii_link_interrupt
-#ifdef CONFIG_RPXCLASSIC
-static void
-mii_link_interrupt(void *dev_id);
-#else
static irqreturn_t
mii_link_interrupt(int irq, void * dev_id);
#endif
-#endif
#if defined(CONFIG_M5272)
/*
@@ -1795,24 +1776,6 @@ static void __inline__ fec_request_intrs(struct net_device *dev)
if (request_8xxirq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0)
panic("Could not allocate FEC IRQ!");
-
-#ifdef CONFIG_RPXCLASSIC
- /* Make Port C, bit 15 an input that causes interrupts.
- */
- immap->im_ioport.iop_pcpar &= ~0x0001;
- immap->im_ioport.iop_pcdir &= ~0x0001;
- immap->im_ioport.iop_pcso &= ~0x0001;
- immap->im_ioport.iop_pcint |= 0x0001;
- cpm_install_handler(CPMVEC_PIO_PC15, mii_link_interrupt, dev);
-
- /* Make LEDS reflect Link status.
- */
- *((uint *) RPX_CSR_ADDR) &= ~BCSR2_FETHLEDMODE;
-#endif
-#ifdef CONFIG_FADS
- if (request_8xxirq(SIU_IRQ2, mii_link_interrupt, 0, "mii", dev) != 0)
- panic("Could not allocate MII IRQ!");
-#endif
}
static void __inline__ fec_get_mac(struct net_device *dev)
@@ -1821,16 +1784,6 @@ static void __inline__ fec_get_mac(struct net_device *dev)
bd = (bd_t *)__res;
memcpy(dev->dev_addr, bd->bi_enetaddr, ETH_ALEN);
-
-#ifdef CONFIG_RPXCLASSIC
- /* The Embedded Planet boards have only one MAC address in
- * the EEPROM, but can have two Ethernet ports. For the
- * FEC port, we create another address by setting one of
- * the address bits above something that would have (up to
- * now) been allocated.
- */
- dev->dev_adrd[3] |= 0x80;
-#endif
}
static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep)
@@ -2109,13 +2062,8 @@ mii_discover_phy(uint mii_reg, struct net_device *dev)
/* This interrupt occurs when the PHY detects a link change.
*/
#ifdef HAVE_mii_link_interrupt
-#ifdef CONFIG_RPXCLASSIC
-static void
-mii_link_interrupt(void *dev_id)
-#else
static irqreturn_t
mii_link_interrupt(int irq, void * dev_id)
-#endif
{
struct net_device *dev = dev_id;
struct fec_enet_private *fep = netdev_priv(dev);
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index ae9ecb7df22..4e4f68304e8 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -197,9 +197,6 @@ static void mpc52xx_fec_adjust_link(struct net_device *dev)
if (priv->link == PHY_DOWN) {
new_state = 1;
priv->link = phydev->link;
- netif_tx_schedule_all(dev);
- netif_carrier_on(dev);
- netif_start_queue(dev);
}
} else if (priv->link) {
@@ -207,8 +204,6 @@ static void mpc52xx_fec_adjust_link(struct net_device *dev)
priv->link = PHY_DOWN;
priv->speed = 0;
priv->duplex = -1;
- netif_stop_queue(dev);
- netif_carrier_off(dev);
}
if (new_state && netif_msg_link(priv))
diff --git a/drivers/net/fs_enet/Makefile b/drivers/net/fs_enet/Makefile
index 1ffbe0756a0..d4a305ee345 100644
--- a/drivers/net/fs_enet/Makefile
+++ b/drivers/net/fs_enet/Makefile
@@ -8,12 +8,7 @@ fs_enet-$(CONFIG_FS_ENET_HAS_SCC) += mac-scc.o
fs_enet-$(CONFIG_FS_ENET_HAS_FEC) += mac-fec.o
fs_enet-$(CONFIG_FS_ENET_HAS_FCC) += mac-fcc.o
-ifeq ($(CONFIG_PPC_CPM_NEW_BINDING),y)
obj-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o
obj-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o
-else
-fs_enet-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o
-fs_enet-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o
-endif
fs_enet-objs := fs_enet-main.o $(fs_enet-m)
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 445763e5648..9a51ec8293c 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -36,26 +36,18 @@
#include <linux/fs.h>
#include <linux/platform_device.h>
#include <linux/phy.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
#include <linux/vmalloc.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
-#include <linux/of_gpio.h>
-#include <linux/of_platform.h>
-#endif
-
#include "fs_enet.h"
/*************************************************/
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
-static char version[] __devinitdata =
- DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")" "\n";
-#endif
-
MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>");
MODULE_DESCRIPTION("Freescale Ethernet Driver");
MODULE_LICENSE("GPL");
@@ -738,9 +730,6 @@ static void generic_adjust_link(struct net_device *dev)
if (!fep->oldlink) {
new_state = 1;
fep->oldlink = 1;
- netif_tx_schedule_all(dev);
- netif_carrier_on(dev);
- netif_start_queue(dev);
}
if (new_state)
@@ -750,8 +739,6 @@ static void generic_adjust_link(struct net_device *dev)
fep->oldlink = 0;
fep->oldspeed = 0;
fep->oldduplex = -1;
- netif_carrier_off(dev);
- netif_stop_queue(dev);
}
if (new_state && netif_msg_link(fep))
@@ -826,6 +813,8 @@ static int fs_enet_open(struct net_device *dev)
}
phy_start(fep->phydev);
+ netif_start_queue(dev);
+
return 0;
}
@@ -958,190 +947,6 @@ static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
extern int fs_mii_connect(struct net_device *dev);
extern void fs_mii_disconnect(struct net_device *dev);
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
-static struct net_device *fs_init_instance(struct device *dev,
- struct fs_platform_info *fpi)
-{
- struct net_device *ndev = NULL;
- struct fs_enet_private *fep = NULL;
- int privsize, i, r, err = 0, registered = 0;
-
- fpi->fs_no = fs_get_id(fpi);
- /* guard */
- if ((unsigned int)fpi->fs_no >= FS_MAX_INDEX)
- return ERR_PTR(-EINVAL);
-
- privsize = sizeof(*fep) + (sizeof(struct sk_buff **) *
- (fpi->rx_ring + fpi->tx_ring));
-
- ndev = alloc_etherdev(privsize);
- if (!ndev) {
- err = -ENOMEM;
- goto err;
- }
-
- fep = netdev_priv(ndev);
-
- fep->dev = dev;
- dev_set_drvdata(dev, ndev);
- fep->fpi = fpi;
- if (fpi->init_ioports)
- fpi->init_ioports((struct fs_platform_info *)fpi);
-
-#ifdef CONFIG_FS_ENET_HAS_FEC
- if (fs_get_fec_index(fpi->fs_no) >= 0)
- fep->ops = &fs_fec_ops;
-#endif
-
-#ifdef CONFIG_FS_ENET_HAS_SCC
- if (fs_get_scc_index(fpi->fs_no) >=0)
- fep->ops = &fs_scc_ops;
-#endif
-
-#ifdef CONFIG_FS_ENET_HAS_FCC
- if (fs_get_fcc_index(fpi->fs_no) >= 0)
- fep->ops = &fs_fcc_ops;
-#endif
-
- if (fep->ops == NULL) {
- printk(KERN_ERR DRV_MODULE_NAME
- ": %s No matching ops found (%d).\n",
- ndev->name, fpi->fs_no);
- err = -EINVAL;
- goto err;
- }
-
- r = (*fep->ops->setup_data)(ndev);
- if (r != 0) {
- printk(KERN_ERR DRV_MODULE_NAME
- ": %s setup_data failed\n",
- ndev->name);
- err = r;
- goto err;
- }
-
- /* point rx_skbuff, tx_skbuff */
- fep->rx_skbuff = (struct sk_buff **)&fep[1];
- fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;
-
- /* init locks */
- spin_lock_init(&fep->lock);
- spin_lock_init(&fep->tx_lock);
-
- /*
- * Set the Ethernet address.
- */
- for (i = 0; i < 6; i++)
- ndev->dev_addr[i] = fpi->macaddr[i];
-
- r = (*fep->ops->allocate_bd)(ndev);
-
- if (fep->ring_base == NULL) {
- printk(KERN_ERR DRV_MODULE_NAME
- ": %s buffer descriptor alloc failed (%d).\n", ndev->name, r);
- err = r;
- goto err;
- }
-
- /*
- * Set receive and transmit descriptor base.
- */
- fep->rx_bd_base = fep->ring_base;
- fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;
-
- /* initialize ring size variables */
- fep->tx_ring = fpi->tx_ring;
- fep->rx_ring = fpi->rx_ring;
-
- /*
- * The FEC Ethernet specific entries in the device structure.
- */
- ndev->open = fs_enet_open;
- ndev->hard_start_xmit = fs_enet_start_xmit;
- ndev->tx_timeout = fs_timeout;
- ndev->watchdog_timeo = 2 * HZ;
- ndev->stop = fs_enet_close;
- ndev->get_stats = fs_enet_get_stats;
- ndev->set_multicast_list = fs_set_multicast_list;
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
- ndev->poll_controller = fs_enet_netpoll;
-#endif
-
- netif_napi_add(ndev, &fep->napi,
- fs_enet_rx_napi, fpi->napi_weight);
-
- ndev->ethtool_ops = &fs_ethtool_ops;
- ndev->do_ioctl = fs_ioctl;
-
- init_timer(&fep->phy_timer_list);
-
- netif_carrier_off(ndev);
-
- err = register_netdev(ndev);
- if (err != 0) {
- printk(KERN_ERR DRV_MODULE_NAME
- ": %s register_netdev failed.\n", ndev->name);
- goto err;
- }
- registered = 1;
-
-
- return ndev;
-
-err:
- if (ndev != NULL) {
- if (registered)
- unregister_netdev(ndev);
-
- if (fep && fep->ops) {
- (*fep->ops->free_bd)(ndev);
- (*fep->ops->cleanup_data)(ndev);
- }
-
- free_netdev(ndev);
- }
-
- dev_set_drvdata(dev, NULL);
-
- return ERR_PTR(err);
-}
-
-static int fs_cleanup_instance(struct net_device *ndev)
-{
- struct fs_enet_private *fep;
- const struct fs_platform_info *fpi;
- struct device *dev;
-
- if (ndev == NULL)
- return -EINVAL;
-
- fep = netdev_priv(ndev);
- if (fep == NULL)
- return -EINVAL;
-
- fpi = fep->fpi;
-
- unregister_netdev(ndev);
-
- dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t),
- (void __force *)fep->ring_base, fep->ring_mem_addr);
-
- /* reset it */
- (*fep->ops->cleanup_data)(ndev);
-
- dev = fep->dev;
- if (dev != NULL) {
- dev_set_drvdata(dev, NULL);
- fep->dev = NULL;
- }
-
- free_netdev(ndev);
-
- return 0;
-}
-#endif
-
/**************************************************************************************/
/* handy pointer to the immap */
@@ -1168,7 +973,6 @@ static void cleanup_immap(void)
/**************************************************************************************/
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
static int __devinit find_phy(struct device_node *np,
struct fs_platform_info *fpi)
{
@@ -1408,121 +1212,6 @@ static void __exit fs_cleanup(void)
of_unregister_platform_driver(&fs_enet_driver);
cleanup_immap();
}
-#else
-static int __devinit fs_enet_probe(struct device *dev)
-{
- struct net_device *ndev;
-
- /* no fixup - no device */
- if (dev->platform_data == NULL) {
- printk(KERN_INFO "fs_enet: "
- "probe called with no platform data; "
- "remove unused devices\n");
- return -ENODEV;
- }
-
- ndev = fs_init_instance(dev, dev->platform_data);
- if (IS_ERR(ndev))
- return PTR_ERR(ndev);
- return 0;
-}
-
-static int fs_enet_remove(struct device *dev)
-{
- return fs_cleanup_instance(dev_get_drvdata(dev));
-}
-
-static struct device_driver fs_enet_fec_driver = {
- .name = "fsl-cpm-fec",
- .bus = &platform_bus_type,
- .probe = fs_enet_probe,
- .remove = fs_enet_remove,
-#ifdef CONFIG_PM
-/* .suspend = fs_enet_suspend, TODO */
-/* .resume = fs_enet_resume, TODO */
-#endif
-};
-
-static struct device_driver fs_enet_scc_driver = {
- .name = "fsl-cpm-scc",
- .bus = &platform_bus_type,
- .probe = fs_enet_probe,
- .remove = fs_enet_remove,
-#ifdef CONFIG_PM
-/* .suspend = fs_enet_suspend, TODO */
-/* .resume = fs_enet_resume, TODO */
-#endif
-};
-
-static struct device_driver fs_enet_fcc_driver = {
- .name = "fsl-cpm-fcc",
- .bus = &platform_bus_type,
- .probe = fs_enet_probe,
- .remove = fs_enet_remove,
-#ifdef CONFIG_PM
-/* .suspend = fs_enet_suspend, TODO */
-/* .resume = fs_enet_resume, TODO */
-#endif
-};
-
-static int __init fs_init(void)
-{
- int r;
-
- printk(KERN_INFO
- "%s", version);
-
- r = setup_immap();
- if (r != 0)
- return r;
-
-#ifdef CONFIG_FS_ENET_HAS_FCC
- /* let's insert mii stuff */
- r = fs_enet_mdio_bb_init();
-
- if (r != 0) {
- printk(KERN_ERR DRV_MODULE_NAME
- "BB PHY init failed.\n");
- return r;
- }
- r = driver_register(&fs_enet_fcc_driver);
- if (r != 0)
- goto err;
-#endif
-
-#ifdef CONFIG_FS_ENET_HAS_FEC
- r = fs_enet_mdio_fec_init();
- if (r != 0) {
- printk(KERN_ERR DRV_MODULE_NAME
- "FEC PHY init failed.\n");
- return r;
- }
-
- r = driver_register(&fs_enet_fec_driver);
- if (r != 0)
- goto err;
-#endif
-
-#ifdef CONFIG_FS_ENET_HAS_SCC
- r = driver_register(&fs_enet_scc_driver);
- if (r != 0)
- goto err;
-#endif
-
- return 0;
-err:
- cleanup_immap();
- return r;
-}
-
-static void __exit fs_cleanup(void)
-{
- driver_unregister(&fs_enet_fec_driver);
- driver_unregister(&fs_enet_fcc_driver);
- driver_unregister(&fs_enet_scc_driver);
- cleanup_immap();
-}
-#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
static void fs_enet_netpoll(struct net_device *dev)
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index e05389c49bb..db46d2e7232 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -138,10 +138,6 @@ struct fs_enet_private {
};
/***************************************************************************/
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
-int fs_enet_mdio_bb_init(void);
-int fs_enet_mdio_fec_init(void);
-#endif
void fs_init_bds(struct net_device *dev);
void fs_cleanup_bds(struct net_device *dev);
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index 8268b3535b3..0a97fc2d97e 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -33,6 +33,7 @@
#include <linux/fs.h>
#include <linux/platform_device.h>
#include <linux/phy.h>
+#include <linux/of_device.h>
#include <asm/immap_cpm2.h>
#include <asm/mpc8260.h>
@@ -42,10 +43,6 @@
#include <asm/irq.h>
#include <asm/uaccess.h>
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
-#include <asm/of_device.h>
-#endif
-
#include "fs_enet.h"
/*************************************************/
@@ -87,7 +84,6 @@ static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 op)
static int do_pd_setup(struct fs_enet_private *fep)
{
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
struct of_device *ofdev = to_of_device(fep->dev);
struct fs_platform_info *fpi = fep->fpi;
int ret = -EINVAL;
@@ -125,44 +121,6 @@ out_fccp:
iounmap(fep->fcc.fccp);
out:
return ret;
-#else
- struct platform_device *pdev = to_platform_device(fep->dev);
- struct resource *r;
-
- /* Fill out IRQ field */
- fep->interrupt = platform_get_irq(pdev, 0);
- if (fep->interrupt < 0)
- return -EINVAL;
-
- /* Attach the memory for the FCC Parameter RAM */
- r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_pram");
- fep->fcc.ep = ioremap(r->start, r->end - r->start + 1);
- if (fep->fcc.ep == NULL)
- return -EINVAL;
-
- r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_regs");
- fep->fcc.fccp = ioremap(r->start, r->end - r->start + 1);
- if (fep->fcc.fccp == NULL)
- return -EINVAL;
-
- if (fep->fpi->fcc_regs_c) {
- fep->fcc.fcccp = (void __iomem *)fep->fpi->fcc_regs_c;
- } else {
- r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "fcc_regs_c");
- fep->fcc.fcccp = ioremap(r->start,
- r->end - r->start + 1);
- }
-
- if (fep->fcc.fcccp == NULL)
- return -EINVAL;
-
- fep->fcc.mem = (void __iomem *)fep->fpi->mem_offset;
- if (fep->fcc.mem == NULL)
- return -EINVAL;
-
- return 0;
-#endif
}
#define FCC_NAPI_RX_EVENT_MSK (FCC_ENET_RXF | FCC_ENET_RXB)
@@ -173,17 +131,6 @@ out:
static int setup_data(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
- struct fs_platform_info *fpi = fep->fpi;
-
- fpi->cp_command = (fpi->cp_page << 26) |
- (fpi->cp_block << 21) |
- (12 << 6);
-
- fep->fcc.idx = fs_get_fcc_index(fpi->fs_no);
- if ((unsigned int)fep->fcc.idx >= 3) /* max 3 FCCs */
- return -EINVAL;
-#endif
if (do_pd_setup(fep) != 0)
return -EINVAL;
@@ -304,9 +251,6 @@ static void restart(struct net_device *dev)
fcc_enet_t __iomem *ep = fep->fcc.ep;
dma_addr_t rx_bd_base_phys, tx_bd_base_phys;
u16 paddrh, paddrm, paddrl;
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
- u16 mem_addr;
-#endif
const unsigned char *mac;
int i;
@@ -338,19 +282,10 @@ static void restart(struct net_device *dev)
* this area.
*/
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
W16(ep, fen_genfcc.fcc_riptr, fpi->dpram_offset);
W16(ep, fen_genfcc.fcc_tiptr, fpi->dpram_offset + 32);
W16(ep, fen_padptr, fpi->dpram_offset + 64);
-#else
- mem_addr = (u32) fep->fcc.mem; /* de-fixup dpram offset */
-
- W16(ep, fen_genfcc.fcc_riptr, (mem_addr & 0xffff));
- W16(ep, fen_genfcc.fcc_tiptr, ((mem_addr + 32) & 0xffff));
-
- W16(ep, fen_padptr, mem_addr + 64);
-#endif
/* fill with special symbol... */
memset_io(fep->fcc.mem + fpi->dpram_offset + 64, 0x88, 32);
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index 8a311d1e435..0a7d1c5c652 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -32,6 +32,7 @@
#include <linux/bitops.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
+#include <linux/of_device.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -43,10 +44,6 @@
#include <asm/cpm1.h>
#endif
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
-#include <asm/of_device.h>
-#endif
-
#include "fs_enet.h"
#include "fec.h"
@@ -99,7 +96,6 @@ static int whack_reset(fec_t __iomem *fecp)
static int do_pd_setup(struct fs_enet_private *fep)
{
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
struct of_device *ofdev = to_of_device(fep->dev);
fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL);
@@ -111,23 +107,6 @@ static int do_pd_setup(struct fs_enet_private *fep)
return -EINVAL;
return 0;
-#else
- struct platform_device *pdev = to_platform_device(fep->dev);
- struct resource *r;
-
- /* Fill out IRQ field */
- fep->interrupt = platform_get_irq_byname(pdev,"interrupt");
- if (fep->interrupt < 0)
- return -EINVAL;
-
- r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
- fep->fec.fecp = ioremap(r->start, r->end - r->start + 1);
-
- if(fep->fec.fecp == NULL)
- return -EINVAL;
-
- return 0;
-#endif
}
#define FEC_NAPI_RX_EVENT_MSK (FEC_ENET_RXF | FEC_ENET_RXB)
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index e3557eca7b6..029b3c7ef29 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -32,6 +32,7 @@
#include <linux/bitops.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
+#include <linux/of_platform.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -43,10 +44,6 @@
#include <asm/cpm1.h>
#endif
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
-#include <linux/of_platform.h>
-#endif
-
#include "fs_enet.h"
/*************************************************/
@@ -99,7 +96,6 @@ static inline int scc_cr_cmd(struct fs_enet_private *fep, u32 op)
static int do_pd_setup(struct fs_enet_private *fep)
{
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
struct of_device *ofdev = to_of_device(fep->dev);
fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL);
@@ -115,27 +111,6 @@ static int do_pd_setup(struct fs_enet_private *fep)
iounmap(fep->scc.sccp);
return -EINVAL;
}
-#else
- struct platform_device *pdev = to_platform_device(fep->dev);
- struct resource *r;
-
- /* Fill out IRQ field */
- fep->interrupt = platform_get_irq_byname(pdev, "interrupt");
- if (fep->interrupt < 0)
- return -EINVAL;
-
- r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
- fep->scc.sccp = ioremap(r->start, r->end - r->start + 1);
-
- if (fep->scc.sccp == NULL)
- return -EINVAL;
-
- r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram");
- fep->scc.ep = ioremap(r->start, r->end - r->start + 1);
-
- if (fep->scc.ep == NULL)
- return -EINVAL;
-#endif
return 0;
}
@@ -149,16 +124,6 @@ static int setup_data(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
- struct fs_platform_info *fpi = fep->fpi;
-
- fep->scc.idx = fs_get_scc_index(fpi->fs_no);
- if ((unsigned int)fep->fcc.idx >= 4) /* max 4 SCCs */
- return -EINVAL;
-
- fpi->cp_command = fep->fcc.idx << 6;
-#endif
-
do_pd_setup(fep);
fep->scc.hthi = 0;
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index 1620030cd33..be4b72f4f49 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -22,10 +22,7 @@
#include <linux/mii.h>
#include <linux/platform_device.h>
#include <linux/mdio-bitbang.h>
-
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
#include <linux/of_platform.h>
-#endif
#include "fs_enet.h"
@@ -110,7 +107,6 @@ static struct mdiobb_ops bb_ops = {
.get_mdio_data = mdio_read,
};
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
struct device_node *np)
{
@@ -271,106 +267,3 @@ static void fs_enet_mdio_bb_exit(void)
module_init(fs_enet_mdio_bb_init);
module_exit(fs_enet_mdio_bb_exit);
-#else
-static int __devinit fs_mii_bitbang_init(struct bb_info *bitbang,
- struct fs_mii_bb_platform_info *fmpi)
-{
- bitbang->dir = (u32 __iomem *)fmpi->mdio_dir.offset;
- bitbang->dat = (u32 __iomem *)fmpi->mdio_dat.offset;
- bitbang->mdio_msk = 1U << (31 - fmpi->mdio_dat.bit);
- bitbang->mdc_msk = 1U << (31 - fmpi->mdc_dat.bit);
-
- return 0;
-}
-
-static int __devinit fs_enet_mdio_probe(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct fs_mii_bb_platform_info *pdata;
- struct mii_bus *new_bus;
- struct bb_info *bitbang;
- int err = 0;
-
- if (NULL == dev)
- return -EINVAL;
-
- bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
-
- if (NULL == bitbang)
- return -ENOMEM;
-
- bitbang->ctrl.ops = &bb_ops;
-
- new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
-
- if (NULL == new_bus)
- return -ENOMEM;
-
- new_bus->name = "BB MII Bus",
- snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
-
- new_bus->phy_mask = ~0x9;
- pdata = (struct fs_mii_bb_platform_info *)pdev->dev.platform_data;
-
- if (NULL == pdata) {
- printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
- return -ENODEV;
- }
-
- /*set up workspace*/
- fs_mii_bitbang_init(bitbang, pdata);
-
- new_bus->priv = bitbang;
-
- new_bus->irq = pdata->irq;
-
- new_bus->dev = dev;
- dev_set_drvdata(dev, new_bus);
-
- err = mdiobus_register(new_bus);
-
- if (0 != err) {
- printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
- new_bus->name);
- goto bus_register_fail;
- }
-
- return 0;
-
-bus_register_fail:
- free_mdio_bitbang(new_bus);
- kfree(bitbang);
-
- return err;
-}
-
-static int fs_enet_mdio_remove(struct device *dev)
-{
- struct mii_bus *bus = dev_get_drvdata(dev);
-
- mdiobus_unregister(bus);
-
- dev_set_drvdata(dev, NULL);
-
- free_mdio_bitbang(bus);
-
- return 0;
-}
-
-static struct device_driver fs_enet_bb_mdio_driver = {
- .name = "fsl-bb-mdio",
- .bus = &platform_bus_type,
- .probe = fs_enet_mdio_probe,
- .remove = fs_enet_mdio_remove,
-};
-
-int fs_enet_mdio_bb_init(void)
-{
- return driver_register(&fs_enet_bb_mdio_driver);
-}
-
-void fs_enet_mdio_bb_exit(void)
-{
- driver_unregister(&fs_enet_bb_mdio_driver);
-}
-#endif
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index 8f6a43b0e0f..695f74cc439 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -31,15 +31,12 @@
#include <linux/ethtool.h>
#include <linux/bitops.h>
#include <linux/platform_device.h>
+#include <linux/of_platform.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
-#include <linux/of_platform.h>
-#endif
-
#include "fs_enet.h"
#include "fec.h"
@@ -51,52 +48,6 @@
#define FEC_MII_LOOPS 10000
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
-static int match_has_phy (struct device *dev, void* data)
-{
- struct platform_device* pdev = container_of(dev, struct platform_device, dev);
- struct fs_platform_info* fpi;
- if(strcmp(pdev->name, (char*)data))
- {
- return 0;
- }
-
- fpi = pdev->dev.platform_data;
- if((fpi)&&(fpi->has_phy))
- return 1;
- return 0;
-}
-
-static int fs_mii_fec_init(struct fec_info* fec, struct fs_mii_fec_platform_info *fmpi)
-{
- struct resource *r;
- fec_t __iomem *fecp;
- char* name = "fsl-cpm-fec";
-
- /* we need fec in order to be useful */
- struct platform_device *fec_pdev =
- container_of(bus_find_device(&platform_bus_type, NULL, name, match_has_phy),
- struct platform_device, dev);
-
- if(fec_pdev == NULL) {
- printk(KERN_ERR"Unable to find PHY for %s", name);
- return -ENODEV;
- }
-
- r = platform_get_resource_byname(fec_pdev, IORESOURCE_MEM, "regs");
-
- fec->fecp = fecp = ioremap(r->start,sizeof(fec_t));
- fec->mii_speed = fmpi->mii_speed;
-
- setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
- setbits32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
- out_be32(&fecp->fec_ievent, FEC_ENET_MII);
- out_be32(&fecp->fec_mii_speed, fec->mii_speed);
-
- return 0;
-}
-#endif
-
static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
{
struct fec_info* fec = bus->priv;
@@ -151,7 +102,6 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus)
return 0;
}
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
{
const u32 *data;
@@ -286,95 +236,3 @@ static void fs_enet_mdio_fec_exit(void)
module_init(fs_enet_mdio_fec_init);
module_exit(fs_enet_mdio_fec_exit);
-#else
-static int __devinit fs_enet_fec_mdio_probe(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct fs_mii_fec_platform_info *pdata;
- struct mii_bus *new_bus;
- struct fec_info *fec;
- int err = 0;
- if (NULL == dev)
- return -EINVAL;
- new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
-
- if (NULL == new_bus)
- return -ENOMEM;
-
- fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL);
-
- if (NULL == fec)
- return -ENOMEM;
-
- new_bus->name = "FEC MII Bus",
- new_bus->read = &fs_enet_fec_mii_read,
- new_bus->write = &fs_enet_fec_mii_write,
- new_bus->reset = &fs_enet_fec_mii_reset,
- snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
-
- pdata = (struct fs_mii_fec_platform_info *)pdev->dev.platform_data;
-
- if (NULL == pdata) {
- printk(KERN_ERR "fs_enet FEC mdio %d: Missing platform data!\n", pdev->id);
- return -ENODEV;
- }
-
- /*set up workspace*/
-
- fs_mii_fec_init(fec, pdata);
- new_bus->priv = fec;
-
- new_bus->irq = pdata->irq;
-
- new_bus->dev = dev;
- dev_set_drvdata(dev, new_bus);
-
- err = mdiobus_register(new_bus);
-
- if (0 != err) {
- printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
- new_bus->name);
- goto bus_register_fail;
- }
-
- return 0;
-
-bus_register_fail:
- kfree(new_bus);
-
- return err;
-}
-
-
-static int fs_enet_fec_mdio_remove(struct device *dev)
-{
- struct mii_bus *bus = dev_get_drvdata(dev);
-
- mdiobus_unregister(bus);
-
- dev_set_drvdata(dev, NULL);
- kfree(bus->priv);
-
- bus->priv = NULL;
- kfree(bus);
-
- return 0;
-}
-
-static struct device_driver fs_enet_fec_mdio_driver = {
- .name = "fsl-cpm-fec-mdio",
- .bus = &platform_bus_type,
- .probe = fs_enet_fec_mdio_probe,
- .remove = fs_enet_fec_mdio_remove,
-};
-
-int fs_enet_mdio_fec_init(void)
-{
- return driver_register(&fs_enet_fec_mdio_driver);
-}
-
-void fs_enet_mdio_fec_exit(void)
-{
- driver_unregister(&fs_enet_fec_mdio_driver);
-}
-#endif
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 39b45e901be..b8394cf134e 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -134,6 +134,9 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int l
static void gfar_vlan_rx_register(struct net_device *netdev,
struct vlan_group *grp);
void gfar_halt(struct net_device *dev);
+#ifdef CONFIG_PM
+static void gfar_halt_nodisable(struct net_device *dev);
+#endif
void gfar_start(struct net_device *dev);
static void gfar_clear_exact_match(struct net_device *dev);
static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr);
@@ -207,6 +210,7 @@ static int gfar_probe(struct platform_device *pdev)
spin_lock_init(&priv->txlock);
spin_lock_init(&priv->rxlock);
+ spin_lock_init(&priv->bflock);
platform_set_drvdata(pdev, dev);
@@ -378,6 +382,103 @@ static int gfar_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+static int gfar_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
+ u32 tempval;
+
+ int magic_packet = priv->wol_en &&
+ (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+
+ netif_device_detach(dev);
+
+ if (netif_running(dev)) {
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
+
+ gfar_halt_nodisable(dev);
+
+ /* Disable Tx, and Rx if wake-on-LAN is disabled. */
+ tempval = gfar_read(&priv->regs->maccfg1);
+
+ tempval &= ~MACCFG1_TX_EN;
+
+ if (!magic_packet)
+ tempval &= ~MACCFG1_RX_EN;
+
+ gfar_write(&priv->regs->maccfg1, tempval);
+
+ spin_unlock(&priv->rxlock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
+
+#ifdef CONFIG_GFAR_NAPI
+ napi_disable(&priv->napi);
+#endif
+
+ if (magic_packet) {
+ /* Enable interrupt on Magic Packet */
+ gfar_write(&priv->regs->imask, IMASK_MAG);
+
+ /* Enable Magic Packet mode */
+ tempval = gfar_read(&priv->regs->maccfg2);
+ tempval |= MACCFG2_MPEN;
+ gfar_write(&priv->regs->maccfg2, tempval);
+ } else {
+ phy_stop(priv->phydev);
+ }
+ }
+
+ return 0;
+}
+
+static int gfar_resume(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
+ u32 tempval;
+ int magic_packet = priv->wol_en &&
+ (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+
+ if (!netif_running(dev)) {
+ netif_device_attach(dev);
+ return 0;
+ }
+
+ if (!magic_packet && priv->phydev)
+ phy_start(priv->phydev);
+
+ /* Disable Magic Packet mode, in case something
+ * else woke us up.
+ */
+
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
+
+ tempval = gfar_read(&priv->regs->maccfg2);
+ tempval &= ~MACCFG2_MPEN;
+ gfar_write(&priv->regs->maccfg2, tempval);
+
+ gfar_start(dev);
+
+ spin_unlock(&priv->rxlock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
+
+ netif_device_attach(dev);
+
+#ifdef CONFIG_GFAR_NAPI
+ napi_enable(&priv->napi);
+#endif
+
+ return 0;
+}
+#else
+#define gfar_suspend NULL
+#define gfar_resume NULL
+#endif
/* Reads the controller's registers to determine what interface
* connects it to the PHY.
@@ -534,8 +635,9 @@ static void init_registers(struct net_device *dev)
}
+#ifdef CONFIG_PM
/* Halt the receive and transmit queues */
-void gfar_halt(struct net_device *dev)
+static void gfar_halt_nodisable(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
struct gfar __iomem *regs = priv->regs;
@@ -558,6 +660,15 @@ void gfar_halt(struct net_device *dev)
(IEVENT_GRSC | IEVENT_GTSC)))
cpu_relax();
}
+}
+#endif
+
+/* Halt the receive and transmit queues */
+void gfar_halt(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar __iomem *regs = priv->regs;
+ u32 tempval;
/* Disable Rx and Tx */
tempval = gfar_read(&regs->maccfg1);
@@ -1909,7 +2020,12 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
u32 events = gfar_read(&priv->regs->ievent);
/* Clear IEVENT */
- gfar_write(&priv->regs->ievent, IEVENT_ERR_MASK);
+ gfar_write(&priv->regs->ievent, events & IEVENT_ERR_MASK);
+
+ /* Magic Packet is not an error. */
+ if ((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
+ (events & IEVENT_MAG))
+ events &= ~IEVENT_MAG;
/* Hmm... */
if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv))
@@ -1977,6 +2093,8 @@ MODULE_ALIAS("platform:fsl-gianfar");
static struct platform_driver gfar_driver = {
.probe = gfar_probe,
.remove = gfar_remove,
+ .suspend = gfar_suspend,
+ .resume = gfar_resume,
.driver = {
.name = "fsl-gianfar",
.owner = THIS_MODULE,
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index bead71cb2b1..d59df98bd63 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -157,6 +157,7 @@ extern const char gfar_driver_version[];
#define MACCFG2_GMII 0x00000200
#define MACCFG2_HUGEFRAME 0x00000020
#define MACCFG2_LENGTHCHECK 0x00000010
+#define MACCFG2_MPEN 0x00000008
#define ECNTRL_INIT_SETTINGS 0x00001000
#define ECNTRL_TBI_MODE 0x00000020
@@ -229,6 +230,7 @@ extern const char gfar_driver_version[];
#define IEVENT_CRL 0x00020000
#define IEVENT_XFUN 0x00010000
#define IEVENT_RXB0 0x00008000
+#define IEVENT_MAG 0x00000800
#define IEVENT_GRSC 0x00000100
#define IEVENT_RXF0 0x00000080
#define IEVENT_FIR 0x00000008
@@ -241,7 +243,8 @@ extern const char gfar_driver_version[];
#define IEVENT_ERR_MASK \
(IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \
IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \
- | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR)
+ | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR \
+ | IEVENT_MAG)
#define IMASK_INIT_CLEAR 0x00000000
#define IMASK_BABR 0x80000000
@@ -259,6 +262,7 @@ extern const char gfar_driver_version[];
#define IMASK_CRL 0x00020000
#define IMASK_XFUN 0x00010000
#define IMASK_RXB0 0x00008000
+#define IMASK_MAG 0x00000800
#define IMASK_GTSC 0x00000100
#define IMASK_RXFEN0 0x00000080
#define IMASK_FIR 0x00000008
@@ -726,10 +730,14 @@ struct gfar_private {
unsigned int fifo_starve;
unsigned int fifo_starve_off;
+ /* Bitfield update lock */
+ spinlock_t bflock;
+
unsigned char vlan_enable:1,
rx_csum_enable:1,
extended_hash:1,
- bd_stash_en:1;
+ bd_stash_en:1,
+ wol_en:1; /* Wake-on-LAN enabled */
unsigned short padding;
unsigned int interruptTransmit;
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 6007147cc1e..fb7d3ccc0fd 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -479,14 +479,13 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
{
struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
int err = 0;
if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
return -EOPNOTSUPP;
if (dev->flags & IFF_UP) {
- unsigned long flags;
-
/* Halt TX and RX, and process the frames which
* have already been received */
spin_lock_irqsave(&priv->txlock, flags);
@@ -502,7 +501,9 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
stop_gfar(dev);
}
+ spin_lock_irqsave(&priv->bflock, flags);
priv->rx_csum_enable = data;
+ spin_unlock_irqrestore(&priv->bflock, flags);
if (dev->flags & IFF_UP)
err = startup_gfar(dev);
@@ -564,6 +565,38 @@ static void gfar_set_msglevel(struct net_device *dev, uint32_t data)
priv->msg_enable = data;
}
+#ifdef CONFIG_PM
+static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+
+ if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) {
+ wol->supported = WAKE_MAGIC;
+ wol->wolopts = priv->wol_en ? WAKE_MAGIC : 0;
+ } else {
+ wol->supported = wol->wolopts = 0;
+ }
+}
+
+static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
+
+ if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
+ wol->wolopts != 0)
+ return -EINVAL;
+
+ if (wol->wolopts & ~WAKE_MAGIC)
+ return -EINVAL;
+
+ spin_lock_irqsave(&priv->bflock, flags);
+ priv->wol_en = wol->wolopts & WAKE_MAGIC ? 1 : 0;
+ spin_unlock_irqrestore(&priv->bflock, flags);
+
+ return 0;
+}
+#endif
const struct ethtool_ops gfar_ethtool_ops = {
.get_settings = gfar_gsettings,
@@ -585,4 +618,8 @@ const struct ethtool_ops gfar_ethtool_ops = {
.set_tx_csum = gfar_set_tx_csum,
.get_msglevel = gfar_get_msglevel,
.set_msglevel = gfar_set_msglevel,
+#ifdef CONFIG_PM
+ .get_wol = gfar_get_wol,
+ .set_wol = gfar_set_wol,
+#endif
};
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index b6500b2aacf..58f4b1d7bf1 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -123,6 +123,7 @@ static LIST_HEAD(bpq_devices);
* off into a separate class since they always nest.
*/
static struct lock_class_key bpq_netdev_xmit_lock_key;
+static struct lock_class_key bpq_netdev_addr_lock_key;
static void bpq_set_lockdep_class_one(struct net_device *dev,
struct netdev_queue *txq,
@@ -133,6 +134,7 @@ static void bpq_set_lockdep_class_one(struct net_device *dev,
static void bpq_set_lockdep_class(struct net_device *dev)
{
+ lockdep_set_class(&dev->addr_list_lock, &bpq_netdev_addr_lock_key);
netdev_for_each_tx_queue(dev, bpq_set_lockdep_class_one, NULL);
}
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index c2c4f49d757..8239939554b 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -262,7 +262,7 @@ static int __init hpp_probe1(struct net_device *dev, int ioaddr)
}
outw(Perf_Page, ioaddr + HP_PAGING);
- NS8390_init(dev, 0);
+ NS8390p_init(dev, 0);
/* Leave the 8390 and HP chip reset. */
outw(inw(ioaddr + HPP_OPTION) & ~EnableIRQ, ioaddr + HPP_OPTION);
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index 8281209eded..0a8c64930ad 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -389,7 +389,7 @@ static void __init
hp_init_card(struct net_device *dev)
{
int irq = dev->irq;
- NS8390_init(dev, 0);
+ NS8390p_init(dev, 0);
outb_p(irqmap[irq&0x0f] | HP_RUN,
dev->base_addr - NIC_OFFSET + HP_CONFIGURE);
return;
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 00527805e4f..e5a6e2e8454 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -33,6 +33,7 @@
*/
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/ioport.h>
@@ -52,7 +53,9 @@
#include <asm/hvcall.h>
#include <asm/atomic.h>
#include <asm/vio.h>
+#include <asm/iommu.h>
#include <asm/uaccess.h>
+#include <asm/firmware.h>
#include <linux/seq_file.h>
#include "ibmveth.h"
@@ -94,8 +97,10 @@ static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter);
static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter);
static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance);
static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter);
+static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev);
static struct kobj_type ktype_veth_pool;
+
#ifdef CONFIG_PROC_FS
#define IBMVETH_PROC_DIR "ibmveth"
static struct proc_dir_entry *ibmveth_proc_dir;
@@ -226,16 +231,16 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
u32 i;
u32 count = pool->size - atomic_read(&pool->available);
u32 buffers_added = 0;
+ struct sk_buff *skb;
+ unsigned int free_index, index;
+ u64 correlator;
+ unsigned long lpar_rc;
+ dma_addr_t dma_addr;
mb();
for(i = 0; i < count; ++i) {
- struct sk_buff *skb;
- unsigned int free_index, index;
- u64 correlator;
union ibmveth_buf_desc desc;
- unsigned long lpar_rc;
- dma_addr_t dma_addr;
skb = alloc_skb(pool->buff_size, GFP_ATOMIC);
@@ -255,6 +260,9 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
dma_addr = dma_map_single(&adapter->vdev->dev, skb->data,
pool->buff_size, DMA_FROM_DEVICE);
+ if (dma_mapping_error(dma_addr))
+ goto failure;
+
pool->free_map[free_index] = IBM_VETH_INVALID_MAP;
pool->dma_addr[index] = dma_addr;
pool->skbuff[index] = skb;
@@ -267,20 +275,9 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
- if(lpar_rc != H_SUCCESS) {
- pool->free_map[free_index] = index;
- pool->skbuff[index] = NULL;
- if (pool->consumer_index == 0)
- pool->consumer_index = pool->size - 1;
- else
- pool->consumer_index--;
- dma_unmap_single(&adapter->vdev->dev,
- pool->dma_addr[index], pool->buff_size,
- DMA_FROM_DEVICE);
- dev_kfree_skb_any(skb);
- adapter->replenish_add_buff_failure++;
- break;
- } else {
+ if (lpar_rc != H_SUCCESS)
+ goto failure;
+ else {
buffers_added++;
adapter->replenish_add_buff_success++;
}
@@ -288,6 +285,24 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
mb();
atomic_add(buffers_added, &(pool->available));
+ return;
+
+failure:
+ pool->free_map[free_index] = index;
+ pool->skbuff[index] = NULL;
+ if (pool->consumer_index == 0)
+ pool->consumer_index = pool->size - 1;
+ else
+ pool->consumer_index--;
+ if (!dma_mapping_error(dma_addr))
+ dma_unmap_single(&adapter->vdev->dev,
+ pool->dma_addr[index], pool->buff_size,
+ DMA_FROM_DEVICE);
+ dev_kfree_skb_any(skb);
+ adapter->replenish_add_buff_failure++;
+
+ mb();
+ atomic_add(buffers_added, &(pool->available));
}
/* replenish routine */
@@ -297,7 +312,7 @@ static void ibmveth_replenish_task(struct ibmveth_adapter *adapter)
adapter->replenish_task_cycles++;
- for(i = 0; i < IbmVethNumBufferPools; i++)
+ for (i = (IbmVethNumBufferPools - 1); i >= 0; i--)
if(adapter->rx_buff_pool[i].active)
ibmveth_replenish_buffer_pool(adapter,
&adapter->rx_buff_pool[i]);
@@ -472,6 +487,18 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
if (adapter->rx_buff_pool[i].active)
ibmveth_free_buffer_pool(adapter,
&adapter->rx_buff_pool[i]);
+
+ if (adapter->bounce_buffer != NULL) {
+ if (!dma_mapping_error(adapter->bounce_buffer_dma)) {
+ dma_unmap_single(&adapter->vdev->dev,
+ adapter->bounce_buffer_dma,
+ adapter->netdev->mtu + IBMVETH_BUFF_OH,
+ DMA_BIDIRECTIONAL);
+ adapter->bounce_buffer_dma = DMA_ERROR_CODE;
+ }
+ kfree(adapter->bounce_buffer);
+ adapter->bounce_buffer = NULL;
+ }
}
static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter,
@@ -607,6 +634,24 @@ static int ibmveth_open(struct net_device *netdev)
return rc;
}
+ adapter->bounce_buffer =
+ kmalloc(netdev->mtu + IBMVETH_BUFF_OH, GFP_KERNEL);
+ if (!adapter->bounce_buffer) {
+ ibmveth_error_printk("unable to allocate bounce buffer\n");
+ ibmveth_cleanup(adapter);
+ napi_disable(&adapter->napi);
+ return -ENOMEM;
+ }
+ adapter->bounce_buffer_dma =
+ dma_map_single(&adapter->vdev->dev, adapter->bounce_buffer,
+ netdev->mtu + IBMVETH_BUFF_OH, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(adapter->bounce_buffer_dma)) {
+ ibmveth_error_printk("unable to map bounce buffer\n");
+ ibmveth_cleanup(adapter);
+ napi_disable(&adapter->napi);
+ return -ENOMEM;
+ }
+
ibmveth_debug_printk("initial replenish cycle\n");
ibmveth_interrupt(netdev->irq, netdev);
@@ -853,10 +898,12 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
unsigned int tx_packets = 0;
unsigned int tx_send_failed = 0;
unsigned int tx_map_failed = 0;
+ int used_bounce = 0;
+ unsigned long data_dma_addr;
desc.fields.flags_len = IBMVETH_BUF_VALID | skb->len;
- desc.fields.address = dma_map_single(&adapter->vdev->dev, skb->data,
- skb->len, DMA_TO_DEVICE);
+ data_dma_addr = dma_map_single(&adapter->vdev->dev, skb->data,
+ skb->len, DMA_TO_DEVICE);
if (skb->ip_summed == CHECKSUM_PARTIAL &&
ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) {
@@ -875,12 +922,16 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
buf[1] = 0;
}
- if (dma_mapping_error(desc.fields.address)) {
- ibmveth_error_printk("tx: unable to map xmit buffer\n");
+ if (dma_mapping_error(data_dma_addr)) {
+ if (!firmware_has_feature(FW_FEATURE_CMO))
+ ibmveth_error_printk("tx: unable to map xmit buffer\n");
+ skb_copy_from_linear_data(skb, adapter->bounce_buffer,
+ skb->len);
+ desc.fields.address = adapter->bounce_buffer_dma;
tx_map_failed++;
- tx_dropped++;
- goto out;
- }
+ used_bounce = 1;
+ } else
+ desc.fields.address = data_dma_addr;
/* send the frame. Arbitrarily set retrycount to 1024 */
correlator = 0;
@@ -904,8 +955,9 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
netdev->trans_start = jiffies;
}
- dma_unmap_single(&adapter->vdev->dev, desc.fields.address,
- skb->len, DMA_TO_DEVICE);
+ if (!used_bounce)
+ dma_unmap_single(&adapter->vdev->dev, data_dma_addr,
+ skb->len, DMA_TO_DEVICE);
out: spin_lock_irqsave(&adapter->stats_lock, flags);
netdev->stats.tx_dropped += tx_dropped;
@@ -1053,9 +1105,9 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
{
struct ibmveth_adapter *adapter = dev->priv;
+ struct vio_dev *viodev = adapter->vdev;
int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH;
- int reinit = 0;
- int i, rc;
+ int i;
if (new_mtu < IBMVETH_MAX_MTU)
return -EINVAL;
@@ -1067,23 +1119,34 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
if (i == IbmVethNumBufferPools)
return -EINVAL;
+ /* Deactivate all the buffer pools so that the next loop can activate
+ only the buffer pools necessary to hold the new MTU */
+ for (i = 0; i < IbmVethNumBufferPools; i++)
+ if (adapter->rx_buff_pool[i].active) {
+ ibmveth_free_buffer_pool(adapter,
+ &adapter->rx_buff_pool[i]);
+ adapter->rx_buff_pool[i].active = 0;
+ }
+
/* Look for an active buffer pool that can hold the new MTU */
for(i = 0; i<IbmVethNumBufferPools; i++) {
- if (!adapter->rx_buff_pool[i].active) {
- adapter->rx_buff_pool[i].active = 1;
- reinit = 1;
- }
+ adapter->rx_buff_pool[i].active = 1;
if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) {
- if (reinit && netif_running(adapter->netdev)) {
+ if (netif_running(adapter->netdev)) {
adapter->pool_config = 1;
ibmveth_close(adapter->netdev);
adapter->pool_config = 0;
dev->mtu = new_mtu;
- if ((rc = ibmveth_open(adapter->netdev)))
- return rc;
- } else
- dev->mtu = new_mtu;
+ vio_cmo_set_dev_desired(viodev,
+ ibmveth_get_desired_dma
+ (viodev));
+ return ibmveth_open(adapter->netdev);
+ }
+ dev->mtu = new_mtu;
+ vio_cmo_set_dev_desired(viodev,
+ ibmveth_get_desired_dma
+ (viodev));
return 0;
}
}
@@ -1098,6 +1161,46 @@ static void ibmveth_poll_controller(struct net_device *dev)
}
#endif
+/**
+ * ibmveth_get_desired_dma - Calculate IO memory desired by the driver
+ *
+ * @vdev: struct vio_dev for the device whose desired IO mem is to be returned
+ *
+ * Return value:
+ * Number of bytes of IO data the driver will need to perform well.
+ */
+static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev)
+{
+ struct net_device *netdev = dev_get_drvdata(&vdev->dev);
+ struct ibmveth_adapter *adapter;
+ unsigned long ret;
+ int i;
+ int rxqentries = 1;
+
+ /* netdev inits at probe time along with the structures we need below*/
+ if (netdev == NULL)
+ return IOMMU_PAGE_ALIGN(IBMVETH_IO_ENTITLEMENT_DEFAULT);
+
+ adapter = netdev_priv(netdev);
+
+ ret = IBMVETH_BUFF_LIST_SIZE + IBMVETH_FILT_LIST_SIZE;
+ ret += IOMMU_PAGE_ALIGN(netdev->mtu);
+
+ for (i = 0; i < IbmVethNumBufferPools; i++) {
+ /* add the size of the active receive buffers */
+ if (adapter->rx_buff_pool[i].active)
+ ret +=
+ adapter->rx_buff_pool[i].size *
+ IOMMU_PAGE_ALIGN(adapter->rx_buff_pool[i].
+ buff_size);
+ rxqentries += adapter->rx_buff_pool[i].size;
+ }
+ /* add the size of the receive queue entries */
+ ret += IOMMU_PAGE_ALIGN(rxqentries * sizeof(struct ibmveth_rx_q_entry));
+
+ return ret;
+}
+
static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
{
int rc, i;
@@ -1242,6 +1345,8 @@ static int __devexit ibmveth_remove(struct vio_dev *dev)
ibmveth_proc_unregister_adapter(adapter);
free_netdev(netdev);
+ dev_set_drvdata(&dev->dev, NULL);
+
return 0;
}
@@ -1402,14 +1507,15 @@ const char * buf, size_t count)
return -EPERM;
}
- pool->active = 0;
if (netif_running(netdev)) {
adapter->pool_config = 1;
ibmveth_close(netdev);
+ pool->active = 0;
adapter->pool_config = 0;
if ((rc = ibmveth_open(netdev)))
return rc;
}
+ pool->active = 0;
}
} else if (attr == &veth_num_attr) {
if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT)
@@ -1485,6 +1591,7 @@ static struct vio_driver ibmveth_driver = {
.id_table = ibmveth_device_table,
.probe = ibmveth_probe,
.remove = ibmveth_remove,
+ .get_desired_dma = ibmveth_get_desired_dma,
.driver = {
.name = ibmveth_driver_name,
.owner = THIS_MODULE,
diff --git a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h
index 41f61cd1885..d2818694875 100644
--- a/drivers/net/ibmveth.h
+++ b/drivers/net/ibmveth.h
@@ -93,9 +93,12 @@ static inline long h_illan_attributes(unsigned long unit_address,
plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac)
#define IbmVethNumBufferPools 5
+#define IBMVETH_IO_ENTITLEMENT_DEFAULT 4243456 /* MTU of 1500 needs 4.2Mb */
#define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */
#define IBMVETH_MAX_MTU 68
#define IBMVETH_MAX_POOL_COUNT 4096
+#define IBMVETH_BUFF_LIST_SIZE 4096
+#define IBMVETH_FILT_LIST_SIZE 4096
#define IBMVETH_MAX_BUF_SIZE (1024 * 128)
static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 };
@@ -143,6 +146,8 @@ struct ibmveth_adapter {
struct ibmveth_rx_q rx_queue;
int pool_config;
int rx_csum;
+ void *bounce_buffer;
+ dma_addr_t bounce_buffer_dma;
/* adapter specific stats */
u64 replenish_task_cycles;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 1b7cb29fe68..b602c4dd0d1 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -385,7 +385,7 @@ static void igb_configure_msix(struct igb_adapter *adapter)
for (i = 0; i < adapter->num_rx_queues; i++) {
struct igb_ring *rx_ring = &adapter->rx_ring[i];
- rx_ring->buddy = 0;
+ rx_ring->buddy = NULL;
igb_assign_vector(adapter, i, IGB_N0_QUEUE, vector++);
adapter->eims_enable_mask |= rx_ring->eims_value;
if (rx_ring->itr_val)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index be7b723c924..e5f3da8468c 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -70,8 +70,6 @@ static struct pci_device_id ixgbe_pci_tbl[] = {
board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT),
board_82598 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT_DUAL_PORT),
- board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_CX4),
board_82598 },
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 0496d16f9de..daba82bbcb5 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -164,9 +164,7 @@ static void macb_handle_link_change(struct net_device *dev)
}
if (phydev->link != bp->link) {
- if (phydev->link)
- netif_tx_schedule_all(dev);
- else {
+ if (!phydev->link) {
bp->speed = 0;
bp->duplex = -1;
}
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index efbc15567dd..42394505bb5 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -276,6 +276,7 @@ static int macvlan_change_mtu(struct net_device *dev, int new_mtu)
* separate class since they always nest.
*/
static struct lock_class_key macvlan_netdev_xmit_lock_key;
+static struct lock_class_key macvlan_netdev_addr_lock_key;
#define MACVLAN_FEATURES \
(NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
@@ -295,6 +296,8 @@ static void macvlan_set_lockdep_class_one(struct net_device *dev,
static void macvlan_set_lockdep_class(struct net_device *dev)
{
+ lockdep_set_class(&dev->addr_list_lock,
+ &macvlan_netdev_addr_lock_key);
netdev_for_each_tx_queue(dev, macvlan_set_lockdep_class_one, NULL);
}
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index 0b32648a213..4cb364e67dc 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -287,7 +287,7 @@ int meth_reset(struct net_device *dev)
/* Initial mode: 10 | Half-duplex | Accept normal packets */
priv->mac_ctrl = METH_ACCEPT_MCAST | METH_DEFAULT_IPG;
- if (dev->flags | IFF_PROMISC)
+ if (dev->flags & IFF_PROMISC)
priv->mac_ctrl |= METH_PROMISC;
mace->eth.mac_ctrl = priv->mac_ctrl;
diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
index 70dff94a8bc..04d5bc69a6f 100644
--- a/drivers/net/mlx4/cmd.c
+++ b/drivers/net/mlx4/cmd.c
@@ -67,6 +67,8 @@ enum {
CMD_STAT_BAD_INDEX = 0x0a,
/* FW image corrupted: */
CMD_STAT_BAD_NVMEM = 0x0b,
+ /* Error in ICM mapping (e.g. not enough auxiliary ICM pages to execute command): */
+ CMD_STAT_ICM_ERROR = 0x0c,
/* Attempt to modify a QP/EE which is not in the presumed state: */
CMD_STAT_BAD_QP_STATE = 0x10,
/* Bad segment parameters (Address/Size): */
@@ -119,6 +121,7 @@ static int mlx4_status_to_errno(u8 status)
[CMD_STAT_BAD_RES_STATE] = -EBADF,
[CMD_STAT_BAD_INDEX] = -EBADF,
[CMD_STAT_BAD_NVMEM] = -EFAULT,
+ [CMD_STAT_ICM_ERROR] = -ENFILE,
[CMD_STAT_BAD_QP_STATE] = -EINVAL,
[CMD_STAT_BAD_SEG_PARAM] = -EFAULT,
[CMD_STAT_REG_BOUND] = -EBUSY,
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index e141a1513f0..ea3a09aaa84 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -33,6 +33,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include <linux/mlx4/cmd.h>
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 2b5006b9be6..57278224ba1 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -46,6 +46,10 @@ enum {
extern void __buggy_use_of_MLX4_GET(void);
extern void __buggy_use_of_MLX4_PUT(void);
+static int enable_qos;
+module_param(enable_qos, bool, 0444);
+MODULE_PARM_DESC(enable_qos, "Enable Quality of Service support in the HCA (default: off)");
+
#define MLX4_GET(dest, source, offset) \
do { \
void *__p = (char *) (source) + (offset); \
@@ -198,7 +202,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET 0x8e
#define QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET 0x90
#define QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET 0x92
-#define QUERY_DEV_CAP_BMME_FLAGS_OFFSET 0x97
+#define QUERY_DEV_CAP_BMME_FLAGS_OFFSET 0x94
#define QUERY_DEV_CAP_RSVD_LKEY_OFFSET 0x98
#define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0
@@ -373,12 +377,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
}
}
- if (dev_cap->bmme_flags & 1)
- mlx4_dbg(dev, "Base MM extensions: yes "
- "(flags %d, rsvd L_Key %08x)\n",
- dev_cap->bmme_flags, dev_cap->reserved_lkey);
- else
- mlx4_dbg(dev, "Base MM extensions: no\n");
+ mlx4_dbg(dev, "Base MM extensions: flags %08x, rsvd L_Key %08x\n",
+ dev_cap->bmme_flags, dev_cap->reserved_lkey);
/*
* Each UAR has 4 EQ doorbells; so if a UAR is reserved, then
@@ -737,6 +737,10 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM)
*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 3);
+ /* Enable QoS support if module parameter set */
+ if (enable_qos)
+ *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 2);
+
/* QPC/EEC/CQC/EQC/RDMARC attributes */
MLX4_PUT(inbox, param->qpc_base, INIT_HCA_QPC_BASE_OFFSET);
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index a0e046c149b..fbf0e22be12 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -98,7 +98,7 @@ struct mlx4_dev_cap {
int cmpt_entry_sz;
int mtt_entry_sz;
int resize_srq;
- u8 bmme_flags;
+ u32 bmme_flags;
u32 reserved_lkey;
u64 max_icm_sz;
int max_gso_sz;
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index d3736013fe9..8e1d24cda1b 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -158,6 +158,8 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.max_msg_sz = dev_cap->max_msg_sz;
dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1);
dev->caps.flags = dev_cap->flags;
+ dev->caps.bmme_flags = dev_cap->bmme_flags;
+ dev->caps.reserved_lkey = dev_cap->reserved_lkey;
dev->caps.stat_rate_support = dev_cap->stat_rate_support;
dev->caps.max_gso_sz = dev_cap->max_gso_sz;
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index a4023c2dd05..78038499cff 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -118,6 +118,7 @@ struct mlx4_bitmap {
struct mlx4_buddy {
unsigned long **bits;
+ unsigned int *num_free;
int max_order;
spinlock_t lock;
};
diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c
index 03a9abcce52..a3c04c5f12c 100644
--- a/drivers/net/mlx4/mr.c
+++ b/drivers/net/mlx4/mr.c
@@ -47,7 +47,7 @@ struct mlx4_mpt_entry {
__be32 flags;
__be32 qpn;
__be32 key;
- __be32 pd;
+ __be32 pd_flags;
__be64 start;
__be64 length;
__be32 lkey;
@@ -61,11 +61,15 @@ struct mlx4_mpt_entry {
} __attribute__((packed));
#define MLX4_MPT_FLAG_SW_OWNS (0xfUL << 28)
+#define MLX4_MPT_FLAG_FREE (0x3UL << 28)
#define MLX4_MPT_FLAG_MIO (1 << 17)
#define MLX4_MPT_FLAG_BIND_ENABLE (1 << 15)
#define MLX4_MPT_FLAG_PHYSICAL (1 << 9)
#define MLX4_MPT_FLAG_REGION (1 << 8)
+#define MLX4_MPT_PD_FLAG_FAST_REG (1 << 26)
+#define MLX4_MPT_PD_FLAG_EN_INV (3 << 24)
+
#define MLX4_MTT_FLAG_PRESENT 1
#define MLX4_MPT_STATUS_SW 0xF0
@@ -79,23 +83,26 @@ static u32 mlx4_buddy_alloc(struct mlx4_buddy *buddy, int order)
spin_lock(&buddy->lock);
- for (o = order; o <= buddy->max_order; ++o) {
- m = 1 << (buddy->max_order - o);
- seg = find_first_bit(buddy->bits[o], m);
- if (seg < m)
- goto found;
- }
+ for (o = order; o <= buddy->max_order; ++o)
+ if (buddy->num_free[o]) {
+ m = 1 << (buddy->max_order - o);
+ seg = find_first_bit(buddy->bits[o], m);
+ if (seg < m)
+ goto found;
+ }
spin_unlock(&buddy->lock);
return -1;
found:
clear_bit(seg, buddy->bits[o]);
+ --buddy->num_free[o];
while (o > order) {
--o;
seg <<= 1;
set_bit(seg ^ 1, buddy->bits[o]);
+ ++buddy->num_free[o];
}
spin_unlock(&buddy->lock);
@@ -113,11 +120,13 @@ static void mlx4_buddy_free(struct mlx4_buddy *buddy, u32 seg, int order)
while (test_bit(seg ^ 1, buddy->bits[order])) {
clear_bit(seg ^ 1, buddy->bits[order]);
+ --buddy->num_free[order];
seg >>= 1;
++order;
}
set_bit(seg, buddy->bits[order]);
+ ++buddy->num_free[order];
spin_unlock(&buddy->lock);
}
@@ -131,7 +140,9 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
GFP_KERNEL);
- if (!buddy->bits)
+ buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof (int *),
+ GFP_KERNEL);
+ if (!buddy->bits || !buddy->num_free)
goto err_out;
for (i = 0; i <= buddy->max_order; ++i) {
@@ -143,6 +154,7 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
}
set_bit(0, buddy->bits[buddy->max_order]);
+ buddy->num_free[buddy->max_order] = 1;
return 0;
@@ -150,9 +162,10 @@ err_out_free:
for (i = 0; i <= buddy->max_order; ++i)
kfree(buddy->bits[i]);
+err_out:
kfree(buddy->bits);
+ kfree(buddy->num_free);
-err_out:
return -ENOMEM;
}
@@ -164,6 +177,7 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy)
kfree(buddy->bits[i]);
kfree(buddy->bits);
+ kfree(buddy->num_free);
}
static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order)
@@ -314,21 +328,30 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr)
memset(mpt_entry, 0, sizeof *mpt_entry);
- mpt_entry->flags = cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS |
- MLX4_MPT_FLAG_MIO |
+ mpt_entry->flags = cpu_to_be32(MLX4_MPT_FLAG_MIO |
MLX4_MPT_FLAG_REGION |
mr->access);
mpt_entry->key = cpu_to_be32(key_to_hw_index(mr->key));
- mpt_entry->pd = cpu_to_be32(mr->pd);
+ mpt_entry->pd_flags = cpu_to_be32(mr->pd | MLX4_MPT_PD_FLAG_EN_INV);
mpt_entry->start = cpu_to_be64(mr->iova);
mpt_entry->length = cpu_to_be64(mr->size);
mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift);
+
if (mr->mtt.order < 0) {
mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL);
mpt_entry->mtt_seg = 0;
- } else
+ } else {
mpt_entry->mtt_seg = cpu_to_be64(mlx4_mtt_addr(dev, &mr->mtt));
+ }
+
+ if (mr->mtt.order >= 0 && mr->mtt.page_shift == 0) {
+ /* fast register MR in free state */
+ mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_FREE);
+ mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_FAST_REG);
+ } else {
+ mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS);
+ }
err = mlx4_SW2HW_MPT(dev, mailbox,
key_to_hw_index(mr->key) & (dev->caps.num_mpts - 1));
diff --git a/drivers/net/mlx4/pd.c b/drivers/net/mlx4/pd.c
index 3a93c5f0f7a..aa616892d09 100644
--- a/drivers/net/mlx4/pd.c
+++ b/drivers/net/mlx4/pd.c
@@ -91,6 +91,13 @@ EXPORT_SYMBOL_GPL(mlx4_uar_free);
int mlx4_init_uar_table(struct mlx4_dev *dev)
{
+ if (dev->caps.num_uars <= 128) {
+ mlx4_err(dev, "Only %d UAR pages (need more than 128)\n",
+ dev->caps.num_uars);
+ mlx4_err(dev, "Increase firmware log2_uar_bar_megabytes?\n");
+ return -ENODEV;
+ }
+
return mlx4_bitmap_init(&mlx4_priv(dev)->uar_table.bitmap,
dev->caps.num_uars, dev->caps.num_uars - 1,
max(128, dev->caps.reserved_uars));
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 83a877f3a55..8a97a0066a8 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -2112,7 +2112,7 @@ static void mv643xx_eth_netpoll(struct net_device *dev)
mv643xx_eth_irq(dev->irq, dev);
- wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_CAUSE_EXT);
+ wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT);
}
#endif
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index b3981ed972b..3ab0e5289f7 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -125,7 +125,6 @@ struct myri10ge_cmd {
struct myri10ge_rx_buf {
struct mcp_kreq_ether_recv __iomem *lanai; /* lanai ptr for recv ring */
- u8 __iomem *wc_fifo; /* w/c rx dma addr fifo address */
struct mcp_kreq_ether_recv *shadow; /* host shadow of recv ring */
struct myri10ge_rx_buffer_state *info;
struct page *page;
@@ -140,7 +139,6 @@ struct myri10ge_rx_buf {
struct myri10ge_tx_buf {
struct mcp_kreq_ether_send __iomem *lanai; /* lanai ptr for sendq */
- u8 __iomem *wc_fifo; /* w/c send fifo address */
struct mcp_kreq_ether_send *req_list; /* host shadow of sendq */
char *req_bytes;
struct myri10ge_tx_buffer_state *info;
@@ -332,10 +330,6 @@ MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed");
static int myri10ge_reset_recover = 1;
-static int myri10ge_wcfifo = 0;
-module_param(myri10ge_wcfifo, int, S_IRUGO);
-MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled");
-
static int myri10ge_max_slices = 1;
module_param(myri10ge_max_slices, int, S_IRUGO);
MODULE_PARM_DESC(myri10ge_max_slices, "Max tx/rx queues");
@@ -1218,14 +1212,8 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
/* copy 8 descriptors to the firmware at a time */
if ((idx & 7) == 7) {
- if (rx->wc_fifo == NULL)
- myri10ge_submit_8rx(&rx->lanai[idx - 7],
- &rx->shadow[idx - 7]);
- else {
- mb();
- myri10ge_pio_copy(rx->wc_fifo,
- &rx->shadow[idx - 7], 64);
- }
+ myri10ge_submit_8rx(&rx->lanai[idx - 7],
+ &rx->shadow[idx - 7]);
}
}
}
@@ -2229,18 +2217,6 @@ static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice)
ss->rx_big.lanai = (struct mcp_kreq_ether_recv __iomem *)
(mgp->sram + cmd.data0);
- if (myri10ge_wcfifo && mgp->wc_enabled) {
- ss->tx.wc_fifo = (u8 __iomem *)
- mgp->sram + MXGEFW_ETH_SEND_4 + 64 * slice;
- ss->rx_small.wc_fifo = (u8 __iomem *)
- mgp->sram + MXGEFW_ETH_RECV_SMALL + 64 * slice;
- ss->rx_big.wc_fifo = (u8 __iomem *)
- mgp->sram + MXGEFW_ETH_RECV_BIG + 64 * slice;
- } else {
- ss->tx.wc_fifo = NULL;
- ss->rx_small.wc_fifo = NULL;
- ss->rx_big.wc_fifo = NULL;
- }
return status;
}
@@ -2573,27 +2549,6 @@ myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src,
mb();
}
-static inline void
-myri10ge_submit_req_wc(struct myri10ge_tx_buf *tx,
- struct mcp_kreq_ether_send *src, int cnt)
-{
- tx->req += cnt;
- mb();
- while (cnt >= 4) {
- myri10ge_pio_copy(tx->wc_fifo, src, 64);
- mb();
- src += 4;
- cnt -= 4;
- }
- if (cnt > 0) {
- /* pad it to 64 bytes. The src is 64 bytes bigger than it
- * needs to be so that we don't overrun it */
- myri10ge_pio_copy(tx->wc_fifo + MXGEFW_ETH_SEND_OFFSET(cnt),
- src, 64);
- mb();
- }
-}
-
/*
* Transmit a packet. We need to split the packet so that a single
* segment does not cross myri10ge->tx_boundary, so this makes segment
@@ -2830,10 +2785,7 @@ again:
MXGEFW_FLAGS_FIRST)));
idx = ((count - 1) + tx->req) & tx->mask;
tx->info[idx].last = 1;
- if (tx->wc_fifo == NULL)
- myri10ge_submit_req(tx, tx->req_list, count);
- else
- myri10ge_submit_req_wc(tx, tx->req_list, count);
+ myri10ge_submit_req(tx, tx->req_list, count);
tx->pkt_start++;
if ((avail - count) < MXGEFW_MAX_SEND_DESC) {
tx->stop_queue++;
@@ -3768,14 +3720,14 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (mgp->sram_size > mgp->board_span) {
dev_err(&pdev->dev, "board span %ld bytes too small\n",
mgp->board_span);
- goto abort_with_wc;
+ goto abort_with_mtrr;
}
- mgp->sram = ioremap(mgp->iomem_base, mgp->board_span);
+ mgp->sram = ioremap_wc(mgp->iomem_base, mgp->board_span);
if (mgp->sram == NULL) {
dev_err(&pdev->dev, "ioremap failed for %ld bytes at 0x%lx\n",
mgp->board_span, mgp->iomem_base);
status = -ENXIO;
- goto abort_with_wc;
+ goto abort_with_mtrr;
}
memcpy_fromio(mgp->eeprom_strings,
mgp->sram + mgp->sram_size - MYRI10GE_EEPROM_STRINGS_SIZE,
@@ -3876,7 +3828,7 @@ abort_with_firmware:
abort_with_ioremap:
iounmap(mgp->sram);
-abort_with_wc:
+abort_with_mtrr:
#ifdef CONFIG_MTRR
if (mgp->mtrr >= 0)
mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span);
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 14126973bd1..2fec6122c7f 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -355,7 +355,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
}
/* Read the 16 bytes of station address PROM.
- We must first initialize registers, similar to NS8390_init(eifdev, 0).
+ We must first initialize registers, similar to NS8390p_init(eifdev, 0).
We can't reliably read the SAPROM address without this.
(I learned the hard way!). */
{
diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c
index 8f725634692..332df75a9ab 100644
--- a/drivers/net/ne2.c
+++ b/drivers/net/ne2.c
@@ -404,7 +404,7 @@ static int __init ne2_probe1(struct net_device *dev, int slot)
/* Read the 16 bytes of station address PROM.
We must first initialize registers, similar to
- NS8390_init(eifdev, 0).
+ NS8390p_init(eifdev, 0).
We can't reliably read the SAPROM address without this.
(I learned the hard way!). */
{
diff --git a/drivers/net/netxen/Makefile b/drivers/net/netxen/Makefile
index a07cdc6f738..8e7c4c910d2 100644
--- a/drivers/net/netxen/Makefile
+++ b/drivers/net/netxen/Makefile
@@ -32,4 +32,4 @@
obj-$(CONFIG_NETXEN_NIC) := netxen_nic.o
netxen_nic-y := netxen_nic_hw.o netxen_nic_main.o netxen_nic_init.o \
- netxen_nic_isr.o netxen_nic_ethtool.o netxen_nic_niu.o
+ netxen_nic_ethtool.o netxen_nic_niu.o netxen_nic_ctx.o
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index da4c4fb9706..8e736614407 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -54,6 +54,7 @@
#include <linux/mm.h>
#include <linux/mman.h>
+#include <linux/vmalloc.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -63,10 +64,12 @@
#include "netxen_nic_hw.h"
-#define _NETXEN_NIC_LINUX_MAJOR 3
-#define _NETXEN_NIC_LINUX_MINOR 4
-#define _NETXEN_NIC_LINUX_SUBVERSION 18
-#define NETXEN_NIC_LINUX_VERSIONID "3.4.18"
+#define _NETXEN_NIC_LINUX_MAJOR 4
+#define _NETXEN_NIC_LINUX_MINOR 0
+#define _NETXEN_NIC_LINUX_SUBVERSION 0
+#define NETXEN_NIC_LINUX_VERSIONID "4.0.0"
+
+#define NETXEN_VERSION_CODE(a, b, c) (((a) << 16) + ((b) << 8) + (c))
#define NETXEN_NUM_FLASH_SECTORS (64)
#define NETXEN_FLASH_SECTOR_SIZE (64 * 1024)
@@ -84,7 +87,7 @@
#define TX_RINGSIZE \
(sizeof(struct netxen_cmd_buffer) * adapter->max_tx_desc_count)
#define RCV_BUFFSIZE \
- (sizeof(struct netxen_rx_buffer) * rcv_desc->max_rx_desc_count)
+ (sizeof(struct netxen_rx_buffer) * rds_ring->max_rx_desc_count)
#define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a)))
#define NETXEN_NETDEV_STATUS 0x1
@@ -111,6 +114,13 @@
#define NX_P2_C0 0x24
#define NX_P2_C1 0x25
+#define NX_P3_A0 0x30
+#define NX_P3_A2 0x30
+#define NX_P3_B0 0x40
+#define NX_P3_B1 0x41
+
+#define NX_IS_REVISION_P2(REVISION) (REVISION <= NX_P2_C1)
+#define NX_IS_REVISION_P3(REVISION) (REVISION >= NX_P3_A0)
#define FIRST_PAGE_GROUP_START 0
#define FIRST_PAGE_GROUP_END 0x100000
@@ -125,6 +135,16 @@
#define SECOND_PAGE_GROUP_SIZE SECOND_PAGE_GROUP_END - SECOND_PAGE_GROUP_START
#define THIRD_PAGE_GROUP_SIZE THIRD_PAGE_GROUP_END - THIRD_PAGE_GROUP_START
+#define P2_MAX_MTU (8000)
+#define P3_MAX_MTU (9600)
+#define NX_ETHERMTU 1500
+#define NX_MAX_ETHERHDR 32 /* This contains some padding */
+
+#define NX_RX_NORMAL_BUF_MAX_LEN (NX_MAX_ETHERHDR + NX_ETHERMTU)
+#define NX_P2_RX_JUMBO_BUF_MAX_LEN (NX_MAX_ETHERHDR + P2_MAX_MTU)
+#define NX_P3_RX_JUMBO_BUF_MAX_LEN (NX_MAX_ETHERHDR + P3_MAX_MTU)
+#define NX_CT_DEFAULT_RX_BUF_LEN 2048
+
#define MAX_RX_BUFFER_LENGTH 1760
#define MAX_RX_JUMBO_BUFFER_LENGTH 8062
#define MAX_RX_LRO_BUFFER_LENGTH ((48*1024)-512)
@@ -132,7 +152,6 @@
#define RX_JUMBO_DMA_MAP_LEN \
(MAX_RX_JUMBO_BUFFER_LENGTH - 2)
#define RX_LRO_DMA_MAP_LEN (MAX_RX_LRO_BUFFER_LENGTH - 2)
-#define NETXEN_ROM_ROUNDUP 0x80000000ULL
/*
* Maximum number of ring contexts
@@ -140,16 +159,16 @@
#define MAX_RING_CTX 1
/* Opcodes to be used with the commands */
-enum {
- TX_ETHER_PKT = 0x01,
-/* The following opcodes are for IP checksum */
- TX_TCP_PKT,
- TX_UDP_PKT,
- TX_IP_PKT,
- TX_TCP_LSO,
- TX_IPSEC,
- TX_IPSEC_CMD
-};
+#define TX_ETHER_PKT 0x01
+#define TX_TCP_PKT 0x02
+#define TX_UDP_PKT 0x03
+#define TX_IP_PKT 0x04
+#define TX_TCP_LSO 0x05
+#define TX_TCP_LSO6 0x06
+#define TX_IPSEC 0x07
+#define TX_IPSEC_CMD 0x0a
+#define TX_TCPV6_PKT 0x0b
+#define TX_UDPV6_PKT 0x0c
/* The following opcodes are for internal consumption. */
#define NETXEN_CONTROL_OP 0x10
@@ -191,6 +210,7 @@ enum {
#define MAX_RCV_DESCRIPTORS 16384
#define MAX_CMD_DESCRIPTORS_HOST (MAX_CMD_DESCRIPTORS / 4)
#define MAX_RCV_DESCRIPTORS_1G (MAX_RCV_DESCRIPTORS / 4)
+#define MAX_RCV_DESCRIPTORS_10G 8192
#define MAX_JUMBO_RCV_DESCRIPTORS 1024
#define MAX_LRO_RCV_DESCRIPTORS 64
#define MAX_RCVSTATUS_DESCRIPTORS MAX_RCV_DESCRIPTORS
@@ -219,8 +239,6 @@ enum {
#define MPORT_MULTI_FUNCTION_MODE 0x2222
#include "netxen_nic_phan_reg.h"
-extern unsigned long long netxen_dma_mask;
-extern unsigned long last_schedule_time;
/*
* NetXen host-peg signal message structure
@@ -289,7 +307,7 @@ struct netxen_ring_ctx {
#define netxen_set_cmd_desc_port(cmd_desc, var) \
((cmd_desc)->port_ctxid |= ((var) & 0x0F))
#define netxen_set_cmd_desc_ctxid(cmd_desc, var) \
- ((cmd_desc)->port_ctxid |= ((var) & 0xF0))
+ ((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
#define netxen_set_cmd_desc_flags(cmd_desc, val) \
(cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \
@@ -377,8 +395,8 @@ struct rcv_desc {
};
/* opcode field in status_desc */
-#define RCV_NIC_PKT (0xA)
-#define STATUS_NIC_PKT ((RCV_NIC_PKT) << 12)
+#define NETXEN_NIC_RXPKT_DESC 0x04
+#define NETXEN_OLD_RXPKT_DESC 0x3f
/* for status field in status_desc */
#define STATUS_NEED_CKSUM (1)
@@ -410,6 +428,8 @@ struct rcv_desc {
(((sts_data) >> 28) & 0xFFFF)
#define netxen_get_sts_prot(sts_data) \
(((sts_data) >> 44) & 0x0F)
+#define netxen_get_sts_pkt_offset(sts_data) \
+ (((sts_data) >> 48) & 0x1F)
#define netxen_get_sts_opcode(sts_data) \
(((sts_data) >> 58) & 0x03F)
@@ -424,17 +444,30 @@ struct rcv_desc {
struct status_desc {
/* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length
- 28-43 reference_handle, 44-47 protocol, 48-52 unused
+ 28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
53-55 desc_cnt, 56-57 owner, 58-63 opcode
*/
__le64 status_desc_data;
- __le32 hash_value;
- u8 hash_type;
- u8 msg_type;
- u8 unused;
- /* Bit pattern: 0-6 lro_count indicates frag sequence,
- 7 last_frag indicates last frag */
- u8 lro;
+ union {
+ struct {
+ __le32 hash_value;
+ u8 hash_type;
+ u8 msg_type;
+ u8 unused;
+ union {
+ /* Bit pattern: 0-6 lro_count indicates frag
+ * sequence, 7 last_frag indicates last frag
+ */
+ u8 lro;
+
+ /* chained buffers */
+ u8 nr_frags;
+ };
+ };
+ struct {
+ __le16 frag_handles[4];
+ };
+ };
} __attribute__ ((aligned(16)));
enum {
@@ -464,7 +497,20 @@ typedef enum {
NETXEN_BRDTYPE_P2_SB31_10G_IMEZ = 0x000d,
NETXEN_BRDTYPE_P2_SB31_10G_HMEZ = 0x000e,
- NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f
+ NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f,
+
+ NETXEN_BRDTYPE_P3_REF_QG = 0x0021,
+ NETXEN_BRDTYPE_P3_HMEZ = 0x0022,
+ NETXEN_BRDTYPE_P3_10G_CX4_LP = 0x0023,
+ NETXEN_BRDTYPE_P3_4_GB = 0x0024,
+ NETXEN_BRDTYPE_P3_IMEZ = 0x0025,
+ NETXEN_BRDTYPE_P3_10G_SFP_PLUS = 0x0026,
+ NETXEN_BRDTYPE_P3_10000_BASE_T = 0x0027,
+ NETXEN_BRDTYPE_P3_XG_LOM = 0x0028,
+ NETXEN_BRDTYPE_P3_4_GB_MM = 0x0029,
+ NETXEN_BRDTYPE_P3_10G_CX4 = 0x0031,
+ NETXEN_BRDTYPE_P3_10G_XFP = 0x0032
+
} netxen_brdtype_t;
typedef enum {
@@ -747,6 +793,7 @@ struct netxen_cmd_buffer {
/* In rx_buffer, we do not need multiple fragments as is a single buffer */
struct netxen_rx_buffer {
+ struct list_head list;
struct sk_buff *skb;
u64 dma;
u16 ref_handle;
@@ -765,7 +812,6 @@ struct netxen_rx_buffer {
* contains interrupt info as well shared hardware info.
*/
struct netxen_hardware_context {
- struct pci_dev *pdev;
void __iomem *pci_base0;
void __iomem *pci_base1;
void __iomem *pci_base2;
@@ -773,15 +819,20 @@ struct netxen_hardware_context {
unsigned long first_page_group_start;
void __iomem *db_base;
unsigned long db_len;
+ unsigned long pci_len0;
+
+ u8 cut_through;
+ int qdr_sn_window;
+ int ddr_mn_window;
+ unsigned long mn_win_crb;
+ unsigned long ms_win_crb;
u8 revision_id;
u16 board_type;
struct netxen_board_info boardcfg;
- u32 xg_linkup;
- u32 qg_linksup;
+ u32 linkup;
/* Address of cmd ring in Phantom */
struct cmd_desc_type0 *cmd_desc_head;
- struct pci_dev *cmd_desc_pdev;
dma_addr_t cmd_desc_phys_addr;
struct netxen_adapter *adapter;
int pci_func;
@@ -813,17 +864,17 @@ struct netxen_adapter_stats {
* Rcv Descriptor Context. One such per Rcv Descriptor. There may
* be one Rcv Descriptor for normal packets, one for jumbo and may be others.
*/
-struct netxen_rcv_desc_ctx {
+struct nx_host_rds_ring {
u32 flags;
u32 producer;
- u32 rcv_pending; /* Num of bufs posted in phantom */
dma_addr_t phys_addr;
- struct pci_dev *phys_pdev;
+ u32 crb_rcv_producer; /* reg offset */
struct rcv_desc *desc_head; /* address of rx ring in Phantom */
u32 max_rx_desc_count;
u32 dma_size;
u32 skb_size;
struct netxen_rx_buffer *rx_buf_arr; /* rx buffers for receive */
+ struct list_head free_list;
int begin_alloc;
};
@@ -834,17 +885,319 @@ struct netxen_rcv_desc_ctx {
* present elsewhere.
*/
struct netxen_recv_context {
- struct netxen_rcv_desc_ctx rcv_desc[NUM_RCV_DESC_RINGS];
- u32 status_rx_producer;
+ u32 state;
+ u16 context_id;
+ u16 virt_port;
+
+ struct nx_host_rds_ring rds_rings[NUM_RCV_DESC_RINGS];
u32 status_rx_consumer;
+ u32 crb_sts_consumer; /* reg offset */
dma_addr_t rcv_status_desc_phys_addr;
- struct pci_dev *rcv_status_desc_pdev;
struct status_desc *rcv_status_desc_head;
};
-#define NETXEN_NIC_MSI_ENABLED 0x02
-#define NETXEN_DMA_MASK 0xfffffffe
-#define NETXEN_DB_MAPSIZE_BYTES 0x1000
+/* New HW context creation */
+
+#define NX_OS_CRB_RETRY_COUNT 4000
+#define NX_CDRP_SIGNATURE_MAKE(pcifn, version) \
+ (((pcifn) & 0xff) | (((version) & 0xff) << 8) | (0xcafe << 16))
+
+#define NX_CDRP_CLEAR 0x00000000
+#define NX_CDRP_CMD_BIT 0x80000000
+
+/*
+ * All responses must have the NX_CDRP_CMD_BIT cleared
+ * in the crb NX_CDRP_CRB_OFFSET.
+ */
+#define NX_CDRP_FORM_RSP(rsp) (rsp)
+#define NX_CDRP_IS_RSP(rsp) (((rsp) & NX_CDRP_CMD_BIT) == 0)
+
+#define NX_CDRP_RSP_OK 0x00000001
+#define NX_CDRP_RSP_FAIL 0x00000002
+#define NX_CDRP_RSP_TIMEOUT 0x00000003
+
+/*
+ * All commands must have the NX_CDRP_CMD_BIT set in
+ * the crb NX_CDRP_CRB_OFFSET.
+ */
+#define NX_CDRP_FORM_CMD(cmd) (NX_CDRP_CMD_BIT | (cmd))
+#define NX_CDRP_IS_CMD(cmd) (((cmd) & NX_CDRP_CMD_BIT) != 0)
+
+#define NX_CDRP_CMD_SUBMIT_CAPABILITIES 0x00000001
+#define NX_CDRP_CMD_READ_MAX_RDS_PER_CTX 0x00000002
+#define NX_CDRP_CMD_READ_MAX_SDS_PER_CTX 0x00000003
+#define NX_CDRP_CMD_READ_MAX_RULES_PER_CTX 0x00000004
+#define NX_CDRP_CMD_READ_MAX_RX_CTX 0x00000005
+#define NX_CDRP_CMD_READ_MAX_TX_CTX 0x00000006
+#define NX_CDRP_CMD_CREATE_RX_CTX 0x00000007
+#define NX_CDRP_CMD_DESTROY_RX_CTX 0x00000008
+#define NX_CDRP_CMD_CREATE_TX_CTX 0x00000009
+#define NX_CDRP_CMD_DESTROY_TX_CTX 0x0000000a
+#define NX_CDRP_CMD_SETUP_STATISTICS 0x0000000e
+#define NX_CDRP_CMD_GET_STATISTICS 0x0000000f
+#define NX_CDRP_CMD_DELETE_STATISTICS 0x00000010
+#define NX_CDRP_CMD_SET_MTU 0x00000012
+#define NX_CDRP_CMD_MAX 0x00000013
+
+#define NX_RCODE_SUCCESS 0
+#define NX_RCODE_NO_HOST_MEM 1
+#define NX_RCODE_NO_HOST_RESOURCE 2
+#define NX_RCODE_NO_CARD_CRB 3
+#define NX_RCODE_NO_CARD_MEM 4
+#define NX_RCODE_NO_CARD_RESOURCE 5
+#define NX_RCODE_INVALID_ARGS 6
+#define NX_RCODE_INVALID_ACTION 7
+#define NX_RCODE_INVALID_STATE 8
+#define NX_RCODE_NOT_SUPPORTED 9
+#define NX_RCODE_NOT_PERMITTED 10
+#define NX_RCODE_NOT_READY 11
+#define NX_RCODE_DOES_NOT_EXIST 12
+#define NX_RCODE_ALREADY_EXISTS 13
+#define NX_RCODE_BAD_SIGNATURE 14
+#define NX_RCODE_CMD_NOT_IMPL 15
+#define NX_RCODE_CMD_INVALID 16
+#define NX_RCODE_TIMEOUT 17
+#define NX_RCODE_CMD_FAILED 18
+#define NX_RCODE_MAX_EXCEEDED 19
+#define NX_RCODE_MAX 20
+
+#define NX_DESTROY_CTX_RESET 0
+#define NX_DESTROY_CTX_D3_RESET 1
+#define NX_DESTROY_CTX_MAX 2
+
+/*
+ * Capabilities
+ */
+#define NX_CAP_BIT(class, bit) (1 << bit)
+#define NX_CAP0_LEGACY_CONTEXT NX_CAP_BIT(0, 0)
+#define NX_CAP0_MULTI_CONTEXT NX_CAP_BIT(0, 1)
+#define NX_CAP0_LEGACY_MN NX_CAP_BIT(0, 2)
+#define NX_CAP0_LEGACY_MS NX_CAP_BIT(0, 3)
+#define NX_CAP0_CUT_THROUGH NX_CAP_BIT(0, 4)
+#define NX_CAP0_LRO NX_CAP_BIT(0, 5)
+#define NX_CAP0_LSO NX_CAP_BIT(0, 6)
+#define NX_CAP0_JUMBO_CONTIGUOUS NX_CAP_BIT(0, 7)
+#define NX_CAP0_LRO_CONTIGUOUS NX_CAP_BIT(0, 8)
+
+/*
+ * Context state
+ */
+#define NX_HOST_CTX_STATE_FREED 0
+#define NX_HOST_CTX_STATE_ALLOCATED 1
+#define NX_HOST_CTX_STATE_ACTIVE 2
+#define NX_HOST_CTX_STATE_DISABLED 3
+#define NX_HOST_CTX_STATE_QUIESCED 4
+#define NX_HOST_CTX_STATE_MAX 5
+
+/*
+ * Rx context
+ */
+
+typedef struct {
+ u64 host_phys_addr; /* Ring base addr */
+ u32 ring_size; /* Ring entries */
+ u16 msi_index;
+ u16 rsvd; /* Padding */
+} nx_hostrq_sds_ring_t;
+
+typedef struct {
+ u64 host_phys_addr; /* Ring base addr */
+ u64 buff_size; /* Packet buffer size */
+ u32 ring_size; /* Ring entries */
+ u32 ring_kind; /* Class of ring */
+} nx_hostrq_rds_ring_t;
+
+typedef struct {
+ u64 host_rsp_dma_addr; /* Response dma'd here */
+ u32 capabilities[4]; /* Flag bit vector */
+ u32 host_int_crb_mode; /* Interrupt crb usage */
+ u32 host_rds_crb_mode; /* RDS crb usage */
+ /* These ring offsets are relative to data[0] below */
+ u32 rds_ring_offset; /* Offset to RDS config */
+ u32 sds_ring_offset; /* Offset to SDS config */
+ u16 num_rds_rings; /* Count of RDS rings */
+ u16 num_sds_rings; /* Count of SDS rings */
+ u16 rsvd1; /* Padding */
+ u16 rsvd2; /* Padding */
+ u8 reserved[128]; /* reserve space for future expansion*/
+ /* MUST BE 64-bit aligned.
+ The following is packed:
+ - N hostrq_rds_rings
+ - N hostrq_sds_rings */
+ char data[0];
+} nx_hostrq_rx_ctx_t;
+
+typedef struct {
+ u32 host_producer_crb; /* Crb to use */
+ u32 rsvd1; /* Padding */
+} nx_cardrsp_rds_ring_t;
+
+typedef struct {
+ u32 host_consumer_crb; /* Crb to use */
+ u32 interrupt_crb; /* Crb to use */
+} nx_cardrsp_sds_ring_t;
+
+typedef struct {
+ /* These ring offsets are relative to data[0] below */
+ u32 rds_ring_offset; /* Offset to RDS config */
+ u32 sds_ring_offset; /* Offset to SDS config */
+ u32 host_ctx_state; /* Starting State */
+ u32 num_fn_per_port; /* How many PCI fn share the port */
+ u16 num_rds_rings; /* Count of RDS rings */
+ u16 num_sds_rings; /* Count of SDS rings */
+ u16 context_id; /* Handle for context */
+ u8 phys_port; /* Physical id of port */
+ u8 virt_port; /* Virtual/Logical id of port */
+ u8 reserved[128]; /* save space for future expansion */
+ /* MUST BE 64-bit aligned.
+ The following is packed:
+ - N cardrsp_rds_rings
+ - N cardrs_sds_rings */
+ char data[0];
+} nx_cardrsp_rx_ctx_t;
+
+#define SIZEOF_HOSTRQ_RX(HOSTRQ_RX, rds_rings, sds_rings) \
+ (sizeof(HOSTRQ_RX) + \
+ (rds_rings)*(sizeof(nx_hostrq_rds_ring_t)) + \
+ (sds_rings)*(sizeof(nx_hostrq_sds_ring_t)))
+
+#define SIZEOF_CARDRSP_RX(CARDRSP_RX, rds_rings, sds_rings) \
+ (sizeof(CARDRSP_RX) + \
+ (rds_rings)*(sizeof(nx_cardrsp_rds_ring_t)) + \
+ (sds_rings)*(sizeof(nx_cardrsp_sds_ring_t)))
+
+/*
+ * Tx context
+ */
+
+typedef struct {
+ u64 host_phys_addr; /* Ring base addr */
+ u32 ring_size; /* Ring entries */
+ u32 rsvd; /* Padding */
+} nx_hostrq_cds_ring_t;
+
+typedef struct {
+ u64 host_rsp_dma_addr; /* Response dma'd here */
+ u64 cmd_cons_dma_addr; /* */
+ u64 dummy_dma_addr; /* */
+ u32 capabilities[4]; /* Flag bit vector */
+ u32 host_int_crb_mode; /* Interrupt crb usage */
+ u32 rsvd1; /* Padding */
+ u16 rsvd2; /* Padding */
+ u16 interrupt_ctl;
+ u16 msi_index;
+ u16 rsvd3; /* Padding */
+ nx_hostrq_cds_ring_t cds_ring; /* Desc of cds ring */
+ u8 reserved[128]; /* future expansion */
+} nx_hostrq_tx_ctx_t;
+
+typedef struct {
+ u32 host_producer_crb; /* Crb to use */
+ u32 interrupt_crb; /* Crb to use */
+} nx_cardrsp_cds_ring_t;
+
+typedef struct {
+ u32 host_ctx_state; /* Starting state */
+ u16 context_id; /* Handle for context */
+ u8 phys_port; /* Physical id of port */
+ u8 virt_port; /* Virtual/Logical id of port */
+ nx_cardrsp_cds_ring_t cds_ring; /* Card cds settings */
+ u8 reserved[128]; /* future expansion */
+} nx_cardrsp_tx_ctx_t;
+
+#define SIZEOF_HOSTRQ_TX(HOSTRQ_TX) (sizeof(HOSTRQ_TX))
+#define SIZEOF_CARDRSP_TX(CARDRSP_TX) (sizeof(CARDRSP_TX))
+
+/* CRB */
+
+#define NX_HOST_RDS_CRB_MODE_UNIQUE 0
+#define NX_HOST_RDS_CRB_MODE_SHARED 1
+#define NX_HOST_RDS_CRB_MODE_CUSTOM 2
+#define NX_HOST_RDS_CRB_MODE_MAX 3
+
+#define NX_HOST_INT_CRB_MODE_UNIQUE 0
+#define NX_HOST_INT_CRB_MODE_SHARED 1
+#define NX_HOST_INT_CRB_MODE_NORX 2
+#define NX_HOST_INT_CRB_MODE_NOTX 3
+#define NX_HOST_INT_CRB_MODE_NORXTX 4
+
+
+/* MAC */
+
+#define MC_COUNT_P2 16
+#define MC_COUNT_P3 38
+
+#define NETXEN_MAC_NOOP 0
+#define NETXEN_MAC_ADD 1
+#define NETXEN_MAC_DEL 2
+
+typedef struct nx_mac_list_s {
+ struct nx_mac_list_s *next;
+ uint8_t mac_addr[MAX_ADDR_LEN];
+} nx_mac_list_t;
+
+/*
+ * Interrupt coalescing defaults. The defaults are for 1500 MTU. It is
+ * adjusted based on configured MTU.
+ */
+#define NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US 3
+#define NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS 256
+#define NETXEN_DEFAULT_INTR_COALESCE_TX_PACKETS 64
+#define NETXEN_DEFAULT_INTR_COALESCE_TX_TIME_US 4
+
+#define NETXEN_NIC_INTR_DEFAULT 0x04
+
+typedef union {
+ struct {
+ uint16_t rx_packets;
+ uint16_t rx_time_us;
+ uint16_t tx_packets;
+ uint16_t tx_time_us;
+ } data;
+ uint64_t word;
+} nx_nic_intr_coalesce_data_t;
+
+typedef struct {
+ uint16_t stats_time_us;
+ uint16_t rate_sample_time;
+ uint16_t flags;
+ uint16_t rsvd_1;
+ uint32_t low_threshold;
+ uint32_t high_threshold;
+ nx_nic_intr_coalesce_data_t normal;
+ nx_nic_intr_coalesce_data_t low;
+ nx_nic_intr_coalesce_data_t high;
+ nx_nic_intr_coalesce_data_t irq;
+} nx_nic_intr_coalesce_t;
+
+typedef struct {
+ u64 qhdr;
+ u64 req_hdr;
+ u64 words[6];
+} nx_nic_req_t;
+
+typedef struct {
+ u8 op;
+ u8 tag;
+ u8 mac_addr[6];
+} nx_mac_req_t;
+
+#define MAX_PENDING_DESC_BLOCK_SIZE 64
+
+#define NETXEN_NIC_MSI_ENABLED 0x02
+#define NETXEN_NIC_MSIX_ENABLED 0x04
+#define NETXEN_IS_MSI_FAMILY(adapter) \
+ ((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED))
+
+#define MSIX_ENTRIES_PER_ADAPTER 8
+#define NETXEN_MSIX_TBL_SPACE 8192
+#define NETXEN_PCI_REG_MSIX_TBL 0x44
+
+#define NETXEN_DB_MAPSIZE_BYTES 0x1000
+
+#define NETXEN_NETDEV_WEIGHT 120
+#define NETXEN_ADAPTER_UP_MAGIC 777
+#define NETXEN_NIC_PEG_TUNE 0
struct netxen_dummy_dma {
void *addr;
@@ -854,46 +1207,65 @@ struct netxen_dummy_dma {
struct netxen_adapter {
struct netxen_hardware_context ahw;
- struct netxen_adapter *master;
struct net_device *netdev;
struct pci_dev *pdev;
+ int pci_using_dac;
struct napi_struct napi;
struct net_device_stats net_stats;
- unsigned char mac_addr[ETH_ALEN];
int mtu;
int portnum;
u8 physical_port;
+ u16 tx_context_id;
+
+ uint8_t mc_enabled;
+ uint8_t max_mc_count;
+ nx_mac_list_t *mac_list;
+
+ struct netxen_legacy_intr_set legacy_intr;
+ u32 crb_intr_mask;
struct work_struct watchdog_task;
struct timer_list watchdog_timer;
struct work_struct tx_timeout_task;
u32 curr_window;
+ u32 crb_win;
+ rwlock_t adapter_lock;
+
+ uint64_t dma_mask;
u32 cmd_producer;
__le32 *cmd_consumer;
u32 last_cmd_consumer;
+ u32 crb_addr_cmd_producer;
+ u32 crb_addr_cmd_consumer;
u32 max_tx_desc_count;
u32 max_rx_desc_count;
u32 max_jumbo_rx_desc_count;
u32 max_lro_rx_desc_count;
+ int max_rds_rings;
+
u32 flags;
u32 irq;
int driver_mismatch;
u32 temp;
+ u32 fw_major;
+
+ u8 msix_supported;
+ u8 max_possible_rss_rings;
+ struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER];
+
struct netxen_adapter_stats stats;
- u16 portno;
u16 link_speed;
u16 link_duplex;
u16 state;
u16 link_autoneg;
int rx_csum;
int status;
- spinlock_t stats_lock;
struct netxen_cmd_buffer *cmd_buf_arr; /* Command buffers for xmit */
@@ -905,25 +1277,33 @@ struct netxen_adapter {
int is_up;
struct netxen_dummy_dma dummy_dma;
+ nx_nic_intr_coalesce_t coal;
/* Context interface shared between card and host */
struct netxen_ring_ctx *ctx_desc;
- struct pci_dev *ctx_desc_pdev;
dma_addr_t ctx_desc_phys_addr;
int intr_scheme;
int msi_mode;
int (*enable_phy_interrupts) (struct netxen_adapter *);
int (*disable_phy_interrupts) (struct netxen_adapter *);
- void (*handle_phy_intr) (struct netxen_adapter *);
int (*macaddr_set) (struct netxen_adapter *, netxen_ethernet_macaddr_t);
int (*set_mtu) (struct netxen_adapter *, int);
int (*set_promisc) (struct netxen_adapter *, netxen_niu_prom_mode_t);
- int (*unset_promisc) (struct netxen_adapter *, netxen_niu_prom_mode_t);
int (*phy_read) (struct netxen_adapter *, long reg, u32 *);
int (*phy_write) (struct netxen_adapter *, long reg, u32 val);
int (*init_port) (struct netxen_adapter *, int);
- void (*init_niu) (struct netxen_adapter *);
int (*stop_port) (struct netxen_adapter *);
+
+ int (*hw_read_wx)(struct netxen_adapter *, ulong, void *, int);
+ int (*hw_write_wx)(struct netxen_adapter *, ulong, void *, int);
+ int (*pci_mem_read)(struct netxen_adapter *, u64, void *, int);
+ int (*pci_mem_write)(struct netxen_adapter *, u64, void *, int);
+ int (*pci_write_immediate)(struct netxen_adapter *, u64, u32);
+ u32 (*pci_read_immediate)(struct netxen_adapter *, u64);
+ void (*pci_write_normalize)(struct netxen_adapter *, u64, u32);
+ u32 (*pci_read_normalize)(struct netxen_adapter *, u64);
+ unsigned long (*pci_set_window)(struct netxen_adapter *,
+ unsigned long long);
}; /* netxen_adapter structure */
/*
@@ -988,8 +1368,6 @@ int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter);
int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter);
int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter);
int netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter);
-void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter);
-void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter);
int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
__u32 * readval);
int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
@@ -998,27 +1376,61 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
/* Functions available from netxen_nic_hw.c */
int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu);
int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu);
-void netxen_nic_init_niu_gb(struct netxen_adapter *adapter);
-void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw);
void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val);
int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off);
void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value);
-void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value);
+void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value);
+void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value);
+void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value);
int netxen_nic_get_board_info(struct netxen_adapter *adapter);
-int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
- int len);
-int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
- int len);
+
+int netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len);
+int netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len);
+int netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size);
+int netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size);
+int netxen_nic_pci_write_immediate_128M(struct netxen_adapter *adapter,
+ u64 off, u32 data);
+u32 netxen_nic_pci_read_immediate_128M(struct netxen_adapter *adapter, u64 off);
+void netxen_nic_pci_write_normalize_128M(struct netxen_adapter *adapter,
+ u64 off, u32 data);
+u32 netxen_nic_pci_read_normalize_128M(struct netxen_adapter *adapter, u64 off);
+unsigned long netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter,
+ unsigned long long addr);
+void netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter,
+ u32 wndw);
+
+int netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len);
+int netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len);
+int netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size);
+int netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size);
void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
unsigned long off, int data);
+int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter,
+ u64 off, u32 data);
+u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off);
+void netxen_nic_pci_write_normalize_2M(struct netxen_adapter *adapter,
+ u64 off, u32 data);
+u32 netxen_nic_pci_read_normalize_2M(struct netxen_adapter *adapter, u64 off);
+unsigned long netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,
+ unsigned long long addr);
/* Functions from netxen_nic_init.c */
void netxen_free_adapter_offload(struct netxen_adapter *adapter);
int netxen_initialize_adapter_offload(struct netxen_adapter *adapter);
int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
+int netxen_receive_peg_ready(struct netxen_adapter *adapter);
int netxen_load_firmware(struct netxen_adapter *adapter);
int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose);
+
int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp);
int netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
u8 *bytes, size_t size);
@@ -1032,33 +1444,43 @@ void netxen_halt_pegs(struct netxen_adapter *adapter);
int netxen_rom_se(struct netxen_adapter *adapter, int addr);
-/* Functions from netxen_nic_isr.c */
-void netxen_initialize_adapter_sw(struct netxen_adapter *adapter);
-void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr,
- struct pci_dev **used_dev);
+int netxen_alloc_sw_resources(struct netxen_adapter *adapter);
+void netxen_free_sw_resources(struct netxen_adapter *adapter);
+
+int netxen_alloc_hw_resources(struct netxen_adapter *adapter);
+void netxen_free_hw_resources(struct netxen_adapter *adapter);
+
+void netxen_release_rx_buffers(struct netxen_adapter *adapter);
+void netxen_release_tx_buffers(struct netxen_adapter *adapter);
+
void netxen_initialize_adapter_ops(struct netxen_adapter *adapter);
int netxen_init_firmware(struct netxen_adapter *adapter);
-void netxen_free_hw_resources(struct netxen_adapter *adapter);
void netxen_tso_check(struct netxen_adapter *adapter,
struct cmd_desc_type0 *desc, struct sk_buff *skb);
-int netxen_nic_hw_resources(struct netxen_adapter *adapter);
void netxen_nic_clear_stats(struct netxen_adapter *adapter);
void netxen_watchdog_task(struct work_struct *work);
void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
u32 ringid);
int netxen_process_cmd_ring(struct netxen_adapter *adapter);
u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max);
-void netxen_nic_set_multi(struct net_device *netdev);
+void netxen_p2_nic_set_multi(struct net_device *netdev);
+void netxen_p3_nic_set_multi(struct net_device *netdev);
+int netxen_config_intr_coalesce(struct netxen_adapter *adapter);
+
+u32 nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, u32 mtu);
int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
+
int netxen_nic_set_mac(struct net_device *netdev, void *p);
struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
+void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
+ uint32_t crb_producer);
/*
* NetXen Board information
*/
-#define NETXEN_MAX_SHORT_NAME 16
+#define NETXEN_MAX_SHORT_NAME 32
struct netxen_brdinfo {
netxen_brdtype_t brdtype; /* type of board */
long ports; /* max no of physical ports */
@@ -1072,6 +1494,17 @@ static const struct netxen_brdinfo netxen_boards[] = {
{NETXEN_BRDTYPE_P2_SB31_10G, 1, "XGb XFP"},
{NETXEN_BRDTYPE_P2_SB35_4G, 4, "Quad Gb"},
{NETXEN_BRDTYPE_P2_SB31_2G, 2, "Dual Gb"},
+ {NETXEN_BRDTYPE_P3_REF_QG, 4, "Reference Quad Gig "},
+ {NETXEN_BRDTYPE_P3_HMEZ, 2, "Dual XGb HMEZ"},
+ {NETXEN_BRDTYPE_P3_10G_CX4_LP, 2, "Dual XGb CX4 LP"},
+ {NETXEN_BRDTYPE_P3_4_GB, 4, "Quad Gig LP"},
+ {NETXEN_BRDTYPE_P3_IMEZ, 2, "Dual XGb IMEZ"},
+ {NETXEN_BRDTYPE_P3_10G_SFP_PLUS, 2, "Dual XGb SFP+ LP"},
+ {NETXEN_BRDTYPE_P3_10000_BASE_T, 1, "XGB 10G BaseT LP"},
+ {NETXEN_BRDTYPE_P3_XG_LOM, 2, "Dual XGb LOM"},
+ {NETXEN_BRDTYPE_P3_4_GB_MM, 4, "Quad GB - March Madness"},
+ {NETXEN_BRDTYPE_P3_10G_CX4, 2, "Reference Dual CX4 Option"},
+ {NETXEN_BRDTYPE_P3_10G_XFP, 1, "Reference Single XFP Option"}
};
#define NUM_SUPPORTED_BOARDS ARRAY_SIZE(netxen_boards)
@@ -1097,7 +1530,7 @@ dma_watchdog_shutdown_request(struct netxen_adapter *adapter)
u32 ctrl;
/* check if already inactive */
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
printk(KERN_ERR "failed to read dma watchdog status\n");
@@ -1117,7 +1550,7 @@ dma_watchdog_shutdown_poll_result(struct netxen_adapter *adapter)
{
u32 ctrl;
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
printk(KERN_ERR "failed to read dma watchdog status\n");
@@ -1129,7 +1562,7 @@ dma_watchdog_wakeup(struct netxen_adapter *adapter)
{
u32 ctrl;
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
printk(KERN_ERR "failed to read dma watchdog status\n");
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
new file mode 100644
index 00000000000..64babc59e69
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -0,0 +1,710 @@
+/*
+ * Copyright (C) 2003 - 2008 NetXen, Inc.
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ *
+ * Contact Information:
+ * info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ *
+ */
+
+#include "netxen_nic_hw.h"
+#include "netxen_nic.h"
+#include "netxen_nic_phan_reg.h"
+
+#define NXHAL_VERSION 1
+
+static int
+netxen_api_lock(struct netxen_adapter *adapter)
+{
+ u32 done = 0, timeout = 0;
+
+ for (;;) {
+ /* Acquire PCIE HW semaphore5 */
+ netxen_nic_read_w0(adapter,
+ NETXEN_PCIE_REG(PCIE_SEM5_LOCK), &done);
+
+ if (done == 1)
+ break;
+
+ if (++timeout >= NX_OS_CRB_RETRY_COUNT) {
+ printk(KERN_ERR "%s: lock timeout.\n", __func__);
+ return -1;
+ }
+
+ msleep(1);
+ }
+
+#if 0
+ netxen_nic_write_w1(adapter,
+ NETXEN_API_LOCK_ID, NX_OS_API_LOCK_DRIVER);
+#endif
+ return 0;
+}
+
+static int
+netxen_api_unlock(struct netxen_adapter *adapter)
+{
+ u32 val;
+
+ /* Release PCIE HW semaphore5 */
+ netxen_nic_read_w0(adapter,
+ NETXEN_PCIE_REG(PCIE_SEM5_UNLOCK), &val);
+ return 0;
+}
+
+static u32
+netxen_poll_rsp(struct netxen_adapter *adapter)
+{
+ u32 raw_rsp, rsp = NX_CDRP_RSP_OK;
+ int timeout = 0;
+
+ do {
+ /* give atleast 1ms for firmware to respond */
+ msleep(1);
+
+ if (++timeout > NX_OS_CRB_RETRY_COUNT)
+ return NX_CDRP_RSP_TIMEOUT;
+
+ netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET,
+ &raw_rsp);
+
+ rsp = le32_to_cpu(raw_rsp);
+ } while (!NX_CDRP_IS_RSP(rsp));
+
+ return rsp;
+}
+
+static u32
+netxen_issue_cmd(struct netxen_adapter *adapter,
+ u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd)
+{
+ u32 rsp;
+ u32 signature = 0;
+ u32 rcode = NX_RCODE_SUCCESS;
+
+ signature = NX_CDRP_SIGNATURE_MAKE(pci_fn, version);
+
+ /* Acquire semaphore before accessing CRB */
+ if (netxen_api_lock(adapter))
+ return NX_RCODE_TIMEOUT;
+
+ netxen_nic_write_w1(adapter, NX_SIGN_CRB_OFFSET,
+ cpu_to_le32(signature));
+
+ netxen_nic_write_w1(adapter, NX_ARG1_CRB_OFFSET,
+ cpu_to_le32(arg1));
+
+ netxen_nic_write_w1(adapter, NX_ARG2_CRB_OFFSET,
+ cpu_to_le32(arg2));
+
+ netxen_nic_write_w1(adapter, NX_ARG3_CRB_OFFSET,
+ cpu_to_le32(arg3));
+
+ netxen_nic_write_w1(adapter, NX_CDRP_CRB_OFFSET,
+ cpu_to_le32(NX_CDRP_FORM_CMD(cmd)));
+
+ rsp = netxen_poll_rsp(adapter);
+
+ if (rsp == NX_CDRP_RSP_TIMEOUT) {
+ printk(KERN_ERR "%s: card response timeout.\n",
+ netxen_nic_driver_name);
+
+ rcode = NX_RCODE_TIMEOUT;
+ } else if (rsp == NX_CDRP_RSP_FAIL) {
+ netxen_nic_read_w1(adapter, NX_ARG1_CRB_OFFSET, &rcode);
+ rcode = le32_to_cpu(rcode);
+
+ printk(KERN_ERR "%s: failed card response code:0x%x\n",
+ netxen_nic_driver_name, rcode);
+ }
+
+ /* Release semaphore */
+ netxen_api_unlock(adapter);
+
+ return rcode;
+}
+
+u32
+nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, u32 mtu)
+{
+ u32 rcode = NX_RCODE_SUCCESS;
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0];
+
+ if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE)
+ rcode = netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ recv_ctx->context_id,
+ mtu,
+ 0,
+ NX_CDRP_CMD_SET_MTU);
+
+ return rcode;
+}
+
+static int
+nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
+{
+ void *addr;
+ nx_hostrq_rx_ctx_t *prq;
+ nx_cardrsp_rx_ctx_t *prsp;
+ nx_hostrq_rds_ring_t *prq_rds;
+ nx_hostrq_sds_ring_t *prq_sds;
+ nx_cardrsp_rds_ring_t *prsp_rds;
+ nx_cardrsp_sds_ring_t *prsp_sds;
+ struct nx_host_rds_ring *rds_ring;
+
+ dma_addr_t hostrq_phys_addr, cardrsp_phys_addr;
+ u64 phys_addr;
+
+ int i, nrds_rings, nsds_rings;
+ size_t rq_size, rsp_size;
+ u32 cap, reg;
+
+ int err;
+
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0];
+
+ /* only one sds ring for now */
+ nrds_rings = adapter->max_rds_rings;
+ nsds_rings = 1;
+
+ rq_size =
+ SIZEOF_HOSTRQ_RX(nx_hostrq_rx_ctx_t, nrds_rings, nsds_rings);
+ rsp_size =
+ SIZEOF_CARDRSP_RX(nx_cardrsp_rx_ctx_t, nrds_rings, nsds_rings);
+
+ addr = pci_alloc_consistent(adapter->pdev,
+ rq_size, &hostrq_phys_addr);
+ if (addr == NULL)
+ return -ENOMEM;
+ prq = (nx_hostrq_rx_ctx_t *)addr;
+
+ addr = pci_alloc_consistent(adapter->pdev,
+ rsp_size, &cardrsp_phys_addr);
+ if (addr == NULL) {
+ err = -ENOMEM;
+ goto out_free_rq;
+ }
+ prsp = (nx_cardrsp_rx_ctx_t *)addr;
+
+ prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr);
+
+ cap = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN);
+ cap |= (NX_CAP0_JUMBO_CONTIGUOUS | NX_CAP0_LRO_CONTIGUOUS);
+
+ prq->capabilities[0] = cpu_to_le32(cap);
+ prq->host_int_crb_mode =
+ cpu_to_le32(NX_HOST_INT_CRB_MODE_SHARED);
+ prq->host_rds_crb_mode =
+ cpu_to_le32(NX_HOST_RDS_CRB_MODE_UNIQUE);
+
+ prq->num_rds_rings = cpu_to_le16(nrds_rings);
+ prq->num_sds_rings = cpu_to_le16(nsds_rings);
+ prq->rds_ring_offset = 0;
+ prq->sds_ring_offset = prq->rds_ring_offset +
+ (sizeof(nx_hostrq_rds_ring_t) * nrds_rings);
+
+ prq_rds = (nx_hostrq_rds_ring_t *)(prq->data + prq->rds_ring_offset);
+
+ for (i = 0; i < nrds_rings; i++) {
+
+ rds_ring = &recv_ctx->rds_rings[i];
+
+ prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr);
+ prq_rds[i].ring_size = cpu_to_le32(rds_ring->max_rx_desc_count);
+ prq_rds[i].ring_kind = cpu_to_le32(i);
+ prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size);
+ }
+
+ prq_sds = (nx_hostrq_sds_ring_t *)(prq->data + prq->sds_ring_offset);
+
+ prq_sds[0].host_phys_addr =
+ cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
+ prq_sds[0].ring_size = cpu_to_le32(adapter->max_rx_desc_count);
+ /* only one msix vector for now */
+ prq_sds[0].msi_index = cpu_to_le32(0);
+
+ /* now byteswap offsets */
+ prq->rds_ring_offset = cpu_to_le32(prq->rds_ring_offset);
+ prq->sds_ring_offset = cpu_to_le32(prq->sds_ring_offset);
+
+ phys_addr = hostrq_phys_addr;
+ err = netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ (u32)(phys_addr >> 32),
+ (u32)(phys_addr & 0xffffffff),
+ rq_size,
+ NX_CDRP_CMD_CREATE_RX_CTX);
+ if (err) {
+ printk(KERN_WARNING
+ "Failed to create rx ctx in firmware%d\n", err);
+ goto out_free_rsp;
+ }
+
+
+ prsp_rds = ((nx_cardrsp_rds_ring_t *)
+ &prsp->data[prsp->rds_ring_offset]);
+
+ for (i = 0; i < le32_to_cpu(prsp->num_rds_rings); i++) {
+ rds_ring = &recv_ctx->rds_rings[i];
+
+ reg = le32_to_cpu(prsp_rds[i].host_producer_crb);
+ rds_ring->crb_rcv_producer = NETXEN_NIC_REG(reg - 0x200);
+ }
+
+ prsp_sds = ((nx_cardrsp_sds_ring_t *)
+ &prsp->data[prsp->sds_ring_offset]);
+ reg = le32_to_cpu(prsp_sds[0].host_consumer_crb);
+ recv_ctx->crb_sts_consumer = NETXEN_NIC_REG(reg - 0x200);
+
+ reg = le32_to_cpu(prsp_sds[0].interrupt_crb);
+ adapter->crb_intr_mask = NETXEN_NIC_REG(reg - 0x200);
+
+ recv_ctx->state = le32_to_cpu(prsp->host_ctx_state);
+ recv_ctx->context_id = le16_to_cpu(prsp->context_id);
+ recv_ctx->virt_port = le16_to_cpu(prsp->virt_port);
+
+out_free_rsp:
+ pci_free_consistent(adapter->pdev, rsp_size, prsp, cardrsp_phys_addr);
+out_free_rq:
+ pci_free_consistent(adapter->pdev, rq_size, prq, hostrq_phys_addr);
+ return err;
+}
+
+static void
+nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter)
+{
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0];
+
+ if (netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ recv_ctx->context_id,
+ NX_DESTROY_CTX_RESET,
+ 0,
+ NX_CDRP_CMD_DESTROY_RX_CTX)) {
+
+ printk(KERN_WARNING
+ "%s: Failed to destroy rx ctx in firmware\n",
+ netxen_nic_driver_name);
+ }
+}
+
+static int
+nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter)
+{
+ nx_hostrq_tx_ctx_t *prq;
+ nx_hostrq_cds_ring_t *prq_cds;
+ nx_cardrsp_tx_ctx_t *prsp;
+ void *rq_addr, *rsp_addr;
+ size_t rq_size, rsp_size;
+ u32 temp;
+ int err = 0;
+ u64 offset, phys_addr;
+ dma_addr_t rq_phys_addr, rsp_phys_addr;
+
+ rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t);
+ rq_addr = pci_alloc_consistent(adapter->pdev,
+ rq_size, &rq_phys_addr);
+ if (!rq_addr)
+ return -ENOMEM;
+
+ rsp_size = SIZEOF_CARDRSP_TX(nx_cardrsp_tx_ctx_t);
+ rsp_addr = pci_alloc_consistent(adapter->pdev,
+ rsp_size, &rsp_phys_addr);
+ if (!rsp_addr) {
+ err = -ENOMEM;
+ goto out_free_rq;
+ }
+
+ memset(rq_addr, 0, rq_size);
+ prq = (nx_hostrq_tx_ctx_t *)rq_addr;
+
+ memset(rsp_addr, 0, rsp_size);
+ prsp = (nx_cardrsp_tx_ctx_t *)rsp_addr;
+
+ prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr);
+
+ temp = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN | NX_CAP0_LSO);
+ prq->capabilities[0] = cpu_to_le32(temp);
+
+ prq->host_int_crb_mode =
+ cpu_to_le32(NX_HOST_INT_CRB_MODE_SHARED);
+
+ prq->interrupt_ctl = 0;
+ prq->msi_index = 0;
+
+ prq->dummy_dma_addr = cpu_to_le64(adapter->dummy_dma.phys_addr);
+
+ offset = adapter->ctx_desc_phys_addr+sizeof(struct netxen_ring_ctx);
+ prq->cmd_cons_dma_addr = cpu_to_le64(offset);
+
+ prq_cds = &prq->cds_ring;
+
+ prq_cds->host_phys_addr =
+ cpu_to_le64(adapter->ahw.cmd_desc_phys_addr);
+
+ prq_cds->ring_size = cpu_to_le32(adapter->max_tx_desc_count);
+
+ phys_addr = rq_phys_addr;
+ err = netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ (u32)(phys_addr >> 32),
+ ((u32)phys_addr & 0xffffffff),
+ rq_size,
+ NX_CDRP_CMD_CREATE_TX_CTX);
+
+ if (err == NX_RCODE_SUCCESS) {
+ temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
+ adapter->crb_addr_cmd_producer =
+ NETXEN_NIC_REG(temp - 0x200);
+#if 0
+ adapter->tx_state =
+ le32_to_cpu(prsp->host_ctx_state);
+#endif
+ adapter->tx_context_id =
+ le16_to_cpu(prsp->context_id);
+ } else {
+ printk(KERN_WARNING
+ "Failed to create tx ctx in firmware%d\n", err);
+ err = -EIO;
+ }
+
+ pci_free_consistent(adapter->pdev, rsp_size, rsp_addr, rsp_phys_addr);
+
+out_free_rq:
+ pci_free_consistent(adapter->pdev, rq_size, rq_addr, rq_phys_addr);
+
+ return err;
+}
+
+static void
+nx_fw_cmd_destroy_tx_ctx(struct netxen_adapter *adapter)
+{
+ if (netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ adapter->tx_context_id,
+ NX_DESTROY_CTX_RESET,
+ 0,
+ NX_CDRP_CMD_DESTROY_TX_CTX)) {
+
+ printk(KERN_WARNING
+ "%s: Failed to destroy tx ctx in firmware\n",
+ netxen_nic_driver_name);
+ }
+}
+
+static u64 ctx_addr_sig_regs[][3] = {
+ {NETXEN_NIC_REG(0x188), NETXEN_NIC_REG(0x18c), NETXEN_NIC_REG(0x1c0)},
+ {NETXEN_NIC_REG(0x190), NETXEN_NIC_REG(0x194), NETXEN_NIC_REG(0x1c4)},
+ {NETXEN_NIC_REG(0x198), NETXEN_NIC_REG(0x19c), NETXEN_NIC_REG(0x1c8)},
+ {NETXEN_NIC_REG(0x1a0), NETXEN_NIC_REG(0x1a4), NETXEN_NIC_REG(0x1cc)}
+};
+
+#define CRB_CTX_ADDR_REG_LO(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][0])
+#define CRB_CTX_ADDR_REG_HI(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][2])
+#define CRB_CTX_SIGNATURE_REG(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][1])
+
+#define lower32(x) ((u32)((x) & 0xffffffff))
+#define upper32(x) ((u32)(((u64)(x) >> 32) & 0xffffffff))
+
+static struct netxen_recv_crb recv_crb_registers[] = {
+ /* Instance 0 */
+ {
+ /* crb_rcv_producer: */
+ {
+ NETXEN_NIC_REG(0x100),
+ /* Jumbo frames */
+ NETXEN_NIC_REG(0x110),
+ /* LRO */
+ NETXEN_NIC_REG(0x120)
+ },
+ /* crb_sts_consumer: */
+ NETXEN_NIC_REG(0x138),
+ },
+ /* Instance 1 */
+ {
+ /* crb_rcv_producer: */
+ {
+ NETXEN_NIC_REG(0x144),
+ /* Jumbo frames */
+ NETXEN_NIC_REG(0x154),
+ /* LRO */
+ NETXEN_NIC_REG(0x164)
+ },
+ /* crb_sts_consumer: */
+ NETXEN_NIC_REG(0x17c),
+ },
+ /* Instance 2 */
+ {
+ /* crb_rcv_producer: */
+ {
+ NETXEN_NIC_REG(0x1d8),
+ /* Jumbo frames */
+ NETXEN_NIC_REG(0x1f8),
+ /* LRO */
+ NETXEN_NIC_REG(0x208)
+ },
+ /* crb_sts_consumer: */
+ NETXEN_NIC_REG(0x220),
+ },
+ /* Instance 3 */
+ {
+ /* crb_rcv_producer: */
+ {
+ NETXEN_NIC_REG(0x22c),
+ /* Jumbo frames */
+ NETXEN_NIC_REG(0x23c),
+ /* LRO */
+ NETXEN_NIC_REG(0x24c)
+ },
+ /* crb_sts_consumer: */
+ NETXEN_NIC_REG(0x264),
+ },
+};
+
+static int
+netxen_init_old_ctx(struct netxen_adapter *adapter)
+{
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+ int ctx, ring;
+ int func_id = adapter->portnum;
+
+ adapter->ctx_desc->cmd_ring_addr =
+ cpu_to_le64(adapter->ahw.cmd_desc_phys_addr);
+ adapter->ctx_desc->cmd_ring_size =
+ cpu_to_le32(adapter->max_tx_desc_count);
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr =
+ cpu_to_le64(rds_ring->phys_addr);
+ adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size =
+ cpu_to_le32(rds_ring->max_rx_desc_count);
+ }
+ adapter->ctx_desc->sts_ring_addr =
+ cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
+ adapter->ctx_desc->sts_ring_size =
+ cpu_to_le32(adapter->max_rx_desc_count);
+ }
+
+ adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_LO(func_id),
+ lower32(adapter->ctx_desc_phys_addr));
+ adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_HI(func_id),
+ upper32(adapter->ctx_desc_phys_addr));
+ adapter->pci_write_normalize(adapter, CRB_CTX_SIGNATURE_REG(func_id),
+ NETXEN_CTX_SIGNATURE | func_id);
+ return 0;
+}
+
+static uint32_t sw_int_mask[4] = {
+ CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1,
+ CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3
+};
+
+int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
+{
+ struct netxen_hardware_context *hw = &adapter->ahw;
+ u32 state = 0;
+ void *addr;
+ int err = 0;
+ int ctx, ring;
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+
+ err = netxen_receive_peg_ready(adapter);
+ if (err) {
+ printk(KERN_ERR "Rcv Peg initialization not complete:%x.\n",
+ state);
+ return err;
+ }
+
+ addr = pci_alloc_consistent(adapter->pdev,
+ sizeof(struct netxen_ring_ctx) + sizeof(uint32_t),
+ &adapter->ctx_desc_phys_addr);
+
+ if (addr == NULL) {
+ DPRINTK(ERR, "failed to allocate hw context\n");
+ return -ENOMEM;
+ }
+ memset(addr, 0, sizeof(struct netxen_ring_ctx));
+ adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
+ adapter->ctx_desc->ctx_id = cpu_to_le32(adapter->portnum);
+ adapter->ctx_desc->cmd_consumer_offset =
+ cpu_to_le64(adapter->ctx_desc_phys_addr +
+ sizeof(struct netxen_ring_ctx));
+ adapter->cmd_consumer =
+ (__le32 *)(((char *)addr) + sizeof(struct netxen_ring_ctx));
+
+ /* cmd desc ring */
+ addr = pci_alloc_consistent(adapter->pdev,
+ sizeof(struct cmd_desc_type0) *
+ adapter->max_tx_desc_count,
+ &hw->cmd_desc_phys_addr);
+
+ if (addr == NULL) {
+ printk(KERN_ERR "%s failed to allocate tx desc ring\n",
+ netxen_nic_driver_name);
+ return -ENOMEM;
+ }
+
+ hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ /* rx desc ring */
+ rds_ring = &recv_ctx->rds_rings[ring];
+ addr = pci_alloc_consistent(adapter->pdev,
+ RCV_DESC_RINGSIZE,
+ &rds_ring->phys_addr);
+ if (addr == NULL) {
+ printk(KERN_ERR "%s failed to allocate rx "
+ "desc ring[%d]\n",
+ netxen_nic_driver_name, ring);
+ err = -ENOMEM;
+ goto err_out_free;
+ }
+ rds_ring->desc_head = (struct rcv_desc *)addr;
+
+ if (adapter->fw_major < 4)
+ rds_ring->crb_rcv_producer =
+ recv_crb_registers[adapter->portnum].
+ crb_rcv_producer[ring];
+ }
+
+ /* status desc ring */
+ addr = pci_alloc_consistent(adapter->pdev,
+ STATUS_DESC_RINGSIZE,
+ &recv_ctx->rcv_status_desc_phys_addr);
+ if (addr == NULL) {
+ printk(KERN_ERR "%s failed to allocate sts desc ring\n",
+ netxen_nic_driver_name);
+ err = -ENOMEM;
+ goto err_out_free;
+ }
+ recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
+
+ if (adapter->fw_major < 4)
+ recv_ctx->crb_sts_consumer =
+ recv_crb_registers[adapter->portnum].
+ crb_sts_consumer;
+ }
+
+ if (adapter->fw_major >= 4) {
+ adapter->intr_scheme = INTR_SCHEME_PERPORT;
+ adapter->msi_mode = MSI_MODE_MULTIFUNC;
+
+ err = nx_fw_cmd_create_rx_ctx(adapter);
+ if (err)
+ goto err_out_free;
+ err = nx_fw_cmd_create_tx_ctx(adapter);
+ if (err)
+ goto err_out_free;
+ } else {
+
+ adapter->intr_scheme = adapter->pci_read_normalize(adapter,
+ CRB_NIC_CAPABILITIES_FW);
+ adapter->msi_mode = adapter->pci_read_normalize(adapter,
+ CRB_NIC_MSI_MODE_FW);
+ adapter->crb_intr_mask = sw_int_mask[adapter->portnum];
+
+ err = netxen_init_old_ctx(adapter);
+ if (err) {
+ netxen_free_hw_resources(adapter);
+ return err;
+ }
+
+ }
+
+ return 0;
+
+err_out_free:
+ netxen_free_hw_resources(adapter);
+ return err;
+}
+
+void netxen_free_hw_resources(struct netxen_adapter *adapter)
+{
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+ int ctx, ring;
+
+ if (adapter->fw_major >= 4) {
+ nx_fw_cmd_destroy_tx_ctx(adapter);
+ nx_fw_cmd_destroy_rx_ctx(adapter);
+ }
+
+ if (adapter->ctx_desc != NULL) {
+ pci_free_consistent(adapter->pdev,
+ sizeof(struct netxen_ring_ctx) +
+ sizeof(uint32_t),
+ adapter->ctx_desc,
+ adapter->ctx_desc_phys_addr);
+ adapter->ctx_desc = NULL;
+ }
+
+ if (adapter->ahw.cmd_desc_head != NULL) {
+ pci_free_consistent(adapter->pdev,
+ sizeof(struct cmd_desc_type0) *
+ adapter->max_tx_desc_count,
+ adapter->ahw.cmd_desc_head,
+ adapter->ahw.cmd_desc_phys_addr);
+ adapter->ahw.cmd_desc_head = NULL;
+ }
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ if (rds_ring->desc_head != NULL) {
+ pci_free_consistent(adapter->pdev,
+ RCV_DESC_RINGSIZE,
+ rds_ring->desc_head,
+ rds_ring->phys_addr);
+ rds_ring->desc_head = NULL;
+ }
+ }
+
+ if (recv_ctx->rcv_status_desc_head != NULL) {
+ pci_free_consistent(adapter->pdev,
+ STATUS_DESC_RINGSIZE,
+ recv_ctx->rcv_status_desc_head,
+ recv_ctx->rcv_status_desc_phys_addr);
+ recv_ctx->rcv_status_desc_head = NULL;
+ }
+ }
+}
+
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index 723487bf200..48ee06b6f4e 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -93,17 +93,21 @@ static void
netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
{
struct netxen_adapter *adapter = netdev_priv(dev);
+ unsigned long flags;
u32 fw_major = 0;
u32 fw_minor = 0;
u32 fw_build = 0;
strncpy(drvinfo->driver, netxen_nic_driver_name, 32);
strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32);
- fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_FW_VERSION_MAJOR));
- fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_FW_VERSION_MINOR));
- fw_build = readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB));
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ fw_major = adapter->pci_read_normalize(adapter,
+ NETXEN_FW_VERSION_MAJOR);
+ fw_minor = adapter->pci_read_normalize(adapter,
+ NETXEN_FW_VERSION_MINOR);
+ fw_build = adapter->pci_read_normalize(adapter,
+ NETXEN_FW_VERSION_SUB);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build);
strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
@@ -159,9 +163,16 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
switch ((netxen_brdtype_t) boardinfo->board_type) {
case NETXEN_BRDTYPE_P2_SB35_4G:
case NETXEN_BRDTYPE_P2_SB31_2G:
+ case NETXEN_BRDTYPE_P3_REF_QG:
+ case NETXEN_BRDTYPE_P3_4_GB:
+ case NETXEN_BRDTYPE_P3_4_GB_MM:
+ case NETXEN_BRDTYPE_P3_10000_BASE_T:
+
ecmd->supported |= SUPPORTED_Autoneg;
ecmd->advertising |= ADVERTISED_Autoneg;
case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+ case NETXEN_BRDTYPE_P3_10G_CX4:
+ case NETXEN_BRDTYPE_P3_10G_CX4_LP:
ecmd->supported |= SUPPORTED_TP;
ecmd->advertising |= ADVERTISED_TP;
ecmd->port = PORT_TP;
@@ -171,12 +182,17 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
break;
case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
+ case NETXEN_BRDTYPE_P3_IMEZ:
+ case NETXEN_BRDTYPE_P3_XG_LOM:
+ case NETXEN_BRDTYPE_P3_HMEZ:
ecmd->supported |= SUPPORTED_MII;
ecmd->advertising |= ADVERTISED_MII;
ecmd->port = PORT_FIBRE;
ecmd->autoneg = AUTONEG_DISABLE;
break;
case NETXEN_BRDTYPE_P2_SB31_10G:
+ case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
+ case NETXEN_BRDTYPE_P3_10G_XFP:
ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising |= ADVERTISED_FIBRE;
ecmd->port = PORT_FIBRE;
@@ -349,19 +365,18 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
{
struct netxen_adapter *adapter = netdev_priv(dev);
__u32 mode, *regs_buff = p;
- void __iomem *addr;
int i, window;
memset(p, 0, NETXEN_NIC_REGS_LEN);
regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
(adapter->pdev)->device;
/* which mode */
- NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_MODE, &regs_buff[0]);
+ adapter->hw_read_wx(adapter, NETXEN_NIU_MODE, &regs_buff[0], 4);
mode = regs_buff[0];
/* Common registers to all the modes */
- NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER,
- &regs_buff[2]);
+ adapter->hw_read_wx(adapter,
+ NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER, &regs_buff[2], 4);
/* GB/XGB Mode */
mode = (mode / 2) - 1;
window = 0;
@@ -372,9 +387,9 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
window = adapter->physical_port *
NETXEN_NIC_PORT_WINDOW;
- NETXEN_NIC_LOCKED_READ_REG(niu_registers[mode].
- reg[i - 3] + window,
- &regs_buff[i]);
+ adapter->hw_read_wx(adapter,
+ niu_registers[mode].reg[i - 3] + window,
+ &regs_buff[i], 4);
}
}
@@ -398,7 +413,7 @@ static u32 netxen_nic_test_link(struct net_device *dev)
return !val;
}
} else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
- val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
+ val = adapter->pci_read_normalize(adapter, CRB_XG_STATE);
return (val == XG_LINK_UP) ? 0 : 1;
}
return -EIO;
@@ -427,6 +442,7 @@ netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
return 0;
}
+#if 0
static int
netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
u8 * bytes)
@@ -447,7 +463,6 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
}
printk(KERN_INFO "%s: flash unlocked. \n",
netxen_nic_driver_name);
- last_schedule_time = jiffies;
ret = netxen_flash_erase_secondary(adapter);
if (ret != FLASH_SUCCESS) {
printk(KERN_ERR "%s: Flash erase failed.\n",
@@ -497,6 +512,7 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
return netxen_rom_fast_write_words(adapter, offset, bytes, eeprom->len);
}
+#endif /* 0 */
static void
netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
@@ -508,9 +524,9 @@ netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
ring->rx_jumbo_pending = 0;
for (i = 0; i < MAX_RCV_CTX; ++i) {
ring->rx_pending += adapter->recv_ctx[i].
- rcv_desc[RCV_DESC_NORMAL_CTXID].max_rx_desc_count;
+ rds_rings[RCV_DESC_NORMAL_CTXID].max_rx_desc_count;
ring->rx_jumbo_pending += adapter->recv_ctx[i].
- rcv_desc[RCV_DESC_JUMBO_CTXID].max_rx_desc_count;
+ rds_rings[RCV_DESC_JUMBO_CTXID].max_rx_desc_count;
}
ring->tx_pending = adapter->max_tx_desc_count;
@@ -655,7 +671,7 @@ static int netxen_nic_reg_test(struct net_device *dev)
data_written = (u32)0xa5a5a5a5;
netxen_nic_reg_write(adapter, CRB_SCRATCHPAD_TEST, data_written);
- data_read = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_SCRATCHPAD_TEST));
+ data_read = adapter->pci_read_normalize(adapter, CRB_SCRATCHPAD_TEST);
if (data_written != data_read)
return 1;
@@ -736,6 +752,117 @@ static int netxen_nic_set_rx_csum(struct net_device *dev, u32 data)
return 0;
}
+static u32 netxen_nic_get_tso(struct net_device *dev)
+{
+ struct netxen_adapter *adapter = netdev_priv(dev);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ return (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) != 0;
+
+ return (dev->features & NETIF_F_TSO) != 0;
+}
+
+static int netxen_nic_set_tso(struct net_device *dev, u32 data)
+{
+ if (data) {
+ struct netxen_adapter *adapter = netdev_priv(dev);
+
+ dev->features |= NETIF_F_TSO;
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ dev->features |= NETIF_F_TSO6;
+ } else
+ dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+
+ return 0;
+}
+
+/*
+ * Set the coalescing parameters. Currently only normal is supported.
+ * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
+ * firmware coalescing to default.
+ */
+static int netxen_set_intr_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *ethcoal)
+{
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+
+ if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ return -EINVAL;
+
+ if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+ return -EINVAL;
+
+ /*
+ * Return Error if unsupported values or
+ * unsupported parameters are set.
+ */
+ if (ethcoal->rx_coalesce_usecs > 0xffff ||
+ ethcoal->rx_max_coalesced_frames > 0xffff ||
+ ethcoal->tx_coalesce_usecs > 0xffff ||
+ ethcoal->tx_max_coalesced_frames > 0xffff ||
+ ethcoal->rx_coalesce_usecs_irq ||
+ ethcoal->rx_max_coalesced_frames_irq ||
+ ethcoal->tx_coalesce_usecs_irq ||
+ ethcoal->tx_max_coalesced_frames_irq ||
+ ethcoal->stats_block_coalesce_usecs ||
+ ethcoal->use_adaptive_rx_coalesce ||
+ ethcoal->use_adaptive_tx_coalesce ||
+ ethcoal->pkt_rate_low ||
+ ethcoal->rx_coalesce_usecs_low ||
+ ethcoal->rx_max_coalesced_frames_low ||
+ ethcoal->tx_coalesce_usecs_low ||
+ ethcoal->tx_max_coalesced_frames_low ||
+ ethcoal->pkt_rate_high ||
+ ethcoal->rx_coalesce_usecs_high ||
+ ethcoal->rx_max_coalesced_frames_high ||
+ ethcoal->tx_coalesce_usecs_high ||
+ ethcoal->tx_max_coalesced_frames_high)
+ return -EINVAL;
+
+ if (!ethcoal->rx_coalesce_usecs ||
+ !ethcoal->rx_max_coalesced_frames) {
+ adapter->coal.flags = NETXEN_NIC_INTR_DEFAULT;
+ adapter->coal.normal.data.rx_time_us =
+ NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US;
+ adapter->coal.normal.data.rx_packets =
+ NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS;
+ } else {
+ adapter->coal.flags = 0;
+ adapter->coal.normal.data.rx_time_us =
+ ethcoal->rx_coalesce_usecs;
+ adapter->coal.normal.data.rx_packets =
+ ethcoal->rx_max_coalesced_frames;
+ }
+ adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs;
+ adapter->coal.normal.data.tx_packets =
+ ethcoal->tx_max_coalesced_frames;
+
+ netxen_config_intr_coalesce(adapter);
+
+ return 0;
+}
+
+static int netxen_get_intr_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *ethcoal)
+{
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+
+ if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ return -EINVAL;
+
+ if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+ return -EINVAL;
+
+ ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us;
+ ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us;
+ ethcoal->rx_max_coalesced_frames =
+ adapter->coal.normal.data.rx_packets;
+ ethcoal->tx_max_coalesced_frames =
+ adapter->coal.normal.data.tx_packets;
+
+ return 0;
+}
+
struct ethtool_ops netxen_nic_ethtool_ops = {
.get_settings = netxen_nic_get_settings,
.set_settings = netxen_nic_set_settings,
@@ -745,17 +872,22 @@ struct ethtool_ops netxen_nic_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_eeprom_len = netxen_nic_get_eeprom_len,
.get_eeprom = netxen_nic_get_eeprom,
+#if 0
.set_eeprom = netxen_nic_set_eeprom,
+#endif
.get_ringparam = netxen_nic_get_ringparam,
.get_pauseparam = netxen_nic_get_pauseparam,
.set_pauseparam = netxen_nic_set_pauseparam,
.set_tx_csum = ethtool_op_set_tx_csum,
.set_sg = ethtool_op_set_sg,
- .set_tso = ethtool_op_set_tso,
+ .get_tso = netxen_nic_get_tso,
+ .set_tso = netxen_nic_set_tso,
.self_test = netxen_nic_diag_test,
.get_strings = netxen_nic_get_strings,
.get_ethtool_stats = netxen_nic_get_ethtool_stats,
.get_sset_count = netxen_get_sset_count,
.get_rx_csum = netxen_nic_get_rx_csum,
.set_rx_csum = netxen_nic_set_rx_csum,
+ .get_coalesce = netxen_get_intr_coalesce,
+ .set_coalesce = netxen_set_intr_coalesce,
};
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
index 24d027e29c4..3ce13e451aa 100644
--- a/drivers/net/netxen/netxen_nic_hdr.h
+++ b/drivers/net/netxen/netxen_nic_hdr.h
@@ -126,7 +126,8 @@ enum {
NETXEN_HW_PEGR0_CRB_AGT_ADR,
NETXEN_HW_PEGR1_CRB_AGT_ADR,
NETXEN_HW_PEGR2_CRB_AGT_ADR,
- NETXEN_HW_PEGR3_CRB_AGT_ADR
+ NETXEN_HW_PEGR3_CRB_AGT_ADR,
+ NETXEN_HW_PEGN4_CRB_AGT_ADR
};
/* Hub 5 */
@@ -316,6 +317,8 @@ enum {
((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN2_CRB_AGT_ADR)
#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN3 \
((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN3_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN4 \
+ ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN4_CRB_AGT_ADR)
#define NETXEN_HW_CRB_HUB_AGT_ADR_PGNC \
((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGNC_CRB_AGT_ADR)
#define NETXEN_HW_CRB_HUB_AGT_ADR_PGR0 \
@@ -435,6 +438,7 @@ enum {
#define NETXEN_CRB_ROMUSB \
NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_ROMUSB)
#define NETXEN_CRB_I2Q NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_I2Q)
+#define NETXEN_CRB_SMB NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_SMB)
#define NETXEN_CRB_MAX NETXEN_PCI_CRB_WINDOW(64)
#define NETXEN_CRB_PCIX_HOST NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PH)
@@ -446,6 +450,7 @@ enum {
#define NETXEN_CRB_PEG_NET_D NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGND)
#define NETXEN_CRB_PEG_NET_I NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGNI)
#define NETXEN_CRB_DDR_NET NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_MN)
+#define NETXEN_CRB_QDR_NET NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_SN)
#define NETXEN_CRB_PCIX_MD NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PS)
#define NETXEN_CRB_PCIE NETXEN_CRB_PCIX_MD
@@ -461,11 +466,20 @@ enum {
#define ISR_INT_TARGET_MASK_F2 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F2))
#define ISR_INT_TARGET_STATUS_F3 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F3))
#define ISR_INT_TARGET_MASK_F3 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F3))
+#define ISR_INT_TARGET_STATUS_F4 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F4))
+#define ISR_INT_TARGET_MASK_F4 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F4))
+#define ISR_INT_TARGET_STATUS_F5 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F5))
+#define ISR_INT_TARGET_MASK_F5 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F5))
+#define ISR_INT_TARGET_STATUS_F6 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F6))
+#define ISR_INT_TARGET_MASK_F6 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F6))
+#define ISR_INT_TARGET_STATUS_F7 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F7))
+#define ISR_INT_TARGET_MASK_F7 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F7))
#define NETXEN_PCI_MAPSIZE 128
#define NETXEN_PCI_DDR_NET (0x00000000UL)
#define NETXEN_PCI_QDR_NET (0x04000000UL)
#define NETXEN_PCI_DIRECT_CRB (0x04400000UL)
+#define NETXEN_PCI_CAMQM (0x04800000UL)
#define NETXEN_PCI_CAMQM_MAX (0x04ffffffUL)
#define NETXEN_PCI_OCM0 (0x05000000UL)
#define NETXEN_PCI_OCM0_MAX (0x050fffffUL)
@@ -474,6 +488,13 @@ enum {
#define NETXEN_PCI_CRBSPACE (0x06000000UL)
#define NETXEN_PCI_128MB_SIZE (0x08000000UL)
#define NETXEN_PCI_32MB_SIZE (0x02000000UL)
+#define NETXEN_PCI_2MB_SIZE (0x00200000UL)
+
+#define NETXEN_PCI_MN_2M (0)
+#define NETXEN_PCI_MS_2M (0x80000)
+#define NETXEN_PCI_OCM0_2M (0x000c0000UL)
+#define NETXEN_PCI_CAMQM_2M_BASE (0x000ff800UL)
+#define NETXEN_PCI_CAMQM_2M_END (0x04800800UL)
#define NETXEN_CRB_CAM NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_CAM)
@@ -484,7 +505,14 @@ enum {
#define NETXEN_ADDR_OCM1 (0x0000000200400000ULL)
#define NETXEN_ADDR_OCM1_MAX (0x00000002004fffffULL)
#define NETXEN_ADDR_QDR_NET (0x0000000300000000ULL)
-#define NETXEN_ADDR_QDR_NET_MAX (0x00000003003fffffULL)
+#define NETXEN_ADDR_QDR_NET_MAX_P2 (0x00000003003fffffULL)
+#define NETXEN_ADDR_QDR_NET_MAX_P3 (0x0000000303ffffffULL)
+
+/*
+ * Register offsets for MN
+ */
+#define NETXEN_MIU_CONTROL (0x000)
+#define NETXEN_MIU_MN_CONTROL (NETXEN_CRB_DDR_NET+NETXEN_MIU_CONTROL)
/* 200ms delay in each loop */
#define NETXEN_NIU_PHY_WAITLEN 200000
@@ -550,6 +578,9 @@ enum {
#define NETXEN_MULTICAST_ADDR_HI_2 (NETXEN_CRB_NIU + 0x1018)
#define NETXEN_MULTICAST_ADDR_HI_3 (NETXEN_CRB_NIU + 0x101c)
+#define NETXEN_UNICAST_ADDR_BASE (NETXEN_CRB_NIU + 0x1080)
+#define NETXEN_MULTICAST_ADDR_BASE (NETXEN_CRB_NIU + 0x1100)
+
#define NETXEN_NIU_GB_MAC_CONFIG_0(I) \
(NETXEN_CRB_NIU + 0x30000 + (I)*0x10000)
#define NETXEN_NIU_GB_MAC_CONFIG_1(I) \
@@ -630,16 +661,76 @@ enum {
#define NETXEN_NIU_XG1_CONTROL_CHAR_CNT (NETXEN_CRB_NIU + 0x80054)
#define NETXEN_NIU_XG1_PAUSE_FRAME_CNT (NETXEN_CRB_NIU + 0x80058)
+/* P3 802.3ap */
+#define NETXEN_NIU_AP_MAC_CONFIG_0(I) (NETXEN_CRB_NIU+0xa0000+(I)*0x10000)
+#define NETXEN_NIU_AP_MAC_CONFIG_1(I) (NETXEN_CRB_NIU+0xa0004+(I)*0x10000)
+#define NETXEN_NIU_AP_MAC_IPG_IFG(I) (NETXEN_CRB_NIU+0xa0008+(I)*0x10000)
+#define NETXEN_NIU_AP_HALF_DUPLEX_CTRL(I) (NETXEN_CRB_NIU+0xa000c+(I)*0x10000)
+#define NETXEN_NIU_AP_MAX_FRAME_SIZE(I) (NETXEN_CRB_NIU+0xa0010+(I)*0x10000)
+#define NETXEN_NIU_AP_TEST_REG(I) (NETXEN_CRB_NIU+0xa001c+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_CONFIG(I) (NETXEN_CRB_NIU+0xa0020+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_COMMAND(I) (NETXEN_CRB_NIU+0xa0024+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_ADDR(I) (NETXEN_CRB_NIU+0xa0028+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_CTRL(I) (NETXEN_CRB_NIU+0xa002c+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_STATUS(I) (NETXEN_CRB_NIU+0xa0030+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_INDICATE(I) (NETXEN_CRB_NIU+0xa0034+(I)*0x10000)
+#define NETXEN_NIU_AP_INTERFACE_CTRL(I) (NETXEN_CRB_NIU+0xa0038+(I)*0x10000)
+#define NETXEN_NIU_AP_INTERFACE_STATUS(I) (NETXEN_CRB_NIU+0xa003c+(I)*0x10000)
+#define NETXEN_NIU_AP_STATION_ADDR_0(I) (NETXEN_CRB_NIU+0xa0040+(I)*0x10000)
+#define NETXEN_NIU_AP_STATION_ADDR_1(I) (NETXEN_CRB_NIU+0xa0044+(I)*0x10000)
+
+/*
+ * Register offsets for MN
+ */
+#define MIU_CONTROL (0x000)
+#define MIU_TEST_AGT_CTRL (0x090)
+#define MIU_TEST_AGT_ADDR_LO (0x094)
+#define MIU_TEST_AGT_ADDR_HI (0x098)
+#define MIU_TEST_AGT_WRDATA_LO (0x0a0)
+#define MIU_TEST_AGT_WRDATA_HI (0x0a4)
+#define MIU_TEST_AGT_WRDATA(i) (0x0a0+(4*(i)))
+#define MIU_TEST_AGT_RDDATA_LO (0x0a8)
+#define MIU_TEST_AGT_RDDATA_HI (0x0ac)
+#define MIU_TEST_AGT_RDDATA(i) (0x0a8+(4*(i)))
+#define MIU_TEST_AGT_ADDR_MASK 0xfffffff8
+#define MIU_TEST_AGT_UPPER_ADDR(off) (0)
+
+/* MIU_TEST_AGT_CTRL flags. work for SIU as well */
+#define MIU_TA_CTL_START 1
+#define MIU_TA_CTL_ENABLE 2
+#define MIU_TA_CTL_WRITE 4
+#define MIU_TA_CTL_BUSY 8
+
+#define SIU_TEST_AGT_CTRL (0x060)
+#define SIU_TEST_AGT_ADDR_LO (0x064)
+#define SIU_TEST_AGT_ADDR_HI (0x078)
+#define SIU_TEST_AGT_WRDATA_LO (0x068)
+#define SIU_TEST_AGT_WRDATA_HI (0x06c)
+#define SIU_TEST_AGT_WRDATA(i) (0x068+(4*(i)))
+#define SIU_TEST_AGT_RDDATA_LO (0x070)
+#define SIU_TEST_AGT_RDDATA_HI (0x074)
+#define SIU_TEST_AGT_RDDATA(i) (0x070+(4*(i)))
+
+#define SIU_TEST_AGT_ADDR_MASK 0x3ffff8
+#define SIU_TEST_AGT_UPPER_ADDR(off) ((off)>>22)
+
/* XG Link status */
#define XG_LINK_UP 0x10
#define XG_LINK_DOWN 0x20
+#define XG_LINK_UP_P3 0x01
+#define XG_LINK_DOWN_P3 0x02
+#define XG_LINK_STATE_P3_MASK 0xf
+#define XG_LINK_STATE_P3(pcifn,val) \
+ (((val) >> ((pcifn) * 4)) & XG_LINK_STATE_P3_MASK)
+
#define NETXEN_CAM_RAM_BASE (NETXEN_CRB_CAM + 0x02000)
#define NETXEN_CAM_RAM(reg) (NETXEN_CAM_RAM_BASE + (reg))
#define NETXEN_FW_VERSION_MAJOR (NETXEN_CAM_RAM(0x150))
#define NETXEN_FW_VERSION_MINOR (NETXEN_CAM_RAM(0x154))
#define NETXEN_FW_VERSION_SUB (NETXEN_CAM_RAM(0x158))
#define NETXEN_ROM_LOCK_ID (NETXEN_CAM_RAM(0x100))
+#define NETXEN_CRB_WIN_LOCK_ID (NETXEN_CAM_RAM(0x124))
#define NETXEN_PHY_LOCK_ID (NETXEN_CAM_RAM(0x120))
@@ -654,30 +745,71 @@ enum {
#define PCIX_INT_VECTOR (0x10100)
#define PCIX_INT_MASK (0x10104)
-#define PCIX_MN_WINDOW_F0 (0x10200)
-#define PCIX_MN_WINDOW(_f) (PCIX_MN_WINDOW_F0 + (0x20 * (_f)))
-#define PCIX_MS_WINDOW (0x10204)
-#define PCIX_SN_WINDOW_F0 (0x10208)
-#define PCIX_SN_WINDOW(_f) (PCIX_SN_WINDOW_F0 + (0x20 * (_f)))
#define PCIX_CRB_WINDOW (0x10210)
#define PCIX_CRB_WINDOW_F0 (0x10210)
#define PCIX_CRB_WINDOW_F1 (0x10230)
#define PCIX_CRB_WINDOW_F2 (0x10250)
#define PCIX_CRB_WINDOW_F3 (0x10270)
+#define PCIX_CRB_WINDOW_F4 (0x102ac)
+#define PCIX_CRB_WINDOW_F5 (0x102bc)
+#define PCIX_CRB_WINDOW_F6 (0x102cc)
+#define PCIX_CRB_WINDOW_F7 (0x102dc)
+#define PCIE_CRB_WINDOW_REG(func) (((func) < 4) ? \
+ (PCIX_CRB_WINDOW_F0 + (0x20 * (func))) :\
+ (PCIX_CRB_WINDOW_F4 + (0x10 * ((func)-4))))
+
+#define PCIX_MN_WINDOW (0x10200)
+#define PCIX_MN_WINDOW_F0 (0x10200)
+#define PCIX_MN_WINDOW_F1 (0x10220)
+#define PCIX_MN_WINDOW_F2 (0x10240)
+#define PCIX_MN_WINDOW_F3 (0x10260)
+#define PCIX_MN_WINDOW_F4 (0x102a0)
+#define PCIX_MN_WINDOW_F5 (0x102b0)
+#define PCIX_MN_WINDOW_F6 (0x102c0)
+#define PCIX_MN_WINDOW_F7 (0x102d0)
+#define PCIE_MN_WINDOW_REG(func) (((func) < 4) ? \
+ (PCIX_MN_WINDOW_F0 + (0x20 * (func))) :\
+ (PCIX_MN_WINDOW_F4 + (0x10 * ((func)-4))))
+
+#define PCIX_SN_WINDOW (0x10208)
+#define PCIX_SN_WINDOW_F0 (0x10208)
+#define PCIX_SN_WINDOW_F1 (0x10228)
+#define PCIX_SN_WINDOW_F2 (0x10248)
+#define PCIX_SN_WINDOW_F3 (0x10268)
+#define PCIX_SN_WINDOW_F4 (0x102a8)
+#define PCIX_SN_WINDOW_F5 (0x102b8)
+#define PCIX_SN_WINDOW_F6 (0x102c8)
+#define PCIX_SN_WINDOW_F7 (0x102d8)
+#define PCIE_SN_WINDOW_REG(func) (((func) < 4) ? \
+ (PCIX_SN_WINDOW_F0 + (0x20 * (func))) :\
+ (PCIX_SN_WINDOW_F4 + (0x10 * ((func)-4))))
#define PCIX_TARGET_STATUS (0x10118)
+#define PCIX_TARGET_STATUS_F1 (0x10160)
+#define PCIX_TARGET_STATUS_F2 (0x10164)
+#define PCIX_TARGET_STATUS_F3 (0x10168)
+#define PCIX_TARGET_STATUS_F4 (0x10360)
+#define PCIX_TARGET_STATUS_F5 (0x10364)
+#define PCIX_TARGET_STATUS_F6 (0x10368)
+#define PCIX_TARGET_STATUS_F7 (0x1036c)
+
#define PCIX_TARGET_MASK (0x10128)
-#define PCIX_TARGET_STATUS_F1 (0x10160)
-#define PCIX_TARGET_MASK_F1 (0x10170)
-#define PCIX_TARGET_STATUS_F2 (0x10164)
-#define PCIX_TARGET_MASK_F2 (0x10174)
-#define PCIX_TARGET_STATUS_F3 (0x10168)
-#define PCIX_TARGET_MASK_F3 (0x10178)
+#define PCIX_TARGET_MASK_F1 (0x10170)
+#define PCIX_TARGET_MASK_F2 (0x10174)
+#define PCIX_TARGET_MASK_F3 (0x10178)
+#define PCIX_TARGET_MASK_F4 (0x10370)
+#define PCIX_TARGET_MASK_F5 (0x10374)
+#define PCIX_TARGET_MASK_F6 (0x10378)
+#define PCIX_TARGET_MASK_F7 (0x1037c)
#define PCIX_MSI_F0 (0x13000)
#define PCIX_MSI_F1 (0x13004)
#define PCIX_MSI_F2 (0x13008)
#define PCIX_MSI_F3 (0x1300c)
+#define PCIX_MSI_F4 (0x13010)
+#define PCIX_MSI_F5 (0x13014)
+#define PCIX_MSI_F6 (0x13018)
+#define PCIX_MSI_F7 (0x1301c)
#define PCIX_MSI_F(i) (0x13000+((i)*4))
#define PCIX_PS_MEM_SPACE (0x90000)
@@ -695,11 +827,102 @@ enum {
#define PCIE_SEM2_UNLOCK (0x1c014) /* Flash unlock */
#define PCIE_SEM3_LOCK (0x1c018) /* Phy lock */
#define PCIE_SEM3_UNLOCK (0x1c01c) /* Phy unlock */
-
+#define PCIE_SEM5_LOCK (0x1c028) /* API lock */
+#define PCIE_SEM5_UNLOCK (0x1c02c) /* API unlock */
+#define PCIE_SEM6_LOCK (0x1c030) /* sw lock */
+#define PCIE_SEM6_UNLOCK (0x1c034) /* sw unlock */
+#define PCIE_SEM7_LOCK (0x1c038) /* crb win lock */
+#define PCIE_SEM7_UNLOCK (0x1c03c) /* crbwin unlock*/
+
+#define PCIE_SETUP_FUNCTION (0x12040)
+#define PCIE_SETUP_FUNCTION2 (0x12048)
#define PCIE_TGT_SPLIT_CHICKEN (0x12080)
+#define PCIE_CHICKEN3 (0x120c8)
#define PCIE_MAX_MASTER_SPLIT (0x14048)
+#define NETXEN_PORT_MODE_NONE 0
+#define NETXEN_PORT_MODE_XG 1
+#define NETXEN_PORT_MODE_GB 2
+#define NETXEN_PORT_MODE_802_3_AP 3
+#define NETXEN_PORT_MODE_AUTO_NEG 4
+#define NETXEN_PORT_MODE_AUTO_NEG_1G 5
+#define NETXEN_PORT_MODE_AUTO_NEG_XG 6
+#define NETXEN_PORT_MODE_ADDR (NETXEN_CAM_RAM(0x24))
+#define NETXEN_WOL_PORT_MODE (NETXEN_CAM_RAM(0x198))
+
#define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14)
+#define ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
+
+/*
+ * PCI Interrupt Vector Values.
+ */
+#define PCIX_INT_VECTOR_BIT_F0 0x0080
+#define PCIX_INT_VECTOR_BIT_F1 0x0100
+#define PCIX_INT_VECTOR_BIT_F2 0x0200
+#define PCIX_INT_VECTOR_BIT_F3 0x0400
+#define PCIX_INT_VECTOR_BIT_F4 0x0800
+#define PCIX_INT_VECTOR_BIT_F5 0x1000
+#define PCIX_INT_VECTOR_BIT_F6 0x2000
+#define PCIX_INT_VECTOR_BIT_F7 0x4000
+
+struct netxen_legacy_intr_set {
+ uint32_t int_vec_bit;
+ uint32_t tgt_status_reg;
+ uint32_t tgt_mask_reg;
+ uint32_t pci_int_reg;
+};
+
+#define NX_LEGACY_INTR_CONFIG \
+{ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F0, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(0) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F1, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F1, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F1, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(1) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F2, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F2, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F2, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(2) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F3, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F3, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F3, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(3) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F4, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F4, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F4, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(4) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F5, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F5, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F5, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(5) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F6, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F6, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F6, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(6) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F7, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F7, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F7, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(7) }, \
+}
+
#endif /* __NETXEN_NIC_HDR_H_ */
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index c43d06b8de9..96a3bc6426e 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -38,242 +38,262 @@
#include <net/ip.h>
-struct netxen_recv_crb recv_crb_registers[] = {
- /*
- * Instance 0.
- */
- {
- /* rcv_desc_crb: */
- {
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x100),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x104),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x108),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x10c),
-
- },
- /* Jumbo frames */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x110),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x114),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x118),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x11c),
- },
- /* LRO */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x120),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x124),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x128),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x12c),
- }
- },
- /* crb_rcvstatus_ring: */
- NETXEN_NIC_REG(0x130),
- /* crb_rcv_status_producer: */
- NETXEN_NIC_REG(0x134),
- /* crb_rcv_status_consumer: */
- NETXEN_NIC_REG(0x138),
- /* crb_rcvpeg_state: */
- NETXEN_NIC_REG(0x13c),
- /* crb_status_ring_size */
- NETXEN_NIC_REG(0x140),
-
- },
- /*
- * Instance 1,
- */
- {
- /* rcv_desc_crb: */
- {
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x144),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x148),
- /* crb_globalrcv_ring: */
- NETXEN_NIC_REG(0x14c),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x150),
-
- },
- /* Jumbo frames */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x154),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x158),
- /* crb_globalrcv_ring: */
- NETXEN_NIC_REG(0x15c),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x160),
- },
- /* LRO */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x164),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x168),
- /* crb_globalrcv_ring: */
- NETXEN_NIC_REG(0x16c),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x170),
- }
-
- },
- /* crb_rcvstatus_ring: */
- NETXEN_NIC_REG(0x174),
- /* crb_rcv_status_producer: */
- NETXEN_NIC_REG(0x178),
- /* crb_rcv_status_consumer: */
- NETXEN_NIC_REG(0x17c),
- /* crb_rcvpeg_state: */
- NETXEN_NIC_REG(0x180),
- /* crb_status_ring_size */
- NETXEN_NIC_REG(0x184),
- },
- /*
- * Instance 2,
- */
- {
- {
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x1d8),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x1dc),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x1f0),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x1f4),
- },
- /* Jumbo frames */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x1f8),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x1fc),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x200),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x204),
- },
- /* LRO */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x208),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x20c),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x210),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x214),
- }
- },
- /* crb_rcvstatus_ring: */
- NETXEN_NIC_REG(0x218),
- /* crb_rcv_status_producer: */
- NETXEN_NIC_REG(0x21c),
- /* crb_rcv_status_consumer: */
- NETXEN_NIC_REG(0x220),
- /* crb_rcvpeg_state: */
- NETXEN_NIC_REG(0x224),
- /* crb_status_ring_size */
- NETXEN_NIC_REG(0x228),
- },
- /*
- * Instance 3,
- */
- {
- {
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x22c),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x230),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x234),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x238),
- },
- /* Jumbo frames */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x23c),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x240),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x244),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x248),
- },
- /* LRO */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x24c),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x250),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x254),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x258),
- }
- },
- /* crb_rcvstatus_ring: */
- NETXEN_NIC_REG(0x25c),
- /* crb_rcv_status_producer: */
- NETXEN_NIC_REG(0x260),
- /* crb_rcv_status_consumer: */
- NETXEN_NIC_REG(0x264),
- /* crb_rcvpeg_state: */
- NETXEN_NIC_REG(0x268),
- /* crb_status_ring_size */
- NETXEN_NIC_REG(0x26c),
- },
+#define MASK(n) ((1ULL<<(n))-1)
+#define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff))
+#define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff))
+#define MS_WIN(addr) (addr & 0x0ffc0000)
+
+#define GET_MEM_OFFS_2M(addr) (addr & MASK(18))
+
+#define CRB_BLK(off) ((off >> 20) & 0x3f)
+#define CRB_SUBBLK(off) ((off >> 16) & 0xf)
+#define CRB_WINDOW_2M (0x130060)
+#define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000))
+#define CRB_INDIRECT_2M (0x1e0000UL)
+
+#define CRB_WIN_LOCK_TIMEOUT 100000000
+static crb_128M_2M_block_map_t crb_128M_2M_map[64] = {
+ {{{0, 0, 0, 0} } }, /* 0: PCI */
+ {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */
+ {1, 0x0110000, 0x0120000, 0x130000},
+ {1, 0x0120000, 0x0122000, 0x124000},
+ {1, 0x0130000, 0x0132000, 0x126000},
+ {1, 0x0140000, 0x0142000, 0x128000},
+ {1, 0x0150000, 0x0152000, 0x12a000},
+ {1, 0x0160000, 0x0170000, 0x110000},
+ {1, 0x0170000, 0x0172000, 0x12e000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x01e0000, 0x01e0800, 0x122000},
+ {0, 0x0000000, 0x0000000, 0x000000} } },
+ {{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */
+ {{{0, 0, 0, 0} } }, /* 3: */
+ {{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */
+ {{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE */
+ {{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU */
+ {{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM */
+ {{{1, 0x0800000, 0x0802000, 0x170000}, /* 8: SQM0 */
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x08f0000, 0x08f2000, 0x172000} } },
+ {{{1, 0x0900000, 0x0902000, 0x174000}, /* 9: SQM1*/
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x09f0000, 0x09f2000, 0x176000} } },
+ {{{0, 0x0a00000, 0x0a02000, 0x178000}, /* 10: SQM2*/
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x0af0000, 0x0af2000, 0x17a000} } },
+ {{{0, 0x0b00000, 0x0b02000, 0x17c000}, /* 11: SQM3*/
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x0bf0000, 0x0bf2000, 0x17e000} } },
+ {{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */
+ {{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */
+ {{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */
+ {{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */
+ {{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */
+ {{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */
+ {{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */
+ {{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */
+ {{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */
+ {{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */
+ {{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */
+ {{{0, 0, 0, 0} } }, /* 23: */
+ {{{0, 0, 0, 0} } }, /* 24: */
+ {{{0, 0, 0, 0} } }, /* 25: */
+ {{{0, 0, 0, 0} } }, /* 26: */
+ {{{0, 0, 0, 0} } }, /* 27: */
+ {{{0, 0, 0, 0} } }, /* 28: */
+ {{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */
+ {{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */
+ {{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */
+ {{{0} } }, /* 32: PCI */
+ {{{1, 0x2100000, 0x2102000, 0x120000}, /* 33: PCIE */
+ {1, 0x2110000, 0x2120000, 0x130000},
+ {1, 0x2120000, 0x2122000, 0x124000},
+ {1, 0x2130000, 0x2132000, 0x126000},
+ {1, 0x2140000, 0x2142000, 0x128000},
+ {1, 0x2150000, 0x2152000, 0x12a000},
+ {1, 0x2160000, 0x2170000, 0x110000},
+ {1, 0x2170000, 0x2172000, 0x12e000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000} } },
+ {{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */
+ {{{0} } }, /* 35: */
+ {{{0} } }, /* 36: */
+ {{{0} } }, /* 37: */
+ {{{0} } }, /* 38: */
+ {{{0} } }, /* 39: */
+ {{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */
+ {{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */
+ {{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */
+ {{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */
+ {{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */
+ {{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */
+ {{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */
+ {{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */
+ {{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */
+ {{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */
+ {{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */
+ {{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */
+ {{{0} } }, /* 52: */
+ {{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */
+ {{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */
+ {{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */
+ {{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */
+ {{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */
+ {{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */
+ {{{0} } }, /* 59: I2C0 */
+ {{{0} } }, /* 60: I2C1 */
+ {{{1, 0x3d00000, 0x3d04000, 0x1d8000} } },/* 61: LPC */
+ {{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */
+ {{{1, 0x3f00000, 0x3f01000, 0x168000} } } /* 63: P2NR0 */
};
-static u64 ctx_addr_sig_regs[][3] = {
- {NETXEN_NIC_REG(0x188), NETXEN_NIC_REG(0x18c), NETXEN_NIC_REG(0x1c0)},
- {NETXEN_NIC_REG(0x190), NETXEN_NIC_REG(0x194), NETXEN_NIC_REG(0x1c4)},
- {NETXEN_NIC_REG(0x198), NETXEN_NIC_REG(0x19c), NETXEN_NIC_REG(0x1c8)},
- {NETXEN_NIC_REG(0x1a0), NETXEN_NIC_REG(0x1a4), NETXEN_NIC_REG(0x1cc)}
+/*
+ * top 12 bits of crb internal address (hub, agent)
+ */
+static unsigned crb_hub_agt[64] =
+{
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PS,
+ NETXEN_HW_CRB_HUB_AGT_ADR_MN,
+ NETXEN_HW_CRB_HUB_AGT_ADR_MS,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SRE,
+ NETXEN_HW_CRB_HUB_AGT_ADR_NIU,
+ NETXEN_HW_CRB_HUB_AGT_ADR_QMN,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SQN0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SQN1,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SQN2,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SQN3,
+ NETXEN_HW_CRB_HUB_AGT_ADR_I2Q,
+ NETXEN_HW_CRB_HUB_AGT_ADR_TIMR,
+ NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGN4,
+ NETXEN_HW_CRB_HUB_AGT_ADR_XDMA,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGN0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGN1,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGN2,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGN3,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGND,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGNI,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGS0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGS1,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGS2,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGS3,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGSI,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SN,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_EG,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PS,
+ NETXEN_HW_CRB_HUB_AGT_ADR_CAM,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_TIMR,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX1,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX2,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX3,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX4,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX5,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX6,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX7,
+ NETXEN_HW_CRB_HUB_AGT_ADR_XDMA,
+ NETXEN_HW_CRB_HUB_AGT_ADR_I2Q,
+ NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX8,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX9,
+ NETXEN_HW_CRB_HUB_AGT_ADR_OCM0,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SMB,
+ NETXEN_HW_CRB_HUB_AGT_ADR_I2C0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_I2C1,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGNC,
+ 0,
};
-#define CRB_CTX_ADDR_REG_LO(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][0])
-#define CRB_CTX_ADDR_REG_HI(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][2])
-#define CRB_CTX_SIGNATURE_REG(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][1])
-
/* PCI Windowing for DDR regions. */
#define ADDR_IN_RANGE(addr, low, high) \
(((addr) <= (high)) && ((addr) >= (low)))
-#define NETXEN_FLASH_BASE (NETXEN_BOOTLD_START)
-#define NETXEN_PHANTOM_MEM_BASE (NETXEN_FLASH_BASE)
#define NETXEN_MAX_MTU 8000 + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE
#define NETXEN_MIN_MTU 64
#define NETXEN_ETH_FCS_SIZE 4
#define NETXEN_ENET_HEADER_SIZE 14
-#define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */
+#define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */
#define NETXEN_FIRMWARE_LEN ((16 * 1024) / 4)
#define NETXEN_NIU_HDRSIZE (0x1 << 6)
#define NETXEN_NIU_TLRSIZE (0x1 << 5)
-#define lower32(x) ((u32)((x) & 0xffffffff))
-#define upper32(x) \
- ((u32)(((unsigned long long)(x) >> 32) & 0xffffffff))
-
#define NETXEN_NIC_ZERO_PAUSE_ADDR 0ULL
#define NETXEN_NIC_UNIT_PAUSE_ADDR 0x200ULL
#define NETXEN_NIC_EPG_PAUSE_ADDR1 0x2200010000c28001ULL
@@ -281,10 +301,6 @@ static u64 ctx_addr_sig_regs[][3] = {
#define NETXEN_NIC_WINDOW_MARGIN 0x100000
-static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,
- unsigned long long addr);
-void netxen_free_hw_resources(struct netxen_adapter *adapter);
-
int netxen_nic_set_mac(struct net_device *netdev, void *p)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
@@ -296,266 +312,370 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- DPRINTK(INFO, "valid ether addr\n");
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
- if (adapter->macaddr_set)
- adapter->macaddr_set(adapter, addr->sa_data);
+ /* For P3, MAC addr is not set in NIU */
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ if (adapter->macaddr_set)
+ adapter->macaddr_set(adapter, addr->sa_data);
return 0;
}
-/*
- * netxen_nic_set_multi - Multicast
- */
-void netxen_nic_set_multi(struct net_device *netdev)
+#define NETXEN_UNICAST_ADDR(port, index) \
+ (NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8))
+#define NETXEN_MCAST_ADDR(port, index) \
+ (NETXEN_MULTICAST_ADDR_BASE+(port*0x80)+(index*8))
+#define MAC_HI(addr) \
+ ((addr[2] << 16) | (addr[1] << 8) | (addr[0]))
+#define MAC_LO(addr) \
+ ((addr[5] << 16) | (addr[4] << 8) | (addr[3]))
+
+static int
+netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter)
+{
+ u32 val = 0;
+ u16 port = adapter->physical_port;
+ u8 *addr = adapter->netdev->dev_addr;
+
+ if (adapter->mc_enabled)
+ return 0;
+
+ adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+ val |= (1UL << (28+port));
+ adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+
+ /* add broadcast addr to filter */
+ val = 0xffffff;
+ netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_UNICAST_ADDR(port, 0)+4, val);
+
+ /* add station addr to filter */
+ val = MAC_HI(addr);
+ netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), val);
+ val = MAC_LO(addr);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_UNICAST_ADDR(port, 1)+4, val);
+
+ adapter->mc_enabled = 1;
+ return 0;
+}
+
+static int
+netxen_nic_disable_mcast_filter(struct netxen_adapter *adapter)
+{
+ u32 val = 0;
+ u16 port = adapter->physical_port;
+ u8 *addr = adapter->netdev->dev_addr;
+
+ if (!adapter->mc_enabled)
+ return 0;
+
+ adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+ val &= ~(1UL << (28+port));
+ adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+
+ val = MAC_HI(addr);
+ netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
+ val = MAC_LO(addr);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_UNICAST_ADDR(port, 0)+4, val);
+
+ netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0);
+
+ adapter->mc_enabled = 0;
+ return 0;
+}
+
+static int
+netxen_nic_set_mcast_addr(struct netxen_adapter *adapter,
+ int index, u8 *addr)
+{
+ u32 hi = 0, lo = 0;
+ u16 port = adapter->physical_port;
+
+ lo = MAC_LO(addr);
+ hi = MAC_HI(addr);
+
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_MCAST_ADDR(port, index), hi);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_MCAST_ADDR(port, index)+4, lo);
+
+ return 0;
+}
+
+void netxen_p2_nic_set_multi(struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
struct dev_mc_list *mc_ptr;
+ u8 null_addr[6];
+ int index = 0;
+
+ memset(null_addr, 0, 6);
- mc_ptr = netdev->mc_list;
if (netdev->flags & IFF_PROMISC) {
- if (adapter->set_promisc)
- adapter->set_promisc(adapter,
- NETXEN_NIU_PROMISC_MODE);
- } else {
- if (adapter->unset_promisc)
- adapter->unset_promisc(adapter,
- NETXEN_NIU_NON_PROMISC_MODE);
+
+ adapter->set_promisc(adapter,
+ NETXEN_NIU_PROMISC_MODE);
+
+ /* Full promiscuous mode */
+ netxen_nic_disable_mcast_filter(adapter);
+
+ return;
+ }
+
+ if (netdev->mc_count == 0) {
+ adapter->set_promisc(adapter,
+ NETXEN_NIU_NON_PROMISC_MODE);
+ netxen_nic_disable_mcast_filter(adapter);
+ return;
}
+
+ adapter->set_promisc(adapter, NETXEN_NIU_ALLMULTI_MODE);
+ if (netdev->flags & IFF_ALLMULTI ||
+ netdev->mc_count > adapter->max_mc_count) {
+ netxen_nic_disable_mcast_filter(adapter);
+ return;
+ }
+
+ netxen_nic_enable_mcast_filter(adapter);
+
+ for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next, index++)
+ netxen_nic_set_mcast_addr(adapter, index, mc_ptr->dmi_addr);
+
+ if (index != netdev->mc_count)
+ printk(KERN_WARNING "%s: %s multicast address count mismatch\n",
+ netxen_nic_driver_name, netdev->name);
+
+ /* Clear out remaining addresses */
+ for (; index < adapter->max_mc_count; index++)
+ netxen_nic_set_mcast_addr(adapter, index, null_addr);
}
-/*
- * netxen_nic_change_mtu - Change the Maximum Transfer Unit
- * @returns 0 on success, negative on failure
- */
-int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
+static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
+ u8 *addr, nx_mac_list_t **add_list, nx_mac_list_t **del_list)
{
- struct netxen_adapter *adapter = netdev_priv(netdev);
- int eff_mtu = mtu + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE;
+ nx_mac_list_t *cur, *prev;
+
+ /* if in del_list, move it to adapter->mac_list */
+ for (cur = *del_list, prev = NULL; cur;) {
+ if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
+ if (prev == NULL)
+ *del_list = cur->next;
+ else
+ prev->next = cur->next;
+ cur->next = adapter->mac_list;
+ adapter->mac_list = cur;
+ return 0;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+
+ /* make sure to add each mac address only once */
+ for (cur = adapter->mac_list; cur; cur = cur->next) {
+ if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0)
+ return 0;
+ }
+ /* not in del_list, create new entry and add to add_list */
+ cur = kmalloc(sizeof(*cur), in_atomic()? GFP_ATOMIC : GFP_KERNEL);
+ if (cur == NULL) {
+ printk(KERN_ERR "%s: cannot allocate memory. MAC filtering may"
+ "not work properly from now.\n", __func__);
+ return -1;
+ }
- if ((eff_mtu > NETXEN_MAX_MTU) || (eff_mtu < NETXEN_MIN_MTU)) {
- printk(KERN_ERR "%s: %s %d is not supported.\n",
- netxen_nic_driver_name, netdev->name, mtu);
+ memcpy(cur->mac_addr, addr, ETH_ALEN);
+ cur->next = *add_list;
+ *add_list = cur;
+ return 0;
+}
+
+static int
+netxen_send_cmd_descs(struct netxen_adapter *adapter,
+ struct cmd_desc_type0 *cmd_desc_arr, int nr_elements)
+{
+ uint32_t i, producer;
+ struct netxen_cmd_buffer *pbuf;
+ struct cmd_desc_type0 *cmd_desc;
+
+ if (nr_elements > MAX_PENDING_DESC_BLOCK_SIZE || nr_elements == 0) {
+ printk(KERN_WARNING "%s: Too many command descriptors in a "
+ "request\n", __func__);
return -EINVAL;
}
- if (adapter->set_mtu)
- adapter->set_mtu(adapter, mtu);
- netdev->mtu = mtu;
+ i = 0;
+
+ producer = adapter->cmd_producer;
+ do {
+ cmd_desc = &cmd_desc_arr[i];
+
+ pbuf = &adapter->cmd_buf_arr[producer];
+ pbuf->mss = 0;
+ pbuf->total_length = 0;
+ pbuf->skb = NULL;
+ pbuf->cmd = 0;
+ pbuf->frag_count = 0;
+ pbuf->port = 0;
+
+ /* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */
+ memcpy(&adapter->ahw.cmd_desc_head[producer],
+ &cmd_desc_arr[i], sizeof(struct cmd_desc_type0));
+
+ producer = get_next_index(producer,
+ adapter->max_tx_desc_count);
+ i++;
+
+ } while (i != nr_elements);
+
+ adapter->cmd_producer = producer;
+
+ /* write producer index to start the xmit */
+
+ netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer);
return 0;
}
-/*
- * check if the firmware has been downloaded and ready to run and
- * setup the address for the descriptors in the adapter
- */
-int netxen_nic_hw_resources(struct netxen_adapter *adapter)
+#define NIC_REQUEST 0x14
+#define NETXEN_MAC_EVENT 0x1
+
+static int nx_p3_sre_macaddr_change(struct net_device *dev,
+ u8 *addr, unsigned op)
{
- struct netxen_hardware_context *hw = &adapter->ahw;
- u32 state = 0;
- void *addr;
- int loops = 0, err = 0;
- int ctx, ring;
- struct netxen_recv_context *recv_ctx;
- struct netxen_rcv_desc_ctx *rcv_desc;
- int func_id = adapter->portnum;
-
- DPRINTK(INFO, "crb_base: %lx %x", NETXEN_PCI_CRBSPACE,
- PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCI_CRBSPACE));
- DPRINTK(INFO, "cam base: %lx %x", NETXEN_CRB_CAM,
- pci_base_offset(adapter, NETXEN_CRB_CAM));
- DPRINTK(INFO, "cam RAM: %lx %x", NETXEN_CAM_RAM_BASE,
- pci_base_offset(adapter, NETXEN_CAM_RAM_BASE));
-
-
- for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
- DPRINTK(INFO, "Command Peg ready..waiting for rcv peg\n");
- loops = 0;
- state = 0;
- /* Window 1 call */
- state = readl(NETXEN_CRB_NORMALIZE(adapter,
- recv_crb_registers[ctx].
- crb_rcvpeg_state));
- while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) {
- msleep(1);
- /* Window 1 call */
- state = readl(NETXEN_CRB_NORMALIZE(adapter,
- recv_crb_registers
- [ctx].
- crb_rcvpeg_state));
- loops++;
- }
- if (loops >= 20) {
- printk(KERN_ERR "Rcv Peg initialization not complete:"
- "%x.\n", state);
- err = -EIO;
- return err;
- }
+ struct netxen_adapter *adapter = (struct netxen_adapter *)dev->priv;
+ nx_nic_req_t req;
+ nx_mac_req_t mac_req;
+ int rv;
+
+ memset(&req, 0, sizeof(nx_nic_req_t));
+ req.qhdr |= (NIC_REQUEST << 23);
+ req.req_hdr |= NETXEN_MAC_EVENT;
+ req.req_hdr |= ((u64)adapter->portnum << 16);
+ mac_req.op = op;
+ memcpy(&mac_req.mac_addr, addr, 6);
+ req.words[0] = cpu_to_le64(*(u64 *)&mac_req);
+
+ rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0) {
+ printk(KERN_ERR "ERROR. Could not send mac update\n");
+ return rv;
}
- adapter->intr_scheme = readl(
- NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW));
- adapter->msi_mode = readl(
- NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_MSI_MODE_FW));
-
- addr = netxen_alloc(adapter->ahw.pdev,
- sizeof(struct netxen_ring_ctx) +
- sizeof(uint32_t),
- (dma_addr_t *) & adapter->ctx_desc_phys_addr,
- &adapter->ctx_desc_pdev);
-
- if (addr == NULL) {
- DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
- err = -ENOMEM;
- return err;
- }
- memset(addr, 0, sizeof(struct netxen_ring_ctx));
- adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
- adapter->ctx_desc->ctx_id = cpu_to_le32(adapter->portnum);
- adapter->ctx_desc->cmd_consumer_offset =
- cpu_to_le64(adapter->ctx_desc_phys_addr +
- sizeof(struct netxen_ring_ctx));
- adapter->cmd_consumer = (__le32 *) (((char *)addr) +
- sizeof(struct netxen_ring_ctx));
-
- addr = netxen_alloc(adapter->ahw.pdev,
- sizeof(struct cmd_desc_type0) *
- adapter->max_tx_desc_count,
- (dma_addr_t *) & hw->cmd_desc_phys_addr,
- &adapter->ahw.cmd_desc_pdev);
-
- if (addr == NULL) {
- DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
- netxen_free_hw_resources(adapter);
- return -ENOMEM;
- }
-
- adapter->ctx_desc->cmd_ring_addr =
- cpu_to_le64(hw->cmd_desc_phys_addr);
- adapter->ctx_desc->cmd_ring_size =
- cpu_to_le32(adapter->max_tx_desc_count);
-
- hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
-
- for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
- recv_ctx = &adapter->recv_ctx[ctx];
-
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- rcv_desc = &recv_ctx->rcv_desc[ring];
- addr = netxen_alloc(adapter->ahw.pdev,
- RCV_DESC_RINGSIZE,
- &rcv_desc->phys_addr,
- &rcv_desc->phys_pdev);
- if (addr == NULL) {
- DPRINTK(ERR, "bad return from "
- "pci_alloc_consistent\n");
- netxen_free_hw_resources(adapter);
- err = -ENOMEM;
- return err;
- }
- rcv_desc->desc_head = (struct rcv_desc *)addr;
- adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr =
- cpu_to_le64(rcv_desc->phys_addr);
- adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size =
- cpu_to_le32(rcv_desc->max_rx_desc_count);
- }
- addr = netxen_alloc(adapter->ahw.pdev, STATUS_DESC_RINGSIZE,
- &recv_ctx->rcv_status_desc_phys_addr,
- &recv_ctx->rcv_status_desc_pdev);
- if (addr == NULL) {
- DPRINTK(ERR, "bad return from"
- " pci_alloc_consistent\n");
- netxen_free_hw_resources(adapter);
- err = -ENOMEM;
- return err;
- }
- recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
- adapter->ctx_desc->sts_ring_addr =
- cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
- adapter->ctx_desc->sts_ring_size =
- cpu_to_le32(adapter->max_rx_desc_count);
-
- }
- /* Window = 1 */
-
- writel(lower32(adapter->ctx_desc_phys_addr),
- NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG_LO(func_id)));
- writel(upper32(adapter->ctx_desc_phys_addr),
- NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG_HI(func_id)));
- writel(NETXEN_CTX_SIGNATURE | func_id,
- NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_SIGNATURE_REG(func_id)));
- return err;
+ return 0;
}
-void netxen_free_hw_resources(struct netxen_adapter *adapter)
+void netxen_p3_nic_set_multi(struct net_device *netdev)
{
- struct netxen_recv_context *recv_ctx;
- struct netxen_rcv_desc_ctx *rcv_desc;
- int ctx, ring;
-
- if (adapter->ctx_desc != NULL) {
- pci_free_consistent(adapter->ctx_desc_pdev,
- sizeof(struct netxen_ring_ctx) +
- sizeof(uint32_t),
- adapter->ctx_desc,
- adapter->ctx_desc_phys_addr);
- adapter->ctx_desc = NULL;
- }
-
- if (adapter->ahw.cmd_desc_head != NULL) {
- pci_free_consistent(adapter->ahw.cmd_desc_pdev,
- sizeof(struct cmd_desc_type0) *
- adapter->max_tx_desc_count,
- adapter->ahw.cmd_desc_head,
- adapter->ahw.cmd_desc_phys_addr);
- adapter->ahw.cmd_desc_head = NULL;
- }
-
- for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
- recv_ctx = &adapter->recv_ctx[ctx];
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- rcv_desc = &recv_ctx->rcv_desc[ring];
-
- if (rcv_desc->desc_head != NULL) {
- pci_free_consistent(rcv_desc->phys_pdev,
- RCV_DESC_RINGSIZE,
- rcv_desc->desc_head,
- rcv_desc->phys_addr);
- rcv_desc->desc_head = NULL;
- }
- }
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+ nx_mac_list_t *cur, *next, *del_list, *add_list = NULL;
+ struct dev_mc_list *mc_ptr;
+ u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+ adapter->set_promisc(adapter, NETXEN_NIU_PROMISC_MODE);
- if (recv_ctx->rcv_status_desc_head != NULL) {
- pci_free_consistent(recv_ctx->rcv_status_desc_pdev,
- STATUS_DESC_RINGSIZE,
- recv_ctx->rcv_status_desc_head,
- recv_ctx->
- rcv_status_desc_phys_addr);
- recv_ctx->rcv_status_desc_head = NULL;
+ /*
+ * Programming mac addresses will automaticly enabling L2 filtering.
+ * HW will replace timestamp with L2 conid when L2 filtering is
+ * enabled. This causes problem for LSA. Do not enabling L2 filtering
+ * until that problem is fixed.
+ */
+ if ((netdev->flags & IFF_PROMISC) ||
+ (netdev->mc_count > adapter->max_mc_count))
+ return;
+
+ del_list = adapter->mac_list;
+ adapter->mac_list = NULL;
+
+ nx_p3_nic_add_mac(adapter, netdev->dev_addr, &add_list, &del_list);
+ if (netdev->mc_count > 0) {
+ nx_p3_nic_add_mac(adapter, bcast_addr, &add_list, &del_list);
+ for (mc_ptr = netdev->mc_list; mc_ptr;
+ mc_ptr = mc_ptr->next) {
+ nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr,
+ &add_list, &del_list);
}
}
+ for (cur = del_list; cur;) {
+ nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_DEL);
+ next = cur->next;
+ kfree(cur);
+ cur = next;
+ }
+ for (cur = add_list; cur;) {
+ nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_ADD);
+ next = cur->next;
+ cur->next = adapter->mac_list;
+ adapter->mac_list = cur;
+ cur = next;
+ }
}
-void netxen_tso_check(struct netxen_adapter *adapter,
- struct cmd_desc_type0 *desc, struct sk_buff *skb)
+#define NETXEN_CONFIG_INTR_COALESCE 3
+
+/*
+ * Send the interrupt coalescing parameter set by ethtool to the card.
+ */
+int netxen_config_intr_coalesce(struct netxen_adapter *adapter)
{
- if (desc->mss) {
- desc->total_hdr_length = (sizeof(struct ethhdr) +
- ip_hdrlen(skb) + tcp_hdrlen(skb));
- netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
- } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
- if (ip_hdr(skb)->protocol == IPPROTO_TCP) {
- netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
- } else if (ip_hdr(skb)->protocol == IPPROTO_UDP) {
- netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
- } else {
- return;
- }
+ nx_nic_req_t req;
+ int rv;
+
+ memset(&req, 0, sizeof(nx_nic_req_t));
+
+ req.qhdr |= (NIC_REQUEST << 23);
+ req.req_hdr |= NETXEN_CONFIG_INTR_COALESCE;
+ req.req_hdr |= ((u64)adapter->portnum << 16);
+
+ memcpy(&req.words[0], &adapter->coal, sizeof(adapter->coal));
+
+ rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0) {
+ printk(KERN_ERR "ERROR. Could not send "
+ "interrupt coalescing parameters\n");
}
- desc->tcp_hdr_offset = skb_transport_offset(skb);
- desc->ip_hdr_offset = skb_network_offset(skb);
+
+ return rv;
+}
+
+/*
+ * netxen_nic_change_mtu - Change the Maximum Transfer Unit
+ * @returns 0 on success, negative on failure
+ */
+
+#define MTU_FUDGE_FACTOR 100
+
+int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
+{
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+ int max_mtu;
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ max_mtu = P3_MAX_MTU;
+ else
+ max_mtu = P2_MAX_MTU;
+
+ if (mtu > max_mtu) {
+ printk(KERN_ERR "%s: mtu > %d bytes unsupported\n",
+ netdev->name, max_mtu);
+ return -EINVAL;
+ }
+
+ if (adapter->set_mtu)
+ adapter->set_mtu(adapter, mtu);
+ netdev->mtu = mtu;
+
+ mtu += MTU_FUDGE_FACTOR;
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ nx_fw_cmd_set_mtu(adapter, mtu);
+ else if (adapter->set_mtu)
+ adapter->set_mtu(adapter, mtu);
+
+ return 0;
}
int netxen_is_flash_supported(struct netxen_adapter *adapter)
@@ -632,41 +752,49 @@ int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 mac[])
return 0;
}
+#define CRB_WIN_LOCK_TIMEOUT 100000000
+
+static int crb_win_lock(struct netxen_adapter *adapter)
+{
+ int done = 0, timeout = 0;
+
+ while (!done) {
+ /* acquire semaphore3 from PCI HW block */
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_SEM7_LOCK), &done, 4);
+ if (done == 1)
+ break;
+ if (timeout >= CRB_WIN_LOCK_TIMEOUT)
+ return -1;
+ timeout++;
+ udelay(1);
+ }
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_CRB_WIN_LOCK_ID, adapter->portnum);
+ return 0;
+}
+
+static void crb_win_unlock(struct netxen_adapter *adapter)
+{
+ int val;
+
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK), &val, 4);
+}
+
/*
* Changes the CRB window to the specified window.
*/
-void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
+void
+netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter, u32 wndw)
{
void __iomem *offset;
u32 tmp;
int count = 0;
+ uint8_t func = adapter->ahw.pci_func;
if (adapter->curr_window == wndw)
return;
- switch(adapter->ahw.pci_func) {
- case 0:
- offset = PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW));
- break;
- case 1:
- offset = PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW_F1));
- break;
- case 2:
- offset = PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW_F2));
- break;
- case 3:
- offset = PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW_F3));
- break;
- default:
- printk(KERN_INFO "Changing the window for PCI function "
- "%d\n", adapter->ahw.pci_func);
- offset = PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW));
- break;
- }
/*
* Move the CRB window.
* We need to write to the "direct access" region of PCI
@@ -675,6 +803,8 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
* register address is received by PCI. The direct region bypasses
* the CRB bus.
*/
+ offset = PCI_OFFSET_SECOND_RANGE(adapter,
+ NETXEN_PCIX_PH_REG(PCIE_CRB_WINDOW_REG(func)));
if (wndw & 0x1)
wndw = NETXEN_WINDOW_ONE;
@@ -685,7 +815,7 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
while ((tmp = readl(offset)) != wndw) {
printk(KERN_WARNING "%s: %s WARNING: CRB window value not "
"registered properly: 0x%08x.\n",
- netxen_nic_driver_name, __FUNCTION__, tmp);
+ netxen_nic_driver_name, __func__, tmp);
mdelay(1);
if (count >= 10)
break;
@@ -698,51 +828,119 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
adapter->curr_window = 0;
}
+/*
+ * Return -1 if off is not valid,
+ * 1 if window access is needed. 'off' is set to offset from
+ * CRB space in 128M pci map
+ * 0 if no window access is needed. 'off' is set to 2M addr
+ * In: 'off' is offset from base in 128M pci map
+ */
+static int
+netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter,
+ ulong *off, int len)
+{
+ unsigned long end = *off + len;
+ crb_128M_2M_sub_block_map_t *m;
+
+
+ if (*off >= NETXEN_CRB_MAX)
+ return -1;
+
+ if (*off >= NETXEN_PCI_CAMQM && (end <= NETXEN_PCI_CAMQM_2M_END)) {
+ *off = (*off - NETXEN_PCI_CAMQM) + NETXEN_PCI_CAMQM_2M_BASE +
+ (ulong)adapter->ahw.pci_base0;
+ return 0;
+ }
+
+ if (*off < NETXEN_PCI_CRBSPACE)
+ return -1;
+
+ *off -= NETXEN_PCI_CRBSPACE;
+ end = *off + len;
+
+ /*
+ * Try direct map
+ */
+ m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
+
+ if (m->valid && (m->start_128M <= *off) && (m->end_128M >= end)) {
+ *off = *off + m->start_2M - m->start_128M +
+ (ulong)adapter->ahw.pci_base0;
+ return 0;
+ }
+
+ /*
+ * Not in direct map, use crb window
+ */
+ return 1;
+}
+
+/*
+ * In: 'off' is offset from CRB space in 128M pci map
+ * Out: 'off' is 2M pci map addr
+ * side effect: lock crb window
+ */
+static void
+netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off)
+{
+ u32 win_read;
+
+ adapter->crb_win = CRB_HI(*off);
+ writel(adapter->crb_win, (void *)(CRB_WINDOW_2M +
+ adapter->ahw.pci_base0));
+ /*
+ * Read back value to make sure write has gone through before trying
+ * to use it.
+ */
+ win_read = readl((void *)(CRB_WINDOW_2M + adapter->ahw.pci_base0));
+ if (win_read != adapter->crb_win) {
+ printk(KERN_ERR "%s: Written crbwin (0x%x) != "
+ "Read crbwin (0x%x), off=0x%lx\n",
+ __func__, adapter->crb_win, win_read, *off);
+ }
+ *off = (*off & MASK(16)) + CRB_INDIRECT_2M +
+ (ulong)adapter->ahw.pci_base0;
+}
+
int netxen_load_firmware(struct netxen_adapter *adapter)
{
int i;
u32 data, size = 0;
- u32 flashaddr = NETXEN_FLASH_BASE, memaddr = NETXEN_PHANTOM_MEM_BASE;
- u64 off;
- void __iomem *addr;
+ u32 flashaddr = NETXEN_BOOTLD_START, memaddr = NETXEN_BOOTLD_START;
- size = NETXEN_FIRMWARE_LEN;
- writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
+ size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START)/4;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_CAS_RST, 1);
for (i = 0; i < size; i++) {
- int retries = 10;
if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0)
return -EIO;
- off = netxen_nic_pci_set_window(adapter, memaddr);
- addr = pci_base_offset(adapter, off);
- writel(data, addr);
- do {
- if (readl(addr) == data)
- break;
- msleep(100);
- writel(data, addr);
- } while (--retries);
- if (!retries) {
- printk(KERN_ERR "%s: firmware load aborted, write failed at 0x%x\n",
- netxen_nic_driver_name, memaddr);
- return -EIO;
- }
+ adapter->pci_mem_write(adapter, memaddr, &data, 4);
flashaddr += 4;
memaddr += 4;
+ cond_resched();
+ }
+ msleep(1);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d);
+ else {
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff);
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_CAS_RST, 0);
}
- udelay(100);
- /* make sure Casper is powered on */
- writel(0x3fff,
- NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL));
- writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
return 0;
}
int
-netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
- int len)
+netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len)
{
void __iomem *addr;
@@ -750,7 +948,7 @@ netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
addr = NETXEN_CRB_NORMALIZE(adapter, off);
} else { /* Window 0 */
addr = pci_base_offset(adapter, off);
- netxen_nic_pci_change_crbwindow(adapter, 0);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 0);
}
DPRINTK(INFO, "writing to base %lx offset %llx addr %p"
@@ -758,7 +956,7 @@ netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
pci_base(adapter, off), off, addr,
*(unsigned long long *)data, len);
if (!addr) {
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
return 1;
}
@@ -785,14 +983,14 @@ netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
break;
}
if (!ADDR_IN_WINDOW1(off))
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
return 0;
}
int
-netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
- int len)
+netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len)
{
void __iomem *addr;
@@ -800,13 +998,13 @@ netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
addr = NETXEN_CRB_NORMALIZE(adapter, off);
} else { /* Window 0 */
addr = pci_base_offset(adapter, off);
- netxen_nic_pci_change_crbwindow(adapter, 0);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 0);
}
DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
pci_base(adapter, off), off, addr);
if (!addr) {
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
return 1;
}
switch (len) {
@@ -830,81 +1028,195 @@ netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
DPRINTK(INFO, "read %lx\n", *(unsigned long *)data);
if (!ADDR_IN_WINDOW1(off))
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
return 0;
}
-void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val)
-{ /* Only for window 1 */
- void __iomem *addr;
+int
+netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len)
+{
+ unsigned long flags = 0;
+ int rv;
+
+ rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len);
+
+ if (rv == -1) {
+ printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
+ __func__, off);
+ dump_stack();
+ return -1;
+ }
+
+ if (rv == 1) {
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ crb_win_lock(adapter);
+ netxen_nic_pci_set_crbwindow_2M(adapter, &off);
+ }
- addr = NETXEN_CRB_NORMALIZE(adapter, off);
- DPRINTK(INFO, "writing to base %lx offset %llx addr %p data %x\n",
- pci_base(adapter, off), off, addr, val);
- writel(val, addr);
+ DPRINTK(1, INFO, "write data %lx to offset %llx, len=%d\n",
+ *(unsigned long *)data, off, len);
+ switch (len) {
+ case 1:
+ writeb(*(uint8_t *)data, (void *)off);
+ break;
+ case 2:
+ writew(*(uint16_t *)data, (void *)off);
+ break;
+ case 4:
+ writel(*(uint32_t *)data, (void *)off);
+ break;
+ case 8:
+ writeq(*(uint64_t *)data, (void *)off);
+ break;
+ default:
+ DPRINTK(1, INFO,
+ "writing data %lx to offset %llx, num words=%d\n",
+ *(unsigned long *)data, off, (len>>3));
+ break;
+ }
+ if (rv == 1) {
+ crb_win_unlock(adapter);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ }
+
+ return 0;
}
-int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
-{ /* Only for window 1 */
- void __iomem *addr;
- int val;
+int
+netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len)
+{
+ unsigned long flags = 0;
+ int rv;
- addr = NETXEN_CRB_NORMALIZE(adapter, off);
- DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
- pci_base(adapter, off), off, addr);
- val = readl(addr);
- writel(val, addr);
+ rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len);
+
+ if (rv == -1) {
+ printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
+ __func__, off);
+ dump_stack();
+ return -1;
+ }
+
+ if (rv == 1) {
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ crb_win_lock(adapter);
+ netxen_nic_pci_set_crbwindow_2M(adapter, &off);
+ }
+
+ DPRINTK(1, INFO, "read from offset %lx, len=%d\n", off, len);
+
+ switch (len) {
+ case 1:
+ *(uint8_t *)data = readb((void *)off);
+ break;
+ case 2:
+ *(uint16_t *)data = readw((void *)off);
+ break;
+ case 4:
+ *(uint32_t *)data = readl((void *)off);
+ break;
+ case 8:
+ *(uint64_t *)data = readq((void *)off);
+ break;
+ default:
+ break;
+ }
+ DPRINTK(1, INFO, "read %lx\n", *(unsigned long *)data);
+
+ if (rv == 1) {
+ crb_win_unlock(adapter);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ }
+
+ return 0;
+}
+
+void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val)
+{
+ adapter->hw_write_wx(adapter, off, &val, 4);
+}
+
+int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
+{
+ int val;
+ adapter->hw_read_wx(adapter, off, &val, 4);
return val;
}
/* Change the window to 0, write and change back to window 1. */
void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value)
{
- void __iomem *addr;
-
- netxen_nic_pci_change_crbwindow(adapter, 0);
- addr = pci_base_offset(adapter, index);
- writel(value, addr);
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ adapter->hw_write_wx(adapter, index, &value, 4);
}
/* Change the window to 0, read and change back to window 1. */
-void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value)
+void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value)
{
- void __iomem *addr;
+ adapter->hw_read_wx(adapter, index, value, 4);
+}
- addr = pci_base_offset(adapter, index);
+void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value)
+{
+ adapter->hw_write_wx(adapter, index, &value, 4);
+}
+
+void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value)
+{
+ adapter->hw_read_wx(adapter, index, value, 4);
+}
+
+/*
+ * check memory access boundary.
+ * used by test agent. support ddr access only for now
+ */
+static unsigned long
+netxen_nic_pci_mem_bound_check(struct netxen_adapter *adapter,
+ unsigned long long addr, int size)
+{
+ if (!ADDR_IN_RANGE(addr,
+ NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX) ||
+ !ADDR_IN_RANGE(addr+size-1,
+ NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX) ||
+ ((size != 1) && (size != 2) && (size != 4) && (size != 8))) {
+ return 0;
+ }
- netxen_nic_pci_change_crbwindow(adapter, 0);
- *value = readl(addr);
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ return 1;
}
static int netxen_pci_set_window_warning_count;
-static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,
- unsigned long long addr)
+unsigned long
+netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter,
+ unsigned long long addr)
{
- static int ddr_mn_window = -1;
- static int qdr_sn_window = -1;
+ void __iomem *offset;
int window;
+ unsigned long long qdr_max;
+ uint8_t func = adapter->ahw.pci_func;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ qdr_max = NETXEN_ADDR_QDR_NET_MAX_P2;
+ } else {
+ qdr_max = NETXEN_ADDR_QDR_NET_MAX_P3;
+ }
if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
/* DDR network side */
addr -= NETXEN_ADDR_DDR_NET;
window = (addr >> 25) & 0x3ff;
- if (ddr_mn_window != window) {
- ddr_mn_window = window;
- writel(window, PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG
- (PCIX_MN_WINDOW(adapter->ahw.pci_func))));
+ if (adapter->ahw.ddr_mn_window != window) {
+ adapter->ahw.ddr_mn_window = window;
+ offset = PCI_OFFSET_SECOND_RANGE(adapter,
+ NETXEN_PCIX_PH_REG(PCIE_MN_WINDOW_REG(func)));
+ writel(window, offset);
/* MUST make sure window is set before we forge on... */
- readl(PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG
- (PCIX_MN_WINDOW(adapter->ahw.pci_func))));
+ readl(offset);
}
addr -= (window * NETXEN_WINDOW_ONE);
addr += NETXEN_PCI_DDR_NET;
@@ -914,22 +1226,17 @@ static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,
} else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
addr -= NETXEN_ADDR_OCM1;
addr += NETXEN_PCI_OCM1;
- } else
- if (ADDR_IN_RANGE
- (addr, NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX)) {
+ } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_QDR_NET, qdr_max)) {
/* QDR network side */
addr -= NETXEN_ADDR_QDR_NET;
window = (addr >> 22) & 0x3f;
- if (qdr_sn_window != window) {
- qdr_sn_window = window;
- writel((window << 22),
- PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG
- (PCIX_SN_WINDOW(adapter->ahw.pci_func))));
+ if (adapter->ahw.qdr_sn_window != window) {
+ adapter->ahw.qdr_sn_window = window;
+ offset = PCI_OFFSET_SECOND_RANGE(adapter,
+ NETXEN_PCIX_PH_REG(PCIE_SN_WINDOW_REG(func)));
+ writel((window << 22), offset);
/* MUST make sure window is set before we forge on... */
- readl(PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG
- (PCIX_SN_WINDOW(adapter->ahw.pci_func))));
+ readl(offset);
}
addr -= (window * 0x400000);
addr += NETXEN_PCI_QDR_NET;
@@ -943,11 +1250,711 @@ static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,
printk("%s: Warning:netxen_nic_pci_set_window()"
" Unknown address range!\n",
netxen_nic_driver_name);
+ addr = -1UL;
+ }
+ return addr;
+}
+
+/*
+ * Note : only 32-bit writes!
+ */
+int netxen_nic_pci_write_immediate_128M(struct netxen_adapter *adapter,
+ u64 off, u32 data)
+{
+ writel(data, (void __iomem *)(PCI_OFFSET_SECOND_RANGE(adapter, off)));
+ return 0;
+}
+
+u32 netxen_nic_pci_read_immediate_128M(struct netxen_adapter *adapter, u64 off)
+{
+ return readl((void __iomem *)(pci_base_offset(adapter, off)));
+}
+
+void netxen_nic_pci_write_normalize_128M(struct netxen_adapter *adapter,
+ u64 off, u32 data)
+{
+ writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
+}
+
+u32 netxen_nic_pci_read_normalize_128M(struct netxen_adapter *adapter, u64 off)
+{
+ return readl(NETXEN_CRB_NORMALIZE(adapter, off));
+}
+
+unsigned long
+netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,
+ unsigned long long addr)
+{
+ int window;
+ u32 win_read;
+
+ if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
+ /* DDR network side */
+ window = MN_WIN(addr);
+ adapter->ahw.ddr_mn_window = window;
+ adapter->hw_write_wx(adapter,
+ adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+ &window, 4);
+ adapter->hw_read_wx(adapter,
+ adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+ &win_read, 4);
+ if ((win_read << 17) != window) {
+ printk(KERN_INFO "Written MNwin (0x%x) != "
+ "Read MNwin (0x%x)\n", window, win_read);
+ }
+ addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_DDR_NET;
+ } else if (ADDR_IN_RANGE(addr,
+ NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
+ if ((addr & 0x00ff800) == 0xff800) {
+ printk("%s: QM access not handled.\n", __func__);
+ addr = -1UL;
+ }
+
+ window = OCM_WIN(addr);
+ adapter->ahw.ddr_mn_window = window;
+ adapter->hw_write_wx(adapter,
+ adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+ &window, 4);
+ adapter->hw_read_wx(adapter,
+ adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+ &win_read, 4);
+ if ((win_read >> 7) != window) {
+ printk(KERN_INFO "%s: Written OCMwin (0x%x) != "
+ "Read OCMwin (0x%x)\n",
+ __func__, window, win_read);
+ }
+ addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_OCM0_2M;
+
+ } else if (ADDR_IN_RANGE(addr,
+ NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX_P3)) {
+ /* QDR network side */
+ window = MS_WIN(addr);
+ adapter->ahw.qdr_sn_window = window;
+ adapter->hw_write_wx(adapter,
+ adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE,
+ &window, 4);
+ adapter->hw_read_wx(adapter,
+ adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE,
+ &win_read, 4);
+ if (win_read != window) {
+ printk(KERN_INFO "%s: Written MSwin (0x%x) != "
+ "Read MSwin (0x%x)\n",
+ __func__, window, win_read);
+ }
+ addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_QDR_NET;
+ } else {
+ /*
+ * peg gdb frequently accesses memory that doesn't exist,
+ * this limits the chit chat so debugging isn't slowed down.
+ */
+ if ((netxen_pci_set_window_warning_count++ < 8)
+ || (netxen_pci_set_window_warning_count%64 == 0)) {
+ printk("%s: Warning:%s Unknown address range!\n",
+ __func__, netxen_nic_driver_name);
+}
+ addr = -1UL;
}
return addr;
}
+static int netxen_nic_pci_is_same_window(struct netxen_adapter *adapter,
+ unsigned long long addr)
+{
+ int window;
+ unsigned long long qdr_max;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ qdr_max = NETXEN_ADDR_QDR_NET_MAX_P2;
+ else
+ qdr_max = NETXEN_ADDR_QDR_NET_MAX_P3;
+
+ if (ADDR_IN_RANGE(addr,
+ NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
+ /* DDR network side */
+ BUG(); /* MN access can not come here */
+ } else if (ADDR_IN_RANGE(addr,
+ NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
+ return 1;
+ } else if (ADDR_IN_RANGE(addr,
+ NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
+ return 1;
+ } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_QDR_NET, qdr_max)) {
+ /* QDR network side */
+ window = ((addr - NETXEN_ADDR_QDR_NET) >> 22) & 0x3f;
+ if (adapter->ahw.qdr_sn_window == window)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int netxen_nic_pci_mem_read_direct(struct netxen_adapter *adapter,
+ u64 off, void *data, int size)
+{
+ unsigned long flags;
+ void *addr;
+ int ret = 0;
+ u64 start;
+ uint8_t *mem_ptr = NULL;
+ unsigned long mem_base;
+ unsigned long mem_page;
+
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+
+ /*
+ * If attempting to access unknown address or straddle hw windows,
+ * do not access.
+ */
+ start = adapter->pci_set_window(adapter, off);
+ if ((start == -1UL) ||
+ (netxen_nic_pci_is_same_window(adapter, off+size-1) == 0)) {
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ printk(KERN_ERR "%s out of bound pci memory access. "
+ "offset is 0x%llx\n", netxen_nic_driver_name, off);
+ return -1;
+ }
+
+ addr = (void *)(pci_base_offset(adapter, start));
+ if (!addr) {
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ mem_base = pci_resource_start(adapter->pdev, 0);
+ mem_page = start & PAGE_MASK;
+ /* Map two pages whenever user tries to access addresses in two
+ consecutive pages.
+ */
+ if (mem_page != ((start + size - 1) & PAGE_MASK))
+ mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2);
+ else
+ mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
+ if (mem_ptr == 0UL) {
+ *(uint8_t *)data = 0;
+ return -1;
+ }
+ addr = mem_ptr;
+ addr += start & (PAGE_SIZE - 1);
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ }
+
+ switch (size) {
+ case 1:
+ *(uint8_t *)data = readb(addr);
+ break;
+ case 2:
+ *(uint16_t *)data = readw(addr);
+ break;
+ case 4:
+ *(uint32_t *)data = readl(addr);
+ break;
+ case 8:
+ *(uint64_t *)data = readq(addr);
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data);
+
+ if (mem_ptr)
+ iounmap(mem_ptr);
+ return ret;
+}
+
+static int
+netxen_nic_pci_mem_write_direct(struct netxen_adapter *adapter, u64 off,
+ void *data, int size)
+{
+ unsigned long flags;
+ void *addr;
+ int ret = 0;
+ u64 start;
+ uint8_t *mem_ptr = NULL;
+ unsigned long mem_base;
+ unsigned long mem_page;
+
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+
+ /*
+ * If attempting to access unknown address or straddle hw windows,
+ * do not access.
+ */
+ start = adapter->pci_set_window(adapter, off);
+ if ((start == -1UL) ||
+ (netxen_nic_pci_is_same_window(adapter, off+size-1) == 0)) {
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ printk(KERN_ERR "%s out of bound pci memory access. "
+ "offset is 0x%llx\n", netxen_nic_driver_name, off);
+ return -1;
+ }
+
+ addr = (void *)(pci_base_offset(adapter, start));
+ if (!addr) {
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ mem_base = pci_resource_start(adapter->pdev, 0);
+ mem_page = start & PAGE_MASK;
+ /* Map two pages whenever user tries to access addresses in two
+ * consecutive pages.
+ */
+ if (mem_page != ((start + size - 1) & PAGE_MASK))
+ mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2);
+ else
+ mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
+ if (mem_ptr == 0UL)
+ return -1;
+ addr = mem_ptr;
+ addr += start & (PAGE_SIZE - 1);
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ }
+
+ switch (size) {
+ case 1:
+ writeb(*(uint8_t *)data, addr);
+ break;
+ case 2:
+ writew(*(uint16_t *)data, addr);
+ break;
+ case 4:
+ writel(*(uint32_t *)data, addr);
+ break;
+ case 8:
+ writeq(*(uint64_t *)data, addr);
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ DPRINTK(1, INFO, "writing data %llx to offset %llx\n",
+ *(unsigned long long *)data, start);
+ if (mem_ptr)
+ iounmap(mem_ptr);
+ return ret;
+}
+
+#define MAX_CTL_CHECK 1000
+
+int
+netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size)
+{
+ unsigned long flags, mem_crb;
+ int i, j, ret = 0, loop, sz[2], off0;
+ uint32_t temp;
+ uint64_t off8, tmpw, word[2] = {0, 0};
+
+ /*
+ * If not MN, go check for MS or invalid.
+ */
+ if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0)
+ return netxen_nic_pci_mem_write_direct(adapter,
+ off, data, size);
+
+ off8 = off & 0xfffffff8;
+ off0 = off & 0x7;
+ sz[0] = (size < (8 - off0)) ? size : (8 - off0);
+ sz[1] = size - sz[0];
+ loop = ((off0 + size - 1) >> 3) + 1;
+ mem_crb = (unsigned long)pci_base_offset(adapter, NETXEN_CRB_DDR_NET);
+
+ if ((size != 8) || (off0 != 0)) {
+ for (i = 0; i < loop; i++) {
+ if (adapter->pci_mem_read(adapter,
+ off8 + (i << 3), &word[i], 8))
+ return -1;
+ }
+ }
+
+ switch (size) {
+ case 1:
+ tmpw = *((uint8_t *)data);
+ break;
+ case 2:
+ tmpw = *((uint16_t *)data);
+ break;
+ case 4:
+ tmpw = *((uint32_t *)data);
+ break;
+ case 8:
+ default:
+ tmpw = *((uint64_t *)data);
+ break;
+ }
+ word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
+ word[0] |= tmpw << (off0 * 8);
+
+ if (loop == 2) {
+ word[1] &= ~(~0ULL << (sz[1] * 8));
+ word[1] |= tmpw >> (sz[0] * 8);
+ }
+
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+
+ for (i = 0; i < loop; i++) {
+ writel((uint32_t)(off8 + (i << 3)),
+ (void *)(mem_crb+MIU_TEST_AGT_ADDR_LO));
+ writel(0,
+ (void *)(mem_crb+MIU_TEST_AGT_ADDR_HI));
+ writel(word[i] & 0xffffffff,
+ (void *)(mem_crb+MIU_TEST_AGT_WRDATA_LO));
+ writel((word[i] >> 32) & 0xffffffff,
+ (void *)(mem_crb+MIU_TEST_AGT_WRDATA_HI));
+ writel(MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+ writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ temp = readl(
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+ if ((temp & MIU_TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ printk("%s: %s Fail to write through agent\n",
+ __func__, netxen_nic_driver_name);
+ ret = -1;
+ break;
+ }
+ }
+
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ return ret;
+}
+
+int
+netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size)
+{
+ unsigned long flags, mem_crb;
+ int i, j = 0, k, start, end, loop, sz[2], off0[2];
+ uint32_t temp;
+ uint64_t off8, val, word[2] = {0, 0};
+
+
+ /*
+ * If not MN, go check for MS or invalid.
+ */
+ if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0)
+ return netxen_nic_pci_mem_read_direct(adapter, off, data, size);
+
+ off8 = off & 0xfffffff8;
+ off0[0] = off & 0x7;
+ off0[1] = 0;
+ sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
+ sz[1] = size - sz[0];
+ loop = ((off0[0] + size - 1) >> 3) + 1;
+ mem_crb = (unsigned long)pci_base_offset(adapter, NETXEN_CRB_DDR_NET);
+
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+
+ for (i = 0; i < loop; i++) {
+ writel((uint32_t)(off8 + (i << 3)),
+ (void *)(mem_crb+MIU_TEST_AGT_ADDR_LO));
+ writel(0,
+ (void *)(mem_crb+MIU_TEST_AGT_ADDR_HI));
+ writel(MIU_TA_CTL_ENABLE,
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+ writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE,
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ temp = readl(
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+ if ((temp & MIU_TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ printk(KERN_ERR "%s: %s Fail to read through agent\n",
+ __func__, netxen_nic_driver_name);
+ break;
+ }
+
+ start = off0[i] >> 2;
+ end = (off0[i] + sz[i] - 1) >> 2;
+ for (k = start; k <= end; k++) {
+ word[i] |= ((uint64_t) readl(
+ (void *)(mem_crb +
+ MIU_TEST_AGT_RDDATA(k))) << (32*k));
+ }
+ }
+
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+
+ if (j >= MAX_CTL_CHECK)
+ return -1;
+
+ if (sz[0] == 8) {
+ val = word[0];
+ } else {
+ val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
+ ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
+ }
+
+ switch (size) {
+ case 1:
+ *(uint8_t *)data = val;
+ break;
+ case 2:
+ *(uint16_t *)data = val;
+ break;
+ case 4:
+ *(uint32_t *)data = val;
+ break;
+ case 8:
+ *(uint64_t *)data = val;
+ break;
+ }
+ DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data);
+ return 0;
+}
+
+int
+netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size)
+{
+ int i, j, ret = 0, loop, sz[2], off0;
+ uint32_t temp;
+ uint64_t off8, mem_crb, tmpw, word[2] = {0, 0};
+
+ /*
+ * If not MN, go check for MS or invalid.
+ */
+ if (off >= NETXEN_ADDR_QDR_NET && off <= NETXEN_ADDR_QDR_NET_MAX_P3)
+ mem_crb = NETXEN_CRB_QDR_NET;
+ else {
+ mem_crb = NETXEN_CRB_DDR_NET;
+ if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0)
+ return netxen_nic_pci_mem_write_direct(adapter,
+ off, data, size);
+ }
+
+ off8 = off & 0xfffffff8;
+ off0 = off & 0x7;
+ sz[0] = (size < (8 - off0)) ? size : (8 - off0);
+ sz[1] = size - sz[0];
+ loop = ((off0 + size - 1) >> 3) + 1;
+
+ if ((size != 8) || (off0 != 0)) {
+ for (i = 0; i < loop; i++) {
+ if (adapter->pci_mem_read(adapter, off8 + (i << 3),
+ &word[i], 8))
+ return -1;
+ }
+ }
+
+ switch (size) {
+ case 1:
+ tmpw = *((uint8_t *)data);
+ break;
+ case 2:
+ tmpw = *((uint16_t *)data);
+ break;
+ case 4:
+ tmpw = *((uint32_t *)data);
+ break;
+ case 8:
+ default:
+ tmpw = *((uint64_t *)data);
+ break;
+ }
+
+ word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
+ word[0] |= tmpw << (off0 * 8);
+
+ if (loop == 2) {
+ word[1] &= ~(~0ULL << (sz[1] * 8));
+ word[1] |= tmpw >> (sz[0] * 8);
+ }
+
+ /*
+ * don't lock here - write_wx gets the lock if each time
+ * write_lock_irqsave(&adapter->adapter_lock, flags);
+ * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+ */
+
+ for (i = 0; i < loop; i++) {
+ temp = off8 + (i << 3);
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_ADDR_LO, &temp, 4);
+ temp = 0;
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_ADDR_HI, &temp, 4);
+ temp = word[i] & 0xffffffff;
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_WRDATA_LO, &temp, 4);
+ temp = (word[i] >> 32) & 0xffffffff;
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_WRDATA_HI, &temp, 4);
+ temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
+ temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ adapter->hw_read_wx(adapter,
+ mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+ if ((temp & MIU_TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ printk(KERN_ERR "%s: Fail to write through agent\n",
+ netxen_nic_driver_name);
+ ret = -1;
+ break;
+ }
+ }
+
+ /*
+ * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+ * write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ */
+ return ret;
+}
+
+int
+netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size)
+{
+ int i, j = 0, k, start, end, loop, sz[2], off0[2];
+ uint32_t temp;
+ uint64_t off8, val, mem_crb, word[2] = {0, 0};
+
+ /*
+ * If not MN, go check for MS or invalid.
+ */
+
+ if (off >= NETXEN_ADDR_QDR_NET && off <= NETXEN_ADDR_QDR_NET_MAX_P3)
+ mem_crb = NETXEN_CRB_QDR_NET;
+ else {
+ mem_crb = NETXEN_CRB_DDR_NET;
+ if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0)
+ return netxen_nic_pci_mem_read_direct(adapter,
+ off, data, size);
+ }
+
+ off8 = off & 0xfffffff8;
+ off0[0] = off & 0x7;
+ off0[1] = 0;
+ sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
+ sz[1] = size - sz[0];
+ loop = ((off0[0] + size - 1) >> 3) + 1;
+
+ /*
+ * don't lock here - write_wx gets the lock if each time
+ * write_lock_irqsave(&adapter->adapter_lock, flags);
+ * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+ */
+
+ for (i = 0; i < loop; i++) {
+ temp = off8 + (i << 3);
+ adapter->hw_write_wx(adapter,
+ mem_crb + MIU_TEST_AGT_ADDR_LO, &temp, 4);
+ temp = 0;
+ adapter->hw_write_wx(adapter,
+ mem_crb + MIU_TEST_AGT_ADDR_HI, &temp, 4);
+ temp = MIU_TA_CTL_ENABLE;
+ adapter->hw_write_wx(adapter,
+ mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+ temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
+ adapter->hw_write_wx(adapter,
+ mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ adapter->hw_read_wx(adapter,
+ mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+ if ((temp & MIU_TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ printk(KERN_ERR "%s: Fail to read through agent\n",
+ netxen_nic_driver_name);
+ break;
+ }
+
+ start = off0[i] >> 2;
+ end = (off0[i] + sz[i] - 1) >> 2;
+ for (k = start; k <= end; k++) {
+ adapter->hw_read_wx(adapter,
+ mem_crb + MIU_TEST_AGT_RDDATA(k), &temp, 4);
+ word[i] |= ((uint64_t)temp << (32 * k));
+ }
+ }
+
+ /*
+ * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+ * write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ */
+
+ if (j >= MAX_CTL_CHECK)
+ return -1;
+
+ if (sz[0] == 8) {
+ val = word[0];
+ } else {
+ val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
+ ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
+ }
+
+ switch (size) {
+ case 1:
+ *(uint8_t *)data = val;
+ break;
+ case 2:
+ *(uint16_t *)data = val;
+ break;
+ case 4:
+ *(uint32_t *)data = val;
+ break;
+ case 8:
+ *(uint64_t *)data = val;
+ break;
+ }
+ DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data);
+ return 0;
+}
+
+/*
+ * Note : only 32-bit writes!
+ */
+int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter,
+ u64 off, u32 data)
+{
+ adapter->hw_write_wx(adapter, off, &data, 4);
+
+ return 0;
+}
+
+u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off)
+{
+ u32 temp;
+ adapter->hw_read_wx(adapter, off, &temp, 4);
+ return temp;
+}
+
+void netxen_nic_pci_write_normalize_2M(struct netxen_adapter *adapter,
+ u64 off, u32 data)
+{
+ adapter->hw_write_wx(adapter, off, &data, 4);
+}
+
+u32 netxen_nic_pci_read_normalize_2M(struct netxen_adapter *adapter, u64 off)
+{
+ u32 temp;
+ adapter->hw_read_wx(adapter, off, &temp, 4);
+ return temp;
+}
+
#if 0
int
netxen_nic_erase_pxe(struct netxen_adapter *adapter)
@@ -1003,12 +2010,25 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+ case NETXEN_BRDTYPE_P3_HMEZ:
+ case NETXEN_BRDTYPE_P3_XG_LOM:
+ case NETXEN_BRDTYPE_P3_10G_CX4:
+ case NETXEN_BRDTYPE_P3_10G_CX4_LP:
+ case NETXEN_BRDTYPE_P3_IMEZ:
+ case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
+ case NETXEN_BRDTYPE_P3_10G_XFP:
+ case NETXEN_BRDTYPE_P3_10000_BASE_T:
+
adapter->ahw.board_type = NETXEN_NIC_XGBE;
break;
case NETXEN_BRDTYPE_P1_BD:
case NETXEN_BRDTYPE_P1_SB:
case NETXEN_BRDTYPE_P1_SMAX:
case NETXEN_BRDTYPE_P1_SOCK:
+ case NETXEN_BRDTYPE_P3_REF_QG:
+ case NETXEN_BRDTYPE_P3_4_GB:
+ case NETXEN_BRDTYPE_P3_4_GB_MM:
+
adapter->ahw.board_type = NETXEN_NIC_GBE;
break;
default:
@@ -1042,25 +2062,11 @@ int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu)
return 0;
}
-void netxen_nic_init_niu_gb(struct netxen_adapter *adapter)
-{
- netxen_niu_gbe_init_port(adapter, adapter->physical_port);
-}
-
void
-netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off,
- int data)
+netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
+ unsigned long off, int data)
{
- void __iomem *addr;
-
- if (ADDR_IN_WINDOW1(off)) {
- writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
- } else {
- netxen_nic_pci_change_crbwindow(adapter, 0);
- addr = pci_base_offset(adapter, off);
- writel(data, addr);
- netxen_nic_pci_change_crbwindow(adapter, 1);
- }
+ adapter->hw_write_wx(adapter, off, &data, 4);
}
void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
@@ -1147,12 +2153,11 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
addr += sizeof(u32);
}
- fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_FW_VERSION_MAJOR));
- fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_FW_VERSION_MINOR));
- fw_build =
- readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB));
+ adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MAJOR, &fw_major, 4);
+ adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MINOR, &fw_minor, 4);
+ adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_SUB, &fw_build, 4);
+
+ adapter->fw_major = fw_major;
if (adapter->portnum == 0) {
get_brd_name_by_type(board_info->board_type, brd_name);
@@ -1163,28 +2168,13 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
fw_minor, fw_build);
}
- if (fw_major != _NETXEN_NIC_LINUX_MAJOR) {
- adapter->driver_mismatch = 1;
- }
- if (fw_minor != _NETXEN_NIC_LINUX_MINOR &&
- fw_minor != (_NETXEN_NIC_LINUX_MINOR + 1)) {
+ if (NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build) <
+ NETXEN_VERSION_CODE(3, 4, 216)) {
adapter->driver_mismatch = 1;
- }
- if (adapter->driver_mismatch) {
- printk(KERN_ERR "%s: driver and firmware version mismatch\n",
- adapter->netdev->name);
+ printk(KERN_ERR "%s: firmware version %d.%d.%d unsupported\n",
+ netxen_nic_driver_name,
+ fw_major, fw_minor, fw_build);
return;
}
-
- switch (adapter->ahw.board_type) {
- case NETXEN_NIC_GBE:
- dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n",
- adapter->netdev->name);
- break;
- case NETXEN_NIC_XGBE:
- dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n",
- adapter->netdev->name);
- break;
- }
}
diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h
index a3ea1dd98c4..b8e0030f03d 100644
--- a/drivers/net/netxen/netxen_nic_hw.h
+++ b/drivers/net/netxen/netxen_nic_hw.h
@@ -82,19 +82,9 @@ struct netxen_adapter;
#define NETXEN_PCI_MAPSIZE_BYTES (NETXEN_PCI_MAPSIZE << 20)
-#define NETXEN_NIC_LOCKED_READ_REG(X, Y) \
- addr = pci_base_offset(adapter, X); \
- *(u32 *)Y = readl((void __iomem*) addr);
-
struct netxen_port;
void netxen_nic_set_link_parameters(struct netxen_adapter *adapter);
void netxen_nic_flash_print(struct netxen_adapter *adapter);
-int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off,
- void *data, int len);
-void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
- unsigned long off, int data);
-int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off,
- void *data, int len);
typedef u8 netxen_ethernet_macaddr_t[6];
@@ -432,7 +422,8 @@ typedef enum {
/* Promiscous mode options (GbE mode only) */
typedef enum {
NETXEN_NIU_PROMISC_MODE = 0,
- NETXEN_NIU_NON_PROMISC_MODE
+ NETXEN_NIU_NON_PROMISC_MODE,
+ NETXEN_NIU_ALLMULTI_MODE
} netxen_niu_prom_mode_t;
/*
@@ -478,42 +469,6 @@ typedef enum {
#define netxen_xg_soft_reset(config_word) \
((config_word) |= 1 << 4)
-/*
- * MAC Control Register
- *
- * Bit 0-1 : id_pool0
- * Bit 2 : enable_xtnd0
- * Bit 4-5 : id_pool1
- * Bit 6 : enable_xtnd1
- * Bit 8-9 : id_pool2
- * Bit 10 : enable_xtnd2
- * Bit 12-13 : id_pool3
- * Bit 14 : enable_xtnd3
- * Bit 24-25 : mode_select
- * Bit 28-31 : enable_pool
- */
-
-#define netxen_nic_mcr_set_id_pool0(config, val) \
- ((config) |= ((val) &0x03))
-#define netxen_nic_mcr_set_enable_xtnd0(config) \
- ((config) |= 1 << 3)
-#define netxen_nic_mcr_set_id_pool1(config, val) \
- ((config) |= (((val) & 0x03) << 4))
-#define netxen_nic_mcr_set_enable_xtnd1(config) \
- ((config) |= 1 << 6)
-#define netxen_nic_mcr_set_id_pool2(config, val) \
- ((config) |= (((val) & 0x03) << 8))
-#define netxen_nic_mcr_set_enable_xtnd2(config) \
- ((config) |= 1 << 10)
-#define netxen_nic_mcr_set_id_pool3(config, val) \
- ((config) |= (((val) & 0x03) << 12))
-#define netxen_nic_mcr_set_enable_xtnd3(config) \
- ((config) |= 1 << 14)
-#define netxen_nic_mcr_set_mode_select(config, val) \
- ((config) |= (((val) & 0x03) << 24))
-#define netxen_nic_mcr_set_enable_pool(config, val) \
- ((config) |= (((val) & 0x0f) << 28))
-
/* Set promiscuous mode for a GbE interface */
int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
netxen_niu_prom_mode_t mode);
@@ -538,4 +493,15 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter);
int netxen_niu_disable_xg_port(struct netxen_adapter *adapter);
+typedef struct {
+ unsigned valid;
+ unsigned start_128M;
+ unsigned end_128M;
+ unsigned start_2M;
+} crb_128M_2M_sub_block_map_t;
+
+typedef struct {
+ crb_128M_2M_sub_block_map_t sub_block[16];
+} crb_128M_2M_block_map_t;
+
#endif /* __NETXEN_NIC_HW_H_ */
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 70d1b22ced2..01ab31b34a8 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -42,8 +42,6 @@ struct crb_addr_pair {
u32 data;
};
-unsigned long last_schedule_time;
-
#define NETXEN_MAX_CRB_XFORM 60
static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM];
#define NETXEN_ADDR_ERROR (0xffffffff)
@@ -117,6 +115,8 @@ static void crb_addr_transform_setup(void)
crb_addr_transform(C2C1);
crb_addr_transform(C2C0);
crb_addr_transform(SMB);
+ crb_addr_transform(OCM0);
+ crb_addr_transform(I2C0);
}
int netxen_init_firmware(struct netxen_adapter *adapter)
@@ -124,15 +124,15 @@ int netxen_init_firmware(struct netxen_adapter *adapter)
u32 state = 0, loops = 0, err = 0;
/* Window 1 call */
- state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+ state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE);
if (state == PHAN_INITIALIZE_ACK)
return 0;
while (state != PHAN_INITIALIZE_COMPLETE && loops < 2000) {
- udelay(100);
+ msleep(1);
/* Window 1 call */
- state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+ state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE);
loops++;
}
@@ -143,64 +143,193 @@ int netxen_init_firmware(struct netxen_adapter *adapter)
return err;
}
/* Window 1 call */
- writel(INTR_SCHEME_PERPORT,
- NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_HOST));
- writel(MSI_MODE_MULTIFUNC,
- NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_MSI_MODE_HOST));
- writel(MPORT_MULTI_FUNCTION_MODE,
- NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE));
- writel(PHAN_INITIALIZE_ACK,
- NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+ adapter->pci_write_normalize(adapter,
+ CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT);
+ adapter->pci_write_normalize(adapter,
+ CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC);
+ adapter->pci_write_normalize(adapter,
+ CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE);
+ adapter->pci_write_normalize(adapter,
+ CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
return err;
}
-#define NETXEN_ADDR_LIMIT 0xffffffffULL
+void netxen_release_rx_buffers(struct netxen_adapter *adapter)
+{
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+ struct netxen_rx_buffer *rx_buf;
+ int i, ctxid, ring;
+
+ for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
+ recv_ctx = &adapter->recv_ctx[ctxid];
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+ for (i = 0; i < rds_ring->max_rx_desc_count; ++i) {
+ rx_buf = &(rds_ring->rx_buf_arr[i]);
+ if (rx_buf->state == NETXEN_BUFFER_FREE)
+ continue;
+ pci_unmap_single(adapter->pdev,
+ rx_buf->dma,
+ rds_ring->dma_size,
+ PCI_DMA_FROMDEVICE);
+ if (rx_buf->skb != NULL)
+ dev_kfree_skb_any(rx_buf->skb);
+ }
+ }
+ }
+}
-void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr,
- struct pci_dev **used_dev)
+void netxen_release_tx_buffers(struct netxen_adapter *adapter)
{
- void *addr;
+ struct netxen_cmd_buffer *cmd_buf;
+ struct netxen_skb_frag *buffrag;
+ int i, j;
+
+ cmd_buf = adapter->cmd_buf_arr;
+ for (i = 0; i < adapter->max_tx_desc_count; i++) {
+ buffrag = cmd_buf->frag_array;
+ if (buffrag->dma) {
+ pci_unmap_single(adapter->pdev, buffrag->dma,
+ buffrag->length, PCI_DMA_TODEVICE);
+ buffrag->dma = 0ULL;
+ }
+ for (j = 0; j < cmd_buf->frag_count; j++) {
+ buffrag++;
+ if (buffrag->dma) {
+ pci_unmap_page(adapter->pdev, buffrag->dma,
+ buffrag->length,
+ PCI_DMA_TODEVICE);
+ buffrag->dma = 0ULL;
+ }
+ }
+ /* Free the skb we received in netxen_nic_xmit_frame */
+ if (cmd_buf->skb) {
+ dev_kfree_skb_any(cmd_buf->skb);
+ cmd_buf->skb = NULL;
+ }
+ cmd_buf++;
+ }
+}
- addr = pci_alloc_consistent(pdev, sz, ptr);
- if ((unsigned long long)(*ptr) < NETXEN_ADDR_LIMIT) {
- *used_dev = pdev;
- return addr;
+void netxen_free_sw_resources(struct netxen_adapter *adapter)
+{
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+ int ctx, ring;
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ctx++) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+ if (rds_ring->rx_buf_arr) {
+ vfree(rds_ring->rx_buf_arr);
+ rds_ring->rx_buf_arr = NULL;
+ }
+ }
}
- pci_free_consistent(pdev, sz, addr, *ptr);
- addr = pci_alloc_consistent(NULL, sz, ptr);
- *used_dev = NULL;
- return addr;
+ if (adapter->cmd_buf_arr)
+ vfree(adapter->cmd_buf_arr);
+ return;
}
-void netxen_initialize_adapter_sw(struct netxen_adapter *adapter)
+int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
{
- int ctxid, ring;
- u32 i;
- u32 num_rx_bufs = 0;
- struct netxen_rcv_desc_ctx *rcv_desc;
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+ struct netxen_rx_buffer *rx_buf;
+ int ctx, ring, i, num_rx_bufs;
- DPRINTK(INFO, "initializing some queues: %p\n", adapter);
- for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- struct netxen_rx_buffer *rx_buf;
- rcv_desc = &adapter->recv_ctx[ctxid].rcv_desc[ring];
- rcv_desc->begin_alloc = 0;
- rx_buf = rcv_desc->rx_buf_arr;
- num_rx_bufs = rcv_desc->max_rx_desc_count;
+ struct netxen_cmd_buffer *cmd_buf_arr;
+ struct net_device *netdev = adapter->netdev;
+
+ cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE);
+ if (cmd_buf_arr == NULL) {
+ printk(KERN_ERR "%s: Failed to allocate cmd buffer ring\n",
+ netdev->name);
+ return -ENOMEM;
+ }
+ memset(cmd_buf_arr, 0, TX_RINGSIZE);
+ adapter->cmd_buf_arr = cmd_buf_arr;
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ctx++) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+ switch (RCV_DESC_TYPE(ring)) {
+ case RCV_DESC_NORMAL:
+ rds_ring->max_rx_desc_count =
+ adapter->max_rx_desc_count;
+ rds_ring->flags = RCV_DESC_NORMAL;
+ if (adapter->ahw.cut_through) {
+ rds_ring->dma_size =
+ NX_CT_DEFAULT_RX_BUF_LEN;
+ rds_ring->skb_size =
+ NX_CT_DEFAULT_RX_BUF_LEN;
+ } else {
+ rds_ring->dma_size = RX_DMA_MAP_LEN;
+ rds_ring->skb_size =
+ MAX_RX_BUFFER_LENGTH;
+ }
+ break;
+
+ case RCV_DESC_JUMBO:
+ rds_ring->max_rx_desc_count =
+ adapter->max_jumbo_rx_desc_count;
+ rds_ring->flags = RCV_DESC_JUMBO;
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ rds_ring->dma_size =
+ NX_P3_RX_JUMBO_BUF_MAX_LEN;
+ else
+ rds_ring->dma_size =
+ NX_P2_RX_JUMBO_BUF_MAX_LEN;
+ rds_ring->skb_size =
+ rds_ring->dma_size + NET_IP_ALIGN;
+ break;
+
+ case RCV_RING_LRO:
+ rds_ring->max_rx_desc_count =
+ adapter->max_lro_rx_desc_count;
+ rds_ring->flags = RCV_DESC_LRO;
+ rds_ring->dma_size = RX_LRO_DMA_MAP_LEN;
+ rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
+ break;
+
+ }
+ rds_ring->rx_buf_arr = (struct netxen_rx_buffer *)
+ vmalloc(RCV_BUFFSIZE);
+ if (rds_ring->rx_buf_arr == NULL) {
+ printk(KERN_ERR "%s: Failed to allocate "
+ "rx buffer ring %d\n",
+ netdev->name, ring);
+ /* free whatever was already allocated */
+ goto err_out;
+ }
+ memset(rds_ring->rx_buf_arr, 0, RCV_BUFFSIZE);
+ INIT_LIST_HEAD(&rds_ring->free_list);
+ rds_ring->begin_alloc = 0;
/*
* Now go through all of them, set reference handles
* and put them in the queues.
*/
+ num_rx_bufs = rds_ring->max_rx_desc_count;
+ rx_buf = rds_ring->rx_buf_arr;
for (i = 0; i < num_rx_bufs; i++) {
+ list_add_tail(&rx_buf->list,
+ &rds_ring->free_list);
rx_buf->ref_handle = i;
rx_buf->state = NETXEN_BUFFER_FREE;
- DPRINTK(INFO, "Rx buf:ctx%d i(%d) rx_buf:"
- "%p\n", ctxid, i, rx_buf);
rx_buf++;
}
}
}
+
+ return 0;
+
+err_out:
+ netxen_free_sw_resources(adapter);
+ return -ENOMEM;
}
void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
@@ -211,14 +340,12 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
netxen_niu_gbe_enable_phy_interrupts;
adapter->disable_phy_interrupts =
netxen_niu_gbe_disable_phy_interrupts;
- adapter->handle_phy_intr = netxen_nic_gbe_handle_phy_intr;
adapter->macaddr_set = netxen_niu_macaddr_set;
adapter->set_mtu = netxen_nic_set_mtu_gb;
adapter->set_promisc = netxen_niu_set_promiscuous_mode;
- adapter->unset_promisc = netxen_niu_set_promiscuous_mode;
adapter->phy_read = netxen_niu_gbe_phy_read;
adapter->phy_write = netxen_niu_gbe_phy_write;
- adapter->init_niu = netxen_nic_init_niu_gb;
+ adapter->init_port = netxen_niu_gbe_init_port;
adapter->stop_port = netxen_niu_disable_gbe_port;
break;
@@ -227,12 +354,10 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
netxen_niu_xgbe_enable_phy_interrupts;
adapter->disable_phy_interrupts =
netxen_niu_xgbe_disable_phy_interrupts;
- adapter->handle_phy_intr = netxen_nic_xgbe_handle_phy_intr;
adapter->macaddr_set = netxen_niu_xg_macaddr_set;
adapter->set_mtu = netxen_nic_set_mtu_xgb;
adapter->init_port = netxen_niu_xg_init_port;
adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode;
- adapter->unset_promisc = netxen_niu_xg_set_promiscuous_mode;
adapter->stop_port = netxen_niu_disable_xg_port;
break;
@@ -270,7 +395,9 @@ static u32 netxen_decode_crb_addr(u32 addr)
static long rom_max_timeout = 100;
static long rom_lock_timeout = 10000;
+#if 0
static long rom_write_timeout = 700;
+#endif
static int rom_lock(struct netxen_adapter *adapter)
{
@@ -319,6 +446,7 @@ static int netxen_wait_rom_done(struct netxen_adapter *adapter)
return 0;
}
+#if 0
static int netxen_rom_wren(struct netxen_adapter *adapter)
{
/* Set write enable latch in ROM status register */
@@ -348,6 +476,7 @@ static int netxen_do_rom_rdsr(struct netxen_adapter *adapter)
}
return netxen_rdcrbreg(adapter, NETXEN_ROMUSB_ROM_RDATA);
}
+#endif
static void netxen_rom_unlock(struct netxen_adapter *adapter)
{
@@ -358,6 +487,7 @@ static void netxen_rom_unlock(struct netxen_adapter *adapter)
}
+#if 0
static int netxen_rom_wip_poll(struct netxen_adapter *adapter)
{
long timeout = 0;
@@ -393,6 +523,7 @@ static int do_rom_fast_write(struct netxen_adapter *adapter, int addr,
return netxen_rom_wip_poll(adapter);
}
+#endif
static int do_rom_fast_read(struct netxen_adapter *adapter,
int addr, int *valp)
@@ -475,7 +606,6 @@ int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data)
netxen_rom_unlock(adapter);
return ret;
}
-#endif /* 0 */
static int do_rom_fast_write_words(struct netxen_adapter *adapter,
int addr, u8 *bytes, size_t size)
@@ -740,28 +870,25 @@ int netxen_flash_unlock(struct netxen_adapter *adapter)
return ret;
}
+#endif /* 0 */
#define NETXEN_BOARDTYPE 0x4008
#define NETXEN_BOARDNUM 0x400c
#define NETXEN_CHIPNUM 0x4010
-#define NETXEN_ROMBUS_RESET 0xFFFFFFFF
-#define NETXEN_ROM_FIRST_BARRIER 0x800000000ULL
-#define NETXEN_ROM_FOUND_INIT 0x400
int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
{
int addr, val;
- int n, i;
- int init_delay = 0;
+ int i, init_delay = 0;
struct crb_addr_pair *buf;
+ unsigned offset, n;
u32 off;
/* resetall */
netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
- NETXEN_ROMBUS_RESET);
+ 0xffffffff);
if (verbose) {
- int val;
if (netxen_rom_fast_read(adapter, NETXEN_BOARDTYPE, &val) == 0)
printk("P2 ROM board type: 0x%08x\n", val);
else
@@ -776,117 +903,141 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
printk("Could not read chip number\n");
}
- if (netxen_rom_fast_read(adapter, 0, &n) == 0
- && (n & NETXEN_ROM_FIRST_BARRIER)) {
- n &= ~NETXEN_ROM_ROUNDUP;
- if (n < NETXEN_ROM_FOUND_INIT) {
- if (verbose)
- printk("%s: %d CRB init values found"
- " in ROM.\n", netxen_nic_driver_name, n);
- } else {
- printk("%s:n=0x%x Error! NetXen card flash not"
- " initialized.\n", __FUNCTION__, n);
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
+ (n != 0xcafecafeUL) ||
+ netxen_rom_fast_read(adapter, 4, &n) != 0) {
+ printk(KERN_ERR "%s: ERROR Reading crb_init area: "
+ "n: %08x\n", netxen_nic_driver_name, n);
return -EIO;
}
- buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
- if (buf == NULL) {
- printk("%s: netxen_pinit_from_rom: Unable to calloc "
- "memory.\n", netxen_nic_driver_name);
- return -ENOMEM;
- }
- for (i = 0; i < n; i++) {
- if (netxen_rom_fast_read(adapter, 8 * i + 4, &val) != 0
- || netxen_rom_fast_read(adapter, 8 * i + 8,
- &addr) != 0)
- return -EIO;
-
- buf[i].addr = addr;
- buf[i].data = val;
-
- if (verbose)
- printk("%s: PCI: 0x%08x == 0x%08x\n",
- netxen_nic_driver_name, (unsigned int)
- netxen_decode_crb_addr(addr), val);
+ offset = n & 0xffffU;
+ n = (n >> 16) & 0xffffU;
+ } else {
+ if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
+ !(n & 0x80000000)) {
+ printk(KERN_ERR "%s: ERROR Reading crb_init area: "
+ "n: %08x\n", netxen_nic_driver_name, n);
+ return -EIO;
}
- for (i = 0; i < n; i++) {
+ offset = 1;
+ n &= ~0x80000000;
+ }
+
+ if (n < 1024) {
+ if (verbose)
+ printk(KERN_DEBUG "%s: %d CRB init values found"
+ " in ROM.\n", netxen_nic_driver_name, n);
+ } else {
+ printk(KERN_ERR "%s:n=0x%x Error! NetXen card flash not"
+ " initialized.\n", __func__, n);
+ return -EIO;
+ }
+
+ buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
+ if (buf == NULL) {
+ printk("%s: netxen_pinit_from_rom: Unable to calloc memory.\n",
+ netxen_nic_driver_name);
+ return -ENOMEM;
+ }
+ for (i = 0; i < n; i++) {
+ if (netxen_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 ||
+ netxen_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0)
+ return -EIO;
+
+ buf[i].addr = addr;
+ buf[i].data = val;
- off = netxen_decode_crb_addr(buf[i].addr);
- if (off == NETXEN_ADDR_ERROR) {
- printk(KERN_ERR"CRB init value out of range %x\n",
+ if (verbose)
+ printk(KERN_DEBUG "%s: PCI: 0x%08x == 0x%08x\n",
+ netxen_nic_driver_name,
+ (u32)netxen_decode_crb_addr(addr), val);
+ }
+ for (i = 0; i < n; i++) {
+
+ off = netxen_decode_crb_addr(buf[i].addr);
+ if (off == NETXEN_ADDR_ERROR) {
+ printk(KERN_ERR"CRB init value out of range %x\n",
buf[i].addr);
+ continue;
+ }
+ off += NETXEN_PCI_CRBSPACE;
+ /* skipping cold reboot MAGIC */
+ if (off == NETXEN_CAM_RAM(0x1fc))
+ continue;
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ /* do not reset PCI */
+ if (off == (ROMUSB_GLB + 0xbc))
continue;
- }
- off += NETXEN_PCI_CRBSPACE;
- /* skipping cold reboot MAGIC */
- if (off == NETXEN_CAM_RAM(0x1fc))
+ if (off == (NETXEN_CRB_PEG_NET_1 + 0x18))
+ buf[i].data = 0x1020;
+ /* skip the function enable register */
+ if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION))
+ continue;
+ if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION2))
continue;
+ if ((off & 0x0ff00000) == NETXEN_CRB_SMB)
+ continue;
+ }
- /* After writing this register, HW needs time for CRB */
- /* to quiet down (else crb_window returns 0xffffffff) */
- if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
- init_delay = 1;
+ if (off == NETXEN_ADDR_ERROR) {
+ printk(KERN_ERR "%s: Err: Unknown addr: 0x%08x\n",
+ netxen_nic_driver_name, buf[i].addr);
+ continue;
+ }
+
+ /* After writing this register, HW needs time for CRB */
+ /* to quiet down (else crb_window returns 0xffffffff) */
+ if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
+ init_delay = 1;
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
/* hold xdma in reset also */
buf[i].data = NETXEN_NIC_XDMA_RESET;
}
+ }
- if (ADDR_IN_WINDOW1(off)) {
- writel(buf[i].data,
- NETXEN_CRB_NORMALIZE(adapter, off));
- } else {
- netxen_nic_pci_change_crbwindow(adapter, 0);
- writel(buf[i].data,
- pci_base_offset(adapter, off));
+ adapter->hw_write_wx(adapter, off, &buf[i].data, 4);
- netxen_nic_pci_change_crbwindow(adapter, 1);
- }
- if (init_delay == 1) {
- msleep(1000);
- init_delay = 0;
- }
- msleep(1);
+ if (init_delay == 1) {
+ msleep(1000);
+ init_delay = 0;
}
- kfree(buf);
+ msleep(1);
+ }
+ kfree(buf);
- /* disable_peg_cache_all */
+ /* disable_peg_cache_all */
- /* unreset_net_cache */
- netxen_nic_hw_read_wx(adapter, NETXEN_ROMUSB_GLB_SW_RESET, &val,
- 4);
- netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
- (val & 0xffffff0f));
- /* p2dn replyCount */
- netxen_crb_writelit_adapter(adapter,
- NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
- /* disable_peg_cache 0 */
+ /* unreset_net_cache */
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ adapter->hw_read_wx(adapter,
+ NETXEN_ROMUSB_GLB_SW_RESET, &val, 4);
netxen_crb_writelit_adapter(adapter,
- NETXEN_CRB_PEG_NET_D + 0x4c, 8);
- /* disable_peg_cache 1 */
- netxen_crb_writelit_adapter(adapter,
- NETXEN_CRB_PEG_NET_I + 0x4c, 8);
-
- /* peg_clr_all */
-
- /* peg_clr 0 */
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8,
- 0);
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc,
- 0);
- /* peg_clr 1 */
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8,
- 0);
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc,
- 0);
- /* peg_clr 2 */
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8,
- 0);
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc,
- 0);
- /* peg_clr 3 */
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8,
- 0);
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc,
- 0);
+ NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f));
}
+
+ /* p2dn replyCount */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
+ /* disable_peg_cache 0 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8);
+ /* disable_peg_cache 1 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8);
+
+ /* peg_clr_all */
+
+ /* peg_clr 0 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0);
+ /* peg_clr 1 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0);
+ /* peg_clr 2 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0);
+ /* peg_clr 3 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0);
return 0;
}
@@ -897,12 +1048,12 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
uint32_t lo;
adapter->dummy_dma.addr =
- pci_alloc_consistent(adapter->ahw.pdev,
+ pci_alloc_consistent(adapter->pdev,
NETXEN_HOST_DUMMY_DMA_SIZE,
&adapter->dummy_dma.phys_addr);
if (adapter->dummy_dma.addr == NULL) {
printk("%s: ERROR: Could not allocate dummy DMA memory\n",
- __FUNCTION__);
+ __func__);
return -ENOMEM;
}
@@ -910,8 +1061,13 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
hi = (addr >> 32) & 0xffffffff;
lo = addr & 0xffffffff;
- writel(hi, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI));
- writel(lo, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO));
+ adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi);
+ adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ uint32_t temp = 0;
+ adapter->hw_write_wx(adapter, CRB_HOST_DUMMY_BUF, &temp, 4);
+ }
return 0;
}
@@ -931,7 +1087,7 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter)
} while (--i);
if (i) {
- pci_free_consistent(adapter->ahw.pdev,
+ pci_free_consistent(adapter->pdev,
NETXEN_HOST_DUMMY_DMA_SIZE,
adapter->dummy_dma.addr,
adapter->dummy_dma.phys_addr);
@@ -946,22 +1102,24 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter)
int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
{
u32 val = 0;
- int retries = 30;
+ int retries = 60;
if (!pegtune_val) {
do {
- val = readl(NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMDPEG_STATE));
- pegtune_val = readl(NETXEN_CRB_NORMALIZE
- (adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
+ val = adapter->pci_read_normalize(adapter,
+ CRB_CMDPEG_STATE);
if (val == PHAN_INITIALIZE_COMPLETE ||
val == PHAN_INITIALIZE_ACK)
return 0;
- msleep(1000);
+ msleep(500);
+
} while (--retries);
+
if (!retries) {
+ pegtune_val = adapter->pci_read_normalize(adapter,
+ NETXEN_ROMUSB_GLB_PEGTUNE_DONE);
printk(KERN_WARNING "netxen_phantom_init: init failed, "
"pegtune_val=%x\n", pegtune_val);
return -1;
@@ -971,58 +1129,61 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
return 0;
}
-static int netxen_nic_check_temp(struct netxen_adapter *adapter)
+int netxen_receive_peg_ready(struct netxen_adapter *adapter)
{
- struct net_device *netdev = adapter->netdev;
- uint32_t temp, temp_state, temp_val;
- int rv = 0;
-
- temp = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_TEMP_STATE));
-
- temp_state = nx_get_temp_state(temp);
- temp_val = nx_get_temp_val(temp);
-
- if (temp_state == NX_TEMP_PANIC) {
- printk(KERN_ALERT
- "%s: Device temperature %d degrees C exceeds"
- " maximum allowed. Hardware has been shut down.\n",
- netxen_nic_driver_name, temp_val);
-
- netif_carrier_off(netdev);
- netif_stop_queue(netdev);
- rv = 1;
- } else if (temp_state == NX_TEMP_WARN) {
- if (adapter->temp == NX_TEMP_NORMAL) {
- printk(KERN_ALERT
- "%s: Device temperature %d degrees C "
- "exceeds operating range."
- " Immediate action needed.\n",
- netxen_nic_driver_name, temp_val);
- }
- } else {
- if (adapter->temp == NX_TEMP_WARN) {
- printk(KERN_INFO
- "%s: Device temperature is now %d degrees C"
- " in normal range.\n", netxen_nic_driver_name,
- temp_val);
- }
+ u32 val = 0;
+ int retries = 2000;
+
+ do {
+ val = adapter->pci_read_normalize(adapter, CRB_RCVPEG_STATE);
+
+ if (val == PHAN_PEG_RCV_INITIALIZED)
+ return 0;
+
+ msleep(10);
+
+ } while (--retries);
+
+ if (!retries) {
+ printk(KERN_ERR "Receive Peg initialization not "
+ "complete, state: 0x%x.\n", val);
+ return -EIO;
}
- adapter->temp = temp_state;
- return rv;
+
+ return 0;
}
-void netxen_watchdog_task(struct work_struct *work)
+static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter,
+ struct nx_host_rds_ring *rds_ring, u16 index, u16 cksum)
{
- struct netxen_adapter *adapter =
- container_of(work, struct netxen_adapter, watchdog_task);
+ struct netxen_rx_buffer *buffer;
+ struct sk_buff *skb;
- if ((adapter->portnum == 0) && netxen_nic_check_temp(adapter))
- return;
+ buffer = &rds_ring->rx_buf_arr[index];
+
+ pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size,
+ PCI_DMA_FROMDEVICE);
- if (adapter->handle_phy_intr)
- adapter->handle_phy_intr(adapter);
+ skb = buffer->skb;
+ if (!skb)
+ goto no_skb;
- mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+ if (likely(adapter->rx_csum && cksum == STATUS_CKSUM_OK)) {
+ adapter->stats.csummed++;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ } else
+ skb->ip_summed = CHECKSUM_NONE;
+
+ skb->dev = adapter->netdev;
+
+ buffer->skb = NULL;
+
+no_skb:
+ buffer->state = NETXEN_BUFFER_FREE;
+ buffer->lro_current_frags = 0;
+ buffer->lro_expected_frags = 0;
+ list_add_tail(&buffer->list, &rds_ring->free_list);
+ return skb;
}
/*
@@ -1031,9 +1192,8 @@ void netxen_watchdog_task(struct work_struct *work)
* invoke the routine to send more rx buffers to the Phantom...
*/
static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
- struct status_desc *desc)
+ struct status_desc *desc, struct status_desc *frag_desc)
{
- struct pci_dev *pdev = adapter->pdev;
struct net_device *netdev = adapter->netdev;
u64 sts_data = le64_to_cpu(desc->status_desc_data);
int index = netxen_get_sts_refhandle(sts_data);
@@ -1042,8 +1202,8 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
struct sk_buff *skb;
u32 length = netxen_get_sts_totallength(sts_data);
u32 desc_ctx;
- struct netxen_rcv_desc_ctx *rcv_desc;
- int ret;
+ u16 pkt_offset = 0, cksum;
+ struct nx_host_rds_ring *rds_ring;
desc_ctx = netxen_get_sts_type(sts_data);
if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) {
@@ -1052,13 +1212,13 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
return;
}
- rcv_desc = &recv_ctx->rcv_desc[desc_ctx];
- if (unlikely(index > rcv_desc->max_rx_desc_count)) {
+ rds_ring = &recv_ctx->rds_rings[desc_ctx];
+ if (unlikely(index > rds_ring->max_rx_desc_count)) {
DPRINTK(ERR, "Got a buffer index:%x Max is %x\n",
- index, rcv_desc->max_rx_desc_count);
+ index, rds_ring->max_rx_desc_count);
return;
}
- buffer = &rcv_desc->rx_buf_arr[index];
+ buffer = &rds_ring->rx_buf_arr[index];
if (desc_ctx == RCV_DESC_LRO_CTXID) {
buffer->lro_current_frags++;
if (netxen_get_sts_desc_lro_last_frag(desc)) {
@@ -1079,43 +1239,52 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
}
}
- pci_unmap_single(pdev, buffer->dma, rcv_desc->dma_size,
- PCI_DMA_FROMDEVICE);
+ cksum = netxen_get_sts_status(sts_data);
- skb = (struct sk_buff *)buffer->skb;
-
- if (likely(adapter->rx_csum &&
- netxen_get_sts_status(sts_data) == STATUS_CKSUM_OK)) {
- adapter->stats.csummed++;
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- } else
- skb->ip_summed = CHECKSUM_NONE;
+ skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum);
+ if (!skb)
+ return;
- skb->dev = netdev;
if (desc_ctx == RCV_DESC_LRO_CTXID) {
/* True length was only available on the last pkt */
skb_put(skb, buffer->lro_length);
} else {
- skb_put(skb, length);
+ if (length > rds_ring->skb_size)
+ skb_put(skb, rds_ring->skb_size);
+ else
+ skb_put(skb, length);
+
+ pkt_offset = netxen_get_sts_pkt_offset(sts_data);
+ if (pkt_offset)
+ skb_pull(skb, pkt_offset);
}
skb->protocol = eth_type_trans(skb, netdev);
- ret = netif_receive_skb(skb);
- netdev->last_rx = jiffies;
-
- rcv_desc->rcv_pending--;
-
/*
- * We just consumed one buffer so post a buffer.
+ * rx buffer chaining is disabled, walk and free
+ * any spurious rx buffer chain.
*/
- buffer->skb = NULL;
- buffer->state = NETXEN_BUFFER_FREE;
- buffer->lro_current_frags = 0;
- buffer->lro_expected_frags = 0;
+ if (frag_desc) {
+ u16 i, nr_frags = desc->nr_frags;
+
+ dev_kfree_skb_any(skb);
+ for (i = 0; i < nr_frags; i++) {
+ index = frag_desc->frag_handles[i];
+ skb = netxen_process_rxbuf(adapter,
+ rds_ring, index, cksum);
+ if (skb)
+ dev_kfree_skb_any(skb);
+ }
+ adapter->stats.rxdropped++;
+ } else {
- adapter->stats.no_rcv++;
- adapter->stats.rxbytes += length;
+ netif_receive_skb(skb);
+ netdev->last_rx = jiffies;
+
+ adapter->stats.no_rcv++;
+ adapter->stats.rxbytes += length;
+ }
}
/* Process Receive status ring */
@@ -1123,10 +1292,11 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
{
struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]);
struct status_desc *desc_head = recv_ctx->rcv_status_desc_head;
- struct status_desc *desc; /* used to read status desc here */
+ struct status_desc *desc, *frag_desc;
u32 consumer = recv_ctx->status_rx_consumer;
- u32 producer = 0;
int count = 0, ring;
+ u64 sts_data;
+ u16 opcode;
while (count < max) {
desc = &desc_head[consumer];
@@ -1135,24 +1305,38 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
netxen_get_sts_owner(desc));
break;
}
- netxen_process_rcv(adapter, ctxid, desc);
+
+ sts_data = le64_to_cpu(desc->status_desc_data);
+ opcode = netxen_get_sts_opcode(sts_data);
+ frag_desc = NULL;
+ if (opcode == NETXEN_NIC_RXPKT_DESC) {
+ if (desc->nr_frags) {
+ consumer = get_next_index(consumer,
+ adapter->max_rx_desc_count);
+ frag_desc = &desc_head[consumer];
+ netxen_set_sts_owner(frag_desc,
+ STATUS_OWNER_PHANTOM);
+ }
+ }
+
+ netxen_process_rcv(adapter, ctxid, desc, frag_desc);
+
netxen_set_sts_owner(desc, STATUS_OWNER_PHANTOM);
- consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1);
+
+ consumer = get_next_index(consumer,
+ adapter->max_rx_desc_count);
count++;
}
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++)
+ for (ring = 0; ring < adapter->max_rds_rings; ring++)
netxen_post_rx_buffers_nodb(adapter, ctxid, ring);
/* update the consumer index in phantom */
if (count) {
recv_ctx->status_rx_consumer = consumer;
- recv_ctx->status_rx_producer = producer;
/* Window = 1 */
- writel(consumer,
- NETXEN_CRB_NORMALIZE(adapter,
- recv_crb_registers[adapter->portnum].
- crb_rcv_status_consumer));
+ adapter->pci_write_normalize(adapter,
+ recv_ctx->crb_sts_consumer, consumer);
}
return count;
@@ -1231,10 +1415,10 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
*/
void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
{
- struct pci_dev *pdev = adapter->ahw.pdev;
+ struct pci_dev *pdev = adapter->pdev;
struct sk_buff *skb;
struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]);
- struct netxen_rcv_desc_ctx *rcv_desc = NULL;
+ struct nx_host_rds_ring *rds_ring = NULL;
uint producer;
struct rcv_desc *pdesc;
struct netxen_rx_buffer *buffer;
@@ -1242,41 +1426,36 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
int index = 0;
netxen_ctx_msg msg = 0;
dma_addr_t dma;
+ struct list_head *head;
- rcv_desc = &recv_ctx->rcv_desc[ringid];
+ rds_ring = &recv_ctx->rds_rings[ringid];
+
+ producer = rds_ring->producer;
+ index = rds_ring->begin_alloc;
+ head = &rds_ring->free_list;
- producer = rcv_desc->producer;
- index = rcv_desc->begin_alloc;
- buffer = &rcv_desc->rx_buf_arr[index];
/* We can start writing rx descriptors into the phantom memory. */
- while (buffer->state == NETXEN_BUFFER_FREE) {
- skb = dev_alloc_skb(rcv_desc->skb_size);
+ while (!list_empty(head)) {
+
+ skb = dev_alloc_skb(rds_ring->skb_size);
if (unlikely(!skb)) {
- /*
- * TODO
- * We need to schedule the posting of buffers to the pegs.
- */
- rcv_desc->begin_alloc = index;
- DPRINTK(ERR, "netxen_post_rx_buffers: "
- " allocated only %d buffers\n", count);
+ rds_ring->begin_alloc = index;
break;
}
+ buffer = list_entry(head->next, struct netxen_rx_buffer, list);
+ list_del(&buffer->list);
+
count++; /* now there should be no failure */
- pdesc = &rcv_desc->desc_head[producer];
+ pdesc = &rds_ring->desc_head[producer];
-#if defined(XGB_DEBUG)
- *(unsigned long *)(skb->head) = 0xc0debabe;
- if (skb_is_nonlinear(skb)) {
- printk("Allocated SKB @%p is nonlinear\n");
- }
-#endif
- skb_reserve(skb, 2);
+ if (!adapter->ahw.cut_through)
+ skb_reserve(skb, 2);
/* This will be setup when we receive the
* buffer after it has been filled FSL TBD TBD
* skb->dev = netdev;
*/
- dma = pci_map_single(pdev, skb->data, rcv_desc->dma_size,
+ dma = pci_map_single(pdev, skb->data, rds_ring->dma_size,
PCI_DMA_FROMDEVICE);
pdesc->addr_buffer = cpu_to_le64(dma);
buffer->skb = skb;
@@ -1284,112 +1463,101 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
buffer->dma = dma;
/* make a rcv descriptor */
pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
- pdesc->buffer_length = cpu_to_le32(rcv_desc->dma_size);
+ pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
DPRINTK(INFO, "done writing descripter\n");
producer =
- get_next_index(producer, rcv_desc->max_rx_desc_count);
- index = get_next_index(index, rcv_desc->max_rx_desc_count);
- buffer = &rcv_desc->rx_buf_arr[index];
+ get_next_index(producer, rds_ring->max_rx_desc_count);
+ index = get_next_index(index, rds_ring->max_rx_desc_count);
}
/* if we did allocate buffers, then write the count to Phantom */
if (count) {
- rcv_desc->begin_alloc = index;
- rcv_desc->rcv_pending += count;
- rcv_desc->producer = producer;
+ rds_ring->begin_alloc = index;
+ rds_ring->producer = producer;
/* Window = 1 */
- writel((producer - 1) &
- (rcv_desc->max_rx_desc_count - 1),
- NETXEN_CRB_NORMALIZE(adapter,
- recv_crb_registers[
- adapter->portnum].
- rcv_desc_crb[ringid].
- crb_rcv_producer_offset));
+ adapter->pci_write_normalize(adapter,
+ rds_ring->crb_rcv_producer,
+ (producer-1) & (rds_ring->max_rx_desc_count-1));
+
+ if (adapter->fw_major < 4) {
/*
* Write a doorbell msg to tell phanmon of change in
* receive ring producer
+ * Only for firmware version < 4.0.0
*/
netxen_set_msg_peg_id(msg, NETXEN_RCV_PEG_DB_ID);
netxen_set_msg_privid(msg);
netxen_set_msg_count(msg,
((producer -
- 1) & (rcv_desc->
+ 1) & (rds_ring->
max_rx_desc_count - 1)));
netxen_set_msg_ctxid(msg, adapter->portnum);
netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid));
writel(msg,
DB_NORMALIZE(adapter,
NETXEN_RCV_PRODUCER_OFFSET));
+ }
}
}
static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
uint32_t ctx, uint32_t ringid)
{
- struct pci_dev *pdev = adapter->ahw.pdev;
+ struct pci_dev *pdev = adapter->pdev;
struct sk_buff *skb;
struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]);
- struct netxen_rcv_desc_ctx *rcv_desc = NULL;
+ struct nx_host_rds_ring *rds_ring = NULL;
u32 producer;
struct rcv_desc *pdesc;
struct netxen_rx_buffer *buffer;
int count = 0;
int index = 0;
+ struct list_head *head;
- rcv_desc = &recv_ctx->rcv_desc[ringid];
+ rds_ring = &recv_ctx->rds_rings[ringid];
- producer = rcv_desc->producer;
- index = rcv_desc->begin_alloc;
- buffer = &rcv_desc->rx_buf_arr[index];
+ producer = rds_ring->producer;
+ index = rds_ring->begin_alloc;
+ head = &rds_ring->free_list;
/* We can start writing rx descriptors into the phantom memory. */
- while (buffer->state == NETXEN_BUFFER_FREE) {
- skb = dev_alloc_skb(rcv_desc->skb_size);
+ while (!list_empty(head)) {
+
+ skb = dev_alloc_skb(rds_ring->skb_size);
if (unlikely(!skb)) {
- /*
- * We need to schedule the posting of buffers to the pegs.
- */
- rcv_desc->begin_alloc = index;
- DPRINTK(ERR, "netxen_post_rx_buffers_nodb: "
- " allocated only %d buffers\n", count);
+ rds_ring->begin_alloc = index;
break;
}
+
+ buffer = list_entry(head->next, struct netxen_rx_buffer, list);
+ list_del(&buffer->list);
+
count++; /* now there should be no failure */
- pdesc = &rcv_desc->desc_head[producer];
- skb_reserve(skb, 2);
- /*
- * This will be setup when we receive the
- * buffer after it has been filled
- * skb->dev = netdev;
- */
+ pdesc = &rds_ring->desc_head[producer];
+ if (!adapter->ahw.cut_through)
+ skb_reserve(skb, 2);
buffer->skb = skb;
buffer->state = NETXEN_BUFFER_BUSY;
buffer->dma = pci_map_single(pdev, skb->data,
- rcv_desc->dma_size,
+ rds_ring->dma_size,
PCI_DMA_FROMDEVICE);
/* make a rcv descriptor */
pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
- pdesc->buffer_length = cpu_to_le32(rcv_desc->dma_size);
+ pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
pdesc->addr_buffer = cpu_to_le64(buffer->dma);
- DPRINTK(INFO, "done writing descripter\n");
producer =
- get_next_index(producer, rcv_desc->max_rx_desc_count);
- index = get_next_index(index, rcv_desc->max_rx_desc_count);
- buffer = &rcv_desc->rx_buf_arr[index];
+ get_next_index(producer, rds_ring->max_rx_desc_count);
+ index = get_next_index(index, rds_ring->max_rx_desc_count);
+ buffer = &rds_ring->rx_buf_arr[index];
}
/* if we did allocate buffers, then write the count to Phantom */
if (count) {
- rcv_desc->begin_alloc = index;
- rcv_desc->rcv_pending += count;
- rcv_desc->producer = producer;
+ rds_ring->begin_alloc = index;
+ rds_ring->producer = producer;
/* Window = 1 */
- writel((producer - 1) &
- (rcv_desc->max_rx_desc_count - 1),
- NETXEN_CRB_NORMALIZE(adapter,
- recv_crb_registers[
- adapter->portnum].
- rcv_desc_crb[ringid].
- crb_rcv_producer_offset));
+ adapter->pci_write_normalize(adapter,
+ rds_ring->crb_rcv_producer,
+ (producer-1) & (rds_ring->max_rx_desc_count-1));
wmb();
}
}
diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c
deleted file mode 100644
index 96cec41f901..00000000000
--- a/drivers/net/netxen/netxen_nic_isr.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2003 - 2006 NetXen, Inc.
- * All rights reserved.
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.
- *
- * Contact Information:
- * info@netxen.com
- * NetXen,
- * 3965 Freedom Circle, Fourth floor,
- * Santa Clara, CA 95054
- */
-
-#include <linux/netdevice.h>
-#include <linux/delay.h>
-
-#include "netxen_nic.h"
-#include "netxen_nic_hw.h"
-#include "netxen_nic_phan_reg.h"
-
-/*
- * netxen_nic_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- */
-struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
-{
- struct netxen_adapter *adapter = netdev_priv(netdev);
- struct net_device_stats *stats = &adapter->net_stats;
-
- memset(stats, 0, sizeof(*stats));
-
- /* total packets received */
- stats->rx_packets = adapter->stats.no_rcv;
- /* total packets transmitted */
- stats->tx_packets = adapter->stats.xmitedframes +
- adapter->stats.xmitfinished;
- /* total bytes received */
- stats->rx_bytes = adapter->stats.rxbytes;
- /* total bytes transmitted */
- stats->tx_bytes = adapter->stats.txbytes;
- /* bad packets received */
- stats->rx_errors = adapter->stats.rcvdbadskb;
- /* packet transmit problems */
- stats->tx_errors = adapter->stats.nocmddescriptor;
- /* no space in linux buffers */
- stats->rx_dropped = adapter->stats.rxdropped;
- /* no space available in linux */
- stats->tx_dropped = adapter->stats.txdropped;
-
- return stats;
-}
-
-static void netxen_indicate_link_status(struct netxen_adapter *adapter,
- u32 link)
-{
- struct net_device *netdev = adapter->netdev;
-
- if (link)
- netif_carrier_on(netdev);
- else
- netif_carrier_off(netdev);
-}
-
-#if 0
-void netxen_handle_port_int(struct netxen_adapter *adapter, u32 enable)
-{
- __u32 int_src;
-
- /* This should clear the interrupt source */
- if (adapter->phy_read)
- adapter->phy_read(adapter,
- NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
- &int_src);
- if (int_src == 0) {
- DPRINTK(INFO, "No phy interrupts for port #%d\n", portno);
- return;
- }
- if (adapter->disable_phy_interrupts)
- adapter->disable_phy_interrupts(adapter);
-
- if (netxen_get_phy_int_jabber(int_src))
- DPRINTK(INFO, "Jabber interrupt \n");
-
- if (netxen_get_phy_int_polarity_changed(int_src))
- DPRINTK(INFO, "POLARITY CHANGED int \n");
-
- if (netxen_get_phy_int_energy_detect(int_src))
- DPRINTK(INFO, "ENERGY DETECT INT \n");
-
- if (netxen_get_phy_int_downshift(int_src))
- DPRINTK(INFO, "DOWNSHIFT INT \n");
- /* write it down later.. */
- if ((netxen_get_phy_int_speed_changed(int_src))
- || (netxen_get_phy_int_link_status_changed(int_src))) {
- __u32 status;
-
- DPRINTK(INFO, "SPEED CHANGED OR LINK STATUS CHANGED \n");
-
- if (adapter->phy_read
- && adapter->phy_read(adapter,
- NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
- &status) == 0) {
- if (netxen_get_phy_int_link_status_changed(int_src)) {
- if (netxen_get_phy_link(status)) {
- printk(KERN_INFO "%s: %s Link UP\n",
- netxen_nic_driver_name,
- adapter->netdev->name);
-
- } else {
- printk(KERN_INFO "%s: %s Link DOWN\n",
- netxen_nic_driver_name,
- adapter->netdev->name);
- }
- netxen_indicate_link_status(adapter,
- netxen_get_phy_link
- (status));
- }
- }
- }
- if (adapter->enable_phy_interrupts)
- adapter->enable_phy_interrupts(adapter);
-}
-#endif /* 0 */
-
-static void netxen_nic_isr_other(struct netxen_adapter *adapter)
-{
- int portno = adapter->portnum;
- u32 val, linkup, qg_linksup;
-
- /* verify the offset */
- val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
- val = val >> adapter->physical_port;
- if (val == adapter->ahw.qg_linksup)
- return;
-
- qg_linksup = adapter->ahw.qg_linksup;
- adapter->ahw.qg_linksup = val;
- DPRINTK(INFO, "link update 0x%08x\n", val);
-
- linkup = val & 1;
-
- if (linkup != (qg_linksup & 1)) {
- printk(KERN_INFO "%s: %s PORT %d link %s\n",
- adapter->netdev->name,
- netxen_nic_driver_name, portno,
- ((linkup == 0) ? "down" : "up"));
- netxen_indicate_link_status(adapter, linkup);
- if (linkup)
- netxen_nic_set_link_parameters(adapter);
-
- }
-}
-
-void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter)
-{
- netxen_nic_isr_other(adapter);
-}
-
-#if 0
-int netxen_nic_link_ok(struct netxen_adapter *adapter)
-{
- switch (adapter->ahw.board_type) {
- case NETXEN_NIC_GBE:
- return ((adapter->ahw.qg_linksup) & 1);
-
- case NETXEN_NIC_XGBE:
- return ((adapter->ahw.xg_linkup) & 1);
-
- default:
- printk(KERN_ERR"%s: Function: %s, Unknown board type\n",
- netxen_nic_driver_name, __FUNCTION__);
- break;
- }
-
- return 0;
-}
-#endif /* 0 */
-
-void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
-{
- struct net_device *netdev = adapter->netdev;
- u32 val;
-
- /* WINDOW = 1 */
- val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
- val >>= (adapter->physical_port * 8);
- val &= 0xff;
-
- if (adapter->ahw.xg_linkup == 1 && val != XG_LINK_UP) {
- printk(KERN_INFO "%s: %s NIC Link is down\n",
- netxen_nic_driver_name, netdev->name);
- adapter->ahw.xg_linkup = 0;
- if (netif_running(netdev)) {
- netif_carrier_off(netdev);
- netif_stop_queue(netdev);
- }
- } else if (adapter->ahw.xg_linkup == 0 && val == XG_LINK_UP) {
- printk(KERN_INFO "%s: %s NIC Link is up\n",
- netxen_nic_driver_name, netdev->name);
- adapter->ahw.xg_linkup = 1;
- netif_carrier_on(netdev);
- netif_wake_queue(netdev);
- }
-}
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 63cd67b931e..91d209a8f6c 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -49,13 +49,18 @@ char netxen_nic_driver_name[] = "netxen_nic";
static char netxen_nic_driver_string[] = "NetXen Network Driver version "
NETXEN_NIC_LINUX_VERSIONID;
-#define NETXEN_NETDEV_WEIGHT 120
-#define NETXEN_ADAPTER_UP_MAGIC 777
-#define NETXEN_NIC_PEG_TUNE 0
+static int port_mode = NETXEN_PORT_MODE_AUTO_NEG;
+
+/* Default to restricted 1G auto-neg mode */
+static int wol_port_mode = 5;
+
+static int use_msi = 1;
+
+static int use_msi_x = 1;
/* Local functions to NetXen NIC driver */
static int __devinit netxen_nic_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent);
+ const struct pci_device_id *ent);
static void __devexit netxen_nic_remove(struct pci_dev *pdev);
static int netxen_nic_open(struct net_device *netdev);
static int netxen_nic_close(struct net_device *netdev);
@@ -83,6 +88,7 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = {
ENTRY(0x0005),
ENTRY(0x0024),
ENTRY(0x0025),
+ ENTRY(0x0100),
{0,}
};
@@ -108,95 +114,61 @@ static struct workqueue_struct *netxen_workq;
static void netxen_watchdog(unsigned long);
-static void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
- uint32_t crb_producer)
+static uint32_t crb_cmd_producer[4] = {
+ CRB_CMD_PRODUCER_OFFSET, CRB_CMD_PRODUCER_OFFSET_1,
+ CRB_CMD_PRODUCER_OFFSET_2, CRB_CMD_PRODUCER_OFFSET_3
+};
+
+void
+netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
+ uint32_t crb_producer)
{
- switch (adapter->portnum) {
- case 0:
- writel(crb_producer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_PRODUCER_OFFSET));
- return;
- case 1:
- writel(crb_producer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_PRODUCER_OFFSET_1));
- return;
- case 2:
- writel(crb_producer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_PRODUCER_OFFSET_2));
- return;
- case 3:
- writel(crb_producer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_PRODUCER_OFFSET_3));
- return;
- default:
- printk(KERN_WARNING "We tried to update "
- "CRB_CMD_PRODUCER_OFFSET for invalid "
- "PCI function id %d\n",
- adapter->portnum);
- return;
- }
+ adapter->pci_write_normalize(adapter,
+ adapter->crb_addr_cmd_producer, crb_producer);
}
-static void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter,
- u32 crb_consumer)
+static uint32_t crb_cmd_consumer[4] = {
+ CRB_CMD_CONSUMER_OFFSET, CRB_CMD_CONSUMER_OFFSET_1,
+ CRB_CMD_CONSUMER_OFFSET_2, CRB_CMD_CONSUMER_OFFSET_3
+};
+
+static inline void
+netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter,
+ u32 crb_consumer)
{
- switch (adapter->portnum) {
- case 0:
- writel(crb_consumer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_CONSUMER_OFFSET));
- return;
- case 1:
- writel(crb_consumer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_CONSUMER_OFFSET_1));
- return;
- case 2:
- writel(crb_consumer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_CONSUMER_OFFSET_2));
- return;
- case 3:
- writel(crb_consumer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_CONSUMER_OFFSET_3));
- return;
- default:
- printk(KERN_WARNING "We tried to update "
- "CRB_CMD_PRODUCER_OFFSET for invalid "
- "PCI function id %d\n",
- adapter->portnum);
- return;
- }
+ adapter->pci_write_normalize(adapter,
+ adapter->crb_addr_cmd_consumer, crb_consumer);
}
-#define ADAPTER_LIST_SIZE 12
-
-static uint32_t msi_tgt_status[4] = {
+static uint32_t msi_tgt_status[8] = {
ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
- ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3
+ ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
+ ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
+ ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
};
-static uint32_t sw_int_mask[4] = {
- CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1,
- CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3
-};
+static struct netxen_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG;
static void netxen_nic_disable_int(struct netxen_adapter *adapter)
{
u32 mask = 0x7ff;
int retries = 32;
- int port = adapter->portnum;
int pci_fn = adapter->ahw.pci_func;
if (adapter->msi_mode != MSI_MODE_MULTIFUNC)
- writel(0x0, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port]));
+ adapter->pci_write_normalize(adapter,
+ adapter->crb_intr_mask, 0);
if (adapter->intr_scheme != -1 &&
adapter->intr_scheme != INTR_SCHEME_PERPORT)
- writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+ adapter->pci_write_immediate(adapter, ISR_INT_MASK, mask);
- if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ if (!NETXEN_IS_MSI_FAMILY(adapter)) {
do {
- writel(0xffffffff,
- PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_STATUS));
- mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR));
+ adapter->pci_write_immediate(adapter,
+ ISR_INT_TARGET_STATUS, 0xffffffff);
+ mask = adapter->pci_read_immediate(adapter,
+ ISR_INT_VECTOR);
if (!(mask & 0x80))
break;
udelay(10);
@@ -208,8 +180,8 @@ static void netxen_nic_disable_int(struct netxen_adapter *adapter)
}
} else {
if (adapter->msi_mode == MSI_MODE_MULTIFUNC) {
- writel(0xffffffff, PCI_OFFSET_SECOND_RANGE(adapter,
- msi_tgt_status[pci_fn]));
+ adapter->pci_write_immediate(adapter,
+ msi_tgt_status[pci_fn], 0xffffffff);
}
}
}
@@ -217,7 +189,6 @@ static void netxen_nic_disable_int(struct netxen_adapter *adapter)
static void netxen_nic_enable_int(struct netxen_adapter *adapter)
{
u32 mask;
- int port = adapter->portnum;
DPRINTK(1, INFO, "Entered ISR Enable \n");
@@ -235,24 +206,299 @@ static void netxen_nic_enable_int(struct netxen_adapter *adapter)
break;
}
- writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+ adapter->pci_write_immediate(adapter, ISR_INT_MASK, mask);
}
- writel(0x1, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port]));
+ adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0x1);
- if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ if (!NETXEN_IS_MSI_FAMILY(adapter)) {
mask = 0xbff;
if (adapter->intr_scheme != -1 &&
adapter->intr_scheme != INTR_SCHEME_PERPORT) {
- writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+ adapter->pci_write_normalize(adapter,
+ CRB_INT_VECTOR, 0);
}
- writel(mask,
- PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_MASK));
+ adapter->pci_write_immediate(adapter,
+ ISR_INT_TARGET_MASK, mask);
}
DPRINTK(1, INFO, "Done with enable Int\n");
}
+static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ int err;
+ uint64_t mask;
+
+#ifdef CONFIG_IA64
+ adapter->dma_mask = DMA_32BIT_MASK;
+#else
+ if (revision_id >= NX_P3_B0) {
+ /* should go to DMA_64BIT_MASK */
+ adapter->dma_mask = DMA_39BIT_MASK;
+ mask = DMA_39BIT_MASK;
+ } else if (revision_id == NX_P3_A2) {
+ adapter->dma_mask = DMA_39BIT_MASK;
+ mask = DMA_39BIT_MASK;
+ } else if (revision_id == NX_P2_C1) {
+ adapter->dma_mask = DMA_35BIT_MASK;
+ mask = DMA_35BIT_MASK;
+ } else {
+ adapter->dma_mask = DMA_32BIT_MASK;
+ mask = DMA_32BIT_MASK;
+ goto set_32_bit_mask;
+ }
+
+ /*
+ * Consistent DMA mask is set to 32 bit because it cannot be set to
+ * 35 bits. For P3 also leave it at 32 bits for now. Only the rings
+ * come off this pool.
+ */
+ if (pci_set_dma_mask(pdev, mask) == 0 &&
+ pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) == 0) {
+ adapter->pci_using_dac = 1;
+ return 0;
+ }
+#endif /* CONFIG_IA64 */
+
+set_32_bit_mask:
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (!err)
+ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ DPRINTK(ERR, "No usable DMA configuration, aborting:%d\n", err);
+ return err;
+ }
+
+ adapter->pci_using_dac = 0;
+ return 0;
+}
+
+static void netxen_check_options(struct netxen_adapter *adapter)
+{
+ switch (adapter->ahw.boardcfg.board_type) {
+ case NETXEN_BRDTYPE_P3_HMEZ:
+ case NETXEN_BRDTYPE_P3_XG_LOM:
+ case NETXEN_BRDTYPE_P3_10G_CX4:
+ case NETXEN_BRDTYPE_P3_10G_CX4_LP:
+ case NETXEN_BRDTYPE_P3_IMEZ:
+ case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
+ case NETXEN_BRDTYPE_P3_10G_XFP:
+ case NETXEN_BRDTYPE_P3_10000_BASE_T:
+ adapter->msix_supported = !!use_msi_x;
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
+ break;
+
+ case NETXEN_BRDTYPE_P2_SB31_10G:
+ case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+ case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
+ case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
+ adapter->msix_supported = 0;
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
+ break;
+
+ case NETXEN_BRDTYPE_P3_REF_QG:
+ case NETXEN_BRDTYPE_P3_4_GB:
+ case NETXEN_BRDTYPE_P3_4_GB_MM:
+ case NETXEN_BRDTYPE_P2_SB35_4G:
+ case NETXEN_BRDTYPE_P2_SB31_2G:
+ adapter->msix_supported = 0;
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
+ break;
+
+ default:
+ adapter->msix_supported = 0;
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
+
+ printk(KERN_WARNING "Unknown board type(0x%x)\n",
+ adapter->ahw.boardcfg.board_type);
+ break;
+ }
+
+ adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS_HOST;
+ adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS;
+ adapter->max_lro_rx_desc_count = MAX_LRO_RCV_DESCRIPTORS;
+
+ adapter->max_possible_rss_rings = 1;
+ return;
+}
+
+static int
+netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot)
+{
+ int ret = 0;
+
+ if (first_boot == 0x55555555) {
+ /* This is the first boot after power up */
+
+ /* PCI bus master workaround */
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(0x4), &first_boot, 4);
+ if (!(first_boot & 0x4)) {
+ first_boot |= 0x4;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PCIE_REG(0x4), &first_boot, 4);
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(0x4), &first_boot, 4);
+ }
+
+ /* This is the first boot after power up */
+ adapter->hw_read_wx(adapter,
+ NETXEN_ROMUSB_GLB_SW_RESET, &first_boot, 4);
+ if (first_boot != 0x80000f) {
+ /* clear the register for future unloads/loads */
+ adapter->pci_write_normalize(adapter,
+ NETXEN_CAM_RAM(0x1fc), 0);
+ ret = -1;
+ }
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ /* Start P2 boot loader */
+ adapter->pci_write_normalize(adapter,
+ NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1);
+ }
+ }
+ return ret;
+}
+
+static void netxen_set_port_mode(struct netxen_adapter *adapter)
+{
+ u32 val, data;
+
+ val = adapter->ahw.boardcfg.board_type;
+ if ((val == NETXEN_BRDTYPE_P3_HMEZ) ||
+ (val == NETXEN_BRDTYPE_P3_XG_LOM)) {
+ if (port_mode == NETXEN_PORT_MODE_802_3_AP) {
+ data = NETXEN_PORT_MODE_802_3_AP;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PORT_MODE_ADDR, &data, 4);
+ } else if (port_mode == NETXEN_PORT_MODE_XG) {
+ data = NETXEN_PORT_MODE_XG;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PORT_MODE_ADDR, &data, 4);
+ } else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_1G) {
+ data = NETXEN_PORT_MODE_AUTO_NEG_1G;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PORT_MODE_ADDR, &data, 4);
+ } else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_XG) {
+ data = NETXEN_PORT_MODE_AUTO_NEG_XG;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PORT_MODE_ADDR, &data, 4);
+ } else {
+ data = NETXEN_PORT_MODE_AUTO_NEG;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PORT_MODE_ADDR, &data, 4);
+ }
+
+ if ((wol_port_mode != NETXEN_PORT_MODE_802_3_AP) &&
+ (wol_port_mode != NETXEN_PORT_MODE_XG) &&
+ (wol_port_mode != NETXEN_PORT_MODE_AUTO_NEG_1G) &&
+ (wol_port_mode != NETXEN_PORT_MODE_AUTO_NEG_XG)) {
+ wol_port_mode = NETXEN_PORT_MODE_AUTO_NEG;
+ }
+ adapter->hw_write_wx(adapter, NETXEN_WOL_PORT_MODE,
+ &wol_port_mode, 4);
+ }
+}
+
+#define PCI_CAP_ID_GEN 0x10
+
+static void netxen_pcie_strap_init(struct netxen_adapter *adapter)
+{
+ u32 pdevfuncsave;
+ u32 c8c9value = 0;
+ u32 chicken = 0;
+ u32 control = 0;
+ int i, pos;
+ struct pci_dev *pdev;
+
+ pdev = pci_get_device(0x1166, 0x0140, NULL);
+ if (pdev) {
+ pci_dev_put(pdev);
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_TGT_SPLIT_CHICKEN), &chicken, 4);
+ chicken |= 0x4000;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_TGT_SPLIT_CHICKEN), &chicken, 4);
+ }
+
+ pdev = adapter->pdev;
+
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_CHICKEN3), &chicken, 4);
+ /* clear chicken3.25:24 */
+ chicken &= 0xFCFFFFFF;
+ /*
+ * if gen1 and B0, set F1020 - if gen 2, do nothing
+ * if gen2 set to F1000
+ */
+ pos = pci_find_capability(pdev, PCI_CAP_ID_GEN);
+ if (pos == 0xC0) {
+ pci_read_config_dword(pdev, pos + 0x10, &control);
+ if ((control & 0x000F0000) != 0x00020000) {
+ /* set chicken3.24 if gen1 */
+ chicken |= 0x01000000;
+ }
+ printk(KERN_INFO "%s Gen2 strapping detected\n",
+ netxen_nic_driver_name);
+ c8c9value = 0xF1000;
+ } else {
+ /* set chicken3.24 if gen1 */
+ chicken |= 0x01000000;
+ printk(KERN_INFO "%s Gen1 strapping detected\n",
+ netxen_nic_driver_name);
+ if (adapter->ahw.revision_id == NX_P3_B0)
+ c8c9value = 0xF1020;
+ else
+ c8c9value = 0;
+
+ }
+ adapter->hw_write_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_CHICKEN3), &chicken, 4);
+
+ if (!c8c9value)
+ return;
+
+ pdevfuncsave = pdev->devfn;
+ if (pdevfuncsave & 0x07)
+ return;
+
+ for (i = 0; i < 8; i++) {
+ pci_read_config_dword(pdev, pos + 8, &control);
+ pci_read_config_dword(pdev, pos + 8, &control);
+ pci_write_config_dword(pdev, pos + 8, c8c9value);
+ pdev->devfn++;
+ }
+ pdev->devfn = pdevfuncsave;
+}
+
+static void netxen_set_msix_bit(struct pci_dev *pdev, int enable)
+{
+ u32 control;
+ int pos;
+
+ pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
+ if (pos) {
+ pci_read_config_dword(pdev, pos, &control);
+ if (enable)
+ control |= PCI_MSIX_FLAGS_ENABLE;
+ else
+ control = 0;
+ pci_write_config_dword(pdev, pos, control);
+ }
+}
+
+static void netxen_init_msix_entries(struct netxen_adapter *adapter)
+{
+ int i;
+
+ for (i = 0; i < MSIX_ENTRIES_PER_ADAPTER; i++)
+ adapter->msix_entries[i].entry = i;
+}
+
/*
* netxen_nic_probe()
*
@@ -278,28 +524,28 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
u8 __iomem *db_ptr = NULL;
- unsigned long mem_base, mem_len, db_base, db_len;
- int pci_using_dac, i = 0, err;
- int ring;
- struct netxen_recv_context *recv_ctx = NULL;
- struct netxen_rcv_desc_ctx *rcv_desc = NULL;
- struct netxen_cmd_buffer *cmd_buf_arr = NULL;
+ unsigned long mem_base, mem_len, db_base, db_len, pci_len0 = 0;
+ int i = 0, err;
+ int first_driver, first_boot;
__le64 mac_addr[FLASH_NUM_PORTS + 1];
- int valid_mac = 0;
u32 val;
int pci_func_id = PCI_FUNC(pdev->devfn);
DECLARE_MAC_BUF(mac);
+ struct netxen_legacy_intr_set *legacy_intrp;
+ uint8_t revision_id;
if (pci_func_id == 0)
- printk(KERN_INFO "%s \n", netxen_nic_driver_string);
+ printk(KERN_INFO "%s\n", netxen_nic_driver_string);
if (pdev->class != 0x020000) {
printk(KERN_DEBUG "NetXen function %d, class %x will not "
"be enabled.\n",pci_func_id, pdev->class);
return -ENODEV;
}
+
if ((err = pci_enable_device(pdev)))
return err;
+
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
err = -ENODEV;
goto err_out_disable_pdev;
@@ -309,18 +555,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_disable_pdev;
pci_set_master(pdev);
- if (pdev->revision == NX_P2_C1 &&
- (pci_set_dma_mask(pdev, DMA_35BIT_MASK) == 0) &&
- (pci_set_consistent_dma_mask(pdev, DMA_35BIT_MASK) == 0)) {
- pci_using_dac = 1;
- } else {
- if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ||
- (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)))
- goto err_out_free_res;
-
- pci_using_dac = 0;
- }
-
netdev = alloc_etherdev(sizeof(struct netxen_adapter));
if(!netdev) {
@@ -333,13 +567,35 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
SET_NETDEV_DEV(netdev, &pdev->dev);
adapter = netdev->priv;
-
- adapter->ahw.pdev = pdev;
+ adapter->netdev = netdev;
+ adapter->pdev = pdev;
adapter->ahw.pci_func = pci_func_id;
+ revision_id = pdev->revision;
+ adapter->ahw.revision_id = revision_id;
+
+ err = nx_set_dma_mask(adapter, revision_id);
+ if (err)
+ goto err_out_free_netdev;
+
+ rwlock_init(&adapter->adapter_lock);
+ adapter->ahw.qdr_sn_window = -1;
+ adapter->ahw.ddr_mn_window = -1;
+
/* remap phys address */
mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */
mem_len = pci_resource_len(pdev, 0);
+ pci_len0 = 0;
+
+ adapter->hw_write_wx = netxen_nic_hw_write_wx_128M;
+ adapter->hw_read_wx = netxen_nic_hw_read_wx_128M;
+ adapter->pci_read_immediate = netxen_nic_pci_read_immediate_128M;
+ adapter->pci_write_immediate = netxen_nic_pci_write_immediate_128M;
+ adapter->pci_read_normalize = netxen_nic_pci_read_normalize_128M;
+ adapter->pci_write_normalize = netxen_nic_pci_write_normalize_128M;
+ adapter->pci_set_window = netxen_nic_pci_set_window_128M;
+ adapter->pci_mem_read = netxen_nic_pci_mem_read_128M;
+ adapter->pci_mem_write = netxen_nic_pci_mem_write_128M;
/* 128 Meg of memory */
if (mem_len == NETXEN_PCI_128MB_SIZE) {
@@ -356,27 +612,48 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
SECOND_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE);
first_page_group_start = 0;
first_page_group_end = 0;
+ } else if (mem_len == NETXEN_PCI_2MB_SIZE) {
+ adapter->hw_write_wx = netxen_nic_hw_write_wx_2M;
+ adapter->hw_read_wx = netxen_nic_hw_read_wx_2M;
+ adapter->pci_read_immediate = netxen_nic_pci_read_immediate_2M;
+ adapter->pci_write_immediate =
+ netxen_nic_pci_write_immediate_2M;
+ adapter->pci_read_normalize = netxen_nic_pci_read_normalize_2M;
+ adapter->pci_write_normalize =
+ netxen_nic_pci_write_normalize_2M;
+ adapter->pci_set_window = netxen_nic_pci_set_window_2M;
+ adapter->pci_mem_read = netxen_nic_pci_mem_read_2M;
+ adapter->pci_mem_write = netxen_nic_pci_mem_write_2M;
+
+ mem_ptr0 = ioremap(mem_base, mem_len);
+ pci_len0 = mem_len;
+ first_page_group_start = 0;
+ first_page_group_end = 0;
+
+ adapter->ahw.ddr_mn_window = 0;
+ adapter->ahw.qdr_sn_window = 0;
+
+ adapter->ahw.mn_win_crb = 0x100000 + PCIX_MN_WINDOW +
+ (pci_func_id * 0x20);
+ adapter->ahw.ms_win_crb = 0x100000 + PCIX_SN_WINDOW;
+ if (pci_func_id < 4)
+ adapter->ahw.ms_win_crb += (pci_func_id * 0x20);
+ else
+ adapter->ahw.ms_win_crb +=
+ 0xA0 + ((pci_func_id - 4) * 0x10);
} else {
err = -EIO;
goto err_out_free_netdev;
}
- if ((!mem_ptr0 && mem_len == NETXEN_PCI_128MB_SIZE) ||
- !mem_ptr1 || !mem_ptr2) {
- DPRINTK(ERR,
- "Cannot remap adapter memory aborting.:"
- "0 -> %p, 1 -> %p, 2 -> %p\n",
- mem_ptr0, mem_ptr1, mem_ptr2);
+ dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20));
- err = -EIO;
- goto err_out_iounmap;
- }
db_base = pci_resource_start(pdev, 4); /* doorbell is on bar 4 */
db_len = pci_resource_len(pdev, 4);
if (db_len == 0) {
printk(KERN_ERR "%s: doorbell is disabled\n",
- netxen_nic_driver_name);
+ netxen_nic_driver_name);
err = -EIO;
goto err_out_iounmap;
}
@@ -386,13 +663,14 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
db_ptr = ioremap(db_base, NETXEN_DB_MAPSIZE_BYTES);
if (!db_ptr) {
printk(KERN_ERR "%s: Failed to allocate doorbell map.",
- netxen_nic_driver_name);
+ netxen_nic_driver_name);
err = -EIO;
goto err_out_iounmap;
}
DPRINTK(INFO, "doorbell ioremaped at %p\n", db_ptr);
adapter->ahw.pci_base0 = mem_ptr0;
+ adapter->ahw.pci_len0 = pci_len0;
adapter->ahw.first_page_group_start = first_page_group_start;
adapter->ahw.first_page_group_end = first_page_group_end;
adapter->ahw.pci_base1 = mem_ptr1;
@@ -400,11 +678,18 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->ahw.db_base = db_ptr;
adapter->ahw.db_len = db_len;
- adapter->netdev = netdev;
- adapter->pdev = pdev;
-
netif_napi_add(netdev, &adapter->napi,
- netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
+ netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
+
+ if (revision_id >= NX_P3_B0)
+ legacy_intrp = &legacy_intr[pci_func_id];
+ else
+ legacy_intrp = &legacy_intr[0];
+
+ adapter->legacy_intr.int_vec_bit = legacy_intrp->int_vec_bit;
+ adapter->legacy_intr.tgt_status_reg = legacy_intrp->tgt_status_reg;
+ adapter->legacy_intr.tgt_mask_reg = legacy_intrp->tgt_mask_reg;
+ adapter->legacy_intr.pci_int_reg = legacy_intrp->pci_int_reg;
/* this will be read from FW later */
adapter->intr_scheme = -1;
@@ -414,12 +699,23 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->portnum = pci_func_id;
adapter->status &= ~NETXEN_NETDEV_STATUS;
adapter->rx_csum = 1;
+ adapter->mc_enabled = 0;
+ if (NX_IS_REVISION_P3(revision_id)) {
+ adapter->max_mc_count = 38;
+ adapter->max_rds_rings = 2;
+ } else {
+ adapter->max_mc_count = 16;
+ adapter->max_rds_rings = 3;
+ }
netdev->open = netxen_nic_open;
netdev->stop = netxen_nic_close;
netdev->hard_start_xmit = netxen_nic_xmit_frame;
netdev->get_stats = netxen_nic_get_stats;
- netdev->set_multicast_list = netxen_nic_set_multi;
+ if (NX_IS_REVISION_P3(revision_id))
+ netdev->set_multicast_list = netxen_p3_nic_set_multi;
+ else
+ netdev->set_multicast_list = netxen_p2_nic_set_multi;
netdev->set_mac_address = netxen_nic_set_mac;
netdev->change_mtu = netxen_nic_change_mtu;
netdev->tx_timeout = netxen_tx_timeout;
@@ -435,18 +731,14 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->features = NETIF_F_SG;
netdev->features |= NETIF_F_IP_CSUM;
netdev->features |= NETIF_F_TSO;
+ if (NX_IS_REVISION_P3(revision_id)) {
+ netdev->features |= NETIF_F_IPV6_CSUM;
+ netdev->features |= NETIF_F_TSO6;
+ }
- if (pci_using_dac)
+ if (adapter->pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
- if (pci_enable_msi(pdev))
- adapter->flags &= ~NETXEN_NIC_MSI_ENABLED;
- else
- adapter->flags |= NETXEN_NIC_MSI_ENABLED;
-
- netdev->irq = pdev->irq;
- INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task);
-
/*
* Set the CRB window to invalid. If any register in window 0 is
* accessed it should set the window to 0 and then reset it to 1.
@@ -455,87 +747,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (netxen_nic_get_board_info(adapter) != 0) {
printk("%s: Error getting board config info.\n",
- netxen_nic_driver_name);
+ netxen_nic_driver_name);
err = -EIO;
goto err_out_iounmap;
}
- /*
- * Adapter in our case is quad port so initialize it before
- * initializing the ports
- */
-
netxen_initialize_adapter_ops(adapter);
- adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS_HOST;
- if ((adapter->ahw.boardcfg.board_type == NETXEN_BRDTYPE_P2_SB35_4G) ||
- (adapter->ahw.boardcfg.board_type ==
- NETXEN_BRDTYPE_P2_SB31_2G))
- adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
- else
- adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS;
- adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS;
- adapter->max_lro_rx_desc_count = MAX_LRO_RCV_DESCRIPTORS;
-
- cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE);
- if (cmd_buf_arr == NULL) {
- printk(KERN_ERR
- "%s: Could not allocate cmd_buf_arr memory:%d\n",
- netxen_nic_driver_name, (int)TX_RINGSIZE);
- err = -ENOMEM;
- goto err_out_free_adapter;
- }
- memset(cmd_buf_arr, 0, TX_RINGSIZE);
- adapter->cmd_buf_arr = cmd_buf_arr;
-
- for (i = 0; i < MAX_RCV_CTX; ++i) {
- recv_ctx = &adapter->recv_ctx[i];
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- rcv_desc = &recv_ctx->rcv_desc[ring];
- switch (RCV_DESC_TYPE(ring)) {
- case RCV_DESC_NORMAL:
- rcv_desc->max_rx_desc_count =
- adapter->max_rx_desc_count;
- rcv_desc->flags = RCV_DESC_NORMAL;
- rcv_desc->dma_size = RX_DMA_MAP_LEN;
- rcv_desc->skb_size = MAX_RX_BUFFER_LENGTH;
- break;
-
- case RCV_DESC_JUMBO:
- rcv_desc->max_rx_desc_count =
- adapter->max_jumbo_rx_desc_count;
- rcv_desc->flags = RCV_DESC_JUMBO;
- rcv_desc->dma_size = RX_JUMBO_DMA_MAP_LEN;
- rcv_desc->skb_size = MAX_RX_JUMBO_BUFFER_LENGTH;
- break;
-
- case RCV_RING_LRO:
- rcv_desc->max_rx_desc_count =
- adapter->max_lro_rx_desc_count;
- rcv_desc->flags = RCV_DESC_LRO;
- rcv_desc->dma_size = RX_LRO_DMA_MAP_LEN;
- rcv_desc->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
- break;
-
- }
- rcv_desc->rx_buf_arr = (struct netxen_rx_buffer *)
- vmalloc(RCV_BUFFSIZE);
-
- if (rcv_desc->rx_buf_arr == NULL) {
- printk(KERN_ERR "%s: Could not allocate "
- "rcv_desc->rx_buf_arr memory:%d\n",
- netxen_nic_driver_name,
- (int)RCV_BUFFSIZE);
- err = -ENOMEM;
- goto err_out_free_rx_buffer;
- }
- memset(rcv_desc->rx_buf_arr, 0, RCV_BUFFSIZE);
- }
-
- }
-
- netxen_initialize_adapter_sw(adapter); /* initialize the buffers in adapter */
-
/* Mezz cards have PCI function 0,2,3 enabled */
switch (adapter->ahw.boardcfg.board_type) {
case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
@@ -547,90 +765,71 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
break;
}
- init_timer(&adapter->watchdog_timer);
- adapter->ahw.xg_linkup = 0;
- adapter->watchdog_timer.function = &netxen_watchdog;
- adapter->watchdog_timer.data = (unsigned long)adapter;
- INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
- adapter->ahw.pdev = pdev;
- adapter->ahw.revision_id = pdev->revision;
-
- /* make sure Window == 1 */
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ /*
+ * This call will setup various max rx/tx counts.
+ * It must be done before any buffer/ring allocations.
+ */
+ netxen_check_options(adapter);
+ first_driver = 0;
+ if (NX_IS_REVISION_P3(revision_id)) {
+ if (adapter->ahw.pci_func == 0)
+ first_driver = 1;
+ } else {
+ if (adapter->portnum == 0)
+ first_driver = 1;
+ }
+ adapter->crb_addr_cmd_producer = crb_cmd_producer[adapter->portnum];
+ adapter->crb_addr_cmd_consumer = crb_cmd_consumer[adapter->portnum];
netxen_nic_update_cmd_producer(adapter, 0);
netxen_nic_update_cmd_consumer(adapter, 0);
- writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO));
- if (netxen_is_flash_supported(adapter) == 0 &&
- netxen_get_flash_mac_addr(adapter, mac_addr) == 0)
- valid_mac = 1;
- else
- valid_mac = 0;
-
- if (valid_mac) {
- unsigned char *p = (unsigned char *)&mac_addr[adapter->portnum];
- netdev->dev_addr[0] = *(p + 5);
- netdev->dev_addr[1] = *(p + 4);
- netdev->dev_addr[2] = *(p + 3);
- netdev->dev_addr[3] = *(p + 2);
- netdev->dev_addr[4] = *(p + 1);
- netdev->dev_addr[5] = *(p + 0);
+ if (first_driver) {
+ first_boot = adapter->pci_read_normalize(adapter,
+ NETXEN_CAM_RAM(0x1fc));
- memcpy(netdev->perm_addr, netdev->dev_addr,
- netdev->addr_len);
- if (!is_valid_ether_addr(netdev->perm_addr)) {
- printk(KERN_ERR "%s: Bad MAC address %s.\n",
- netxen_nic_driver_name,
- print_mac(mac, netdev->dev_addr));
- } else {
- if (adapter->macaddr_set)
- adapter->macaddr_set(adapter,
- netdev->dev_addr);
+ err = netxen_check_hw_init(adapter, first_boot);
+ if (err) {
+ printk(KERN_ERR "%s: error in init HW init sequence\n",
+ netxen_nic_driver_name);
+ goto err_out_iounmap;
}
- }
- if (adapter->portnum == 0) {
- err = netxen_initialize_adapter_offload(adapter);
- if (err)
- goto err_out_free_rx_buffer;
- val = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_CAM_RAM(0x1fc)));
- if (val == 0x55555555) {
- /* This is the first boot after power up */
- netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val);
- if (!(val & 0x4)) {
- val |= 0x4;
- netxen_nic_write_w0(adapter, NETXEN_PCIE_REG(0x4), val);
- netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val);
- if (!(val & 0x4))
- printk(KERN_ERR "%s: failed to set MSI bit in PCI-e reg\n",
- netxen_nic_driver_name);
- }
- val = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_ROMUSB_GLB_SW_RESET));
- printk(KERN_INFO"NetXen: read 0x%08x for reset reg.\n",val);
- if (val != 0x80000f) {
- /* clear the register for future unloads/loads */
- writel(0, NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_CAM_RAM(0x1fc)));
- printk(KERN_ERR "ERROR in NetXen HW init sequence.\n");
- err = -ENODEV;
- goto err_out_free_dev;
- }
- } else {
- writel(0, NETXEN_CRB_NORMALIZE(adapter,
- CRB_CMDPEG_STATE));
+ if (NX_IS_REVISION_P3(revision_id))
+ netxen_set_port_mode(adapter);
+
+ if (first_boot != 0x55555555) {
+ adapter->pci_write_normalize(adapter,
+ CRB_CMDPEG_STATE, 0);
netxen_pinit_from_rom(adapter, 0);
msleep(1);
netxen_load_firmware(adapter);
- netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
}
- /* clear the register for future unloads/loads */
- writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc)));
- dev_info(&pdev->dev, "cmdpeg state: 0x%0x\n",
- readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)));
+ if (NX_IS_REVISION_P3(revision_id))
+ netxen_pcie_strap_init(adapter);
+
+ if (NX_IS_REVISION_P2(revision_id)) {
+
+ /* Initialize multicast addr pool owners */
+ val = 0x7654;
+ if (adapter->ahw.board_type == NETXEN_NIC_XGBE)
+ val |= 0x0f000000;
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_MAC_ADDR_CNTL_REG, val);
+
+ }
+
+ if ((first_boot == 0x55555555) &&
+ (NX_IS_REVISION_P2(revision_id))) {
+ /* Unlock the HW, prompting the boot sequence */
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1);
+ }
+
+ err = netxen_initialize_adapter_offload(adapter);
+ if (err)
+ goto err_out_iounmap;
/*
* Tell the hardware our version number.
@@ -638,24 +837,101 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
i = (_NETXEN_NIC_LINUX_MAJOR << 16)
| ((_NETXEN_NIC_LINUX_MINOR << 8))
| (_NETXEN_NIC_LINUX_SUBVERSION);
- writel(i, NETXEN_CRB_NORMALIZE(adapter, CRB_DRIVER_VERSION));
+ adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, i);
- /* Unlock the HW, prompting the boot sequence */
- writel(1,
- NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
/* Handshake with the card before we register the devices. */
netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+
+ } /* first_driver */
+
+ netxen_nic_flash_print(adapter);
+
+ if (NX_IS_REVISION_P3(revision_id)) {
+ adapter->hw_read_wx(adapter,
+ NETXEN_MIU_MN_CONTROL, &val, 4);
+ adapter->ahw.cut_through = (val & 0x4) ? 1 : 0;
+ dev_info(&pdev->dev, "firmware running in %s mode\n",
+ adapter->ahw.cut_through ? "cut through" : "legacy");
}
/*
* See if the firmware gave us a virtual-physical port mapping.
*/
adapter->physical_port = adapter->portnum;
- i = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_V2P(adapter->portnum)));
+ i = adapter->pci_read_normalize(adapter, CRB_V2P(adapter->portnum));
if (i != 0x55555555)
adapter->physical_port = i;
+ adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED);
+
+ netxen_set_msix_bit(pdev, 0);
+
+ if (NX_IS_REVISION_P3(revision_id)) {
+ if ((mem_len != NETXEN_PCI_128MB_SIZE) &&
+ mem_len != NETXEN_PCI_2MB_SIZE)
+ adapter->msix_supported = 0;
+ }
+
+ if (adapter->msix_supported) {
+
+ netxen_init_msix_entries(adapter);
+
+ if (pci_enable_msix(pdev, adapter->msix_entries,
+ MSIX_ENTRIES_PER_ADAPTER))
+ goto request_msi;
+
+ adapter->flags |= NETXEN_NIC_MSIX_ENABLED;
+ netxen_set_msix_bit(pdev, 1);
+ dev_info(&pdev->dev, "using msi-x interrupts\n");
+
+ } else {
+request_msi:
+ if (use_msi && !pci_enable_msi(pdev)) {
+ adapter->flags |= NETXEN_NIC_MSI_ENABLED;
+ dev_info(&pdev->dev, "using msi interrupts\n");
+ } else
+ dev_info(&pdev->dev, "using legacy interrupts\n");
+ }
+
+ if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+ netdev->irq = adapter->msix_entries[0].vector;
+ else
+ netdev->irq = pdev->irq;
+
+ err = netxen_receive_peg_ready(adapter);
+ if (err)
+ goto err_out_disable_msi;
+
+ init_timer(&adapter->watchdog_timer);
+ adapter->ahw.linkup = 0;
+ adapter->watchdog_timer.function = &netxen_watchdog;
+ adapter->watchdog_timer.data = (unsigned long)adapter;
+ INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
+ INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task);
+
+ if (netxen_is_flash_supported(adapter) == 0 &&
+ netxen_get_flash_mac_addr(adapter, mac_addr) == 0) {
+ unsigned char *p;
+
+ p = (unsigned char *)&mac_addr[adapter->portnum];
+ netdev->dev_addr[0] = *(p + 5);
+ netdev->dev_addr[1] = *(p + 4);
+ netdev->dev_addr[2] = *(p + 3);
+ netdev->dev_addr[3] = *(p + 2);
+ netdev->dev_addr[4] = *(p + 1);
+ netdev->dev_addr[5] = *(p + 0);
+
+ memcpy(netdev->perm_addr, netdev->dev_addr,
+ netdev->addr_len);
+ if (!is_valid_ether_addr(netdev->perm_addr)) {
+ printk(KERN_ERR "%s: Bad MAC address %s.\n",
+ netxen_nic_driver_name,
+ print_mac(mac, netdev->dev_addr));
+ } else {
+ adapter->macaddr_set(adapter, netdev->dev_addr);
+ }
+ }
+
netif_carrier_off(netdev);
netif_stop_queue(netdev);
@@ -664,41 +940,37 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
" aborting\n", netxen_nic_driver_name,
adapter->portnum);
err = -EIO;
- goto err_out_free_dev;
+ goto err_out_disable_msi;
}
- netxen_nic_flash_print(adapter);
pci_set_drvdata(pdev, adapter);
- return 0;
-
-err_out_free_dev:
- if (adapter->portnum == 0)
- netxen_free_adapter_offload(adapter);
-
-err_out_free_rx_buffer:
- for (i = 0; i < MAX_RCV_CTX; ++i) {
- recv_ctx = &adapter->recv_ctx[i];
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- rcv_desc = &recv_ctx->rcv_desc[ring];
- if (rcv_desc->rx_buf_arr != NULL) {
- vfree(rcv_desc->rx_buf_arr);
- rcv_desc->rx_buf_arr = NULL;
- }
- }
+ switch (adapter->ahw.board_type) {
+ case NETXEN_NIC_GBE:
+ dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n",
+ adapter->netdev->name);
+ break;
+ case NETXEN_NIC_XGBE:
+ dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n",
+ adapter->netdev->name);
+ break;
}
- vfree(cmd_buf_arr);
-err_out_free_adapter:
+ return 0;
+
+err_out_disable_msi:
+ if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+ pci_disable_msix(pdev);
if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
pci_disable_msi(pdev);
- pci_set_drvdata(pdev, NULL);
+ if (first_driver)
+ netxen_free_adapter_offload(adapter);
+err_out_iounmap:
if (db_ptr)
iounmap(db_ptr);
-err_out_iounmap:
if (mem_ptr0)
iounmap(mem_ptr0);
if (mem_ptr1)
@@ -713,6 +985,7 @@ err_out_free_res:
pci_release_regions(pdev);
err_out_disable_pdev:
+ pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
return err;
}
@@ -721,11 +994,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
{
struct netxen_adapter *adapter;
struct net_device *netdev;
- struct netxen_rx_buffer *buffer;
- struct netxen_recv_context *recv_ctx;
- struct netxen_rcv_desc_ctx *rcv_desc;
- int i, ctxid, ring;
- static int init_firmware_done = 0;
adapter = pci_get_drvdata(pdev);
if (adapter == NULL)
@@ -736,36 +1004,18 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
unregister_netdev(netdev);
if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
- init_firmware_done++;
netxen_free_hw_resources(adapter);
+ netxen_free_sw_resources(adapter);
}
- for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
- recv_ctx = &adapter->recv_ctx[ctxid];
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- rcv_desc = &recv_ctx->rcv_desc[ring];
- for (i = 0; i < rcv_desc->max_rx_desc_count; ++i) {
- buffer = &(rcv_desc->rx_buf_arr[i]);
- if (buffer->state == NETXEN_BUFFER_FREE)
- continue;
- pci_unmap_single(pdev, buffer->dma,
- rcv_desc->dma_size,
- PCI_DMA_FROMDEVICE);
- if (buffer->skb != NULL)
- dev_kfree_skb_any(buffer->skb);
- }
- vfree(rcv_desc->rx_buf_arr);
- }
- }
-
- vfree(adapter->cmd_buf_arr);
-
if (adapter->portnum == 0)
netxen_free_adapter_offload(adapter);
if (adapter->irq)
free_irq(adapter->irq, adapter);
+ if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+ pci_disable_msix(pdev);
if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
pci_disable_msi(pdev);
@@ -803,51 +1053,69 @@ static int netxen_nic_open(struct net_device *netdev)
return -EIO;
}
- /* setup all the resources for the Phantom... */
- /* this include the descriptors for rcv, tx, and status */
- netxen_nic_clear_stats(adapter);
- err = netxen_nic_hw_resources(adapter);
+ err = netxen_alloc_sw_resources(adapter);
if (err) {
- printk(KERN_ERR "Error in setting hw resources:%d\n",
- err);
+ printk(KERN_ERR "%s: Error in setting sw resources\n",
+ netdev->name);
return err;
}
+
+ netxen_nic_clear_stats(adapter);
+
+ err = netxen_alloc_hw_resources(adapter);
+ if (err) {
+ printk(KERN_ERR "%s: Error in setting hw resources\n",
+ netdev->name);
+ goto err_out_free_sw;
+ }
+
+ if (adapter->fw_major < 4) {
+ adapter->crb_addr_cmd_producer =
+ crb_cmd_producer[adapter->portnum];
+ adapter->crb_addr_cmd_consumer =
+ crb_cmd_consumer[adapter->portnum];
+ }
+
+ netxen_nic_update_cmd_producer(adapter, 0);
+ netxen_nic_update_cmd_consumer(adapter, 0);
+
for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++)
+ for (ring = 0; ring < adapter->max_rds_rings; ring++)
netxen_post_rx_buffers(adapter, ctx, ring);
}
- adapter->irq = adapter->ahw.pdev->irq;
- if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
+ if (NETXEN_IS_MSI_FAMILY(adapter))
handler = netxen_msi_intr;
else {
flags |= IRQF_SHARED;
handler = netxen_intr;
}
+ adapter->irq = netdev->irq;
err = request_irq(adapter->irq, handler,
flags, netdev->name, adapter);
if (err) {
printk(KERN_ERR "request_irq failed with: %d\n", err);
- netxen_free_hw_resources(adapter);
- return err;
+ goto err_out_free_hw;
}
adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
}
+
/* Done here again so that even if phantom sw overwrote it,
* we set it */
- if (adapter->init_port
- && adapter->init_port(adapter, adapter->portnum) != 0) {
+ err = adapter->init_port(adapter, adapter->physical_port);
+ if (err) {
printk(KERN_ERR "%s: Failed to initialize port %d\n",
netxen_nic_driver_name, adapter->portnum);
- return -EIO;
+ goto err_out_free_irq;
}
- if (adapter->macaddr_set)
- adapter->macaddr_set(adapter, netdev->dev_addr);
+ adapter->macaddr_set(adapter, netdev->dev_addr);
netxen_nic_set_link_parameters(adapter);
- netxen_nic_set_multi(netdev);
- if (adapter->set_mtu)
+ netdev->set_multicast_list(netdev);
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ nx_fw_cmd_set_mtu(adapter, netdev->mtu);
+ else
adapter->set_mtu(adapter, netdev->mtu);
mod_timer(&adapter->watchdog_timer, jiffies);
@@ -858,6 +1126,14 @@ static int netxen_nic_open(struct net_device *netdev)
netif_start_queue(netdev);
return 0;
+
+err_out_free_irq:
+ free_irq(adapter->irq, adapter);
+err_out_free_hw:
+ netxen_free_hw_resources(adapter);
+err_out_free_sw:
+ netxen_free_sw_resources(adapter);
+ return err;
}
/*
@@ -866,9 +1142,6 @@ static int netxen_nic_open(struct net_device *netdev)
static int netxen_nic_close(struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
- int i, j;
- struct netxen_cmd_buffer *cmd_buff;
- struct netxen_skb_frag *buffrag;
netif_carrier_off(netdev);
netif_stop_queue(netdev);
@@ -879,30 +1152,8 @@ static int netxen_nic_close(struct net_device *netdev)
netxen_nic_disable_int(adapter);
- cmd_buff = adapter->cmd_buf_arr;
- for (i = 0; i < adapter->max_tx_desc_count; i++) {
- buffrag = cmd_buff->frag_array;
- if (buffrag->dma) {
- pci_unmap_single(adapter->pdev, buffrag->dma,
- buffrag->length, PCI_DMA_TODEVICE);
- buffrag->dma = 0ULL;
- }
- for (j = 0; j < cmd_buff->frag_count; j++) {
- buffrag++;
- if (buffrag->dma) {
- pci_unmap_page(adapter->pdev, buffrag->dma,
- buffrag->length,
- PCI_DMA_TODEVICE);
- buffrag->dma = 0ULL;
- }
- }
- /* Free the skb we received in netxen_nic_xmit_frame */
- if (cmd_buff->skb) {
- dev_kfree_skb_any(cmd_buff->skb);
- cmd_buff->skb = NULL;
- }
- cmd_buff++;
- }
+ netxen_release_tx_buffers(adapter);
+
if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
FLUSH_SCHEDULED_WORK();
del_timer_sync(&adapter->watchdog_timer);
@@ -911,6 +1162,31 @@ static int netxen_nic_close(struct net_device *netdev)
return 0;
}
+void netxen_tso_check(struct netxen_adapter *adapter,
+ struct cmd_desc_type0 *desc, struct sk_buff *skb)
+{
+ if (desc->mss) {
+ desc->total_hdr_length = (sizeof(struct ethhdr) +
+ ip_hdrlen(skb) + tcp_hdrlen(skb));
+
+ if ((NX_IS_REVISION_P3(adapter->ahw.revision_id)) &&
+ (skb->protocol == htons(ETH_P_IPV6)))
+ netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO6);
+ else
+ netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
+
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+ netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
+ else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+ netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
+ else
+ return;
+ }
+ desc->tcp_hdr_offset = skb_transport_offset(skb);
+ desc->ip_hdr_offset = skb_network_offset(skb);
+}
+
static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
@@ -932,7 +1208,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* There 4 fragments per descriptor */
no_of_desc = (frag_count + 3) >> 2;
- if (netdev->features & NETIF_F_TSO) {
+ if (netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) {
if (skb_shinfo(skb)->gso_size > 0) {
no_of_desc++;
@@ -959,7 +1235,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
/* Take skb->data itself */
pbuf = &adapter->cmd_buf_arr[producer];
- if ((netdev->features & NETIF_F_TSO) && skb_shinfo(skb)->gso_size > 0) {
+ if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
+ skb_shinfo(skb)->gso_size > 0) {
pbuf->mss = skb_shinfo(skb)->gso_size;
hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
} else {
@@ -1086,6 +1363,89 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
}
+static int netxen_nic_check_temp(struct netxen_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ uint32_t temp, temp_state, temp_val;
+ int rv = 0;
+
+ temp = adapter->pci_read_normalize(adapter, CRB_TEMP_STATE);
+
+ temp_state = nx_get_temp_state(temp);
+ temp_val = nx_get_temp_val(temp);
+
+ if (temp_state == NX_TEMP_PANIC) {
+ printk(KERN_ALERT
+ "%s: Device temperature %d degrees C exceeds"
+ " maximum allowed. Hardware has been shut down.\n",
+ netxen_nic_driver_name, temp_val);
+
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ rv = 1;
+ } else if (temp_state == NX_TEMP_WARN) {
+ if (adapter->temp == NX_TEMP_NORMAL) {
+ printk(KERN_ALERT
+ "%s: Device temperature %d degrees C "
+ "exceeds operating range."
+ " Immediate action needed.\n",
+ netxen_nic_driver_name, temp_val);
+ }
+ } else {
+ if (adapter->temp == NX_TEMP_WARN) {
+ printk(KERN_INFO
+ "%s: Device temperature is now %d degrees C"
+ " in normal range.\n", netxen_nic_driver_name,
+ temp_val);
+ }
+ }
+ adapter->temp = temp_state;
+ return rv;
+}
+
+static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ u32 val, port, linkup;
+
+ port = adapter->physical_port;
+
+ if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+ val = adapter->pci_read_normalize(adapter, CRB_XG_STATE);
+ linkup = (val >> port) & 1;
+ } else {
+ if (adapter->fw_major < 4) {
+ val = adapter->pci_read_normalize(adapter,
+ CRB_XG_STATE);
+ val = (val >> port*8) & 0xff;
+ linkup = (val == XG_LINK_UP);
+ } else {
+ val = adapter->pci_read_normalize(adapter,
+ CRB_XG_STATE_P3);
+ val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
+ linkup = (val == XG_LINK_UP_P3);
+ }
+ }
+
+ if (adapter->ahw.linkup && !linkup) {
+ printk(KERN_INFO "%s: %s NIC Link is down\n",
+ netxen_nic_driver_name, netdev->name);
+ adapter->ahw.linkup = 0;
+ if (netif_running(netdev)) {
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+ } else if (!adapter->ahw.linkup && linkup) {
+ printk(KERN_INFO "%s: %s NIC Link is up\n",
+ netxen_nic_driver_name, netdev->name);
+ adapter->ahw.linkup = 1;
+ if (netif_running(netdev)) {
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
+ }
+ }
+}
+
static void netxen_watchdog(unsigned long v)
{
struct netxen_adapter *adapter = (struct netxen_adapter *)v;
@@ -1093,6 +1453,19 @@ static void netxen_watchdog(unsigned long v)
SCHEDULE_WORK(&adapter->watchdog_task);
}
+void netxen_watchdog_task(struct work_struct *work)
+{
+ struct netxen_adapter *adapter =
+ container_of(work, struct netxen_adapter, watchdog_task);
+
+ if ((adapter->portnum == 0) && netxen_nic_check_temp(adapter))
+ return;
+
+ netxen_nic_handle_phy_intr(adapter);
+
+ mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+}
+
static void netxen_tx_timeout(struct net_device *netdev)
{
struct netxen_adapter *adapter = (struct netxen_adapter *)
@@ -1118,6 +1491,38 @@ static void netxen_tx_timeout_task(struct work_struct *work)
netif_wake_queue(adapter->netdev);
}
+/*
+ * netxen_nic_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ */
+struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
+{
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+ struct net_device_stats *stats = &adapter->net_stats;
+
+ memset(stats, 0, sizeof(*stats));
+
+ /* total packets received */
+ stats->rx_packets = adapter->stats.no_rcv;
+ /* total packets transmitted */
+ stats->tx_packets = adapter->stats.xmitedframes +
+ adapter->stats.xmitfinished;
+ /* total bytes received */
+ stats->rx_bytes = adapter->stats.rxbytes;
+ /* total bytes transmitted */
+ stats->tx_bytes = adapter->stats.txbytes;
+ /* bad packets received */
+ stats->rx_errors = adapter->stats.rcvdbadskb;
+ /* packet transmit problems */
+ stats->tx_errors = adapter->stats.nocmddescriptor;
+ /* no space in linux buffers */
+ stats->rx_dropped = adapter->stats.rxdropped;
+ /* no space available in linux */
+ stats->tx_dropped = adapter->stats.txdropped;
+
+ return stats;
+}
+
static inline void
netxen_handle_int(struct netxen_adapter *adapter)
{
@@ -1125,20 +1530,20 @@ netxen_handle_int(struct netxen_adapter *adapter)
napi_schedule(&adapter->napi);
}
-irqreturn_t netxen_intr(int irq, void *data)
+static irqreturn_t netxen_intr(int irq, void *data)
{
struct netxen_adapter *adapter = data;
u32 our_int = 0;
- our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+ our_int = adapter->pci_read_normalize(adapter, CRB_INT_VECTOR);
/* not our interrupt */
if ((our_int & (0x80 << adapter->portnum)) == 0)
return IRQ_NONE;
if (adapter->intr_scheme == INTR_SCHEME_PERPORT) {
/* claim interrupt */
- writel(our_int & ~((u32)(0x80 << adapter->portnum)),
- NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+ adapter->pci_write_normalize(adapter, CRB_INT_VECTOR,
+ our_int & ~((u32)(0x80 << adapter->portnum)));
}
netxen_handle_int(adapter);
@@ -1146,7 +1551,7 @@ irqreturn_t netxen_intr(int irq, void *data)
return IRQ_HANDLED;
}
-irqreturn_t netxen_msi_intr(int irq, void *data)
+static irqreturn_t netxen_msi_intr(int irq, void *data)
{
struct netxen_adapter *adapter = data;
@@ -1220,10 +1625,6 @@ module_init(netxen_init_module);
static void __exit netxen_exit_module(void)
{
- /*
- * Wait for some time to allow the dma to drain, if any.
- */
- msleep(100);
pci_unregister_driver(&netxen_driver);
destroy_workqueue(netxen_workq);
}
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index a3bc7cc67a6..4cb8f4a1cf4 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -46,9 +46,8 @@ static int phy_lock(struct netxen_adapter *adapter)
int done = 0, timeout = 0;
while (!done) {
- done =
- readl(pci_base_offset
- (adapter, NETXEN_PCIE_REG(PCIE_SEM3_LOCK)));
+ done = netxen_nic_reg_read(adapter,
+ NETXEN_PCIE_REG(PCIE_SEM3_LOCK));
if (done == 1)
break;
if (timeout >= phy_lock_timeout) {
@@ -63,14 +62,14 @@ static int phy_lock(struct netxen_adapter *adapter)
}
}
- writel(PHY_LOCK_DRIVER,
- NETXEN_CRB_NORMALIZE(adapter, NETXEN_PHY_LOCK_ID));
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER);
return 0;
}
static int phy_unlock(struct netxen_adapter *adapter)
{
- readl(pci_base_offset(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK)));
+ adapter->pci_read_immediate(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK));
return 0;
}
@@ -109,7 +108,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
* so it cannot be in reset
*/
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
&mac_cfg0, 4))
return -EIO;
if (netxen_gb_get_soft_reset(mac_cfg0)) {
@@ -119,7 +118,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
netxen_gb_rx_reset_pb(temp);
netxen_gb_tx_reset_mac(temp);
netxen_gb_rx_reset_mac(temp);
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_0(0),
&temp, 4))
return -EIO;
@@ -129,22 +128,22 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
address = 0;
netxen_gb_mii_mgmt_reg_addr(address, reg);
netxen_gb_mii_mgmt_phy_addr(address, phy);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
&address, 4))
return -EIO;
command = 0; /* turn off any prior activity */
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
&command, 4))
return -EIO;
/* send read command */
netxen_gb_mii_mgmt_set_read_cycle(command);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
&command, 4))
return -EIO;
status = 0;
do {
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
&status, 4))
return -EIO;
@@ -154,7 +153,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
&& (timeout++ < NETXEN_NIU_PHY_WAITMAX));
if (timeout < NETXEN_NIU_PHY_WAITMAX) {
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_NIU_GB_MII_MGMT_STATUS(0),
readval, 4))
return -EIO;
@@ -163,7 +162,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
result = -1;
if (restore)
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_0(0),
&mac_cfg0, 4))
return -EIO;
@@ -201,7 +200,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
* cannot be in reset
*/
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
&mac_cfg0, 4))
return -EIO;
if (netxen_gb_get_soft_reset(mac_cfg0)) {
@@ -212,7 +211,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
netxen_gb_tx_reset_mac(temp);
netxen_gb_rx_reset_mac(temp);
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_0(0),
&temp, 4))
return -EIO;
@@ -220,24 +219,24 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
}
command = 0; /* turn off any prior activity */
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
&command, 4))
return -EIO;
address = 0;
netxen_gb_mii_mgmt_reg_addr(address, reg);
netxen_gb_mii_mgmt_phy_addr(address, phy);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
&address, 4))
return -EIO;
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0),
&val, 4))
return -EIO;
status = 0;
do {
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
&status, 4))
return -EIO;
@@ -252,7 +251,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
/* restore the state of port 0 MAC in case we tampered with it */
if (restore)
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_0(0),
&mac_cfg0, 4))
return -EIO;
@@ -401,14 +400,16 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
{
int result = 0;
__u32 status;
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ return 0;
+
if (adapter->disable_phy_interrupts)
adapter->disable_phy_interrupts(adapter);
mdelay(2);
- if (0 ==
- netxen_niu_gbe_phy_read(adapter,
- NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
- &status)) {
+ if (0 == netxen_niu_gbe_phy_read(adapter,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, &status)) {
if (netxen_get_phy_link(status)) {
if (netxen_get_phy_speed(status) == 2) {
netxen_niu_gbe_set_gmii_mode(adapter, port, 1);
@@ -456,12 +457,12 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
{
- u32 portnum = adapter->physical_port;
-
- netxen_crb_writelit_adapter(adapter,
- NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), 0x1447);
- netxen_crb_writelit_adapter(adapter,
- NETXEN_NIU_XGE_CONFIG_0+(0x10000*portnum), 0x5);
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5);
+ }
return 0;
}
@@ -581,10 +582,10 @@ static int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
if ((phy < 0) || (phy > 3))
return -EINVAL;
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
&stationhigh, 4))
return -EIO;
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
&stationlow, 4))
return -EIO;
((__le32 *)val)[1] = cpu_to_le32(stationhigh);
@@ -613,14 +614,14 @@ int netxen_niu_macaddr_set(struct netxen_adapter *adapter,
temp[0] = temp[1] = 0;
memcpy(temp + 2, addr, 2);
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx
- (adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4))
+ if (adapter->hw_write_wx(adapter,
+ NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4))
return -EIO;
memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32));
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx
- (adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4))
+ if (adapter->hw_write_wx(adapter,
+ NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4))
return -2;
netxen_niu_macaddr_get(adapter,
@@ -654,7 +655,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
mac_cfg0 = 0;
netxen_gb_soft_reset(mac_cfg0);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
&mac_cfg0, 4))
return -EIO;
mac_cfg0 = 0;
@@ -666,7 +667,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
netxen_gb_tx_reset_mac(mac_cfg0);
netxen_gb_rx_reset_mac(mac_cfg0);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
&mac_cfg0, 4))
return -EIO;
mac_cfg1 = 0;
@@ -679,7 +680,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
if (mode == NETXEN_NIU_10_100_MB) {
netxen_gb_set_intfmode(mac_cfg1, 1);
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_1(port),
&mac_cfg1, 4))
return -EIO;
@@ -692,7 +693,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
} else if (mode == NETXEN_NIU_1000_MB) {
netxen_gb_set_intfmode(mac_cfg1, 2);
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_1(port),
&mac_cfg1, 4))
return -EIO;
@@ -704,7 +705,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
}
mii_cfg = 0;
netxen_gb_set_mii_mgmt_clockselect(mii_cfg, 7);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port),
&mii_cfg, 4))
return -EIO;
mac_cfg0 = 0;
@@ -713,7 +714,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
netxen_gb_unset_rx_flowctl(mac_cfg0);
netxen_gb_unset_tx_flowctl(mac_cfg0);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
&mac_cfg0, 4))
return -EIO;
return 0;
@@ -730,7 +731,7 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter)
return -EINVAL;
mac_cfg0 = 0;
netxen_gb_soft_reset(mac_cfg0);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
&mac_cfg0, 4))
return -EIO;
return 0;
@@ -746,7 +747,7 @@ int netxen_niu_disable_xg_port(struct netxen_adapter *adapter)
return -EINVAL;
mac_cfg = 0;
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), &mac_cfg, 4))
return -EIO;
return 0;
@@ -763,7 +764,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
return -EINVAL;
/* save previous contents */
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
&reg, 4))
return -EIO;
if (mode == NETXEN_NIU_PROMISC_MODE) {
@@ -801,7 +802,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
return -EIO;
}
}
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
&reg, 4))
return -EIO;
return 0;
@@ -826,13 +827,13 @@ int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter,
case 0:
memcpy(temp + 2, addr, 2);
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
&val, 4))
return -EIO;
memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
&val, 4))
return -EIO;
break;
@@ -840,13 +841,13 @@ int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter,
case 1:
memcpy(temp + 2, addr, 2);
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1,
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1,
&val, 4))
return -EIO;
memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI,
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI,
&val, 4))
return -EIO;
break;
@@ -877,10 +878,10 @@ int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter,
if (phy != 0)
return -EINVAL;
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
&stationhigh, 4))
return -EIO;
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
&stationlow, 4))
return -EIO;
((__le32 *)val)[1] = cpu_to_le32(stationhigh);
@@ -901,7 +902,7 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
if (port > NETXEN_NIU_MAX_XG_PORTS)
return -EINVAL;
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), &reg, 4))
return -EIO;
if (mode == NETXEN_NIU_PROMISC_MODE)
@@ -909,6 +910,11 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
else
reg = (reg & ~0x2000UL);
+ if (mode == NETXEN_NIU_ALLMULTI_MODE)
+ reg = (reg | 0x1000UL);
+ else
+ reg = (reg & ~0x1000UL);
+
netxen_crb_writelit_adapter(adapter,
NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h
index a566b50f36f..3bfa51b62a4 100644
--- a/drivers/net/netxen/netxen_nic_phan_reg.h
+++ b/drivers/net/netxen/netxen_nic_phan_reg.h
@@ -42,8 +42,11 @@
#define CRB_CMD_CONSUMER_OFFSET NETXEN_NIC_REG(0x0c)
#define CRB_PAUSE_ADDR_LO NETXEN_NIC_REG(0x10) /* C0 EPG BUG */
#define CRB_PAUSE_ADDR_HI NETXEN_NIC_REG(0x14)
-#define CRB_HOST_CMD_ADDR_HI NETXEN_NIC_REG(0x18) /* host add:cmd ring */
-#define CRB_HOST_CMD_ADDR_LO NETXEN_NIC_REG(0x1c)
+#define NX_CDRP_CRB_OFFSET NETXEN_NIC_REG(0x18)
+#define NX_ARG1_CRB_OFFSET NETXEN_NIC_REG(0x1c)
+#define NX_ARG2_CRB_OFFSET NETXEN_NIC_REG(0x20)
+#define NX_ARG3_CRB_OFFSET NETXEN_NIC_REG(0x24)
+#define NX_SIGN_CRB_OFFSET NETXEN_NIC_REG(0x28)
#define CRB_CMD_INTR_LOOP NETXEN_NIC_REG(0x20) /* 4 regs for perf */
#define CRB_CMD_DMA_LOOP NETXEN_NIC_REG(0x24)
#define CRB_RCV_INTR_LOOP NETXEN_NIC_REG(0x28)
@@ -73,8 +76,8 @@
#define CRB_RX_LRO_MID_TIMER NETXEN_NIC_REG(0x88)
#define CRB_DMA_MAX_RCV_BUFS NETXEN_NIC_REG(0x8c)
#define CRB_MAX_DMA_ENTRIES NETXEN_NIC_REG(0x90)
-#define CRB_XG_STATE NETXEN_NIC_REG(0x94) /* XG Link status */
-#define CRB_AGENT_GO NETXEN_NIC_REG(0x98) /* NIC pkt gen agent */
+#define CRB_XG_STATE NETXEN_NIC_REG(0x94) /* XG Link status */
+#define CRB_XG_STATE_P3 NETXEN_NIC_REG(0x98) /* XG PF Link status */
#define CRB_AGENT_TX_SIZE NETXEN_NIC_REG(0x9c)
#define CRB_AGENT_TX_TYPE NETXEN_NIC_REG(0xa0)
#define CRB_AGENT_TX_ADDR NETXEN_NIC_REG(0xa4)
@@ -97,7 +100,9 @@
#define CRB_HOST_BUFFER_CONS NETXEN_NIC_REG(0xf0)
#define CRB_JUMBO_BUFFER_PROD NETXEN_NIC_REG(0xf4)
#define CRB_JUMBO_BUFFER_CONS NETXEN_NIC_REG(0xf8)
+#define CRB_HOST_DUMMY_BUF NETXEN_NIC_REG(0xfc)
+#define CRB_RCVPEG_STATE NETXEN_NIC_REG(0x13c)
#define CRB_CMD_PRODUCER_OFFSET_1 NETXEN_NIC_REG(0x1ac)
#define CRB_CMD_CONSUMER_OFFSET_1 NETXEN_NIC_REG(0x1b0)
#define CRB_CMD_PRODUCER_OFFSET_2 NETXEN_NIC_REG(0x1b8)
@@ -147,29 +152,15 @@
#define nx_get_temp_state(x) ((x) & 0xffff)
#define nx_encode_temp(val, state) (((val) << 16) | (state))
-/* CRB registers per Rcv Descriptor ring */
-struct netxen_rcv_desc_crb {
- u32 crb_rcv_producer_offset __attribute__ ((aligned(512)));
- u32 crb_rcv_consumer_offset;
- u32 crb_globalrcv_ring;
- u32 crb_rcv_ring_size;
-};
-
/*
* CRB registers used by the receive peg logic.
*/
struct netxen_recv_crb {
- struct netxen_rcv_desc_crb rcv_desc_crb[NUM_RCV_DESC_RINGS];
- u32 crb_rcvstatus_ring;
- u32 crb_rcv_status_producer;
- u32 crb_rcv_status_consumer;
- u32 crb_rcvpeg_state;
- u32 crb_status_ring_size;
+ u32 crb_rcv_producer[NUM_RCV_DESC_RINGS];
+ u32 crb_sts_consumer;
};
-extern struct netxen_recv_crb recv_crb_registers[];
-
/*
* Temperature control.
*/
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 32a8503a7ac..4aa54794704 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -158,11 +158,10 @@ static int m88e1111_config_init(struct phy_device *phydev)
{
int err;
int temp;
- int mode;
/* Enable Fiber/Copper auto selection */
temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
- temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO;
+ temp &= ~MII_M1111_HWCFG_FIBER_COPPER_AUTO;
phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
temp = phy_read(phydev, MII_BMCR);
@@ -198,9 +197,7 @@ static int m88e1111_config_init(struct phy_device *phydev)
temp &= ~(MII_M1111_HWCFG_MODE_MASK);
- mode = phy_read(phydev, MII_M1111_PHY_EXT_CR);
-
- if (mode & MII_M1111_HWCFG_FIBER_COPPER_RES)
+ if (temp & MII_M1111_HWCFG_FIBER_COPPER_RES)
temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII;
else
temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII;
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 6b1d7a8edf1..739b3ab7bcc 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -866,7 +866,8 @@ static int __init ppp_init(void)
err = PTR_ERR(ppp_class);
goto out_chrdev;
}
- device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), "ppp");
+ device_create_drvdata(ppp_class, NULL, MKDEV(PPP_MAJOR, 0),
+ NULL, "ppp");
}
out:
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 504a48ff73c..6531ff565c5 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -50,8 +50,8 @@
#include <asm/processor.h>
#define DRV_NAME "r6040"
-#define DRV_VERSION "0.16"
-#define DRV_RELDATE "10Nov2007"
+#define DRV_VERSION "0.18"
+#define DRV_RELDATE "13Jul2008"
/* PHY CHIP Address */
#define PHY1_ADDR 1 /* For MAC1 */
@@ -91,6 +91,14 @@
#define MISR 0x3C /* Status register */
#define MIER 0x40 /* INT enable register */
#define MSK_INT 0x0000 /* Mask off interrupts */
+#define RX_FINISH 0x0001 /* RX finished */
+#define RX_NO_DESC 0x0002 /* No RX descriptor available */
+#define RX_FIFO_FULL 0x0004 /* RX FIFO full */
+#define RX_EARLY 0x0008 /* RX early */
+#define TX_FINISH 0x0010 /* TX finished */
+#define TX_EARLY 0x0080 /* TX early */
+#define EVENT_OVRFL 0x0100 /* Event counter overflow */
+#define LINK_CHANGED 0x0200 /* PHY link changed */
#define ME_CISR 0x44 /* Event counter INT status */
#define ME_CIER 0x48 /* Event counter INT enable */
#define MR_CNT 0x50 /* Successfully received packet counter */
@@ -130,6 +138,21 @@
#define MBCR_DEFAULT 0x012A /* MAC Bus Control Register */
#define MCAST_MAX 4 /* Max number multicast addresses to filter */
+/* Descriptor status */
+#define DSC_OWNER_MAC 0x8000 /* MAC is the owner of this descriptor */
+#define DSC_RX_OK 0x4000 /* RX was successful */
+#define DSC_RX_ERR 0x0800 /* RX PHY error */
+#define DSC_RX_ERR_DRI 0x0400 /* RX dribble packet */
+#define DSC_RX_ERR_BUF 0x0200 /* RX length exceeds buffer size */
+#define DSC_RX_ERR_LONG 0x0100 /* RX length > maximum packet length */
+#define DSC_RX_ERR_RUNT 0x0080 /* RX packet length < 64 byte */
+#define DSC_RX_ERR_CRC 0x0040 /* RX CRC error */
+#define DSC_RX_BCAST 0x0020 /* RX broadcast (no error) */
+#define DSC_RX_MCAST 0x0010 /* RX multicast (no error) */
+#define DSC_RX_MCH_HIT 0x0008 /* RX multicast hit in hash table (no error) */
+#define DSC_RX_MIDH_HIT 0x0004 /* RX MID table hit (no error) */
+#define DSC_RX_IDX_MID_MASK 3 /* RX mask for the index of matched MIDx */
+
/* PHY settings */
#define ICPLUS_PHY_ID 0x0243
@@ -139,10 +162,10 @@ MODULE_AUTHOR("Sten Wang <sten.wang@rdc.com.tw>,"
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("RDC R6040 NAPI PCI FastEthernet driver");
-#define RX_INT 0x0001
-#define TX_INT 0x0010
-#define RX_NO_DESC_INT 0x0002
-#define INT_MASK (RX_INT | TX_INT)
+/* RX and TX interrupts that we handle */
+#define RX_INTS (RX_FIFO_FULL | RX_NO_DESC | RX_FINISH)
+#define TX_INTS (TX_FINISH)
+#define INT_MASK (RX_INTS | TX_INTS)
struct r6040_descriptor {
u16 status, len; /* 0-3 */
@@ -167,7 +190,7 @@ struct r6040_private {
struct r6040_descriptor *tx_ring;
dma_addr_t rx_ring_dma;
dma_addr_t tx_ring_dma;
- u16 tx_free_desc, rx_free_desc, phy_addr, phy_mode;
+ u16 tx_free_desc, phy_addr, phy_mode;
u16 mcr0, mcr1;
u16 switch_sig;
struct net_device *dev;
@@ -183,7 +206,7 @@ static char version[] __devinitdata = KERN_INFO DRV_NAME
static int phy_table[] = { PHY1_ADDR, PHY2_ADDR };
/* Read a word data from PHY Chip */
-static int phy_read(void __iomem *ioaddr, int phy_addr, int reg)
+static int r6040_phy_read(void __iomem *ioaddr, int phy_addr, int reg)
{
int limit = 2048;
u16 cmd;
@@ -200,7 +223,7 @@ static int phy_read(void __iomem *ioaddr, int phy_addr, int reg)
}
/* Write a word data from PHY Chip */
-static void phy_write(void __iomem *ioaddr, int phy_addr, int reg, u16 val)
+static void r6040_phy_write(void __iomem *ioaddr, int phy_addr, int reg, u16 val)
{
int limit = 2048;
u16 cmd;
@@ -216,20 +239,20 @@ static void phy_write(void __iomem *ioaddr, int phy_addr, int reg, u16 val)
}
}
-static int mdio_read(struct net_device *dev, int mii_id, int reg)
+static int r6040_mdio_read(struct net_device *dev, int mii_id, int reg)
{
struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
- return (phy_read(ioaddr, lp->phy_addr, reg));
+ return (r6040_phy_read(ioaddr, lp->phy_addr, reg));
}
-static void mdio_write(struct net_device *dev, int mii_id, int reg, int val)
+static void r6040_mdio_write(struct net_device *dev, int mii_id, int reg, int val)
{
struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
- phy_write(ioaddr, lp->phy_addr, reg, val);
+ r6040_phy_write(ioaddr, lp->phy_addr, reg, val);
}
static void r6040_free_txbufs(struct net_device *dev)
@@ -283,58 +306,101 @@ static void r6040_init_ring_desc(struct r6040_descriptor *desc_ring,
desc->vndescp = desc_ring;
}
-/* Allocate skb buffer for rx descriptor */
-static void rx_buf_alloc(struct r6040_private *lp, struct net_device *dev)
+static void r6040_init_txbufs(struct net_device *dev)
{
- struct r6040_descriptor *descptr;
- void __iomem *ioaddr = lp->base;
+ struct r6040_private *lp = netdev_priv(dev);
- descptr = lp->rx_insert_ptr;
- while (lp->rx_free_desc < RX_DCNT) {
- descptr->skb_ptr = netdev_alloc_skb(dev, MAX_BUF_SIZE);
+ lp->tx_free_desc = TX_DCNT;
- if (!descptr->skb_ptr)
- break;
- descptr->buf = cpu_to_le32(pci_map_single(lp->pdev,
- descptr->skb_ptr->data,
- MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
- descptr->status = 0x8000;
- descptr = descptr->vndescp;
- lp->rx_free_desc++;
- /* Trigger RX DMA */
- iowrite16(lp->mcr0 | 0x0002, ioaddr);
- }
- lp->rx_insert_ptr = descptr;
+ lp->tx_remove_ptr = lp->tx_insert_ptr = lp->tx_ring;
+ r6040_init_ring_desc(lp->tx_ring, lp->tx_ring_dma, TX_DCNT);
}
-static void r6040_alloc_txbufs(struct net_device *dev)
+static int r6040_alloc_rxbufs(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
- void __iomem *ioaddr = lp->base;
+ struct r6040_descriptor *desc;
+ struct sk_buff *skb;
+ int rc;
- lp->tx_free_desc = TX_DCNT;
+ lp->rx_remove_ptr = lp->rx_insert_ptr = lp->rx_ring;
+ r6040_init_ring_desc(lp->rx_ring, lp->rx_ring_dma, RX_DCNT);
- lp->tx_remove_ptr = lp->tx_insert_ptr = lp->tx_ring;
- r6040_init_ring_desc(lp->tx_ring, lp->tx_ring_dma, TX_DCNT);
+ /* Allocate skbs for the rx descriptors */
+ desc = lp->rx_ring;
+ do {
+ skb = netdev_alloc_skb(dev, MAX_BUF_SIZE);
+ if (!skb) {
+ printk(KERN_ERR "%s: failed to alloc skb for rx\n", dev->name);
+ rc = -ENOMEM;
+ goto err_exit;
+ }
+ desc->skb_ptr = skb;
+ desc->buf = cpu_to_le32(pci_map_single(lp->pdev,
+ desc->skb_ptr->data,
+ MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
+ desc->status = DSC_OWNER_MAC;
+ desc = desc->vndescp;
+ } while (desc != lp->rx_ring);
- iowrite16(lp->tx_ring_dma, ioaddr + MTD_SA0);
- iowrite16(lp->tx_ring_dma >> 16, ioaddr + MTD_SA1);
+ return 0;
+
+err_exit:
+ /* Deallocate all previously allocated skbs */
+ r6040_free_rxbufs(dev);
+ return rc;
}
-static void r6040_alloc_rxbufs(struct net_device *dev)
+static void r6040_init_mac_regs(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
+ int limit = 2048;
+ u16 cmd;
- lp->rx_free_desc = 0;
+ /* Mask Off Interrupt */
+ iowrite16(MSK_INT, ioaddr + MIER);
- lp->rx_remove_ptr = lp->rx_insert_ptr = lp->rx_ring;
- r6040_init_ring_desc(lp->rx_ring, lp->rx_ring_dma, RX_DCNT);
+ /* Reset RDC MAC */
+ iowrite16(MAC_RST, ioaddr + MCR1);
+ while (limit--) {
+ cmd = ioread16(ioaddr + MCR1);
+ if (cmd & 0x1)
+ break;
+ }
+ /* Reset internal state machine */
+ iowrite16(2, ioaddr + MAC_SM);
+ iowrite16(0, ioaddr + MAC_SM);
+ udelay(5000);
- rx_buf_alloc(lp, dev);
+ /* MAC Bus Control Register */
+ iowrite16(MBCR_DEFAULT, ioaddr + MBCR);
+
+ /* Buffer Size Register */
+ iowrite16(MAX_BUF_SIZE, ioaddr + MR_BSR);
+
+ /* Write TX ring start address */
+ iowrite16(lp->tx_ring_dma, ioaddr + MTD_SA0);
+ iowrite16(lp->tx_ring_dma >> 16, ioaddr + MTD_SA1);
+ /* Write RX ring start address */
iowrite16(lp->rx_ring_dma, ioaddr + MRD_SA0);
iowrite16(lp->rx_ring_dma >> 16, ioaddr + MRD_SA1);
+
+ /* Set interrupt waiting time and packet numbers */
+ iowrite16(0, ioaddr + MT_ICR);
+ iowrite16(0, ioaddr + MR_ICR);
+
+ /* Enable interrupts */
+ iowrite16(INT_MASK, ioaddr + MIER);
+
+ /* Enable TX and RX */
+ iowrite16(lp->mcr0 | 0x0002, ioaddr);
+
+ /* Let TX poll the descriptors
+ * we may got called by r6040_tx_timeout which has left
+ * some unsent tx buffers */
+ iowrite16(0x01, ioaddr + MTPR);
}
static void r6040_tx_timeout(struct net_device *dev)
@@ -342,27 +408,16 @@ static void r6040_tx_timeout(struct net_device *dev)
struct r6040_private *priv = netdev_priv(dev);
void __iomem *ioaddr = priv->base;
- printk(KERN_WARNING "%s: transmit timed out, status %4.4x, PHY status "
- "%4.4x\n",
+ printk(KERN_WARNING "%s: transmit timed out, int enable %4.4x "
+ "status %4.4x, PHY status %4.4x\n",
dev->name, ioread16(ioaddr + MIER),
- mdio_read(dev, priv->mii_if.phy_id, MII_BMSR));
-
- disable_irq(dev->irq);
- napi_disable(&priv->napi);
- spin_lock(&priv->lock);
- /* Clear all descriptors */
- r6040_free_txbufs(dev);
- r6040_free_rxbufs(dev);
- r6040_alloc_txbufs(dev);
- r6040_alloc_rxbufs(dev);
-
- /* Reset MAC */
- iowrite16(MAC_RST, ioaddr + MCR1);
- spin_unlock(&priv->lock);
- enable_irq(dev->irq);
+ ioread16(ioaddr + MISR),
+ r6040_mdio_read(dev, priv->mii_if.phy_id, MII_BMSR));
dev->stats.tx_errors++;
- netif_wake_queue(dev);
+
+ /* Reset MAC and re-init all registers */
+ r6040_init_mac_regs(dev);
}
static struct net_device_stats *r6040_get_stats(struct net_device *dev)
@@ -424,6 +479,7 @@ static int r6040_close(struct net_device *dev)
del_timer_sync(&lp->timer);
spin_lock_irq(&lp->lock);
+ napi_disable(&lp->napi);
netif_stop_queue(dev);
r6040_down(dev);
spin_unlock_irq(&lp->lock);
@@ -432,23 +488,23 @@ static int r6040_close(struct net_device *dev)
}
/* Status of PHY CHIP */
-static int phy_mode_chk(struct net_device *dev)
+static int r6040_phy_mode_chk(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
int phy_dat;
/* PHY Link Status Check */
- phy_dat = phy_read(ioaddr, lp->phy_addr, 1);
+ phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 1);
if (!(phy_dat & 0x4))
phy_dat = 0x8000; /* Link Failed, full duplex */
/* PHY Chip Auto-Negotiation Status */
- phy_dat = phy_read(ioaddr, lp->phy_addr, 1);
+ phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 1);
if (phy_dat & 0x0020) {
/* Auto Negotiation Mode */
- phy_dat = phy_read(ioaddr, lp->phy_addr, 5);
- phy_dat &= phy_read(ioaddr, lp->phy_addr, 4);
+ phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 5);
+ phy_dat &= r6040_phy_read(ioaddr, lp->phy_addr, 4);
if (phy_dat & 0x140)
/* Force full duplex */
phy_dat = 0x8000;
@@ -456,7 +512,7 @@ static int phy_mode_chk(struct net_device *dev)
phy_dat = 0;
} else {
/* Force Mode */
- phy_dat = phy_read(ioaddr, lp->phy_addr, 0);
+ phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 0);
if (phy_dat & 0x100)
phy_dat = 0x8000;
else
@@ -468,12 +524,12 @@ static int phy_mode_chk(struct net_device *dev)
static void r6040_set_carrier(struct mii_if_info *mii)
{
- if (phy_mode_chk(mii->dev)) {
+ if (r6040_phy_mode_chk(mii->dev)) {
/* autoneg is off: Link is always assumed to be up */
if (!netif_carrier_ok(mii->dev))
netif_carrier_on(mii->dev);
} else
- phy_mode_chk(mii->dev);
+ r6040_phy_mode_chk(mii->dev);
}
static int r6040_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -494,73 +550,72 @@ static int r6040_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static int r6040_rx(struct net_device *dev, int limit)
{
struct r6040_private *priv = netdev_priv(dev);
- int count;
- void __iomem *ioaddr = priv->base;
+ struct r6040_descriptor *descptr = priv->rx_remove_ptr;
+ struct sk_buff *skb_ptr, *new_skb;
+ int count = 0;
u16 err;
- for (count = 0; count < limit; ++count) {
- struct r6040_descriptor *descptr = priv->rx_remove_ptr;
- struct sk_buff *skb_ptr;
-
- /* Disable RX interrupt */
- iowrite16(ioread16(ioaddr + MIER) & (~RX_INT), ioaddr + MIER);
- descptr = priv->rx_remove_ptr;
-
- /* Check for errors */
- err = ioread16(ioaddr + MLSR);
- if (err & 0x0400)
- dev->stats.rx_errors++;
- /* RX FIFO over-run */
- if (err & 0x8000)
- dev->stats.rx_fifo_errors++;
- /* RX descriptor unavailable */
- if (err & 0x0080)
- dev->stats.rx_frame_errors++;
- /* Received packet with length over buffer lenght */
- if (err & 0x0020)
- dev->stats.rx_over_errors++;
- /* Received packet with too long or short */
- if (err & (0x0010 | 0x0008))
- dev->stats.rx_length_errors++;
- /* Received packet with CRC errors */
- if (err & 0x0004) {
- spin_lock(&priv->lock);
- dev->stats.rx_crc_errors++;
- spin_unlock(&priv->lock);
- }
-
- while (priv->rx_free_desc) {
- /* No RX packet */
- if (descptr->status & 0x8000)
- break;
- skb_ptr = descptr->skb_ptr;
- if (!skb_ptr) {
- printk(KERN_ERR "%s: Inconsistent RX"
- "descriptor chain\n",
- dev->name);
- break;
+ /* Limit not reached and the descriptor belongs to the CPU */
+ while (count < limit && !(descptr->status & DSC_OWNER_MAC)) {
+ /* Read the descriptor status */
+ err = descptr->status;
+ /* Global error status set */
+ if (err & DSC_RX_ERR) {
+ /* RX dribble */
+ if (err & DSC_RX_ERR_DRI)
+ dev->stats.rx_frame_errors++;
+ /* Buffer lenght exceeded */
+ if (err & DSC_RX_ERR_BUF)
+ dev->stats.rx_length_errors++;
+ /* Packet too long */
+ if (err & DSC_RX_ERR_LONG)
+ dev->stats.rx_length_errors++;
+ /* Packet < 64 bytes */
+ if (err & DSC_RX_ERR_RUNT)
+ dev->stats.rx_length_errors++;
+ /* CRC error */
+ if (err & DSC_RX_ERR_CRC) {
+ spin_lock(&priv->lock);
+ dev->stats.rx_crc_errors++;
+ spin_unlock(&priv->lock);
}
- descptr->skb_ptr = NULL;
- skb_ptr->dev = priv->dev;
- /* Do not count the CRC */
- skb_put(skb_ptr, descptr->len - 4);
- pci_unmap_single(priv->pdev, le32_to_cpu(descptr->buf),
- MAX_BUF_SIZE, PCI_DMA_FROMDEVICE);
- skb_ptr->protocol = eth_type_trans(skb_ptr, priv->dev);
- /* Send to upper layer */
- netif_receive_skb(skb_ptr);
- dev->last_rx = jiffies;
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += descptr->len;
- /* To next descriptor */
- descptr = descptr->vndescp;
- priv->rx_free_desc--;
+ goto next_descr;
+ }
+
+ /* Packet successfully received */
+ new_skb = netdev_alloc_skb(dev, MAX_BUF_SIZE);
+ if (!new_skb) {
+ dev->stats.rx_dropped++;
+ goto next_descr;
}
- priv->rx_remove_ptr = descptr;
+ skb_ptr = descptr->skb_ptr;
+ skb_ptr->dev = priv->dev;
+
+ /* Do not count the CRC */
+ skb_put(skb_ptr, descptr->len - 4);
+ pci_unmap_single(priv->pdev, le32_to_cpu(descptr->buf),
+ MAX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ skb_ptr->protocol = eth_type_trans(skb_ptr, priv->dev);
+
+ /* Send to upper layer */
+ netif_receive_skb(skb_ptr);
+ dev->last_rx = jiffies;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += descptr->len - 4;
+
+ /* put new skb into descriptor */
+ descptr->skb_ptr = new_skb;
+ descptr->buf = cpu_to_le32(pci_map_single(priv->pdev,
+ descptr->skb_ptr->data,
+ MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
+
+next_descr:
+ /* put the descriptor back to the MAC */
+ descptr->status = DSC_OWNER_MAC;
+ descptr = descptr->vndescp;
+ count++;
}
- /* Allocate new RX buffer */
- if (priv->rx_free_desc < RX_DCNT)
- rx_buf_alloc(priv, priv->dev);
+ priv->rx_remove_ptr = descptr;
return count;
}
@@ -584,7 +639,7 @@ static void r6040_tx(struct net_device *dev)
if (err & (0x2000 | 0x4000))
dev->stats.tx_carrier_errors++;
- if (descptr->status & 0x8000)
+ if (descptr->status & DSC_OWNER_MAC)
break; /* Not complete */
skb_ptr = descptr->skb_ptr;
pci_unmap_single(priv->pdev, le32_to_cpu(descptr->buf),
@@ -616,7 +671,7 @@ static int r6040_poll(struct napi_struct *napi, int budget)
if (work_done < budget) {
netif_rx_complete(dev, napi);
/* Enable RX interrupt */
- iowrite16(ioread16(ioaddr + MIER) | RX_INT, ioaddr + MIER);
+ iowrite16(ioread16(ioaddr + MIER) | RX_INTS, ioaddr + MIER);
}
return work_done;
}
@@ -638,13 +693,22 @@ static irqreturn_t r6040_interrupt(int irq, void *dev_id)
return IRQ_NONE;
/* RX interrupt request */
- if (status & 0x01) {
+ if (status & RX_INTS) {
+ if (status & RX_NO_DESC) {
+ /* RX descriptor unavailable */
+ dev->stats.rx_dropped++;
+ dev->stats.rx_missed_errors++;
+ }
+ if (status & RX_FIFO_FULL)
+ dev->stats.rx_fifo_errors++;
+
+ /* Mask off RX interrupt */
+ iowrite16(ioread16(ioaddr + MIER) & ~RX_INTS, ioaddr + MIER);
netif_rx_schedule(dev, &lp->napi);
- iowrite16(TX_INT, ioaddr + MIER);
}
/* TX interrupt request */
- if (status & 0x10)
+ if (status & TX_INTS)
r6040_tx(dev);
return IRQ_HANDLED;
@@ -660,52 +724,48 @@ static void r6040_poll_controller(struct net_device *dev)
#endif
/* Init RDC MAC */
-static void r6040_up(struct net_device *dev)
+static int r6040_up(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
+ int ret;
/* Initialise and alloc RX/TX buffers */
- r6040_alloc_txbufs(dev);
- r6040_alloc_rxbufs(dev);
+ r6040_init_txbufs(dev);
+ ret = r6040_alloc_rxbufs(dev);
+ if (ret)
+ return ret;
- /* Buffer Size Register */
- iowrite16(MAX_BUF_SIZE, ioaddr + MR_BSR);
/* Read the PHY ID */
- lp->switch_sig = phy_read(ioaddr, 0, 2);
+ lp->switch_sig = r6040_phy_read(ioaddr, 0, 2);
if (lp->switch_sig == ICPLUS_PHY_ID) {
- phy_write(ioaddr, 29, 31, 0x175C); /* Enable registers */
+ r6040_phy_write(ioaddr, 29, 31, 0x175C); /* Enable registers */
lp->phy_mode = 0x8000;
} else {
/* PHY Mode Check */
- phy_write(ioaddr, lp->phy_addr, 4, PHY_CAP);
- phy_write(ioaddr, lp->phy_addr, 0, PHY_MODE);
+ r6040_phy_write(ioaddr, lp->phy_addr, 4, PHY_CAP);
+ r6040_phy_write(ioaddr, lp->phy_addr, 0, PHY_MODE);
if (PHY_MODE == 0x3100)
- lp->phy_mode = phy_mode_chk(dev);
+ lp->phy_mode = r6040_phy_mode_chk(dev);
else
lp->phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;
}
- /* MAC Bus Control Register */
- iowrite16(MBCR_DEFAULT, ioaddr + MBCR);
- /* MAC TX/RX Enable */
+ /* Set duplex mode */
lp->mcr0 |= lp->phy_mode;
- iowrite16(lp->mcr0, ioaddr);
-
- /* set interrupt waiting time and packet numbers */
- iowrite16(0x0F06, ioaddr + MT_ICR);
- iowrite16(0x0F06, ioaddr + MR_ICR);
/* improve performance (by RDC guys) */
- phy_write(ioaddr, 30, 17, (phy_read(ioaddr, 30, 17) | 0x4000));
- phy_write(ioaddr, 30, 17, ~((~phy_read(ioaddr, 30, 17)) | 0x2000));
- phy_write(ioaddr, 0, 19, 0x0000);
- phy_write(ioaddr, 0, 30, 0x01F0);
+ r6040_phy_write(ioaddr, 30, 17, (r6040_phy_read(ioaddr, 30, 17) | 0x4000));
+ r6040_phy_write(ioaddr, 30, 17, ~((~r6040_phy_read(ioaddr, 30, 17)) | 0x2000));
+ r6040_phy_write(ioaddr, 0, 19, 0x0000);
+ r6040_phy_write(ioaddr, 0, 30, 0x01F0);
- /* Interrupt Mask Register */
- iowrite16(INT_MASK, ioaddr + MIER);
+ /* Initialize all MAC registers */
+ r6040_init_mac_regs(dev);
+
+ return 0;
}
/*
@@ -721,7 +781,7 @@ static void r6040_timer(unsigned long data)
/* Polling PHY Chip Status */
if (PHY_MODE == 0x3100)
- phy_mode = phy_mode_chk(dev);
+ phy_mode = r6040_phy_mode_chk(dev);
else
phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;
@@ -784,7 +844,14 @@ static int r6040_open(struct net_device *dev)
return -ENOMEM;
}
- r6040_up(dev);
+ ret = r6040_up(dev);
+ if (ret) {
+ pci_free_consistent(lp->pdev, TX_DESC_SIZE, lp->tx_ring,
+ lp->tx_ring_dma);
+ pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring,
+ lp->rx_ring_dma);
+ return ret;
+ }
napi_enable(&lp->napi);
netif_start_queue(dev);
@@ -830,7 +897,7 @@ static int r6040_start_xmit(struct sk_buff *skb, struct net_device *dev)
descptr->skb_ptr = skb;
descptr->buf = cpu_to_le32(pci_map_single(lp->pdev,
skb->data, skb->len, PCI_DMA_TODEVICE));
- descptr->status = 0x8000;
+ descptr->status = DSC_OWNER_MAC;
/* Trigger the MAC to check the TX descriptor */
iowrite16(0x01, ioaddr + MTPR);
lp->tx_insert_ptr = descptr->vndescp;
@@ -987,24 +1054,27 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
err = pci_enable_device(pdev);
if (err)
- return err;
+ goto err_out;
/* this should always be supported */
- if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses"
"not supported by the card\n");
- return -ENODEV;
+ goto err_out;
}
- if (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
+ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses"
"not supported by the card\n");
- return -ENODEV;
+ goto err_out;
}
/* IO Size check */
if (pci_resource_len(pdev, 0) < io_size) {
- printk(KERN_ERR "Insufficient PCI resources, aborting\n");
- return -EIO;
+ printk(KERN_ERR DRV_NAME "Insufficient PCI resources, aborting\n");
+ err = -EIO;
+ goto err_out;
}
pioaddr = pci_resource_start(pdev, 0); /* IO map base address */
@@ -1012,24 +1082,26 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
dev = alloc_etherdev(sizeof(struct r6040_private));
if (!dev) {
- printk(KERN_ERR "Failed to allocate etherdev\n");
- return -ENOMEM;
+ printk(KERN_ERR DRV_NAME "Failed to allocate etherdev\n");
+ err = -ENOMEM;
+ goto err_out;
}
SET_NETDEV_DEV(dev, &pdev->dev);
lp = netdev_priv(dev);
- lp->pdev = pdev;
- if (pci_request_regions(pdev, DRV_NAME)) {
+ err = pci_request_regions(pdev, DRV_NAME);
+
+ if (err) {
printk(KERN_ERR DRV_NAME ": Failed to request PCI regions\n");
- err = -ENODEV;
- goto err_out_disable;
+ goto err_out_free_dev;
}
ioaddr = pci_iomap(pdev, bar, io_size);
if (!ioaddr) {
printk(KERN_ERR "ioremap failed for device %s\n",
pci_name(pdev));
- return -EIO;
+ err = -EIO;
+ goto err_out_free_res;
}
/* Init system & device */
@@ -1049,6 +1121,7 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
/* Link new device into r6040_root_dev */
lp->pdev = pdev;
+ lp->dev = dev;
/* Init RDC private data */
lp->mcr0 = 0x1002;
@@ -1070,8 +1143,8 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
#endif
netif_napi_add(dev, &lp->napi, r6040_poll, 64);
lp->mii_if.dev = dev;
- lp->mii_if.mdio_read = mdio_read;
- lp->mii_if.mdio_write = mdio_write;
+ lp->mii_if.mdio_read = r6040_mdio_read;
+ lp->mii_if.mdio_write = r6040_mdio_write;
lp->mii_if.phy_id = lp->phy_addr;
lp->mii_if.phy_id_mask = 0x1f;
lp->mii_if.reg_num_mask = 0x1f;
@@ -1080,17 +1153,17 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
err = register_netdev(dev);
if (err) {
printk(KERN_ERR DRV_NAME ": Failed to register net device\n");
- goto err_out_res;
+ goto err_out_unmap;
}
return 0;
-err_out_res:
+err_out_unmap:
+ pci_iounmap(pdev, ioaddr);
+err_out_free_res:
pci_release_regions(pdev);
-err_out_disable:
- pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
+err_out_free_dev:
free_netdev(dev);
-
+err_out:
return err;
}
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index cfe8829ed31..a3e3895e503 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1418,8 +1418,10 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
rtl_hw_phy_config(dev);
- dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
- RTL_W8(0x82, 0x01);
+ if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
+ dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
+ RTL_W8(0x82, 0x01);
+ }
pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
@@ -3032,13 +3034,7 @@ static void rtl_set_rx_mode(struct net_device *dev)
tmp = rtl8169_rx_config | rx_mode |
(RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
- if ((tp->mac_version == RTL_GIGA_MAC_VER_11) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_12) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_13) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_14) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_15) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_16) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_17)) {
+ if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
u32 data = mc_filter[0];
mc_filter[0] = swab32(mc_filter[1]);
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 7b2015f9e46..45c72eebb3a 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -19,6 +19,7 @@
#include <linux/in.h>
#include <linux/crc32.h>
#include <linux/ethtool.h>
+#include <linux/topology.h>
#include "net_driver.h"
#include "gmii.h"
#include "ethtool.h"
@@ -832,7 +833,23 @@ static void efx_probe_interrupts(struct efx_nic *efx)
if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
BUG_ON(!pci_find_capability(efx->pci_dev, PCI_CAP_ID_MSIX));
- efx->rss_queues = rss_cpus ? rss_cpus : num_online_cpus();
+ if (rss_cpus == 0) {
+ cpumask_t core_mask;
+ int cpu;
+
+ cpus_clear(core_mask);
+ efx->rss_queues = 0;
+ for_each_online_cpu(cpu) {
+ if (!cpu_isset(cpu, core_mask)) {
+ ++efx->rss_queues;
+ cpus_or(core_mask, core_mask,
+ topology_core_siblings(cpu));
+ }
+ }
+ } else {
+ efx->rss_queues = rss_cpus;
+ }
+
efx->rss_queues = min(efx->rss_queues, max_channel + 1);
efx->rss_queues = min(efx->rss_queues, EFX_MAX_CHANNELS);
@@ -1762,7 +1779,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
efx->reset_pending = method;
- queue_work(efx->workqueue, &efx->reset_work);
+ queue_work(efx->reset_workqueue, &efx->reset_work);
}
/**************************************************************************
@@ -1907,14 +1924,28 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
goto fail1;
}
+ efx->reset_workqueue = create_singlethread_workqueue("sfc_reset");
+ if (!efx->reset_workqueue) {
+ rc = -ENOMEM;
+ goto fail2;
+ }
+
return 0;
+ fail2:
+ destroy_workqueue(efx->workqueue);
+ efx->workqueue = NULL;
+
fail1:
return rc;
}
static void efx_fini_struct(struct efx_nic *efx)
{
+ if (efx->reset_workqueue) {
+ destroy_workqueue(efx->reset_workqueue);
+ efx->reset_workqueue = NULL;
+ }
if (efx->workqueue) {
destroy_workqueue(efx->workqueue);
efx->workqueue = NULL;
@@ -1977,7 +2008,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
* scheduled from this point because efx_stop_all() has been
* called, we are no longer registered with driverlink, and
* the net_device's have been removed. */
- flush_workqueue(efx->workqueue);
+ flush_workqueue(efx->reset_workqueue);
efx_pci_remove_main(efx);
@@ -2098,7 +2129,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
* scheduled since efx_stop_all() has been called, and we
* have not and never have been registered with either
* the rtnetlink or driverlink layers. */
- cancel_work_sync(&efx->reset_work);
+ flush_workqueue(efx->reset_workqueue);
/* Retry if a recoverably reset event has been scheduled */
if ((efx->reset_pending != RESET_TYPE_INVISIBLE) &&
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 630406e142e..9138ee5b7b7 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -223,13 +223,8 @@ static struct i2c_algo_bit_data falcon_i2c_bit_operations = {
.getsda = falcon_getsda,
.getscl = falcon_getscl,
.udelay = 5,
- /*
- * This is the number of system clock ticks after which
- * i2c-algo-bit gives up waiting for SCL to become high.
- * It must be at least 2 since the first tick can happen
- * immediately after it starts waiting.
- */
- .timeout = 2,
+ /* Wait up to 50 ms for slave to let us pull SCL high */
+ .timeout = DIV_ROUND_UP(HZ, 20),
};
/**************************************************************************
@@ -2479,12 +2474,11 @@ int falcon_probe_nic(struct efx_nic *efx)
/* Initialise I2C adapter */
efx->i2c_adap.owner = THIS_MODULE;
- efx->i2c_adap.class = I2C_CLASS_HWMON;
nic_data->i2c_data = falcon_i2c_bit_operations;
nic_data->i2c_data.data = efx;
efx->i2c_adap.algo_data = &nic_data->i2c_data;
efx->i2c_adap.dev.parent = &efx->pci_dev->dev;
- strcpy(efx->i2c_adap.name, "SFC4000 GPIO");
+ strlcpy(efx->i2c_adap.name, "SFC4000 GPIO", sizeof(efx->i2c_adap.name));
rc = i2c_bit_add_bus(&efx->i2c_adap);
if (rc)
goto fail5;
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index d803b86c647..219c74a772c 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -616,7 +616,9 @@ union efx_multicast_hash {
* @pci_dev: The PCI device
* @type: Controller type attributes
* @legacy_irq: IRQ number
- * @workqueue: Workqueue for resets, port reconfigures and the HW monitor
+ * @workqueue: Workqueue for port reconfigures and the HW monitor.
+ * Work items do not hold and must not acquire RTNL.
+ * @reset_workqueue: Workqueue for resets. Work item will acquire RTNL.
* @reset_work: Scheduled reset workitem
* @monitor_work: Hardware monitor workitem
* @membase_phys: Memory BAR value as physical address
@@ -684,6 +686,7 @@ struct efx_nic {
const struct efx_nic_type *type;
int legacy_irq;
struct workqueue_struct *workqueue;
+ struct workqueue_struct *reset_workqueue;
struct work_struct reset_work;
struct delayed_work monitor_work;
resource_size_t membase_phys;
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index a4bc812aa99..c69ba1395fa 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -642,17 +642,12 @@ static void sh_eth_adjust_link(struct net_device *ndev)
| ECMR_DM, ioaddr + ECMR);
new_state = 1;
mdp->link = phydev->link;
- netif_tx_schedule_all(ndev);
- netif_carrier_on(ndev);
- netif_start_queue(ndev);
}
} else if (mdp->link) {
new_state = 1;
mdp->link = PHY_DOWN;
mdp->speed = 0;
mdp->duplex = -1;
- netif_stop_queue(ndev);
- netif_carrier_off(ndev);
}
if (new_state)
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 711e4a8948e..5257cf464f1 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1829,9 +1829,6 @@ static int sky2_down(struct net_device *dev)
if (netif_msg_ifdown(sky2))
printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
- /* Stop more packets from being queued */
- netif_stop_queue(dev);
-
/* Disable port IRQ */
imask = sky2_read32(hw, B0_IMSK);
imask &= ~portirq_msk[port];
@@ -1887,8 +1884,6 @@ static int sky2_down(struct net_device *dev)
sky2_phy_power_down(hw, port);
- netif_carrier_off(dev);
-
/* turn off LED's */
sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index f2051b209da..2040965d772 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -308,7 +308,7 @@ static void smc_reset(struct net_device *dev)
* can't handle it then there will be no recovery except for
* a hard reset or power cycle
*/
- if (nowait)
+ if (lp->cfg.flags & SMC91X_NOWAIT)
cfg |= CONFIG_NO_WAIT;
/*
@@ -1939,8 +1939,11 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
if (retval)
goto err_out;
-#ifdef SMC_USE_PXA_DMA
- {
+#ifdef CONFIG_ARCH_PXA
+# ifdef SMC_USE_PXA_DMA
+ lp->cfg.flags |= SMC91X_USE_DMA;
+# endif
+ if (lp->cfg.flags & SMC91X_USE_DMA) {
int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW,
smc_pxa_dma_irq, NULL);
if (dma >= 0)
@@ -1980,7 +1983,7 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
}
err_out:
-#ifdef SMC_USE_PXA_DMA
+#ifdef CONFIG_ARCH_PXA
if (retval && dev->dma != (unsigned char)-1)
pxa_free_dma(dev->dma);
#endif
@@ -2050,9 +2053,11 @@ static int smc_enable_device(struct platform_device *pdev)
return 0;
}
-static int smc_request_attrib(struct platform_device *pdev)
+static int smc_request_attrib(struct platform_device *pdev,
+ struct net_device *ndev)
{
struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+ struct smc_local *lp = netdev_priv(ndev);
if (!res)
return 0;
@@ -2063,9 +2068,11 @@ static int smc_request_attrib(struct platform_device *pdev)
return 0;
}
-static void smc_release_attrib(struct platform_device *pdev)
+static void smc_release_attrib(struct platform_device *pdev,
+ struct net_device *ndev)
{
struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+ struct smc_local *lp = netdev_priv(ndev);
if (res)
release_mem_region(res->start, ATTRIB_SIZE);
@@ -2123,27 +2130,14 @@ static int smc_drv_probe(struct platform_device *pdev)
struct net_device *ndev;
struct resource *res, *ires;
unsigned int __iomem *addr;
+ unsigned long irq_flags = SMC_IRQ_FLAGS;
int ret;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
- if (!res)
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -ENODEV;
- goto out;
- }
-
-
- if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
- ret = -EBUSY;
- goto out;
- }
-
ndev = alloc_etherdev(sizeof(struct smc_local));
if (!ndev) {
printk("%s: could not allocate device.\n", CARDNAME);
ret = -ENOMEM;
- goto out_release_io;
+ goto out;
}
SET_NETDEV_DEV(ndev, &pdev->dev);
@@ -2152,37 +2146,47 @@ static int smc_drv_probe(struct platform_device *pdev)
*/
lp = netdev_priv(ndev);
- lp->cfg.irq_flags = SMC_IRQ_FLAGS;
-#ifdef SMC_DYNAMIC_BUS_CONFIG
- if (pd)
+ if (pd) {
memcpy(&lp->cfg, pd, sizeof(lp->cfg));
- else {
- lp->cfg.flags = SMC91X_USE_8BIT;
- lp->cfg.flags |= SMC91X_USE_16BIT;
- lp->cfg.flags |= SMC91X_USE_32BIT;
+ lp->io_shift = SMC91X_IO_SHIFT(lp->cfg.flags);
+ } else {
+ lp->cfg.flags |= (SMC_CAN_USE_8BIT) ? SMC91X_USE_8BIT : 0;
+ lp->cfg.flags |= (SMC_CAN_USE_16BIT) ? SMC91X_USE_16BIT : 0;
+ lp->cfg.flags |= (SMC_CAN_USE_32BIT) ? SMC91X_USE_32BIT : 0;
+ lp->cfg.flags |= (nowait) ? SMC91X_NOWAIT : 0;
}
- lp->cfg.flags &= ~(SMC_CAN_USE_8BIT ? 0 : SMC91X_USE_8BIT);
- lp->cfg.flags &= ~(SMC_CAN_USE_16BIT ? 0 : SMC91X_USE_16BIT);
- lp->cfg.flags &= ~(SMC_CAN_USE_32BIT ? 0 : SMC91X_USE_32BIT);
-#endif
-
ndev->dma = (unsigned char)-1;
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+ if (!res)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -ENODEV;
+ goto out_free_netdev;
+ }
+
+
+ if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
+ ret = -EBUSY;
+ goto out_free_netdev;
+ }
+
ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!ires) {
ret = -ENODEV;
- goto out_free_netdev;
+ goto out_release_io;
}
ndev->irq = ires->start;
- if (SMC_IRQ_FLAGS == -1)
- lp->cfg.irq_flags = ires->flags & IRQF_TRIGGER_MASK;
- ret = smc_request_attrib(pdev);
+ if (ires->flags & IRQF_TRIGGER_MASK)
+ irq_flags = ires->flags & IRQF_TRIGGER_MASK;
+
+ ret = smc_request_attrib(pdev, ndev);
if (ret)
- goto out_free_netdev;
+ goto out_release_io;
#if defined(CONFIG_SA1100_ASSABET)
NCR_0 |= NCR_ENET_OSC_EN;
#endif
@@ -2197,7 +2201,7 @@ static int smc_drv_probe(struct platform_device *pdev)
goto out_release_attrib;
}
-#ifdef SMC_USE_PXA_DMA
+#ifdef CONFIG_ARCH_PXA
{
struct smc_local *lp = netdev_priv(ndev);
lp->device = &pdev->dev;
@@ -2205,7 +2209,7 @@ static int smc_drv_probe(struct platform_device *pdev)
}
#endif
- ret = smc_probe(ndev, addr, lp->cfg.irq_flags);
+ ret = smc_probe(ndev, addr, irq_flags);
if (ret != 0)
goto out_iounmap;
@@ -2217,11 +2221,11 @@ static int smc_drv_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
iounmap(addr);
out_release_attrib:
- smc_release_attrib(pdev);
- out_free_netdev:
- free_netdev(ndev);
+ smc_release_attrib(pdev, ndev);
out_release_io:
release_mem_region(res->start, SMC_IO_EXTENT);
+ out_free_netdev:
+ free_netdev(ndev);
out:
printk("%s: not found (%d).\n", CARDNAME, ret);
@@ -2240,14 +2244,14 @@ static int smc_drv_remove(struct platform_device *pdev)
free_irq(ndev->irq, ndev);
-#ifdef SMC_USE_PXA_DMA
+#ifdef CONFIG_ARCH_PXA
if (ndev->dma != (unsigned char)-1)
pxa_free_dma(ndev->dma);
#endif
iounmap(lp->base);
smc_release_datacs(pdev,ndev);
- smc_release_attrib(pdev);
+ smc_release_attrib(pdev,ndev);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
if (!res)
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 8606818653f..22209b6f140 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -40,23 +40,46 @@
* Define your architecture specific bus configuration parameters here.
*/
-#if defined(CONFIG_ARCH_LUBBOCK)
+#if defined(CONFIG_ARCH_LUBBOCK) ||\
+ defined(CONFIG_MACH_MAINSTONE) ||\
+ defined(CONFIG_MACH_ZYLONITE) ||\
+ defined(CONFIG_MACH_LITTLETON)
-/* We can only do 16-bit reads and writes in the static memory space. */
-#define SMC_CAN_USE_8BIT 0
+#include <asm/mach-types.h>
+
+/* Now the bus width is specified in the platform data
+ * pretend here to support all I/O access types
+ */
+#define SMC_CAN_USE_8BIT 1
#define SMC_CAN_USE_16BIT 1
-#define SMC_CAN_USE_32BIT 0
+#define SMC_CAN_USE_32BIT 1
#define SMC_NOWAIT 1
-/* The first two address lines aren't connected... */
-#define SMC_IO_SHIFT 2
+#define SMC_IO_SHIFT (lp->io_shift)
+#define SMC_inb(a, r) readb((a) + (r))
#define SMC_inw(a, r) readw((a) + (r))
-#define SMC_outw(v, a, r) writew(v, (a) + (r))
+#define SMC_inl(a, r) readl((a) + (r))
+#define SMC_outb(v, a, r) writeb(v, (a) + (r))
+#define SMC_outl(v, a, r) writel(v, (a) + (r))
#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l)
#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
+#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l)
#define SMC_IRQ_FLAGS (-1) /* from resource */
+/* We actually can't write halfwords properly if not word aligned */
+static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
+{
+ if (machine_is_mainstone() && reg & 2) {
+ unsigned int v = val << 16;
+ v |= readl(ioaddr + (reg & ~2)) & 0xffff;
+ writel(v, ioaddr + (reg & ~2));
+ } else {
+ writew(val, ioaddr + reg);
+ }
+}
+
#elif defined(CONFIG_BLACKFIN)
#define SMC_IRQ_FLAGS IRQF_TRIGGER_HIGH
@@ -195,7 +218,6 @@
#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
#elif defined(CONFIG_ARCH_INNOKOM) || \
- defined(CONFIG_MACH_MAINSTONE) || \
defined(CONFIG_ARCH_PXA_IDP) || \
defined(CONFIG_ARCH_RAMSES) || \
defined(CONFIG_ARCH_PCM027)
@@ -229,22 +251,6 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
}
}
-#elif defined(CONFIG_MACH_ZYLONITE)
-
-#define SMC_CAN_USE_8BIT 1
-#define SMC_CAN_USE_16BIT 1
-#define SMC_CAN_USE_32BIT 0
-#define SMC_IO_SHIFT 0
-#define SMC_NOWAIT 1
-#define SMC_USE_PXA_DMA 1
-#define SMC_inb(a, r) readb((a) + (r))
-#define SMC_inw(a, r) readw((a) + (r))
-#define SMC_insw(a, r, p, l) insw((a) + (r), p, l)
-#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l)
-#define SMC_outb(v, a, r) writeb(v, (a) + (r))
-#define SMC_outw(v, a, r) writew(v, (a) + (r))
-#define SMC_IRQ_FLAGS (-1) /* from resource */
-
#elif defined(CONFIG_ARCH_OMAP)
/* We can only do 16-bit reads and writes in the static memory space. */
@@ -454,7 +460,6 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r,
#define RPC_LSA_DEFAULT RPC_LED_100_10
#define RPC_LSB_DEFAULT RPC_LED_TX_RX
-#define SMC_DYNAMIC_BUS_CONFIG
#endif
@@ -493,7 +498,7 @@ struct smc_local {
spinlock_t lock;
-#ifdef SMC_USE_PXA_DMA
+#ifdef CONFIG_ARCH_PXA
/* DMA needs the physical address of the chip */
u_long physaddr;
struct device *device;
@@ -501,20 +506,17 @@ struct smc_local {
void __iomem *base;
void __iomem *datacs;
+ /* the low address lines on some platforms aren't connected... */
+ int io_shift;
+
struct smc91x_platdata cfg;
};
-#ifdef SMC_DYNAMIC_BUS_CONFIG
-#define SMC_8BIT(p) (((p)->cfg.flags & SMC91X_USE_8BIT) && SMC_CAN_USE_8BIT)
-#define SMC_16BIT(p) (((p)->cfg.flags & SMC91X_USE_16BIT) && SMC_CAN_USE_16BIT)
-#define SMC_32BIT(p) (((p)->cfg.flags & SMC91X_USE_32BIT) && SMC_CAN_USE_32BIT)
-#else
-#define SMC_8BIT(p) SMC_CAN_USE_8BIT
-#define SMC_16BIT(p) SMC_CAN_USE_16BIT
-#define SMC_32BIT(p) SMC_CAN_USE_32BIT
-#endif
+#define SMC_8BIT(p) ((p)->cfg.flags & SMC91X_USE_8BIT)
+#define SMC_16BIT(p) ((p)->cfg.flags & SMC91X_USE_16BIT)
+#define SMC_32BIT(p) ((p)->cfg.flags & SMC91X_USE_32BIT)
-#ifdef SMC_USE_PXA_DMA
+#ifdef CONFIG_ARCH_PXA
/*
* Let's use the DMA engine on the XScale PXA2xx for RX packets. This is
* always happening in irq context so no need to worry about races. TX is
@@ -608,7 +610,7 @@ smc_pxa_dma_irq(int dma, void *dummy)
{
DCSR(dma) = 0;
}
-#endif /* SMC_USE_PXA_DMA */
+#endif /* CONFIG_ARCH_PXA */
/*
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index 41d3ac45685..a645e5028c1 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -672,7 +672,6 @@ static void tc_handle_link_change(struct net_device *dev)
if (dev->flags & IFF_PROMISC)
tc35815_set_multicast_list(dev);
#endif
- netif_tx_schedule_all(dev);
} else {
lp->speed = 0;
lp->duplex = -1;
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index bc30c6e8fea..617ef41bdfe 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -5514,22 +5514,6 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
netif_wake_queue(dev); /* Unlock the TX ring */
break;
- case DE4X5_SET_PROM: /* Set Promiscuous Mode */
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- omr = inl(DE4X5_OMR);
- omr |= OMR_PR;
- outl(omr, DE4X5_OMR);
- dev->flags |= IFF_PROMISC;
- break;
-
- case DE4X5_CLR_PROM: /* Clear Promiscuous Mode */
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- omr = inl(DE4X5_OMR);
- omr &= ~OMR_PR;
- outl(omr, DE4X5_OMR);
- dev->flags &= ~IFF_PROMISC;
- break;
-
case DE4X5_SAY_BOO: /* Say "Boo!" to the kernel log file */
if (!capable(CAP_NET_ADMIN)) return -EPERM;
printk("%s: Boo!\n", dev->name);
diff --git a/drivers/net/tulip/de4x5.h b/drivers/net/tulip/de4x5.h
index f5f33b3eb06..9f2877438fb 100644
--- a/drivers/net/tulip/de4x5.h
+++ b/drivers/net/tulip/de4x5.h
@@ -1004,8 +1004,7 @@ struct de4x5_ioctl {
*/
#define DE4X5_GET_HWADDR 0x01 /* Get the hardware address */
#define DE4X5_SET_HWADDR 0x02 /* Set the hardware address */
-#define DE4X5_SET_PROM 0x03 /* Set Promiscuous Mode */
-#define DE4X5_CLR_PROM 0x04 /* Clear Promiscuous Mode */
+/* 0x03 and 0x04 were used before and are obsoleted now. Don't use them. */
#define DE4X5_SAY_BOO 0x05 /* Say "Boo!" to the kernel log file */
#define DE4X5_GET_MCA 0x06 /* Get a multicast address */
#define DE4X5_SET_MCA 0x07 /* Set a multicast address */
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a82b32b4013..e6bbc639c2d 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -900,7 +900,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
return -EINVAL;
rtnl_lock();
- ret = update_filter(&tun->txflt, (void *) __user arg);
+ ret = update_filter(&tun->txflt, (void __user *)arg);
rtnl_unlock();
return ret;
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index a934428a589..0e061dfea78 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -50,10 +50,18 @@ static int is_activesync(struct usb_interface_descriptor *desc)
&& desc->bInterfaceProtocol == 1;
}
+static int is_wireless_rndis(struct usb_interface_descriptor *desc)
+{
+ return desc->bInterfaceClass == USB_CLASS_WIRELESS_CONTROLLER
+ && desc->bInterfaceSubClass == 1
+ && desc->bInterfaceProtocol == 3;
+}
+
#else
#define is_rndis(desc) 0
#define is_activesync(desc) 0
+#define is_wireless_rndis(desc) 0
#endif
@@ -110,7 +118,8 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
* of cdc-acm, it'll fail RNDIS requests cleanly.
*/
rndis = is_rndis(&intf->cur_altsetting->desc)
- || is_activesync(&intf->cur_altsetting->desc);
+ || is_activesync(&intf->cur_altsetting->desc)
+ || is_wireless_rndis(&intf->cur_altsetting->desc);
memset(info, 0, sizeof *info);
info->control = intf;
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
index 61c98beb4d1..bcd858c567e 100644
--- a/drivers/net/usb/rndis_host.c
+++ b/drivers/net/usb/rndis_host.c
@@ -576,6 +576,10 @@ static const struct usb_device_id products [] = {
/* "ActiveSync" is an undocumented variant of RNDIS, used in WM5 */
USB_INTERFACE_INFO(USB_CLASS_MISC, 1, 1),
.driver_info = (unsigned long) &rndis_info,
+}, {
+ /* RNDIS for tethering */
+ USB_INTERFACE_INFO(USB_CLASS_WIRELESS_CONTROLLER, 1, 3),
+ .driver_info = (unsigned long) &rndis_info,
},
{ }, // END
};
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index c28d7cb2035..0196a0df902 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -19,6 +19,7 @@
//#define DEBUG
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
#include <linux/module.h>
#include <linux/virtio.h>
#include <linux/virtio_net.h>
@@ -54,9 +55,15 @@ struct virtnet_info
struct tasklet_struct tasklet;
bool free_in_tasklet;
+ /* I like... big packets and I cannot lie! */
+ bool big_packets;
+
/* Receive & send queues. */
struct sk_buff_head recv;
struct sk_buff_head send;
+
+ /* Chain pages by the private ptr. */
+ struct page *pages;
};
static inline struct virtio_net_hdr *skb_vnet_hdr(struct sk_buff *skb)
@@ -69,6 +76,23 @@ static inline void vnet_hdr_to_sg(struct scatterlist *sg, struct sk_buff *skb)
sg_init_one(sg, skb_vnet_hdr(skb), sizeof(struct virtio_net_hdr));
}
+static void give_a_page(struct virtnet_info *vi, struct page *page)
+{
+ page->private = (unsigned long)vi->pages;
+ vi->pages = page;
+}
+
+static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask)
+{
+ struct page *p = vi->pages;
+
+ if (p)
+ vi->pages = (struct page *)p->private;
+ else
+ p = alloc_page(gfp_mask);
+ return p;
+}
+
static void skb_xmit_done(struct virtqueue *svq)
{
struct virtnet_info *vi = svq->vdev->priv;
@@ -88,6 +112,7 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
unsigned len)
{
struct virtio_net_hdr *hdr = skb_vnet_hdr(skb);
+ int err;
if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) {
pr_debug("%s: short packet %i\n", dev->name, len);
@@ -95,10 +120,23 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
goto drop;
}
len -= sizeof(struct virtio_net_hdr);
- BUG_ON(len > MAX_PACKET_LEN);
- skb_trim(skb, len);
+ if (len <= MAX_PACKET_LEN) {
+ unsigned int i;
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+ give_a_page(dev->priv, skb_shinfo(skb)->frags[i].page);
+ skb->data_len = 0;
+ skb_shinfo(skb)->nr_frags = 0;
+ }
+
+ err = pskb_trim(skb, len);
+ if (err) {
+ pr_debug("%s: pskb_trim failed %i %d\n", dev->name, len, err);
+ dev->stats.rx_dropped++;
+ goto drop;
+ }
+ skb->truesize += skb->data_len;
dev->stats.rx_bytes += skb->len;
dev->stats.rx_packets++;
@@ -160,7 +198,7 @@ static void try_fill_recv(struct virtnet_info *vi)
{
struct sk_buff *skb;
struct scatterlist sg[2+MAX_SKB_FRAGS];
- int num, err;
+ int num, err, i;
sg_init_table(sg, 2+MAX_SKB_FRAGS);
for (;;) {
@@ -170,6 +208,24 @@ static void try_fill_recv(struct virtnet_info *vi)
skb_put(skb, MAX_PACKET_LEN);
vnet_hdr_to_sg(sg, skb);
+
+ if (vi->big_packets) {
+ for (i = 0; i < MAX_SKB_FRAGS; i++) {
+ skb_frag_t *f = &skb_shinfo(skb)->frags[i];
+ f->page = get_a_page(vi, GFP_ATOMIC);
+ if (!f->page)
+ break;
+
+ f->page_offset = 0;
+ f->size = PAGE_SIZE;
+
+ skb->data_len += PAGE_SIZE;
+ skb->len += PAGE_SIZE;
+
+ skb_shinfo(skb)->nr_frags++;
+ }
+ }
+
num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
skb_queue_head(&vi->recv, skb);
@@ -335,16 +391,11 @@ again:
free_old_xmit_skbs(vi);
/* If we has a buffer left over from last time, send it now. */
- if (unlikely(vi->last_xmit_skb)) {
- if (xmit_skb(vi, vi->last_xmit_skb) != 0) {
- /* Drop this skb: we only queue one. */
- vi->dev->stats.tx_dropped++;
- kfree_skb(skb);
- skb = NULL;
- goto stop_queue;
- }
- vi->last_xmit_skb = NULL;
- }
+ if (unlikely(vi->last_xmit_skb) &&
+ xmit_skb(vi, vi->last_xmit_skb) != 0)
+ goto stop_queue;
+
+ vi->last_xmit_skb = NULL;
/* Put new one in send queue and do transmit */
if (likely(skb)) {
@@ -370,6 +421,11 @@ stop_queue:
netif_start_queue(dev);
goto again;
}
+ if (skb) {
+ /* Drop this skb: we only queue one. */
+ vi->dev->stats.tx_dropped++;
+ kfree_skb(skb);
+ }
goto done;
}
@@ -408,6 +464,22 @@ static int virtnet_close(struct net_device *dev)
return 0;
}
+static int virtnet_set_tx_csum(struct net_device *dev, u32 data)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ struct virtio_device *vdev = vi->vdev;
+
+ if (data && !virtio_has_feature(vdev, VIRTIO_NET_F_CSUM))
+ return -ENOSYS;
+
+ return ethtool_op_set_tx_hw_csum(dev, data);
+}
+
+static struct ethtool_ops virtnet_ethtool_ops = {
+ .set_tx_csum = virtnet_set_tx_csum,
+ .set_sg = ethtool_op_set_sg,
+};
+
static int virtnet_probe(struct virtio_device *vdev)
{
int err;
@@ -427,6 +499,7 @@ static int virtnet_probe(struct virtio_device *vdev)
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = virtnet_netpoll;
#endif
+ SET_ETHTOOL_OPS(dev, &virtnet_ethtool_ops);
SET_NETDEV_DEV(dev, &vdev->dev);
/* Do we support "hardware" checksums? */
@@ -462,11 +535,18 @@ static int virtnet_probe(struct virtio_device *vdev)
vi->dev = dev;
vi->vdev = vdev;
vdev->priv = vi;
+ vi->pages = NULL;
/* If they give us a callback when all buffers are done, we don't need
* the timer. */
vi->free_in_tasklet = virtio_has_feature(vdev,VIRTIO_F_NOTIFY_ON_EMPTY);
+ /* If we can receive ANY GSO packets, we must allocate large ones. */
+ if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4)
+ || virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6)
+ || virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN))
+ vi->big_packets = true;
+
/* We expect two virtqueues, receive then send. */
vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done);
if (IS_ERR(vi->rvq)) {
@@ -541,6 +621,10 @@ static void virtnet_remove(struct virtio_device *vdev)
vdev->config->del_vq(vi->svq);
vdev->config->del_vq(vi->rvq);
unregister_netdev(vi->dev);
+
+ while (vi->pages)
+ __free_pages(get_a_page(vi, GFP_KERNEL), 0);
+
free_netdev(vi->dev);
}
@@ -553,7 +637,9 @@ static unsigned int features[] = {
VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM,
VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC,
VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
- VIRTIO_NET_F_HOST_ECN, VIRTIO_F_NOTIFY_ON_EMPTY,
+ VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
+ VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */
+ VIRTIO_F_NOTIFY_ON_EMPTY,
};
static struct virtio_driver virtio_net = {
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 5827324e9d9..f7d3349dc3e 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -397,9 +397,9 @@ static int __init cosa_init(void)
err = PTR_ERR(cosa_class);
goto out_chrdev;
}
- for (i=0; i<nr_cards; i++) {
- device_create(cosa_class, NULL, MKDEV(cosa_major, i), "cosa%d", i);
- }
+ for (i = 0; i < nr_cards; i++)
+ device_create_drvdata(cosa_class, NULL, MKDEV(cosa_major, i),
+ NULL, "cosa%d", i);
err = 0;
goto out;
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index 13d5882f1f2..3153fe9d7ce 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -3101,6 +3101,7 @@ static void prism2_clear_set_tim_queue(local_info_t *local)
* This is a natural nesting, which needs a split lock type.
*/
static struct lock_class_key hostap_netdev_xmit_lock_key;
+static struct lock_class_key hostap_netdev_addr_lock_key;
static void prism2_set_lockdep_class_one(struct net_device *dev,
struct netdev_queue *txq,
@@ -3112,6 +3113,8 @@ static void prism2_set_lockdep_class_one(struct net_device *dev,
static void prism2_set_lockdep_class(struct net_device *dev)
{
+ lockdep_set_class(&dev->addr_list_lock,
+ &hostap_netdev_addr_lock_key);
netdev_for_each_tx_queue(dev, prism2_set_lockdep_class_one, NULL);
}
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 6e704608947..1acfbcd3703 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -4972,8 +4972,7 @@ static int ipw_queue_tx_reclaim(struct ipw_priv *priv,
}
done:
if ((ipw_tx_queue_space(q) > q->low_mark) &&
- (qindex >= 0) &&
- (priv->status & STATUS_ASSOCIATED) && netif_running(priv->net_dev))
+ (qindex >= 0))
netif_wake_queue(priv->net_dev);
used = q->first_empty - q->last_used;
if (used < 0)
@@ -10154,14 +10153,8 @@ static void init_sys_config(struct ipw_sys_config *sys_config)
static int ipw_net_open(struct net_device *dev)
{
- struct ipw_priv *priv = ieee80211_priv(dev);
IPW_DEBUG_INFO("dev->open\n");
- /* we should be verifying the device is ready to be opened */
- mutex_lock(&priv->mutex);
- if (!(priv->status & STATUS_RF_KILL_MASK) &&
- (priv->status & STATUS_ASSOCIATED))
- netif_start_queue(dev);
- mutex_unlock(&priv->mutex);
+ netif_start_queue(dev);
return 0;
}
@@ -10481,13 +10474,6 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
IPW_DEBUG_TX("dev->xmit(%d bytes)\n", txb->payload_size);
spin_lock_irqsave(&priv->lock, flags);
- if (!(priv->status & STATUS_ASSOCIATED)) {
- IPW_DEBUG_INFO("Tx attempt while not associated.\n");
- priv->ieee->stats.tx_carrier_errors++;
- netif_stop_queue(dev);
- goto fail_unlock;
- }
-
#ifdef CONFIG_IPW2200_PROMISCUOUS
if (rtap_iface && netif_running(priv->prom_net_dev))
ipw_handle_promiscuous_tx(priv, txb);
@@ -10499,10 +10485,6 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
spin_unlock_irqrestore(&priv->lock, flags);
return ret;
-
- fail_unlock:
- spin_unlock_irqrestore(&priv->lock, flags);
- return 1;
}
static struct net_device_stats *ipw_net_get_stats(struct net_device *dev)
@@ -10703,13 +10685,6 @@ static void ipw_link_up(struct ipw_priv *priv)
priv->last_packet_time = 0;
netif_carrier_on(priv->net_dev);
- if (netif_queue_stopped(priv->net_dev)) {
- IPW_DEBUG_NOTIF("waking queue\n");
- netif_wake_queue(priv->net_dev);
- } else {
- IPW_DEBUG_NOTIF("starting queue\n");
- netif_start_queue(priv->net_dev);
- }
cancel_delayed_work(&priv->request_scan);
cancel_delayed_work(&priv->request_direct_scan);
@@ -10739,7 +10714,6 @@ static void ipw_link_down(struct ipw_priv *priv)
{
ipw_led_link_down(priv);
netif_carrier_off(priv->net_dev);
- netif_stop_queue(priv->net_dev);
notify_wx_assoc_event(priv);
/* Cancel any queued work ... */
@@ -11419,7 +11393,6 @@ static void ipw_down(struct ipw_priv *priv)
/* Clear all bits but the RF Kill */
priv->status &= STATUS_RF_KILL_MASK | STATUS_EXIT_PENDING;
netif_carrier_off(priv->net_dev);
- netif_stop_queue(priv->net_dev);
ipw_stop_nic(priv);
@@ -11522,7 +11495,6 @@ static int ipw_prom_open(struct net_device *dev)
IPW_DEBUG_INFO("prom dev->open\n");
netif_carrier_off(dev);
- netif_stop_queue(dev);
if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
priv->sys_config.accept_all_data_frames = 1;
@@ -11558,7 +11530,6 @@ static int ipw_prom_stop(struct net_device *dev)
static int ipw_prom_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
IPW_DEBUG_INFO("prom dev->xmit\n");
- netif_stop_queue(dev);
return -EOPNOTSUPP;
}
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 913dc9fe08f..5816230d58f 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -364,8 +364,7 @@ static void mac80211_hwsim_free(void)
struct mac80211_hwsim_data *data;
data = hwsim_radios[i]->priv;
ieee80211_unregister_hw(hwsim_radios[i]);
- if (!IS_ERR(data->dev))
- device_unregister(data->dev);
+ device_unregister(data->dev);
ieee80211_free_hw(hwsim_radios[i]);
}
}
@@ -437,7 +436,7 @@ static int __init init_mac80211_hwsim(void)
"mac80211_hwsim: device_create_drvdata "
"failed (%ld)\n", PTR_ERR(data->dev));
err = -ENOMEM;
- goto failed;
+ goto failed_drvdata;
}
data->dev->driver = &mac80211_hwsim_driver;
@@ -461,7 +460,7 @@ static int __init init_mac80211_hwsim(void)
if (err < 0) {
printk(KERN_DEBUG "mac80211_hwsim: "
"ieee80211_register_hw failed (%d)\n", err);
- goto failed;
+ goto failed_hw;
}
printk(KERN_DEBUG "%s: hwaddr %s registered\n",
@@ -479,9 +478,9 @@ static int __init init_mac80211_hwsim(void)
rtnl_lock();
err = dev_alloc_name(hwsim_mon, hwsim_mon->name);
- if (err < 0) {
+ if (err < 0)
goto failed_mon;
- }
+
err = register_netdevice(hwsim_mon);
if (err < 0)
@@ -494,7 +493,14 @@ static int __init init_mac80211_hwsim(void)
failed_mon:
rtnl_unlock();
free_netdev(hwsim_mon);
+ mac80211_hwsim_free();
+ return err;
+failed_hw:
+ device_unregister(data->dev);
+failed_drvdata:
+ ieee80211_free_hw(hw);
+ hwsim_radios[i] = 0;
failed:
mac80211_hwsim_free();
return err;
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 3a7a11a75fb..1d7ec312934 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -4,7 +4,7 @@ config OF_DEVICE
config OF_GPIO
def_bool y
- depends on OF && PPC_OF && HAVE_GPIO_LIB
+ depends on OF && PPC_OF && GPIOLIB
help
OpenFirmware GPIO accessors
diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
index 5c015d310d4..344e1b03dd8 100644
--- a/drivers/of/of_i2c.c
+++ b/drivers/of/of_i2c.c
@@ -91,8 +91,6 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
}
info.irq = irq_of_parse_and_map(node, 0);
- if (info.irq == NO_IRQ)
- info.irq = -1;
if (of_find_i2c_driver(node, &info) < 0) {
irq_dispose_mapping(info.irq);
diff --git a/drivers/parport/parport_ax88796.c b/drivers/parport/parport_ax88796.c
index 4ec220b2eae..6938d2e9f18 100644
--- a/drivers/parport/parport_ax88796.c
+++ b/drivers/parport/parport_ax88796.c
@@ -406,6 +406,8 @@ static int parport_ax88796_resume(struct platform_device *dev)
#define parport_ax88796_resume NULL
#endif
+MODULE_ALIAS("platform:ax88796-pp");
+
static struct platform_driver axdrv = {
.driver = {
.name = "ax88796-pp",
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index f941f609dbf..8bf86ae2333 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -317,10 +317,8 @@ int __init dmar_table_init(void)
return -ENODEV;
}
- if (list_empty(&dmar_rmrr_units)) {
+ if (list_empty(&dmar_rmrr_units))
printk(KERN_INFO PREFIX "No RMRR found\n");
- return -ENODEV;
- }
return 0;
}
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index eecf7cbf413..5a58b075dd8 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -36,7 +36,7 @@
#define _ACPIPHP_H
#include <linux/acpi.h>
-#include <linux/kobject.h> /* for KOBJ_NAME_LEN */
+#include <linux/kobject.h>
#include <linux/mutex.h>
#include <linux/pci_hotplug.h>
@@ -51,7 +51,7 @@
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
/* name size which is used for entries in pcihpfs */
-#define SLOT_NAME_SIZE KOBJ_NAME_LEN /* {_SUN} */
+#define SLOT_NAME_SIZE 20 /* {_SUN} */
struct acpiphp_bridge;
struct acpiphp_slot;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index d00f0e0d845..e9c356236d2 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1040,7 +1040,7 @@ int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)
* @dev: PCI device to handle.
* @state: PCI state from which device will issue PME#.
*/
-static bool pci_pme_capable(struct pci_dev *dev, pci_power_t state)
+bool pci_pme_capable(struct pci_dev *dev, pci_power_t state)
{
if (!dev->pm_cap)
return false;
@@ -1123,17 +1123,10 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable)
}
/**
- * pci_prepare_to_sleep - prepare PCI device for system-wide transition into a sleep state
- * @dev: Device to handle.
- *
- * Choose the power state appropriate for the device depending on whether
- * it can wake up the system and/or is power manageable by the platform
- * (PCI_D3hot is the default) and put the device into that state.
*/
-int pci_prepare_to_sleep(struct pci_dev *dev)
+pci_power_t pci_target_state(struct pci_dev *dev)
{
pci_power_t target_state = PCI_D3hot;
- int error;
if (platform_pci_power_manageable(dev)) {
/*
@@ -1160,7 +1153,7 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
* to generate PME#.
*/
if (!dev->pm_cap)
- return -EIO;
+ return PCI_POWER_ERROR;
if (dev->pme_support) {
while (target_state
@@ -1169,6 +1162,25 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
}
}
+ return target_state;
+}
+
+/**
+ * pci_prepare_to_sleep - prepare PCI device for system-wide transition into a sleep state
+ * @dev: Device to handle.
+ *
+ * Choose the power state appropriate for the device depending on whether
+ * it can wake up the system and/or is power manageable by the platform
+ * (PCI_D3hot is the default) and put the device into that state.
+ */
+int pci_prepare_to_sleep(struct pci_dev *dev)
+{
+ pci_power_t target_state = pci_target_state(dev);
+ int error;
+
+ if (target_state == PCI_POWER_ERROR)
+ return -EIO;
+
pci_enable_wake(dev, target_state, true);
error = pci_set_power_state(dev, target_state);
@@ -1918,7 +1930,9 @@ EXPORT_SYMBOL(pci_select_bars);
EXPORT_SYMBOL(pci_set_power_state);
EXPORT_SYMBOL(pci_save_state);
EXPORT_SYMBOL(pci_restore_state);
+EXPORT_SYMBOL(pci_pme_capable);
EXPORT_SYMBOL(pci_enable_wake);
+EXPORT_SYMBOL(pci_target_state);
EXPORT_SYMBOL(pci_prepare_to_sleep);
EXPORT_SYMBOL(pci_back_from_sleep);
EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state);
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 4400dffbd93..e1098c302c4 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -88,7 +88,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
if ((pos & 3) && cnt > 2) {
unsigned short val;
pci_user_read_config_word(dev, pos, &val);
- __put_user(cpu_to_le16(val), (unsigned short __user *) buf);
+ __put_user(cpu_to_le16(val), (__le16 __user *) buf);
buf += 2;
pos += 2;
cnt -= 2;
@@ -97,7 +97,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
while (cnt >= 4) {
unsigned int val;
pci_user_read_config_dword(dev, pos, &val);
- __put_user(cpu_to_le32(val), (unsigned int __user *) buf);
+ __put_user(cpu_to_le32(val), (__le32 __user *) buf);
buf += 4;
pos += 4;
cnt -= 4;
@@ -106,7 +106,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
if (cnt >= 2) {
unsigned short val;
pci_user_read_config_word(dev, pos, &val);
- __put_user(cpu_to_le16(val), (unsigned short __user *) buf);
+ __put_user(cpu_to_le16(val), (__le16 __user *) buf);
buf += 2;
pos += 2;
cnt -= 2;
@@ -156,8 +156,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
}
if ((pos & 3) && cnt > 2) {
- unsigned short val;
- __get_user(val, (unsigned short __user *) buf);
+ __le16 val;
+ __get_user(val, (__le16 __user *) buf);
pci_user_write_config_word(dev, pos, le16_to_cpu(val));
buf += 2;
pos += 2;
@@ -165,8 +165,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
}
while (cnt >= 4) {
- unsigned int val;
- __get_user(val, (unsigned int __user *) buf);
+ __le32 val;
+ __get_user(val, (__le32 __user *) buf);
pci_user_write_config_dword(dev, pos, le32_to_cpu(val));
buf += 4;
pos += 4;
@@ -174,8 +174,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
}
if (cnt >= 2) {
- unsigned short val;
- __get_user(val, (unsigned short __user *) buf);
+ __le16 val;
+ __get_user(val, (__le16 __user *) buf);
pci_user_write_config_word(dev, pos, le16_to_cpu(val));
buf += 2;
pos += 2;
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index e45402adac3..e0f884034c9 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -219,7 +219,8 @@ config PCMCIA_SA1111
config PCMCIA_PXA2XX
tristate "PXA2xx support"
depends on ARM && ARCH_PXA && PCMCIA
- depends on ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL || MACH_ARMCORE
+ depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \
+ || MACH_ARMCORE || ARCH_PXA_PALM)
help
Say Y here to include support for the PXA2xx PCMCIA controller
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 85c6cc931f9..269a9e913ba 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -72,4 +72,5 @@ pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock.o sa1111_generic.o
pxa2xx_cs-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o
pxa2xx_cs-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o
pxa2xx_cs-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x270.o
+pxa2xx_cs-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
index c21f9a9c3e3..a34284b1482 100644
--- a/drivers/pcmcia/electra_cf.c
+++ b/drivers/pcmcia/electra_cf.c
@@ -28,6 +28,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/of_platform.h>
diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c
index f123fce65f2..bb95db7d2b7 100644
--- a/drivers/pcmcia/pxa2xx_cm_x270.c
+++ b/drivers/pcmcia/pxa2xx_cm_x270.c
@@ -5,83 +5,60 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * Compulab Ltd., 2003, 2007
+ * Compulab Ltd., 2003, 2007, 2008
* Mike Rapoport <mike@compulab.co.il>
*
*/
-#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/delay.h>
+#include <linux/gpio.h>
-#include <pcmcia/ss.h>
-#include <asm/hardware.h>
#include <asm/mach-types.h>
-
#include <asm/arch/pxa-regs.h>
-#include <asm/arch/pxa2xx-gpio.h>
-#include <asm/arch/cm-x270.h>
#include "soc_common.h"
+#define GPIO_PCMCIA_S0_CD_VALID (84)
+#define GPIO_PCMCIA_S0_RDYINT (82)
+#define GPIO_PCMCIA_RESET (53)
+
+#define PCMCIA_S0_CD_VALID IRQ_GPIO(GPIO_PCMCIA_S0_CD_VALID)
+#define PCMCIA_S0_RDYINT IRQ_GPIO(GPIO_PCMCIA_S0_RDYINT)
+
+
static struct pcmcia_irqs irqs[] = {
{ 0, PCMCIA_S0_CD_VALID, "PCMCIA0 CD" },
- { 1, PCMCIA_S1_CD_VALID, "PCMCIA1 CD" },
};
static int cmx270_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
- GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) |
- GPIO_bit(GPIO49_nPWE) |
- GPIO_bit(GPIO50_nPIOR) |
- GPIO_bit(GPIO51_nPIOW) |
- GPIO_bit(GPIO85_nPCE_1) |
- GPIO_bit(GPIO54_nPCE_2);
-
- pxa_gpio_mode(GPIO48_nPOE_MD);
- pxa_gpio_mode(GPIO49_nPWE_MD);
- pxa_gpio_mode(GPIO50_nPIOR_MD);
- pxa_gpio_mode(GPIO51_nPIOW_MD);
- pxa_gpio_mode(GPIO85_nPCE_1_MD);
- pxa_gpio_mode(GPIO54_nPCE_2_MD);
- pxa_gpio_mode(GPIO55_nPREG_MD);
- pxa_gpio_mode(GPIO56_nPWAIT_MD);
- pxa_gpio_mode(GPIO57_nIOIS16_MD);
-
- /* Reset signal */
- pxa_gpio_mode(GPIO53_nPCE_2 | GPIO_OUT);
- GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
-
- set_irq_type(PCMCIA_S0_CD_VALID, IRQ_TYPE_EDGE_BOTH);
- set_irq_type(PCMCIA_S1_CD_VALID, IRQ_TYPE_EDGE_BOTH);
-
- /* irq's for slots: */
- set_irq_type(PCMCIA_S0_RDYINT, IRQ_TYPE_EDGE_FALLING);
- set_irq_type(PCMCIA_S1_RDYINT, IRQ_TYPE_EDGE_FALLING);
-
- skt->irq = (skt->nr == 0) ? PCMCIA_S0_RDYINT : PCMCIA_S1_RDYINT;
- return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+ int ret = gpio_request(GPIO_PCMCIA_RESET, "PCCard reset");
+ if (ret)
+ return ret;
+ gpio_direction_output(GPIO_PCMCIA_RESET, 0);
+
+ skt->irq = PCMCIA_S0_RDYINT;
+ ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+ if (!ret)
+ gpio_free(GPIO_PCMCIA_RESET);
+
+ return ret;
}
static void cmx270_pcmcia_shutdown(struct soc_pcmcia_socket *skt)
{
soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
-
- set_irq_type(IRQ_TO_GPIO(PCMCIA_S0_CD_VALID), IRQ_TYPE_NONE);
- set_irq_type(IRQ_TO_GPIO(PCMCIA_S1_CD_VALID), IRQ_TYPE_NONE);
-
- set_irq_type(IRQ_TO_GPIO(PCMCIA_S0_RDYINT), IRQ_TYPE_NONE);
- set_irq_type(IRQ_TO_GPIO(PCMCIA_S1_RDYINT), IRQ_TYPE_NONE);
+ gpio_free(GPIO_PCMCIA_RESET);
}
static void cmx270_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
struct pcmcia_state *state)
{
- state->detect = (PCC_DETECT(skt->nr) == 0) ? 1 : 0;
- state->ready = (PCC_READY(skt->nr) == 0) ? 0 : 1;
+ state->detect = (gpio_get_value(GPIO_PCMCIA_S0_CD_VALID) == 0) ? 1 : 0;
+ state->ready = (gpio_get_value(GPIO_PCMCIA_S0_RDYINT) == 0) ? 0 : 1;
state->bvd1 = 1;
state->bvd2 = 1;
state->vs_3v = 0;
@@ -93,32 +70,16 @@ static void cmx270_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
static int cmx270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
const socket_state_t *state)
{
- GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
- pxa_gpio_mode(GPIO49_nPWE | GPIO_OUT);
-
switch (skt->nr) {
case 0:
if (state->flags & SS_RESET) {
- GPCR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
- GPSR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
- udelay(10);
- GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
- GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
- }
- break;
- case 1:
- if (state->flags & SS_RESET) {
- GPCR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
- GPSR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
+ gpio_set_value(GPIO_PCMCIA_RESET, 1);
udelay(10);
- GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
- GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
+ gpio_set_value(GPIO_PCMCIA_RESET, 0);
}
break;
}
- pxa_gpio_mode(GPIO49_nPWE_MD);
-
return 0;
}
@@ -139,7 +100,7 @@ static struct pcmcia_low_level cmx270_pcmcia_ops __initdata = {
.configure_socket = cmx270_pcmcia_configure_socket,
.socket_init = cmx270_pcmcia_socket_init,
.socket_suspend = cmx270_pcmcia_socket_suspend,
- .nr = 2,
+ .nr = 1,
};
static struct platform_device *cmx270_pcmcia_device;
diff --git a/drivers/pcmcia/pxa2xx_palmtx.c b/drivers/pcmcia/pxa2xx_palmtx.c
new file mode 100644
index 00000000000..4abde190c1f
--- /dev/null
+++ b/drivers/pcmcia/pxa2xx_palmtx.c
@@ -0,0 +1,118 @@
+/*
+ * linux/drivers/pcmcia/pxa2xx_palmtx.c
+ *
+ * Driver for Palm T|X PCMCIA
+ *
+ * Copyright (C) 2007-2008 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/palmtx.h>
+
+#include "soc_common.h"
+
+static int palmtx_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+ skt->irq = IRQ_GPIO(GPIO_NR_PALMTX_PCMCIA_READY);
+ return 0;
+}
+
+static void palmtx_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+}
+
+static void palmtx_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+ struct pcmcia_state *state)
+{
+ state->detect = 1; /* always inserted */
+ state->ready = !!gpio_get_value(GPIO_NR_PALMTX_PCMCIA_READY);
+ state->bvd1 = 1;
+ state->bvd2 = 1;
+ state->wrprot = 0;
+ state->vs_3v = 1;
+ state->vs_Xv = 0;
+}
+
+static int
+palmtx_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+ const socket_state_t *state)
+{
+ gpio_set_value(GPIO_NR_PALMTX_PCMCIA_POWER1, 1);
+ gpio_set_value(GPIO_NR_PALMTX_PCMCIA_POWER2, 1);
+ gpio_set_value(GPIO_NR_PALMTX_PCMCIA_RESET,
+ !!(state->flags & SS_RESET));
+
+ return 0;
+}
+
+static void palmtx_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+}
+
+static void palmtx_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+}
+
+static struct pcmcia_low_level palmtx_pcmcia_ops = {
+ .owner = THIS_MODULE,
+
+ .first = 0,
+ .nr = 1,
+
+ .hw_init = palmtx_pcmcia_hw_init,
+ .hw_shutdown = palmtx_pcmcia_hw_shutdown,
+
+ .socket_state = palmtx_pcmcia_socket_state,
+ .configure_socket = palmtx_pcmcia_configure_socket,
+
+ .socket_init = palmtx_pcmcia_socket_init,
+ .socket_suspend = palmtx_pcmcia_socket_suspend,
+};
+
+static struct platform_device *palmtx_pcmcia_device;
+
+static int __init palmtx_pcmcia_init(void)
+{
+ int ret;
+
+ if (!machine_is_palmtx())
+ return -ENODEV;
+
+ palmtx_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
+ if (!palmtx_pcmcia_device)
+ return -ENOMEM;
+
+ ret = platform_device_add_data(palmtx_pcmcia_device, &palmtx_pcmcia_ops,
+ sizeof(palmtx_pcmcia_ops));
+
+ if (!ret)
+ ret = platform_device_add(palmtx_pcmcia_device);
+
+ if (ret)
+ platform_device_put(palmtx_pcmcia_device);
+
+ return ret;
+}
+
+static void __exit palmtx_pcmcia_exit(void)
+{
+ platform_device_unregister(palmtx_pcmcia_device);
+}
+
+fs_initcall(palmtx_pcmcia_init);
+module_exit(palmtx_pcmcia_exit);
+
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("PCMCIA support for Palm T|X");
+MODULE_ALIAS("platform:pxa2xx-pcmcia");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 58c806e9c58..4d17d384578 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -49,4 +49,10 @@ config BATTERY_OLPC
help
Say Y to enable support for the battery on the OLPC laptop.
+config BATTERY_PALMTX
+ tristate "Palm T|X battery"
+ depends on MACH_PALMTX
+ help
+ Say Y to enable support for the battery in Palm T|X.
+
endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 6413ded5fe5..6f43a54ee42 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_APM_POWER) += apm_power.o
obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o
obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
+obj-$(CONFIG_BATTERY_PALMTX) += palmtx_battery.o
diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c
index a4892275659..936bae560fa 100644
--- a/drivers/power/apm_power.c
+++ b/drivers/power/apm_power.c
@@ -78,7 +78,7 @@ static void find_main_battery(void)
main_battery = NULL;
bp.main = main_battery;
- error = class_for_each_device(power_supply_class, &bp,
+ error = class_for_each_device(power_supply_class, NULL, &bp,
__find_main_battery);
if (error) {
main_battery = bp.main;
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
index 71be36f1870..308ddb201b6 100644
--- a/drivers/power/ds2760_battery.c
+++ b/drivers/power/ds2760_battery.c
@@ -433,6 +433,8 @@ static int ds2760_battery_resume(struct platform_device *pdev)
#endif /* CONFIG_PM */
+MODULE_ALIAS("platform:ds2760-battery");
+
static struct platform_driver ds2760_battery_driver = {
.driver = {
.name = "ds2760-battery",
diff --git a/drivers/power/palmtx_battery.c b/drivers/power/palmtx_battery.c
new file mode 100644
index 00000000000..244bb273a63
--- /dev/null
+++ b/drivers/power/palmtx_battery.c
@@ -0,0 +1,198 @@
+/*
+ * linux/drivers/power/palmtx_battery.c
+ *
+ * Battery measurement code for Palm T|X Handheld computer
+ *
+ * based on tosa_battery.c
+ *
+ * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * 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/module.h>
+#include <linux/power_supply.h>
+#include <linux/wm97xx.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/arch/palmtx.h>
+
+static DEFINE_MUTEX(bat_lock);
+static struct work_struct bat_work;
+struct mutex work_lock;
+int bat_status = POWER_SUPPLY_STATUS_DISCHARGING;
+
+static unsigned long palmtx_read_bat(struct power_supply *bat_ps)
+{
+ return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data,
+ WM97XX_AUX_ID3) * 1000 / 414;
+}
+
+static unsigned long palmtx_read_temp(struct power_supply *bat_ps)
+{
+ return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data,
+ WM97XX_AUX_ID2);
+}
+
+static int palmtx_bat_get_property(struct power_supply *bat_ps,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = bat_status;
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = palmtx_read_bat(bat_ps);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ val->intval = PALMTX_BAT_MAX_VOLTAGE;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ val->intval = PALMTX_BAT_MIN_VOLTAGE;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = palmtx_read_temp(bat_ps);
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void palmtx_bat_external_power_changed(struct power_supply *bat_ps)
+{
+ schedule_work(&bat_work);
+}
+
+static char *status_text[] = {
+ [POWER_SUPPLY_STATUS_UNKNOWN] = "Unknown",
+ [POWER_SUPPLY_STATUS_CHARGING] = "Charging",
+ [POWER_SUPPLY_STATUS_DISCHARGING] = "Discharging",
+};
+
+static void palmtx_bat_update(struct power_supply *bat_ps)
+{
+ int old_status = bat_status;
+
+ mutex_lock(&work_lock);
+
+ bat_status = gpio_get_value(GPIO_NR_PALMTX_POWER_DETECT) ?
+ POWER_SUPPLY_STATUS_CHARGING :
+ POWER_SUPPLY_STATUS_DISCHARGING;
+
+ if (old_status != bat_status) {
+ pr_debug("%s %s -> %s\n", bat_ps->name,
+ status_text[old_status],
+ status_text[bat_status]);
+ power_supply_changed(bat_ps);
+ }
+
+ mutex_unlock(&work_lock);
+}
+
+static enum power_supply_property palmtx_bat_main_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_PRESENT,
+};
+
+struct power_supply bat_ps = {
+ .name = "main-battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = palmtx_bat_main_props,
+ .num_properties = ARRAY_SIZE(palmtx_bat_main_props),
+ .get_property = palmtx_bat_get_property,
+ .external_power_changed = palmtx_bat_external_power_changed,
+ .use_for_apm = 1,
+};
+
+static void palmtx_bat_work(struct work_struct *work)
+{
+ palmtx_bat_update(&bat_ps);
+}
+
+#ifdef CONFIG_PM
+static int palmtx_bat_suspend(struct platform_device *dev, pm_message_t state)
+{
+ flush_scheduled_work();
+ return 0;
+}
+
+static int palmtx_bat_resume(struct platform_device *dev)
+{
+ schedule_work(&bat_work);
+ return 0;
+}
+#else
+#define palmtx_bat_suspend NULL
+#define palmtx_bat_resume NULL
+#endif
+
+static int __devinit palmtx_bat_probe(struct platform_device *dev)
+{
+ int ret = 0;
+
+ if (!machine_is_palmtx())
+ return -ENODEV;
+
+ mutex_init(&work_lock);
+
+ INIT_WORK(&bat_work, palmtx_bat_work);
+
+ ret = power_supply_register(&dev->dev, &bat_ps);
+ if (!ret)
+ schedule_work(&bat_work);
+
+ return ret;
+}
+
+static int __devexit palmtx_bat_remove(struct platform_device *dev)
+{
+ power_supply_unregister(&bat_ps);
+ return 0;
+}
+
+static struct platform_driver palmtx_bat_driver = {
+ .driver.name = "wm97xx-battery",
+ .driver.owner = THIS_MODULE,
+ .probe = palmtx_bat_probe,
+ .remove = __devexit_p(palmtx_bat_remove),
+ .suspend = palmtx_bat_suspend,
+ .resume = palmtx_bat_resume,
+};
+
+static int __init palmtx_bat_init(void)
+{
+ return platform_driver_register(&palmtx_bat_driver);
+}
+
+static void __exit palmtx_bat_exit(void)
+{
+ platform_driver_unregister(&palmtx_bat_driver);
+}
+
+module_init(palmtx_bat_init);
+module_exit(palmtx_bat_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("Palm T|X battery driver");
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
index 82810b7bff9..0471ec743ab 100644
--- a/drivers/power/pda_power.c
+++ b/drivers/power/pda_power.c
@@ -362,6 +362,8 @@ static int pda_power_resume(struct platform_device *pdev)
#define pda_power_resume NULL
#endif /* CONFIG_PM */
+MODULE_ALIAS("platform:pda-power");
+
static struct platform_driver pda_power_pdrv = {
.driver = {
.name = "pda-power",
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index af1633eb3b7..cb1ccb47292 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -41,7 +41,7 @@ static void power_supply_changed_work(struct work_struct *work)
dev_dbg(psy->dev, "%s\n", __func__);
- class_for_each_device(power_supply_class, psy,
+ class_for_each_device(power_supply_class, NULL, psy,
__power_supply_changed_work);
power_supply_update_leds(psy);
@@ -79,7 +79,7 @@ int power_supply_am_i_supplied(struct power_supply *psy)
{
int error;
- error = class_for_each_device(power_supply_class, psy,
+ error = class_for_each_device(power_supply_class, NULL, psy,
__power_supply_am_i_supplied);
dev_dbg(psy->dev, "%s %d\n", __func__, error);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index fc85bf2e4a9..90ab7382540 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -273,6 +273,25 @@ comment "SPI RTC drivers"
if SPI_MASTER
+config RTC_DRV_M41T94
+ tristate "ST M41T94"
+ help
+ If you say yes here you will get support for the
+ ST M41T94 SPI RTC chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-m41t94.
+
+config RTC_DRV_DS1305
+ tristate "Dallas/Maxim DS1305/DS1306"
+ help
+ Select this driver to get support for the Dallas/Maxim DS1305
+ and DS1306 real time clock chips. These support a trickle
+ charger, alarms, and NVRAM in addition to the clock.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-ds1305.
+
config RTC_DRV_MAX6902
tristate "Maxim MAX6902"
help
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index b5d9d67df88..18622ef84ca 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o
obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o
obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
+obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o
obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o
obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o
obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o
@@ -34,6 +35,7 @@ obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o
obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o
obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o
+obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o
obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 58b7336640f..d397fa5f3a9 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -345,7 +345,7 @@ struct rtc_device *rtc_class_open(char *name)
struct device *dev;
struct rtc_device *rtc = NULL;
- dev = class_find_device(rtc_class, name, __rtc_match);
+ dev = class_find_device(rtc_class, NULL, name, __rtc_match);
if (dev)
rtc = to_rtc_device(dev);
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index 9c3db934cc2..cd32d05db77 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -171,8 +171,10 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
| BIN2BCD(tm.tm_mday) << 24
| AT91_RTC_DATEEN | AT91_RTC_MTHEN);
- if (alrm->enabled)
+ if (alrm->enabled) {
+ at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
+ }
pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
@@ -191,28 +193,22 @@ static int at91_rtc_ioctl(struct device *dev, unsigned int cmd,
pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __func__, cmd, arg);
+ /* important: scrub old status before enabling IRQs */
switch (cmd) {
case RTC_AIE_OFF: /* alarm off */
at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM);
break;
case RTC_AIE_ON: /* alarm on */
+ at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
break;
case RTC_UIE_OFF: /* update off */
- case RTC_PIE_OFF: /* periodic off */
at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV);
break;
case RTC_UIE_ON: /* update on */
- case RTC_PIE_ON: /* periodic on */
+ at91_sys_write(AT91_RTC_SCCR, AT91_RTC_SECEV);
at91_sys_write(AT91_RTC_IER, AT91_RTC_SECEV);
break;
- case RTC_IRQP_READ: /* read periodic alarm frequency */
- ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg);
- break;
- case RTC_IRQP_SET: /* set periodic alarm frequency */
- if (arg != AT91_RTC_FREQ)
- ret = -EINVAL;
- break;
default:
ret = -ENOIOCTLCMD;
break;
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index d7bb9bac71d..6ea349aba3b 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -36,25 +36,9 @@
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
-#ifdef CONFIG_HPET_EMULATE_RTC
-#include <asm/hpet.h>
-#endif
-
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
#include <asm-generic/rtc.h>
-#ifndef CONFIG_HPET_EMULATE_RTC
-#define is_hpet_enabled() 0
-#define hpet_set_alarm_time(hrs, min, sec) do { } while (0)
-#define hpet_set_periodic_freq(arg) 0
-#define hpet_mask_rtc_irq_bit(arg) do { } while (0)
-#define hpet_set_rtc_irq_bit(arg) do { } while (0)
-#define hpet_rtc_timer_init() do { } while (0)
-#define hpet_register_irq_handler(h) 0
-#define hpet_unregister_irq_handler(h) do { } while (0)
-extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
-#endif
-
struct cmos_rtc {
struct rtc_device *rtc;
struct device *dev;
@@ -93,6 +77,72 @@ static inline int is_intr(u8 rtc_intr)
/*----------------------------------------------------------------*/
+/* Much modern x86 hardware has HPETs (10+ MHz timers) which, because
+ * many BIOS programmers don't set up "sane mode" IRQ routing, are mostly
+ * used in a broken "legacy replacement" mode. The breakage includes
+ * HPET #1 hijacking the IRQ for this RTC, and being unavailable for
+ * other (better) use.
+ *
+ * When that broken mode is in use, platform glue provides a partial
+ * emulation of hardware RTC IRQ facilities using HPET #1. We don't
+ * want to use HPET for anything except those IRQs though...
+ */
+#ifdef CONFIG_HPET_EMULATE_RTC
+#include <asm/hpet.h>
+#else
+
+static inline int is_hpet_enabled(void)
+{
+ return 0;
+}
+
+static inline int hpet_mask_rtc_irq_bit(unsigned long mask)
+{
+ return 0;
+}
+
+static inline int hpet_set_rtc_irq_bit(unsigned long mask)
+{
+ return 0;
+}
+
+static inline int
+hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec)
+{
+ return 0;
+}
+
+static inline int hpet_set_periodic_freq(unsigned long freq)
+{
+ return 0;
+}
+
+static inline int hpet_rtc_dropped_irq(void)
+{
+ return 0;
+}
+
+static inline int hpet_rtc_timer_init(void)
+{
+ return 0;
+}
+
+extern irq_handler_t hpet_rtc_interrupt;
+
+static inline int hpet_register_irq_handler(irq_handler_t handler)
+{
+ return 0;
+}
+
+static inline int hpet_unregister_irq_handler(irq_handler_t handler)
+{
+ return 0;
+}
+
+#endif
+
+/*----------------------------------------------------------------*/
+
static int cmos_read_time(struct device *dev, struct rtc_time *t)
{
/* REVISIT: if the clock has a "century" register, use
@@ -185,11 +235,56 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
return 0;
}
+static void cmos_checkintr(struct cmos_rtc *cmos, unsigned char rtc_control)
+{
+ unsigned char rtc_intr;
+
+ /* NOTE after changing RTC_xIE bits we always read INTR_FLAGS;
+ * allegedly some older rtcs need that to handle irqs properly
+ */
+ rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
+
+ if (is_hpet_enabled())
+ return;
+
+ rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
+ if (is_intr(rtc_intr))
+ rtc_update_irq(cmos->rtc, 1, rtc_intr);
+}
+
+static void cmos_irq_enable(struct cmos_rtc *cmos, unsigned char mask)
+{
+ unsigned char rtc_control;
+
+ /* flush any pending IRQ status, notably for update irqs,
+ * before we enable new IRQs
+ */
+ rtc_control = CMOS_READ(RTC_CONTROL);
+ cmos_checkintr(cmos, rtc_control);
+
+ rtc_control |= mask;
+ CMOS_WRITE(rtc_control, RTC_CONTROL);
+ hpet_set_rtc_irq_bit(mask);
+
+ cmos_checkintr(cmos, rtc_control);
+}
+
+static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask)
+{
+ unsigned char rtc_control;
+
+ rtc_control = CMOS_READ(RTC_CONTROL);
+ rtc_control &= ~mask;
+ CMOS_WRITE(rtc_control, RTC_CONTROL);
+ hpet_mask_rtc_irq_bit(mask);
+
+ cmos_checkintr(cmos, rtc_control);
+}
+
static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
{
struct cmos_rtc *cmos = dev_get_drvdata(dev);
unsigned char mon, mday, hrs, min, sec;
- unsigned char rtc_control, rtc_intr;
if (!is_valid_irq(cmos->irq))
return -EIO;
@@ -213,17 +308,10 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
sec = t->time.tm_sec;
sec = (sec < 60) ? BIN2BCD(sec) : 0xff;
- hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec);
spin_lock_irq(&rtc_lock);
/* next rtc irq must not be from previous alarm setting */
- rtc_control = CMOS_READ(RTC_CONTROL);
- rtc_control &= ~RTC_AIE;
- CMOS_WRITE(rtc_control, RTC_CONTROL);
- rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
- rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
- if (is_intr(rtc_intr))
- rtc_update_irq(cmos->rtc, 1, rtc_intr);
+ cmos_irq_disable(cmos, RTC_AIE);
/* update alarm */
CMOS_WRITE(hrs, RTC_HOURS_ALARM);
@@ -237,14 +325,13 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
CMOS_WRITE(mon, cmos->mon_alrm);
}
- if (t->enabled) {
- rtc_control |= RTC_AIE;
- CMOS_WRITE(rtc_control, RTC_CONTROL);
- rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
- rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
- if (is_intr(rtc_intr))
- rtc_update_irq(cmos->rtc, 1, rtc_intr);
- }
+ /* FIXME the HPET alarm glue currently ignores day_alrm
+ * and mon_alrm ...
+ */
+ hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec);
+
+ if (t->enabled)
+ cmos_irq_enable(cmos, RTC_AIE);
spin_unlock_irq(&rtc_lock);
@@ -267,8 +354,8 @@ static int cmos_irq_set_freq(struct device *dev, int freq)
f = 16 - f;
spin_lock_irqsave(&rtc_lock, flags);
- if (!hpet_set_periodic_freq(freq))
- CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT);
+ hpet_set_periodic_freq(freq);
+ CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT);
spin_unlock_irqrestore(&rtc_lock, flags);
return 0;
@@ -277,26 +364,17 @@ static int cmos_irq_set_freq(struct device *dev, int freq)
static int cmos_irq_set_state(struct device *dev, int enabled)
{
struct cmos_rtc *cmos = dev_get_drvdata(dev);
- unsigned char rtc_control, rtc_intr;
unsigned long flags;
if (!is_valid_irq(cmos->irq))
return -ENXIO;
spin_lock_irqsave(&rtc_lock, flags);
- rtc_control = CMOS_READ(RTC_CONTROL);
if (enabled)
- rtc_control |= RTC_PIE;
+ cmos_irq_enable(cmos, RTC_PIE);
else
- rtc_control &= ~RTC_PIE;
-
- CMOS_WRITE(rtc_control, RTC_CONTROL);
-
- rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
- rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
- if (is_intr(rtc_intr))
- rtc_update_irq(cmos->rtc, 1, rtc_intr);
+ cmos_irq_disable(cmos, RTC_PIE);
spin_unlock_irqrestore(&rtc_lock, flags);
return 0;
@@ -308,7 +386,6 @@ static int
cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
struct cmos_rtc *cmos = dev_get_drvdata(dev);
- unsigned char rtc_control, rtc_intr;
unsigned long flags;
switch (cmd) {
@@ -316,51 +393,29 @@ cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
case RTC_AIE_ON:
case RTC_UIE_OFF:
case RTC_UIE_ON:
- case RTC_PIE_OFF:
- case RTC_PIE_ON:
if (!is_valid_irq(cmos->irq))
return -EINVAL;
break;
+ /* PIE ON/OFF is handled by cmos_irq_set_state() */
default:
return -ENOIOCTLCMD;
}
spin_lock_irqsave(&rtc_lock, flags);
- rtc_control = CMOS_READ(RTC_CONTROL);
switch (cmd) {
case RTC_AIE_OFF: /* alarm off */
- rtc_control &= ~RTC_AIE;
- hpet_mask_rtc_irq_bit(RTC_AIE);
+ cmos_irq_disable(cmos, RTC_AIE);
break;
case RTC_AIE_ON: /* alarm on */
- rtc_control |= RTC_AIE;
- hpet_set_rtc_irq_bit(RTC_AIE);
+ cmos_irq_enable(cmos, RTC_AIE);
break;
case RTC_UIE_OFF: /* update off */
- rtc_control &= ~RTC_UIE;
- hpet_mask_rtc_irq_bit(RTC_UIE);
+ cmos_irq_disable(cmos, RTC_UIE);
break;
case RTC_UIE_ON: /* update on */
- rtc_control |= RTC_UIE;
- hpet_set_rtc_irq_bit(RTC_UIE);
- break;
- case RTC_PIE_OFF: /* periodic off */
- rtc_control &= ~RTC_PIE;
- hpet_mask_rtc_irq_bit(RTC_PIE);
- break;
- case RTC_PIE_ON: /* periodic on */
- rtc_control |= RTC_PIE;
- hpet_set_rtc_irq_bit(RTC_PIE);
+ cmos_irq_enable(cmos, RTC_UIE);
break;
}
- if (!is_hpet_enabled())
- CMOS_WRITE(rtc_control, RTC_CONTROL);
-
- rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
- rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
- if (is_intr(rtc_intr))
- rtc_update_irq(cmos->rtc, 1, rtc_intr);
-
spin_unlock_irqrestore(&rtc_lock, flags);
return 0;
}
@@ -502,27 +557,29 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
u8 rtc_control;
spin_lock(&rtc_lock);
- /*
- * In this case it is HPET RTC interrupt handler
- * calling us, with the interrupt information
- * passed as arg1, instead of irq.
+
+ /* When the HPET interrupt handler calls us, the interrupt
+ * status is passed as arg1 instead of the irq number. But
+ * always clear irq status, even when HPET is in the way.
+ *
+ * Note that HPET and RTC are almost certainly out of phase,
+ * giving different IRQ status ...
*/
+ irqstat = CMOS_READ(RTC_INTR_FLAGS);
+ rtc_control = CMOS_READ(RTC_CONTROL);
if (is_hpet_enabled())
irqstat = (unsigned long)irq & 0xF0;
- else {
- irqstat = CMOS_READ(RTC_INTR_FLAGS);
- rtc_control = CMOS_READ(RTC_CONTROL);
- irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
- }
+ irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
/* All Linux RTC alarms should be treated as if they were oneshot.
* Similar code may be needed in system wakeup paths, in case the
* alarm woke the system.
*/
if (irqstat & RTC_AIE) {
- rtc_control = CMOS_READ(RTC_CONTROL);
rtc_control &= ~RTC_AIE;
CMOS_WRITE(rtc_control, RTC_CONTROL);
+ hpet_mask_rtc_irq_bit(RTC_AIE);
+
CMOS_READ(RTC_INTR_FLAGS);
}
spin_unlock(&rtc_lock);
@@ -629,18 +686,13 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
* do something about other clock frequencies.
*/
cmos_rtc.rtc->irq_freq = 1024;
- if (!hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq))
- CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
+ hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq);
+ CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
+
+ /* disable irqs */
+ cmos_irq_disable(&cmos_rtc, RTC_PIE | RTC_AIE | RTC_UIE);
- /* disable irqs.
- *
- * NOTE after changing RTC_xIE bits we always read INTR_FLAGS;
- * allegedly some older rtcs need that to handle irqs properly
- */
rtc_control = CMOS_READ(RTC_CONTROL);
- rtc_control &= ~(RTC_PIE | RTC_AIE | RTC_UIE);
- CMOS_WRITE(rtc_control, RTC_CONTROL);
- CMOS_READ(RTC_INTR_FLAGS);
spin_unlock_irq(&rtc_lock);
@@ -687,7 +739,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
goto cleanup2;
}
- pr_info("%s: alarms up to one %s%s\n",
+ pr_info("%s: alarms up to one %s%s%s\n",
cmos_rtc.rtc->dev.bus_id,
is_valid_irq(rtc_irq)
? (cmos_rtc.mon_alrm
@@ -695,8 +747,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
: (cmos_rtc.day_alrm
? "month" : "day"))
: "no",
- cmos_rtc.century ? ", y3k" : ""
- );
+ cmos_rtc.century ? ", y3k" : "",
+ is_hpet_enabled() ? ", hpet irqs" : "");
return 0;
@@ -713,13 +765,8 @@ cleanup0:
static void cmos_do_shutdown(void)
{
- unsigned char rtc_control;
-
spin_lock_irq(&rtc_lock);
- rtc_control = CMOS_READ(RTC_CONTROL);
- rtc_control &= ~(RTC_PIE|RTC_AIE|RTC_UIE);
- CMOS_WRITE(rtc_control, RTC_CONTROL);
- CMOS_READ(RTC_INTR_FLAGS);
+ cmos_irq_disable(&cmos_rtc, RTC_IRQMASK);
spin_unlock_irq(&rtc_lock);
}
@@ -760,17 +807,17 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg)
spin_lock_irq(&rtc_lock);
cmos->suspend_ctrl = tmp = CMOS_READ(RTC_CONTROL);
if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) {
- unsigned char irqstat;
+ unsigned char mask;
if (do_wake)
- tmp &= ~(RTC_PIE|RTC_UIE);
+ mask = RTC_IRQMASK & ~RTC_AIE;
else
- tmp &= ~(RTC_PIE|RTC_AIE|RTC_UIE);
+ mask = RTC_IRQMASK;
+ tmp &= ~mask;
CMOS_WRITE(tmp, RTC_CONTROL);
- irqstat = CMOS_READ(RTC_INTR_FLAGS);
- irqstat &= (tmp & RTC_IRQMASK) | RTC_IRQF;
- if (is_intr(irqstat))
- rtc_update_irq(cmos->rtc, 1, irqstat);
+ hpet_mask_rtc_irq_bit(mask);
+
+ cmos_checkintr(cmos, tmp);
}
spin_unlock_irq(&rtc_lock);
@@ -796,7 +843,8 @@ static int cmos_resume(struct device *dev)
unsigned char tmp = cmos->suspend_ctrl;
/* re-enable any irqs previously active */
- if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) {
+ if (tmp & RTC_IRQMASK) {
+ unsigned char mask;
if (cmos->enabled_wake) {
if (cmos->wake_off)
@@ -807,18 +855,28 @@ static int cmos_resume(struct device *dev)
}
spin_lock_irq(&rtc_lock);
- CMOS_WRITE(tmp, RTC_CONTROL);
- tmp = CMOS_READ(RTC_INTR_FLAGS);
- tmp &= (cmos->suspend_ctrl & RTC_IRQMASK) | RTC_IRQF;
- if (is_intr(tmp))
- rtc_update_irq(cmos->rtc, 1, tmp);
+ do {
+ CMOS_WRITE(tmp, RTC_CONTROL);
+ hpet_set_rtc_irq_bit(tmp & RTC_IRQMASK);
+
+ mask = CMOS_READ(RTC_INTR_FLAGS);
+ mask &= (tmp & RTC_IRQMASK) | RTC_IRQF;
+ if (!is_hpet_enabled() || !is_intr(mask))
+ break;
+
+ /* force one-shot behavior if HPET blocked
+ * the wake alarm's irq
+ */
+ rtc_update_irq(cmos->rtc, 1, mask);
+ tmp &= ~RTC_AIE;
+ hpet_mask_rtc_irq_bit(RTC_AIE);
+ } while (mask & RTC_AIE);
spin_unlock_irq(&rtc_lock);
}
pr_debug("%s: resume, ctrl %02x\n",
cmos_rtc.rtc->dev.bus_id,
- cmos->suspend_ctrl);
-
+ tmp);
return 0;
}
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 0114a78b7cb..0a870b7e5c3 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -209,7 +209,7 @@ static unsigned int rtc_dev_poll(struct file *file, poll_table *wait)
return (data != 0) ? (POLLIN | POLLRDNORM) : 0;
}
-static int rtc_dev_ioctl(struct inode *inode, struct file *file,
+static long rtc_dev_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
int err = 0;
@@ -219,6 +219,10 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
struct rtc_wkalrm alarm;
void __user *uarg = (void __user *) arg;
+ err = mutex_lock_interruptible(&rtc->ops_lock);
+ if (err)
+ return -EBUSY;
+
/* check that the calling task has appropriate permissions
* for certain ioctls. doing this check here is useful
* to avoid duplicate code in each driver.
@@ -227,26 +231,31 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
case RTC_EPOCH_SET:
case RTC_SET_TIME:
if (!capable(CAP_SYS_TIME))
- return -EACCES;
+ err = -EACCES;
break;
case RTC_IRQP_SET:
if (arg > rtc->max_user_freq && !capable(CAP_SYS_RESOURCE))
- return -EACCES;
+ err = -EACCES;
break;
case RTC_PIE_ON:
if (rtc->irq_freq > rtc->max_user_freq &&
!capable(CAP_SYS_RESOURCE))
- return -EACCES;
+ err = -EACCES;
break;
}
+ if (err)
+ goto done;
+
/* try the driver's ioctl interface */
if (ops->ioctl) {
err = ops->ioctl(rtc->dev.parent, cmd, arg);
- if (err != -ENOIOCTLCMD)
+ if (err != -ENOIOCTLCMD) {
+ mutex_unlock(&rtc->ops_lock);
return err;
+ }
}
/* if the driver does not provide the ioctl interface
@@ -265,15 +274,19 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case RTC_ALM_READ:
+ mutex_unlock(&rtc->ops_lock);
+
err = rtc_read_alarm(rtc, &alarm);
if (err < 0)
return err;
if (copy_to_user(uarg, &alarm.time, sizeof(tm)))
- return -EFAULT;
- break;
+ err = -EFAULT;
+ return err;
case RTC_ALM_SET:
+ mutex_unlock(&rtc->ops_lock);
+
if (copy_from_user(&alarm.time, uarg, sizeof(tm)))
return -EFAULT;
@@ -321,24 +334,26 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
}
}
- err = rtc_set_alarm(rtc, &alarm);
- break;
+ return rtc_set_alarm(rtc, &alarm);
case RTC_RD_TIME:
+ mutex_unlock(&rtc->ops_lock);
+
err = rtc_read_time(rtc, &tm);
if (err < 0)
return err;
if (copy_to_user(uarg, &tm, sizeof(tm)))
- return -EFAULT;
- break;
+ err = -EFAULT;
+ return err;
case RTC_SET_TIME:
+ mutex_unlock(&rtc->ops_lock);
+
if (copy_from_user(&tm, uarg, sizeof(tm)))
return -EFAULT;
- err = rtc_set_time(rtc, &tm);
- break;
+ return rtc_set_time(rtc, &tm);
case RTC_PIE_ON:
err = rtc_irq_set_state(rtc, NULL, 1);
@@ -376,34 +391,37 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
break;
#endif
case RTC_WKALM_SET:
+ mutex_unlock(&rtc->ops_lock);
if (copy_from_user(&alarm, uarg, sizeof(alarm)))
return -EFAULT;
- err = rtc_set_alarm(rtc, &alarm);
- break;
+ return rtc_set_alarm(rtc, &alarm);
case RTC_WKALM_RD:
+ mutex_unlock(&rtc->ops_lock);
err = rtc_read_alarm(rtc, &alarm);
if (err < 0)
return err;
if (copy_to_user(uarg, &alarm, sizeof(alarm)))
- return -EFAULT;
- break;
+ err = -EFAULT;
+ return err;
#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
case RTC_UIE_OFF:
clear_uie(rtc);
- return 0;
+ break;
case RTC_UIE_ON:
- return set_uie(rtc);
+ err = set_uie(rtc);
#endif
default:
err = -ENOTTY;
break;
}
+done:
+ mutex_unlock(&rtc->ops_lock);
return err;
}
@@ -432,7 +450,7 @@ static const struct file_operations rtc_dev_fops = {
.llseek = no_llseek,
.read = rtc_dev_read,
.poll = rtc_dev_poll,
- .ioctl = rtc_dev_ioctl,
+ .unlocked_ioctl = rtc_dev_ioctl,
.open = rtc_dev_open,
.release = rtc_dev_release,
.fasync = rtc_dev_fasync,
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c
new file mode 100644
index 00000000000..b91d02a3ace
--- /dev/null
+++ b/drivers/rtc/rtc-ds1305.c
@@ -0,0 +1,847 @@
+/*
+ * rtc-ds1305.c -- driver for DS1305 and DS1306 SPI RTC chips
+ *
+ * Copyright (C) 2008 David Brownell
+ *
+ * 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/bcd.h>
+#include <linux/rtc.h>
+#include <linux/workqueue.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/ds1305.h>
+
+
+/*
+ * Registers ... mask DS1305_WRITE into register address to write,
+ * otherwise you're reading it. All non-bitmask values are BCD.
+ */
+#define DS1305_WRITE 0x80
+
+
+/* RTC date/time ... the main special cases are that we:
+ * - Need fancy "hours" encoding in 12hour mode
+ * - Don't rely on the "day-of-week" field (or tm_wday)
+ * - Are a 21st-century clock (2000 <= year < 2100)
+ */
+#define DS1305_RTC_LEN 7 /* bytes for RTC regs */
+
+#define DS1305_SEC 0x00 /* register addresses */
+#define DS1305_MIN 0x01
+#define DS1305_HOUR 0x02
+# define DS1305_HR_12 0x40 /* set == 12 hr mode */
+# define DS1305_HR_PM 0x20 /* set == PM (12hr mode) */
+#define DS1305_WDAY 0x03
+#define DS1305_MDAY 0x04
+#define DS1305_MON 0x05
+#define DS1305_YEAR 0x06
+
+
+/* The two alarms have only sec/min/hour/wday fields (ALM_LEN).
+ * DS1305_ALM_DISABLE disables a match field (some combos are bad).
+ *
+ * NOTE that since we don't use WDAY, we limit ourselves to alarms
+ * only one day into the future (vs potentially up to a week).
+ *
+ * NOTE ALSO that while we could generate once-a-second IRQs (UIE), we
+ * don't currently support them. We'd either need to do it only when
+ * no alarm is pending (not the standard model), or to use the second
+ * alarm (implying that this is a DS1305 not DS1306, *and* that either
+ * it's wired up a second IRQ we know, or that INTCN is set)
+ */
+#define DS1305_ALM_LEN 4 /* bytes for ALM regs */
+#define DS1305_ALM_DISABLE 0x80
+
+#define DS1305_ALM0(r) (0x07 + (r)) /* register addresses */
+#define DS1305_ALM1(r) (0x0b + (r))
+
+
+/* three control registers */
+#define DS1305_CONTROL_LEN 3 /* bytes of control regs */
+
+#define DS1305_CONTROL 0x0f /* register addresses */
+# define DS1305_nEOSC 0x80 /* low enables oscillator */
+# define DS1305_WP 0x40 /* write protect */
+# define DS1305_INTCN 0x04 /* clear == only int0 used */
+# define DS1306_1HZ 0x04 /* enable 1Hz output */
+# define DS1305_AEI1 0x02 /* enable ALM1 IRQ */
+# define DS1305_AEI0 0x01 /* enable ALM0 IRQ */
+#define DS1305_STATUS 0x10
+/* status has just AEIx bits, mirrored as IRQFx */
+#define DS1305_TRICKLE 0x11
+/* trickle bits are defined in <linux/spi/ds1305.h> */
+
+/* a bunch of NVRAM */
+#define DS1305_NVRAM_LEN 96 /* bytes of NVRAM */
+
+#define DS1305_NVRAM 0x20 /* register addresses */
+
+
+struct ds1305 {
+ struct spi_device *spi;
+ struct rtc_device *rtc;
+
+ struct work_struct work;
+
+ unsigned long flags;
+#define FLAG_EXITING 0
+
+ bool hr12;
+ u8 ctrl[DS1305_CONTROL_LEN];
+};
+
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Utilities ... tolerate 12-hour AM/PM notation in case of non-Linux
+ * software (like a bootloader) which may require it.
+ */
+
+static unsigned bcd2hour(u8 bcd)
+{
+ if (bcd & DS1305_HR_12) {
+ unsigned hour = 0;
+
+ bcd &= ~DS1305_HR_12;
+ if (bcd & DS1305_HR_PM) {
+ hour = 12;
+ bcd &= ~DS1305_HR_PM;
+ }
+ hour += BCD2BIN(bcd);
+ return hour - 1;
+ }
+ return BCD2BIN(bcd);
+}
+
+static u8 hour2bcd(bool hr12, int hour)
+{
+ if (hr12) {
+ hour++;
+ if (hour <= 12)
+ return DS1305_HR_12 | BIN2BCD(hour);
+ hour -= 12;
+ return DS1305_HR_12 | DS1305_HR_PM | BIN2BCD(hour);
+ }
+ return BIN2BCD(hour);
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Interface to RTC framework
+ */
+
+#ifdef CONFIG_RTC_INTF_DEV
+
+/*
+ * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl)
+ */
+static int ds1305_ioctl(struct device *dev, unsigned cmd, unsigned long arg)
+{
+ struct ds1305 *ds1305 = dev_get_drvdata(dev);
+ u8 buf[2];
+ int status = -ENOIOCTLCMD;
+
+ buf[0] = DS1305_WRITE | DS1305_CONTROL;
+ buf[1] = ds1305->ctrl[0];
+
+ switch (cmd) {
+ case RTC_AIE_OFF:
+ status = 0;
+ if (!(buf[1] & DS1305_AEI0))
+ goto done;
+ buf[1] &= ~DS1305_AEI0;
+ break;
+
+ case RTC_AIE_ON:
+ status = 0;
+ if (ds1305->ctrl[0] & DS1305_AEI0)
+ goto done;
+ buf[1] |= DS1305_AEI0;
+ break;
+ }
+ if (status == 0) {
+ status = spi_write_then_read(ds1305->spi, buf, sizeof buf,
+ NULL, 0);
+ if (status >= 0)
+ ds1305->ctrl[0] = buf[1];
+ }
+
+done:
+ return status;
+}
+
+#else
+#define ds1305_ioctl NULL
+#endif
+
+/*
+ * Get/set of date and time is pretty normal.
+ */
+
+static int ds1305_get_time(struct device *dev, struct rtc_time *time)
+{
+ struct ds1305 *ds1305 = dev_get_drvdata(dev);
+ u8 addr = DS1305_SEC;
+ u8 buf[DS1305_RTC_LEN];
+ int status;
+
+ /* Use write-then-read to get all the date/time registers
+ * since dma from stack is nonportable
+ */
+ status = spi_write_then_read(ds1305->spi, &addr, sizeof addr,
+ buf, sizeof buf);
+ if (status < 0)
+ return status;
+
+ dev_vdbg(dev, "%s: %02x %02x %02x, %02x %02x %02x %02x\n",
+ "read", buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6]);
+
+ /* Decode the registers */
+ time->tm_sec = BCD2BIN(buf[DS1305_SEC]);
+ time->tm_min = BCD2BIN(buf[DS1305_MIN]);
+ time->tm_hour = bcd2hour(buf[DS1305_HOUR]);
+ time->tm_wday = buf[DS1305_WDAY] - 1;
+ time->tm_mday = BCD2BIN(buf[DS1305_MDAY]);
+ time->tm_mon = BCD2BIN(buf[DS1305_MON]) - 1;
+ time->tm_year = BCD2BIN(buf[DS1305_YEAR]) + 100;
+
+ dev_vdbg(dev, "%s secs=%d, mins=%d, "
+ "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+ "read", time->tm_sec, time->tm_min,
+ time->tm_hour, time->tm_mday,
+ time->tm_mon, time->tm_year, time->tm_wday);
+
+ /* Time may not be set */
+ return rtc_valid_tm(time);
+}
+
+static int ds1305_set_time(struct device *dev, struct rtc_time *time)
+{
+ struct ds1305 *ds1305 = dev_get_drvdata(dev);
+ u8 buf[1 + DS1305_RTC_LEN];
+ u8 *bp = buf;
+
+ dev_vdbg(dev, "%s secs=%d, mins=%d, "
+ "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+ "write", time->tm_sec, time->tm_min,
+ time->tm_hour, time->tm_mday,
+ time->tm_mon, time->tm_year, time->tm_wday);
+
+ /* Write registers starting at the first time/date address. */
+ *bp++ = DS1305_WRITE | DS1305_SEC;
+
+ *bp++ = BIN2BCD(time->tm_sec);
+ *bp++ = BIN2BCD(time->tm_min);
+ *bp++ = hour2bcd(ds1305->hr12, time->tm_hour);
+ *bp++ = (time->tm_wday < 7) ? (time->tm_wday + 1) : 1;
+ *bp++ = BIN2BCD(time->tm_mday);
+ *bp++ = BIN2BCD(time->tm_mon + 1);
+ *bp++ = BIN2BCD(time->tm_year - 100);
+
+ dev_dbg(dev, "%s: %02x %02x %02x, %02x %02x %02x %02x\n",
+ "write", buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6], buf[7]);
+
+ /* use write-then-read since dma from stack is nonportable */
+ return spi_write_then_read(ds1305->spi, buf, sizeof buf,
+ NULL, 0);
+}
+
+/*
+ * Get/set of alarm is a bit funky:
+ *
+ * - First there's the inherent raciness of getting the (partitioned)
+ * status of an alarm that could trigger while we're reading parts
+ * of that status.
+ *
+ * - Second there's its limited range (we could increase it a bit by
+ * relying on WDAY), which means it will easily roll over.
+ *
+ * - Third there's the choice of two alarms and alarm signals.
+ * Here we use ALM0 and expect that nINT0 (open drain) is used;
+ * that's the only real option for DS1306 runtime alarms, and is
+ * natural on DS1305.
+ *
+ * - Fourth, there's also ALM1, and a second interrupt signal:
+ * + On DS1305 ALM1 uses nINT1 (when INTCN=1) else nINT0;
+ * + On DS1306 ALM1 only uses INT1 (an active high pulse)
+ * and it won't work when VCC1 is active.
+ *
+ * So to be most general, we should probably set both alarms to the
+ * same value, letting ALM1 be the wakeup event source on DS1306
+ * and handling several wiring options on DS1305.
+ *
+ * - Fifth, we support the polled mode (as well as possible; why not?)
+ * even when no interrupt line is wired to an IRQ.
+ */
+
+/*
+ * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl)
+ */
+static int ds1305_get_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+ struct ds1305 *ds1305 = dev_get_drvdata(dev);
+ struct spi_device *spi = ds1305->spi;
+ u8 addr;
+ int status;
+ u8 buf[DS1305_ALM_LEN];
+
+ /* Refresh control register cache BEFORE reading ALM0 registers,
+ * since reading alarm registers acks any pending IRQ. That
+ * makes returning "pending" status a bit of a lie, but that bit
+ * of EFI status is at best fragile anyway (given IRQ handlers).
+ */
+ addr = DS1305_CONTROL;
+ status = spi_write_then_read(spi, &addr, sizeof addr,
+ ds1305->ctrl, sizeof ds1305->ctrl);
+ if (status < 0)
+ return status;
+
+ alm->enabled = !!(ds1305->ctrl[0] & DS1305_AEI0);
+ alm->pending = !!(ds1305->ctrl[1] & DS1305_AEI0);
+
+ /* get and check ALM0 registers */
+ addr = DS1305_ALM0(DS1305_SEC);
+ status = spi_write_then_read(spi, &addr, sizeof addr,
+ buf, sizeof buf);
+ if (status < 0)
+ return status;
+
+ dev_vdbg(dev, "%s: %02x %02x %02x %02x\n",
+ "alm0 read", buf[DS1305_SEC], buf[DS1305_MIN],
+ buf[DS1305_HOUR], buf[DS1305_WDAY]);
+
+ if ((DS1305_ALM_DISABLE & buf[DS1305_SEC])
+ || (DS1305_ALM_DISABLE & buf[DS1305_MIN])
+ || (DS1305_ALM_DISABLE & buf[DS1305_HOUR]))
+ return -EIO;
+
+ /* Stuff these values into alm->time and let RTC framework code
+ * fill in the rest ... and also handle rollover to tomorrow when
+ * that's needed.
+ */
+ alm->time.tm_sec = BCD2BIN(buf[DS1305_SEC]);
+ alm->time.tm_min = BCD2BIN(buf[DS1305_MIN]);
+ alm->time.tm_hour = bcd2hour(buf[DS1305_HOUR]);
+ alm->time.tm_mday = -1;
+ alm->time.tm_mon = -1;
+ alm->time.tm_year = -1;
+ /* next three fields are unused by Linux */
+ alm->time.tm_wday = -1;
+ alm->time.tm_mday = -1;
+ alm->time.tm_isdst = -1;
+
+ return 0;
+}
+
+/*
+ * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl)
+ */
+static int ds1305_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+ struct ds1305 *ds1305 = dev_get_drvdata(dev);
+ struct spi_device *spi = ds1305->spi;
+ unsigned long now, later;
+ struct rtc_time tm;
+ int status;
+ u8 buf[1 + DS1305_ALM_LEN];
+
+ /* convert desired alarm to time_t */
+ status = rtc_tm_to_time(&alm->time, &later);
+ if (status < 0)
+ return status;
+
+ /* Read current time as time_t */
+ status = ds1305_get_time(dev, &tm);
+ if (status < 0)
+ return status;
+ status = rtc_tm_to_time(&tm, &now);
+ if (status < 0)
+ return status;
+
+ /* make sure alarm fires within the next 24 hours */
+ if (later <= now)
+ return -EINVAL;
+ if ((later - now) > 24 * 60 * 60)
+ return -EDOM;
+
+ /* disable alarm if needed */
+ if (ds1305->ctrl[0] & DS1305_AEI0) {
+ ds1305->ctrl[0] &= ~DS1305_AEI0;
+
+ buf[0] = DS1305_WRITE | DS1305_CONTROL;
+ buf[1] = ds1305->ctrl[0];
+ status = spi_write_then_read(ds1305->spi, buf, 2, NULL, 0);
+ if (status < 0)
+ return status;
+ }
+
+ /* write alarm */
+ buf[0] = DS1305_WRITE | DS1305_ALM0(DS1305_SEC);
+ buf[1 + DS1305_SEC] = BIN2BCD(alm->time.tm_sec);
+ buf[1 + DS1305_MIN] = BIN2BCD(alm->time.tm_min);
+ buf[1 + DS1305_HOUR] = hour2bcd(ds1305->hr12, alm->time.tm_hour);
+ buf[1 + DS1305_WDAY] = DS1305_ALM_DISABLE;
+
+ dev_dbg(dev, "%s: %02x %02x %02x %02x\n",
+ "alm0 write", buf[1 + DS1305_SEC], buf[1 + DS1305_MIN],
+ buf[1 + DS1305_HOUR], buf[1 + DS1305_WDAY]);
+
+ status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0);
+ if (status < 0)
+ return status;
+
+ /* enable alarm if requested */
+ if (alm->enabled) {
+ ds1305->ctrl[0] |= DS1305_AEI0;
+
+ buf[0] = DS1305_WRITE | DS1305_CONTROL;
+ buf[1] = ds1305->ctrl[0];
+ status = spi_write_then_read(ds1305->spi, buf, 2, NULL, 0);
+ }
+
+ return status;
+}
+
+#ifdef CONFIG_PROC_FS
+
+static int ds1305_proc(struct device *dev, struct seq_file *seq)
+{
+ struct ds1305 *ds1305 = dev_get_drvdata(dev);
+ char *diodes = "no";
+ char *resistors = "";
+
+ /* ctrl[2] is treated as read-only; no locking needed */
+ if ((ds1305->ctrl[2] & 0xf0) == DS1305_TRICKLE_MAGIC) {
+ switch (ds1305->ctrl[2] & 0x0c) {
+ case DS1305_TRICKLE_DS2:
+ diodes = "2 diodes, ";
+ break;
+ case DS1305_TRICKLE_DS1:
+ diodes = "1 diode, ";
+ break;
+ default:
+ goto done;
+ }
+ switch (ds1305->ctrl[2] & 0x03) {
+ case DS1305_TRICKLE_2K:
+ resistors = "2k Ohm";
+ break;
+ case DS1305_TRICKLE_4K:
+ resistors = "4k Ohm";
+ break;
+ case DS1305_TRICKLE_8K:
+ resistors = "8k Ohm";
+ break;
+ default:
+ diodes = "no";
+ break;
+ }
+ }
+
+done:
+ return seq_printf(seq,
+ "trickle_charge\t: %s%s\n",
+ diodes, resistors);
+}
+
+#else
+#define ds1305_proc NULL
+#endif
+
+static const struct rtc_class_ops ds1305_ops = {
+ .ioctl = ds1305_ioctl,
+ .read_time = ds1305_get_time,
+ .set_time = ds1305_set_time,
+ .read_alarm = ds1305_get_alarm,
+ .set_alarm = ds1305_set_alarm,
+ .proc = ds1305_proc,
+};
+
+static void ds1305_work(struct work_struct *work)
+{
+ struct ds1305 *ds1305 = container_of(work, struct ds1305, work);
+ struct mutex *lock = &ds1305->rtc->ops_lock;
+ struct spi_device *spi = ds1305->spi;
+ u8 buf[3];
+ int status;
+
+ /* lock to protect ds1305->ctrl */
+ mutex_lock(lock);
+
+ /* Disable the IRQ, and clear its status ... for now, we "know"
+ * that if more than one alarm is active, they're in sync.
+ * Note that reading ALM data registers also clears IRQ status.
+ */
+ ds1305->ctrl[0] &= ~(DS1305_AEI1 | DS1305_AEI0);
+ ds1305->ctrl[1] = 0;
+
+ buf[0] = DS1305_WRITE | DS1305_CONTROL;
+ buf[1] = ds1305->ctrl[0];
+ buf[2] = 0;
+
+ status = spi_write_then_read(spi, buf, sizeof buf,
+ NULL, 0);
+ if (status < 0)
+ dev_dbg(&spi->dev, "clear irq --> %d\n", status);
+
+ mutex_unlock(lock);
+
+ if (!test_bit(FLAG_EXITING, &ds1305->flags))
+ enable_irq(spi->irq);
+
+ /* rtc_update_irq() requires an IRQ-disabled context */
+ local_irq_disable();
+ rtc_update_irq(ds1305->rtc, 1, RTC_AF | RTC_IRQF);
+ local_irq_enable();
+}
+
+/*
+ * This "real" IRQ handler hands off to a workqueue mostly to allow
+ * mutex locking for ds1305->ctrl ... unlike I2C, we could issue async
+ * I/O requests in IRQ context (to clear the IRQ status).
+ */
+static irqreturn_t ds1305_irq(int irq, void *p)
+{
+ struct ds1305 *ds1305 = p;
+
+ disable_irq(irq);
+ schedule_work(&ds1305->work);
+ return IRQ_HANDLED;
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Interface for NVRAM
+ */
+
+static void msg_init(struct spi_message *m, struct spi_transfer *x,
+ u8 *addr, size_t count, char *tx, char *rx)
+{
+ spi_message_init(m);
+ memset(x, 0, 2 * sizeof(*x));
+
+ x->tx_buf = addr;
+ x->len = 1;
+ spi_message_add_tail(x, m);
+
+ x++;
+
+ x->tx_buf = tx;
+ x->rx_buf = rx;
+ x->len = count;
+ spi_message_add_tail(x, m);
+}
+
+static ssize_t
+ds1305_nvram_read(struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct spi_device *spi;
+ u8 addr;
+ struct spi_message m;
+ struct spi_transfer x[2];
+ int status;
+
+ spi = container_of(kobj, struct spi_device, dev.kobj);
+
+ if (unlikely(off >= DS1305_NVRAM_LEN))
+ return 0;
+ if (count >= DS1305_NVRAM_LEN)
+ count = DS1305_NVRAM_LEN;
+ if ((off + count) > DS1305_NVRAM_LEN)
+ count = DS1305_NVRAM_LEN - off;
+ if (unlikely(!count))
+ return count;
+
+ addr = DS1305_NVRAM + off;
+ msg_init(&m, x, &addr, count, NULL, buf);
+
+ status = spi_sync(spi, &m);
+ if (status < 0)
+ dev_err(&spi->dev, "nvram %s error %d\n", "read", status);
+ return (status < 0) ? status : count;
+}
+
+static ssize_t
+ds1305_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct spi_device *spi;
+ u8 addr;
+ struct spi_message m;
+ struct spi_transfer x[2];
+ int status;
+
+ spi = container_of(kobj, struct spi_device, dev.kobj);
+
+ if (unlikely(off >= DS1305_NVRAM_LEN))
+ return -EFBIG;
+ if (count >= DS1305_NVRAM_LEN)
+ count = DS1305_NVRAM_LEN;
+ if ((off + count) > DS1305_NVRAM_LEN)
+ count = DS1305_NVRAM_LEN - off;
+ if (unlikely(!count))
+ return count;
+
+ addr = (DS1305_WRITE | DS1305_NVRAM) + off;
+ msg_init(&m, x, &addr, count, buf, NULL);
+
+ status = spi_sync(spi, &m);
+ if (status < 0)
+ dev_err(&spi->dev, "nvram %s error %d\n", "write", status);
+ return (status < 0) ? status : count;
+}
+
+static struct bin_attribute nvram = {
+ .attr.name = "nvram",
+ .attr.mode = S_IRUGO | S_IWUSR,
+ .attr.owner = THIS_MODULE,
+ .read = ds1305_nvram_read,
+ .write = ds1305_nvram_write,
+ .size = DS1305_NVRAM_LEN,
+};
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Interface to SPI stack
+ */
+
+static int __devinit ds1305_probe(struct spi_device *spi)
+{
+ struct ds1305 *ds1305;
+ struct rtc_device *rtc;
+ int status;
+ u8 addr, value;
+ struct ds1305_platform_data *pdata = spi->dev.platform_data;
+ bool write_ctrl = false;
+
+ /* Sanity check board setup data. This may be hooked up
+ * in 3wire mode, but we don't care. Note that unless
+ * there's an inverter in place, this needs SPI_CS_HIGH!
+ */
+ if ((spi->bits_per_word && spi->bits_per_word != 8)
+ || (spi->max_speed_hz > 2000000)
+ || !(spi->mode & SPI_CPHA))
+ return -EINVAL;
+
+ /* set up driver data */
+ ds1305 = kzalloc(sizeof *ds1305, GFP_KERNEL);
+ if (!ds1305)
+ return -ENOMEM;
+ ds1305->spi = spi;
+ spi_set_drvdata(spi, ds1305);
+
+ /* read and cache control registers */
+ addr = DS1305_CONTROL;
+ status = spi_write_then_read(spi, &addr, sizeof addr,
+ ds1305->ctrl, sizeof ds1305->ctrl);
+ if (status < 0) {
+ dev_dbg(&spi->dev, "can't %s, %d\n",
+ "read", status);
+ goto fail0;
+ }
+
+ dev_dbg(&spi->dev, "ctrl %s: %02x %02x %02x\n",
+ "read", ds1305->ctrl[0],
+ ds1305->ctrl[1], ds1305->ctrl[2]);
+
+ /* Sanity check register values ... partially compensating for the
+ * fact that SPI has no device handshake. A pullup on MISO would
+ * make these tests fail; but not all systems will have one. If
+ * some register is neither 0x00 nor 0xff, a chip is likely there.
+ */
+ if ((ds1305->ctrl[0] & 0x38) != 0 || (ds1305->ctrl[1] & 0xfc) != 0) {
+ dev_dbg(&spi->dev, "RTC chip is not present\n");
+ status = -ENODEV;
+ goto fail0;
+ }
+ if (ds1305->ctrl[2] == 0)
+ dev_dbg(&spi->dev, "chip may not be present\n");
+
+ /* enable writes if needed ... if we were paranoid it would
+ * make sense to enable them only when absolutely necessary.
+ */
+ if (ds1305->ctrl[0] & DS1305_WP) {
+ u8 buf[2];
+
+ ds1305->ctrl[0] &= ~DS1305_WP;
+
+ buf[0] = DS1305_WRITE | DS1305_CONTROL;
+ buf[1] = ds1305->ctrl[0];
+ status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0);
+
+ dev_dbg(&spi->dev, "clear WP --> %d\n", status);
+ if (status < 0)
+ goto fail0;
+ }
+
+ /* on DS1305, maybe start oscillator; like most low power
+ * oscillators, it may take a second to stabilize
+ */
+ if (ds1305->ctrl[0] & DS1305_nEOSC) {
+ ds1305->ctrl[0] &= ~DS1305_nEOSC;
+ write_ctrl = true;
+ dev_warn(&spi->dev, "SET TIME!\n");
+ }
+
+ /* ack any pending IRQs */
+ if (ds1305->ctrl[1]) {
+ ds1305->ctrl[1] = 0;
+ write_ctrl = true;
+ }
+
+ /* this may need one-time (re)init */
+ if (pdata) {
+ /* maybe enable trickle charge */
+ if (((ds1305->ctrl[2] & 0xf0) != DS1305_TRICKLE_MAGIC)) {
+ ds1305->ctrl[2] = DS1305_TRICKLE_MAGIC
+ | pdata->trickle;
+ write_ctrl = true;
+ }
+
+ /* on DS1306, configure 1 Hz signal */
+ if (pdata->is_ds1306) {
+ if (pdata->en_1hz) {
+ if (!(ds1305->ctrl[0] & DS1306_1HZ)) {
+ ds1305->ctrl[0] |= DS1306_1HZ;
+ write_ctrl = true;
+ }
+ } else {
+ if (ds1305->ctrl[0] & DS1306_1HZ) {
+ ds1305->ctrl[0] &= ~DS1306_1HZ;
+ write_ctrl = true;
+ }
+ }
+ }
+ }
+
+ if (write_ctrl) {
+ u8 buf[4];
+
+ buf[0] = DS1305_WRITE | DS1305_CONTROL;
+ buf[1] = ds1305->ctrl[0];
+ buf[2] = ds1305->ctrl[1];
+ buf[3] = ds1305->ctrl[2];
+ status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0);
+ if (status < 0) {
+ dev_dbg(&spi->dev, "can't %s, %d\n",
+ "write", status);
+ goto fail0;
+ }
+
+ dev_dbg(&spi->dev, "ctrl %s: %02x %02x %02x\n",
+ "write", ds1305->ctrl[0],
+ ds1305->ctrl[1], ds1305->ctrl[2]);
+ }
+
+ /* see if non-Linux software set up AM/PM mode */
+ addr = DS1305_HOUR;
+ status = spi_write_then_read(spi, &addr, sizeof addr,
+ &value, sizeof value);
+ if (status < 0) {
+ dev_dbg(&spi->dev, "read HOUR --> %d\n", status);
+ goto fail0;
+ }
+
+ ds1305->hr12 = (DS1305_HR_12 & value) != 0;
+ if (ds1305->hr12)
+ dev_dbg(&spi->dev, "AM/PM\n");
+
+ /* register RTC ... from here on, ds1305->ctrl needs locking */
+ rtc = rtc_device_register("ds1305", &spi->dev,
+ &ds1305_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ status = PTR_ERR(rtc);
+ dev_dbg(&spi->dev, "register rtc --> %d\n", status);
+ goto fail0;
+ }
+ ds1305->rtc = rtc;
+
+ /* Maybe set up alarm IRQ; be ready to handle it triggering right
+ * away. NOTE that we don't share this. The signal is active low,
+ * and we can't ack it before a SPI message delay. We temporarily
+ * disable the IRQ until it's acked, which lets us work with more
+ * IRQ trigger modes (not all IRQ controllers can do falling edge).
+ */
+ if (spi->irq) {
+ INIT_WORK(&ds1305->work, ds1305_work);
+ status = request_irq(spi->irq, ds1305_irq,
+ 0, dev_name(&rtc->dev), ds1305);
+ if (status < 0) {
+ dev_dbg(&spi->dev, "request_irq %d --> %d\n",
+ spi->irq, status);
+ goto fail1;
+ }
+ }
+
+ /* export NVRAM */
+ status = sysfs_create_bin_file(&spi->dev.kobj, &nvram);
+ if (status < 0) {
+ dev_dbg(&spi->dev, "register nvram --> %d\n", status);
+ goto fail2;
+ }
+
+ return 0;
+
+fail2:
+ free_irq(spi->irq, ds1305);
+fail1:
+ rtc_device_unregister(rtc);
+fail0:
+ kfree(ds1305);
+ return status;
+}
+
+static int __devexit ds1305_remove(struct spi_device *spi)
+{
+ struct ds1305 *ds1305 = spi_get_drvdata(spi);
+
+ sysfs_remove_bin_file(&spi->dev.kobj, &nvram);
+
+ /* carefully shut down irq and workqueue, if present */
+ if (spi->irq) {
+ set_bit(FLAG_EXITING, &ds1305->flags);
+ free_irq(spi->irq, ds1305);
+ flush_scheduled_work();
+ }
+
+ rtc_device_unregister(ds1305->rtc);
+ spi_set_drvdata(spi, NULL);
+ kfree(ds1305);
+ return 0;
+}
+
+static struct spi_driver ds1305_driver = {
+ .driver.name = "rtc-ds1305",
+ .driver.owner = THIS_MODULE,
+ .probe = ds1305_probe,
+ .remove = __devexit_p(ds1305_remove),
+ /* REVISIT add suspend/resume */
+};
+
+static int __init ds1305_init(void)
+{
+ return spi_register_driver(&ds1305_driver);
+}
+module_init(ds1305_init);
+
+static void __exit ds1305_exit(void)
+{
+ spi_unregister_driver(&ds1305_driver);
+}
+module_exit(ds1305_exit);
+
+MODULE_DESCRIPTION("RTC driver for DS1305 and DS1306 chips");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index 0a19c06019b..24bc1689fc7 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -13,21 +13,21 @@
*
*/
-#include <linux/module.h>
+#include <linux/bcd.h>
+#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/string.h>
-#include <linux/i2c.h>
-#include <linux/rtc.h>
-#include <linux/bcd.h>
#ifdef CONFIG_RTC_DRV_M41T80_WDT
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/reboot.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
+#include <linux/miscdevice.h>
+#include <linux/reboot.h>
+#include <linux/watchdog.h>
#endif
#define M41T80_REG_SSEC 0
@@ -631,14 +631,12 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return -EFAULT;
if (rv & WDIOS_DISABLECARD) {
- printk(KERN_INFO
- "rtc-m41t80: disable watchdog\n");
+ pr_info("rtc-m41t80: disable watchdog\n");
wdt_disable();
}
if (rv & WDIOS_ENABLECARD) {
- printk(KERN_INFO
- "rtc-m41t80: enable watchdog\n");
+ pr_info("rtc-m41t80: enable watchdog\n");
wdt_ping();
}
diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c
new file mode 100644
index 00000000000..9b19499c829
--- /dev/null
+++ b/drivers/rtc/rtc-m41t94.c
@@ -0,0 +1,173 @@
+/*
+ * Driver for ST M41T94 SPI RTC
+ *
+ * Copyright (C) 2008 Kim B. Heino
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/spi/spi.h>
+#include <linux/bcd.h>
+
+#define M41T94_REG_SECONDS 0x01
+#define M41T94_REG_MINUTES 0x02
+#define M41T94_REG_HOURS 0x03
+#define M41T94_REG_WDAY 0x04
+#define M41T94_REG_DAY 0x05
+#define M41T94_REG_MONTH 0x06
+#define M41T94_REG_YEAR 0x07
+#define M41T94_REG_HT 0x0c
+
+#define M41T94_BIT_HALT 0x40
+#define M41T94_BIT_STOP 0x80
+#define M41T94_BIT_CB 0x40
+#define M41T94_BIT_CEB 0x80
+
+static int m41t94_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ u8 buf[8]; /* write cmd + 7 registers */
+
+ dev_dbg(dev, "%s secs=%d, mins=%d, "
+ "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+ "write", tm->tm_sec, tm->tm_min,
+ tm->tm_hour, tm->tm_mday,
+ tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ buf[0] = 0x80 | M41T94_REG_SECONDS; /* write time + date */
+ buf[M41T94_REG_SECONDS] = BIN2BCD(tm->tm_sec);
+ buf[M41T94_REG_MINUTES] = BIN2BCD(tm->tm_min);
+ buf[M41T94_REG_HOURS] = BIN2BCD(tm->tm_hour);
+ buf[M41T94_REG_WDAY] = BIN2BCD(tm->tm_wday + 1);
+ buf[M41T94_REG_DAY] = BIN2BCD(tm->tm_mday);
+ buf[M41T94_REG_MONTH] = BIN2BCD(tm->tm_mon + 1);
+
+ buf[M41T94_REG_HOURS] |= M41T94_BIT_CEB;
+ if (tm->tm_year >= 100)
+ buf[M41T94_REG_HOURS] |= M41T94_BIT_CB;
+ buf[M41T94_REG_YEAR] = BIN2BCD(tm->tm_year % 100);
+
+ return spi_write(spi, buf, 8);
+}
+
+static int m41t94_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ u8 buf[2];
+ int ret, hour;
+
+ /* clear halt update bit */
+ ret = spi_w8r8(spi, M41T94_REG_HT);
+ if (ret < 0)
+ return ret;
+ if (ret & M41T94_BIT_HALT) {
+ buf[0] = 0x80 | M41T94_REG_HT;
+ buf[1] = ret & ~M41T94_BIT_HALT;
+ spi_write(spi, buf, 2);
+ }
+
+ /* clear stop bit */
+ ret = spi_w8r8(spi, M41T94_REG_SECONDS);
+ if (ret < 0)
+ return ret;
+ if (ret & M41T94_BIT_STOP) {
+ buf[0] = 0x80 | M41T94_REG_SECONDS;
+ buf[1] = ret & ~M41T94_BIT_STOP;
+ spi_write(spi, buf, 2);
+ }
+
+ tm->tm_sec = BCD2BIN(spi_w8r8(spi, M41T94_REG_SECONDS));
+ tm->tm_min = BCD2BIN(spi_w8r8(spi, M41T94_REG_MINUTES));
+ hour = spi_w8r8(spi, M41T94_REG_HOURS);
+ tm->tm_hour = BCD2BIN(hour & 0x3f);
+ tm->tm_wday = BCD2BIN(spi_w8r8(spi, M41T94_REG_WDAY)) - 1;
+ tm->tm_mday = BCD2BIN(spi_w8r8(spi, M41T94_REG_DAY));
+ tm->tm_mon = BCD2BIN(spi_w8r8(spi, M41T94_REG_MONTH)) - 1;
+ tm->tm_year = BCD2BIN(spi_w8r8(spi, M41T94_REG_YEAR));
+ if ((hour & M41T94_BIT_CB) || !(hour & M41T94_BIT_CEB))
+ tm->tm_year += 100;
+
+ dev_dbg(dev, "%s secs=%d, mins=%d, "
+ "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+ "read", tm->tm_sec, tm->tm_min,
+ tm->tm_hour, tm->tm_mday,
+ tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ /* initial clock setting can be undefined */
+ return rtc_valid_tm(tm);
+}
+
+static const struct rtc_class_ops m41t94_rtc_ops = {
+ .read_time = m41t94_read_time,
+ .set_time = m41t94_set_time,
+};
+
+static struct spi_driver m41t94_driver;
+
+static int __devinit m41t94_probe(struct spi_device *spi)
+{
+ struct rtc_device *rtc;
+ int res;
+
+ spi->bits_per_word = 8;
+ spi_setup(spi);
+
+ res = spi_w8r8(spi, M41T94_REG_SECONDS);
+ if (res < 0) {
+ dev_err(&spi->dev, "not found.\n");
+ return res;
+ }
+
+ rtc = rtc_device_register(m41t94_driver.driver.name,
+ &spi->dev, &m41t94_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
+
+ dev_set_drvdata(&spi->dev, rtc);
+
+ return 0;
+}
+
+static int __devexit m41t94_remove(struct spi_device *spi)
+{
+ struct rtc_device *rtc = platform_get_drvdata(spi);
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ return 0;
+}
+
+static struct spi_driver m41t94_driver = {
+ .driver = {
+ .name = "rtc-m41t94",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = m41t94_probe,
+ .remove = __devexit_p(m41t94_remove),
+};
+
+static __init int m41t94_init(void)
+{
+ return spi_register_driver(&m41t94_driver);
+}
+
+module_init(m41t94_init);
+
+static __exit void m41t94_exit(void)
+{
+ spi_unregister_driver(&m41t94_driver);
+}
+
+module_exit(m41t94_exit);
+
+MODULE_AUTHOR("Kim B. Heino <Kim.Heino@bluegiga.com>");
+MODULE_DESCRIPTION("Driver for ST M41T94 SPI RTC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index eb23d8423f4..8876605d4d4 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -92,18 +92,6 @@
#define rtc_write(val, addr) omap_writeb(val, OMAP_RTC_BASE + (addr))
-/* platform_bus isn't hotpluggable, so for static linkage it'd be safe
- * to get rid of probe() and remove() code ... too bad the driver struct
- * remembers probe(), that's about 25% of the runtime footprint!!
- */
-#ifndef MODULE
-#undef __devexit
-#undef __devexit_p
-#define __devexit __exit
-#define __devexit_p __exit_p
-#endif
-
-
/* we rely on the rtc framework to handle locking (rtc->ops_lock),
* so the only other requirement is that register accesses which
* require BUSY to be clear are made with IRQs locally disabled
@@ -324,7 +312,7 @@ static struct rtc_class_ops omap_rtc_ops = {
static int omap_rtc_alarm;
static int omap_rtc_timer;
-static int __devinit omap_rtc_probe(struct platform_device *pdev)
+static int __init omap_rtc_probe(struct platform_device *pdev)
{
struct resource *res, *mem;
struct rtc_device *rtc;
@@ -440,7 +428,7 @@ fail:
return -EIO;
}
-static int __devexit omap_rtc_remove(struct platform_device *pdev)
+static int __exit omap_rtc_remove(struct platform_device *pdev)
{
struct rtc_device *rtc = platform_get_drvdata(pdev);;
@@ -498,8 +486,7 @@ static void omap_rtc_shutdown(struct platform_device *pdev)
MODULE_ALIAS("platform:omap_rtc");
static struct platform_driver omap_rtc_driver = {
- .probe = omap_rtc_probe,
- .remove = __devexit_p(omap_rtc_remove),
+ .remove = __exit_p(omap_rtc_remove),
.suspend = omap_rtc_suspend,
.resume = omap_rtc_resume,
.shutdown = omap_rtc_shutdown,
@@ -511,7 +498,7 @@ static struct platform_driver omap_rtc_driver = {
static int __init rtc_init(void)
{
- return platform_driver_register(&omap_rtc_driver);
+ return platform_driver_probe(&omap_rtc_driver, omap_rtc_probe);
}
module_init(rtc_init);
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c
index 3d09d8f0b1f..d388c662bf4 100644
--- a/drivers/rtc/rtc-pcf8583.c
+++ b/drivers/rtc/rtc-pcf8583.c
@@ -2,6 +2,7 @@
* drivers/rtc/rtc-pcf8583.c
*
* Copyright (C) 2000 Russell King
+ * Copyright (C) 2008 Wolfram Sang & Juergen Beisert, Pengutronix
*
* 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
@@ -14,7 +15,6 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/slab.h>
-#include <linux/string.h>
#include <linux/rtc.h>
#include <linux/init.h>
#include <linux/errno.h>
@@ -27,7 +27,6 @@ struct rtc_mem {
};
struct pcf8583 {
- struct i2c_client client;
struct rtc_device *rtc;
unsigned char ctrl;
};
@@ -40,10 +39,6 @@ struct pcf8583 {
#define CTRL_ALARM 0x02
#define CTRL_TIMER 0x01
-static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END };
-
-/* Module parameters */
-I2C_CLIENT_INSMOD;
static struct i2c_driver pcf8583_driver;
@@ -269,106 +264,60 @@ static const struct rtc_class_ops pcf8583_rtc_ops = {
.set_time = pcf8583_rtc_set_time,
};
-static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind);
-
-static int pcf8583_attach(struct i2c_adapter *adap)
-{
- return i2c_probe(adap, &addr_data, pcf8583_probe);
-}
-
-static int pcf8583_detach(struct i2c_client *client)
-{
- int err;
- struct pcf8583 *pcf = i2c_get_clientdata(client);
- struct rtc_device *rtc = pcf->rtc;
-
- if (rtc)
- rtc_device_unregister(rtc);
-
- if ((err = i2c_detach_client(client)))
- return err;
-
- kfree(pcf);
- return 0;
-}
-
-static struct i2c_driver pcf8583_driver = {
- .driver = {
- .name = "pcf8583",
- },
- .id = I2C_DRIVERID_PCF8583,
- .attach_adapter = pcf8583_attach,
- .detach_client = pcf8583_detach,
-};
-
-static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind)
+static int pcf8583_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct pcf8583 *pcf;
- struct i2c_client *client;
- struct rtc_device *rtc;
- unsigned char buf[1], ad[1] = { 0 };
+ struct pcf8583 *pcf8583;
int err;
- struct i2c_msg msgs[2] = {
- {
- .addr = addr,
- .flags = 0,
- .len = 1,
- .buf = ad,
- }, {
- .addr = addr,
- .flags = I2C_M_RD,
- .len = 1,
- .buf = buf,
- }
- };
- if (!i2c_check_functionality(adap, I2C_FUNC_I2C))
- return 0;
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return -ENODEV;
- pcf = kzalloc(sizeof(*pcf), GFP_KERNEL);
- if (!pcf)
+ pcf8583 = kzalloc(sizeof(struct pcf8583), GFP_KERNEL);
+ if (!pcf8583)
return -ENOMEM;
- client = &pcf->client;
+ pcf8583->rtc = rtc_device_register(pcf8583_driver.driver.name,
+ &client->dev, &pcf8583_rtc_ops, THIS_MODULE);
- client->addr = addr;
- client->adapter = adap;
- client->driver = &pcf8583_driver;
-
- strlcpy(client->name, pcf8583_driver.driver.name, I2C_NAME_SIZE);
-
- if (i2c_transfer(client->adapter, msgs, 2) != 2) {
- err = -EIO;
+ if (IS_ERR(pcf8583->rtc)) {
+ err = PTR_ERR(pcf8583->rtc);
goto exit_kfree;
}
- err = i2c_attach_client(client);
-
- if (err)
- goto exit_kfree;
-
- rtc = rtc_device_register(pcf8583_driver.driver.name, &client->dev,
- &pcf8583_rtc_ops, THIS_MODULE);
+ i2c_set_clientdata(client, pcf8583);
+ return 0;
- if (IS_ERR(rtc)) {
- err = PTR_ERR(rtc);
- goto exit_detach;
- }
+exit_kfree:
+ kfree(pcf8583);
+ return err;
+}
- pcf->rtc = rtc;
- i2c_set_clientdata(client, pcf);
- set_ctrl(client, buf[0]);
+static int __devexit pcf8583_remove(struct i2c_client *client)
+{
+ struct pcf8583 *pcf8583 = i2c_get_clientdata(client);
+ if (pcf8583->rtc)
+ rtc_device_unregister(pcf8583->rtc);
+ kfree(pcf8583);
return 0;
+}
-exit_detach:
- i2c_detach_client(client);
-
-exit_kfree:
- kfree(pcf);
+static const struct i2c_device_id pcf8583_id[] = {
+ { "pcf8583", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, pcf8583_id);
- return err;
-}
+static struct i2c_driver pcf8583_driver = {
+ .driver = {
+ .name = "pcf8583",
+ .owner = THIS_MODULE,
+ },
+ .probe = pcf8583_probe,
+ .remove = __devexit_p(pcf8583_remove),
+ .id_table = pcf8583_id,
+};
static __init int pcf8583_init(void)
{
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index fed86e507fd..54b1ebb0150 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -36,10 +36,8 @@ static struct resource *s3c_rtc_mem;
static void __iomem *s3c_rtc_base;
static int s3c_rtc_alarmno = NO_IRQ;
static int s3c_rtc_tickno = NO_IRQ;
-static int s3c_rtc_freq = 1;
static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
-static unsigned int tick_count;
/* IRQ Handlers */
@@ -55,7 +53,7 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
{
struct rtc_device *rdev = id;
- rtc_update_irq(rdev, tick_count++, RTC_PF | RTC_IRQF);
+ rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
return IRQ_HANDLED;
}
@@ -74,35 +72,37 @@ static void s3c_rtc_setaie(int to)
writeb(tmp, s3c_rtc_base + S3C2410_RTCALM);
}
-static void s3c_rtc_setpie(int to)
+static int s3c_rtc_setpie(struct device *dev, int enabled)
{
unsigned int tmp;
- pr_debug("%s: pie=%d\n", __func__, to);
+ pr_debug("%s: pie=%d\n", __func__, enabled);
spin_lock_irq(&s3c_rtc_pie_lock);
tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;
- if (to)
+ if (enabled)
tmp |= S3C2410_TICNT_ENABLE;
writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
spin_unlock_irq(&s3c_rtc_pie_lock);
+
+ return 0;
}
-static void s3c_rtc_setfreq(int freq)
+static int s3c_rtc_setfreq(struct device *dev, int freq)
{
unsigned int tmp;
spin_lock_irq(&s3c_rtc_pie_lock);
- tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE;
-
- s3c_rtc_freq = freq;
+ tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE;
tmp |= (128 / freq)-1;
writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
spin_unlock_irq(&s3c_rtc_pie_lock);
+
+ return 0;
}
/* Time read/write */
@@ -267,12 +267,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
writeb(alrm_en, base + S3C2410_RTCALM);
- if (0) {
- alrm_en = readb(base + S3C2410_RTCALM);
- alrm_en &= ~S3C2410_RTCALM_ALMEN;
- writeb(alrm_en, base + S3C2410_RTCALM);
- disable_irq_wake(s3c_rtc_alarmno);
- }
+ s3c_rtc_setaie(alrm->enabled);
if (alrm->enabled)
enable_irq_wake(s3c_rtc_alarmno);
@@ -282,59 +277,12 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
return 0;
}
-static int s3c_rtc_ioctl(struct device *dev,
- unsigned int cmd, unsigned long arg)
-{
- unsigned int ret = -ENOIOCTLCMD;
-
- switch (cmd) {
- case RTC_AIE_OFF:
- case RTC_AIE_ON:
- s3c_rtc_setaie((cmd == RTC_AIE_ON) ? 1 : 0);
- ret = 0;
- break;
-
- case RTC_PIE_OFF:
- case RTC_PIE_ON:
- tick_count = 0;
- s3c_rtc_setpie((cmd == RTC_PIE_ON) ? 1 : 0);
- ret = 0;
- break;
-
- case RTC_IRQP_READ:
- ret = put_user(s3c_rtc_freq, (unsigned long __user *)arg);
- break;
-
- case RTC_IRQP_SET:
- if (!is_power_of_2(arg)) {
- ret = -EINVAL;
- goto exit;
- }
-
- pr_debug("s3c2410_rtc: setting frequency %ld\n", arg);
-
- s3c_rtc_setfreq(arg);
- ret = 0;
- break;
-
- case RTC_UIE_ON:
- case RTC_UIE_OFF:
- ret = -EINVAL;
- }
-
- exit:
- return ret;
-}
-
static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
{
unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT);
seq_printf(seq, "periodic_IRQ\t: %s\n",
(ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" );
-
- seq_printf(seq, "periodic_freq\t: %d\n", s3c_rtc_freq);
-
return 0;
}
@@ -374,7 +322,7 @@ static void s3c_rtc_release(struct device *dev)
/* do not clear AIE here, it may be needed for wake */
- s3c_rtc_setpie(0);
+ s3c_rtc_setpie(dev, 0);
free_irq(s3c_rtc_alarmno, rtc_dev);
free_irq(s3c_rtc_tickno, rtc_dev);
}
@@ -382,11 +330,12 @@ static void s3c_rtc_release(struct device *dev)
static const struct rtc_class_ops s3c_rtcops = {
.open = s3c_rtc_open,
.release = s3c_rtc_release,
- .ioctl = s3c_rtc_ioctl,
.read_time = s3c_rtc_gettime,
.set_time = s3c_rtc_settime,
.read_alarm = s3c_rtc_getalarm,
.set_alarm = s3c_rtc_setalarm,
+ .irq_set_freq = s3c_rtc_setfreq,
+ .irq_set_state = s3c_rtc_setpie,
.proc = s3c_rtc_proc,
};
@@ -430,14 +379,14 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
}
}
-static int s3c_rtc_remove(struct platform_device *dev)
+static int __devexit s3c_rtc_remove(struct platform_device *dev)
{
struct rtc_device *rtc = platform_get_drvdata(dev);
platform_set_drvdata(dev, NULL);
rtc_device_unregister(rtc);
- s3c_rtc_setpie(0);
+ s3c_rtc_setpie(&dev->dev, 0);
s3c_rtc_setaie(0);
iounmap(s3c_rtc_base);
@@ -447,7 +396,7 @@ static int s3c_rtc_remove(struct platform_device *dev)
return 0;
}
-static int s3c_rtc_probe(struct platform_device *pdev)
+static int __devinit s3c_rtc_probe(struct platform_device *pdev)
{
struct rtc_device *rtc;
struct resource *res;
@@ -504,7 +453,7 @@ static int s3c_rtc_probe(struct platform_device *pdev)
pr_debug("s3c2410_rtc: RTCCON=%02x\n",
readb(s3c_rtc_base + S3C2410_RTCCON));
- s3c_rtc_setfreq(s3c_rtc_freq);
+ s3c_rtc_setfreq(&pdev->dev, 1);
/* register RTC and exit */
@@ -560,7 +509,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
static struct platform_driver s3c2410_rtcdrv = {
.probe = s3c_rtc_probe,
- .remove = s3c_rtc_remove,
+ .remove = __devexit_p(s3c_rtc_remove),
.suspend = s3c_rtc_suspend,
.resume = s3c_rtc_resume,
.driver = {
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
index be9c70d0b19..884b635f028 100644
--- a/drivers/rtc/rtc-vr41xx.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -1,7 +1,7 @@
/*
* Driver for NEC VR4100 series Real Time Clock unit.
*
- * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* 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
@@ -34,7 +34,7 @@
MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
/* RTC 1 registers */
#define ETIMELREG 0x00
@@ -82,7 +82,6 @@ static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */
static DEFINE_SPINLOCK(rtc_lock);
static char rtc_name[] = "RTC";
-static unsigned long periodic_frequency;
static unsigned long periodic_count;
static unsigned int alarm_enabled;
static int aie_irq = -1;
@@ -207,10 +206,37 @@ static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
return 0;
}
-static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+static int vr41xx_rtc_irq_set_freq(struct device *dev, int freq)
{
unsigned long count;
+ count = RTC_FREQUENCY;
+ do_div(count, freq);
+
+ periodic_count = count;
+
+ spin_lock_irq(&rtc_lock);
+
+ rtc1_write(RTCL1LREG, count);
+ rtc1_write(RTCL1HREG, count >> 16);
+
+ spin_unlock_irq(&rtc_lock);
+
+ return 0;
+}
+
+static int vr41xx_rtc_irq_set_state(struct device *dev, int enabled)
+{
+ if (enabled)
+ enable_irq(pie_irq);
+ else
+ disable_irq(pie_irq);
+
+ return 0;
+}
+
+static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
switch (cmd) {
case RTC_AIE_ON:
spin_lock_irq(&rtc_lock);
@@ -232,33 +258,6 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long
spin_unlock_irq(&rtc_lock);
break;
- case RTC_PIE_ON:
- enable_irq(pie_irq);
- break;
- case RTC_PIE_OFF:
- disable_irq(pie_irq);
- break;
- case RTC_IRQP_READ:
- return put_user(periodic_frequency, (unsigned long __user *)arg);
- break;
- case RTC_IRQP_SET:
- if (arg > MAX_PERIODIC_RATE)
- return -EINVAL;
-
- periodic_frequency = arg;
-
- count = RTC_FREQUENCY;
- do_div(count, arg);
-
- periodic_count = count;
-
- spin_lock_irq(&rtc_lock);
-
- rtc1_write(RTCL1LREG, count);
- rtc1_write(RTCL1HREG, count >> 16);
-
- spin_unlock_irq(&rtc_lock);
- break;
case RTC_EPOCH_READ:
return put_user(epoch, (unsigned long __user *)arg);
case RTC_EPOCH_SET:
@@ -309,6 +308,8 @@ static const struct rtc_class_ops vr41xx_rtc_ops = {
.set_time = vr41xx_rtc_set_time,
.read_alarm = vr41xx_rtc_read_alarm,
.set_alarm = vr41xx_rtc_set_alarm,
+ .irq_set_freq = vr41xx_rtc_irq_set_freq,
+ .irq_set_state = vr41xx_rtc_irq_set_state,
};
static int __devinit rtc_probe(struct platform_device *pdev)
@@ -346,6 +347,8 @@ static int __devinit rtc_probe(struct platform_device *pdev)
goto err_iounmap_all;
}
+ rtc->max_user_freq = MAX_PERIODIC_RATE;
+
spin_lock_irq(&rtc_lock);
rtc1_write(ECMPLREG, 0);
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 81a96e01908..c3dee900a5c 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -1168,17 +1168,19 @@ static int raw3270_create_attributes(struct raw3270 *rp)
if (rc)
goto out;
- rp->clttydev = device_create(class3270, &rp->cdev->dev,
- MKDEV(IBM_TTY3270_MAJOR, rp->minor),
- "tty%s", rp->cdev->dev.bus_id);
+ rp->clttydev = device_create_drvdata(class3270, &rp->cdev->dev,
+ MKDEV(IBM_TTY3270_MAJOR, rp->minor),
+ NULL,
+ "tty%s", rp->cdev->dev.bus_id);
if (IS_ERR(rp->clttydev)) {
rc = PTR_ERR(rp->clttydev);
goto out_ttydev;
}
- rp->cltubdev = device_create(class3270, &rp->cdev->dev,
- MKDEV(IBM_FS3270_MAJOR, rp->minor),
- "tub%s", rp->cdev->dev.bus_id);
+ rp->cltubdev = device_create_drvdata(class3270, &rp->cdev->dev,
+ MKDEV(IBM_FS3270_MAJOR, rp->minor),
+ NULL,
+ "tub%s", rp->cdev->dev.bus_id);
if (!IS_ERR(rp->cltubdev))
goto out;
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index 6dfdb7c1798..12c2a5aaf31 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -69,10 +69,9 @@ struct tape_class_device *register_tape_dev(
if (rc)
goto fail_with_cdev;
- tcd->class_device = device_create(tape_class, device,
- tcd->char_device->dev,
- "%s", tcd->device_name
- );
+ tcd->class_device = device_create_drvdata(tape_class, device,
+ tcd->char_device->dev,
+ NULL, "%s", tcd->device_name);
rc = IS_ERR(tcd->class_device) ? PTR_ERR(tcd->class_device) : 0;
if (rc)
goto fail_with_cdev;
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index b0ac44b2712..c1f352b8486 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -896,8 +896,9 @@ static int ur_set_online(struct ccw_device *cdev)
goto fail_free_cdev;
}
- urd->device = device_create(vmur_class, NULL, urd->char_device->dev,
- "%s", node_id);
+ urd->device = device_create_drvdata(vmur_class, NULL,
+ urd->char_device->dev, NULL,
+ "%s", node_id);
if (IS_ERR(urd->device)) {
rc = PTR_ERR(urd->device);
TRACE("ur_set_online: device_create rc=%d\n", rc);
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
index 5ab34340919..79954bd6bfa 100644
--- a/drivers/s390/kvm/kvm_virtio.c
+++ b/drivers/s390/kvm/kvm_virtio.c
@@ -15,6 +15,7 @@
#include <linux/err.h>
#include <linux/virtio.h>
#include <linux/virtio_config.h>
+#include <linux/virtio_console.h>
#include <linux/interrupt.h>
#include <linux/virtio_ring.h>
#include <linux/pfn.h>
@@ -87,16 +88,20 @@ static u32 kvm_get_features(struct virtio_device *vdev)
return features;
}
-static void kvm_set_features(struct virtio_device *vdev, u32 features)
+static void kvm_finalize_features(struct virtio_device *vdev)
{
- unsigned int i;
+ unsigned int i, bits;
struct kvm_device_desc *desc = to_kvmdev(vdev)->desc;
/* Second half of bitmap is features we accept. */
u8 *out_features = kvm_vq_features(desc) + desc->feature_len;
+ /* Give virtio_ring a chance to accept features. */
+ vring_transport_features(vdev);
+
memset(out_features, 0, desc->feature_len);
- for (i = 0; i < min(desc->feature_len * 8, 32); i++) {
- if (features & (1 << i))
+ bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8;
+ for (i = 0; i < bits; i++) {
+ if (test_bit(i, vdev->features))
out_features[i / 8] |= (1 << (i % 8));
}
}
@@ -222,7 +227,7 @@ static void kvm_del_vq(struct virtqueue *vq)
*/
static struct virtio_config_ops kvm_vq_configspace_ops = {
.get_features = kvm_get_features,
- .set_features = kvm_set_features,
+ .finalize_features = kvm_finalize_features,
.get = kvm_get,
.set = kvm_set,
.get_status = kvm_get_status,
@@ -333,6 +338,25 @@ static int __init kvm_devices_init(void)
return 0;
}
+/* code for early console output with virtio_console */
+static __init int early_put_chars(u32 vtermno, const char *buf, int count)
+{
+ char scratch[17];
+ unsigned int len = count;
+
+ if (len > sizeof(scratch) - 1)
+ len = sizeof(scratch) - 1;
+ scratch[len] = '\0';
+ memcpy(scratch, buf, len);
+ kvm_hypercall1(KVM_S390_VIRTIO_NOTIFY, __pa(scratch));
+ return len;
+}
+
+void s390_virtio_console_init(void)
+{
+ virtio_cons_early_init(early_put_chars);
+}
+
/*
* We do this after core stuff, but before the drivers.
*/
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index c644669a75c..a08b1682c8e 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -58,13 +58,13 @@
* 1.10 Changes for Buffer allocation
* 1.15 Changed for 2.6 Kernel No longer compiles on 2.4 or lower
* 1.25 Added Packing support
+ * 1.5
*/
#include <asm/ccwdev.h>
#include <asm/ccwgroup.h>
#include <asm/debug.h>
#include <asm/idals.h>
#include <asm/io.h>
-
#include <linux/bitops.h>
#include <linux/ctype.h>
#include <linux/delay.h>
@@ -90,36 +90,10 @@
#include "cu3088.h"
#include "claw.h"
-MODULE_AUTHOR("Andy Richter <richtera@us.ibm.com>");
-MODULE_DESCRIPTION("Linux for zSeries CLAW Driver\n" \
- "Copyright 2000,2005 IBM Corporation\n");
-MODULE_LICENSE("GPL");
-
-/* Debugging is based on DEBUGMSG, IOTRACE, or FUNCTRACE options:
- DEBUGMSG - Enables output of various debug messages in the code
- IOTRACE - Enables output of CCW and other IO related traces
- FUNCTRACE - Enables output of function entry/exit trace
- Define any combination of above options to enable tracing
-
- CLAW also uses the s390dbf file system see claw_trace and claw_setup
+/*
+ CLAW uses the s390dbf file system see claw_trace and claw_setup
*/
-/* following enables tracing */
-//#define DEBUGMSG
-//#define IOTRACE
-//#define FUNCTRACE
-
-#ifdef DEBUGMSG
-#define DEBUG
-#endif
-
-#ifdef IOTRACE
-#define DEBUG
-#endif
-
-#ifdef FUNCTRACE
-#define DEBUG
-#endif
static char debug_buffer[255];
/**
@@ -146,7 +120,6 @@ claw_register_debug_facility(void)
claw_dbf_setup = debug_register("claw_setup", 2, 1, 8);
claw_dbf_trace = debug_register("claw_trace", 2, 2, 8);
if (claw_dbf_setup == NULL || claw_dbf_trace == NULL) {
- printk(KERN_WARNING "Not enough memory for debug facility.\n");
claw_unregister_debug_facility();
return -ENOMEM;
}
@@ -232,9 +205,6 @@ static void probe_error( struct ccwgroup_device *cgdev);
static struct net_device_stats *claw_stats(struct net_device *dev);
static int pages_to_order_of_mag(int num_of_pages);
static struct sk_buff *claw_pack_skb(struct claw_privbk *privptr);
-#ifdef DEBUG
-static void dumpit (char *buf, int len);
-#endif
/* sysfs Functions */
static ssize_t claw_hname_show(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t claw_hname_write(struct device *dev, struct device_attribute *attr,
@@ -263,12 +233,12 @@ static int claw_snd_disc(struct net_device *dev, struct clawctl * p_ctl);
static int claw_snd_sys_validate_rsp(struct net_device *dev,
struct clawctl * p_ctl, __u32 return_code);
static int claw_strt_conn_req(struct net_device *dev );
-static void claw_strt_read ( struct net_device *dev, int lock );
-static void claw_strt_out_IO( struct net_device *dev );
-static void claw_free_wrt_buf( struct net_device *dev );
+static void claw_strt_read(struct net_device *dev, int lock);
+static void claw_strt_out_IO(struct net_device *dev);
+static void claw_free_wrt_buf(struct net_device *dev);
/* Functions for unpack reads */
-static void unpack_read (struct net_device *dev );
+static void unpack_read(struct net_device *dev);
/* ccwgroup table */
@@ -284,7 +254,6 @@ static struct ccwgroup_driver claw_group_driver = {
};
/*
-*
* Key functions
*/
@@ -298,23 +267,14 @@ claw_probe(struct ccwgroup_device *cgdev)
int rc;
struct claw_privbk *privptr=NULL;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s Enter\n",__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"probe");
+ CLAW_DBF_TEXT(2, setup, "probe");
if (!get_device(&cgdev->dev))
return -ENODEV;
-#ifdef DEBUGMSG
- printk(KERN_INFO "claw: variable cgdev =\n");
- dumpit((char *)cgdev, sizeof(struct ccwgroup_device));
-#endif
privptr = kzalloc(sizeof(struct claw_privbk), GFP_KERNEL);
if (privptr == NULL) {
probe_error(cgdev);
put_device(&cgdev->dev);
- printk(KERN_WARNING "Out of memory %s %s Exit Line %d \n",
- cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
- CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM);
+ CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM);
return -ENOMEM;
}
privptr->p_mtc_envelope= kzalloc( MAX_ENVELOPE_SIZE, GFP_KERNEL);
@@ -322,9 +282,7 @@ claw_probe(struct ccwgroup_device *cgdev)
if ((privptr->p_mtc_envelope==NULL) || (privptr->p_env==NULL)) {
probe_error(cgdev);
put_device(&cgdev->dev);
- printk(KERN_WARNING "Out of memory %s %s Exit Line %d \n",
- cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
- CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM);
+ CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM);
return -ENOMEM;
}
memcpy(privptr->p_env->adapter_name,WS_NAME_NOT_DEF,8);
@@ -341,19 +299,14 @@ claw_probe(struct ccwgroup_device *cgdev)
put_device(&cgdev->dev);
printk(KERN_WARNING "add_files failed %s %s Exit Line %d \n",
cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
- CLAW_DBF_TEXT_(2,setup,"probex%d",rc);
+ CLAW_DBF_TEXT_(2, setup, "probex%d", rc);
return rc;
}
- printk(KERN_INFO "claw: sysfs files added for %s\n",cgdev->cdev[0]->dev.bus_id);
privptr->p_env->p_priv = privptr;
cgdev->cdev[0]->handler = claw_irq_handler;
cgdev->cdev[1]->handler = claw_irq_handler;
cgdev->dev.driver_data = privptr;
-#ifdef FUNCTRACE
- printk(KERN_INFO "claw:%s exit on line %d, "
- "rc = 0\n",__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(2,setup,"prbext 0");
+ CLAW_DBF_TEXT(2, setup, "prbext 0");
return 0;
} /* end of claw_probe */
@@ -370,37 +323,18 @@ claw_tx(struct sk_buff *skb, struct net_device *dev)
unsigned long saveflags;
struct chbk *p_ch;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s enter\n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"claw_tx");
+ CLAW_DBF_TEXT(4, trace, "claw_tx");
p_ch=&privptr->channel[WRITE];
if (skb == NULL) {
- printk(KERN_WARNING "%s: null pointer passed as sk_buffer\n",
- dev->name);
privptr->stats.tx_dropped++;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() exit on line %d, rc = EIO\n",
- dev->name,__func__, __LINE__);
-#endif
- CLAW_DBF_TEXT_(2,trace,"clawtx%d",-EIO);
+ privptr->stats.tx_errors++;
+ CLAW_DBF_TEXT_(2, trace, "clawtx%d", -EIO);
return -EIO;
}
-
-#ifdef IOTRACE
- printk(KERN_INFO "%s: variable sk_buff=\n",dev->name);
- dumpit((char *) skb, sizeof(struct sk_buff));
- printk(KERN_INFO "%s: variable dev=\n",dev->name);
- dumpit((char *) dev, sizeof(struct net_device));
-#endif
spin_lock_irqsave(get_ccwdev_lock(p_ch->cdev), saveflags);
rc=claw_hw_tx( skb, dev, 1 );
spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s exit on line %d, rc = %d\n",
- dev->name, __func__, __LINE__, rc);
-#endif
- CLAW_DBF_TEXT_(4,trace,"clawtx%d",rc);
+ CLAW_DBF_TEXT_(4, trace, "clawtx%d", rc);
return rc;
} /* end of claw_tx */
@@ -419,7 +353,7 @@ claw_pack_skb(struct claw_privbk *privptr)
new_skb = NULL; /* assume no dice */
pkt_cnt = 0;
- CLAW_DBF_TEXT(4,trace,"PackSKBe");
+ CLAW_DBF_TEXT(4, trace, "PackSKBe");
if (!skb_queue_empty(&p_ch->collect_queue)) {
/* some data */
held_skb = skb_dequeue(&p_ch->collect_queue);
@@ -457,13 +391,8 @@ claw_pack_skb(struct claw_privbk *privptr)
skb_queue_head(&p_ch->collect_queue,held_skb);
}
}
-#ifdef IOTRACE
- printk(KERN_INFO "%s: %s() Packed %d len %d\n",
- p_env->ndev->name,
- __func__,pkt_cnt,new_skb->len);
-#endif
}
- CLAW_DBF_TEXT(4,trace,"PackSKBx");
+ CLAW_DBF_TEXT(4, trace, "PackSKBx");
return new_skb;
}
@@ -477,29 +406,12 @@ claw_change_mtu(struct net_device *dev, int new_mtu)
{
struct claw_privbk *privptr=dev->priv;
int buff_size;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
-#endif
-#ifdef DEBUGMSG
- printk(KERN_INFO "variable dev =\n");
- dumpit((char *) dev, sizeof(struct net_device));
- printk(KERN_INFO "variable new_mtu = %d\n", new_mtu);
-#endif
- CLAW_DBF_TEXT(4,trace,"setmtu");
+ CLAW_DBF_TEXT(4, trace, "setmtu");
buff_size = privptr->p_env->write_size;
if ((new_mtu < 60) || (new_mtu > buff_size)) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d, rc=EINVAL\n",
- dev->name,
- __func__, __LINE__);
-#endif
return -EINVAL;
}
dev->mtu = new_mtu;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",dev->name,
- __func__, __LINE__);
-#endif
return 0;
} /* end of claw_change_mtu */
@@ -521,24 +433,13 @@ claw_open(struct net_device *dev)
struct timer_list timer;
struct ccwbk *p_buf;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"open");
- if (!dev || (dev->name[0] == 0x00)) {
- CLAW_DBF_TEXT(2,trace,"BadDev");
- printk(KERN_WARNING "claw: Bad device at open failing \n");
- return -ENODEV;
- }
+ CLAW_DBF_TEXT(4, trace, "open");
privptr = (struct claw_privbk *)dev->priv;
/* allocate and initialize CCW blocks */
if (privptr->buffs_alloc == 0) {
rc=init_ccw_bk(dev);
if (rc) {
- printk(KERN_INFO "%s:%s Exit on line %d, rc=ENOMEM\n",
- dev->name,
- __func__, __LINE__);
- CLAW_DBF_TEXT(2,trace,"openmem");
+ CLAW_DBF_TEXT(2, trace, "openmem");
return -ENOMEM;
}
}
@@ -557,7 +458,7 @@ claw_open(struct net_device *dev)
tasklet_init(&privptr->channel[READ].tasklet, claw_irq_tasklet,
(unsigned long) &privptr->channel[READ]);
for ( i = 0; i < 2; i++) {
- CLAW_DBF_TEXT_(2,trace,"opn_ch%d",i);
+ CLAW_DBF_TEXT_(2, trace, "opn_ch%d", i);
init_waitqueue_head(&privptr->channel[i].wait);
/* skb_queue_head_init(&p_ch->io_queue); */
if (i == WRITE)
@@ -595,15 +496,8 @@ claw_open(struct net_device *dev)
~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) ||
(((privptr->channel[READ].flag |
privptr->channel[WRITE].flag) & CLAW_TIMER) != 0x00)) {
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: channel problems during open - read:"
- " %02x - write: %02x\n",
- dev->name,
- privptr->channel[READ].last_dstat,
- privptr->channel[WRITE].last_dstat);
-#endif
printk(KERN_INFO "%s: remote side is not ready\n", dev->name);
- CLAW_DBF_TEXT(2,trace,"notrdy");
+ CLAW_DBF_TEXT(2, trace, "notrdy");
for ( i = 0; i < 2; i++) {
spin_lock_irqsave(
@@ -659,23 +553,14 @@ claw_open(struct net_device *dev)
privptr->p_buff_read=NULL;
privptr->p_buff_write=NULL;
claw_clear_busy(dev);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d, rc=EIO\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(2,trace,"open EIO");
+ CLAW_DBF_TEXT(2, trace, "open EIO");
return -EIO;
}
/* Send SystemValidate command */
claw_clear_busy(dev);
-
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d, rc=0\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"openok");
+ CLAW_DBF_TEXT(4, trace, "openok");
return 0;
} /* end of claw_open */
@@ -694,22 +579,14 @@ claw_irq_handler(struct ccw_device *cdev,
struct claw_env *p_env;
struct chbk *p_ch_r=NULL;
-
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s enter \n",__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"clawirq");
+ CLAW_DBF_TEXT(4, trace, "clawirq");
/* Bypass all 'unsolicited interrupts' */
if (!cdev->dev.driver_data) {
printk(KERN_WARNING "claw: unsolicited interrupt for device:"
"%s received c-%02x d-%02x\n",
cdev->dev.bus_id, irb->scsw.cmd.cstat,
irb->scsw.cmd.dstat);
-#ifdef FUNCTRACE
- printk(KERN_INFO "claw: %s() "
- "exit on line %d\n",__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(2,trace,"badirq");
+ CLAW_DBF_TEXT(2, trace, "badirq");
return;
}
privptr = (struct claw_privbk *)cdev->dev.driver_data;
@@ -722,41 +599,25 @@ claw_irq_handler(struct ccw_device *cdev,
else {
printk(KERN_WARNING "claw: Can't determine channel for "
"interrupt, device %s\n", cdev->dev.bus_id);
- CLAW_DBF_TEXT(2,trace,"badchan");
+ CLAW_DBF_TEXT(2, trace, "badchan");
return;
}
- CLAW_DBF_TEXT_(4,trace,"IRQCH=%d",p_ch->flag);
+ CLAW_DBF_TEXT_(4, trace, "IRQCH=%d", p_ch->flag);
dev = (struct net_device *) (p_ch->ndev);
p_env=privptr->p_env;
-#ifdef IOTRACE
- printk(KERN_INFO "%s: interrupt for device: %04x "
- "received c-%02x d-%02x state-%02x\n",
- dev->name, p_ch->devno, irb->scsw.cmd.cstat,
- irb->scsw.cmd.dstat, p_ch->claw_state);
-#endif
-
/* Copy interruption response block. */
memcpy(p_ch->irb, irb, sizeof(struct irb));
- /* Check for good subchannel return code, otherwise error message */
+ /* Check for good subchannel return code, otherwise info message */
if (irb->scsw.cmd.cstat && !(irb->scsw.cmd.cstat & SCHN_STAT_PCI)) {
printk(KERN_INFO "%s: subchannel check for device: %04x -"
" Sch Stat %02x Dev Stat %02x CPA - %04x\n",
dev->name, p_ch->devno,
irb->scsw.cmd.cstat, irb->scsw.cmd.dstat,
irb->scsw.cmd.cpa);
-#ifdef IOTRACE
- dumpit((char *)irb,sizeof(struct irb));
- dumpit((char *)(unsigned long)irb->scsw.cmd.cpa,
- sizeof(struct ccw1));
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(2,trace,"chanchk");
+ CLAW_DBF_TEXT(2, trace, "chanchk");
/* return; */
}
@@ -768,233 +629,138 @@ claw_irq_handler(struct ccw_device *cdev,
p_ch->last_dstat = irb->scsw.cmd.dstat;
switch (p_ch->claw_state) {
- case CLAW_STOP:/* HALT_IO by claw_release (halt sequence) */
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: CLAW_STOP enter\n", dev->name);
-#endif
- if (!((p_ch->irb->scsw.cmd.stctl &
- SCSW_STCTL_SEC_STATUS) ||
- (p_ch->irb->scsw.cmd.stctl ==
- SCSW_STCTL_STATUS_PEND) ||
- (p_ch->irb->scsw.cmd.stctl ==
- (SCSW_STCTL_ALERT_STATUS |
- SCSW_STCTL_STATUS_PEND)))) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- return;
- }
- wake_up(&p_ch->wait); /* wake up claw_release */
-
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: CLAW_STOP exit\n", dev->name);
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"stop");
- return;
-
- case CLAW_START_HALT_IO: /* HALT_IO issued by claw_open */
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: process CLAW_STAT_HALT_IO\n",
- dev->name);
-#endif
- if (!((p_ch->irb->scsw.cmd.stctl &
- SCSW_STCTL_SEC_STATUS) ||
- (p_ch->irb->scsw.cmd.stctl ==
- SCSW_STCTL_STATUS_PEND) ||
- (p_ch->irb->scsw.cmd.stctl ==
- (SCSW_STCTL_ALERT_STATUS |
- SCSW_STCTL_STATUS_PEND)))) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"haltio");
- return;
- }
- if (p_ch->flag == CLAW_READ) {
- p_ch->claw_state = CLAW_START_READ;
- wake_up(&p_ch->wait); /* wake claw_open (READ)*/
- }
+ case CLAW_STOP:/* HALT_IO by claw_release (halt sequence) */
+ if (!((p_ch->irb->scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS) ||
+ (p_ch->irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND) ||
+ (p_ch->irb->scsw.cmd.stctl ==
+ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND))))
+ return;
+ wake_up(&p_ch->wait); /* wake up claw_release */
+ CLAW_DBF_TEXT(4, trace, "stop");
+ return;
+ case CLAW_START_HALT_IO: /* HALT_IO issued by claw_open */
+ if (!((p_ch->irb->scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS) ||
+ (p_ch->irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND) ||
+ (p_ch->irb->scsw.cmd.stctl ==
+ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+ CLAW_DBF_TEXT(4, trace, "haltio");
+ return;
+ }
+ if (p_ch->flag == CLAW_READ) {
+ p_ch->claw_state = CLAW_START_READ;
+ wake_up(&p_ch->wait); /* wake claw_open (READ)*/
+ } else if (p_ch->flag == CLAW_WRITE) {
+ p_ch->claw_state = CLAW_START_WRITE;
+ /* send SYSTEM_VALIDATE */
+ claw_strt_read(dev, LOCK_NO);
+ claw_send_control(dev,
+ SYSTEM_VALIDATE_REQUEST,
+ 0, 0, 0,
+ p_env->host_name,
+ p_env->adapter_name);
+ } else {
+ printk(KERN_WARNING "claw: unsolicited "
+ "interrupt for device:"
+ "%s received c-%02x d-%02x\n",
+ cdev->dev.bus_id,
+ irb->scsw.cmd.cstat,
+ irb->scsw.cmd.dstat);
+ return;
+ }
+ CLAW_DBF_TEXT(4, trace, "haltio");
+ return;
+ case CLAW_START_READ:
+ CLAW_DBF_TEXT(4, trace, "ReadIRQ");
+ if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
+ clear_bit(0, (void *)&p_ch->IO_active);
+ if ((p_ch->irb->ecw[0] & 0x41) == 0x41 ||
+ (p_ch->irb->ecw[0] & 0x40) == 0x40 ||
+ (p_ch->irb->ecw[0]) == 0) {
+ privptr->stats.rx_errors++;
+ printk(KERN_INFO "%s: Restart is "
+ "required after remote "
+ "side recovers \n",
+ dev->name);
+ }
+ CLAW_DBF_TEXT(4, trace, "notrdy");
+ return;
+ }
+ if ((p_ch->irb->scsw.cmd.cstat & SCHN_STAT_PCI) &&
+ (p_ch->irb->scsw.cmd.dstat == 0)) {
+ if (test_and_set_bit(CLAW_BH_ACTIVE,
+ (void *)&p_ch->flag_a) == 0)
+ tasklet_schedule(&p_ch->tasklet);
else
- if (p_ch->flag == CLAW_WRITE) {
- p_ch->claw_state = CLAW_START_WRITE;
- /* send SYSTEM_VALIDATE */
- claw_strt_read(dev, LOCK_NO);
- claw_send_control(dev,
- SYSTEM_VALIDATE_REQUEST,
- 0, 0, 0,
- p_env->host_name,
- p_env->adapter_name );
- } else {
- printk(KERN_WARNING "claw: unsolicited "
- "interrupt for device:"
- "%s received c-%02x d-%02x\n",
- cdev->dev.bus_id,
- irb->scsw.cmd.cstat,
- irb->scsw.cmd.dstat);
- return;
- }
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: process CLAW_STAT_HALT_IO exit\n",
- dev->name);
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"haltio");
- return;
- case CLAW_START_READ:
- CLAW_DBF_TEXT(4,trace,"ReadIRQ");
- if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
- clear_bit(0, (void *)&p_ch->IO_active);
- if ((p_ch->irb->ecw[0] & 0x41) == 0x41 ||
- (p_ch->irb->ecw[0] & 0x40) == 0x40 ||
- (p_ch->irb->ecw[0]) == 0)
- {
- privptr->stats.rx_errors++;
- printk(KERN_INFO "%s: Restart is "
- "required after remote "
- "side recovers \n",
- dev->name);
- }
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"notrdy");
- return;
- }
- if ((p_ch->irb->scsw.cmd.cstat & SCHN_STAT_PCI) &&
- (p_ch->irb->scsw.cmd.dstat == 0)) {
- if (test_and_set_bit(CLAW_BH_ACTIVE,
- (void *)&p_ch->flag_a) == 0) {
- tasklet_schedule(&p_ch->tasklet);
- }
- else {
- CLAW_DBF_TEXT(4,trace,"PCINoBH");
- }
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"PCI_read");
- return;
- }
- if (!((p_ch->irb->scsw.cmd.stctl &
- SCSW_STCTL_SEC_STATUS) ||
- (p_ch->irb->scsw.cmd.stctl ==
- SCSW_STCTL_STATUS_PEND) ||
- (p_ch->irb->scsw.cmd.stctl ==
- (SCSW_STCTL_ALERT_STATUS |
- SCSW_STCTL_STATUS_PEND)))) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"SPend_rd");
- return;
- }
- clear_bit(0, (void *)&p_ch->IO_active);
- claw_clearbit_busy(TB_RETRY,dev);
- if (test_and_set_bit(CLAW_BH_ACTIVE,
- (void *)&p_ch->flag_a) == 0) {
- tasklet_schedule(&p_ch->tasklet);
- }
- else {
- CLAW_DBF_TEXT(4,trace,"RdBHAct");
- }
-
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: process CLAW_START_READ exit\n",
- dev->name);
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"RdIRQXit");
- return;
- case CLAW_START_WRITE:
- if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
- printk(KERN_INFO "%s: Unit Check Occured in "
- "write channel\n",dev->name);
- clear_bit(0, (void *)&p_ch->IO_active);
- if (p_ch->irb->ecw[0] & 0x80 ) {
- printk(KERN_INFO "%s: Resetting Event "
- "occurred:\n",dev->name);
- init_timer(&p_ch->timer);
- p_ch->timer.function =
- (void *)claw_write_retry;
- p_ch->timer.data = (unsigned long)p_ch;
- p_ch->timer.expires = jiffies + 10*HZ;
- add_timer(&p_ch->timer);
- printk(KERN_INFO "%s: write connection "
- "restarting\n",dev->name);
- }
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"rstrtwrt");
- return;
- }
- if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) {
- clear_bit(0, (void *)&p_ch->IO_active);
- printk(KERN_INFO "%s: Unit Exception "
- "Occured in write channel\n",
- dev->name);
- }
- if (!((p_ch->irb->scsw.cmd.stctl &
- SCSW_STCTL_SEC_STATUS) ||
- (p_ch->irb->scsw.cmd.stctl ==
- SCSW_STCTL_STATUS_PEND) ||
- (p_ch->irb->scsw.cmd.stctl ==
- (SCSW_STCTL_ALERT_STATUS |
- SCSW_STCTL_STATUS_PEND)))) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"writeUE");
- return;
- }
- clear_bit(0, (void *)&p_ch->IO_active);
- if (claw_test_and_setbit_busy(TB_TX,dev)==0) {
- claw_write_next(p_ch);
- claw_clearbit_busy(TB_TX,dev);
- claw_clear_busy(dev);
- }
- p_ch_r=(struct chbk *)&privptr->channel[READ];
- if (test_and_set_bit(CLAW_BH_ACTIVE,
- (void *)&p_ch_r->flag_a) == 0) {
- tasklet_schedule(&p_ch_r->tasklet);
- }
-
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: process CLAW_START_WRITE exit\n",
- dev->name);
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"StWtExit");
- return;
- default:
- printk(KERN_WARNING "%s: wrong selection code - irq "
- "state=%d\n",dev->name,p_ch->claw_state);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(2,trace,"badIRQ");
- return;
+ CLAW_DBF_TEXT(4, trace, "PCINoBH");
+ CLAW_DBF_TEXT(4, trace, "PCI_read");
+ return;
+ }
+ if (!((p_ch->irb->scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS) ||
+ (p_ch->irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND) ||
+ (p_ch->irb->scsw.cmd.stctl ==
+ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+ CLAW_DBF_TEXT(4, trace, "SPend_rd");
+ return;
+ }
+ clear_bit(0, (void *)&p_ch->IO_active);
+ claw_clearbit_busy(TB_RETRY, dev);
+ if (test_and_set_bit(CLAW_BH_ACTIVE,
+ (void *)&p_ch->flag_a) == 0)
+ tasklet_schedule(&p_ch->tasklet);
+ else
+ CLAW_DBF_TEXT(4, trace, "RdBHAct");
+ CLAW_DBF_TEXT(4, trace, "RdIRQXit");
+ return;
+ case CLAW_START_WRITE:
+ if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
+ printk(KERN_INFO "%s: Unit Check Occured in "
+ "write channel\n", dev->name);
+ clear_bit(0, (void *)&p_ch->IO_active);
+ if (p_ch->irb->ecw[0] & 0x80) {
+ printk(KERN_INFO "%s: Resetting Event "
+ "occurred:\n", dev->name);
+ init_timer(&p_ch->timer);
+ p_ch->timer.function =
+ (void *)claw_write_retry;
+ p_ch->timer.data = (unsigned long)p_ch;
+ p_ch->timer.expires = jiffies + 10*HZ;
+ add_timer(&p_ch->timer);
+ printk(KERN_INFO "%s: write connection "
+ "restarting\n", dev->name);
+ }
+ CLAW_DBF_TEXT(4, trace, "rstrtwrt");
+ return;
+ }
+ if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) {
+ clear_bit(0, (void *)&p_ch->IO_active);
+ printk(KERN_INFO "%s: Unit Exception "
+ "Occured in write channel\n",
+ dev->name);
+ }
+ if (!((p_ch->irb->scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS) ||
+ (p_ch->irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND) ||
+ (p_ch->irb->scsw.cmd.stctl ==
+ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+ CLAW_DBF_TEXT(4, trace, "writeUE");
+ return;
+ }
+ clear_bit(0, (void *)&p_ch->IO_active);
+ if (claw_test_and_setbit_busy(TB_TX, dev) == 0) {
+ claw_write_next(p_ch);
+ claw_clearbit_busy(TB_TX, dev);
+ claw_clear_busy(dev);
+ }
+ p_ch_r = (struct chbk *)&privptr->channel[READ];
+ if (test_and_set_bit(CLAW_BH_ACTIVE,
+ (void *)&p_ch_r->flag_a) == 0)
+ tasklet_schedule(&p_ch_r->tasklet);
+ CLAW_DBF_TEXT(4, trace, "StWtExit");
+ return;
+ default:
+ printk(KERN_WARNING "%s: wrong selection code - irq "
+ "state=%d\n", dev->name, p_ch->claw_state);
+ CLAW_DBF_TEXT(2, trace, "badIRQ");
+ return;
}
} /* end of claw_irq_handler */
@@ -1013,29 +779,11 @@ claw_irq_tasklet ( unsigned long data )
p_ch = (struct chbk *) data;
dev = (struct net_device *)p_ch->ndev;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
-#endif
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable p_ch =\n",dev->name);
- dumpit((char *) p_ch, sizeof(struct chbk));
-#endif
- CLAW_DBF_TEXT(4,trace,"IRQtask");
-
+ CLAW_DBF_TEXT(4, trace, "IRQtask");
privptr = (struct claw_privbk *) dev->priv;
-
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: bh routine - state-%02x\n" ,
- dev->name, p_ch->claw_state);
-#endif
-
unpack_read(dev);
clear_bit(CLAW_BH_ACTIVE, (void *)&p_ch->flag_a);
- CLAW_DBF_TEXT(4,trace,"TskletXt");
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
+ CLAW_DBF_TEXT(4, trace, "TskletXt");
return;
} /* end of claw_irq_bh */
@@ -1060,16 +808,7 @@ claw_release(struct net_device *dev)
privptr = (struct claw_privbk *) dev->priv;
if (!privptr)
return 0;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"release");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable dev =\n",dev->name);
- dumpit((char *) dev, sizeof(struct net_device));
- printk(KERN_INFO "Priv Buffalloc %d\n",privptr->buffs_alloc);
- printk(KERN_INFO "Priv p_buff_ccw = %p\n",&privptr->p_buff_ccw);
-#endif
+ CLAW_DBF_TEXT(4, trace, "release");
privptr->release_pend=1;
claw_setbit_busy(TB_STOP,dev);
for ( i = 1; i >=0 ; i--) {
@@ -1101,19 +840,15 @@ claw_release(struct net_device *dev)
privptr->pk_skb = NULL;
}
if(privptr->buffs_alloc != 1) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"none2fre");
+ CLAW_DBF_TEXT(4, trace, "none2fre");
return 0;
}
- CLAW_DBF_TEXT(4,trace,"freebufs");
+ CLAW_DBF_TEXT(4, trace, "freebufs");
if (privptr->p_buff_ccw != NULL) {
free_pages((unsigned long)privptr->p_buff_ccw,
(int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
}
- CLAW_DBF_TEXT(4,trace,"freeread");
+ CLAW_DBF_TEXT(4, trace, "freeread");
if (privptr->p_env->read_size < PAGE_SIZE) {
if (privptr->p_buff_read != NULL) {
free_pages((unsigned long)privptr->p_buff_read,
@@ -1129,7 +864,7 @@ claw_release(struct net_device *dev)
p_buf=p_buf->next;
}
}
- CLAW_DBF_TEXT(4,trace,"freewrit");
+ CLAW_DBF_TEXT(4, trace, "freewrit");
if (privptr->p_env->write_size < PAGE_SIZE ) {
free_pages((unsigned long)privptr->p_buff_write,
(int)pages_to_order_of_mag(privptr->p_buff_write_num));
@@ -1143,7 +878,7 @@ claw_release(struct net_device *dev)
p_buf=p_buf->next;
}
}
- CLAW_DBF_TEXT(4,trace,"clearptr");
+ CLAW_DBF_TEXT(4, trace, "clearptr");
privptr->buffs_alloc = 0;
privptr->p_buff_ccw=NULL;
privptr->p_buff_read=NULL;
@@ -1180,18 +915,12 @@ claw_release(struct net_device *dev)
dev->name,
privptr->channel[READ].last_dstat,
privptr->channel[WRITE].last_dstat);
- CLAW_DBF_TEXT(2,trace,"badclose");
+ CLAW_DBF_TEXT(2, trace, "badclose");
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"rlsexit");
+ CLAW_DBF_TEXT(4, trace, "rlsexit");
return 0;
} /* end of claw_release */
-
-
/*-------------------------------------------------------------------*
* claw_write_retry *
* *
@@ -1203,32 +932,12 @@ claw_write_retry ( struct chbk *p_ch )
struct net_device *dev=p_ch->ndev;
-
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
- printk(KERN_INFO "claw: variable p_ch =\n");
- dumpit((char *) p_ch, sizeof(struct chbk));
-#endif
- CLAW_DBF_TEXT(4,trace,"w_retry");
+ CLAW_DBF_TEXT(4, trace, "w_retry");
if (p_ch->claw_state == CLAW_STOP) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
return;
}
-#ifdef DEBUGMSG
- printk( KERN_INFO "%s:%s state-%02x\n" ,
- dev->name,
- __func__,
- p_ch->claw_state);
-#endif
claw_strt_out_IO( dev );
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"rtry_xit");
+ CLAW_DBF_TEXT(4, trace, "rtry_xit");
return;
} /* end of claw_write_retry */
@@ -1247,12 +956,7 @@ claw_write_next ( struct chbk * p_ch )
struct sk_buff *pk_skb;
int rc;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",p_ch->ndev->name,__func__);
- printk(KERN_INFO "%s: variable p_ch =\n",p_ch->ndev->name);
- dumpit((char *) p_ch, sizeof(struct chbk));
-#endif
- CLAW_DBF_TEXT(4,trace,"claw_wrt");
+ CLAW_DBF_TEXT(4, trace, "claw_wrt");
if (p_ch->claw_state == CLAW_STOP)
return;
dev = (struct net_device *) p_ch->ndev;
@@ -1272,11 +976,6 @@ claw_write_next ( struct chbk * p_ch )
if (privptr->p_write_active_first!=NULL) {
claw_strt_out_IO(dev);
}
-
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
return;
} /* end of claw_write_next */
@@ -1288,22 +987,12 @@ claw_write_next ( struct chbk * p_ch )
static void
claw_timer ( struct chbk * p_ch )
{
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Entry\n",p_ch->ndev->name,__func__);
- printk(KERN_INFO "%s: variable p_ch =\n",p_ch->ndev->name);
- dumpit((char *) p_ch, sizeof(struct chbk));
-#endif
- CLAW_DBF_TEXT(4,trace,"timer");
+ CLAW_DBF_TEXT(4, trace, "timer");
p_ch->flag |= CLAW_TIMER;
wake_up(&p_ch->wait);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- p_ch->ndev->name,__func__,__LINE__);
-#endif
return;
} /* end of claw_timer */
-
/*
*
* functions
@@ -1324,10 +1013,8 @@ pages_to_order_of_mag(int num_of_pages)
{
int order_of_mag=1; /* assume 2 pages */
int nump=2;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s Enter pages = %d \n",__func__,num_of_pages);
-#endif
- CLAW_DBF_TEXT_(5,trace,"pages%d",num_of_pages);
+
+ CLAW_DBF_TEXT_(5, trace, "pages%d", num_of_pages);
if (num_of_pages == 1) {return 0; } /* magnitude of 0 = 1 page */
/* 512 pages = 2Meg on 4k page systems */
if (num_of_pages >= 512) {return 9; }
@@ -1338,11 +1025,7 @@ pages_to_order_of_mag(int num_of_pages)
order_of_mag +=1;
}
if (order_of_mag > 9) { order_of_mag = 9; } /* I know it's paranoid */
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s Exit on line %d, order = %d\n",
- __func__,__LINE__, order_of_mag);
-#endif
- CLAW_DBF_TEXT_(5,trace,"mag%d",order_of_mag);
+ CLAW_DBF_TEXT_(5, trace, "mag%d", order_of_mag);
return order_of_mag;
}
@@ -1358,21 +1041,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
struct claw_privbk *privptr;
struct ccw1 temp_ccw;
struct endccw * p_end;
-#ifdef IOTRACE
- struct ccwbk* p_buf;
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
-#endif
-#ifdef DEBUGMSG
- printk(KERN_INFO "dev\n");
- dumpit((char *) dev, sizeof(struct net_device));
- printk(KERN_INFO "p_first\n");
- dumpit((char *) p_first, sizeof(struct ccwbk));
- printk(KERN_INFO "p_last\n");
- dumpit((char *) p_last, sizeof(struct ccwbk));
-#endif
- CLAW_DBF_TEXT(4,trace,"addreads");
+ CLAW_DBF_TEXT(4, trace, "addreads");
privptr = dev->priv;
p_end = privptr->p_end_ccw;
@@ -1380,11 +1049,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
* to apend the running channel programs
*/
if ( p_first==NULL) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"addexit");
+ CLAW_DBF_TEXT(4, trace, "addexit");
return 0;
}
@@ -1411,21 +1076,11 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
}
if ( privptr-> p_read_active_first ==NULL ) {
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s p_read_active_first == NULL \n",
- dev->name,__func__);
- printk(KERN_INFO "%s:%s Read active first/last changed \n",
- dev->name,__func__);
-#endif
privptr-> p_read_active_first= p_first; /* set new first */
privptr-> p_read_active_last = p_last; /* set new last */
}
else {
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s Read in progress \n",
- dev->name,__func__);
-#endif
/* set up TIC ccw */
temp_ccw.cda= (__u32)__pa(&p_first->read);
temp_ccw.count=0;
@@ -1462,27 +1117,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
privptr->p_read_active_last->next = p_first;
privptr->p_read_active_last=p_last;
} /* end of if ( privptr-> p_read_active_first ==NULL) */
-#ifdef IOTRACE
- printk(KERN_INFO "%s:%s dump p_last CCW BK \n",dev->name,__func__);
- dumpit((char *)p_last, sizeof(struct ccwbk));
- printk(KERN_INFO "%s:%s dump p_end CCW BK \n",dev->name,__func__);
- dumpit((char *)p_end, sizeof(struct endccw));
-
- printk(KERN_INFO "%s:%s dump p_first CCW BK \n",dev->name,__func__);
- dumpit((char *)p_first, sizeof(struct ccwbk));
- printk(KERN_INFO "%s:%s Dump Active CCW chain \n",
- dev->name,__func__);
- p_buf=privptr->p_read_active_first;
- while (p_buf!=NULL) {
- dumpit((char *)p_buf, sizeof(struct ccwbk));
- p_buf=p_buf->next;
- }
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"addexit");
+ CLAW_DBF_TEXT(4, trace, "addexit");
return 0;
} /* end of add_claw_reads */
@@ -1494,44 +1129,29 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
static void
ccw_check_return_code(struct ccw_device *cdev, int return_code)
{
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > enter \n",
- cdev->dev.bus_id,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"ccwret");
-#ifdef DEBUGMSG
- printk(KERN_INFO "variable cdev =\n");
- dumpit((char *) cdev, sizeof(struct ccw_device));
- printk(KERN_INFO "variable return_code = %d\n",return_code);
-#endif
+ CLAW_DBF_TEXT(4, trace, "ccwret");
if (return_code != 0) {
switch (return_code) {
- case -EBUSY:
- printk(KERN_INFO "%s: Busy !\n",
- cdev->dev.bus_id);
- break;
- case -ENODEV:
- printk(KERN_EMERG "%s: Missing device called "
- "for IO ENODEV\n", cdev->dev.bus_id);
- break;
- case -EIO:
- printk(KERN_EMERG "%s: Status pending... EIO \n",
- cdev->dev.bus_id);
- break;
- case -EINVAL:
- printk(KERN_EMERG "%s: Invalid Dev State EINVAL \n",
- cdev->dev.bus_id);
- break;
- default:
- printk(KERN_EMERG "%s: Unknown error in "
+ case -EBUSY: /* BUSY is a transient state no action needed */
+ break;
+ case -ENODEV:
+ printk(KERN_EMERG "%s: Missing device called "
+ "for IO ENODEV\n", cdev->dev.bus_id);
+ break;
+ case -EIO:
+ printk(KERN_EMERG "%s: Status pending... EIO \n",
+ cdev->dev.bus_id);
+ break;
+ case -EINVAL:
+ printk(KERN_EMERG "%s: Invalid Dev State EINVAL \n",
+ cdev->dev.bus_id);
+ break;
+ default:
+ printk(KERN_EMERG "%s: Unknown error in "
"Do_IO %d\n",cdev->dev.bus_id, return_code);
- }
- }
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > exit on line %d\n",
- cdev->dev.bus_id,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"ccwret");
+ }
+ }
+ CLAW_DBF_TEXT(4, trace, "ccwret");
} /* end of ccw_check_return_code */
/*-------------------------------------------------------------------*
@@ -1541,173 +1161,46 @@ ccw_check_return_code(struct ccw_device *cdev, int return_code)
static void
ccw_check_unit_check(struct chbk * p_ch, unsigned char sense )
{
- struct net_device *dev = p_ch->ndev;
-
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > enter\n",dev->name,__func__);
-#endif
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable dev =\n",dev->name);
- dumpit((char *)dev, sizeof(struct net_device));
- printk(KERN_INFO "%s: variable sense =\n",dev->name);
- dumpit((char *)&sense, 2);
-#endif
- CLAW_DBF_TEXT(4,trace,"unitchek");
+ struct net_device *ndev = p_ch->ndev;
+ CLAW_DBF_TEXT(4, trace, "unitchek");
printk(KERN_INFO "%s: Unit Check with sense byte:0x%04x\n",
- dev->name, sense);
+ ndev->name, sense);
if (sense & 0x40) {
if (sense & 0x01) {
printk(KERN_WARNING "%s: Interface disconnect or "
"Selective reset "
- "occurred (remote side)\n", dev->name);
+ "occurred (remote side)\n", ndev->name);
}
else {
printk(KERN_WARNING "%s: System reset occured"
- " (remote side)\n", dev->name);
+ " (remote side)\n", ndev->name);
}
}
else if (sense & 0x20) {
if (sense & 0x04) {
printk(KERN_WARNING "%s: Data-streaming "
- "timeout)\n", dev->name);
+ "timeout)\n", ndev->name);
}
else {
printk(KERN_WARNING "%s: Data-transfer parity"
- " error\n", dev->name);
+ " error\n", ndev->name);
}
}
else if (sense & 0x10) {
if (sense & 0x20) {
printk(KERN_WARNING "%s: Hardware malfunction "
- "(remote side)\n", dev->name);
+ "(remote side)\n", ndev->name);
}
else {
printk(KERN_WARNING "%s: read-data parity error "
- "(remote side)\n", dev->name);
+ "(remote side)\n", ndev->name);
}
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
} /* end of ccw_check_unit_check */
-
-
-/*-------------------------------------------------------------------*
-* Dump buffer format *
-* *
-*--------------------------------------------------------------------*/
-#ifdef DEBUG
-static void
-dumpit(char* buf, int len)
-{
-
- __u32 ct, sw, rm, dup;
- char *ptr, *rptr;
- char tbuf[82], tdup[82];
-#if (CONFIG_64BIT)
- char addr[22];
-#else
- char addr[12];
-#endif
- char boff[12];
- char bhex[82], duphex[82];
- char basc[40];
-
- sw = 0;
- rptr =ptr=buf;
- rm = 16;
- duphex[0] = 0x00;
- dup = 0;
- for ( ct=0; ct < len; ct++, ptr++, rptr++ ) {
- if (sw == 0) {
-#if (CONFIG_64BIT)
- sprintf(addr, "%16.16lX",(unsigned long)rptr);
-#else
- sprintf(addr, "%8.8X",(__u32)rptr);
-#endif
- sprintf(boff, "%4.4X", (__u32)ct);
- bhex[0] = '\0';
- basc[0] = '\0';
- }
- if ((sw == 4) || (sw == 12)) {
- strcat(bhex, " ");
- }
- if (sw == 8) {
- strcat(bhex, " ");
- }
-#if (CONFIG_64BIT)
- sprintf(tbuf,"%2.2lX", (unsigned long)*ptr);
-#else
- sprintf(tbuf,"%2.2X", (__u32)*ptr);
-#endif
- tbuf[2] = '\0';
- strcat(bhex, tbuf);
- if ((0!=isprint(*ptr)) && (*ptr >= 0x20)) {
- basc[sw] = *ptr;
- }
- else {
- basc[sw] = '.';
- }
- basc[sw+1] = '\0';
- sw++;
- rm--;
- if (sw==16) {
- if ((strcmp(duphex, bhex)) !=0) {
- if (dup !=0) {
- sprintf(tdup,"Duplicate as above to"
- " %s", addr);
- printk( KERN_INFO " "
- " --- %s ---\n",tdup);
- }
- printk( KERN_INFO " %s (+%s) : %s [%s]\n",
- addr, boff, bhex, basc);
- dup = 0;
- strcpy(duphex, bhex);
- }
- else {
- dup++;
- }
- sw = 0;
- rm = 16;
- }
- } /* endfor */
-
- if (sw != 0) {
- for ( ; rm > 0; rm--, sw++ ) {
- if ((sw==4) || (sw==12)) strcat(bhex, " ");
- if (sw==8) strcat(bhex, " ");
- strcat(bhex, " ");
- strcat(basc, " ");
- }
- if (dup !=0) {
- sprintf(tdup,"Duplicate as above to %s", addr);
- printk( KERN_INFO " --- %s ---\n",
- tdup);
- }
- printk( KERN_INFO " %s (+%s) : %s [%s]\n",
- addr, boff, bhex, basc);
- }
- else {
- if (dup >=1) {
- sprintf(tdup,"Duplicate as above to %s", addr);
- printk( KERN_INFO " --- %s ---\n",
- tdup);
- }
- if (dup !=0) {
- printk( KERN_INFO " %s (+%s) : %s [%s]\n",
- addr, boff, bhex, basc);
- }
- }
- return;
-
-} /* end of dumpit */
-#endif
-
/*-------------------------------------------------------------------*
* find_link *
*--------------------------------------------------------------------*/
@@ -1718,16 +1211,7 @@ find_link(struct net_device *dev, char *host_name, char *ws_name )
struct claw_env *p_env;
int rc=0;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s > enter \n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"findlink");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable dev = \n",dev->name);
- dumpit((char *) dev, sizeof(struct net_device));
- printk(KERN_INFO "%s: variable host_name = %s\n",dev->name, host_name);
- printk(KERN_INFO "%s: variable ws_name = %s\n",dev->name, ws_name);
-#endif
+ CLAW_DBF_TEXT(2, setup, "findlink");
privptr=dev->priv;
p_env=privptr->p_env;
switch (p_env->packing)
@@ -1750,10 +1234,6 @@ find_link(struct net_device *dev, char *host_name, char *ws_name )
break;
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
return 0;
} /* end of find_link */
@@ -1782,27 +1262,11 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
int lock;
struct clawph *pk_head;
struct chbk *ch;
-#ifdef IOTRACE
- struct ccwbk *p_buf;
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > enter\n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"hw_tx");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable dev skb =\n",dev->name);
- dumpit((char *) skb, sizeof(struct sk_buff));
- printk(KERN_INFO "%s: variable dev =\n",dev->name);
- dumpit((char *) dev, sizeof(struct net_device));
- printk(KERN_INFO "%s: variable linkid = %ld\n",dev->name,linkid);
-#endif
+
+ CLAW_DBF_TEXT(4, trace, "hw_tx");
privptr = (struct claw_privbk *) (dev->priv);
p_ch=(struct chbk *)&privptr->channel[WRITE];
p_env =privptr->p_env;
-#ifdef IOTRACE
- printk(KERN_INFO "%s: %s() dump sk_buff \n",dev->name,__func__);
- dumpit((char *)skb ,sizeof(struct sk_buff));
-#endif
claw_free_wrt_buf(dev); /* Clean up free chain if posible */
/* scan the write queue to free any completed write packets */
p_first_ccw=NULL;
@@ -1834,11 +1298,6 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
claw_strt_out_IO(dev );
claw_free_wrt_buf( dev );
if (privptr->write_free_count==0) {
-#ifdef IOTRACE
- printk(KERN_INFO "%s: "
- "(claw_check_busy) no free write "
- "buffers\n", dev->name);
-#endif
ch = &privptr->channel[WRITE];
atomic_inc(&skb->users);
skb_queue_tail(&ch->collect_queue, skb);
@@ -1851,10 +1310,6 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
}
/* tx lock */
if (claw_test_and_setbit_busy(TB_TX,dev)) { /* set to busy */
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: busy (claw_test_and_setbit_"
- "busy)\n", dev->name);
-#endif
ch = &privptr->channel[WRITE];
atomic_inc(&skb->users);
skb_queue_tail(&ch->collect_queue, skb);
@@ -1871,28 +1326,16 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
privptr->p_write_free_chain == NULL ) {
claw_setbit_busy(TB_NOBUFFER,dev);
-
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: busy (claw_setbit_busy"
- "(TB_NOBUFFER))\n", dev->name);
- printk(KERN_INFO " free_count: %d, numBuffers : %d\n",
- (int)privptr->write_free_count,(int) numBuffers );
-#endif
ch = &privptr->channel[WRITE];
atomic_inc(&skb->users);
skb_queue_tail(&ch->collect_queue, skb);
- CLAW_DBF_TEXT(2,trace,"clawbusy");
+ CLAW_DBF_TEXT(2, trace, "clawbusy");
goto Done2;
}
pDataAddress=skb->data;
len_of_data=skb->len;
while (len_of_data > 0) {
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() length-of-data is %ld \n",
- dev->name ,__func__,len_of_data);
- dumpit((char *)pDataAddress ,64);
-#endif
p_this_ccw=privptr->p_write_free_chain; /* get a block */
if (p_this_ccw == NULL) { /* lost the race */
ch = &privptr->channel[WRITE];
@@ -1924,12 +1367,6 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
(__u32)__pa(&p_this_ccw->write);
}
p_last_ccw=p_this_ccw; /* save new last block */
-#ifdef IOTRACE
- printk(KERN_INFO "%s: %s() > CCW and Buffer %ld bytes long \n",
- dev->name,__func__,bytesInThisBuffer);
- dumpit((char *)p_this_ccw, sizeof(struct ccwbk));
- dumpit((char *)p_this_ccw->p_buffer, 64);
-#endif
}
/* FirstCCW and LastCCW now contain a new set of write channel
@@ -1962,13 +1399,11 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
pEnd->write1_nop2.count=1;
} /* end if if (pEnd->write1) */
-
if (privptr->p_write_active_first==NULL ) {
privptr->p_write_active_first=p_first_ccw;
privptr->p_write_active_last=p_last_ccw;
}
else {
-
/* set up Tic CCWs */
tempCCW.cda=(__u32)__pa(&p_first_ccw->write);
@@ -2007,19 +1442,6 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
}
} /* endif (p_first_ccw!=NULL) */
-
-
-#ifdef IOTRACE
- printk(KERN_INFO "%s: %s() > Dump Active CCW chain \n",
- dev->name,__func__);
- p_buf=privptr->p_write_active_first;
- while (p_buf!=NULL) {
- dumpit((char *)p_buf, sizeof(struct ccwbk));
- p_buf=p_buf->next;
- }
- p_buf=(struct ccwbk*)privptr->p_end_ccw;
- dumpit((char *)p_buf, sizeof(struct endccw));
-#endif
dev_kfree_skb_any(skb);
if (linkid==0) {
lock=LOCK_NO;
@@ -2029,21 +1451,12 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
}
claw_strt_out_IO(dev );
/* if write free count is zero , set NOBUFFER */
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() > free_count is %d\n",
- dev->name,__func__,
- (int) privptr->write_free_count );
-#endif
if (privptr->write_free_count==0) {
claw_setbit_busy(TB_NOBUFFER,dev);
}
Done2:
claw_clearbit_busy(TB_TX,dev);
Done:
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > exit on line %d, rc = %d \n",
- dev->name,__func__,__LINE__, rc);
-#endif
return(rc);
} /* end of claw_hw_tx */
@@ -2075,14 +1488,7 @@ init_ccw_bk(struct net_device *dev)
struct clawh *pClawH=NULL;
addr_t real_TIC_address;
int i,j;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() enter \n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"init_ccw");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable dev =\n",dev->name);
- dumpit((char *) dev, sizeof(struct net_device));
-#endif
+ CLAW_DBF_TEXT(4, trace, "init_ccw");
/* initialize statistics field */
privptr->active_link_ID=0;
@@ -2107,20 +1513,6 @@ init_ccw_bk(struct net_device *dev)
*/
ccw_blocks_required =
privptr->p_env->read_buffers+privptr->p_env->write_buffers+1;
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() "
- "ccw_blocks_required=%d\n",
- dev->name,__func__,
- ccw_blocks_required);
- printk(KERN_INFO "%s: %s() "
- "PAGE_SIZE=0x%x\n",
- dev->name,__func__,
- (unsigned int)PAGE_SIZE);
- printk(KERN_INFO "%s: %s() > "
- "PAGE_MASK=0x%x\n",
- dev->name,__func__,
- (unsigned int)PAGE_MASK);
-#endif
/*
* compute number of CCW blocks that will fit in a page
*/
@@ -2128,14 +1520,6 @@ init_ccw_bk(struct net_device *dev)
ccw_pages_required=
DIV_ROUND_UP(ccw_blocks_required, ccw_blocks_perpage);
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() > ccw_blocks_perpage=%d\n",
- dev->name,__func__,
- ccw_blocks_perpage);
- printk(KERN_INFO "%s: %s() > ccw_pages_required=%d\n",
- dev->name,__func__,
- ccw_pages_required);
-#endif
/*
* read and write sizes are set by 2 constants in claw.h
* 4k and 32k. Unpacked values other than 4k are not going to
@@ -2166,36 +1550,6 @@ init_ccw_bk(struct net_device *dev)
claw_write_pages = privptr->p_env->write_buffers *
privptr->p_buff_pages_perwrite;
}
-#ifdef DEBUGMSG
- if (privptr->p_env->read_size < PAGE_SIZE) {
- printk(KERN_INFO "%s: %s() reads_perpage=%d\n",
- dev->name,__func__,
- claw_reads_perpage);
- }
- else {
- printk(KERN_INFO "%s: %s() pages_perread=%d\n",
- dev->name,__func__,
- privptr->p_buff_pages_perread);
- }
- printk(KERN_INFO "%s: %s() read_pages=%d\n",
- dev->name,__func__,
- claw_read_pages);
- if (privptr->p_env->write_size < PAGE_SIZE) {
- printk(KERN_INFO "%s: %s() writes_perpage=%d\n",
- dev->name,__func__,
- claw_writes_perpage);
- }
- else {
- printk(KERN_INFO "%s: %s() pages_perwrite=%d\n",
- dev->name,__func__,
- privptr->p_buff_pages_perwrite);
- }
- printk(KERN_INFO "%s: %s() write_pages=%d\n",
- dev->name,__func__,
- claw_write_pages);
-#endif
-
-
/*
* allocate ccw_pages_required
*/
@@ -2204,17 +1558,6 @@ init_ccw_bk(struct net_device *dev)
(void *)__get_free_pages(__GFP_DMA,
(int)pages_to_order_of_mag(ccw_pages_required ));
if (privptr->p_buff_ccw==NULL) {
- printk(KERN_INFO "%s: %s() "
- "__get_free_pages for CCWs failed : "
- "pages is %d\n",
- dev->name,__func__,
- ccw_pages_required );
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > "
- "exit on line %d, rc = ENOMEM\n",
- dev->name,__func__,
- __LINE__);
-#endif
return -ENOMEM;
}
privptr->p_buff_ccw_num=ccw_pages_required;
@@ -2229,11 +1572,6 @@ init_ccw_bk(struct net_device *dev)
privptr->p_end_ccw = (struct endccw *)&privptr->end_ccw;
real_address = (__u32)__pa(privptr->p_end_ccw);
/* Initialize ending CCW block */
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() begin initialize ending CCW blocks\n",
- dev->name,__func__);
-#endif
-
p_endccw=privptr->p_end_ccw;
p_endccw->real=real_address;
p_endccw->write1=0x00;
@@ -2287,21 +1625,10 @@ init_ccw_bk(struct net_device *dev)
p_endccw->read2_nop2.count = 1;
p_endccw->read2_nop2.cda = 0;
-#ifdef IOTRACE
- printk(KERN_INFO "%s: %s() dump claw ending CCW BK \n",
- dev->name,__func__);
- dumpit((char *)p_endccw, sizeof(struct endccw));
-#endif
-
/*
* Build a chain of CCWs
*
*/
-
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() Begin build a chain of CCW buffer \n",
- dev->name,__func__);
-#endif
p_buff=privptr->p_buff_ccw;
p_free_chain=NULL;
@@ -2316,26 +1643,10 @@ init_ccw_bk(struct net_device *dev)
}
p_buff+=PAGE_SIZE;
}
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() "
- "End build a chain of CCW buffer \n",
- dev->name,__func__);
- p_buf=p_free_chain;
- while (p_buf!=NULL) {
- dumpit((char *)p_buf, sizeof(struct ccwbk));
- p_buf=p_buf->next;
- }
-#endif
-
/*
* Initialize ClawSignalBlock
*
*/
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() "
- "Begin initialize ClawSignalBlock \n",
- dev->name,__func__);
-#endif
if (privptr->p_claw_signal_blk==NULL) {
privptr->p_claw_signal_blk=p_free_chain;
p_free_chain=p_free_chain->next;
@@ -2344,12 +1655,6 @@ init_ccw_bk(struct net_device *dev)
pClawH->opcode=0xff;
pClawH->flag=CLAW_BUSY;
}
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() > End initialize "
- "ClawSignalBlock\n",
- dev->name,__func__);
- dumpit((char *)privptr->p_claw_signal_blk, sizeof(struct ccwbk));
-#endif
/*
* allocate write_pages_required and add to free chain
@@ -2360,17 +1665,7 @@ init_ccw_bk(struct net_device *dev)
(void *)__get_free_pages(__GFP_DMA,
(int)pages_to_order_of_mag(claw_write_pages ));
if (privptr->p_buff_write==NULL) {
- printk(KERN_INFO "%s: %s() __get_free_pages for write"
- " bufs failed : get is for %d pages\n",
- dev->name,__func__,claw_write_pages );
- free_pages((unsigned long)privptr->p_buff_ccw,
- (int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
privptr->p_buff_ccw=NULL;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > exit on line %d,"
- "rc = ENOMEM\n",
- dev->name,__func__,__LINE__);
-#endif
return -ENOMEM;
}
/*
@@ -2380,10 +1675,6 @@ init_ccw_bk(struct net_device *dev)
memset(privptr->p_buff_write, 0x00,
ccw_pages_required * PAGE_SIZE);
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() Begin build claw write free "
- "chain \n",dev->name,__func__);
-#endif
privptr->p_write_free_chain=NULL;
p_buff=privptr->p_buff_write;
@@ -2419,18 +1710,7 @@ init_ccw_bk(struct net_device *dev)
p_buff=(void *)__get_free_pages(__GFP_DMA,
(int)pages_to_order_of_mag(
privptr->p_buff_pages_perwrite) );
-#ifdef IOTRACE
- printk(KERN_INFO "%s:%s __get_free_pages "
- "for writes buf: get for %d pages\n",
- dev->name,__func__,
- privptr->p_buff_pages_perwrite);
-#endif
if (p_buff==NULL) {
- printk(KERN_INFO "%s:%s __get_free_pages "
- "for writes buf failed : get is for %d pages\n",
- dev->name,
- __func__,
- privptr->p_buff_pages_perwrite );
free_pages((unsigned long)privptr->p_buff_ccw,
(int)pages_to_order_of_mag(
privptr->p_buff_ccw_num));
@@ -2443,12 +1723,6 @@ init_ccw_bk(struct net_device *dev)
privptr->p_buff_pages_perwrite));
p_buf=p_buf->next;
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s exit on line %d, rc = ENOMEM\n",
- dev->name,
- __func__,
- __LINE__);
-#endif
return -ENOMEM;
} /* Error on get_pages */
memset(p_buff, 0x00, privptr->p_env->write_size );
@@ -2477,15 +1751,6 @@ init_ccw_bk(struct net_device *dev)
privptr->write_free_count=privptr->p_env->write_buffers;
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s End build claw write free chain \n",
- dev->name,__func__);
- p_buf=privptr->p_write_free_chain;
- while (p_buf!=NULL) {
- dumpit((char *)p_buf, sizeof(struct ccwbk));
- p_buf=p_buf->next;
- }
-#endif
/*
* allocate read_pages_required and chain to free chain
*/
@@ -2495,10 +1760,6 @@ init_ccw_bk(struct net_device *dev)
(void *)__get_free_pages(__GFP_DMA,
(int)pages_to_order_of_mag(claw_read_pages) );
if (privptr->p_buff_read==NULL) {
- printk(KERN_INFO "%s: %s() "
- "__get_free_pages for read buf failed : "
- "get is for %d pages\n",
- dev->name,__func__,claw_read_pages );
free_pages((unsigned long)privptr->p_buff_ccw,
(int)pages_to_order_of_mag(
privptr->p_buff_ccw_num));
@@ -2508,10 +1769,6 @@ init_ccw_bk(struct net_device *dev)
privptr->p_buff_write_num));
privptr->p_buff_ccw=NULL;
privptr->p_buff_write=NULL;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > exit on line %d, rc ="
- " ENOMEM\n",dev->name,__func__,__LINE__);
-#endif
return -ENOMEM;
}
memset(privptr->p_buff_read, 0x00, claw_read_pages * PAGE_SIZE);
@@ -2520,10 +1777,6 @@ init_ccw_bk(struct net_device *dev)
* Build CLAW read free chain
*
*/
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() Begin build claw read free chain \n",
- dev->name,__func__);
-#endif
p_buff=privptr->p_buff_read;
for (i=0 ; i< privptr->p_env->read_buffers ; i++) {
p_buf = p_free_chain;
@@ -2600,19 +1853,10 @@ init_ccw_bk(struct net_device *dev)
} /* for read_buffers */
} /* read_size < PAGE_SIZE */
else { /* read Size >= PAGE_SIZE */
-
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() Begin build claw read free chain \n",
- dev->name,__func__);
-#endif
for (i=0 ; i< privptr->p_env->read_buffers ; i++) {
p_buff = (void *)__get_free_pages(__GFP_DMA,
(int)pages_to_order_of_mag(privptr->p_buff_pages_perread) );
if (p_buff==NULL) {
- printk(KERN_INFO "%s: %s() __get_free_pages for read "
- "buf failed : get is for %d pages\n",
- dev->name,__func__,
- privptr->p_buff_pages_perread );
free_pages((unsigned long)privptr->p_buff_ccw,
(int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
/* free the write pages */
@@ -2633,11 +1877,6 @@ init_ccw_bk(struct net_device *dev)
}
privptr->p_buff_ccw=NULL;
privptr->p_buff_write=NULL;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() exit on line %d, rc = ENOMEM\n",
- dev->name,__func__,
- __LINE__);
-#endif
return -ENOMEM;
}
memset(p_buff, 0x00, privptr->p_env->read_size);
@@ -2706,22 +1945,9 @@ init_ccw_bk(struct net_device *dev)
} /* For read_buffers */
} /* read_size >= PAGE_SIZE */
} /* pBuffread = NULL */
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() > End build claw read free chain \n",
- dev->name,__func__);
- p_buf=p_first_CCWB;
- while (p_buf!=NULL) {
- dumpit((char *)p_buf, sizeof(struct ccwbk));
- p_buf=p_buf->next;
- }
-
-#endif
add_claw_reads( dev ,p_first_CCWB , p_last_CCWB);
privptr->buffs_alloc = 1;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
+
return 0;
} /* end of init_ccw_bk */
@@ -2735,14 +1961,8 @@ static void
probe_error( struct ccwgroup_device *cgdev)
{
struct claw_privbk *privptr;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s enter \n",__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"proberr");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s variable cgdev =\n",__func__);
- dumpit((char *) cgdev, sizeof(struct ccwgroup_device));
-#endif
+
+ CLAW_DBF_TEXT(4, trace, "proberr");
privptr=(struct claw_privbk *)cgdev->dev.driver_data;
if (privptr!=NULL) {
kfree(privptr->p_env);
@@ -2752,16 +1972,9 @@ probe_error( struct ccwgroup_device *cgdev)
kfree(privptr);
privptr=NULL;
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s > exit on line %d\n",
- __func__,__LINE__);
-#endif
-
return;
} /* probe_error */
-
-
/*-------------------------------------------------------------------*
* claw_process_control *
* *
@@ -2783,32 +1996,19 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
struct conncmd *p_connect=NULL;
int rc;
struct chbk *p_ch = NULL;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > enter \n",
- dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"clw_cntl");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable dev =\n",dev->name);
- dumpit((char *) dev, sizeof(struct net_device));
- printk(KERN_INFO "%s: variable p_ccw =\n",dev->name);
- dumpit((char *) p_ccw, sizeof(struct ccwbk *));
-#endif
+ struct device *tdev;
+ CLAW_DBF_TEXT(2, setup, "clw_cntl");
udelay(1000); /* Wait a ms for the control packets to
*catch up to each other */
privptr=dev->priv;
p_env=privptr->p_env;
+ tdev = &privptr->channel[READ].cdev->dev;
memcpy( &temp_host_name, p_env->host_name, 8);
memcpy( &temp_ws_name, p_env->adapter_name , 8);
printk(KERN_INFO "%s: CLAW device %.8s: "
"Received Control Packet\n",
dev->name, temp_ws_name);
if (privptr->release_pend==1) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > "
- "exit on line %d, rc=0\n",
- dev->name,__func__,__LINE__);
-#endif
return 0;
}
p_buf=p_ccw->p_buffer;
@@ -2818,261 +2018,246 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
} else {
memcpy(p_ctlbk, p_buf, sizeof(struct clawctl));
}
-#ifdef IOTRACE
- printk(KERN_INFO "%s: dump claw control data inbound\n",dev->name);
- dumpit((char *)p_ctlbk, sizeof(struct clawctl));
-#endif
switch (p_ctlbk->command)
{
- case SYSTEM_VALIDATE_REQUEST:
- if (p_ctlbk->version!=CLAW_VERSION_ID) {
- claw_snd_sys_validate_rsp(dev, p_ctlbk,
- CLAW_RC_WRONG_VERSION );
- printk("%s: %d is wrong version id. "
- "Expected %d\n",
- dev->name, p_ctlbk->version,
- CLAW_VERSION_ID);
- }
- p_sysval=(struct sysval *)&(p_ctlbk->data);
- printk( "%s: Recv Sys Validate Request: "
- "Vers=%d,link_id=%d,Corr=%d,WS name=%."
- "8s,Host name=%.8s\n",
- dev->name, p_ctlbk->version,
- p_ctlbk->linkid,
- p_ctlbk->correlator,
- p_sysval->WS_name,
- p_sysval->host_name);
- if (0!=memcmp(temp_host_name,p_sysval->host_name,8)) {
- claw_snd_sys_validate_rsp(dev, p_ctlbk,
- CLAW_RC_NAME_MISMATCH );
- CLAW_DBF_TEXT(2,setup,"HSTBAD");
- CLAW_DBF_TEXT_(2,setup,"%s",p_sysval->host_name);
- CLAW_DBF_TEXT_(2,setup,"%s",temp_host_name);
- printk(KERN_INFO "%s: Host name mismatch\n",
- dev->name);
- printk(KERN_INFO "%s: Received :%s: "
- "expected :%s: \n",
- dev->name,
- p_sysval->host_name,
- temp_host_name);
- }
- if (0!=memcmp(temp_ws_name,p_sysval->WS_name,8)) {
- claw_snd_sys_validate_rsp(dev, p_ctlbk,
- CLAW_RC_NAME_MISMATCH );
- CLAW_DBF_TEXT(2,setup,"WSNBAD");
- CLAW_DBF_TEXT_(2,setup,"%s",p_sysval->WS_name);
- CLAW_DBF_TEXT_(2,setup,"%s",temp_ws_name);
- printk(KERN_INFO "%s: WS name mismatch\n",
- dev->name);
- printk(KERN_INFO "%s: Received :%s: "
- "expected :%s: \n",
- dev->name,
- p_sysval->WS_name,
- temp_ws_name);
- }
- if (( p_sysval->write_frame_size < p_env->write_size) &&
- ( p_env->packing == 0)) {
- claw_snd_sys_validate_rsp(dev, p_ctlbk,
- CLAW_RC_HOST_RCV_TOO_SMALL );
- printk(KERN_INFO "%s: host write size is too "
- "small\n", dev->name);
- CLAW_DBF_TEXT(2,setup,"wrtszbad");
- }
- if (( p_sysval->read_frame_size < p_env->read_size) &&
- ( p_env->packing == 0)) {
- claw_snd_sys_validate_rsp(dev, p_ctlbk,
- CLAW_RC_HOST_RCV_TOO_SMALL );
- printk(KERN_INFO "%s: host read size is too "
- "small\n", dev->name);
- CLAW_DBF_TEXT(2,setup,"rdsizbad");
- }
- claw_snd_sys_validate_rsp(dev, p_ctlbk, 0 );
- printk("%s: CLAW device %.8s: System validate"
- " completed.\n",dev->name, temp_ws_name);
- printk("%s: sys Validate Rsize:%d Wsize:%d\n",dev->name,
- p_sysval->read_frame_size,p_sysval->write_frame_size);
- privptr->system_validate_comp=1;
- if(strncmp(p_env->api_type,WS_APPL_NAME_PACKED,6) == 0) {
- p_env->packing = PACKING_ASK;
- }
- claw_strt_conn_req(dev);
- break;
-
- case SYSTEM_VALIDATE_RESPONSE:
- p_sysval=(struct sysval *)&(p_ctlbk->data);
- printk("%s: Recv Sys Validate Resp: Vers=%d,Corr=%d,RC=%d,"
- "WS name=%.8s,Host name=%.8s\n",
- dev->name,
- p_ctlbk->version,
- p_ctlbk->correlator,
- p_ctlbk->rc,
- p_sysval->WS_name,
- p_sysval->host_name);
- switch (p_ctlbk->rc)
- {
- case 0:
- printk(KERN_INFO "%s: CLAW device "
- "%.8s: System validate "
- "completed.\n",
- dev->name, temp_ws_name);
- if (privptr->system_validate_comp == 0)
- claw_strt_conn_req(dev);
- privptr->system_validate_comp=1;
- break;
- case CLAW_RC_NAME_MISMATCH:
- printk(KERN_INFO "%s: Sys Validate "
- "Resp : Host, WS name is "
- "mismatch\n",
- dev->name);
- break;
- case CLAW_RC_WRONG_VERSION:
- printk(KERN_INFO "%s: Sys Validate "
- "Resp : Wrong version\n",
- dev->name);
- break;
- case CLAW_RC_HOST_RCV_TOO_SMALL:
- printk(KERN_INFO "%s: Sys Validate "
- "Resp : bad frame size\n",
- dev->name);
- break;
- default:
- printk(KERN_INFO "%s: Sys Validate "
- "error code=%d \n",
- dev->name, p_ctlbk->rc );
- break;
- }
- break;
+ case SYSTEM_VALIDATE_REQUEST:
+ if (p_ctlbk->version != CLAW_VERSION_ID) {
+ claw_snd_sys_validate_rsp(dev, p_ctlbk,
+ CLAW_RC_WRONG_VERSION);
+ printk("%s: %d is wrong version id. "
+ "Expected %d\n",
+ dev->name, p_ctlbk->version,
+ CLAW_VERSION_ID);
+ }
+ p_sysval = (struct sysval *)&(p_ctlbk->data);
+ printk("%s: Recv Sys Validate Request: "
+ "Vers=%d,link_id=%d,Corr=%d,WS name=%."
+ "8s,Host name=%.8s\n",
+ dev->name, p_ctlbk->version,
+ p_ctlbk->linkid,
+ p_ctlbk->correlator,
+ p_sysval->WS_name,
+ p_sysval->host_name);
+ if (memcmp(temp_host_name, p_sysval->host_name, 8)) {
+ claw_snd_sys_validate_rsp(dev, p_ctlbk,
+ CLAW_RC_NAME_MISMATCH);
+ CLAW_DBF_TEXT(2, setup, "HSTBAD");
+ CLAW_DBF_TEXT_(2, setup, "%s", p_sysval->host_name);
+ CLAW_DBF_TEXT_(2, setup, "%s", temp_host_name);
+ printk(KERN_INFO "%s: Host name mismatch\n",
+ dev->name);
+ printk(KERN_INFO "%s: Received :%s: "
+ "expected :%s: \n",
+ dev->name,
+ p_sysval->host_name,
+ temp_host_name);
+ }
+ if (memcmp(temp_ws_name, p_sysval->WS_name, 8)) {
+ claw_snd_sys_validate_rsp(dev, p_ctlbk,
+ CLAW_RC_NAME_MISMATCH);
+ CLAW_DBF_TEXT(2, setup, "WSNBAD");
+ CLAW_DBF_TEXT_(2, setup, "%s", p_sysval->WS_name);
+ CLAW_DBF_TEXT_(2, setup, "%s", temp_ws_name);
+ printk(KERN_INFO "%s: WS name mismatch\n",
+ dev->name);
+ printk(KERN_INFO "%s: Received :%s: "
+ "expected :%s: \n",
+ dev->name,
+ p_sysval->WS_name,
+ temp_ws_name);
+ }
+ if ((p_sysval->write_frame_size < p_env->write_size) &&
+ (p_env->packing == 0)) {
+ claw_snd_sys_validate_rsp(dev, p_ctlbk,
+ CLAW_RC_HOST_RCV_TOO_SMALL);
+ printk(KERN_INFO "%s: host write size is too "
+ "small\n", dev->name);
+ CLAW_DBF_TEXT(2, setup, "wrtszbad");
+ }
+ if ((p_sysval->read_frame_size < p_env->read_size) &&
+ (p_env->packing == 0)) {
+ claw_snd_sys_validate_rsp(dev, p_ctlbk,
+ CLAW_RC_HOST_RCV_TOO_SMALL);
+ printk(KERN_INFO "%s: host read size is too "
+ "small\n", dev->name);
+ CLAW_DBF_TEXT(2, setup, "rdsizbad");
+ }
+ claw_snd_sys_validate_rsp(dev, p_ctlbk, 0);
+ printk(KERN_INFO "%s: CLAW device %.8s: System validate "
+ "completed.\n", dev->name, temp_ws_name);
+ printk("%s: sys Validate Rsize:%d Wsize:%d\n", dev->name,
+ p_sysval->read_frame_size, p_sysval->write_frame_size);
+ privptr->system_validate_comp = 1;
+ if (strncmp(p_env->api_type, WS_APPL_NAME_PACKED, 6) == 0)
+ p_env->packing = PACKING_ASK;
+ claw_strt_conn_req(dev);
+ break;
+ case SYSTEM_VALIDATE_RESPONSE:
+ p_sysval = (struct sysval *)&(p_ctlbk->data);
+ printk("%s: Recv Sys Validate Resp: Vers=%d,Corr=%d,RC=%d,"
+ "WS name=%.8s,Host name=%.8s\n",
+ dev->name,
+ p_ctlbk->version,
+ p_ctlbk->correlator,
+ p_ctlbk->rc,
+ p_sysval->WS_name,
+ p_sysval->host_name);
+ switch (p_ctlbk->rc) {
+ case 0:
+ printk(KERN_INFO "%s: CLAW device "
+ "%.8s: System validate "
+ "completed.\n",
+ dev->name, temp_ws_name);
+ if (privptr->system_validate_comp == 0)
+ claw_strt_conn_req(dev);
+ privptr->system_validate_comp = 1;
+ break;
+ case CLAW_RC_NAME_MISMATCH:
+ printk(KERN_INFO "%s: Sys Validate "
+ "Resp : Host, WS name is "
+ "mismatch\n",
+ dev->name);
+ break;
+ case CLAW_RC_WRONG_VERSION:
+ printk(KERN_INFO "%s: Sys Validate "
+ "Resp : Wrong version\n",
+ dev->name);
+ break;
+ case CLAW_RC_HOST_RCV_TOO_SMALL:
+ printk(KERN_INFO "%s: Sys Validate "
+ "Resp : bad frame size\n",
+ dev->name);
+ break;
+ default:
+ printk(KERN_INFO "%s: Sys Validate "
+ "error code=%d \n",
+ dev->name, p_ctlbk->rc);
+ break;
+ }
+ break;
- case CONNECTION_REQUEST:
- p_connect=(struct conncmd *)&(p_ctlbk->data);
- printk(KERN_INFO "%s: Recv Conn Req: Vers=%d,link_id=%d,"
- "Corr=%d,HOST appl=%.8s,WS appl=%.8s\n",
- dev->name,
- p_ctlbk->version,
- p_ctlbk->linkid,
- p_ctlbk->correlator,
- p_connect->host_name,
- p_connect->WS_name);
- if (privptr->active_link_ID!=0 ) {
- claw_snd_disc(dev, p_ctlbk);
- printk(KERN_INFO "%s: Conn Req error : "
- "already logical link is active \n",
- dev->name);
- }
- if (p_ctlbk->linkid!=1 ) {
- claw_snd_disc(dev, p_ctlbk);
- printk(KERN_INFO "%s: Conn Req error : "
- "req logical link id is not 1\n",
+ case CONNECTION_REQUEST:
+ p_connect = (struct conncmd *)&(p_ctlbk->data);
+ printk(KERN_INFO "%s: Recv Conn Req: Vers=%d,link_id=%d,"
+ "Corr=%d,HOST appl=%.8s,WS appl=%.8s\n",
+ dev->name,
+ p_ctlbk->version,
+ p_ctlbk->linkid,
+ p_ctlbk->correlator,
+ p_connect->host_name,
+ p_connect->WS_name);
+ if (privptr->active_link_ID != 0) {
+ claw_snd_disc(dev, p_ctlbk);
+ printk(KERN_INFO "%s: Conn Req error : "
+ "already logical link is active \n",
+ dev->name);
+ }
+ if (p_ctlbk->linkid != 1) {
+ claw_snd_disc(dev, p_ctlbk);
+ printk(KERN_INFO "%s: Conn Req error : "
+ "req logical link id is not 1\n",
+ dev->name);
+ }
+ rc = find_link(dev, p_connect->host_name, p_connect->WS_name);
+ if (rc != 0) {
+ claw_snd_disc(dev, p_ctlbk);
+ printk(KERN_INFO "%s: Conn Resp error: "
+ "req appl name does not match\n",
+ dev->name);
+ }
+ claw_send_control(dev,
+ CONNECTION_CONFIRM, p_ctlbk->linkid,
+ p_ctlbk->correlator,
+ 0, p_connect->host_name,
+ p_connect->WS_name);
+ if (p_env->packing == PACKING_ASK) {
+ p_env->packing = PACK_SEND;
+ claw_snd_conn_req(dev, 0);
+ }
+ printk(KERN_INFO "%s: CLAW device %.8s: Connection "
+ "completed link_id=%d.\n",
+ dev->name, temp_ws_name,
+ p_ctlbk->linkid);
+ privptr->active_link_ID = p_ctlbk->linkid;
+ p_ch = &privptr->channel[WRITE];
+ wake_up(&p_ch->wait); /* wake up claw_open ( WRITE) */
+ break;
+ case CONNECTION_RESPONSE:
+ p_connect = (struct conncmd *)&(p_ctlbk->data);
+ printk(KERN_INFO "%s: Revc Conn Resp: Vers=%d,link_id=%d,"
+ "Corr=%d,RC=%d,Host appl=%.8s, WS appl=%.8s\n",
+ dev->name,
+ p_ctlbk->version,
+ p_ctlbk->linkid,
+ p_ctlbk->correlator,
+ p_ctlbk->rc,
+ p_connect->host_name,
+ p_connect->WS_name);
+
+ if (p_ctlbk->rc != 0) {
+ printk(KERN_INFO "%s: Conn Resp error: rc=%d \n",
+ dev->name, p_ctlbk->rc);
+ return 1;
+ }
+ rc = find_link(dev,
+ p_connect->host_name, p_connect->WS_name);
+ if (rc != 0) {
+ claw_snd_disc(dev, p_ctlbk);
+ printk(KERN_INFO "%s: Conn Resp error: "
+ "req appl name does not match\n",
+ dev->name);
+ }
+ /* should be until CONNECTION_CONFIRM */
+ privptr->active_link_ID = -(p_ctlbk->linkid);
+ break;
+ case CONNECTION_CONFIRM:
+ p_connect = (struct conncmd *)&(p_ctlbk->data);
+ printk(KERN_INFO "%s: Recv Conn Confirm:Vers=%d,link_id=%d,"
+ "Corr=%d,Host appl=%.8s,WS appl=%.8s\n",
+ dev->name,
+ p_ctlbk->version,
+ p_ctlbk->linkid,
+ p_ctlbk->correlator,
+ p_connect->host_name,
+ p_connect->WS_name);
+ if (p_ctlbk->linkid == -(privptr->active_link_ID)) {
+ privptr->active_link_ID = p_ctlbk->linkid;
+ if (p_env->packing > PACKING_ASK) {
+ printk(KERN_INFO "%s: Confirmed Now packing\n",
dev->name);
- }
- rc=find_link(dev,
- p_connect->host_name, p_connect->WS_name);
- if (rc!=0) {
- claw_snd_disc(dev, p_ctlbk);
- printk(KERN_INFO "%s: Conn Req error : "
- "req appl name does not match\n",
- dev->name);
- }
- claw_send_control(dev,
- CONNECTION_CONFIRM, p_ctlbk->linkid,
- p_ctlbk->correlator,
- 0, p_connect->host_name,
- p_connect->WS_name);
- if (p_env->packing == PACKING_ASK) {
- printk("%s: Now Pack ask\n",dev->name);
- p_env->packing = PACK_SEND;
- claw_snd_conn_req(dev,0);
- }
- printk(KERN_INFO "%s: CLAW device %.8s: Connection "
- "completed link_id=%d.\n",
- dev->name, temp_ws_name,
- p_ctlbk->linkid);
- privptr->active_link_ID=p_ctlbk->linkid;
- p_ch=&privptr->channel[WRITE];
- wake_up(&p_ch->wait); /* wake up claw_open ( WRITE) */
- break;
- case CONNECTION_RESPONSE:
- p_connect=(struct conncmd *)&(p_ctlbk->data);
- printk(KERN_INFO "%s: Revc Conn Resp: Vers=%d,link_id=%d,"
- "Corr=%d,RC=%d,Host appl=%.8s, WS appl=%.8s\n",
- dev->name,
- p_ctlbk->version,
- p_ctlbk->linkid,
- p_ctlbk->correlator,
- p_ctlbk->rc,
- p_connect->host_name,
- p_connect->WS_name);
-
- if (p_ctlbk->rc !=0 ) {
- printk(KERN_INFO "%s: Conn Resp error: rc=%d \n",
- dev->name, p_ctlbk->rc);
- return 1;
- }
- rc=find_link(dev,
- p_connect->host_name, p_connect->WS_name);
- if (rc!=0) {
- claw_snd_disc(dev, p_ctlbk);
- printk(KERN_INFO "%s: Conn Resp error: "
- "req appl name does not match\n",
- dev->name);
- }
- /* should be until CONNECTION_CONFIRM */
- privptr->active_link_ID = - (p_ctlbk->linkid);
- break;
- case CONNECTION_CONFIRM:
- p_connect=(struct conncmd *)&(p_ctlbk->data);
- printk(KERN_INFO "%s: Recv Conn Confirm:Vers=%d,link_id=%d,"
- "Corr=%d,Host appl=%.8s,WS appl=%.8s\n",
- dev->name,
- p_ctlbk->version,
- p_ctlbk->linkid,
- p_ctlbk->correlator,
- p_connect->host_name,
- p_connect->WS_name);
- if (p_ctlbk->linkid== -(privptr->active_link_ID)) {
- privptr->active_link_ID=p_ctlbk->linkid;
- if (p_env->packing > PACKING_ASK) {
- printk(KERN_INFO "%s: Confirmed Now packing\n",dev->name);
- p_env->packing = DO_PACKED;
- }
- p_ch=&privptr->channel[WRITE];
- wake_up(&p_ch->wait);
- }
- else {
- printk(KERN_INFO "%s: Conn confirm: "
- "unexpected linkid=%d \n",
- dev->name, p_ctlbk->linkid);
- claw_snd_disc(dev, p_ctlbk);
- }
- break;
- case DISCONNECT:
- printk(KERN_INFO "%s: Disconnect: "
- "Vers=%d,link_id=%d,Corr=%d\n",
- dev->name, p_ctlbk->version,
- p_ctlbk->linkid, p_ctlbk->correlator);
- if ((p_ctlbk->linkid == 2) &&
- (p_env->packing == PACK_SEND)) {
- privptr->active_link_ID = 1;
p_env->packing = DO_PACKED;
}
- else
- privptr->active_link_ID=0;
- break;
- case CLAW_ERROR:
- printk(KERN_INFO "%s: CLAW ERROR detected\n",
- dev->name);
- break;
- default:
- printk(KERN_INFO "%s: Unexpected command code=%d \n",
- dev->name, p_ctlbk->command);
- break;
+ p_ch = &privptr->channel[WRITE];
+ wake_up(&p_ch->wait);
+ } else {
+ printk(KERN_INFO "%s: Conn confirm: "
+ "unexpected linkid=%d \n",
+ dev->name, p_ctlbk->linkid);
+ claw_snd_disc(dev, p_ctlbk);
+ }
+ break;
+ case DISCONNECT:
+ printk(KERN_INFO "%s: Disconnect: "
+ "Vers=%d,link_id=%d,Corr=%d\n",
+ dev->name, p_ctlbk->version,
+ p_ctlbk->linkid, p_ctlbk->correlator);
+ if ((p_ctlbk->linkid == 2) &&
+ (p_env->packing == PACK_SEND)) {
+ privptr->active_link_ID = 1;
+ p_env->packing = DO_PACKED;
+ } else
+ privptr->active_link_ID = 0;
+ break;
+ case CLAW_ERROR:
+ printk(KERN_INFO "%s: CLAW ERROR detected\n",
+ dev->name);
+ break;
+ default:
+ printk(KERN_INFO "%s: Unexpected command code=%d \n",
+ dev->name, p_ctlbk->command);
+ break;
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() exit on line %d, rc = 0\n",
- dev->name,__func__,__LINE__);
-#endif
-
return 0;
} /* end of claw_process_control */
@@ -3092,18 +2277,7 @@ claw_send_control(struct net_device *dev, __u8 type, __u8 link,
struct conncmd *p_connect;
struct sk_buff *skb;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s > enter \n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"sndcntl");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: Sending Control Packet \n",dev->name);
- printk(KERN_INFO "%s: variable type = 0x%X, link = "
- "%d, correlator = %d, rc = %d\n",
- dev->name,type, link, correlator, rc);
- printk(KERN_INFO "%s: variable local_name = %s, "
- "remote_name = %s\n",dev->name, local_name, remote_name);
-#endif
+ CLAW_DBF_TEXT(2, setup, "sndcntl");
privptr=dev->priv;
p_ctl=(struct clawctl *)&privptr->ctl_bk;
@@ -3125,7 +2299,7 @@ claw_send_control(struct net_device *dev, __u8 type, __u8 link,
p_sysval->read_frame_size=DEF_PACK_BUFSIZE;
p_sysval->write_frame_size=DEF_PACK_BUFSIZE;
} else {
- /* how big is the piggest group of packets */
+ /* how big is the biggest group of packets */
p_sysval->read_frame_size=privptr->p_env->read_size;
p_sysval->write_frame_size=privptr->p_env->write_size;
}
@@ -3155,29 +2329,14 @@ claw_send_control(struct net_device *dev, __u8 type, __u8 link,
skb = dev_alloc_skb(sizeof(struct clawctl));
if (!skb) {
- printk( "%s:%s low on mem, returning...\n",
- dev->name,__func__);
-#ifdef DEBUG
- printk(KERN_INFO "%s:%s Exit, rc = ENOMEM\n",
- dev->name,__func__);
-#endif
return -ENOMEM;
}
memcpy(skb_put(skb, sizeof(struct clawctl)),
p_ctl, sizeof(struct clawctl));
-#ifdef IOTRACE
- printk(KERN_INFO "%s: outbnd claw cntl data \n",dev->name);
- dumpit((char *)p_ctl,sizeof(struct clawctl));
-#endif
if (privptr->p_env->packing >= PACK_SEND)
claw_hw_tx(skb, dev, 1);
else
claw_hw_tx(skb, dev, 0);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
-
return 0;
} /* end of claw_send_control */
@@ -3192,22 +2351,11 @@ claw_snd_conn_req(struct net_device *dev, __u8 link)
struct claw_privbk *privptr=dev->priv;
struct clawctl *p_ctl;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"snd_conn");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable link = %X, dev =\n",dev->name, link);
- dumpit((char *) dev, sizeof(struct net_device));
-#endif
+ CLAW_DBF_TEXT(2, setup, "snd_conn");
rc = 1;
p_ctl=(struct clawctl *)&privptr->ctl_bk;
p_ctl->linkid = link;
if ( privptr->system_validate_comp==0x00 ) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d, rc = 1\n",
- dev->name,__func__,__LINE__);
-#endif
return rc;
}
if (privptr->p_env->packing == PACKING_ASK )
@@ -3220,10 +2368,6 @@ claw_snd_conn_req(struct net_device *dev, __u8 link)
if (privptr->p_env->packing == 0)
rc=claw_send_control(dev, CONNECTION_REQUEST,0,0,0,
HOST_APPL_NAME, privptr->p_env->api_type);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
- dev->name,__func__,__LINE__, rc);
-#endif
return rc;
} /* end of claw_snd_conn_req */
@@ -3240,25 +2384,12 @@ claw_snd_disc(struct net_device *dev, struct clawctl * p_ctl)
int rc;
struct conncmd * p_connect;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"snd_dsc");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable dev =\n",dev->name);
- dumpit((char *) dev, sizeof(struct net_device));
- printk(KERN_INFO "%s: variable p_ctl",dev->name);
- dumpit((char *) p_ctl, sizeof(struct clawctl));
-#endif
+ CLAW_DBF_TEXT(2, setup, "snd_dsc");
p_connect=(struct conncmd *)&p_ctl->data;
rc=claw_send_control(dev, DISCONNECT, p_ctl->linkid,
p_ctl->correlator, 0,
p_connect->host_name, p_connect->WS_name);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
- dev->name,__func__, __LINE__, rc);
-#endif
return rc;
} /* end of claw_snd_disc */
@@ -3276,18 +2407,7 @@ claw_snd_sys_validate_rsp(struct net_device *dev,
struct claw_privbk *privptr;
int rc;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",
- dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"chkresp");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable return_code = %d, dev =\n",
- dev->name, return_code);
- dumpit((char *) dev, sizeof(struct net_device));
- printk(KERN_INFO "%s: variable p_ctl =\n",dev->name);
- dumpit((char *) p_ctl, sizeof(struct clawctl));
-#endif
+ CLAW_DBF_TEXT(2, setup, "chkresp");
privptr = dev->priv;
p_env=privptr->p_env;
rc=claw_send_control(dev, SYSTEM_VALIDATE_RESPONSE,
@@ -3296,10 +2416,6 @@ claw_snd_sys_validate_rsp(struct net_device *dev,
return_code,
p_env->host_name,
p_env->adapter_name );
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
- dev->name,__func__,__LINE__, rc);
-#endif
return rc;
} /* end of claw_snd_sys_validate_rsp */
@@ -3313,19 +2429,8 @@ claw_strt_conn_req(struct net_device *dev )
{
int rc;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"conn_req");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable dev =\n",dev->name);
- dumpit((char *) dev, sizeof(struct net_device));
-#endif
+ CLAW_DBF_TEXT(2, setup, "conn_req");
rc=claw_snd_conn_req(dev, 1);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
- dev->name,__func__,__LINE__, rc);
-#endif
return rc;
} /* end of claw_strt_conn_req */
@@ -3339,15 +2444,9 @@ static struct
net_device_stats *claw_stats(struct net_device *dev)
{
struct claw_privbk *privptr;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"stats");
+
+ CLAW_DBF_TEXT(4, trace, "stats");
privptr = dev->priv;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
return &privptr->stats;
} /* end of claw_stats */
@@ -3368,36 +2467,28 @@ unpack_read(struct net_device *dev )
struct clawph *p_packh;
void *p_packd;
struct clawctl *p_ctlrec=NULL;
+ struct device *p_dev;
__u32 len_of_data;
__u32 pack_off;
__u8 link_num;
__u8 mtc_this_frm=0;
__u32 bytes_to_mov;
- struct chbk *p_ch = NULL;
int i=0;
int p=0;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s enter \n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"unpkread");
+ CLAW_DBF_TEXT(4, trace, "unpkread");
p_first_ccw=NULL;
p_last_ccw=NULL;
p_packh=NULL;
p_packd=NULL;
privptr=dev->priv;
+
+ p_dev = &privptr->channel[READ].cdev->dev;
p_env = privptr->p_env;
p_this_ccw=privptr->p_read_active_first;
i=0;
while (p_this_ccw!=NULL && p_this_ccw->header.flag!=CLAW_PENDING) {
-#ifdef IOTRACE
- printk(KERN_INFO "%s p_this_ccw \n",dev->name);
- dumpit((char*)p_this_ccw, sizeof(struct ccwbk));
- printk(KERN_INFO "%s Inbound p_this_ccw->p_buffer(64)"
- " pk=%d \n",dev->name,p_env->packing);
- dumpit((char *)p_this_ccw->p_buffer, 64 );
-#endif
pack_off = 0;
p = 0;
p_this_ccw->header.flag=CLAW_PENDING;
@@ -3419,10 +2510,6 @@ unpack_read(struct net_device *dev )
else
link_num=p_this_ccw->header.opcode / 8;
if ((p_this_ccw->header.opcode & MORE_to_COME_FLAG)!=0) {
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s > More_to_come is ON\n",
- dev->name,__func__);
-#endif
mtc_this_frm=1;
if (p_this_ccw->header.length!=
privptr->p_env->read_size ) {
@@ -3445,22 +2532,12 @@ unpack_read(struct net_device *dev )
privptr->mtc_skipping=0; /* Ok, the end */
privptr->mtc_logical_link=-1;
}
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s goto next "
- "frame from MoretoComeSkip \n",
- dev->name,__func__);
-#endif
goto NextFrame;
}
if (link_num==0) {
claw_process_control(dev, p_this_ccw);
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s goto next "
- "frame from claw_process_control \n",
- dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"UnpkCntl");
+ CLAW_DBF_TEXT(4, trace, "UnpkCntl");
goto NextFrame;
}
unpack_next:
@@ -3479,10 +2556,6 @@ unpack_next:
bytes_to_mov=p_this_ccw->header.length;
}
if (privptr->mtc_logical_link<0) {
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s mtc_logical_link < 0 \n",
- dev->name,__func__);
-#endif
/*
* if More-To-Come is set in this frame then we don't know
@@ -3496,15 +2569,6 @@ unpack_next:
if (bytes_to_mov > (MAX_ENVELOPE_SIZE- privptr->mtc_offset) ) {
/* error */
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s > goto next "
- "frame from MoretoComeSkip \n",
- dev->name,
- __func__);
- printk(KERN_INFO " bytes_to_mov %d > (MAX_ENVELOPE_"
- "SIZE-privptr->mtc_offset %d)\n",
- bytes_to_mov,(MAX_ENVELOPE_SIZE- privptr->mtc_offset));
-#endif
privptr->stats.rx_frame_errors++;
goto NextFrame;
}
@@ -3516,16 +2580,6 @@ unpack_next:
memcpy( privptr->p_mtc_envelope+ privptr->mtc_offset,
p_this_ccw->p_buffer, bytes_to_mov);
}
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() received data \n",
- dev->name,__func__);
- if (p_env->packing == DO_PACKED)
- dumpit((char *)p_packd+sizeof(struct clawph),32);
- else
- dumpit((char *)p_this_ccw->p_buffer, 32);
- printk(KERN_INFO "%s: %s() bytelength %d \n",
- dev->name,__func__,bytes_to_mov);
-#endif
if (mtc_this_frm==0) {
len_of_data=privptr->mtc_offset+bytes_to_mov;
skb=dev_alloc_skb(len_of_data);
@@ -3540,11 +2594,6 @@ unpack_next:
privptr->stats.rx_packets++;
privptr->stats.rx_bytes+=len_of_data;
netif_rx(skb);
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() netif_"
- "rx(skb) completed \n",
- dev->name,__func__);
-#endif
}
else {
privptr->stats.rx_dropped++;
@@ -3581,28 +2630,14 @@ NextFrame:
* chain to next block on active read queue
*/
p_this_ccw = privptr->p_read_active_first;
- CLAW_DBF_TEXT_(4,trace,"rxpkt %d",p);
+ CLAW_DBF_TEXT_(4, trace, "rxpkt %d", p);
} /* end of while */
/* check validity */
-#ifdef IOTRACE
- printk(KERN_INFO "%s:%s processed frame is %d \n",
- dev->name,__func__,i);
- printk(KERN_INFO "%s:%s F:%lx L:%lx\n",
- dev->name,
- __func__,
- (unsigned long)p_first_ccw,
- (unsigned long)p_last_ccw);
-#endif
- CLAW_DBF_TEXT_(4,trace,"rxfrm %d",i);
+ CLAW_DBF_TEXT_(4, trace, "rxfrm %d", i);
add_claw_reads(dev, p_first_ccw, p_last_ccw);
- p_ch=&privptr->channel[READ];
claw_strt_read(dev, LOCK_YES);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s exit on line %d\n",
- dev->name, __func__, __LINE__);
-#endif
return;
} /* end of unpack_read */
@@ -3622,12 +2657,7 @@ claw_strt_read (struct net_device *dev, int lock )
struct clawh *p_clawh;
p_ch=&privptr->channel[READ];
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
- printk(KERN_INFO "%s: variable lock = %d, dev =\n",dev->name, lock);
- dumpit((char *) dev, sizeof(struct net_device));
-#endif
- CLAW_DBF_TEXT(4,trace,"StRdNter");
+ CLAW_DBF_TEXT(4, trace, "StRdNter");
p_clawh=(struct clawh *)privptr->p_claw_signal_blk;
p_clawh->flag=CLAW_IDLE; /* 0x00 */
@@ -3637,21 +2667,11 @@ claw_strt_read (struct net_device *dev, int lock )
privptr->p_read_active_first->header.flag!=CLAW_PENDING )) {
p_clawh->flag=CLAW_BUSY; /* 0xff */
}
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s state-%02x\n" ,
- dev->name,__func__, p_ch->claw_state);
-#endif
if (lock==LOCK_YES) {
spin_lock_irqsave(get_ccwdev_lock(p_ch->cdev), saveflags);
}
if (test_and_set_bit(0, (void *)&p_ch->IO_active) == 0) {
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: HOT READ started in %s\n" ,
- dev->name,__func__);
- p_clawh=(struct clawh *)privptr->p_claw_signal_blk;
- dumpit((char *)&p_clawh->flag , 1);
-#endif
- CLAW_DBF_TEXT(4,trace,"HotRead");
+ CLAW_DBF_TEXT(4, trace, "HotRead");
p_ccwbk=privptr->p_read_active_first;
parm = (unsigned long) p_ch;
rc = ccw_device_start (p_ch->cdev, &p_ccwbk->read, parm,
@@ -3661,21 +2681,13 @@ claw_strt_read (struct net_device *dev, int lock )
}
}
else {
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: No READ started by %s() In progress\n" ,
- dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,trace,"ReadAct");
+ CLAW_DBF_TEXT(2, trace, "ReadAct");
}
if (lock==LOCK_YES) {
spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags);
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"StRdExit");
+ CLAW_DBF_TEXT(4, trace, "StRdExit");
return;
} /* end of claw_strt_read */
@@ -3693,38 +2705,23 @@ claw_strt_out_IO( struct net_device *dev )
struct chbk *p_ch;
struct ccwbk *p_first_ccw;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
if (!dev) {
return;
}
privptr=(struct claw_privbk *)dev->priv;
p_ch=&privptr->channel[WRITE];
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s state-%02x\n" ,
- dev->name,__func__,p_ch->claw_state);
-#endif
- CLAW_DBF_TEXT(4,trace,"strt_io");
+ CLAW_DBF_TEXT(4, trace, "strt_io");
p_first_ccw=privptr->p_write_active_first;
if (p_ch->claw_state == CLAW_STOP)
return;
if (p_first_ccw == NULL) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
return;
}
if (test_and_set_bit(0, (void *)&p_ch->IO_active) == 0) {
parm = (unsigned long) p_ch;
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s do_io \n" ,dev->name,__func__);
- dumpit((char *)p_first_ccw, sizeof(struct ccwbk));
-#endif
- CLAW_DBF_TEXT(2,trace,"StWrtIO");
+ CLAW_DBF_TEXT(2, trace, "StWrtIO");
rc = ccw_device_start (p_ch->cdev,&p_first_ccw->write, parm,
0xff, 0);
if (rc != 0) {
@@ -3732,11 +2729,6 @@ claw_strt_out_IO( struct net_device *dev )
}
}
dev->trans_start = jiffies;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
-
return;
} /* end of claw_strt_out_IO */
@@ -3754,32 +2746,11 @@ claw_free_wrt_buf( struct net_device *dev )
struct ccwbk*p_last_ccw;
struct ccwbk*p_this_ccw;
struct ccwbk*p_next_ccw;
-#ifdef IOTRACE
- struct ccwbk*p_buf;
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
- printk(KERN_INFO "%s: free count = %d variable dev =\n",
- dev->name,privptr->write_free_count);
-#endif
- CLAW_DBF_TEXT(4,trace,"freewrtb");
+
+ CLAW_DBF_TEXT(4, trace, "freewrtb");
/* scan the write queue to free any completed write packets */
p_first_ccw=NULL;
p_last_ccw=NULL;
-#ifdef IOTRACE
- printk(KERN_INFO "%s: Dump current CCW chain \n",dev->name );
- p_buf=privptr->p_write_active_first;
- while (p_buf!=NULL) {
- dumpit((char *)p_buf, sizeof(struct ccwbk));
- p_buf=p_buf->next;
- }
- if (p_buf==NULL) {
- printk(KERN_INFO "%s: privptr->p_write_"
- "active_first==NULL\n",dev->name );
- }
- p_buf=(struct ccwbk*)privptr->p_end_ccw;
- dumpit((char *)p_buf, sizeof(struct endccw));
-#endif
p_this_ccw=privptr->p_write_active_first;
while ( (p_this_ccw!=NULL) && (p_this_ccw->header.flag!=CLAW_PENDING))
{
@@ -3809,31 +2780,8 @@ claw_free_wrt_buf( struct net_device *dev )
/* whole chain removed? */
if (privptr->p_write_active_first==NULL) {
privptr->p_write_active_last=NULL;
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s p_write_"
- "active_first==NULL\n",dev->name,__func__);
-#endif
- }
-#ifdef IOTRACE
- printk(KERN_INFO "%s: Dump arranged CCW chain \n",dev->name );
- p_buf=privptr->p_write_active_first;
- while (p_buf!=NULL) {
- dumpit((char *)p_buf, sizeof(struct ccwbk));
- p_buf=p_buf->next;
}
- if (p_buf==NULL) {
- printk(KERN_INFO "%s: privptr->p_write_active_"
- "first==NULL\n",dev->name );
- }
- p_buf=(struct ccwbk*)privptr->p_end_ccw;
- dumpit((char *)p_buf, sizeof(struct endccw));
-#endif
-
- CLAW_DBF_TEXT_(4,trace,"FWC=%d",privptr->write_free_count);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d free_count =%d\n",
- dev->name,__func__, __LINE__,privptr->write_free_count);
-#endif
+ CLAW_DBF_TEXT_(4, trace, "FWC=%d", privptr->write_free_count);
return;
}
@@ -3845,14 +2793,11 @@ static void
claw_free_netdevice(struct net_device * dev, int free_dev)
{
struct claw_privbk *privptr;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"free_dev");
+ CLAW_DBF_TEXT(2, setup, "free_dev");
if (!dev)
return;
- CLAW_DBF_TEXT_(2,setup,"%s",dev->name);
+ CLAW_DBF_TEXT_(2, setup, "%s", dev->name);
privptr = dev->priv;
if (dev->flags & IFF_RUNNING)
claw_release(dev);
@@ -3865,10 +2810,7 @@ claw_free_netdevice(struct net_device * dev, int free_dev)
free_netdev(dev);
}
#endif
- CLAW_DBF_TEXT(2,setup,"feee_ok");
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit\n",dev->name,__func__);
-#endif
+ CLAW_DBF_TEXT(2, setup, "free_ok");
}
/**
@@ -3879,17 +2821,8 @@ claw_free_netdevice(struct net_device * dev, int free_dev)
static void
claw_init_netdevice(struct net_device * dev)
{
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"init_dev");
- CLAW_DBF_TEXT_(2,setup,"%s",dev->name);
- if (!dev) {
- printk(KERN_WARNING "claw:%s BAD Device exit line %d\n",
- __func__,__LINE__);
- CLAW_DBF_TEXT(2,setup,"baddev");
- return;
- }
+ CLAW_DBF_TEXT(2, setup, "init_dev");
+ CLAW_DBF_TEXT_(2, setup, "%s", dev->name);
dev->mtu = CLAW_DEFAULT_MTU_SIZE;
dev->hard_start_xmit = claw_tx;
dev->open = claw_open;
@@ -3901,10 +2834,7 @@ claw_init_netdevice(struct net_device * dev)
dev->type = ARPHRD_SLIP;
dev->tx_queue_len = 1300;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit\n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"initok");
+ CLAW_DBF_TEXT(2, setup, "initok");
return;
}
@@ -3921,10 +2851,7 @@ add_channel(struct ccw_device *cdev,int i,struct claw_privbk *privptr)
struct chbk *p_ch;
struct ccw_dev_id dev_id;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",cdev->dev.bus_id,__func__);
-#endif
- CLAW_DBF_TEXT_(2,setup,"%s",cdev->dev.bus_id);
+ CLAW_DBF_TEXT_(2, setup, "%s", cdev->dev.bus_id);
privptr->channel[i].flag = i+1; /* Read is 1 Write is 2 */
p_ch = &privptr->channel[i];
p_ch->cdev = cdev;
@@ -3932,18 +2859,8 @@ add_channel(struct ccw_device *cdev,int i,struct claw_privbk *privptr)
ccw_device_get_id(cdev, &dev_id);
p_ch->devno = dev_id.devno;
if ((p_ch->irb = kzalloc(sizeof (struct irb),GFP_KERNEL)) == NULL) {
- printk(KERN_WARNING "%s Out of memory in %s for irb\n",
- p_ch->id,__func__);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- p_ch->id,__func__,__LINE__);
-#endif
return -ENOMEM;
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- cdev->dev.bus_id,__func__,__LINE__);
-#endif
return 0;
}
@@ -3965,9 +2882,8 @@ claw_new_device(struct ccwgroup_device *cgdev)
int ret;
struct ccw_dev_id dev_id;
- pr_debug("%s() called\n", __func__);
printk(KERN_INFO "claw: add for %s\n",cgdev->cdev[READ]->dev.bus_id);
- CLAW_DBF_TEXT(2,setup,"new_dev");
+ CLAW_DBF_TEXT(2, setup, "new_dev");
privptr = cgdev->dev.driver_data;
cgdev->cdev[READ]->dev.driver_data = privptr;
cgdev->cdev[WRITE]->dev.driver_data = privptr;
@@ -3982,22 +2898,21 @@ claw_new_device(struct ccwgroup_device *cgdev)
if (ret == 0)
ret = add_channel(cgdev->cdev[1],1,privptr);
if (ret != 0) {
- printk(KERN_WARNING
- "add channel failed "
- "with ret = %d\n", ret);
- goto out;
+ printk(KERN_WARNING
+ "add channel failed with ret = %d\n", ret);
+ goto out;
}
ret = ccw_device_set_online(cgdev->cdev[READ]);
if (ret != 0) {
printk(KERN_WARNING
- "claw: ccw_device_set_online %s READ failed "
+ "claw: ccw_device_set_online %s READ failed "
"with ret = %d\n",cgdev->cdev[READ]->dev.bus_id,ret);
goto out;
}
ret = ccw_device_set_online(cgdev->cdev[WRITE]);
if (ret != 0) {
printk(KERN_WARNING
- "claw: ccw_device_set_online %s WRITE failed "
+ "claw: ccw_device_set_online %s WRITE failed "
"with ret = %d\n",cgdev->cdev[WRITE]->dev.bus_id, ret);
goto out;
}
@@ -4014,18 +2929,16 @@ claw_new_device(struct ccwgroup_device *cgdev)
SET_NETDEV_DEV(dev, &cgdev->dev);
if (register_netdev(dev) != 0) {
claw_free_netdevice(dev, 1);
- CLAW_DBF_TEXT(2,trace,"regfail");
+ CLAW_DBF_TEXT(2, trace, "regfail");
goto out;
}
dev->flags &=~IFF_RUNNING;
if (privptr->buffs_alloc == 0) {
ret=init_ccw_bk(dev);
if (ret !=0) {
- printk(KERN_WARNING
- "claw: init_ccw_bk failed with ret=%d\n", ret);
unregister_netdev(dev);
claw_free_netdevice(dev,1);
- CLAW_DBF_TEXT(2,trace,"ccwmem");
+ CLAW_DBF_TEXT(2, trace, "ccwmem");
goto out;
}
}
@@ -4047,7 +2960,6 @@ claw_new_device(struct ccwgroup_device *cgdev)
out:
ccw_device_set_offline(cgdev->cdev[1]);
ccw_device_set_offline(cgdev->cdev[0]);
-
return -ENODEV;
}
@@ -4056,8 +2968,7 @@ claw_purge_skb_queue(struct sk_buff_head *q)
{
struct sk_buff *skb;
- CLAW_DBF_TEXT(4,trace,"purgque");
-
+ CLAW_DBF_TEXT(4, trace, "purgque");
while ((skb = skb_dequeue(q))) {
atomic_dec(&skb->users);
dev_kfree_skb_any(skb);
@@ -4078,8 +2989,7 @@ claw_shutdown_device(struct ccwgroup_device *cgdev)
struct net_device *ndev;
int ret;
- pr_debug("%s() called\n", __func__);
- CLAW_DBF_TEXT_(2,setup,"%s",cgdev->dev.bus_id);
+ CLAW_DBF_TEXT_(2, setup, "%s", cgdev->dev.bus_id);
priv = cgdev->dev.driver_data;
if (!priv)
return -ENODEV;
@@ -4108,13 +3018,10 @@ claw_remove_device(struct ccwgroup_device *cgdev)
{
struct claw_privbk *priv;
- pr_debug("%s() called\n", __func__);
- CLAW_DBF_TEXT_(2,setup,"%s",cgdev->dev.bus_id);
+ BUG_ON(!cgdev);
+ CLAW_DBF_TEXT_(2, setup, "%s", cgdev->dev.bus_id);
priv = cgdev->dev.driver_data;
- if (!priv) {
- printk(KERN_WARNING "claw: %s() no Priv exiting\n",__func__);
- return;
- }
+ BUG_ON(!priv);
printk(KERN_INFO "claw: %s() called %s will be removed.\n",
__func__,cgdev->cdev[0]->dev.bus_id);
if (cgdev->state == CCWGROUP_ONLINE)
@@ -4133,6 +3040,8 @@ claw_remove_device(struct ccwgroup_device *cgdev)
cgdev->cdev[READ]->dev.driver_data = NULL;
cgdev->cdev[WRITE]->dev.driver_data = NULL;
put_device(&cgdev->dev);
+
+ return;
}
@@ -4168,8 +3077,8 @@ claw_hname_write(struct device *dev, struct device_attribute *attr, const char *
strncpy(p_env->host_name,buf, count);
p_env->host_name[count-1] = 0x20; /* clear extra 0x0a */
p_env->host_name[MAX_NAME_LEN] = 0x00;
- CLAW_DBF_TEXT(2,setup,"HstnSet");
- CLAW_DBF_TEXT_(2,setup,"%s",p_env->host_name);
+ CLAW_DBF_TEXT(2, setup, "HstnSet");
+ CLAW_DBF_TEXT_(2, setup, "%s", p_env->host_name);
return count;
}
@@ -4186,7 +3095,7 @@ claw_adname_show(struct device *dev, struct device_attribute *attr, char *buf)
if (!priv)
return -ENODEV;
p_env = priv->p_env;
- return sprintf(buf, "%s\n",p_env->adapter_name);
+ return sprintf(buf, "%s\n", p_env->adapter_name);
}
static ssize_t
@@ -4205,8 +3114,8 @@ claw_adname_write(struct device *dev, struct device_attribute *attr, const char
strncpy(p_env->adapter_name,buf, count);
p_env->adapter_name[count-1] = 0x20; /* clear extra 0x0a */
p_env->adapter_name[MAX_NAME_LEN] = 0x00;
- CLAW_DBF_TEXT(2,setup,"AdnSet");
- CLAW_DBF_TEXT_(2,setup,"%s",p_env->adapter_name);
+ CLAW_DBF_TEXT(2, setup, "AdnSet");
+ CLAW_DBF_TEXT_(2, setup, "%s", p_env->adapter_name);
return count;
}
@@ -4247,15 +3156,15 @@ claw_apname_write(struct device *dev, struct device_attribute *attr, const char
p_env->read_size=DEF_PACK_BUFSIZE;
p_env->write_size=DEF_PACK_BUFSIZE;
p_env->packing=PACKING_ASK;
- CLAW_DBF_TEXT(2,setup,"PACKING");
+ CLAW_DBF_TEXT(2, setup, "PACKING");
}
else {
p_env->packing=0;
p_env->read_size=CLAW_FRAME_SIZE;
p_env->write_size=CLAW_FRAME_SIZE;
- CLAW_DBF_TEXT(2,setup,"ApiSet");
+ CLAW_DBF_TEXT(2, setup, "ApiSet");
}
- CLAW_DBF_TEXT_(2,setup,"%s",p_env->api_type);
+ CLAW_DBF_TEXT_(2, setup, "%s", p_env->api_type);
return count;
}
@@ -4295,8 +3204,8 @@ claw_wbuff_write(struct device *dev, struct device_attribute *attr, const char *
if ((nnn > max ) || (nnn < 2))
return -EINVAL;
p_env->write_buffers = nnn;
- CLAW_DBF_TEXT(2,setup,"Wbufset");
- CLAW_DBF_TEXT_(2,setup,"WB=%d",p_env->write_buffers);
+ CLAW_DBF_TEXT(2, setup, "Wbufset");
+ CLAW_DBF_TEXT_(2, setup, "WB=%d", p_env->write_buffers);
return count;
}
@@ -4336,8 +3245,8 @@ claw_rbuff_write(struct device *dev, struct device_attribute *attr, const char *
if ((nnn > max ) || (nnn < 2))
return -EINVAL;
p_env->read_buffers = nnn;
- CLAW_DBF_TEXT(2,setup,"Rbufset");
- CLAW_DBF_TEXT_(2,setup,"RB=%d",p_env->read_buffers);
+ CLAW_DBF_TEXT(2, setup, "Rbufset");
+ CLAW_DBF_TEXT_(2, setup, "RB=%d", p_env->read_buffers);
return count;
}
@@ -4359,16 +3268,14 @@ static struct attribute_group claw_attr_group = {
static int
claw_add_files(struct device *dev)
{
- pr_debug("%s() called\n", __func__);
- CLAW_DBF_TEXT(2,setup,"add_file");
+ CLAW_DBF_TEXT(2, setup, "add_file");
return sysfs_create_group(&dev->kobj, &claw_attr_group);
}
static void
claw_remove_files(struct device *dev)
{
- pr_debug("%s() called\n", __func__);
- CLAW_DBF_TEXT(2,setup,"rem_file");
+ CLAW_DBF_TEXT(2, setup, "rem_file");
sysfs_remove_group(&dev->kobj, &claw_attr_group);
}
@@ -4397,35 +3304,27 @@ claw_init(void)
int ret = 0;
printk(KERN_INFO "claw: starting driver\n");
-#ifdef FUNCTRACE
- printk(KERN_INFO "claw: %s() enter \n",__func__);
-#endif
ret = claw_register_debug_facility();
if (ret) {
printk(KERN_WARNING "claw: %s() debug_register failed %d\n",
__func__,ret);
return ret;
}
- CLAW_DBF_TEXT(2,setup,"init_mod");
+ CLAW_DBF_TEXT(2, setup, "init_mod");
ret = register_cu3088_discipline(&claw_group_driver);
if (ret) {
+ CLAW_DBF_TEXT(2, setup, "init_bad");
claw_unregister_debug_facility();
printk(KERN_WARNING "claw; %s() cu3088 register failed %d\n",
__func__,ret);
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "claw: %s() exit \n",__func__);
-#endif
return ret;
}
module_init(claw_init);
module_exit(claw_cleanup);
-
-
-/*--------------------------------------------------------------------*
-* End of File *
-*---------------------------------------------------------------------*/
-
-
+MODULE_AUTHOR("Andy Richter <richtera@us.ibm.com>");
+MODULE_DESCRIPTION("Linux for System z CLAW Driver\n" \
+ "Copyright 2000,2008 IBM Corporation\n");
+MODULE_LICENSE("GPL");
diff --git a/drivers/s390/net/ctcm_dbug.c b/drivers/s390/net/ctcm_dbug.c
index 8eb25d00b2e..1ca58f15347 100644
--- a/drivers/s390/net/ctcm_dbug.c
+++ b/drivers/s390/net/ctcm_dbug.c
@@ -7,6 +7,7 @@
*/
#include <linux/stddef.h>
+#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
@@ -22,15 +23,13 @@
* Debug Facility Stuff
*/
-DEFINE_PER_CPU(char[256], ctcm_dbf_txt_buf);
-
struct ctcm_dbf_info ctcm_dbf[CTCM_DBF_INFOS] = {
- [CTCM_DBF_SETUP] = {"ctc_setup", 8, 1, 64, 5, NULL},
- [CTCM_DBF_ERROR] = {"ctc_error", 8, 1, 64, 3, NULL},
- [CTCM_DBF_TRACE] = {"ctc_trace", 8, 1, 64, 3, NULL},
- [CTCM_DBF_MPC_SETUP] = {"mpc_setup", 8, 1, 64, 5, NULL},
- [CTCM_DBF_MPC_ERROR] = {"mpc_error", 8, 1, 64, 3, NULL},
- [CTCM_DBF_MPC_TRACE] = {"mpc_trace", 8, 1, 64, 3, NULL},
+ [CTCM_DBF_SETUP] = {"ctc_setup", 8, 1, 64, CTC_DBF_INFO, NULL},
+ [CTCM_DBF_ERROR] = {"ctc_error", 8, 1, 64, CTC_DBF_ERROR, NULL},
+ [CTCM_DBF_TRACE] = {"ctc_trace", 8, 1, 64, CTC_DBF_ERROR, NULL},
+ [CTCM_DBF_MPC_SETUP] = {"mpc_setup", 8, 1, 80, CTC_DBF_INFO, NULL},
+ [CTCM_DBF_MPC_ERROR] = {"mpc_error", 8, 1, 80, CTC_DBF_ERROR, NULL},
+ [CTCM_DBF_MPC_TRACE] = {"mpc_trace", 8, 1, 80, CTC_DBF_ERROR, NULL},
};
void ctcm_unregister_dbf_views(void)
@@ -65,3 +64,17 @@ int ctcm_register_dbf_views(void)
return 0;
}
+void ctcm_dbf_longtext(enum ctcm_dbf_names dbf_nix, int level, char *fmt, ...)
+{
+ char dbf_txt_buf[64];
+ va_list args;
+
+ if (level > (ctcm_dbf[dbf_nix].id)->level)
+ return;
+ va_start(args, fmt);
+ vsnprintf(dbf_txt_buf, sizeof(dbf_txt_buf), fmt, args);
+ va_end(args);
+
+ debug_text_event(ctcm_dbf[dbf_nix].id, level, dbf_txt_buf);
+}
+
diff --git a/drivers/s390/net/ctcm_dbug.h b/drivers/s390/net/ctcm_dbug.h
index fdff34fe59a..26966d0b9ab 100644
--- a/drivers/s390/net/ctcm_dbug.h
+++ b/drivers/s390/net/ctcm_dbug.h
@@ -20,16 +20,17 @@
#else
#define do_debug 0
#endif
-#ifdef DEBUGDATA
- #define do_debug_data 1
-#else
- #define do_debug_data 0
-#endif
#ifdef DEBUGCCW
#define do_debug_ccw 1
+ #define DEBUGDATA 1
#else
#define do_debug_ccw 0
#endif
+#ifdef DEBUGDATA
+ #define do_debug_data 1
+#else
+ #define do_debug_data 0
+#endif
/* define dbf debug levels similar to kernel msg levels */
#define CTC_DBF_ALWAYS 0 /* always print this */
@@ -42,8 +43,6 @@
#define CTC_DBF_INFO 5 /* informational */
#define CTC_DBF_DEBUG 6 /* debug-level messages */
-DECLARE_PER_CPU(char[256], ctcm_dbf_txt_buf);
-
enum ctcm_dbf_names {
CTCM_DBF_SETUP,
CTCM_DBF_ERROR,
@@ -67,6 +66,7 @@ extern struct ctcm_dbf_info ctcm_dbf[CTCM_DBF_INFOS];
int ctcm_register_dbf_views(void);
void ctcm_unregister_dbf_views(void);
+void ctcm_dbf_longtext(enum ctcm_dbf_names dbf_nix, int level, char *text, ...);
static inline const char *strtail(const char *s, int n)
{
@@ -74,12 +74,6 @@ static inline const char *strtail(const char *s, int n)
return (l > n) ? s + (l - n) : s;
}
-/* sort out levels early to avoid unnecessary sprintfs */
-static inline int ctcm_dbf_passes(debug_info_t *dbf_grp, int level)
-{
- return (dbf_grp->level >= level);
-}
-
#define CTCM_FUNTAIL strtail((char *)__func__, 16)
#define CTCM_DBF_TEXT(name, level, text) \
@@ -94,16 +88,7 @@ static inline int ctcm_dbf_passes(debug_info_t *dbf_grp, int level)
} while (0)
#define CTCM_DBF_TEXT_(name, level, text...) \
- do { \
- if (ctcm_dbf_passes(ctcm_dbf[CTCM_DBF_##name].id, level)) { \
- char *ctcm_dbf_txt_buf = \
- get_cpu_var(ctcm_dbf_txt_buf); \
- sprintf(ctcm_dbf_txt_buf, text); \
- debug_text_event(ctcm_dbf[CTCM_DBF_##name].id, \
- level, ctcm_dbf_txt_buf); \
- put_cpu_var(ctcm_dbf_txt_buf); \
- } \
- } while (0)
+ ctcm_dbf_longtext(CTCM_DBF_##name, level, text)
/*
* cat : one of {setup, mpc_setup, trace, mpc_trace, error, mpc_error}.
@@ -112,13 +97,13 @@ static inline int ctcm_dbf_passes(debug_info_t *dbf_grp, int level)
*/
#define CTCM_DBF_DEV_NAME(cat, dev, text) \
do { \
- CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%s) : %s", \
+ CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%s) :- %s", \
CTCM_FUNTAIL, dev->name, text); \
} while (0)
#define MPC_DBF_DEV_NAME(cat, dev, text) \
do { \
- CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%s) : %s", \
+ CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%s) := %s", \
CTCM_FUNTAIL, dev->name, text); \
} while (0)
@@ -137,13 +122,13 @@ static inline int ctcm_dbf_passes(debug_info_t *dbf_grp, int level)
*/
#define CTCM_DBF_DEV(cat, dev, text) \
do { \
- CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%p) : %s", \
+ CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%p) :-: %s", \
CTCM_FUNTAIL, dev, text); \
} while (0)
#define MPC_DBF_DEV(cat, dev, text) \
do { \
- CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%p) : %s", \
+ CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%p) :=: %s", \
CTCM_FUNTAIL, dev, text); \
} while (0)
diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c
index 7e6bd387f4d..0b4e6253abe 100644
--- a/drivers/s390/net/ctcm_fsms.c
+++ b/drivers/s390/net/ctcm_fsms.c
@@ -190,7 +190,8 @@ static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg);
void ctcm_ccw_check_rc(struct channel *ch, int rc, char *msg)
{
CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
- "ccw error %s (%s): %04x\n", ch->id, msg, rc);
+ "%s(%s): %s: %04x\n",
+ CTCM_FUNTAIL, ch->id, msg, rc);
switch (rc) {
case -EBUSY:
ctcm_pr_warn("%s (%s): Busy !\n", ch->id, msg);
@@ -212,7 +213,7 @@ void ctcm_purge_skb_queue(struct sk_buff_head *q)
{
struct sk_buff *skb;
- CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
+ CTCM_DBF_TEXT(TRACE, CTC_DBF_DEBUG, __func__);
while ((skb = skb_dequeue(q))) {
atomic_dec(&skb->users);
@@ -251,6 +252,8 @@ static void chx_txdone(fsm_instance *fi, int event, void *arg)
unsigned long duration;
struct timespec done_stamp = current_kernel_time(); /* xtime */
+ CTCM_PR_DEBUG("%s(%s): %s\n", __func__, ch->id, dev->name);
+
duration =
(done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000 +
(done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
@@ -258,8 +261,9 @@ static void chx_txdone(fsm_instance *fi, int event, void *arg)
ch->prof.tx_time = duration;
if (ch->irb->scsw.cmd.count != 0)
- ctcm_pr_debug("%s: TX not complete, remaining %d bytes\n",
- dev->name, ch->irb->scsw.cmd.count);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+ "%s(%s): TX not complete, remaining %d bytes",
+ CTCM_FUNTAIL, dev->name, ch->irb->scsw.cmd.count);
fsm_deltimer(&ch->timer);
while ((skb = skb_dequeue(&ch->io_queue))) {
priv->stats.tx_packets++;
@@ -334,7 +338,8 @@ void ctcm_chx_txidle(fsm_instance *fi, int event, void *arg)
struct net_device *dev = ch->netdev;
struct ctcm_priv *priv = dev->priv;
- CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
+ CTCM_PR_DEBUG("%s(%s): %s\n", __func__, ch->id, dev->name);
+
fsm_deltimer(&ch->timer);
fsm_newstate(fi, CTC_STATE_TXIDLE);
fsm_event(priv->fsm, DEV_EVENT_TXUP, ch->netdev);
@@ -361,15 +366,17 @@ static void chx_rx(fsm_instance *fi, int event, void *arg)
fsm_deltimer(&ch->timer);
if (len < 8) {
- ctcm_pr_debug("%s: got packet with length %d < 8\n",
- dev->name, len);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+ "%s(%s): got packet with length %d < 8\n",
+ CTCM_FUNTAIL, dev->name, len);
priv->stats.rx_dropped++;
priv->stats.rx_length_errors++;
goto again;
}
if (len > ch->max_bufsize) {
- ctcm_pr_debug("%s: got packet with length %d > %d\n",
- dev->name, len, ch->max_bufsize);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+ "%s(%s): got packet with length %d > %d\n",
+ CTCM_FUNTAIL, dev->name, len, ch->max_bufsize);
priv->stats.rx_dropped++;
priv->stats.rx_length_errors++;
goto again;
@@ -388,8 +395,9 @@ static void chx_rx(fsm_instance *fi, int event, void *arg)
break;
}
if ((len < block_len) || (len > check_len)) {
- ctcm_pr_debug("%s: got block length %d != rx length %d\n",
- dev->name, block_len, len);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+ "%s(%s): got block length %d != rx length %d\n",
+ CTCM_FUNTAIL, dev->name, block_len, len);
if (do_debug)
ctcmpc_dump_skb(skb, 0);
@@ -425,17 +433,23 @@ static void chx_rx(fsm_instance *fi, int event, void *arg)
*/
static void chx_firstio(fsm_instance *fi, int event, void *arg)
{
- struct channel *ch = arg;
int rc;
+ struct channel *ch = arg;
+ int fsmstate = fsm_getstate(fi);
- CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+ "%s(%s) : %02x",
+ CTCM_FUNTAIL, ch->id, fsmstate);
- if (fsm_getstate(fi) == CTC_STATE_TXIDLE)
- ctcm_pr_debug("%s: remote side issued READ?, init.\n", ch->id);
+ ch->sense_rc = 0; /* reset unit check report control */
+ if (fsmstate == CTC_STATE_TXIDLE)
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+ "%s(%s): remote side issued READ?, init.\n",
+ CTCM_FUNTAIL, ch->id);
fsm_deltimer(&ch->timer);
if (ctcm_checkalloc_buffer(ch))
return;
- if ((fsm_getstate(fi) == CTC_STATE_SETUPWAIT) &&
+ if ((fsmstate == CTC_STATE_SETUPWAIT) &&
(ch->protocol == CTCM_PROTO_OS390)) {
/* OS/390 resp. z/OS */
if (CHANNEL_DIRECTION(ch->flags) == READ) {
@@ -451,7 +465,6 @@ static void chx_firstio(fsm_instance *fi, int event, void *arg)
}
return;
}
-
/*
* Don't setup a timer for receiving the initial RX frame
* if in compatibility mode, since VM TCP delays the initial
@@ -505,11 +518,10 @@ static void chx_rxidle(fsm_instance *fi, int event, void *arg)
__u16 buflen;
int rc;
- CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
fsm_deltimer(&ch->timer);
buflen = *((__u16 *)ch->trans_skb->data);
- if (do_debug)
- ctcm_pr_debug("%s: Initial RX count %d\n", dev->name, buflen);
+ CTCM_PR_DEBUG("%s: %s: Initial RX count = %d\n",
+ __func__, dev->name, buflen);
if (buflen >= CTCM_INITIAL_BLOCKLEN) {
if (ctcm_checkalloc_buffer(ch))
@@ -524,9 +536,9 @@ static void chx_rxidle(fsm_instance *fi, int event, void *arg)
} else
fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);
} else {
- if (do_debug)
- ctcm_pr_debug("%s: Initial RX count %d not %d\n",
- dev->name, buflen, CTCM_INITIAL_BLOCKLEN);
+ CTCM_PR_DEBUG("%s: %s: Initial RX count %d not %d\n",
+ __func__, dev->name,
+ buflen, CTCM_INITIAL_BLOCKLEN);
chx_firstio(fi, event, arg);
}
}
@@ -548,14 +560,12 @@ static void ctcm_chx_setmode(fsm_instance *fi, int event, void *arg)
fsm_deltimer(&ch->timer);
if (IS_MPC(ch)) {
timeout = 1500;
- if (do_debug)
- ctcm_pr_debug("ctcm enter: %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id);
+ CTCM_PR_DEBUG("enter %s: cp=%i ch=0x%p id=%s\n",
+ __func__, smp_processor_id(), ch, ch->id);
}
fsm_addtimer(&ch->timer, timeout, CTC_EVENT_TIMER, ch);
fsm_newstate(fi, CTC_STATE_SETUPWAIT);
- if (do_debug_ccw && IS_MPC(ch))
- ctcmpc_dumpit((char *)&ch->ccw[6], sizeof(struct ccw1) * 2);
+ CTCM_CCW_DUMP((char *)&ch->ccw[6], sizeof(struct ccw1) * 2);
if (event == CTC_EVENT_TIMER) /* only for timer not yet locked */
spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
@@ -583,24 +593,12 @@ static void ctcm_chx_setmode(fsm_instance *fi, int event, void *arg)
*/
static void ctcm_chx_start(fsm_instance *fi, int event, void *arg)
{
- struct channel *ch = arg;
- int rc;
- struct net_device *dev;
+ struct channel *ch = arg;
unsigned long saveflags;
+ int rc;
- CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
- if (ch == NULL) {
- ctcm_pr_warn("chx_start ch=NULL\n");
- return;
- }
- if (ch->netdev == NULL) {
- ctcm_pr_warn("chx_start dev=NULL, id=%s\n", ch->id);
- return;
- }
- dev = ch->netdev;
-
- if (do_debug)
- ctcm_pr_debug("%s: %s channel start\n", dev->name,
+ CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s): %s",
+ CTCM_FUNTAIL, ch->id,
(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
if (ch->trans_skb != NULL) {
@@ -618,11 +616,12 @@ static void ctcm_chx_start(fsm_instance *fi, int event, void *arg)
ch->ccw[1].count = 0;
}
if (ctcm_checkalloc_buffer(ch)) {
- ctcm_pr_notice("%s: %s trans_skb allocation delayed "
- "until first transfer\n", dev->name,
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+ "%s(%s): %s trans_skb alloc delayed "
+ "until first transfer",
+ CTCM_FUNTAIL, ch->id,
(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
}
-
ch->ccw[0].cmd_code = CCW_CMD_PREPARE;
ch->ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
ch->ccw[0].count = 0;
@@ -661,7 +660,6 @@ static void ctcm_chx_haltio(fsm_instance *fi, int event, void *arg)
int rc;
int oldstate;
- CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
fsm_deltimer(&ch->timer);
if (IS_MPC(ch))
fsm_deltimer(&ch->sweep_timer);
@@ -684,7 +682,7 @@ static void ctcm_chx_haltio(fsm_instance *fi, int event, void *arg)
fsm_deltimer(&ch->timer);
if (event != CTC_EVENT_STOP) {
fsm_newstate(fi, oldstate);
- ctcm_ccw_check_rc(ch, rc, (char *)__FUNCTION__);
+ ctcm_ccw_check_rc(ch, rc, (char *)__func__);
}
}
}
@@ -703,7 +701,9 @@ static void ctcm_chx_cleanup(fsm_instance *fi, int state,
struct net_device *dev = ch->netdev;
struct ctcm_priv *priv = dev->priv;
- CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
+ CTCM_DBF_TEXT_(SETUP, CTC_DBF_NOTICE,
+ "%s(%s): %s[%d]\n",
+ CTCM_FUNTAIL, dev->name, ch->id, state);
fsm_deltimer(&ch->timer);
if (IS_MPC(ch))
@@ -743,7 +743,6 @@ static void ctcm_chx_cleanup(fsm_instance *fi, int state,
*/
static void ctcm_chx_stopped(fsm_instance *fi, int event, void *arg)
{
- CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
ctcm_chx_cleanup(fi, CTC_STATE_STOPPED, arg);
}
@@ -771,7 +770,6 @@ static void ctcm_chx_stop(fsm_instance *fi, int event, void *arg)
*/
static void ctcm_chx_fail(fsm_instance *fi, int event, void *arg)
{
- CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
ctcm_chx_cleanup(fi, CTC_STATE_NOTOP, arg);
}
@@ -809,8 +807,8 @@ static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg)
}
CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT,
- "%s : %s error during %s channel setup state=%s\n",
- dev->name, ctc_ch_event_names[event],
+ "%s(%s) : %s error during %s channel setup state=%s\n",
+ CTCM_FUNTAIL, dev->name, ctc_ch_event_names[event],
(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX",
fsm_getstate_str(fi));
@@ -838,10 +836,12 @@ static void ctcm_chx_restart(fsm_instance *fi, int event, void *arg)
int oldstate;
int rc;
- CTCM_DBF_TEXT(TRACE, CTC_DBF_NOTICE, __FUNCTION__);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+ "%s: %s[%d] of %s\n",
+ CTCM_FUNTAIL, ch->id, event, dev->name);
+
fsm_deltimer(&ch->timer);
- ctcm_pr_debug("%s: %s channel restart\n", dev->name,
- (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+
fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
oldstate = fsm_getstate(fi);
fsm_newstate(fi, CTC_STATE_STARTWAIT);
@@ -876,13 +876,10 @@ static void ctcm_chx_rxiniterr(fsm_instance *fi, int event, void *arg)
struct net_device *dev = ch->netdev;
struct ctcm_priv *priv = dev->priv;
- CTCM_DBF_TEXT(SETUP, 3, __FUNCTION__);
if (event == CTC_EVENT_TIMER) {
if (!IS_MPCDEV(dev))
/* TODO : check if MPC deletes timer somewhere */
fsm_deltimer(&ch->timer);
- ctcm_pr_debug("%s: Timeout during RX init handshake\n",
- dev->name);
if (ch->retry++ < 3)
ctcm_chx_restart(fi, event, arg);
else {
@@ -907,9 +904,10 @@ static void ctcm_chx_rxinitfail(fsm_instance *fi, int event, void *arg)
struct net_device *dev = ch->netdev;
struct ctcm_priv *priv = dev->priv;
- CTCM_DBF_TEXT(SETUP, 3, __FUNCTION__);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): RX %s busy, init. fail",
+ CTCM_FUNTAIL, dev->name, ch->id);
fsm_newstate(fi, CTC_STATE_RXERR);
- ctcm_pr_warn("%s: RX busy. Initialization failed\n", dev->name);
fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
}
@@ -927,11 +925,10 @@ static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg)
struct net_device *dev = ch->netdev;
struct ctcm_priv *priv = dev->priv;
- CTCM_DBF_DEV_NAME(TRACE, dev, "Got remote disconnect, re-initializing");
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+ "%s: %s: remote disconnect - re-init ...",
+ CTCM_FUNTAIL, dev->name);
fsm_deltimer(&ch->timer);
- if (do_debug)
- ctcm_pr_debug("%s: Got remote disconnect, "
- "re-initializing ...\n", dev->name);
/*
* Notify device statemachine
*/
@@ -961,8 +958,6 @@ static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg)
if (event == CTC_EVENT_TIMER) {
fsm_deltimer(&ch->timer);
- CTCM_DBF_DEV_NAME(ERROR, dev,
- "Timeout during TX init handshake");
if (ch->retry++ < 3)
ctcm_chx_restart(fi, event, arg);
else {
@@ -971,9 +966,8 @@ static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg)
}
} else {
CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
- "%s : %s error during channel setup state=%s",
- dev->name, ctc_ch_event_names[event],
- fsm_getstate_str(fi));
+ "%s(%s): %s in %s", CTCM_FUNTAIL, ch->id,
+ ctc_ch_event_names[event], fsm_getstate_str(fi));
ctcm_pr_warn("%s: Error during TX init handshake\n", dev->name);
}
@@ -993,15 +987,15 @@ static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg)
struct ctcm_priv *priv = dev->priv;
struct sk_buff *skb;
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id);
+ CTCM_PR_DEBUG("Enter: %s: cp=%i ch=0x%p id=%s\n",
+ __func__, smp_processor_id(), ch, ch->id);
fsm_deltimer(&ch->timer);
if (ch->retry++ > 3) {
struct mpc_group *gptr = priv->mpcg;
- ctcm_pr_debug("%s: TX retry failed, restarting channel\n",
- dev->name);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_INFO,
+ "%s: %s: retries exceeded",
+ CTCM_FUNTAIL, ch->id);
fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
/* call restart if not MPC or if MPC and mpcg fsm is ready.
use gptr as mpc indicator */
@@ -1010,7 +1004,9 @@ static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg)
goto done;
}
- ctcm_pr_debug("%s: TX retry %d\n", dev->name, ch->retry);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+ "%s : %s: retry %d",
+ CTCM_FUNTAIL, ch->id, ch->retry);
skb = skb_peek(&ch->io_queue);
if (skb) {
int rc = 0;
@@ -1018,8 +1014,9 @@ static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg)
clear_normalized_cda(&ch->ccw[4]);
ch->ccw[4].count = skb->len;
if (set_normalized_cda(&ch->ccw[4], skb->data)) {
- ctcm_pr_debug("%s: IDAL alloc failed, chan restart\n",
- dev->name);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_INFO,
+ "%s: %s: IDAL alloc failed",
+ CTCM_FUNTAIL, ch->id);
fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
ctcm_chx_restart(fi, event, arg);
goto done;
@@ -1061,22 +1058,21 @@ static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg)
struct channel *ch = arg;
struct net_device *dev = ch->netdev;
struct ctcm_priv *priv = dev->priv;
+ int rd = CHANNEL_DIRECTION(ch->flags);
- CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
fsm_deltimer(&ch->timer);
- ctcm_pr_warn("%s %s : unrecoverable channel error\n",
- CTC_DRIVER_NAME, dev->name);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s: %s: %s unrecoverable channel error",
+ CTCM_FUNTAIL, ch->id, rd == READ ? "RX" : "TX");
+
if (IS_MPC(ch)) {
priv->stats.tx_dropped++;
priv->stats.tx_errors++;
}
-
- if (CHANNEL_DIRECTION(ch->flags) == READ) {
- ctcm_pr_debug("%s: RX I/O error\n", dev->name);
+ if (rd == READ) {
fsm_newstate(fi, CTC_STATE_RXERR);
fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
} else {
- ctcm_pr_debug("%s: TX I/O error\n", dev->name);
fsm_newstate(fi, CTC_STATE_TXERR);
fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
}
@@ -1216,27 +1212,27 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
struct sk_buff *skb;
int first = 1;
int i;
- struct timespec done_stamp;
__u32 data_space;
unsigned long duration;
struct sk_buff *peekskb;
int rc;
struct th_header *header;
struct pdu *p_header;
+ struct timespec done_stamp = current_kernel_time(); /* xtime */
- if (do_debug)
- ctcm_pr_debug("%s cp:%i enter: %s()\n",
- dev->name, smp_processor_id(), __FUNCTION__);
+ CTCM_PR_DEBUG("Enter %s: %s cp:%i\n",
+ __func__, dev->name, smp_processor_id());
- done_stamp = current_kernel_time(); /* xtime */
- duration = (done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000
- + (done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
+ duration =
+ (done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000 +
+ (done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
if (duration > ch->prof.tx_time)
ch->prof.tx_time = duration;
if (ch->irb->scsw.cmd.count != 0)
- ctcm_pr_debug("%s: TX not complete, remaining %d bytes\n",
- dev->name, ch->irb->scsw.cmd.count);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
+ "%s(%s): TX not complete, remaining %d bytes",
+ CTCM_FUNTAIL, dev->name, ch->irb->scsw.cmd.count);
fsm_deltimer(&ch->timer);
while ((skb = skb_dequeue(&ch->io_queue))) {
priv->stats.tx_packets++;
@@ -1250,7 +1246,6 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
}
spin_lock(&ch->collect_lock);
clear_normalized_cda(&ch->ccw[4]);
-
if ((ch->collect_len <= 0) || (grp->in_sweep != 0)) {
spin_unlock(&ch->collect_lock);
fsm_newstate(fi, CTC_STATE_TXIDLE);
@@ -1269,17 +1264,13 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
if (ch->prof.maxcqueue < skb_queue_len(&ch->collect_queue))
ch->prof.maxcqueue = skb_queue_len(&ch->collect_queue);
i = 0;
-
- if (do_debug_data)
- ctcm_pr_debug("ctcmpc: %s() building "
- "trans_skb from collect_q \n", __FUNCTION__);
-
+ p_header = NULL;
data_space = grp->group_max_buflen - TH_HEADER_LENGTH;
- if (do_debug_data)
- ctcm_pr_debug("ctcmpc: %s() building trans_skb from collect_q"
- " data_space:%04x\n", __FUNCTION__, data_space);
- p_header = NULL;
+ CTCM_PR_DBGDATA("%s: building trans_skb from collect_q"
+ " data_space:%04x\n",
+ __func__, data_space);
+
while ((skb = skb_dequeue(&ch->collect_queue))) {
memcpy(skb_put(ch->trans_skb, skb->len), skb->data, skb->len);
p_header = (struct pdu *)
@@ -1290,15 +1281,12 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
else
p_header->pdu_flag |= 0x20;
- if (do_debug_data) {
- ctcm_pr_debug("ctcmpc: %s()trans_skb len:%04x \n",
- __FUNCTION__, ch->trans_skb->len);
- ctcm_pr_debug("ctcmpc: %s() pdu header and data"
- " for up to 32 bytes sent to vtam\n",
- __FUNCTION__);
- ctcmpc_dumpit((char *)p_header,
- min_t(int, skb->len, 32));
- }
+ CTCM_PR_DBGDATA("%s: trans_skb len:%04x \n",
+ __func__, ch->trans_skb->len);
+ CTCM_PR_DBGDATA("%s: pdu header and data for up"
+ " to 32 bytes sent to vtam\n", __func__);
+ CTCM_D3_DUMP((char *)p_header, min_t(int, skb->len, 32));
+
ch->collect_len -= skb->len;
data_space -= skb->len;
priv->stats.tx_packets++;
@@ -1314,46 +1302,38 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
if (p_header)
p_header->pdu_flag |= PDU_LAST; /*Say it's the last one*/
header = kzalloc(TH_HEADER_LENGTH, gfp_type());
-
if (!header) {
- printk(KERN_WARNING "ctcmpc: OUT OF MEMORY IN %s()"
- ": Data Lost \n", __FUNCTION__);
spin_unlock(&ch->collect_lock);
fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
- goto done;
+ goto done;
}
-
header->th_ch_flag = TH_HAS_PDU; /* Normal data */
ch->th_seq_num++;
header->th_seq_num = ch->th_seq_num;
- if (do_debug_data)
- ctcm_pr_debug("%s: ToVTAM_th_seq= %08x\n" ,
- __FUNCTION__, ch->th_seq_num);
+ CTCM_PR_DBGDATA("%s: ToVTAM_th_seq= %08x\n" ,
+ __func__, ch->th_seq_num);
memcpy(skb_push(ch->trans_skb, TH_HEADER_LENGTH), header,
TH_HEADER_LENGTH); /* put the TH on the packet */
kfree(header);
- if (do_debug_data) {
- ctcm_pr_debug("ctcmpc: %s()trans_skb len:%04x \n",
- __FUNCTION__, ch->trans_skb->len);
-
- ctcm_pr_debug("ctcmpc: %s() up-to-50 bytes of trans_skb "
- "data to vtam from collect_q\n", __FUNCTION__);
- ctcmpc_dumpit((char *)ch->trans_skb->data,
+ CTCM_PR_DBGDATA("%s: trans_skb len:%04x \n",
+ __func__, ch->trans_skb->len);
+ CTCM_PR_DBGDATA("%s: up-to-50 bytes of trans_skb "
+ "data to vtam from collect_q\n", __func__);
+ CTCM_D3_DUMP((char *)ch->trans_skb->data,
min_t(int, ch->trans_skb->len, 50));
- }
spin_unlock(&ch->collect_lock);
clear_normalized_cda(&ch->ccw[1]);
if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {
dev_kfree_skb_any(ch->trans_skb);
ch->trans_skb = NULL;
- printk(KERN_WARNING
- "ctcmpc: %s()CCW failure - data lost\n",
- __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ERROR,
+ "%s: %s: IDAL alloc failed",
+ CTCM_FUNTAIL, ch->id);
fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
return;
}
@@ -1373,7 +1353,6 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
}
done:
ctcm_clear_busy(dev);
- ctcm_pr_debug("ctcmpc exit: %s %s()\n", dev->name, __FUNCTION__);
return;
}
@@ -1393,26 +1372,25 @@ static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg)
struct mpc_group *grp = priv->mpcg;
struct sk_buff *skb = ch->trans_skb;
struct sk_buff *new_skb;
- unsigned long saveflags = 0; /* avoids compiler warning */
+ unsigned long saveflags = 0; /* avoids compiler warning */
int len = ch->max_bufsize - ch->irb->scsw.cmd.count;
- if (do_debug_data) {
- CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, "mpc_ch_rx %s cp:%i %s\n",
- dev->name, smp_processor_id(), ch->id);
- CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, "mpc_ch_rx: maxbuf: %04x "
- "len: %04x\n", ch->max_bufsize, len);
- }
+ CTCM_PR_DEBUG("%s: %s: cp:%i %s maxbuf : %04x, len: %04x\n",
+ CTCM_FUNTAIL, dev->name, smp_processor_id(),
+ ch->id, ch->max_bufsize, len);
fsm_deltimer(&ch->timer);
if (skb == NULL) {
- ctcm_pr_debug("ctcmpc exit: %s() TRANS_SKB = NULL \n",
- __FUNCTION__);
- goto again;
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): TRANS_SKB = NULL",
+ CTCM_FUNTAIL, dev->name);
+ goto again;
}
if (len < TH_HEADER_LENGTH) {
- ctcm_pr_info("%s: got packet with invalid length %d\n",
- dev->name, len);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): packet length %d to short",
+ CTCM_FUNTAIL, dev->name, len);
priv->stats.rx_dropped++;
priv->stats.rx_length_errors++;
} else {
@@ -1422,11 +1400,9 @@ static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg)
new_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC);
if (new_skb == NULL) {
- printk(KERN_INFO "ctcmpc:%s() NEW_SKB = NULL\n",
- __FUNCTION__);
- printk(KERN_WARNING "ctcmpc: %s() MEMORY ALLOC FAILED"
- " - DATA LOST - MPC FAILED\n",
- __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%d): skb allocation failed",
+ CTCM_FUNTAIL, dev->name);
fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
goto again;
}
@@ -1479,9 +1455,8 @@ again:
break;
}
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
- dev->name, __FUNCTION__, ch, ch->id);
+ CTCM_PR_DEBUG("Exit %s: %s, ch=0x%p, id=%s\n",
+ __func__, dev->name, ch, ch->id);
}
@@ -1497,15 +1472,16 @@ static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg)
struct channel *ch = arg;
struct net_device *dev = ch->netdev;
struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *gptr = priv->mpcg;
+
+ CTCM_PR_DEBUG("Enter %s: id=%s, ch=0x%p\n",
+ __func__, ch->id, ch);
+
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_INFO,
+ "%s: %s: chstate:%i, grpstate:%i, prot:%i\n",
+ CTCM_FUNTAIL, ch->id, fsm_getstate(fi),
+ fsm_getstate(gptr->fsm), ch->protocol);
- if (do_debug) {
- struct mpc_group *gptr = priv->mpcg;
- ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
- __FUNCTION__, ch, ch->id);
- ctcm_pr_debug("%s() %s chstate:%i grpstate:%i chprotocol:%i\n",
- __FUNCTION__, ch->id, fsm_getstate(fi),
- fsm_getstate(gptr->fsm), ch->protocol);
- }
if (fsm_getstate(fi) == CTC_STATE_TXIDLE)
MPC_DBF_DEV_NAME(TRACE, dev, "remote side issued READ? ");
@@ -1531,9 +1507,8 @@ static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg)
? CTC_STATE_RXINIT : CTC_STATE_TXINIT);
done:
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
- __FUNCTION__, ch, ch->id);
+ CTCM_PR_DEBUG("Exit %s: id=%s, ch=0x%p\n",
+ __func__, ch->id, ch);
return;
}
@@ -1556,12 +1531,9 @@ void ctcmpc_chx_rxidle(fsm_instance *fi, int event, void *arg)
unsigned long saveflags = 0; /* avoids compiler warning */
fsm_deltimer(&ch->timer);
- ctcm_pr_debug("%s cp:%i enter: %s()\n",
- dev->name, smp_processor_id(), __FUNCTION__);
- if (do_debug)
- ctcm_pr_debug("%s() %s chstate:%i grpstate:%i\n",
- __FUNCTION__, ch->id,
- fsm_getstate(fi), fsm_getstate(grp->fsm));
+ CTCM_PR_DEBUG("%s: %s: %s: cp:%i, chstate:%i grpstate:%i\n",
+ __func__, ch->id, dev->name, smp_processor_id(),
+ fsm_getstate(fi), fsm_getstate(grp->fsm));
fsm_newstate(fi, CTC_STATE_RXIDLE);
/* XID processing complete */
@@ -1575,9 +1547,7 @@ void ctcmpc_chx_rxidle(fsm_instance *fi, int event, void *arg)
skb_reset_tail_pointer(ch->trans_skb);
ch->trans_skb->len = 0;
ch->ccw[1].count = ch->max_bufsize;
- if (do_debug_ccw)
- ctcmpc_dumpit((char *)&ch->ccw[0],
- sizeof(struct ccw1) * 3);
+ CTCM_CCW_DUMP((char *)&ch->ccw[0], sizeof(struct ccw1) * 3);
if (event == CTC_EVENT_START)
/* see remark about conditional locking */
spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
@@ -1598,9 +1568,6 @@ void ctcmpc_chx_rxidle(fsm_instance *fi, int event, void *arg)
fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);
done:
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit: %s %s()\n",
- dev->name, __FUNCTION__);
return;
}
@@ -1616,13 +1583,9 @@ static void ctcmpc_chx_attn(fsm_instance *fsm, int event, void *arg)
struct ctcm_priv *priv = dev->priv;
struct mpc_group *grp = priv->mpcg;
- if (do_debug) {
- ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s"
- "GrpState:%s ChState:%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id,
- fsm_getstate_str(grp->fsm),
- fsm_getstate_str(ch->fsm));
- }
+ CTCM_PR_DEBUG("%s(%s): %s(ch=0x%p), cp=%i, ChStat:%s, GrpStat:%s\n",
+ __func__, dev->name, ch->id, ch, smp_processor_id(),
+ fsm_getstate_str(ch->fsm), fsm_getstate_str(grp->fsm));
switch (fsm_getstate(grp->fsm)) {
case MPCG_STATE_XID2INITW:
@@ -1664,11 +1627,7 @@ static void ctcmpc_chx_attn(fsm_instance *fsm, int event, void *arg)
break;
}
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id);
return;
-
}
/*
@@ -1683,11 +1642,9 @@ static void ctcmpc_chx_attnbusy(fsm_instance *fsm, int event, void *arg)
struct ctcm_priv *priv = dev->priv;
struct mpc_group *grp = priv->mpcg;
- ctcm_pr_debug("ctcmpc enter: %s %s() %s \nGrpState:%s ChState:%s\n",
- dev->name,
- __FUNCTION__, ch->id,
- fsm_getstate_str(grp->fsm),
- fsm_getstate_str(ch->fsm));
+ CTCM_PR_DEBUG("%s(%s): %s\n ChState:%s GrpState:%s\n",
+ __func__, dev->name, ch->id,
+ fsm_getstate_str(ch->fsm), fsm_getstate_str(grp->fsm));
fsm_deltimer(&ch->timer);
@@ -1750,16 +1707,12 @@ static void ctcmpc_chx_attnbusy(fsm_instance *fsm, int event, void *arg)
if (ch->in_mpcgroup)
fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);
else
- printk(KERN_WARNING "ctcmpc: %s() Not all channels have"
- " been added to group\n", __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): channel %s not added to group",
+ CTCM_FUNTAIL, dev->name, ch->id);
done:
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s()%s ch=0x%p id=%s\n",
- __FUNCTION__, dev->name, ch, ch->id);
-
return;
-
}
/*
@@ -1774,13 +1727,7 @@ static void ctcmpc_chx_resend(fsm_instance *fsm, int event, void *arg)
struct ctcm_priv *priv = dev->priv;
struct mpc_group *grp = priv->mpcg;
- ctcm_pr_debug("ctcmpc enter: %s %s() %s \nGrpState:%s ChState:%s\n",
- dev->name, __FUNCTION__, ch->id,
- fsm_getstate_str(grp->fsm),
- fsm_getstate_str(ch->fsm));
-
fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);
-
return;
}
@@ -1802,19 +1749,16 @@ static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg)
int rc = 0;
unsigned long saveflags = 0;
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ach, ach->id);
+ CTCM_PR_DEBUG("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
+ __func__, smp_processor_id(), ach, ach->id);
if (grp->in_sweep == 0)
goto done;
- if (do_debug_data) {
- ctcm_pr_debug("ctcmpc: %s() 1: ToVTAM_th_seq= %08x\n" ,
- __FUNCTION__, wch->th_seq_num);
- ctcm_pr_debug("ctcmpc: %s() 1: FromVTAM_th_seq= %08x\n" ,
- __FUNCTION__, rch->th_seq_num);
- }
+ CTCM_PR_DBGDATA("%s: 1: ToVTAM_th_seq= %08x\n" ,
+ __func__, wch->th_seq_num);
+ CTCM_PR_DBGDATA("%s: 1: FromVTAM_th_seq= %08x\n" ,
+ __func__, rch->th_seq_num);
if (fsm_getstate(wch->fsm) != CTC_STATE_TXIDLE) {
/* give the previous IO time to complete */
@@ -1853,11 +1797,9 @@ static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg)
header->sw.th_last_seq = wch->th_seq_num;
- if (do_debug_ccw)
- ctcmpc_dumpit((char *)&wch->ccw[3], sizeof(struct ccw1) * 3);
-
- ctcm_pr_debug("ctcmpc: %s() sweep packet\n", __FUNCTION__);
- ctcmpc_dumpit((char *)header, TH_SWEEP_LENGTH);
+ CTCM_CCW_DUMP((char *)&wch->ccw[3], sizeof(struct ccw1) * 3);
+ CTCM_PR_DBGDATA("%s: sweep packet\n", __func__);
+ CTCM_D3_DUMP((char *)header, TH_SWEEP_LENGTH);
fsm_addtimer(&wch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, wch);
fsm_newstate(wch->fsm, CTC_STATE_TX);
@@ -1876,19 +1818,13 @@ static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg)
ctcm_clear_busy_do(dev);
}
- if (do_debug_data) {
- ctcm_pr_debug("ctcmpc: %s()2: ToVTAM_th_seq= %08x\n" ,
- __FUNCTION__, wch->th_seq_num);
- ctcm_pr_debug("ctcmpc: %s()2: FromVTAM_th_seq= %08x\n" ,
- __FUNCTION__, rch->th_seq_num);
- }
+ CTCM_PR_DBGDATA("%s: To-/From-VTAM_th_seq = %08x/%08x\n" ,
+ __func__, wch->th_seq_num, rch->th_seq_num);
if (rc != 0)
ctcm_ccw_check_rc(wch, rc, "send sweep");
done:
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit: %s() %s\n", __FUNCTION__, ach->id);
return;
}
@@ -2149,9 +2085,8 @@ static void dev_action_stop(fsm_instance *fi, int event, void *arg)
struct channel *ch = priv->channel[direction];
fsm_event(ch->fsm, CTC_EVENT_STOP, ch);
ch->th_seq_num = 0x00;
- if (do_debug)
- ctcm_pr_debug("ctcm: %s() CH_th_seq= %08x\n",
- __FUNCTION__, ch->th_seq_num);
+ CTCM_PR_DEBUG("%s: CH_th_seq= %08x\n",
+ __func__, ch->th_seq_num);
}
if (IS_MPC(priv))
fsm_newstate(priv->mpcg->fsm, MPCG_STATE_RESET);
@@ -2199,8 +2134,11 @@ static void dev_action_chup(fsm_instance *fi, int event, void *arg)
{
struct net_device *dev = arg;
struct ctcm_priv *priv = dev->priv;
+ int dev_stat = fsm_getstate(fi);
- CTCMY_DBF_DEV_NAME(SETUP, dev, "");
+ CTCM_DBF_TEXT_(SETUP, CTC_DBF_NOTICE,
+ "%s(%s): priv = %p [%d,%d]\n ", CTCM_FUNTAIL,
+ dev->name, dev->priv, dev_stat, event);
switch (fsm_getstate(fi)) {
case DEV_STATE_STARTWAIT_RXTX:
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 6b13c1c1beb..126a3ebb8ab 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -84,20 +84,19 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb)
skb_pull(pskb, LL_HEADER_LENGTH);
if ((ch->protocol == CTCM_PROTO_S390) &&
(header->type != ETH_P_IP)) {
-
if (!(ch->logflags & LOG_FLAG_ILLEGALPKT)) {
+ ch->logflags |= LOG_FLAG_ILLEGALPKT;
/*
* Check packet type only if we stick strictly
* to S/390's protocol of OS390. This only
* supports IP. Otherwise allow any packet
* type.
*/
- ctcm_pr_warn("%s Illegal packet type 0x%04x "
- "received, dropping\n",
- dev->name, header->type);
- ch->logflags |= LOG_FLAG_ILLEGALPKT;
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): Illegal packet type 0x%04x"
+ " - dropping",
+ CTCM_FUNTAIL, dev->name, header->type);
}
-
priv->stats.rx_dropped++;
priv->stats.rx_frame_errors++;
return;
@@ -105,11 +104,11 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb)
pskb->protocol = ntohs(header->type);
if (header->length <= LL_HEADER_LENGTH) {
if (!(ch->logflags & LOG_FLAG_ILLEGALSIZE)) {
- ctcm_pr_warn(
- "%s Illegal packet size %d "
- "received (MTU=%d blocklen=%d), "
- "dropping\n", dev->name, header->length,
- dev->mtu, len);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): Illegal packet size %d(%d,%d)"
+ "- dropping",
+ CTCM_FUNTAIL, dev->name,
+ header->length, dev->mtu, len);
ch->logflags |= LOG_FLAG_ILLEGALSIZE;
}
@@ -122,10 +121,10 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb)
if ((header->length > skb_tailroom(pskb)) ||
(header->length > len)) {
if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
- ctcm_pr_warn(
- "%s Illegal packet size %d (beyond the"
- " end of received data), dropping\n",
- dev->name, header->length);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): Packet size %d (overrun)"
+ " - dropping", CTCM_FUNTAIL,
+ dev->name, header->length);
ch->logflags |= LOG_FLAG_OVERRUN;
}
@@ -139,9 +138,9 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb)
skb = dev_alloc_skb(pskb->len);
if (!skb) {
if (!(ch->logflags & LOG_FLAG_NOMEM)) {
- ctcm_pr_warn(
- "%s Out of memory in ctcm_unpack_skb\n",
- dev->name);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): MEMORY allocation error",
+ CTCM_FUNTAIL, dev->name);
ch->logflags |= LOG_FLAG_NOMEM;
}
priv->stats.rx_dropped++;
@@ -184,7 +183,7 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb)
*/
static void channel_free(struct channel *ch)
{
- CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
+ CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s)", CTCM_FUNTAIL, ch->id);
ch->flags &= ~CHANNEL_FLAGS_INUSE;
fsm_newstate(ch->fsm, CTC_STATE_IDLE);
}
@@ -251,19 +250,12 @@ static struct channel *channel_get(enum channel_types type,
{
struct channel *ch = channels;
- if (do_debug) {
- char buf[64];
- sprintf(buf, "%s(%d, %s, %d)\n",
- CTCM_FUNTAIL, type, id, direction);
- CTCM_DBF_TEXT(TRACE, CTC_DBF_INFO, buf);
- }
while (ch && (strncmp(ch->id, id, CTCM_ID_SIZE) || (ch->type != type)))
ch = ch->next;
if (!ch) {
- char buf[64];
- sprintf(buf, "%s(%d, %s, %d) not found in channel list\n",
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%d, %s, %d) not found in channel list\n",
CTCM_FUNTAIL, type, id, direction);
- CTCM_DBF_TEXT(ERROR, CTC_DBF_ERROR, buf);
} else {
if (ch->flags & CHANNEL_FLAGS_INUSE)
ch = NULL;
@@ -283,8 +275,9 @@ static long ctcm_check_irb_error(struct ccw_device *cdev, struct irb *irb)
if (!IS_ERR(irb))
return 0;
- CTCM_DBF_TEXT_(ERROR, CTC_DBF_WARN, "irb error %ld on device %s\n",
- PTR_ERR(irb), cdev->dev.bus_id);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_WARN,
+ "irb error %ld on device %s\n",
+ PTR_ERR(irb), cdev->dev.bus_id);
switch (PTR_ERR(irb)) {
case -EIO:
@@ -307,58 +300,85 @@ static long ctcm_check_irb_error(struct ccw_device *cdev, struct irb *irb)
* ch The channel, the sense code belongs to.
* sense The sense code to inspect.
*/
-static inline void ccw_unit_check(struct channel *ch, unsigned char sense)
+static inline void ccw_unit_check(struct channel *ch, __u8 sense)
{
- CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+ "%s(%s): %02x",
+ CTCM_FUNTAIL, ch->id, sense);
+
if (sense & SNS0_INTERVENTION_REQ) {
if (sense & 0x01) {
- ctcm_pr_debug("%s: Interface disc. or Sel. reset "
- "(remote)\n", ch->id);
+ if (ch->sense_rc != 0x01) {
+ ctcm_pr_debug("%s: Interface disc. or Sel. "
+ "reset (remote)\n", ch->id);
+ ch->sense_rc = 0x01;
+ }
fsm_event(ch->fsm, CTC_EVENT_UC_RCRESET, ch);
} else {
- ctcm_pr_debug("%s: System reset (remote)\n", ch->id);
+ if (ch->sense_rc != SNS0_INTERVENTION_REQ) {
+ ctcm_pr_debug("%s: System reset (remote)\n",
+ ch->id);
+ ch->sense_rc = SNS0_INTERVENTION_REQ;
+ }
fsm_event(ch->fsm, CTC_EVENT_UC_RSRESET, ch);
}
} else if (sense & SNS0_EQUIPMENT_CHECK) {
if (sense & SNS0_BUS_OUT_CHECK) {
- ctcm_pr_warn("%s: Hardware malfunction (remote)\n",
- ch->id);
+ if (ch->sense_rc != SNS0_BUS_OUT_CHECK) {
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+ "%s(%s): remote HW error %02x",
+ CTCM_FUNTAIL, ch->id, sense);
+ ch->sense_rc = SNS0_BUS_OUT_CHECK;
+ }
fsm_event(ch->fsm, CTC_EVENT_UC_HWFAIL, ch);
} else {
- ctcm_pr_warn("%s: Read-data parity error (remote)\n",
- ch->id);
+ if (ch->sense_rc != SNS0_EQUIPMENT_CHECK) {
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+ "%s(%s): remote read parity error %02x",
+ CTCM_FUNTAIL, ch->id, sense);
+ ch->sense_rc = SNS0_EQUIPMENT_CHECK;
+ }
fsm_event(ch->fsm, CTC_EVENT_UC_RXPARITY, ch);
}
} else if (sense & SNS0_BUS_OUT_CHECK) {
- if (sense & 0x04) {
- ctcm_pr_warn("%s: Data-streaming timeout)\n", ch->id);
+ if (ch->sense_rc != SNS0_BUS_OUT_CHECK) {
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+ "%s(%s): BUS OUT error %02x",
+ CTCM_FUNTAIL, ch->id, sense);
+ ch->sense_rc = SNS0_BUS_OUT_CHECK;
+ }
+ if (sense & 0x04) /* data-streaming timeout */
fsm_event(ch->fsm, CTC_EVENT_UC_TXTIMEOUT, ch);
- } else {
- ctcm_pr_warn("%s: Data-transfer parity error\n",
- ch->id);
+ else /* Data-transfer parity error */
fsm_event(ch->fsm, CTC_EVENT_UC_TXPARITY, ch);
- }
} else if (sense & SNS0_CMD_REJECT) {
- ctcm_pr_warn("%s: Command reject\n", ch->id);
+ if (ch->sense_rc != SNS0_CMD_REJECT) {
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+ "%s(%s): Command rejected",
+ CTCM_FUNTAIL, ch->id);
+ ch->sense_rc = SNS0_CMD_REJECT;
+ }
} else if (sense == 0) {
- ctcm_pr_debug("%s: Unit check ZERO\n", ch->id);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+ "%s(%s): Unit check ZERO",
+ CTCM_FUNTAIL, ch->id);
fsm_event(ch->fsm, CTC_EVENT_UC_ZERO, ch);
} else {
- ctcm_pr_warn("%s: Unit Check with sense code: %02x\n",
- ch->id, sense);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+ "%s(%s): Unit check code %02x unknown",
+ CTCM_FUNTAIL, ch->id, sense);
fsm_event(ch->fsm, CTC_EVENT_UC_UNKNOWN, ch);
}
}
int ctcm_ch_alloc_buffer(struct channel *ch)
{
- CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
-
clear_normalized_cda(&ch->ccw[1]);
ch->trans_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC | GFP_DMA);
if (ch->trans_skb == NULL) {
- ctcm_pr_warn("%s: Couldn't alloc %s trans_skb\n",
- ch->id,
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): %s trans_skb allocation error",
+ CTCM_FUNTAIL, ch->id,
(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
return -ENOMEM;
}
@@ -367,9 +387,9 @@ int ctcm_ch_alloc_buffer(struct channel *ch)
if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {
dev_kfree_skb(ch->trans_skb);
ch->trans_skb = NULL;
- ctcm_pr_warn("%s: set_normalized_cda for %s "
- "trans_skb failed, dropping packets\n",
- ch->id,
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): %s set norm_cda failed",
+ CTCM_FUNTAIL, ch->id,
(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
return -ENOMEM;
}
@@ -516,7 +536,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
atomic_dec(&skb->users);
skb_pull(skb, LL_HEADER_LENGTH + 2);
ctcm_clear_busy(ch->netdev);
- return -EBUSY;
+ return -ENOMEM;
}
skb_reset_tail_pointer(ch->trans_skb);
@@ -570,15 +590,12 @@ static void ctcmpc_send_sweep_req(struct channel *rch)
struct th_sweep *header;
struct sk_buff *sweep_skb;
struct channel *ch;
- int rc = 0;
+ /* int rc = 0; */
priv = dev->priv;
grp = priv->mpcg;
ch = priv->channel[WRITE];
- if (do_debug)
- MPC_DBF_DEV_NAME(TRACE, dev, ch->id);
-
/* sweep processing is not complete until response and request */
/* has completed for all read channels in group */
if (grp->in_sweep == 0) {
@@ -590,17 +607,16 @@ static void ctcmpc_send_sweep_req(struct channel *rch)
sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA);
if (sweep_skb == NULL) {
- printk(KERN_INFO "Couldn't alloc sweep_skb\n");
- rc = -ENOMEM;
- goto done;
+ /* rc = -ENOMEM; */
+ goto nomem;
}
header = kmalloc(TH_SWEEP_LENGTH, gfp_type());
if (!header) {
dev_kfree_skb_any(sweep_skb);
- rc = -ENOMEM;
- goto done;
+ /* rc = -ENOMEM; */
+ goto nomem;
}
header->th.th_seg = 0x00 ;
@@ -621,12 +637,10 @@ static void ctcmpc_send_sweep_req(struct channel *rch)
return;
-done:
- if (rc != 0) {
- grp->in_sweep = 0;
- ctcm_clear_busy(dev);
- fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
- }
+nomem:
+ grp->in_sweep = 0;
+ ctcm_clear_busy(dev);
+ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
return;
}
@@ -648,11 +662,9 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
unsigned long saveflags = 0; /* avoids compiler warning */
__u16 block_len;
- if (do_debug)
- ctcm_pr_debug(
- "ctcm enter: %s(): %s cp=%i ch=0x%p id=%s state=%s\n",
- __FUNCTION__, dev->name, smp_processor_id(), ch,
- ch->id, fsm_getstate_str(ch->fsm));
+ CTCM_PR_DEBUG("Enter %s: %s, cp=%i ch=0x%p id=%s state=%s\n",
+ __func__, dev->name, smp_processor_id(), ch,
+ ch->id, fsm_getstate_str(ch->fsm));
if ((fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) || grp->in_sweep) {
spin_lock_irqsave(&ch->collect_lock, saveflags);
@@ -660,14 +672,8 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
if (!p_header) {
- printk(KERN_WARNING "ctcm: OUT OF MEMORY IN %s():"
- " Data Lost \n", __FUNCTION__);
-
- atomic_dec(&skb->users);
- dev_kfree_skb_any(skb);
spin_unlock_irqrestore(&ch->collect_lock, saveflags);
- fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
- goto done;
+ goto nomem_exit;
}
p_header->pdu_offset = skb->len;
@@ -682,13 +688,10 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
memcpy(skb_push(skb, PDU_HEADER_LENGTH), p_header,
PDU_HEADER_LENGTH);
- if (do_debug_data) {
- ctcm_pr_debug("ctcm: %s() Putting on collect_q"
- " - skb len: %04x \n", __FUNCTION__, skb->len);
- ctcm_pr_debug("ctcm: %s() pdu header and data"
- " for up to 32 bytes\n", __FUNCTION__);
- ctcmpc_dump32((char *)skb->data, skb->len);
- }
+ CTCM_PR_DEBUG("%s(%s): Put on collect_q - skb len: %04x \n"
+ "pdu header and data for up to 32 bytes:\n",
+ __func__, dev->name, skb->len);
+ CTCM_D3_DUMP((char *)skb->data, min_t(int, 32, skb->len));
skb_queue_tail(&ch->collect_queue, skb);
ch->collect_len += skb->len;
@@ -713,12 +716,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
if (hi) {
nskb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
if (!nskb) {
- printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY"
- "- Data Lost \n", __FUNCTION__);
- atomic_dec(&skb->users);
- dev_kfree_skb_any(skb);
- fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
- goto done;
+ goto nomem_exit;
} else {
memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
atomic_inc(&nskb->users);
@@ -730,15 +728,8 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
- if (!p_header) {
- printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY"
- ": Data Lost \n", __FUNCTION__);
-
- atomic_dec(&skb->users);
- dev_kfree_skb_any(skb);
- fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
- goto done;
- }
+ if (!p_header)
+ goto nomem_exit;
p_header->pdu_offset = skb->len;
p_header->pdu_proto = 0x01;
@@ -768,15 +759,8 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
ch->prof.txlen += skb->len - PDU_HEADER_LENGTH;
header = kmalloc(TH_HEADER_LENGTH, gfp_type());
-
- if (!header) {
- printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY: Data Lost \n",
- __FUNCTION__);
- atomic_dec(&skb->users);
- dev_kfree_skb_any(skb);
- fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
- goto done;
- }
+ if (!header)
+ goto nomem_exit;
header->th_seg = 0x00;
header->th_ch_flag = TH_HAS_PDU; /* Normal data */
@@ -785,41 +769,31 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
ch->th_seq_num++;
header->th_seq_num = ch->th_seq_num;
- if (do_debug_data)
- ctcm_pr_debug("ctcm: %s() ToVTAM_th_seq= %08x\n" ,
- __FUNCTION__, ch->th_seq_num);
+ CTCM_PR_DBGDATA("%s(%s) ToVTAM_th_seq= %08x\n" ,
+ __func__, dev->name, ch->th_seq_num);
/* put the TH on the packet */
memcpy(skb_push(skb, TH_HEADER_LENGTH), header, TH_HEADER_LENGTH);
kfree(header);
- if (do_debug_data) {
- ctcm_pr_debug("ctcm: %s(): skb len: %04x \n",
- __FUNCTION__, skb->len);
- ctcm_pr_debug("ctcm: %s(): pdu header and data for up to 32 "
- "bytes sent to vtam\n", __FUNCTION__);
- ctcmpc_dump32((char *)skb->data, skb->len);
- }
+ CTCM_PR_DBGDATA("%s(%s): skb len: %04x\n - pdu header and data for "
+ "up to 32 bytes sent to vtam:\n",
+ __func__, dev->name, skb->len);
+ CTCM_D3_DUMP((char *)skb->data, min_t(int, 32, skb->len));
ch->ccw[4].count = skb->len;
if (set_normalized_cda(&ch->ccw[4], skb->data)) {
/*
- * idal allocation failed, try via copying to
- * trans_skb. trans_skb usually has a pre-allocated
- * idal.
+ * idal allocation failed, try via copying to trans_skb.
+ * trans_skb usually has a pre-allocated idal.
*/
if (ctcm_checkalloc_buffer(ch)) {
/*
- * Remove our header. It gets added
- * again on retransmit.
+ * Remove our header.
+ * It gets added again on retransmit.
*/
- atomic_dec(&skb->users);
- dev_kfree_skb_any(skb);
- printk(KERN_WARNING "ctcm: %s()OUT OF MEMORY:"
- " Data Lost \n", __FUNCTION__);
- fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
- goto done;
+ goto nomem_exit;
}
skb_reset_tail_pointer(ch->trans_skb);
@@ -829,14 +803,11 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
atomic_dec(&skb->users);
dev_kfree_skb_irq(skb);
ccw_idx = 0;
- if (do_debug_data) {
- ctcm_pr_debug("ctcm: %s() TRANS skb len: %d \n",
- __FUNCTION__, ch->trans_skb->len);
- ctcm_pr_debug("ctcm: %s up to 32 bytes of data"
- " sent to vtam\n", __FUNCTION__);
- ctcmpc_dump32((char *)ch->trans_skb->data,
- ch->trans_skb->len);
- }
+ CTCM_PR_DBGDATA("%s(%s): trans_skb len: %04x\n"
+ "up to 32 bytes sent to vtam:\n",
+ __func__, dev->name, ch->trans_skb->len);
+ CTCM_D3_DUMP((char *)ch->trans_skb->data,
+ min_t(int, 32, ch->trans_skb->len));
} else {
skb_queue_tail(&ch->io_queue, skb);
ccw_idx = 3;
@@ -865,13 +836,21 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
priv->stats.tx_packets++;
priv->stats.tx_bytes += skb->len - TH_HEADER_LENGTH;
}
- if (ch->th_seq_num > 0xf0000000) /* Chose 4Billion at random. */
+ if (ch->th_seq_num > 0xf0000000) /* Chose at random. */
ctcmpc_send_sweep_req(ch);
+ goto done;
+nomem_exit:
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_CRIT,
+ "%s(%s): MEMORY allocation ERROR\n",
+ CTCM_FUNTAIL, ch->id);
+ rc = -ENOMEM;
+ atomic_dec(&skb->users);
+ dev_kfree_skb_any(skb);
+ fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
done:
- if (do_debug)
- ctcm_pr_debug("ctcm exit: %s %s()\n", dev->name, __FUNCTION__);
- return 0;
+ CTCM_PR_DEBUG("Exit %s(%s)\n", __func__, dev->name);
+ return rc;
}
/**
@@ -888,20 +867,19 @@ done:
/* first merge version - leaving both functions separated */
static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
{
- int rc = 0;
- struct ctcm_priv *priv;
-
- CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
- priv = dev->priv;
+ struct ctcm_priv *priv = dev->priv;
if (skb == NULL) {
- ctcm_pr_warn("%s: NULL sk_buff passed\n", dev->name);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): NULL sk_buff passed",
+ CTCM_FUNTAIL, dev->name);
priv->stats.tx_dropped++;
return 0;
}
if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) {
- ctcm_pr_warn("%s: Got sk_buff with head room < %ld bytes\n",
- dev->name, LL_HEADER_LENGTH + 2);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): Got sk_buff with head room < %ld bytes",
+ CTCM_FUNTAIL, dev->name, LL_HEADER_LENGTH + 2);
dev_kfree_skb(skb);
priv->stats.tx_dropped++;
return 0;
@@ -925,51 +903,43 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
if (ctcm_transmit_skb(priv->channel[WRITE], skb) != 0)
- rc = 1;
- return rc;
+ return 1;
+ return 0;
}
/* unmerged MPC variant of ctcm_tx */
static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
{
int len = 0;
- struct ctcm_priv *priv = NULL;
- struct mpc_group *grp = NULL;
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = priv->mpcg;
struct sk_buff *newskb = NULL;
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s(): skb:%0lx\n",
- __FUNCTION__, (unsigned long)skb);
-
- CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
- "ctcmpc enter: %s(): skb:%0lx\n",
- __FUNCTION__, (unsigned long)skb);
-
- priv = dev->priv;
- grp = priv->mpcg;
/*
* Some sanity checks ...
*/
if (skb == NULL) {
- ctcm_pr_warn("ctcmpc: %s: NULL sk_buff passed\n", dev->name);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): NULL sk_buff passed",
+ CTCM_FUNTAIL, dev->name);
priv->stats.tx_dropped++;
goto done;
}
if (skb_headroom(skb) < (TH_HEADER_LENGTH + PDU_HEADER_LENGTH)) {
- CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_WARN,
- "%s: Got sk_buff with head room < %ld bytes\n",
- dev->name, TH_HEADER_LENGTH + PDU_HEADER_LENGTH);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ERROR,
+ "%s(%s): Got sk_buff with head room < %ld bytes",
+ CTCM_FUNTAIL, dev->name,
+ TH_HEADER_LENGTH + PDU_HEADER_LENGTH);
- if (do_debug_data)
- ctcmpc_dump32((char *)skb->data, skb->len);
+ CTCM_D3_DUMP((char *)skb->data, min_t(int, 32, skb->len));
len = skb->len + TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
newskb = __dev_alloc_skb(len, gfp_type() | GFP_DMA);
if (!newskb) {
- printk(KERN_WARNING "ctcmpc: %s() OUT OF MEMORY-"
- "Data Lost\n",
- __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ERROR,
+ "%s: %s: __dev_alloc_skb failed",
+ __func__, dev->name);
dev_kfree_skb_any(skb);
priv->stats.tx_dropped++;
@@ -993,9 +963,9 @@ static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
if ((fsm_getstate(priv->fsm) != DEV_STATE_RUNNING) ||
(fsm_getstate(grp->fsm) < MPCG_STATE_XID2INITW)) {
dev_kfree_skb_any(skb);
- printk(KERN_INFO "ctcmpc: %s() DATA RCVD - MPC GROUP "
- "NOT ACTIVE - DROPPED\n",
- __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): inactive MPCGROUP - dropped",
+ CTCM_FUNTAIL, dev->name);
priv->stats.tx_dropped++;
priv->stats.tx_errors++;
priv->stats.tx_carrier_errors++;
@@ -1003,8 +973,9 @@ static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
}
if (ctcm_test_and_set_busy(dev)) {
- printk(KERN_WARNING "%s:DEVICE ERR - UNRECOVERABLE DATA LOSS\n",
- __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): device busy - dropped",
+ CTCM_FUNTAIL, dev->name);
dev_kfree_skb_any(skb);
priv->stats.tx_dropped++;
priv->stats.tx_errors++;
@@ -1015,12 +986,9 @@ static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
if (ctcmpc_transmit_skb(priv->channel[WRITE], skb) != 0) {
- printk(KERN_WARNING "ctcmpc: %s() DEVICE ERROR"
- ": Data Lost \n",
- __FUNCTION__);
- printk(KERN_WARNING "ctcmpc: %s() DEVICE ERROR"
- " - UNRECOVERABLE DATA LOSS\n",
- __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): device error - dropped",
+ CTCM_FUNTAIL, dev->name);
dev_kfree_skb_any(skb);
priv->stats.tx_dropped++;
priv->stats.tx_errors++;
@@ -1054,8 +1022,6 @@ static int ctcm_change_mtu(struct net_device *dev, int new_mtu)
struct ctcm_priv *priv;
int max_bufsize;
- CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
-
if (new_mtu < 576 || new_mtu > 65527)
return -EINVAL;
@@ -1087,30 +1053,13 @@ static struct net_device_stats *ctcm_stats(struct net_device *dev)
return &((struct ctcm_priv *)dev->priv)->stats;
}
-
-static void ctcm_netdev_unregister(struct net_device *dev)
-{
- CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
- if (!dev)
- return;
- unregister_netdev(dev);
-}
-
-static int ctcm_netdev_register(struct net_device *dev)
-{
- CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
- return register_netdev(dev);
-}
-
static void ctcm_free_netdevice(struct net_device *dev)
{
struct ctcm_priv *priv;
struct mpc_group *grp;
- CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
-
- if (!dev)
- return;
+ CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
+ "%s(%s)", CTCM_FUNTAIL, dev->name);
priv = dev->priv;
if (priv) {
grp = priv->mpcg;
@@ -1171,7 +1120,9 @@ static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv)
dev = alloc_netdev(0, CTC_DEVICE_GENE, ctcm_dev_setup);
if (!dev) {
- ctcm_pr_err("%s: Out of memory\n", __FUNCTION__);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT,
+ "%s: MEMORY allocation ERROR",
+ CTCM_FUNTAIL);
return NULL;
}
dev->priv = priv;
@@ -1209,6 +1160,7 @@ static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv)
}
CTCMY_DBF_DEV(SETUP, dev, "finished");
+
return dev;
}
@@ -1226,18 +1178,24 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
struct net_device *dev;
struct ctcm_priv *priv;
struct ccwgroup_device *cgdev;
+ int cstat;
+ int dstat;
+
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+ "Enter %s(%s)", CTCM_FUNTAIL, &cdev->dev.bus_id);
- CTCM_DBF_TEXT(TRACE, CTC_DBF_DEBUG, __FUNCTION__);
if (ctcm_check_irb_error(cdev, irb))
return;
cgdev = dev_get_drvdata(&cdev->dev);
+ cstat = irb->scsw.cmd.cstat;
+ dstat = irb->scsw.cmd.dstat;
+
/* Check for unsolicited interrupts. */
if (cgdev == NULL) {
- ctcm_pr_warn("ctcm: Got unsolicited irq: %s c-%02x d-%02x\n",
- cdev->dev.bus_id, irb->scsw.cmd.cstat,
- irb->scsw.cmd.dstat);
+ ctcm_pr_warn("ctcm: Got unsolicited irq: c-%02x d-%02x\n",
+ cstat, dstat);
return;
}
@@ -1254,26 +1212,22 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
return;
}
- dev = (struct net_device *)(ch->netdev);
+ dev = ch->netdev;
if (dev == NULL) {
ctcm_pr_crit("ctcm: %s dev=NULL bus_id=%s, ch=0x%p\n",
- __FUNCTION__, cdev->dev.bus_id, ch);
+ __func__, cdev->dev.bus_id, ch);
return;
}
- if (do_debug)
- ctcm_pr_debug("%s: interrupt for device: %s "
- "received c-%02x d-%02x\n",
- dev->name,
- ch->id,
- irb->scsw.cmd.cstat,
- irb->scsw.cmd.dstat);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+ "%s(%s): int. for %s: cstat=%02x dstat=%02x",
+ CTCM_FUNTAIL, dev->name, ch->id, cstat, dstat);
/* Copy interruption response block. */
memcpy(ch->irb, irb, sizeof(struct irb));
- /* Check for good subchannel return code, otherwise error message */
if (irb->scsw.cmd.cstat) {
+ /* Check for good subchannel return code, otherwise error message */
fsm_event(ch->fsm, CTC_EVENT_SC_UNKNOWN, ch);
ctcm_pr_warn("%s: subchannel check for dev: %s - %02x %02x\n",
dev->name, ch->id, irb->scsw.cmd.cstat,
@@ -1283,6 +1237,11 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
/* Check the reason-code of a unit check */
if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
+ if ((irb->ecw[0] & ch->sense_rc) == 0)
+ /* print it only once */
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_INFO,
+ "%s(%s): sense=%02x, ds=%02x",
+ CTCM_FUNTAIL, ch->id, irb->ecw[0], dstat);
ccw_unit_check(ch, irb->ecw[0]);
return;
}
@@ -1320,14 +1279,18 @@ static int ctcm_probe_device(struct ccwgroup_device *cgdev)
struct ctcm_priv *priv;
int rc;
- CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s %p", __FUNCTION__, cgdev);
+ CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
+ "%s %p",
+ __func__, cgdev);
if (!get_device(&cgdev->dev))
return -ENODEV;
priv = kzalloc(sizeof(struct ctcm_priv), GFP_KERNEL);
if (!priv) {
- ctcm_pr_err("%s: Out of memory\n", __FUNCTION__);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s: memory allocation failure",
+ CTCM_FUNTAIL);
put_device(&cgdev->dev);
return -ENOMEM;
}
@@ -1364,10 +1327,13 @@ static int add_channel(struct ccw_device *cdev, enum channel_types type,
int ccw_num;
int rc = 0;
- CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
+ CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
+ "%s(%s), type %d, proto %d",
+ __func__, cdev->dev.bus_id, type, priv->protocol);
+
ch = kzalloc(sizeof(struct channel), GFP_KERNEL);
if (ch == NULL)
- goto nomem_return;
+ return -ENOMEM;
ch->protocol = priv->protocol;
if (IS_MPC(priv)) {
@@ -1478,7 +1444,7 @@ static int add_channel(struct ccw_device *cdev, enum channel_types type,
if (*c && (!strncmp((*c)->id, ch->id, CTCM_ID_SIZE))) {
CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
"%s (%s) already in list, using old entry",
- __FUNCTION__, (*c)->id);
+ __func__, (*c)->id);
goto free_return;
}
@@ -1498,11 +1464,10 @@ static int add_channel(struct ccw_device *cdev, enum channel_types type,
return 0;
nomem_return:
- ctcm_pr_warn("ctcm: Out of memory in %s\n", __FUNCTION__);
rc = -ENOMEM;
free_return: /* note that all channel pointers are 0 or valid */
- kfree(ch->ccw); /* TODO: check that again */
+ kfree(ch->ccw);
kfree(ch->discontact_th);
kfree_fsm(ch->fsm);
kfree(ch->irb);
@@ -1540,48 +1505,48 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
enum channel_types type;
struct ctcm_priv *priv;
struct net_device *dev;
+ struct ccw_device *cdev0;
+ struct ccw_device *cdev1;
int ret;
- CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
-
priv = dev_get_drvdata(&cgdev->dev);
if (!priv)
return -ENODEV;
- type = get_channel_type(&cgdev->cdev[0]->id);
+ cdev0 = cgdev->cdev[0];
+ cdev1 = cgdev->cdev[1];
+
+ type = get_channel_type(&cdev0->id);
- snprintf(read_id, CTCM_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id);
- snprintf(write_id, CTCM_ID_SIZE, "ch-%s", cgdev->cdev[1]->dev.bus_id);
+ snprintf(read_id, CTCM_ID_SIZE, "ch-%s", cdev0->dev.bus_id);
+ snprintf(write_id, CTCM_ID_SIZE, "ch-%s", cdev1->dev.bus_id);
- ret = add_channel(cgdev->cdev[0], type, priv);
+ ret = add_channel(cdev0, type, priv);
if (ret)
return ret;
- ret = add_channel(cgdev->cdev[1], type, priv);
+ ret = add_channel(cdev1, type, priv);
if (ret)
return ret;
- ret = ccw_device_set_online(cgdev->cdev[0]);
+ ret = ccw_device_set_online(cdev0);
if (ret != 0) {
- CTCM_DBF_TEXT(SETUP, CTC_DBF_WARN,
- "ccw_device_set_online (cdev[0]) failed ");
- ctcm_pr_warn("ccw_device_set_online (cdev[0]) failed "
- "with ret = %d\n", ret);
+ /* may be ok to fail now - can be done later */
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+ "%s(%s) set_online rc=%d",
+ CTCM_FUNTAIL, read_id, ret);
}
- ret = ccw_device_set_online(cgdev->cdev[1]);
+ ret = ccw_device_set_online(cdev1);
if (ret != 0) {
- CTCM_DBF_TEXT(SETUP, CTC_DBF_WARN,
- "ccw_device_set_online (cdev[1]) failed ");
- ctcm_pr_warn("ccw_device_set_online (cdev[1]) failed "
- "with ret = %d\n", ret);
+ /* may be ok to fail now - can be done later */
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+ "%s(%s) set_online rc=%d",
+ CTCM_FUNTAIL, write_id, ret);
}
dev = ctcm_init_netdevice(priv);
-
- if (dev == NULL) {
- ctcm_pr_warn("ctcm_init_netdevice failed\n");
- goto out;
- }
+ if (dev == NULL)
+ goto out;
for (direction = READ; direction <= WRITE; direction++) {
priv->channel[direction] =
@@ -1590,8 +1555,7 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
if (priv->channel[direction] == NULL) {
if (direction == WRITE)
channel_free(priv->channel[READ]);
- ctcm_free_netdevice(dev);
- goto out;
+ goto out_dev;
}
priv->channel[direction]->netdev = dev;
priv->channel[direction]->protocol = priv->protocol;
@@ -1600,26 +1564,24 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
/* sysfs magic */
SET_NETDEV_DEV(dev, &cgdev->dev);
- if (ctcm_netdev_register(dev) != 0) {
- ctcm_free_netdevice(dev);
- goto out;
- }
+ if (register_netdev(dev))
+ goto out_dev;
if (ctcm_add_attributes(&cgdev->dev)) {
- ctcm_netdev_unregister(dev);
-/* dev->priv = NULL; why that ???? */
- ctcm_free_netdevice(dev);
- goto out;
+ unregister_netdev(dev);
+ goto out_dev;
}
strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name));
CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
- "setup(%s) ok : r/w = %s / %s, proto : %d",
- dev->name, priv->channel[READ]->id,
+ "setup(%s) OK : r/w = %s/%s, protocol : %d", dev->name,
+ priv->channel[READ]->id,
priv->channel[WRITE]->id, priv->protocol);
return 0;
+out_dev:
+ ctcm_free_netdevice(dev);
out:
ccw_device_set_offline(cgdev->cdev[1]);
ccw_device_set_offline(cgdev->cdev[0]);
@@ -1658,8 +1620,7 @@ static int ctcm_shutdown_device(struct ccwgroup_device *cgdev)
channel_free(priv->channel[WRITE]);
if (dev) {
- ctcm_netdev_unregister(dev);
-/* dev->priv = NULL; why that ??? */
+ unregister_netdev(dev);
ctcm_free_netdevice(dev);
}
@@ -1682,13 +1643,16 @@ static int ctcm_shutdown_device(struct ccwgroup_device *cgdev)
static void ctcm_remove_device(struct ccwgroup_device *cgdev)
{
- struct ctcm_priv *priv;
+ struct ctcm_priv *priv = dev_get_drvdata(&cgdev->dev);
- CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, __FUNCTION__);
+ BUG_ON(priv == NULL);
+
+ CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
+ "removing device %s, r/w = %s/%s, proto : %d",
+ priv->channel[READ]->netdev->name,
+ priv->channel[READ]->id, priv->channel[WRITE]->id,
+ priv->protocol);
- priv = dev_get_drvdata(&cgdev->dev);
- if (!priv)
- return;
if (cgdev->state == CCWGROUP_ONLINE)
ctcm_shutdown_device(cgdev);
ctcm_remove_files(&cgdev->dev);
@@ -1748,8 +1712,6 @@ static int __init ctcm_init(void)
ret = ctcm_register_dbf_views();
if (ret) {
- ctcm_pr_crit("ctcm_init failed with ctcm_register_dbf_views "
- "rc = %d\n", ret);
return ret;
}
ret = register_cu3088_discipline(&ctcm_group_driver);
diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h
index 95b0c0b6ebc..a72e0feeb27 100644
--- a/drivers/s390/net/ctcm_main.h
+++ b/drivers/s390/net/ctcm_main.h
@@ -22,9 +22,9 @@
#define CTC_DRIVER_NAME "ctcm"
#define CTC_DEVICE_NAME "ctc"
-#define CTC_DEVICE_GENE "ctc%d"
#define MPC_DEVICE_NAME "mpc"
-#define MPC_DEVICE_GENE "mpc%d"
+#define CTC_DEVICE_GENE CTC_DEVICE_NAME "%d"
+#define MPC_DEVICE_GENE MPC_DEVICE_NAME "%d"
#define CHANNEL_FLAGS_READ 0
#define CHANNEL_FLAGS_WRITE 1
@@ -48,6 +48,30 @@
#define ctcm_pr_err(fmt, arg...) printk(KERN_ERR fmt, ##arg)
#define ctcm_pr_crit(fmt, arg...) printk(KERN_CRIT fmt, ##arg)
+#define CTCM_PR_DEBUG(fmt, arg...) \
+ do { \
+ if (do_debug) \
+ printk(KERN_DEBUG fmt, ##arg); \
+ } while (0)
+
+#define CTCM_PR_DBGDATA(fmt, arg...) \
+ do { \
+ if (do_debug_data) \
+ printk(KERN_DEBUG fmt, ##arg); \
+ } while (0)
+
+#define CTCM_D3_DUMP(buf, len) \
+ do { \
+ if (do_debug_data) \
+ ctcmpc_dumpit(buf, len); \
+ } while (0)
+
+#define CTCM_CCW_DUMP(buf, len) \
+ do { \
+ if (do_debug_ccw) \
+ ctcmpc_dumpit(buf, len); \
+ } while (0)
+
/*
* CCW commands, used in this driver.
*/
@@ -161,8 +185,9 @@ struct channel {
fsm_instance *fsm; /* finite state machine of this channel */
struct net_device *netdev; /* corresponding net_device */
struct ctcm_profile prof;
- unsigned char *trans_skb_data;
+ __u8 *trans_skb_data;
__u16 logflags;
+ __u8 sense_rc; /* last unit check sense code report control */
};
struct ctcm_priv {
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
index 044addee64a..49ae1cd25ca 100644
--- a/drivers/s390/net/ctcm_mpc.c
+++ b/drivers/s390/net/ctcm_mpc.c
@@ -149,7 +149,7 @@ void ctcmpc_dumpit(char *buf, int len)
for (ct = 0; ct < len; ct++, ptr++, rptr++) {
if (sw == 0) {
#if (UTS_MACHINE == s390x)
- sprintf(addr, "%16.16lx", (unsigned long)rptr);
+ sprintf(addr, "%16.16lx", (__u64)rptr);
#else
sprintf(addr, "%8.8X", (__u32)rptr);
#endif
@@ -164,7 +164,7 @@ void ctcmpc_dumpit(char *buf, int len)
strcat(bhex, " ");
#if (UTS_MACHINE == s390x)
- sprintf(tbuf, "%2.2lX", (unsigned long)*ptr);
+ sprintf(tbuf, "%2.2lX", (__u64)*ptr);
#else
sprintf(tbuf, "%2.2X", (__u32)*ptr);
#endif
@@ -179,24 +179,24 @@ void ctcmpc_dumpit(char *buf, int len)
basc[sw+1] = '\0';
sw++;
rm--;
- if (sw == 16) {
- if ((strcmp(duphex, bhex)) != 0) {
- if (dup != 0) {
- sprintf(tdup, "Duplicate as above "
- "to %s", addr);
- printk(KERN_INFO " "
- " --- %s ---\n", tdup);
- }
- printk(KERN_INFO " %s (+%s) : %s [%s]\n",
+ if (sw != 16)
+ continue;
+ if ((strcmp(duphex, bhex)) != 0) {
+ if (dup != 0) {
+ sprintf(tdup,
+ "Duplicate as above to %s", addr);
+ ctcm_pr_debug(" --- %s ---\n",
+ tdup);
+ }
+ ctcm_pr_debug(" %s (+%s) : %s [%s]\n",
addr, boff, bhex, basc);
- dup = 0;
- strcpy(duphex, bhex);
- } else
- dup++;
+ dup = 0;
+ strcpy(duphex, bhex);
+ } else
+ dup++;
- sw = 0;
- rm = 16;
- }
+ sw = 0;
+ rm = 16;
} /* endfor */
if (sw != 0) {
@@ -210,19 +210,17 @@ void ctcmpc_dumpit(char *buf, int len)
}
if (dup != 0) {
sprintf(tdup, "Duplicate as above to %s", addr);
- printk(KERN_INFO " "
- " --- %s ---\n", tdup);
+ ctcm_pr_debug(" --- %s ---\n", tdup);
}
- printk(KERN_INFO " %s (+%s) : %s [%s]\n",
- addr, boff, bhex, basc);
+ ctcm_pr_debug(" %s (+%s) : %s [%s]\n",
+ addr, boff, bhex, basc);
} else {
if (dup >= 1) {
sprintf(tdup, "Duplicate as above to %s", addr);
- printk(KERN_INFO " "
- " --- %s ---\n", tdup);
+ ctcm_pr_debug(" --- %s ---\n", tdup);
}
if (dup != 0) {
- printk(KERN_INFO " %s (+%s) : %s [%s]\n",
+ ctcm_pr_debug(" %s (+%s) : %s [%s]\n",
addr, boff, bhex, basc);
}
}
@@ -241,7 +239,7 @@ void ctcmpc_dumpit(char *buf, int len)
*/
void ctcmpc_dump_skb(struct sk_buff *skb, int offset)
{
- unsigned char *p = skb->data;
+ __u8 *p = skb->data;
struct th_header *header;
struct pdu *pheader;
int bl = skb->len;
@@ -253,8 +251,8 @@ void ctcmpc_dump_skb(struct sk_buff *skb, int offset)
p += offset;
header = (struct th_header *)p;
- printk(KERN_INFO "dump:\n");
- printk(KERN_INFO "skb len=%d \n", skb->len);
+ ctcm_pr_debug("dump:\n");
+ ctcm_pr_debug("skb len=%d \n", skb->len);
if (skb->len > 2) {
switch (header->th_ch_flag) {
case TH_HAS_PDU:
@@ -273,32 +271,64 @@ void ctcmpc_dump_skb(struct sk_buff *skb, int offset)
}
pheader = (struct pdu *)p;
- printk(KERN_INFO "pdu->offset: %d hex: %04x\n",
- pheader->pdu_offset, pheader->pdu_offset);
- printk(KERN_INFO "pdu->flag : %02x\n", pheader->pdu_flag);
- printk(KERN_INFO "pdu->proto : %02x\n", pheader->pdu_proto);
- printk(KERN_INFO "pdu->seq : %02x\n", pheader->pdu_seq);
+ ctcm_pr_debug("pdu->offset: %d hex: %04x\n",
+ pheader->pdu_offset, pheader->pdu_offset);
+ ctcm_pr_debug("pdu->flag : %02x\n", pheader->pdu_flag);
+ ctcm_pr_debug("pdu->proto : %02x\n", pheader->pdu_proto);
+ ctcm_pr_debug("pdu->seq : %02x\n", pheader->pdu_seq);
goto dumpdata;
dumpth:
- printk(KERN_INFO "th->seg : %02x\n", header->th_seg);
- printk(KERN_INFO "th->ch : %02x\n", header->th_ch_flag);
- printk(KERN_INFO "th->blk_flag: %02x\n", header->th_blk_flag);
- printk(KERN_INFO "th->type : %s\n",
- (header->th_is_xid) ? "DATA" : "XID");
- printk(KERN_INFO "th->seqnum : %04x\n", header->th_seq_num);
+ ctcm_pr_debug("th->seg : %02x\n", header->th_seg);
+ ctcm_pr_debug("th->ch : %02x\n", header->th_ch_flag);
+ ctcm_pr_debug("th->blk_flag: %02x\n", header->th_blk_flag);
+ ctcm_pr_debug("th->type : %s\n",
+ (header->th_is_xid) ? "DATA" : "XID");
+ ctcm_pr_debug("th->seqnum : %04x\n", header->th_seq_num);
}
dumpdata:
if (bl > 32)
bl = 32;
- printk(KERN_INFO "data: ");
+ ctcm_pr_debug("data: ");
for (i = 0; i < bl; i++)
- printk(KERN_INFO "%02x%s", *p++, (i % 16) ? " " : "\n<7>");
- printk(KERN_INFO "\n");
+ ctcm_pr_debug("%02x%s", *p++, (i % 16) ? " " : "\n");
+ ctcm_pr_debug("\n");
}
#endif
+static struct net_device *ctcmpc_get_dev(int port_num)
+{
+ char device[20];
+ struct net_device *dev;
+ struct ctcm_priv *priv;
+
+ sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
+
+ dev = __dev_get_by_name(&init_net, device);
+
+ if (dev == NULL) {
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s: Device not found by name: %s",
+ CTCM_FUNTAIL, device);
+ return NULL;
+ }
+ priv = dev->priv;
+ if (priv == NULL) {
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): dev->priv is NULL",
+ CTCM_FUNTAIL, device);
+ return NULL;
+ }
+ if (priv->mpcg == NULL) {
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): priv->mpcg is NULL",
+ CTCM_FUNTAIL, device);
+ return NULL;
+ }
+ return dev;
+}
+
/*
* ctc_mpc_alloc_channel
* (exported interface)
@@ -308,34 +338,23 @@ dumpdata:
*/
int ctc_mpc_alloc_channel(int port_num, void (*callback)(int, int))
{
- char device[20];
struct net_device *dev;
struct mpc_group *grp;
struct ctcm_priv *priv;
- ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
-
- sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
- dev = __dev_get_by_name(&init_net, device);
-
- if (dev == NULL) {
- printk(KERN_INFO "ctc_mpc_alloc_channel %s dev=NULL\n", device);
+ dev = ctcmpc_get_dev(port_num);
+ if (dev == NULL)
return 1;
- }
-
priv = dev->priv;
grp = priv->mpcg;
- if (!grp)
- return 1;
grp->allochanfunc = callback;
grp->port_num = port_num;
grp->port_persist = 1;
- ctcm_pr_debug("ctcmpc: %s called for device %s state=%s\n",
- __FUNCTION__,
- dev->name,
- fsm_getstate_str(grp->fsm));
+ CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_INFO,
+ "%s(%s): state=%s",
+ CTCM_FUNTAIL, dev->name, fsm_getstate_str(grp->fsm));
switch (fsm_getstate(grp->fsm)) {
case MPCG_STATE_INOP:
@@ -377,12 +396,8 @@ int ctc_mpc_alloc_channel(int port_num, void (*callback)(int, int))
grp->allocchan_callback_retries = 0;
}
break;
- default:
- return 0;
-
}
- ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
return 0;
}
EXPORT_SYMBOL(ctc_mpc_alloc_channel);
@@ -394,31 +409,22 @@ EXPORT_SYMBOL(ctc_mpc_alloc_channel);
void ctc_mpc_establish_connectivity(int port_num,
void (*callback)(int, int, int))
{
- char device[20];
struct net_device *dev;
struct mpc_group *grp;
struct ctcm_priv *priv;
struct channel *rch, *wch;
- ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
-
- sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
- dev = __dev_get_by_name(&init_net, device);
-
- if (dev == NULL) {
- printk(KERN_INFO "ctc_mpc_establish_connectivity "
- "%s dev=NULL\n", device);
+ dev = ctcmpc_get_dev(port_num);
+ if (dev == NULL)
return;
- }
priv = dev->priv;
+ grp = priv->mpcg;
rch = priv->channel[READ];
wch = priv->channel[WRITE];
- grp = priv->mpcg;
-
- ctcm_pr_debug("ctcmpc: %s() called for device %s state=%s\n",
- __FUNCTION__, dev->name,
- fsm_getstate_str(grp->fsm));
+ CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_INFO,
+ "%s(%s): state=%s",
+ CTCM_FUNTAIL, dev->name, fsm_getstate_str(grp->fsm));
grp->estconnfunc = callback;
grp->port_num = port_num;
@@ -446,8 +452,10 @@ void ctc_mpc_establish_connectivity(int port_num,
case MPCG_STATE_RESET:
/* MPC Group is not ready to start XID - min num of */
/* 1 read and 1 write channel have not been acquired*/
- printk(KERN_WARNING "ctcmpc: %s() REJECTED ACTIVE XID Req"
- "uest - Channel Pair is not Active\n", __FUNCTION__);
+
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): REJECTED - inactive channels",
+ CTCM_FUNTAIL, dev->name);
if (grp->estconnfunc) {
grp->estconnfunc(grp->port_num, -1, 0);
grp->estconnfunc = NULL;
@@ -457,11 +465,12 @@ void ctc_mpc_establish_connectivity(int port_num,
/* alloc channel was called but no XID exchange */
/* has occurred. initiate xside XID exchange */
/* make sure yside XID0 processing has not started */
+
if ((fsm_getstate(rch->fsm) > CH_XID0_PENDING) ||
(fsm_getstate(wch->fsm) > CH_XID0_PENDING)) {
- printk(KERN_WARNING "mpc: %s() ABORT ACTIVE XID"
- " Request- PASSIVE XID in process\n"
- , __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): ABORT - PASSIVE XID",
+ CTCM_FUNTAIL, dev->name);
break;
}
grp->send_qllc_disc = 1;
@@ -476,9 +485,9 @@ void ctc_mpc_establish_connectivity(int port_num,
(fsm_getstate(rch->fsm) == CH_XID0_PENDING))
fsm_event(grp->fsm, MPCG_EVENT_XID0DO, rch);
else {
- printk(KERN_WARNING "mpc: %s() Unable to start"
- " ACTIVE XID0 on read channel\n",
- __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): RX-%s not ready for ACTIVE XID0",
+ CTCM_FUNTAIL, dev->name, rch->id);
if (grp->estconnfunc) {
grp->estconnfunc(grp->port_num, -1, 0);
grp->estconnfunc = NULL;
@@ -490,9 +499,9 @@ void ctc_mpc_establish_connectivity(int port_num,
(fsm_getstate(wch->fsm) == CH_XID0_PENDING))
fsm_event(grp->fsm, MPCG_EVENT_XID0DO, wch);
else {
- printk(KERN_WARNING "mpc: %s() Unable to start"
- " ACTIVE XID0 on write channel\n",
- __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): WX-%s not ready for ACTIVE XID0",
+ CTCM_FUNTAIL, dev->name, wch->id);
if (grp->estconnfunc) {
grp->estconnfunc(grp->port_num, -1, 0);
grp->estconnfunc = NULL;
@@ -508,7 +517,7 @@ void ctc_mpc_establish_connectivity(int port_num,
}
done:
- ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
+ CTCM_PR_DEBUG("Exit %s()\n", __func__);
return;
}
EXPORT_SYMBOL(ctc_mpc_establish_connectivity);
@@ -520,40 +529,22 @@ EXPORT_SYMBOL(ctc_mpc_establish_connectivity);
void ctc_mpc_dealloc_ch(int port_num)
{
struct net_device *dev;
- char device[20];
struct ctcm_priv *priv;
struct mpc_group *grp;
- ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
- sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
- dev = __dev_get_by_name(&init_net, device);
-
- if (dev == NULL) {
- printk(KERN_INFO "%s() %s dev=NULL\n", __FUNCTION__, device);
- goto done;
- }
+ dev = ctcmpc_get_dev(port_num);
+ if (dev == NULL)
+ return;
+ priv = dev->priv;
+ grp = priv->mpcg;
- ctcm_pr_debug("ctcmpc:%s %s() called for device %s refcount=%d\n",
- dev->name, __FUNCTION__,
- dev->name, atomic_read(&dev->refcnt));
+ CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_DEBUG,
+ "%s: %s: refcount = %d\n",
+ CTCM_FUNTAIL, dev->name, atomic_read(&dev->refcnt));
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_INFO "%s() %s priv=NULL\n",
- __FUNCTION__, device);
- goto done;
- }
fsm_deltimer(&priv->restart_timer);
-
- grp = priv->mpcg;
- if (grp == NULL) {
- printk(KERN_INFO "%s() %s dev=NULL\n", __FUNCTION__, device);
- goto done;
- }
grp->channels_terminating = 0;
-
fsm_deltimer(&grp->timer);
-
grp->allochanfunc = NULL;
grp->estconnfunc = NULL;
grp->port_persist = 0;
@@ -561,8 +552,6 @@ void ctc_mpc_dealloc_ch(int port_num)
fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
ctcm_close(dev);
-done:
- ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
return;
}
EXPORT_SYMBOL(ctc_mpc_dealloc_ch);
@@ -573,32 +562,22 @@ EXPORT_SYMBOL(ctc_mpc_dealloc_ch);
*/
void ctc_mpc_flow_control(int port_num, int flowc)
{
- char device[20];
struct ctcm_priv *priv;
struct mpc_group *grp;
struct net_device *dev;
struct channel *rch;
int mpcg_state;
- ctcm_pr_debug("ctcmpc enter: %s() %i\n", __FUNCTION__, flowc);
-
- sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
- dev = __dev_get_by_name(&init_net, device);
-
- if (dev == NULL) {
- printk(KERN_INFO "ctc_mpc_flow_control %s dev=NULL\n", device);
+ dev = ctcmpc_get_dev(port_num);
+ if (dev == NULL)
return;
- }
+ priv = dev->priv;
+ grp = priv->mpcg;
- ctcm_pr_debug("ctcmpc: %s %s called \n", dev->name, __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
+ "%s: %s: flowc = %d",
+ CTCM_FUNTAIL, dev->name, flowc);
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_INFO "ctcmpc:%s() %s priv=NULL\n",
- __FUNCTION__, device);
- return;
- }
- grp = priv->mpcg;
rch = priv->channel[READ];
mpcg_state = fsm_getstate(grp->fsm);
@@ -629,7 +608,6 @@ void ctc_mpc_flow_control(int port_num, int flowc)
break;
}
- ctcm_pr_debug("ctcmpc exit: %s() %i\n", __FUNCTION__, flowc);
}
EXPORT_SYMBOL(ctc_mpc_flow_control);
@@ -646,12 +624,8 @@ static void mpc_rcvd_sweep_resp(struct mpcg_info *mpcginfo)
struct mpc_group *grp = priv->mpcg;
struct channel *ch = priv->channel[WRITE];
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
- __FUNCTION__, ch, ch->id);
-
- if (do_debug_data)
- ctcmpc_dumpit((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
+ CTCM_PR_DEBUG("%s: ch=0x%p id=%s\n", __func__, ch, ch->id);
+ CTCM_D3_DUMP((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
grp->sweep_rsp_pend_num--;
@@ -684,14 +658,13 @@ static void ctcmpc_send_sweep_resp(struct channel *rch)
struct sk_buff *sweep_skb;
struct channel *ch = priv->channel[WRITE];
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
- __FUNCTION__, rch, rch->id);
+ CTCM_PR_DEBUG("%s: ch=0x%p id=%s\n", __func__, rch, rch->id);
- sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT,
- GFP_ATOMIC|GFP_DMA);
+ sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC | GFP_DMA);
if (sweep_skb == NULL) {
- printk(KERN_INFO "Couldn't alloc sweep_skb\n");
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): sweep_skb allocation ERROR\n",
+ CTCM_FUNTAIL, rch->id);
rc = -ENOMEM;
goto done;
}
@@ -746,7 +719,7 @@ static void mpc_rcvd_sweep_req(struct mpcg_info *mpcginfo)
if (do_debug)
CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
- " %s(): ch=0x%p id=%s\n", __FUNCTION__, ch, ch->id);
+ " %s(): ch=0x%p id=%s\n", __func__, ch, ch->id);
if (grp->in_sweep == 0) {
grp->in_sweep = 1;
@@ -755,8 +728,7 @@ static void mpc_rcvd_sweep_req(struct mpcg_info *mpcginfo)
grp->sweep_rsp_pend_num = grp->active_channels[READ];
}
- if (do_debug_data)
- ctcmpc_dumpit((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
+ CTCM_D3_DUMP((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
grp->sweep_req_pend_num--;
ctcmpc_send_sweep_resp(ch);
@@ -875,25 +847,13 @@ static int mpcg_fsm_len = ARRAY_SIZE(mpcg_fsm);
static void mpc_action_go_ready(fsm_instance *fsm, int event, void *arg)
{
struct net_device *dev = arg;
- struct ctcm_priv *priv = NULL;
- struct mpc_group *grp = NULL;
-
- if (dev == NULL) {
- printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
- return;
- }
-
- ctcm_pr_debug("ctcmpc enter: %s %s()\n", dev->name, __FUNCTION__);
-
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
- return;
- }
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = priv->mpcg;
- grp = priv->mpcg;
if (grp == NULL) {
- printk(KERN_INFO "%s() grp=NULL\n", __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): No MPC group",
+ CTCM_FUNTAIL, dev->name);
return;
}
@@ -907,7 +867,12 @@ static void mpc_action_go_ready(fsm_instance *fsm, int event, void *arg)
grp->estconnfunc = NULL;
} else if (grp->allochanfunc)
grp->send_qllc_disc = 1;
- goto done;
+
+ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): fails",
+ CTCM_FUNTAIL, dev->name);
+ return;
}
grp->port_persist = 1;
@@ -916,14 +881,7 @@ static void mpc_action_go_ready(fsm_instance *fsm, int event, void *arg)
tasklet_hi_schedule(&grp->mpc_tasklet2);
- ctcm_pr_debug("ctcmpc exit: %s %s()\n", dev->name, __FUNCTION__);
return;
-
-done:
- fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
-
-
- ctcm_pr_info("ctcmpc: %s()failure occurred\n", __FUNCTION__);
}
/*
@@ -933,42 +891,28 @@ done:
void mpc_group_ready(unsigned long adev)
{
struct net_device *dev = (struct net_device *)adev;
- struct ctcm_priv *priv = NULL;
- struct mpc_group *grp = NULL;
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = priv->mpcg;
struct channel *ch = NULL;
-
- ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
-
- if (dev == NULL) {
- printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
- return;
- }
-
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
- return;
- }
-
- grp = priv->mpcg;
if (grp == NULL) {
- printk(KERN_INFO "ctcmpc:%s() grp=NULL\n", __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): No MPC group",
+ CTCM_FUNTAIL, dev->name);
return;
}
- printk(KERN_NOTICE "ctcmpc: %s GROUP TRANSITIONED TO READY"
- " maxbuf:%d\n",
- dev->name, grp->group_max_buflen);
+ CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_NOTICE,
+ "%s: %s: GROUP TRANSITIONED TO READY, maxbuf = %d\n",
+ CTCM_FUNTAIL, dev->name, grp->group_max_buflen);
fsm_newstate(grp->fsm, MPCG_STATE_READY);
/* Put up a read on the channel */
ch = priv->channel[READ];
ch->pdu_seq = 0;
- if (do_debug_data)
- ctcm_pr_debug("ctcmpc: %s() ToDCM_pdu_seq= %08x\n" ,
- __FUNCTION__, ch->pdu_seq);
+ CTCM_PR_DBGDATA("ctcmpc: %s() ToDCM_pdu_seq= %08x\n" ,
+ __func__, ch->pdu_seq);
ctcmpc_chx_rxidle(ch->fsm, CTC_EVENT_START, ch);
/* Put the write channel in idle state */
@@ -980,22 +924,18 @@ void mpc_group_ready(unsigned long adev)
spin_unlock(&ch->collect_lock);
}
ctcm_chx_txidle(ch->fsm, CTC_EVENT_START, ch);
-
ctcm_clear_busy(dev);
if (grp->estconnfunc) {
grp->estconnfunc(grp->port_num, 0,
grp->group_max_buflen);
grp->estconnfunc = NULL;
- } else
- if (grp->allochanfunc)
- grp->allochanfunc(grp->port_num,
- grp->group_max_buflen);
+ } else if (grp->allochanfunc)
+ grp->allochanfunc(grp->port_num, grp->group_max_buflen);
grp->send_qllc_disc = 1;
grp->changed_side = 0;
- ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
return;
}
@@ -1004,51 +944,26 @@ void mpc_group_ready(unsigned long adev)
* Increment the MPC Group Active Channel Counts
* helper of dev_action (called from channel fsm)
*/
-int mpc_channel_action(struct channel *ch, int direction, int action)
+void mpc_channel_action(struct channel *ch, int direction, int action)
{
- struct net_device *dev = ch->netdev;
- struct ctcm_priv *priv;
- struct mpc_group *grp = NULL;
- int rc = 0;
-
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
- __FUNCTION__, ch, ch->id);
-
- if (dev == NULL) {
- printk(KERN_INFO "ctcmpc_channel_action %i dev=NULL\n",
- action);
- rc = 1;
- goto done;
- }
-
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_INFO
- "ctcmpc_channel_action%i priv=NULL, dev=%s\n",
- action, dev->name);
- rc = 2;
- goto done;
- }
-
- grp = priv->mpcg;
+ struct net_device *dev = ch->netdev;
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = priv->mpcg;
if (grp == NULL) {
- printk(KERN_INFO "ctcmpc: %s()%i mpcgroup=NULL, dev=%s\n",
- __FUNCTION__, action, dev->name);
- rc = 3;
- goto done;
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): No MPC group",
+ CTCM_FUNTAIL, dev->name);
+ return;
}
- ctcm_pr_info(
- "ctcmpc: %s() %i(): Grp:%s total_channel_paths=%i "
- "active_channels read=%i, write=%i\n",
- __FUNCTION__,
- action,
- fsm_getstate_str(grp->fsm),
- grp->num_channel_paths,
- grp->active_channels[READ],
- grp->active_channels[WRITE]);
+ CTCM_PR_DEBUG("enter %s: ch=0x%p id=%s\n", __func__, ch, ch->id);
+
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_NOTICE,
+ "%s: %i / Grp:%s total_channels=%i, active_channels: "
+ "read=%i, write=%i\n", __func__, action,
+ fsm_getstate_str(grp->fsm), grp->num_channel_paths,
+ grp->active_channels[READ], grp->active_channels[WRITE]);
if ((action == MPC_CHANNEL_ADD) && (ch->in_mpcgroup == 0)) {
grp->num_channel_paths++;
@@ -1062,10 +977,11 @@ int mpc_channel_action(struct channel *ch, int direction, int action)
ch->xid_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT,
GFP_ATOMIC | GFP_DMA);
if (ch->xid_skb == NULL) {
- printk(KERN_INFO "ctcmpc: %s()"
- "Couldn't alloc ch xid_skb\n", __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): Couldn't alloc ch xid_skb\n",
+ CTCM_FUNTAIL, dev->name);
fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
- return 1;
+ return;
}
ch->xid_skb_data = ch->xid_skb->data;
ch->xid_th = (struct th_header *)ch->xid_skb->data;
@@ -1097,8 +1013,9 @@ int mpc_channel_action(struct channel *ch, int direction, int action)
(grp->active_channels[WRITE] > 0) &&
(fsm_getstate(grp->fsm) < MPCG_STATE_XID2INITW)) {
fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);
- printk(KERN_NOTICE "ctcmpc: %s MPC GROUP "
- "CHANNELS ACTIVE\n", dev->name);
+ CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_NOTICE,
+ "%s: %s: MPC GROUP CHANNELS ACTIVE\n",
+ __func__, dev->name);
}
} else if ((action == MPC_CHANNEL_REMOVE) &&
(ch->in_mpcgroup == 1)) {
@@ -1119,25 +1036,14 @@ int mpc_channel_action(struct channel *ch, int direction, int action)
(grp->active_channels[READ] > 0)))
fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
}
-
done:
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
+ "exit %s: %i / Grp:%s total_channels=%i, active_channels: "
+ "read=%i, write=%i\n", __func__, action,
+ fsm_getstate_str(grp->fsm), grp->num_channel_paths,
+ grp->active_channels[READ], grp->active_channels[WRITE]);
- if (do_debug) {
- ctcm_pr_debug(
- "ctcmpc: %s() %i Grp:%s ttl_chan_paths=%i "
- "active_chans read=%i, write=%i\n",
- __FUNCTION__,
- action,
- fsm_getstate_str(grp->fsm),
- grp->num_channel_paths,
- grp->active_channels[READ],
- grp->active_channels[WRITE]);
-
- ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
- __FUNCTION__, ch, ch->id);
- }
- return rc;
-
+ CTCM_PR_DEBUG("exit %s: ch=0x%p id=%s\n", __func__, ch, ch->id);
}
/**
@@ -1163,9 +1069,8 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
int skblen;
int sendrc = 0;
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s() %s cp:%i ch:%s\n",
- __FUNCTION__, dev->name, smp_processor_id(), ch->id);
+ CTCM_PR_DEBUG("ctcmpc enter: %s() %s cp:%i ch:%s\n",
+ __func__, dev->name, smp_processor_id(), ch->id);
header = (struct th_header *)pskb->data;
if ((header->th_seg == 0) &&
@@ -1174,21 +1079,16 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
(header->th_seq_num == 0))
/* nothing for us */ goto done;
- if (do_debug_data) {
- ctcm_pr_debug("ctcmpc: %s() th_header\n", __FUNCTION__);
- ctcmpc_dumpit((char *)header, TH_HEADER_LENGTH);
- ctcm_pr_debug("ctcmpc: %s() pskb len: %04x \n",
- __FUNCTION__, pskb->len);
- }
+ CTCM_PR_DBGDATA("%s: th_header\n", __func__);
+ CTCM_D3_DUMP((char *)header, TH_HEADER_LENGTH);
+ CTCM_PR_DBGDATA("%s: pskb len: %04x \n", __func__, pskb->len);
pskb->dev = dev;
pskb->ip_summed = CHECKSUM_UNNECESSARY;
skb_pull(pskb, TH_HEADER_LENGTH);
if (likely(header->th_ch_flag == TH_HAS_PDU)) {
- if (do_debug_data)
- ctcm_pr_debug("ctcmpc: %s() came into th_has_pdu\n",
- __FUNCTION__);
+ CTCM_PR_DBGDATA("%s: came into th_has_pdu\n", __func__);
if ((fsm_getstate(grp->fsm) == MPCG_STATE_FLOWC) ||
((fsm_getstate(grp->fsm) == MPCG_STATE_READY) &&
(header->th_seq_num != ch->th_seq_num + 1) &&
@@ -1202,33 +1102,29 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
grp->out_of_sequence += 1;
__skb_push(pskb, TH_HEADER_LENGTH);
skb_queue_tail(&ch->io_queue, pskb);
- if (do_debug_data)
- ctcm_pr_debug("ctcmpc: %s() th_seq_num "
- "expect:%08x got:%08x\n", __FUNCTION__,
- ch->th_seq_num + 1, header->th_seq_num);
+ CTCM_PR_DBGDATA("%s: th_seq_num expect:%08x "
+ "got:%08x\n", __func__,
+ ch->th_seq_num + 1, header->th_seq_num);
return;
}
grp->out_of_sequence = 0;
ch->th_seq_num = header->th_seq_num;
- if (do_debug_data)
- ctcm_pr_debug("ctcmpc: %s() FromVTAM_th_seq=%08x\n",
- __FUNCTION__, ch->th_seq_num);
+ CTCM_PR_DBGDATA("ctcmpc: %s() FromVTAM_th_seq=%08x\n",
+ __func__, ch->th_seq_num);
if (unlikely(fsm_getstate(grp->fsm) != MPCG_STATE_READY))
goto done;
pdu_last_seen = 0;
while ((pskb->len > 0) && !pdu_last_seen) {
curr_pdu = (struct pdu *)pskb->data;
- if (do_debug_data) {
- ctcm_pr_debug("ctcm: %s() pdu_header\n",
- __FUNCTION__);
- ctcmpc_dumpit((char *)pskb->data,
- PDU_HEADER_LENGTH);
- ctcm_pr_debug("ctcm: %s() pskb len: %04x \n",
- __FUNCTION__, pskb->len);
- }
+
+ CTCM_PR_DBGDATA("%s: pdu_header\n", __func__);
+ CTCM_D3_DUMP((char *)pskb->data, PDU_HEADER_LENGTH);
+ CTCM_PR_DBGDATA("%s: pskb len: %04x \n",
+ __func__, pskb->len);
+
skb_pull(pskb, PDU_HEADER_LENGTH);
if (curr_pdu->pdu_flag & PDU_LAST)
@@ -1239,46 +1135,39 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
pskb->protocol = htons(ETH_P_SNA_DIX);
if ((pskb->len <= 0) || (pskb->len > ch->max_bufsize)) {
- printk(KERN_INFO
- "%s Illegal packet size %d "
- "received "
- "dropping\n", dev->name,
- pskb->len);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): Dropping packet with "
+ "illegal siize %d",
+ CTCM_FUNTAIL, dev->name, pskb->len);
+
priv->stats.rx_dropped++;
priv->stats.rx_length_errors++;
goto done;
}
skb_reset_mac_header(pskb);
new_len = curr_pdu->pdu_offset;
- if (do_debug_data)
- ctcm_pr_debug("ctcmpc: %s() new_len: %04x \n",
- __FUNCTION__, new_len);
+ CTCM_PR_DBGDATA("%s: new_len: %04x \n",
+ __func__, new_len);
if ((new_len == 0) || (new_len > pskb->len)) {
/* should never happen */
/* pskb len must be hosed...bail out */
- printk(KERN_INFO
- "ctcmpc: %s(): invalid pdu"
- " offset of %04x - data may be"
- "lost\n", __FUNCTION__, new_len);
- goto done;
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): non valid pdu_offset: %04x",
+ /* "data may be lost", */
+ CTCM_FUNTAIL, dev->name, new_len);
+ goto done;
}
skb = __dev_alloc_skb(new_len+4, GFP_ATOMIC);
if (!skb) {
- printk(KERN_INFO
- "ctcm: %s Out of memory in "
- "%s()- request-len:%04x \n",
- dev->name,
- __FUNCTION__,
- new_len+4);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): MEMORY allocation error",
+ CTCM_FUNTAIL, dev->name);
priv->stats.rx_dropped++;
- fsm_event(grp->fsm,
- MPCG_EVENT_INOP, dev);
+ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
goto done;
}
-
- memcpy(skb_put(skb, new_len),
- pskb->data, new_len);
+ memcpy(skb_put(skb, new_len), pskb->data, new_len);
skb_reset_mac_header(skb);
skb->dev = pskb->dev;
@@ -1287,17 +1176,14 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
*((__u32 *) skb_push(skb, 4)) = ch->pdu_seq;
ch->pdu_seq++;
- if (do_debug_data)
- ctcm_pr_debug("%s: ToDCM_pdu_seq= %08x\n",
- __FUNCTION__, ch->pdu_seq);
-
- ctcm_pr_debug("ctcm: %s() skb:%0lx "
- "skb len: %d \n", __FUNCTION__,
- (unsigned long)skb, skb->len);
if (do_debug_data) {
- ctcm_pr_debug("ctcmpc: %s() up to 32 bytes"
- " of pdu_data sent\n",
- __FUNCTION__);
+ ctcm_pr_debug("%s: ToDCM_pdu_seq= %08x\n",
+ __func__, ch->pdu_seq);
+ ctcm_pr_debug("%s: skb:%0lx "
+ "skb len: %d \n", __func__,
+ (unsigned long)skb, skb->len);
+ ctcm_pr_debug("%s: up to 32 bytes "
+ "of pdu_data sent\n", __func__);
ctcmpc_dump32((char *)skb->data, skb->len);
}
@@ -1316,8 +1202,8 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
mpcginfo->ch = ch;
mpcginfo->th = header;
mpcginfo->skb = pskb;
- ctcm_pr_debug("ctcmpc: %s() Not PDU - may be control pkt\n",
- __FUNCTION__);
+ CTCM_PR_DEBUG("%s: Not PDU - may be control pkt\n",
+ __func__);
/* it's a sweep? */
sweep = (struct th_sweep *)pskb->data;
mpcginfo->sweep = sweep;
@@ -1333,8 +1219,9 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
} else if (header->th_blk_flag == TH_DISCONTACT)
fsm_event(grp->fsm, MPCG_EVENT_DISCONC, mpcginfo);
else if (header->th_seq_num != 0) {
- printk(KERN_INFO "%s unexpected packet"
- " expected control pkt\n", dev->name);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): control pkt expected\n",
+ CTCM_FUNTAIL, dev->name);
priv->stats.rx_dropped++;
/* mpcginfo only used for non-data transfers */
kfree(mpcginfo);
@@ -1347,13 +1234,12 @@ done:
dev_kfree_skb_any(pskb);
if (sendrc == NET_RX_DROP) {
printk(KERN_WARNING "%s %s() NETWORK BACKLOG EXCEEDED"
- " - PACKET DROPPED\n", dev->name, __FUNCTION__);
+ " - PACKET DROPPED\n", dev->name, __func__);
fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
}
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
- dev->name, __FUNCTION__, ch, ch->id);
+ CTCM_PR_DEBUG("exit %s: %s: ch=0x%p id=%s\n",
+ __func__, dev->name, ch, ch->id);
}
/**
@@ -1366,15 +1252,14 @@ done:
*/
void ctcmpc_bh(unsigned long thischan)
{
- struct channel *ch = (struct channel *)thischan;
+ struct channel *ch = (struct channel *)thischan;
struct sk_buff *skb;
- struct net_device *dev = ch->netdev;
- struct ctcm_priv *priv = dev->priv;
- struct mpc_group *grp = priv->mpcg;
+ struct net_device *dev = ch->netdev;
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = priv->mpcg;
- if (do_debug)
- ctcm_pr_debug("%s cp:%i enter: %s() %s\n",
- dev->name, smp_processor_id(), __FUNCTION__, ch->id);
+ CTCM_PR_DEBUG("%s cp:%i enter: %s() %s\n",
+ dev->name, smp_processor_id(), __func__, ch->id);
/* caller has requested driver to throttle back */
while ((fsm_getstate(grp->fsm) != MPCG_STATE_FLOWC) &&
(skb = skb_dequeue(&ch->io_queue))) {
@@ -1390,9 +1275,8 @@ void ctcmpc_bh(unsigned long thischan)
if (skb == skb_peek(&ch->io_queue))
break;
}
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
- dev->name, __FUNCTION__, ch, ch->id);
+ CTCM_PR_DEBUG("exit %s: %s: ch=0x%p id=%s\n",
+ __func__, dev->name, ch, ch->id);
return;
}
@@ -1403,16 +1287,16 @@ struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv)
{
struct mpc_group *grp;
- CTCM_DBF_TEXT(MPC_SETUP, 3, __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_INFO,
+ "Enter %s(%p)", CTCM_FUNTAIL, priv);
grp = kzalloc(sizeof(struct mpc_group), GFP_KERNEL);
if (grp == NULL)
return NULL;
- grp->fsm =
- init_fsm("mpcg", mpcg_state_names, mpcg_event_names,
- MPCG_NR_STATES, MPCG_NR_EVENTS, mpcg_fsm,
- mpcg_fsm_len, GFP_KERNEL);
+ grp->fsm = init_fsm("mpcg", mpcg_state_names, mpcg_event_names,
+ MPCG_NR_STATES, MPCG_NR_EVENTS, mpcg_fsm,
+ mpcg_fsm_len, GFP_KERNEL);
if (grp->fsm == NULL) {
kfree(grp);
return NULL;
@@ -1424,7 +1308,6 @@ struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv)
grp->xid_skb =
__dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC | GFP_DMA);
if (grp->xid_skb == NULL) {
- printk(KERN_INFO "Couldn't alloc MPCgroup xid_skb\n");
kfree_fsm(grp->fsm);
kfree(grp);
return NULL;
@@ -1435,7 +1318,7 @@ struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv)
memcpy(skb_put(grp->xid_skb, TH_HEADER_LENGTH),
&thnorm, TH_HEADER_LENGTH);
- grp->xid = (struct xid2 *) skb_tail_pointer(grp->xid_skb);
+ grp->xid = (struct xid2 *)skb_tail_pointer(grp->xid_skb);
memcpy(skb_put(grp->xid_skb, XID2_LENGTH), &init_xid, XID2_LENGTH);
grp->xid->xid2_adj_id = jiffies | 0xfff00000;
grp->xid->xid2_sender_id = jiffies;
@@ -1446,7 +1329,6 @@ struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv)
grp->rcvd_xid_skb =
__dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA);
if (grp->rcvd_xid_skb == NULL) {
- printk(KERN_INFO "Couldn't alloc MPCgroup rcvd_xid_skb\n");
kfree_fsm(grp->fsm);
dev_kfree_skb(grp->xid_skb);
kfree(grp);
@@ -1492,32 +1374,27 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg)
int rc = 0;
struct channel *wch, *rch;
- if (dev == NULL) {
- printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
- return;
- }
-
- ctcm_pr_debug("ctcmpc enter: %s %s()\n", dev->name, __FUNCTION__);
+ BUG_ON(dev == NULL);
+ CTCM_PR_DEBUG("Enter %s: %s\n", __func__, dev->name);
priv = dev->priv;
grp = priv->mpcg;
grp->flow_off_called = 0;
-
fsm_deltimer(&grp->timer);
-
if (grp->channels_terminating)
- goto done;
+ return;
grp->channels_terminating = 1;
-
grp->saved_state = fsm_getstate(grp->fsm);
fsm_newstate(grp->fsm, MPCG_STATE_INOP);
if (grp->saved_state > MPCG_STATE_XID7INITF)
- printk(KERN_NOTICE "%s:MPC GROUP INOPERATIVE\n", dev->name);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_NOTICE,
+ "%s(%s): MPC GROUP INOPERATIVE",
+ CTCM_FUNTAIL, dev->name);
if ((grp->saved_state != MPCG_STATE_RESET) ||
/* dealloc_channel has been called */
- ((grp->saved_state == MPCG_STATE_RESET) &&
- (grp->port_persist == 0)))
+ ((grp->saved_state == MPCG_STATE_RESET) &&
+ (grp->port_persist == 0)))
fsm_deltimer(&priv->restart_timer);
wch = priv->channel[WRITE];
@@ -1567,29 +1444,24 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg)
/* This can result in INOP of VTAM PU due to halting of */
/* outstanding IO which causes a sense to be returned */
/* Only about 3 senses are allowed and then IOS/VTAM will*/
- /* ebcome unreachable without manual intervention */
- if ((grp->port_persist == 1) || (grp->alloc_called)) {
+ /* become unreachable without manual intervention */
+ if ((grp->port_persist == 1) || (grp->alloc_called)) {
grp->alloc_called = 0;
fsm_deltimer(&priv->restart_timer);
- fsm_addtimer(&priv->restart_timer,
- 500,
- DEV_EVENT_RESTART,
- dev);
+ fsm_addtimer(&priv->restart_timer, 500, DEV_EVENT_RESTART, dev);
fsm_newstate(grp->fsm, MPCG_STATE_RESET);
if (grp->saved_state > MPCG_STATE_XID7INITF)
- printk(KERN_NOTICE "%s:MPC GROUP RECOVERY SCHEDULED\n",
- dev->name);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ALWAYS,
+ "%s(%s): MPC GROUP RECOVERY SCHEDULED",
+ CTCM_FUNTAIL, dev->name);
} else {
fsm_deltimer(&priv->restart_timer);
fsm_addtimer(&priv->restart_timer, 500, DEV_EVENT_STOP, dev);
fsm_newstate(grp->fsm, MPCG_STATE_RESET);
- printk(KERN_NOTICE "%s:MPC GROUP RECOVERY NOT ATTEMPTED\n",
- dev->name);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ALWAYS,
+ "%s(%s): NO MPC GROUP RECOVERY ATTEMPTED",
+ CTCM_FUNTAIL, dev->name);
}
-
-done:
- ctcm_pr_debug("ctcmpc exit:%s %s()\n", dev->name, __FUNCTION__);
- return;
}
/**
@@ -1609,12 +1481,7 @@ static void mpc_action_timeout(fsm_instance *fi, int event, void *arg)
struct channel *wch;
struct channel *rch;
- CTCM_DBF_TEXT(MPC_TRACE, 6, __FUNCTION__);
-
- if (dev == NULL) {
- CTCM_DBF_TEXT_(MPC_ERROR, 4, "%s: dev=NULL\n", __FUNCTION__);
- return;
- }
+ BUG_ON(dev == NULL);
priv = dev->priv;
grp = priv->mpcg;
@@ -1633,8 +1500,9 @@ static void mpc_action_timeout(fsm_instance *fi, int event, void *arg)
fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
}
- CTCM_DBF_TEXT_(MPC_TRACE, 6, "%s: dev=%s exit",
- __FUNCTION__, dev->name);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
+ "%s: dev=%s exit",
+ CTCM_FUNTAIL, dev->name);
return;
}
@@ -1646,25 +1514,25 @@ void mpc_action_discontact(fsm_instance *fi, int event, void *arg)
{
struct mpcg_info *mpcginfo = arg;
struct channel *ch = mpcginfo->ch;
- struct net_device *dev = ch->netdev;
- struct ctcm_priv *priv = dev->priv;
- struct mpc_group *grp = priv->mpcg;
+ struct net_device *dev;
+ struct ctcm_priv *priv;
+ struct mpc_group *grp;
- if (ch == NULL) {
- printk(KERN_INFO "%s() ch=NULL\n", __FUNCTION__);
- return;
- }
- if (ch->netdev == NULL) {
- printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
- return;
+ if (ch) {
+ dev = ch->netdev;
+ if (dev) {
+ priv = dev->priv;
+ if (priv) {
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_NOTICE,
+ "%s: %s: %s\n",
+ CTCM_FUNTAIL, dev->name, ch->id);
+ grp = priv->mpcg;
+ grp->send_qllc_disc = 1;
+ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+ }
+ }
}
- ctcm_pr_debug("ctcmpc enter: %s %s()\n", dev->name, __FUNCTION__);
-
- grp->send_qllc_disc = 1;
- fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
-
- ctcm_pr_debug("ctcmpc exit: %s %s()\n", dev->name, __FUNCTION__);
return;
}
@@ -1675,26 +1543,9 @@ void mpc_action_discontact(fsm_instance *fi, int event, void *arg)
*/
void mpc_action_send_discontact(unsigned long thischan)
{
- struct channel *ch;
- struct net_device *dev;
- struct ctcm_priv *priv;
- struct mpc_group *grp;
- int rc = 0;
- unsigned long saveflags;
-
- ch = (struct channel *)thischan;
- dev = ch->netdev;
- priv = dev->priv;
- grp = priv->mpcg;
-
- ctcm_pr_info("ctcmpc: %s cp:%i enter: %s() GrpState:%s ChState:%s\n",
- dev->name,
- smp_processor_id(),
- __FUNCTION__,
- fsm_getstate_str(grp->fsm),
- fsm_getstate_str(ch->fsm));
- saveflags = 0; /* avoids compiler warning with
- spin_unlock_irqrestore */
+ int rc;
+ struct channel *ch = (struct channel *)thischan;
+ unsigned long saveflags = 0;
spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
rc = ccw_device_start(ch->cdev, &ch->ccw[15],
@@ -1702,16 +1553,9 @@ void mpc_action_send_discontact(unsigned long thischan)
spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
if (rc != 0) {
- ctcm_pr_info("ctcmpc: %s() ch:%s IO failed \n",
- __FUNCTION__,
- ch->id);
- ctcm_ccw_check_rc(ch, rc, "send discontact");
- /* Not checking return code value here */
- /* Making best effort to notify partner*/
- /* that MPC Group is going down */
+ ctcm_ccw_check_rc(ch, rc, (char *)__func__);
}
- ctcm_pr_debug("ctcmpc exit: %s %s()\n", dev->name, __FUNCTION__);
return;
}
@@ -1723,49 +1567,50 @@ void mpc_action_send_discontact(unsigned long thischan)
*/
static int mpc_validate_xid(struct mpcg_info *mpcginfo)
{
- struct channel *ch = mpcginfo->ch;
- struct net_device *dev = ch->netdev;
+ struct channel *ch = mpcginfo->ch;
+ struct net_device *dev = ch->netdev;
struct ctcm_priv *priv = dev->priv;
struct mpc_group *grp = priv->mpcg;
- struct xid2 *xid = mpcginfo->xid;
- int failed = 0;
- int rc = 0;
- __u64 our_id, their_id = 0;
- int len;
-
- len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
+ struct xid2 *xid = mpcginfo->xid;
+ int rc = 0;
+ __u64 our_id = 0;
+ __u64 their_id = 0;
+ int len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
- ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
+ CTCM_PR_DEBUG("Enter %s: xid=%p\n", __func__, xid);
- if (mpcginfo->xid == NULL) {
- printk(KERN_INFO "%s() xid=NULL\n", __FUNCTION__);
+ if (xid == NULL) {
rc = 1;
- goto done;
+ /* XID REJECTED: xid == NULL */
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): xid = NULL",
+ CTCM_FUNTAIL, ch->id);
+ goto done;
}
- ctcm_pr_debug("ctcmpc : %s xid received()\n", __FUNCTION__);
- ctcmpc_dumpit((char *)mpcginfo->xid, XID2_LENGTH);
+ CTCM_D3_DUMP((char *)xid, XID2_LENGTH);
/*the received direction should be the opposite of ours */
if (((CHANNEL_DIRECTION(ch->flags) == READ) ? XID2_WRITE_SIDE :
XID2_READ_SIDE) != xid->xid2_dlc_type) {
- failed = 1;
- printk(KERN_INFO "ctcmpc:%s() XID REJECTED - READ-WRITE CH "
- "Pairing Invalid \n", __FUNCTION__);
+ rc = 2;
+ /* XID REJECTED: r/w channel pairing mismatch */
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): r/w channel pairing mismatch",
+ CTCM_FUNTAIL, ch->id);
+ goto done;
}
if (xid->xid2_dlc_type == XID2_READ_SIDE) {
- ctcm_pr_debug("ctcmpc: %s(): grpmaxbuf:%d xid2buflen:%d\n",
- __FUNCTION__, grp->group_max_buflen,
- xid->xid2_buf_len);
+ CTCM_PR_DEBUG("%s: grpmaxbuf:%d xid2buflen:%d\n", __func__,
+ grp->group_max_buflen, xid->xid2_buf_len);
- if (grp->group_max_buflen == 0 ||
- grp->group_max_buflen > xid->xid2_buf_len - len)
+ if (grp->group_max_buflen == 0 || grp->group_max_buflen >
+ xid->xid2_buf_len - len)
grp->group_max_buflen = xid->xid2_buf_len - len;
}
-
- if (grp->saved_xid2 == NULL) {
+ if (grp->saved_xid2 == NULL) {
grp->saved_xid2 =
(struct xid2 *)skb_tail_pointer(grp->rcvd_xid_skb);
@@ -1786,49 +1631,54 @@ static int mpc_validate_xid(struct mpcg_info *mpcginfo)
/* lower id assume the xside role */
if (our_id < their_id) {
grp->roll = XSIDE;
- ctcm_pr_debug("ctcmpc :%s() WE HAVE LOW ID-"
- "TAKE XSIDE\n", __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_NOTICE,
+ "%s(%s): WE HAVE LOW ID - TAKE XSIDE",
+ CTCM_FUNTAIL, ch->id);
} else {
grp->roll = YSIDE;
- ctcm_pr_debug("ctcmpc :%s() WE HAVE HIGH ID-"
- "TAKE YSIDE\n", __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_NOTICE,
+ "%s(%s): WE HAVE HIGH ID - TAKE YSIDE",
+ CTCM_FUNTAIL, ch->id);
}
} else {
if (xid->xid2_flag4 != grp->saved_xid2->xid2_flag4) {
- failed = 1;
- printk(KERN_INFO "%s XID REJECTED - XID Flag Byte4\n",
- __FUNCTION__);
+ rc = 3;
+ /* XID REJECTED: xid flag byte4 mismatch */
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): xid flag byte4 mismatch",
+ CTCM_FUNTAIL, ch->id);
}
if (xid->xid2_flag2 == 0x40) {
- failed = 1;
- printk(KERN_INFO "%s XID REJECTED - XID NOGOOD\n",
- __FUNCTION__);
+ rc = 4;
+ /* XID REJECTED - xid NOGOOD */
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): xid NOGOOD",
+ CTCM_FUNTAIL, ch->id);
}
if (xid->xid2_adj_id != grp->saved_xid2->xid2_adj_id) {
- failed = 1;
- printk(KERN_INFO "%s XID REJECTED - "
- "Adjacent Station ID Mismatch\n",
- __FUNCTION__);
+ rc = 5;
+ /* XID REJECTED - Adjacent Station ID Mismatch */
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): Adjacent Station ID Mismatch",
+ CTCM_FUNTAIL, ch->id);
}
if (xid->xid2_sender_id != grp->saved_xid2->xid2_sender_id) {
- failed = 1;
- printk(KERN_INFO "%s XID REJECTED - "
- "Sender Address Mismatch\n", __FUNCTION__);
-
+ rc = 6;
+ /* XID REJECTED - Sender Address Mismatch */
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): Sender Address Mismatch",
+ CTCM_FUNTAIL, ch->id);
}
}
- if (failed) {
+done:
+ if (rc) {
ctcm_pr_info("ctcmpc : %s() failed\n", __FUNCTION__);
priv->xid->xid2_flag2 = 0x40;
grp->saved_xid2->xid2_flag2 = 0x40;
- rc = 1;
}
-done:
-
- ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
return rc;
}
@@ -1839,46 +1689,20 @@ done:
static void mpc_action_side_xid(fsm_instance *fsm, void *arg, int side)
{
struct channel *ch = arg;
- struct ctcm_priv *priv;
- struct mpc_group *grp = NULL;
- struct net_device *dev = NULL;
int rc = 0;
int gotlock = 0;
unsigned long saveflags = 0; /* avoids compiler warning with
- spin_unlock_irqrestore */
-
- if (ch == NULL) {
- printk(KERN_INFO "%s ch=NULL\n", __FUNCTION__);
- goto done;
- }
-
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id);
-
- dev = ch->netdev;
- if (dev == NULL) {
- printk(KERN_INFO "%s dev=NULL\n", __FUNCTION__);
- goto done;
- }
-
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_INFO "%s priv=NULL\n", __FUNCTION__);
- goto done;
- }
+ spin_unlock_irqrestore */
- grp = priv->mpcg;
- if (grp == NULL) {
- printk(KERN_INFO "%s grp=NULL\n", __FUNCTION__);
- goto done;
- }
+ CTCM_PR_DEBUG("Enter %s: cp=%i ch=0x%p id=%s\n",
+ __func__, smp_processor_id(), ch, ch->id);
if (ctcm_checkalloc_buffer(ch))
goto done;
- /* skb data-buffer referencing: */
-
+ /*
+ * skb data-buffer referencing:
+ */
ch->trans_skb->data = ch->trans_skb_data;
skb_reset_tail_pointer(ch->trans_skb);
ch->trans_skb->len = 0;
@@ -1911,22 +1735,22 @@ static void mpc_action_side_xid(fsm_instance *fsm, void *arg, int side)
ch->ccw[8].count = 0;
ch->ccw[8].cda = 0x00;
+ if (!(ch->xid_th && ch->xid && ch->xid_id))
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_INFO,
+ "%s(%s): xid_th=%p, xid=%p, xid_id=%p",
+ CTCM_FUNTAIL, ch->id, ch->xid_th, ch->xid, ch->xid_id);
+
if (side == XSIDE) {
/* mpc_action_xside_xid */
- if (ch->xid_th == NULL) {
- printk(KERN_INFO "%s ch->xid_th=NULL\n", __FUNCTION__);
- goto done;
- }
+ if (ch->xid_th == NULL)
+ goto done;
ch->ccw[9].cmd_code = CCW_CMD_WRITE;
ch->ccw[9].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
ch->ccw[9].count = TH_HEADER_LENGTH;
ch->ccw[9].cda = virt_to_phys(ch->xid_th);
- if (ch->xid == NULL) {
- printk(KERN_INFO "%s ch->xid=NULL\n", __FUNCTION__);
- goto done;
- }
-
+ if (ch->xid == NULL)
+ goto done;
ch->ccw[10].cmd_code = CCW_CMD_WRITE;
ch->ccw[10].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
ch->ccw[10].count = XID2_LENGTH;
@@ -1956,28 +1780,22 @@ static void mpc_action_side_xid(fsm_instance *fsm, void *arg, int side)
ch->ccw[10].count = XID2_LENGTH;
ch->ccw[10].cda = virt_to_phys(ch->rcvd_xid);
- if (ch->xid_th == NULL) {
- printk(KERN_INFO "%s ch->xid_th=NULL\n", __FUNCTION__);
- goto done;
- }
+ if (ch->xid_th == NULL)
+ goto done;
ch->ccw[11].cmd_code = CCW_CMD_WRITE;
ch->ccw[11].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
ch->ccw[11].count = TH_HEADER_LENGTH;
ch->ccw[11].cda = virt_to_phys(ch->xid_th);
- if (ch->xid == NULL) {
- printk(KERN_INFO "%s ch->xid=NULL\n", __FUNCTION__);
- goto done;
- }
+ if (ch->xid == NULL)
+ goto done;
ch->ccw[12].cmd_code = CCW_CMD_WRITE;
ch->ccw[12].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
ch->ccw[12].count = XID2_LENGTH;
ch->ccw[12].cda = virt_to_phys(ch->xid);
- if (ch->xid_id == NULL) {
- printk(KERN_INFO "%s ch->xid_id=NULL\n", __FUNCTION__);
- goto done;
- }
+ if (ch->xid_id == NULL)
+ goto done;
ch->ccw[13].cmd_code = CCW_CMD_WRITE;
ch->ccw[13].cda = virt_to_phys(ch->xid_id);
@@ -1990,12 +1808,11 @@ static void mpc_action_side_xid(fsm_instance *fsm, void *arg, int side)
ch->ccw[14].count = 0;
ch->ccw[14].cda = 0;
- if (do_debug_ccw)
- ctcmpc_dumpit((char *)&ch->ccw[8], sizeof(struct ccw1) * 7);
+ CTCM_CCW_DUMP((char *)&ch->ccw[8], sizeof(struct ccw1) * 7);
+ CTCM_D3_DUMP((char *)ch->xid_th, TH_HEADER_LENGTH);
+ CTCM_D3_DUMP((char *)ch->xid, XID2_LENGTH);
+ CTCM_D3_DUMP((char *)ch->xid_id, 4);
- ctcmpc_dumpit((char *)ch->xid_th, TH_HEADER_LENGTH);
- ctcmpc_dumpit((char *)ch->xid, XID2_LENGTH);
- ctcmpc_dumpit((char *)ch->xid_id, 4);
if (!in_irq()) {
/* Such conditional locking is a known problem for
* sparse because its static undeterministic.
@@ -2012,16 +1829,13 @@ static void mpc_action_side_xid(fsm_instance *fsm, void *arg, int side)
spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
if (rc != 0) {
- ctcm_pr_info("ctcmpc: %s() ch:%s IO failed \n",
- __FUNCTION__, ch->id);
ctcm_ccw_check_rc(ch, rc,
(side == XSIDE) ? "x-side XID" : "y-side XID");
}
done:
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
- __FUNCTION__, ch, ch->id);
+ CTCM_PR_DEBUG("Exit %s: ch=0x%p id=%s\n",
+ __func__, ch, ch->id);
return;
}
@@ -2050,41 +1864,19 @@ static void mpc_action_yside_xid(fsm_instance *fsm, int event, void *arg)
*/
static void mpc_action_doxid0(fsm_instance *fsm, int event, void *arg)
{
- struct channel *ch = arg;
- struct ctcm_priv *priv;
- struct mpc_group *grp = NULL;
- struct net_device *dev = NULL;
-
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id);
-
- if (ch == NULL) {
- printk(KERN_WARNING "%s ch=NULL\n", __FUNCTION__);
- goto done;
- }
-
- dev = ch->netdev;
- if (dev == NULL) {
- printk(KERN_WARNING "%s dev=NULL\n", __FUNCTION__);
- goto done;
- }
-
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_WARNING "%s priv=NULL\n", __FUNCTION__);
- goto done;
- }
+ struct channel *ch = arg;
+ struct net_device *dev = ch->netdev;
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = priv->mpcg;
- grp = priv->mpcg;
- if (grp == NULL) {
- printk(KERN_WARNING "%s grp=NULL\n", __FUNCTION__);
- goto done;
- }
+ CTCM_PR_DEBUG("Enter %s: cp=%i ch=0x%p id=%s\n",
+ __func__, smp_processor_id(), ch, ch->id);
if (ch->xid == NULL) {
- printk(KERN_WARNING "%s ch-xid=NULL\n", __FUNCTION__);
- goto done;
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): ch->xid == NULL",
+ CTCM_FUNTAIL, dev->name);
+ return;
}
fsm_newstate(ch->fsm, CH_XID0_INPROGRESS);
@@ -2104,12 +1896,7 @@ static void mpc_action_doxid0(fsm_instance *fsm, int event, void *arg)
fsm_event(grp->fsm, MPCG_EVENT_DOIO, ch);
-done:
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
- __FUNCTION__, ch, ch->id);
return;
-
}
/*
@@ -2119,32 +1906,16 @@ done:
static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg)
{
struct net_device *dev = arg;
- struct ctcm_priv *priv = NULL;
- struct mpc_group *grp = NULL;
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = NULL;
int direction;
- int rc = 0;
int send = 0;
- ctcm_pr_debug("ctcmpc enter: %s() \n", __FUNCTION__);
-
- if (dev == NULL) {
- printk(KERN_INFO "%s dev=NULL \n", __FUNCTION__);
- rc = 1;
- goto done;
- }
-
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_INFO "%s priv=NULL \n", __FUNCTION__);
- rc = 1;
- goto done;
- }
-
- grp = priv->mpcg;
+ if (priv)
+ grp = priv->mpcg;
if (grp == NULL) {
- printk(KERN_INFO "%s grp=NULL \n", __FUNCTION__);
- rc = 1;
- goto done;
+ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+ return;
}
for (direction = READ; direction <= WRITE; direction++) {
@@ -2199,11 +1970,6 @@ static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg)
fsm_event(grp->fsm, MPCG_EVENT_DOIO, ch);
}
-done:
-
- if (rc != 0)
- fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
-
return;
}
@@ -2214,24 +1980,15 @@ done:
static void mpc_action_rcvd_xid0(fsm_instance *fsm, int event, void *arg)
{
- struct mpcg_info *mpcginfo = arg;
- struct channel *ch = mpcginfo->ch;
- struct net_device *dev = ch->netdev;
- struct ctcm_priv *priv;
- struct mpc_group *grp;
-
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id);
-
- priv = dev->priv;
- grp = priv->mpcg;
+ struct mpcg_info *mpcginfo = arg;
+ struct channel *ch = mpcginfo->ch;
+ struct net_device *dev = ch->netdev;
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = priv->mpcg;
- ctcm_pr_debug("ctcmpc in:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
- __FUNCTION__, ch->id,
- grp->outstanding_xid2,
- grp->outstanding_xid7,
- grp->outstanding_xid7_p2);
+ CTCM_PR_DEBUG("%s: ch-id:%s xid2:%i xid7:%i xidt_p2:%i \n",
+ __func__, ch->id, grp->outstanding_xid2,
+ grp->outstanding_xid7, grp->outstanding_xid7_p2);
if (fsm_getstate(ch->fsm) < CH_XID7_PENDING)
fsm_newstate(ch->fsm, CH_XID7_PENDING);
@@ -2268,17 +2025,12 @@ static void mpc_action_rcvd_xid0(fsm_instance *fsm, int event, void *arg)
}
kfree(mpcginfo);
- if (do_debug) {
- ctcm_pr_debug("ctcmpc:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
- __FUNCTION__, ch->id,
- grp->outstanding_xid2,
- grp->outstanding_xid7,
- grp->outstanding_xid7_p2);
- ctcm_pr_debug("ctcmpc:%s() %s grpstate: %s chanstate: %s \n",
- __FUNCTION__, ch->id,
- fsm_getstate_str(grp->fsm),
- fsm_getstate_str(ch->fsm));
- }
+ CTCM_PR_DEBUG("ctcmpc:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
+ __func__, ch->id, grp->outstanding_xid2,
+ grp->outstanding_xid7, grp->outstanding_xid7_p2);
+ CTCM_PR_DEBUG("ctcmpc:%s() %s grpstate: %s chanstate: %s \n",
+ __func__, ch->id,
+ fsm_getstate_str(grp->fsm), fsm_getstate_str(ch->fsm));
return;
}
@@ -2296,15 +2048,10 @@ static void mpc_action_rcvd_xid7(fsm_instance *fsm, int event, void *arg)
struct ctcm_priv *priv = dev->priv;
struct mpc_group *grp = priv->mpcg;
- if (do_debug) {
- ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id);
-
- ctcm_pr_debug("ctcmpc: outstanding_xid7: %i, "
- " outstanding_xid7_p2: %i\n",
- grp->outstanding_xid7,
- grp->outstanding_xid7_p2);
- }
+ CTCM_PR_DEBUG("Enter %s: cp=%i ch=0x%p id=%s\n",
+ __func__, smp_processor_id(), ch, ch->id);
+ CTCM_PR_DEBUG("%s: outstanding_xid7: %i, outstanding_xid7_p2: %i\n",
+ __func__, grp->outstanding_xid7, grp->outstanding_xid7_p2);
grp->outstanding_xid7--;
ch->xid_skb->data = ch->xid_skb_data;
@@ -2337,14 +2084,8 @@ static void mpc_action_rcvd_xid7(fsm_instance *fsm, int event, void *arg)
mpc_validate_xid(mpcginfo);
break;
}
-
kfree(mpcginfo);
-
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit: %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id);
return;
-
}
/*
@@ -2353,36 +2094,14 @@ static void mpc_action_rcvd_xid7(fsm_instance *fsm, int event, void *arg)
*/
static int mpc_send_qllc_discontact(struct net_device *dev)
{
- int rc = 0;
__u32 new_len = 0;
struct sk_buff *skb;
struct qllc *qllcptr;
- struct ctcm_priv *priv;
- struct mpc_group *grp;
-
- ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
-
- if (dev == NULL) {
- printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
- rc = 1;
- goto done;
- }
-
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
- rc = 1;
- goto done;
- }
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = priv->mpcg;
- grp = priv->mpcg;
- if (grp == NULL) {
- printk(KERN_INFO "%s() grp=NULL\n", __FUNCTION__);
- rc = 1;
- goto done;
- }
- ctcm_pr_info("ctcmpc: %s() GROUP STATE: %s\n", __FUNCTION__,
- mpcg_state_names[grp->saved_state]);
+ CTCM_PR_DEBUG("%s: GROUP STATE: %s\n",
+ __func__, mpcg_state_names[grp->saved_state]);
switch (grp->saved_state) {
/*
@@ -2408,11 +2127,10 @@ static int mpc_send_qllc_discontact(struct net_device *dev)
new_len = sizeof(struct qllc);
qllcptr = kzalloc(new_len, gfp_type() | GFP_DMA);
if (qllcptr == NULL) {
- printk(KERN_INFO
- "ctcmpc: Out of memory in %s()\n",
- dev->name);
- rc = 1;
- goto done;
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): qllcptr allocation error",
+ CTCM_FUNTAIL, dev->name);
+ return -ENOMEM;
}
qllcptr->qllc_address = 0xcc;
@@ -2421,31 +2139,29 @@ static int mpc_send_qllc_discontact(struct net_device *dev)
skb = __dev_alloc_skb(new_len, GFP_ATOMIC);
if (skb == NULL) {
- printk(KERN_INFO "%s Out of memory in mpc_send_qllc\n",
- dev->name);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): skb allocation error",
+ CTCM_FUNTAIL, dev->name);
priv->stats.rx_dropped++;
- rc = 1;
kfree(qllcptr);
- goto done;
+ return -ENOMEM;
}
memcpy(skb_put(skb, new_len), qllcptr, new_len);
kfree(qllcptr);
if (skb_headroom(skb) < 4) {
- printk(KERN_INFO "ctcmpc: %s() Unable to"
- " build discontact for %s\n",
- __FUNCTION__, dev->name);
- rc = 1;
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): skb_headroom error",
+ CTCM_FUNTAIL, dev->name);
dev_kfree_skb_any(skb);
- goto done;
+ return -ENOMEM;
}
*((__u32 *)skb_push(skb, 4)) = priv->channel[READ]->pdu_seq;
priv->channel[READ]->pdu_seq++;
- if (do_debug_data)
- ctcm_pr_debug("ctcmpc: %s ToDCM_pdu_seq= %08x\n",
- __FUNCTION__, priv->channel[READ]->pdu_seq);
+ CTCM_PR_DBGDATA("ctcmpc: %s ToDCM_pdu_seq= %08x\n",
+ __func__, priv->channel[READ]->pdu_seq);
/* receipt of CC03 resets anticipated sequence number on
receiving side */
@@ -2455,7 +2171,7 @@ static int mpc_send_qllc_discontact(struct net_device *dev)
skb->protocol = htons(ETH_P_SNAP);
skb->ip_summed = CHECKSUM_UNNECESSARY;
- ctcmpc_dumpit((char *)skb->data, (sizeof(struct qllc) + 4));
+ CTCM_D3_DUMP(skb->data, (sizeof(struct qllc) + 4));
netif_rx(skb);
break;
@@ -2464,9 +2180,7 @@ static int mpc_send_qllc_discontact(struct net_device *dev)
}
-done:
- ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
- return rc;
+ return 0;
}
/* --- This is the END my friend --- */
diff --git a/drivers/s390/net/ctcm_mpc.h b/drivers/s390/net/ctcm_mpc.h
index f99686069a9..5336120cddf 100644
--- a/drivers/s390/net/ctcm_mpc.h
+++ b/drivers/s390/net/ctcm_mpc.h
@@ -231,7 +231,7 @@ static inline void ctcmpc_dump32(char *buf, int len)
int ctcmpc_open(struct net_device *);
void ctcm_ccw_check_rc(struct channel *, int, char *);
void mpc_group_ready(unsigned long adev);
-int mpc_channel_action(struct channel *ch, int direction, int action);
+void mpc_channel_action(struct channel *ch, int direction, int action);
void mpc_action_send_discontact(unsigned long thischan);
void mpc_action_discontact(fsm_instance *fi, int event, void *arg);
void ctcmpc_bh(unsigned long thischan);
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index b29afef5c7f..38de31b5570 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2651,7 +2651,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
tag = (u16 *)(new_skb->data + 12);
*tag = __constant_htons(ETH_P_8021Q);
*(tag + 1) = htons(vlan_tx_tag_get(new_skb));
- VLAN_TX_SKB_CB(new_skb)->magic = 0;
+ new_skb->vlan_tci = 0;
}
}
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
index c37d7c2587f..73a86d09bba 100644
--- a/drivers/sbus/sbus.c
+++ b/drivers/sbus/sbus.c
@@ -78,7 +78,7 @@ static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sde
else
sdev->ofdev.dev.parent = &sdev->bus->ofdev.dev;
sdev->ofdev.dev.bus = &sbus_bus_type;
- sprintf(sdev->ofdev.dev.bus_id, "sbus[%08x]", dp->node);
+ dev_set_name(&sdev->ofdev.dev, "sbus[%08x]", dp->node);
if (of_device_register(&sdev->ofdev) != 0)
printk(KERN_DEBUG "sbus: device registration error for %s!\n",
@@ -257,11 +257,11 @@ 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;
- sprintf(sbus->ofdev.dev.bus_id, "sbus%d", num_sbus);
+ dev_set_name(&sbus->ofdev.dev, "sbus%d", num_sbus);
if (of_device_register(&sbus->ofdev) != 0)
printk(KERN_DEBUG "sbus: device registration error for %s!\n",
- sbus->ofdev.dev.bus_id);
+ dev_name(&sbus->ofdev.dev));
dev_dp = dp->child;
while (dev_dp) {
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 2bc30e32b67..1fe0901e811 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -271,8 +271,8 @@ rebuild_sys_tab:
pHba->initialized = TRUE;
pHba->state &= ~DPTI_STATE_RESET;
if (adpt_sysfs_class) {
- struct device *dev = device_create(adpt_sysfs_class,
- NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit),
+ struct device *dev = device_create_drvdata(adpt_sysfs_class,
+ NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit), NULL,
"dpti%d", pHba->unit);
if (IS_ERR(dev)) {
printk(KERN_WARNING"dpti%d: unable to "
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 35cd892dce0..fed0b02ebc1 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -232,8 +232,8 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
}
if (shost->transportt->create_work_queue) {
- snprintf(shost->work_q_name, KOBJ_NAME_LEN, "scsi_wq_%d",
- shost->host_no);
+ snprintf(shost->work_q_name, sizeof(shost->work_q_name),
+ "scsi_wq_%d", shost->host_no);
shost->work_q = create_singlethread_workqueue(
shost->work_q_name);
if (!shost->work_q) {
@@ -466,7 +466,8 @@ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum)
struct device *cdev;
struct Scsi_Host *shost = ERR_PTR(-ENXIO);
- cdev = class_find_device(&shost_class, &hostnum, __scsi_host_match);
+ cdev = class_find_device(&shost_class, NULL, &hostnum,
+ __scsi_host_match);
if (cdev) {
shost = scsi_host_get(class_to_shost(cdev));
put_device(cdev);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index eb702b96d57..c4a7c06793c 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -3819,6 +3819,20 @@ static int ibmvfc_remove(struct vio_dev *vdev)
return 0;
}
+/**
+ * ibmvfc_get_desired_dma - Calculate DMA resources needed by the driver
+ * @vdev: vio device struct
+ *
+ * Return value:
+ * Number of bytes the driver will need to DMA map at the same time in
+ * order to perform well.
+ */
+static unsigned long ibmvfc_get_desired_dma(struct vio_dev *vdev)
+{
+ unsigned long pool_dma = max_requests * sizeof(union ibmvfc_iu);
+ return pool_dma + ((512 * 1024) * driver_template.cmd_per_lun);
+}
+
static struct vio_device_id ibmvfc_device_table[] __devinitdata = {
{"fcp", "IBM,vfc-client"},
{ "", "" }
@@ -3829,6 +3843,7 @@ static struct vio_driver ibmvfc_driver = {
.id_table = ibmvfc_device_table,
.probe = ibmvfc_probe,
.remove = ibmvfc_remove,
+ .get_desired_dma = ibmvfc_get_desired_dma,
.driver = {
.name = IBMVFC_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 5d23368a1bc..20000ec79b0 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -72,6 +72,7 @@
#include <linux/delay.h>
#include <asm/firmware.h>
#include <asm/vio.h>
+#include <asm/firmware.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h>
@@ -426,8 +427,10 @@ static int map_sg_data(struct scsi_cmnd *cmd,
SG_ALL * sizeof(struct srp_direct_buf),
&evt_struct->ext_list_token, 0);
if (!evt_struct->ext_list) {
- sdev_printk(KERN_ERR, cmd->device,
- "Can't allocate memory for indirect table\n");
+ if (!firmware_has_feature(FW_FEATURE_CMO))
+ sdev_printk(KERN_ERR, cmd->device,
+ "Can't allocate memory "
+ "for indirect table\n");
return 0;
}
}
@@ -743,7 +746,9 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
srp_cmd->lun = ((u64) lun) << 48;
if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
- sdev_printk(KERN_ERR, cmnd->device, "couldn't convert cmd to srp_cmd\n");
+ if (!firmware_has_feature(FW_FEATURE_CMO))
+ sdev_printk(KERN_ERR, cmnd->device,
+ "couldn't convert cmd to srp_cmd\n");
free_event_struct(&hostdata->pool, evt_struct);
return SCSI_MLQUEUE_HOST_BUSY;
}
@@ -855,7 +860,10 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
DMA_BIDIRECTIONAL);
if (dma_mapping_error(req->buffer)) {
- dev_err(hostdata->dev, "Unable to map request_buffer for adapter_info!\n");
+ if (!firmware_has_feature(FW_FEATURE_CMO))
+ dev_err(hostdata->dev,
+ "Unable to map request_buffer for "
+ "adapter_info!\n");
free_event_struct(&hostdata->pool, evt_struct);
return;
}
@@ -1400,7 +1408,9 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
DMA_BIDIRECTIONAL);
if (dma_mapping_error(host_config->buffer)) {
- dev_err(hostdata->dev, "dma_mapping error getting host config\n");
+ if (!firmware_has_feature(FW_FEATURE_CMO))
+ dev_err(hostdata->dev,
+ "dma_mapping error getting host config\n");
free_event_struct(&hostdata->pool, evt_struct);
return -1;
}
@@ -1604,7 +1614,7 @@ static struct scsi_host_template driver_template = {
.eh_host_reset_handler = ibmvscsi_eh_host_reset_handler,
.slave_configure = ibmvscsi_slave_configure,
.change_queue_depth = ibmvscsi_change_queue_depth,
- .cmd_per_lun = 16,
+ .cmd_per_lun = IBMVSCSI_CMDS_PER_LUN_DEFAULT,
.can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT,
.this_id = -1,
.sg_tablesize = SG_ALL,
@@ -1613,6 +1623,26 @@ static struct scsi_host_template driver_template = {
};
/**
+ * ibmvscsi_get_desired_dma - Calculate IO memory desired by the driver
+ *
+ * @vdev: struct vio_dev for the device whose desired IO mem is to be returned
+ *
+ * Return value:
+ * Number of bytes of IO data the driver will need to perform well.
+ */
+static unsigned long ibmvscsi_get_desired_dma(struct vio_dev *vdev)
+{
+ /* iu_storage data allocated in initialize_event_pool */
+ unsigned long desired_io = max_requests * sizeof(union viosrp_iu);
+
+ /* add io space for sg data */
+ desired_io += (IBMVSCSI_MAX_SECTORS_DEFAULT *
+ IBMVSCSI_CMDS_PER_LUN_DEFAULT);
+
+ return desired_io;
+}
+
+/**
* Called by bus code for each adapter
*/
static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
@@ -1641,7 +1671,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
hostdata->host = host;
hostdata->dev = dev;
atomic_set(&hostdata->request_limit, -1);
- hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */
+ hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT;
rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests);
if (rc != 0 && rc != H_RESOURCE) {
@@ -1735,6 +1765,7 @@ static struct vio_driver ibmvscsi_driver = {
.id_table = ibmvscsi_device_table,
.probe = ibmvscsi_probe,
.remove = ibmvscsi_remove,
+ .get_desired_dma = ibmvscsi_get_desired_dma,
.driver = {
.name = "ibmvscsi",
.owner = THIS_MODULE,
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 46e850e302c..2d4339d5e16 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -45,6 +45,8 @@ struct Scsi_Host;
#define MAX_INDIRECT_BUFS 10
#define IBMVSCSI_MAX_REQUESTS_DEFAULT 100
+#define IBMVSCSI_CMDS_PER_LUN_DEFAULT 16
+#define IBMVSCSI_MAX_SECTORS_DEFAULT 256 /* 32 * 8 = default max I/O 32 pages */
#define IBMVSCSI_MAX_CMDS_PER_LUN 64
/* ------------------------------------------------------------
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index f843c1383a4..b40a673985a 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -84,7 +84,6 @@ typedef struct ide_scsi_obj {
struct Scsi_Host *host;
struct ide_atapi_pc *pc; /* Current packet command */
- unsigned long flags; /* Status/Action flags */
unsigned long transform; /* SCSI cmd translation layer */
unsigned long log; /* log flags */
} idescsi_scsi_t;
@@ -102,8 +101,13 @@ static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk)
mutex_lock(&idescsi_ref_mutex);
scsi = ide_scsi_g(disk);
- if (scsi)
+ if (scsi) {
scsi_host_get(scsi->host);
+ if (ide_device_get(scsi->drive)) {
+ scsi_host_put(scsi->host);
+ scsi = NULL;
+ }
+ }
mutex_unlock(&idescsi_ref_mutex);
return scsi;
}
@@ -111,6 +115,7 @@ static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk)
static void ide_scsi_put(struct ide_scsi_obj *scsi)
{
mutex_lock(&idescsi_ref_mutex);
+ ide_device_put(scsi->drive);
scsi_host_put(scsi->host);
mutex_unlock(&idescsi_ref_mutex);
}
@@ -126,23 +131,14 @@ static inline idescsi_scsi_t *drive_to_idescsi(ide_drive_t *ide_drive)
}
/*
- * Per ATAPI device status bits.
- */
-#define IDESCSI_DRQ_INTERRUPT 0 /* DRQ interrupt device */
-
-/*
- * ide-scsi requests.
- */
-#define IDESCSI_PC_RQ 90
-
-/*
* PIO data transfer routine using the scatter gather table.
*/
static void ide_scsi_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
unsigned int bcount, int write)
{
ide_hwif_t *hwif = drive->hwif;
- xfer_func_t *xf = write ? hwif->output_data : hwif->input_data;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+ xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data;
char *buf;
int count;
@@ -211,15 +207,15 @@ static int idescsi_check_condition(ide_drive_t *drive,
/* stuff a sense request in front of our current request */
pc = kzalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);
- rq = kmalloc(sizeof(struct request), GFP_ATOMIC);
+ rq = blk_get_request(drive->queue, READ, GFP_ATOMIC);
buf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC);
if (!pc || !rq || !buf) {
kfree(buf);
- kfree(rq);
+ if (rq)
+ blk_put_request(rq);
kfree(pc);
return -ENOMEM;
}
- blk_rq_init(NULL, rq);
rq->special = (char *) pc;
pc->rq = rq;
pc->buf = buf;
@@ -228,7 +224,6 @@ static int idescsi_check_condition(ide_drive_t *drive,
rq->cmd_type = REQ_TYPE_SENSE;
rq->cmd_flags |= REQ_PREEMPT;
pc->timeout = jiffies + WAIT_READY;
- pc->callback = ide_scsi_callback;
/* NOTE! Save the failed packet command in "rq->buffer" */
rq->buffer = (void *) failed_cmd->special;
pc->scsi_cmd = ((struct ide_atapi_pc *) failed_cmd->special)->scsi_cmd;
@@ -237,6 +232,8 @@ static int idescsi_check_condition(ide_drive_t *drive,
ide_scsi_hex_dump(pc->c, 6);
}
rq->rq_disk = scsi->disk;
+ rq->ref_count++;
+ memcpy(rq->cmd, pc->c, 12);
ide_do_drive_cmd(drive, rq);
return 0;
}
@@ -246,10 +243,9 @@ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
{
ide_hwif_t *hwif = drive->hwif;
- if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
/* force an abort */
- hwif->OUTBSYNC(hwif, WIN_IDLEIMMEDIATE,
- hwif->io_ports.command_addr);
+ hwif->tp_ops->exec_command(hwif, WIN_IDLEIMMEDIATE);
rq->errors++;
@@ -283,7 +279,7 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
SCSI_SENSE_BUFFERSIZE);
kfree(pc->buf);
kfree(pc);
- kfree(rq);
+ blk_put_request(rq);
pc = opc;
rq = pc->rq;
pc->scsi_cmd->result = (CHECK_CONDITION << 1) |
@@ -314,7 +310,7 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
pc->done(pc->scsi_cmd);
spin_unlock_irqrestore(host->host_lock, flags);
kfree(pc);
- kfree(rq);
+ blk_put_request(rq);
scsi->pc = NULL;
return 0;
}
@@ -421,10 +417,6 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r
if (blk_sense_request(rq) || blk_special_request(rq)) {
struct ide_atapi_pc *pc = (struct ide_atapi_pc *)rq->special;
- idescsi_scsi_t *scsi = drive_to_idescsi(drive);
-
- if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags))
- pc->flags |= PC_FLAG_DRQ_INTERRUPT;
if (drive->using_dma && !idescsi_map_sg(drive, pc))
pc->flags |= PC_FLAG_DMA_OK;
@@ -460,11 +452,14 @@ static inline void idescsi_add_settings(ide_drive_t *drive) { ; }
static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
{
if (drive->id && (drive->id->config & 0x0060) == 0x20)
- set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
+ set_bit(IDE_AFLAG_DRQ_INTERRUPT, &drive->atapi_flags);
clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
#if IDESCSI_DEBUG_LOG
set_bit(IDESCSI_LOG_CMD, &scsi->log);
#endif /* IDESCSI_DEBUG_LOG */
+
+ drive->pc_callback = ide_scsi_callback;
+
idescsi_add_settings(drive);
}
@@ -589,6 +584,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
ide_drive_t *drive = scsi->drive;
struct request *rq = NULL;
struct ide_atapi_pc *pc = NULL;
+ int write = cmd->sc_data_direction == DMA_TO_DEVICE;
if (!drive) {
scmd_printk (KERN_ERR, cmd, "drive not present\n");
@@ -596,7 +592,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
}
scsi = drive_to_idescsi(drive);
pc = kmalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);
- rq = kmalloc(sizeof(struct request), GFP_ATOMIC);
+ rq = blk_get_request(drive->queue, write, GFP_ATOMIC);
if (rq == NULL || pc == NULL) {
printk (KERN_ERR "ide-scsi: %s: out of memory\n", drive->name);
goto abort;
@@ -616,7 +612,6 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
pc->scsi_cmd = cmd;
pc->done = done;
pc->timeout = jiffies + cmd->timeout_per_command;
- pc->callback = ide_scsi_callback;
if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);
@@ -627,16 +622,18 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
}
}
- blk_rq_init(NULL, rq);
rq->special = (char *) pc;
rq->cmd_type = REQ_TYPE_SPECIAL;
spin_unlock_irq(host->host_lock);
+ rq->ref_count++;
+ memcpy(rq->cmd, pc->c, 12);
blk_execute_rq_nowait(drive->queue, scsi->disk, rq, 0, NULL);
spin_lock_irq(host->host_lock);
return 0;
abort:
kfree (pc);
- kfree (rq);
+ if (rq)
+ blk_put_request(rq);
cmd->result = DID_ERROR << 16;
done(cmd);
return 0;
@@ -684,7 +681,9 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
if (blk_sense_request(scsi->pc->rq))
kfree(scsi->pc->buf);
- kfree(scsi->pc->rq);
+ /* we need to call blk_put_request twice. */
+ blk_put_request(scsi->pc->rq);
+ blk_put_request(scsi->pc->rq);
kfree(scsi->pc);
scsi->pc = NULL;
@@ -736,7 +735,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
kfree(scsi->pc->buf);
kfree(scsi->pc);
scsi->pc = NULL;
- kfree(req);
+ blk_put_request(req);
/* now nuke the drive queue */
while ((req = elv_next_request(drive->queue))) {
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 5fd64e70029..a272b9a2c86 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -417,15 +417,16 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
fc_host->next_vport_number = 0;
fc_host->npiv_vports_inuse = 0;
- snprintf(fc_host->work_q_name, KOBJ_NAME_LEN, "fc_wq_%d",
- shost->host_no);
+ snprintf(fc_host->work_q_name, sizeof(fc_host->work_q_name),
+ "fc_wq_%d", shost->host_no);
fc_host->work_q = create_singlethread_workqueue(
fc_host->work_q_name);
if (!fc_host->work_q)
return -ENOMEM;
- snprintf(fc_host->devloss_work_q_name, KOBJ_NAME_LEN, "fc_dl_%d",
- shost->host_no);
+ snprintf(fc_host->devloss_work_q_name,
+ sizeof(fc_host->devloss_work_q_name),
+ "fc_dl_%d", shost->host_no);
fc_host->devloss_work_q = create_singlethread_workqueue(
fc_host->devloss_work_q_name);
if (!fc_host->devloss_work_q) {
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 3af7cbcc5c5..043c3921164 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -170,7 +170,7 @@ iscsi_create_endpoint(int dd_size)
int err;
for (id = 1; id < ISCSI_MAX_EPID; id++) {
- dev = class_find_device(&iscsi_endpoint_class, &id,
+ dev = class_find_device(&iscsi_endpoint_class, NULL, &id,
iscsi_match_epid);
if (!dev)
break;
@@ -222,7 +222,7 @@ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
struct iscsi_endpoint *ep;
struct device *dev;
- dev = class_find_device(&iscsi_endpoint_class, &handle,
+ dev = class_find_device(&iscsi_endpoint_class, NULL, &handle,
iscsi_match_epid);
if (!dev)
return NULL;
@@ -247,8 +247,8 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
atomic_set(&ihost->nr_scans, 0);
mutex_init(&ihost->mutex);
- snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d",
- shost->host_no);
+ snprintf(ihost->scan_workq_name, sizeof(ihost->scan_workq_name),
+ "iscsi_scan_%d", shost->host_no);
ihost->scan_workq = create_singlethread_workqueue(
ihost->scan_workq_name);
if (!ihost->scan_workq)
diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c
index 2c87db98cdf..f9cf7015136 100644
--- a/drivers/scsi/sun_esp.c
+++ b/drivers/scsi/sun_esp.c
@@ -7,6 +7,7 @@
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/mm.h>
#include <linux/init.h>
#include <asm/irq.h>
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index ce948b66bbd..a97f1ae11f7 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -1293,7 +1293,18 @@ receive_chars(struct uart_8250_port *up, unsigned int *status)
char flag;
do {
- ch = serial_inp(up, UART_RX);
+ if (likely(lsr & UART_LSR_DR))
+ ch = serial_inp(up, UART_RX);
+ else
+ /*
+ * Intel 82571 has a Serial Over Lan device that will
+ * set UART_LSR_BI without setting UART_LSR_DR when
+ * it receives a break. To avoid reading from the
+ * receive buffer without UART_LSR_DR bit set, we
+ * just force the read character to be 0
+ */
+ ch = 0;
+
flag = TTY_NORMAL;
up->port.icount.rx++;
@@ -1342,7 +1353,7 @@ receive_chars(struct uart_8250_port *up, unsigned int *status)
ignore_char:
lsr = serial_inp(up, UART_LSR);
- } while ((lsr & UART_LSR_DR) && (max_count-- > 0));
+ } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
spin_unlock(&up->port.lock);
tty_flip_buffer_push(tty);
spin_lock(&up->port.lock);
@@ -1425,7 +1436,7 @@ serial8250_handle_port(struct uart_8250_port *up)
DEBUG_INTR("status = %x...", status);
- if (status & UART_LSR_DR)
+ if (status & (UART_LSR_DR | UART_LSR_BI))
receive_chars(up, &status);
check_modem_status(up);
if (status & UART_LSR_THRE)
@@ -1874,7 +1885,9 @@ static int serial8250_startup(struct uart_port *port)
* the interrupt is enabled. Delays are necessary to
* allow register changes to become visible.
*/
- spin_lock_irqsave(&up->port.lock, flags);
+ spin_lock(&up->port.lock);
+ if (up->port.flags & UPF_SHARE_IRQ)
+ disable_irq_nosync(up->port.irq);
wait_for_xmitr(up, UART_LSR_THRE);
serial_out_sync(up, UART_IER, UART_IER_THRI);
@@ -1886,7 +1899,9 @@ static int serial8250_startup(struct uart_port *port)
iir = serial_in(up, UART_IIR);
serial_out(up, UART_IER, 0);
- spin_unlock_irqrestore(&up->port.lock, flags);
+ if (up->port.flags & UPF_SHARE_IRQ)
+ enable_irq(up->port.irq);
+ spin_unlock(&up->port.lock);
/*
* If the interrupt is not reasserted, setup a timer to
diff --git a/drivers/serial/8250_gsc.c b/drivers/serial/8250_gsc.c
index 4eb7437a404..0416ad3bc12 100644
--- a/drivers/serial/8250_gsc.c
+++ b/drivers/serial/8250_gsc.c
@@ -119,3 +119,5 @@ int __init probe_serial_gsc(void)
}
module_init(probe_serial_gsc);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 1b36087665a..c2f23933155 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -767,6 +767,9 @@ pci_default_setup(struct serial_private *priv, struct pciserial_board *board,
#define PCI_SUBDEVICE_ID_POCTAL232 0x0308
#define PCI_SUBDEVICE_ID_POCTAL422 0x0408
+/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
+#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
+
/*
* Master list of serial port init/setup/exit quirks.
* This does not describe the general nature of the port.
@@ -882,6 +885,15 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
},
{
.vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9050,
+ .subvendor = PCI_VENDOR_ID_PLX,
+ .subdevice = PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
+ .init = pci_plx9050_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_plx9050_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
.device = PCI_DEVICE_ID_PLX_ROMULUS,
.subvendor = PCI_VENDOR_ID_PLX,
.subdevice = PCI_DEVICE_ID_PLX_ROMULUS,
@@ -2197,6 +2209,11 @@ static struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b2_4_921600 },
+ /* Unknown card - subdevice 0x1584 */
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_VENDOR_ID_PLX,
+ PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0,
+ pbn_b0_4_115200 },
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
PCI_SUBVENDOR_ID_KEYSPAN,
PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 8fc7451c004..3b4a14e355c 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -942,22 +942,6 @@ config SERIAL_IP22_ZILOG_CONSOLE
depends on SERIAL_IP22_ZILOG=y
select SERIAL_CORE_CONSOLE
-config V850E_UART
- bool "NEC V850E on-chip UART support"
- depends on V850E_MA1 || V850E_ME2 || V850E_TEG || V850E2_ANNA || V850E_AS85EP1
- select SERIAL_CORE
- default y
-
-config V850E_UARTB
- bool
- depends on V850E_UART && V850E_ME2
- default y
-
-config V850E_UART_CONSOLE
- bool "Use NEC V850E on-chip UART for console"
- depends on V850E_UART
- select SERIAL_CORE_CONSOLE
-
config SERIAL_SH_SCI
tristate "SuperH SCI(F) serial port support"
depends on SUPERH || H8300
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index abe129cc927..a4f86927a74 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -201,6 +201,10 @@ static void cpm_uart_int_tx(struct uart_port *port)
cpm_uart_tx_pump(port);
}
+#ifdef CONFIG_CONSOLE_POLL
+static int serial_polled;
+#endif
+
/*
* Receive characters
*/
@@ -209,7 +213,7 @@ static void cpm_uart_int_rx(struct uart_port *port)
int i;
unsigned char ch;
u8 *cp;
- struct tty_struct *tty = port->info->tty;
+ struct tty_struct *tty = port->info->port.tty;
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
cbd_t __iomem *bdp;
u16 status;
@@ -222,6 +226,12 @@ static void cpm_uart_int_rx(struct uart_port *port)
*/
bdp = pinfo->rx_cur;
for (;;) {
+#ifdef CONFIG_CONSOLE_POLL
+ if (unlikely(serial_polled)) {
+ serial_polled = 0;
+ return;
+ }
+#endif
/* get status */
status = in_be16(&bdp->cbd_sc);
/* If this one is empty, return happy */
@@ -253,7 +263,12 @@ static void cpm_uart_int_rx(struct uart_port *port)
goto handle_error;
if (uart_handle_sysrq_char(port, ch))
continue;
-
+#ifdef CONFIG_CONSOLE_POLL
+ if (unlikely(serial_polled)) {
+ serial_polled = 0;
+ return;
+ }
+#endif
error_return:
tty_insert_flip_char(tty, ch, flg);
@@ -420,10 +435,13 @@ static void cpm_uart_shutdown(struct uart_port *port)
}
/* Shut them really down and reinit buffer descriptors */
- if (IS_SMC(pinfo))
+ if (IS_SMC(pinfo)) {
+ out_be16(&pinfo->smcup->smc_brkcr, 0);
cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
- else
+ } else {
+ out_be16(&pinfo->sccup->scc_brkcr, 0);
cpm_line_cr_cmd(pinfo, CPM_CR_GRA_STOP_TX);
+ }
cpm_uart_initbd(pinfo);
}
@@ -539,9 +557,11 @@ static void cpm_uart_set_termios(struct uart_port *port,
* enables, because we want to put them back if they were
* present.
*/
- prev_mode = in_be16(&smcp->smc_smcmr);
- out_be16(&smcp->smc_smcmr, smcr_mk_clen(bits) | cval | SMCMR_SM_UART);
- setbits16(&smcp->smc_smcmr, (prev_mode & (SMCMR_REN | SMCMR_TEN)));
+ prev_mode = in_be16(&smcp->smc_smcmr) & (SMCMR_REN | SMCMR_TEN);
+ /* Output in *one* operation, so we don't interrupt RX/TX if they
+ * were already enabled. */
+ out_be16(&smcp->smc_smcmr, smcr_mk_clen(bits) | cval |
+ SMCMR_SM_UART | prev_mode);
} else {
out_be16(&sccp->scc_psmr, (sbits << 12) | scval);
}
@@ -865,6 +885,80 @@ static void cpm_uart_config_port(struct uart_port *port, int flags)
cpm_uart_request_port(port);
}
}
+
+#ifdef CONFIG_CONSOLE_POLL
+/* Serial polling routines for writing and reading from the uart while
+ * in an interrupt or debug context.
+ */
+
+#define GDB_BUF_SIZE 512 /* power of 2, please */
+
+static char poll_buf[GDB_BUF_SIZE];
+static char *pollp;
+static int poll_chars;
+
+static int poll_wait_key(char *obuf, struct uart_cpm_port *pinfo)
+{
+ u_char c, *cp;
+ volatile cbd_t *bdp;
+ int i;
+
+ /* Get the address of the host memory buffer.
+ */
+ bdp = pinfo->rx_cur;
+ while (bdp->cbd_sc & BD_SC_EMPTY)
+ ;
+
+ /* If the buffer address is in the CPM DPRAM, don't
+ * convert it.
+ */
+ cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
+
+ if (obuf) {
+ i = c = bdp->cbd_datlen;
+ while (i-- > 0)
+ *obuf++ = *cp++;
+ } else
+ c = *cp;
+ bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID);
+ bdp->cbd_sc |= BD_SC_EMPTY;
+
+ if (bdp->cbd_sc & BD_SC_WRAP)
+ bdp = pinfo->rx_bd_base;
+ else
+ bdp++;
+ pinfo->rx_cur = (cbd_t *)bdp;
+
+ return (int)c;
+}
+
+static int cpm_get_poll_char(struct uart_port *port)
+{
+ struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+
+ if (!serial_polled) {
+ serial_polled = 1;
+ poll_chars = 0;
+ }
+ if (poll_chars <= 0) {
+ poll_chars = poll_wait_key(poll_buf, pinfo);
+ pollp = poll_buf;
+ }
+ poll_chars--;
+ return *pollp++;
+}
+
+static void cpm_put_poll_char(struct uart_port *port,
+ unsigned char c)
+{
+ struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+ static char ch[2];
+
+ ch[0] = (char)c;
+ cpm_uart_early_write(pinfo->port.line, ch, 1);
+}
+#endif /* CONFIG_CONSOLE_POLL */
+
static struct uart_ops cpm_uart_pops = {
.tx_empty = cpm_uart_tx_empty,
.set_mctrl = cpm_uart_set_mctrl,
@@ -882,6 +976,10 @@ static struct uart_ops cpm_uart_pops = {
.request_port = cpm_uart_request_port,
.config_port = cpm_uart_config_port,
.verify_port = cpm_uart_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+ .poll_get_char = cpm_get_poll_char,
+ .poll_put_char = cpm_put_poll_char,
+#endif
};
struct uart_cpm_port cpm_uart_ports[UART_NR];
@@ -1105,12 +1203,14 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
udbg_putc = NULL;
#endif
- cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
-
if (IS_SMC(pinfo)) {
+ out_be16(&pinfo->smcup->smc_brkcr, 0);
+ cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX | SMCM_TX);
clrbits16(&pinfo->smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
} else {
+ out_be16(&pinfo->sccup->scc_brkcr, 0);
+ cpm_line_cr_cmd(pinfo, CPM_CR_GRA_STOP_TX);
clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
}
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index a81d2c2ff8a..6042b87797a 100644
--- a/drivers/serial/dz.c
+++ b/drivers/serial/dz.c
@@ -642,6 +642,26 @@ static void dz_set_termios(struct uart_port *uport, struct ktermios *termios,
spin_unlock_irqrestore(&dport->port.lock, flags);
}
+/*
+ * Hack alert!
+ * Required solely so that the initial PROM-based console
+ * works undisturbed in parallel with this one.
+ */
+static void dz_pm(struct uart_port *uport, unsigned int state,
+ unsigned int oldstate)
+{
+ struct dz_port *dport = to_dport(uport);
+ unsigned long flags;
+
+ spin_lock_irqsave(&dport->port.lock, flags);
+ if (state < 3)
+ dz_start_tx(&dport->port);
+ else
+ dz_stop_tx(&dport->port);
+ spin_unlock_irqrestore(&dport->port.lock, flags);
+}
+
+
static const char *dz_type(struct uart_port *uport)
{
return "DZ";
@@ -738,6 +758,7 @@ static struct uart_ops dz_ops = {
.startup = dz_startup,
.shutdown = dz_shutdown,
.set_termios = dz_set_termios,
+ .pm = dz_pm,
.type = dz_type,
.release_port = dz_release_port,
.request_port = dz_request_port,
@@ -861,7 +882,10 @@ static int __init dz_console_setup(struct console *co, char *options)
if (ret)
return ret;
+ spin_lock_init(&dport->port.lock); /* For dz_pm(). */
+
dz_reset(dport);
+ dz_pm(uport, 0, -1);
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index 9c2df5c857c..2b7531d9f6a 100644
--- a/drivers/serial/icom.c
+++ b/drivers/serial/icom.c
@@ -730,7 +730,7 @@ static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port)
static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
{
short int count, rcv_buff;
- struct tty_struct *tty = icom_port->uart_port.info->tty;
+ struct tty_struct *tty = icom_port->uart_port.info->port.tty;
unsigned short int status;
struct uart_icount *icount;
unsigned long offset;
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index c9f53e71f25..61d3ade5286 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -921,6 +921,10 @@ static int mpsc_make_ready(struct mpsc_port_info *pi)
return 0;
}
+#ifdef CONFIG_CONSOLE_POLL
+static int serial_polled;
+#endif
+
/*
******************************************************************************
*
@@ -956,7 +960,12 @@ static int mpsc_rx_intr(struct mpsc_port_info *pi)
while (!((cmdstat = be32_to_cpu(rxre->cmdstat))
& SDMA_DESC_CMDSTAT_O)) {
bytes_in = be16_to_cpu(rxre->bytecnt);
-
+#ifdef CONFIG_CONSOLE_POLL
+ if (unlikely(serial_polled)) {
+ serial_polled = 0;
+ return 0;
+ }
+#endif
/* Following use of tty struct directly is deprecated */
if (unlikely(tty_buffer_request_room(tty, bytes_in)
< bytes_in)) {
@@ -1017,6 +1026,12 @@ static int mpsc_rx_intr(struct mpsc_port_info *pi)
if (uart_handle_sysrq_char(&pi->port, *bp)) {
bp++;
bytes_in--;
+#ifdef CONFIG_CONSOLE_POLL
+ if (unlikely(serial_polled)) {
+ serial_polled = 0;
+ return 0;
+ }
+#endif
goto next_frame;
}
@@ -1519,6 +1534,133 @@ static int mpsc_verify_port(struct uart_port *port, struct serial_struct *ser)
return rc;
}
+#ifdef CONFIG_CONSOLE_POLL
+/* Serial polling routines for writing and reading from the uart while
+ * in an interrupt or debug context.
+ */
+
+static char poll_buf[2048];
+static int poll_ptr;
+static int poll_cnt;
+static void mpsc_put_poll_char(struct uart_port *port,
+ unsigned char c);
+
+static int mpsc_get_poll_char(struct uart_port *port)
+{
+ struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
+ struct mpsc_rx_desc *rxre;
+ u32 cmdstat, bytes_in, i;
+ u8 *bp;
+
+ if (!serial_polled)
+ serial_polled = 1;
+
+ pr_debug("mpsc_rx_intr[%d]: Handling Rx intr\n", pi->port.line);
+
+ if (poll_cnt) {
+ poll_cnt--;
+ return poll_buf[poll_ptr++];
+ }
+ poll_ptr = 0;
+ poll_cnt = 0;
+
+ while (poll_cnt == 0) {
+ rxre = (struct mpsc_rx_desc *)(pi->rxr +
+ (pi->rxr_posn*MPSC_RXRE_SIZE));
+ dma_cache_sync(pi->port.dev, (void *)rxre,
+ MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
+#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+ if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
+ invalidate_dcache_range((ulong)rxre,
+ (ulong)rxre + MPSC_RXRE_SIZE);
+#endif
+ /*
+ * Loop through Rx descriptors handling ones that have
+ * been completed.
+ */
+ while (poll_cnt == 0 &&
+ !((cmdstat = be32_to_cpu(rxre->cmdstat)) &
+ SDMA_DESC_CMDSTAT_O)){
+ bytes_in = be16_to_cpu(rxre->bytecnt);
+ bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE);
+ dma_cache_sync(pi->port.dev, (void *) bp,
+ MPSC_RXBE_SIZE, DMA_FROM_DEVICE);
+#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+ if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
+ invalidate_dcache_range((ulong)bp,
+ (ulong)bp + MPSC_RXBE_SIZE);
+#endif
+ if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR |
+ SDMA_DESC_CMDSTAT_FR | SDMA_DESC_CMDSTAT_OR))) &&
+ !(cmdstat & pi->port.ignore_status_mask)) {
+ poll_buf[poll_cnt] = *bp;
+ poll_cnt++;
+ } else {
+ for (i = 0; i < bytes_in; i++) {
+ poll_buf[poll_cnt] = *bp++;
+ poll_cnt++;
+ }
+ pi->port.icount.rx += bytes_in;
+ }
+ rxre->bytecnt = cpu_to_be16(0);
+ wmb();
+ rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O |
+ SDMA_DESC_CMDSTAT_EI |
+ SDMA_DESC_CMDSTAT_F |
+ SDMA_DESC_CMDSTAT_L);
+ wmb();
+ dma_cache_sync(pi->port.dev, (void *)rxre,
+ MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL);
+#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+ if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
+ flush_dcache_range((ulong)rxre,
+ (ulong)rxre + MPSC_RXRE_SIZE);
+#endif
+
+ /* Advance to next descriptor */
+ pi->rxr_posn = (pi->rxr_posn + 1) &
+ (MPSC_RXR_ENTRIES - 1);
+ rxre = (struct mpsc_rx_desc *)(pi->rxr +
+ (pi->rxr_posn * MPSC_RXRE_SIZE));
+ dma_cache_sync(pi->port.dev, (void *)rxre,
+ MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
+#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+ if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
+ invalidate_dcache_range((ulong)rxre,
+ (ulong)rxre + MPSC_RXRE_SIZE);
+#endif
+ }
+
+ /* Restart rx engine, if its stopped */
+ if ((readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_ERD) == 0)
+ mpsc_start_rx(pi);
+ }
+ if (poll_cnt) {
+ poll_cnt--;
+ return poll_buf[poll_ptr++];
+ }
+
+ return 0;
+}
+
+
+static void mpsc_put_poll_char(struct uart_port *port,
+ unsigned char c)
+{
+ struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
+ u32 data;
+
+ data = readl(pi->mpsc_base + MPSC_MPCR);
+ writeb(c, pi->mpsc_base + MPSC_CHR_1);
+ mb();
+ data = readl(pi->mpsc_base + MPSC_CHR_2);
+ data |= MPSC_CHR_2_TTCS;
+ writel(data, pi->mpsc_base + MPSC_CHR_2);
+ mb();
+
+ while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_TTCS);
+}
+#endif
static struct uart_ops mpsc_pops = {
.tx_empty = mpsc_tx_empty,
@@ -1537,6 +1679,10 @@ static struct uart_ops mpsc_pops = {
.request_port = mpsc_request_port,
.config_port = mpsc_config_port,
.verify_port = mpsc_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+ .poll_get_char = mpsc_get_poll_char,
+ .poll_put_char = mpsc_put_poll_char,
+#endif
};
/*
diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c
index 4a3ecaa629e..d852f83f890 100644
--- a/drivers/serial/samsung.c
+++ b/drivers/serial/samsung.c
@@ -202,7 +202,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id)
{
struct s3c24xx_uart_port *ourport = dev_id;
struct uart_port *port = &ourport->port;
- struct tty_struct *tty = port->info->tty;
+ struct tty_struct *tty = port->info->port.tty;
unsigned int ufcon, ch, flag, ufstat, uerstat;
int max_count = 64;
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 0bce1fe2c62..f977c98cfa9 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -934,7 +934,7 @@ uart_tiocmset(struct tty_struct *tty, struct file *file,
return ret;
}
-static void uart_break_ctl(struct tty_struct *tty, int break_state)
+static int uart_break_ctl(struct tty_struct *tty, int break_state)
{
struct uart_state *state = tty->driver_data;
struct uart_port *port = state->port;
@@ -945,6 +945,7 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state)
port->ops->break_ctl(port, break_state);
mutex_unlock(&state->mutex);
+ return 0;
}
static int uart_do_autoconfig(struct uart_state *state)
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index 7ad21925869..8fcb4c5b9a2 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -272,7 +272,7 @@ static void serial_txx9_initialize(struct uart_port *port)
static inline void
receive_chars(struct uart_txx9_port *up, unsigned int *status)
{
- struct tty_struct *tty = up->port.info->tty;
+ struct tty_struct *tty = up->port.info->port.tty;
unsigned char ch;
unsigned int disr = *status;
int max_count = 256;
diff --git a/drivers/serial/zs.c b/drivers/serial/zs.c
index bd45b6230fd..9e6a873f820 100644
--- a/drivers/serial/zs.c
+++ b/drivers/serial/zs.c
@@ -787,7 +787,6 @@ static int zs_startup(struct uart_port *uport)
zport->regs[1] &= ~RxINT_MASK;
zport->regs[1] |= RxINT_ALL | TxINT_ENAB | EXT_INT_ENAB;
zport->regs[3] |= RxENABLE;
- zport->regs[5] |= TxENAB;
zport->regs[15] |= BRKIE;
write_zsreg(zport, R1, zport->regs[1]);
write_zsreg(zport, R3, zport->regs[3]);
@@ -814,7 +813,6 @@ static void zs_shutdown(struct uart_port *uport)
spin_lock_irqsave(&scc->zlock, flags);
- zport->regs[5] &= ~TxENAB;
zport->regs[3] &= ~RxENABLE;
write_zsreg(zport, R5, zport->regs[5]);
write_zsreg(zport, R3, zport->regs[3]);
@@ -959,6 +957,23 @@ static void zs_set_termios(struct uart_port *uport, struct ktermios *termios,
spin_unlock_irqrestore(&scc->zlock, flags);
}
+/*
+ * Hack alert!
+ * Required solely so that the initial PROM-based console
+ * works undisturbed in parallel with this one.
+ */
+static void zs_pm(struct uart_port *uport, unsigned int state,
+ unsigned int oldstate)
+{
+ struct zs_port *zport = to_zport(uport);
+
+ if (state < 3)
+ zport->regs[5] |= TxENAB;
+ else
+ zport->regs[5] &= ~TxENAB;
+ write_zsreg(zport, R5, zport->regs[5]);
+}
+
static const char *zs_type(struct uart_port *uport)
{
@@ -1041,6 +1056,7 @@ static struct uart_ops zs_ops = {
.startup = zs_startup,
.shutdown = zs_shutdown,
.set_termios = zs_set_termios,
+ .pm = zs_pm,
.type = zs_type,
.release_port = zs_release_port,
.request_port = zs_request_port,
@@ -1190,6 +1206,7 @@ static int __init zs_console_setup(struct console *co, char *options)
return ret;
zs_reset(zport);
+ zs_pm(uport, 0, -1);
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 66ec5d8808d..2303521b4f0 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -49,25 +49,26 @@ config SPI_MASTER
controller and the protocol drivers for the SPI slave chips
that are connected.
+if SPI_MASTER
+
comment "SPI Master Controller Drivers"
- depends on SPI_MASTER
config SPI_ATMEL
tristate "Atmel SPI Controller"
- depends on (ARCH_AT91 || AVR32) && SPI_MASTER
+ depends on (ARCH_AT91 || AVR32)
help
This selects a driver for the Atmel SPI Controller, present on
many AT32 (AVR32) and AT91 (ARM) chips.
config SPI_BFIN
tristate "SPI controller driver for ADI Blackfin5xx"
- depends on SPI_MASTER && BLACKFIN
+ depends on BLACKFIN
help
This is the SPI controller master driver for Blackfin 5xx processor.
config SPI_AU1550
tristate "Au1550/Au12x0 SPI Controller"
- depends on SPI_MASTER && (SOC_AU1550 || SOC_AU1200) && EXPERIMENTAL
+ depends on (SOC_AU1550 || SOC_AU1200) && EXPERIMENTAL
select SPI_BITBANG
help
If you say yes to this option, support will be included for the
@@ -78,7 +79,6 @@ config SPI_AU1550
config SPI_BITBANG
tristate "Bitbanging SPI master"
- depends on SPI_MASTER && EXPERIMENTAL
help
With a few GPIO pins, your system can bitbang the SPI protocol.
Select this to get SPI support through I/O pins (GPIO, parallel
@@ -92,7 +92,7 @@ config SPI_BITBANG
config SPI_BUTTERFLY
tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)"
- depends on SPI_MASTER && PARPORT && EXPERIMENTAL
+ depends on PARPORT
select SPI_BITBANG
help
This uses a custom parallel port cable to connect to an AVR
@@ -102,14 +102,14 @@ config SPI_BUTTERFLY
config SPI_IMX
tristate "Freescale iMX SPI controller"
- depends on SPI_MASTER && ARCH_IMX && EXPERIMENTAL
+ depends on ARCH_IMX && EXPERIMENTAL
help
This enables using the Freescale iMX SPI controller in master
mode.
config SPI_LM70_LLP
tristate "Parallel port adapter for LM70 eval board (DEVELOPMENT)"
- depends on SPI_MASTER && PARPORT && EXPERIMENTAL
+ depends on PARPORT && EXPERIMENTAL
select SPI_BITBANG
help
This driver supports the NS LM70 LLP Evaluation Board,
@@ -118,14 +118,14 @@ config SPI_LM70_LLP
config SPI_MPC52xx_PSC
tristate "Freescale MPC52xx PSC SPI controller"
- depends on SPI_MASTER && PPC_MPC52xx && EXPERIMENTAL
+ depends on PPC_MPC52xx && EXPERIMENTAL
help
This enables using the Freescale MPC52xx Programmable Serial
Controller in master SPI mode.
config SPI_MPC83xx
tristate "Freescale MPC83xx/QUICC Engine SPI controller"
- depends on SPI_MASTER && (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL
+ depends on (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL
help
This enables using the Freescale MPC83xx and QUICC Engine SPI
controllers in master mode.
@@ -137,21 +137,21 @@ config SPI_MPC83xx
config SPI_OMAP_UWIRE
tristate "OMAP1 MicroWire"
- depends on SPI_MASTER && ARCH_OMAP1
+ depends on ARCH_OMAP1
select SPI_BITBANG
help
This hooks up to the MicroWire controller on OMAP1 chips.
config SPI_OMAP24XX
tristate "McSPI driver for OMAP24xx/OMAP34xx"
- depends on SPI_MASTER && (ARCH_OMAP24XX || ARCH_OMAP34XX)
+ depends on ARCH_OMAP24XX || ARCH_OMAP34XX
help
SPI master controller for OMAP24xx/OMAP34xx Multichannel SPI
(McSPI) modules.
config SPI_PXA2XX
tristate "PXA2xx SSP SPI master"
- depends on SPI_MASTER && ARCH_PXA && EXPERIMENTAL
+ depends on ARCH_PXA && EXPERIMENTAL
select PXA_SSP
help
This enables using a PXA2xx SSP port as a SPI master controller.
@@ -160,14 +160,14 @@ config SPI_PXA2XX
config SPI_S3C24XX
tristate "Samsung S3C24XX series SPI"
- depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+ depends on ARCH_S3C2410 && EXPERIMENTAL
select SPI_BITBANG
help
SPI driver for Samsung S3C24XX series ARM SoCs
config SPI_S3C24XX_GPIO
tristate "Samsung S3C24XX series SPI by GPIO"
- depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+ depends on ARCH_S3C2410 && EXPERIMENTAL
select SPI_BITBANG
help
SPI driver for Samsung S3C24XX series ARM SoCs using
@@ -177,20 +177,20 @@ config SPI_S3C24XX_GPIO
config SPI_SH_SCI
tristate "SuperH SCI SPI controller"
- depends on SPI_MASTER && SUPERH
+ depends on SUPERH
select SPI_BITBANG
help
SPI driver for SuperH SCI blocks.
config SPI_TXX9
tristate "Toshiba TXx9 SPI controller"
- depends on SPI_MASTER && GENERIC_GPIO && CPU_TX49XX
+ depends on GENERIC_GPIO && CPU_TX49XX
help
SPI driver for Toshiba TXx9 MIPS SoCs
config SPI_XILINX
tristate "Xilinx SPI controller"
- depends on SPI_MASTER && XILINX_VIRTEX && EXPERIMENTAL
+ depends on XILINX_VIRTEX && EXPERIMENTAL
select SPI_BITBANG
help
This exposes the SPI controller IP from the Xilinx EDK.
@@ -207,11 +207,10 @@ config SPI_XILINX
# being probably the most widely used ones.
#
comment "SPI Protocol Masters"
- depends on SPI_MASTER
config SPI_AT25
tristate "SPI EEPROMs from most vendors"
- depends on SPI_MASTER && SYSFS
+ depends on SYSFS
help
Enable this driver to get read/write support to most SPI EEPROMs,
after you configure the board init code to know about each eeprom
@@ -222,7 +221,7 @@ config SPI_AT25
config SPI_SPIDEV
tristate "User mode SPI device driver support"
- depends on SPI_MASTER && EXPERIMENTAL
+ depends on EXPERIMENTAL
help
This supports user mode SPI protocol drivers.
@@ -231,7 +230,7 @@ config SPI_SPIDEV
config SPI_TLE62X0
tristate "Infineon TLE62X0 (for power switching)"
- depends on SPI_MASTER && SYSFS
+ depends on SYSFS
help
SPI driver for Infineon TLE62X0 series line driver chips,
such as the TLE6220, TLE6230 and TLE6240. This provides a
@@ -242,6 +241,8 @@ config SPI_TLE62X0
# Add new SPI protocol masters in alphabetical order above this line
#
+endif # SPI_MASTER
+
# (slave support would go here)
endif # SPI
diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c
index 072c4a59533..9149689c79d 100644
--- a/drivers/spi/au1550_spi.c
+++ b/drivers/spi/au1550_spi.c
@@ -26,6 +26,7 @@
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/platform_device.h>
+#include <linux/resource.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/dma-mapping.h>
@@ -81,6 +82,7 @@ struct au1550_spi {
struct spi_master *master;
struct device *dev;
struct au1550_spi_info *pdata;
+ struct resource *ioarea;
};
@@ -96,6 +98,8 @@ static dbdev_tab_t au1550_spi_mem_dbdev =
.dev_intpolarity = 0
};
+static int ddma_memid; /* id to above mem dma device */
+
static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw);
@@ -480,9 +484,13 @@ static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw)
au1xxx_dbdma_reset(hw->dma_tx_ch);
au1550_spi_reset_fifos(hw);
- dev_err(hw->dev,
- "Unexpected SPI error: event=0x%x stat=0x%x!\n",
- evnt, stat);
+ if (evnt == PSC_SPIEVNT_RO)
+ dev_err(hw->dev,
+ "dma transfer: receive FIFO overflow!\n");
+ else
+ dev_err(hw->dev,
+ "dma transfer: unexpected SPI error "
+ "(event=0x%x stat=0x%x)!\n", evnt, stat);
complete(&hw->master_done);
return IRQ_HANDLED;
@@ -592,17 +600,17 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
if ((evnt & (PSC_SPIEVNT_MM | PSC_SPIEVNT_RO
| PSC_SPIEVNT_RU | PSC_SPIEVNT_TO
- | PSC_SPIEVNT_TU | PSC_SPIEVNT_SD))
+ | PSC_SPIEVNT_SD))
!= 0) {
- dev_err(hw->dev,
- "Unexpected SPI error: event=0x%x stat=0x%x!\n",
- evnt, stat);
/*
* due to an error we consider transfer as done,
* so mask all events until before next transfer start
*/
au1550_spi_mask_ack_all(hw);
au1550_spi_reset_fifos(hw);
+ dev_err(hw->dev,
+ "pio transfer: unexpected SPI error "
+ "(event=0x%x stat=0x%x)!\n", evnt, stat);
complete(&hw->master_done);
return IRQ_HANDLED;
}
@@ -616,27 +624,50 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
stat = hw->regs->psc_spistat;
au_sync();
- if ((stat & PSC_SPISTAT_RE) == 0 && hw->rx_count < hw->len) {
+ /*
+ * Take care to not let the Rx FIFO overflow.
+ *
+ * We only write a byte if we have read one at least. Initially,
+ * the write fifo is full, so we should read from the read fifo
+ * first.
+ * In case we miss a word from the read fifo, we should get a
+ * RO event and should back out.
+ */
+ if (!(stat & PSC_SPISTAT_RE) && hw->rx_count < hw->len) {
hw->rx_word(hw);
- /* ack the receive request event */
- hw->regs->psc_spievent = PSC_SPIEVNT_RR;
- au_sync();
busy = 1;
- }
- if ((stat & PSC_SPISTAT_TF) == 0 && hw->tx_count < hw->len) {
- hw->tx_word(hw);
- /* ack the transmit request event */
- hw->regs->psc_spievent = PSC_SPIEVNT_TR;
- au_sync();
- busy = 1;
+ if (!(stat & PSC_SPISTAT_TF) && hw->tx_count < hw->len)
+ hw->tx_word(hw);
}
} while (busy);
- evnt = hw->regs->psc_spievent;
+ hw->regs->psc_spievent = PSC_SPIEVNT_RR | PSC_SPIEVNT_TR;
au_sync();
- if (hw->rx_count >= hw->len || (evnt & PSC_SPIEVNT_MD) != 0) {
+ /*
+ * Restart the SPI transmission in case of a transmit underflow.
+ * This seems to work despite the notes in the Au1550 data book
+ * of Figure 8-4 with flowchart for SPI master operation:
+ *
+ * """Note 1: An XFR Error Interrupt occurs, unless masked,
+ * for any of the following events: Tx FIFO Underflow,
+ * Rx FIFO Overflow, or Multiple-master Error
+ * Note 2: In case of a Tx Underflow Error, all zeroes are
+ * transmitted."""
+ *
+ * By simply restarting the spi transfer on Tx Underflow Error,
+ * we assume that spi transfer was paused instead of zeroes
+ * transmittion mentioned in the Note 2 of Au1550 data book.
+ */
+ if (evnt & PSC_SPIEVNT_TU) {
+ hw->regs->psc_spievent = PSC_SPIEVNT_TU | PSC_SPIEVNT_MD;
+ au_sync();
+ hw->regs->psc_spipcr = PSC_SPIPCR_MS;
+ au_sync();
+ }
+
+ if (hw->rx_count >= hw->len) {
/* transfer completed successfully */
au1550_spi_mask_ack_all(hw);
complete(&hw->master_done);
@@ -725,6 +756,8 @@ static void __init au1550_spi_setup_psc_as_spi(struct au1550_spi *hw)
stat = hw->regs->psc_spistat;
au_sync();
} while ((stat & PSC_SPISTAT_DR) == 0);
+
+ au1550_spi_reset_fifos(hw);
}
@@ -732,6 +765,7 @@ static int __init au1550_spi_probe(struct platform_device *pdev)
{
struct au1550_spi *hw;
struct spi_master *master;
+ struct resource *r;
int err = 0;
master = spi_alloc_master(&pdev->dev, sizeof(struct au1550_spi));
@@ -753,76 +787,64 @@ static int __init au1550_spi_probe(struct platform_device *pdev)
goto err_no_pdata;
}
- platform_set_drvdata(pdev, hw);
-
- init_completion(&hw->master_done);
-
- hw->bitbang.master = hw->master;
- hw->bitbang.setup_transfer = au1550_spi_setupxfer;
- hw->bitbang.chipselect = au1550_spi_chipsel;
- hw->bitbang.master->setup = au1550_spi_setup;
- hw->bitbang.txrx_bufs = au1550_spi_txrx_bufs;
+ r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!r) {
+ dev_err(&pdev->dev, "no IRQ\n");
+ err = -ENODEV;
+ goto err_no_iores;
+ }
+ hw->irq = r->start;
+
+ hw->usedma = 0;
+ r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (r) {
+ hw->dma_tx_id = r->start;
+ r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (r) {
+ hw->dma_rx_id = r->start;
+ if (usedma && ddma_memid) {
+ if (pdev->dev.dma_mask == NULL)
+ dev_warn(&pdev->dev, "no dma mask\n");
+ else
+ hw->usedma = 1;
+ }
+ }
+ }
- switch (hw->pdata->bus_num) {
- case 0:
- hw->irq = AU1550_PSC0_INT;
- hw->regs = (volatile psc_spi_t *)PSC0_BASE_ADDR;
- hw->dma_rx_id = DSCR_CMD0_PSC0_RX;
- hw->dma_tx_id = DSCR_CMD0_PSC0_TX;
- break;
- case 1:
- hw->irq = AU1550_PSC1_INT;
- hw->regs = (volatile psc_spi_t *)PSC1_BASE_ADDR;
- hw->dma_rx_id = DSCR_CMD0_PSC1_RX;
- hw->dma_tx_id = DSCR_CMD0_PSC1_TX;
- break;
- case 2:
- hw->irq = AU1550_PSC2_INT;
- hw->regs = (volatile psc_spi_t *)PSC2_BASE_ADDR;
- hw->dma_rx_id = DSCR_CMD0_PSC2_RX;
- hw->dma_tx_id = DSCR_CMD0_PSC2_TX;
- break;
- case 3:
- hw->irq = AU1550_PSC3_INT;
- hw->regs = (volatile psc_spi_t *)PSC3_BASE_ADDR;
- hw->dma_rx_id = DSCR_CMD0_PSC3_RX;
- hw->dma_tx_id = DSCR_CMD0_PSC3_TX;
- break;
- default:
- dev_err(&pdev->dev, "Wrong bus_num of SPI\n");
- err = -ENOENT;
- goto err_no_pdata;
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r) {
+ dev_err(&pdev->dev, "no mmio resource\n");
+ err = -ENODEV;
+ goto err_no_iores;
}
- if (request_mem_region((unsigned long)hw->regs, sizeof(psc_spi_t),
- pdev->name) == NULL) {
+ hw->ioarea = request_mem_region(r->start, sizeof(psc_spi_t),
+ pdev->name);
+ if (!hw->ioarea) {
dev_err(&pdev->dev, "Cannot reserve iomem region\n");
err = -ENXIO;
goto err_no_iores;
}
-
- if (usedma) {
- if (pdev->dev.dma_mask == NULL)
- dev_warn(&pdev->dev, "no dma mask\n");
- else
- hw->usedma = 1;
+ hw->regs = (psc_spi_t __iomem *)ioremap(r->start, sizeof(psc_spi_t));
+ if (!hw->regs) {
+ dev_err(&pdev->dev, "cannot ioremap\n");
+ err = -ENXIO;
+ goto err_ioremap;
}
- if (hw->usedma) {
- /*
- * create memory device with 8 bits dev_devwidth
- * needed for proper byte ordering to spi fifo
- */
- int memid = au1xxx_ddma_add_device(&au1550_spi_mem_dbdev);
- if (!memid) {
- dev_err(&pdev->dev,
- "Cannot create dma 8 bit mem device\n");
- err = -ENXIO;
- goto err_dma_add_dev;
- }
+ platform_set_drvdata(pdev, hw);
+
+ init_completion(&hw->master_done);
+
+ hw->bitbang.master = hw->master;
+ hw->bitbang.setup_transfer = au1550_spi_setupxfer;
+ hw->bitbang.chipselect = au1550_spi_chipsel;
+ hw->bitbang.master->setup = au1550_spi_setup;
+ hw->bitbang.txrx_bufs = au1550_spi_txrx_bufs;
- hw->dma_tx_ch = au1xxx_dbdma_chan_alloc(memid,
+ if (hw->usedma) {
+ hw->dma_tx_ch = au1xxx_dbdma_chan_alloc(ddma_memid,
hw->dma_tx_id, NULL, (void *)hw);
if (hw->dma_tx_ch == 0) {
dev_err(&pdev->dev,
@@ -841,7 +863,7 @@ static int __init au1550_spi_probe(struct platform_device *pdev)
hw->dma_rx_ch = au1xxx_dbdma_chan_alloc(hw->dma_rx_id,
- memid, NULL, (void *)hw);
+ ddma_memid, NULL, (void *)hw);
if (hw->dma_rx_ch == 0) {
dev_err(&pdev->dev,
"Cannot allocate rx dma channel\n");
@@ -874,7 +896,7 @@ static int __init au1550_spi_probe(struct platform_device *pdev)
goto err_no_irq;
}
- master->bus_num = hw->pdata->bus_num;
+ master->bus_num = pdev->id;
master->num_chipselect = hw->pdata->num_chipselect;
/*
@@ -924,8 +946,11 @@ err_no_txdma_descr:
au1xxx_dbdma_chan_free(hw->dma_tx_ch);
err_no_txdma:
-err_dma_add_dev:
- release_mem_region((unsigned long)hw->regs, sizeof(psc_spi_t));
+ iounmap((void __iomem *)hw->regs);
+
+err_ioremap:
+ release_resource(hw->ioarea);
+ kfree(hw->ioarea);
err_no_iores:
err_no_pdata:
@@ -944,7 +969,9 @@ static int __exit au1550_spi_remove(struct platform_device *pdev)
spi_bitbang_stop(&hw->bitbang);
free_irq(hw->irq, hw);
- release_mem_region((unsigned long)hw->regs, sizeof(psc_spi_t));
+ iounmap((void __iomem *)hw->regs);
+ release_resource(hw->ioarea);
+ kfree(hw->ioarea);
if (hw->usedma) {
au1550_spi_dma_rxtmp_free(hw);
@@ -971,12 +998,24 @@ static struct platform_driver au1550_spi_drv = {
static int __init au1550_spi_init(void)
{
+ /*
+ * create memory device with 8 bits dev_devwidth
+ * needed for proper byte ordering to spi fifo
+ */
+ if (usedma) {
+ ddma_memid = au1xxx_ddma_add_device(&au1550_spi_mem_dbdev);
+ if (!ddma_memid)
+ printk(KERN_ERR "au1550-spi: cannot add memory"
+ "dbdma device\n");
+ }
return platform_driver_probe(&au1550_spi_drv, au1550_spi_probe);
}
module_init(au1550_spi_init);
static void __exit au1550_spi_exit(void)
{
+ if (usedma && ddma_memid)
+ au1xxx_ddma_del_device(ddma_memid);
platform_driver_unregister(&au1550_spi_drv);
}
module_exit(au1550_spi_exit);
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 1ad12afc6ba..ecca4a6a6f9 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -218,6 +218,8 @@ struct spi_device *spi_new_device(struct spi_master *master,
if (!spi_master_get(master))
return NULL;
+ WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));
+
proxy = kzalloc(sizeof *proxy, GFP_KERNEL);
if (!proxy) {
dev_err(dev, "can't alloc dev for cs%d\n",
@@ -229,7 +231,7 @@ struct spi_device *spi_new_device(struct spi_master *master,
proxy->max_speed_hz = chip->max_speed_hz;
proxy->mode = chip->mode;
proxy->irq = chip->irq;
- proxy->modalias = chip->modalias;
+ strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));
snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
"%s.%u", master->dev.bus_id,
@@ -502,7 +504,7 @@ struct spi_master *spi_busnum_to_master(u16 bus_num)
struct device *dev;
struct spi_master *master = NULL;
- dev = class_find_device(&spi_master_class, &bus_num,
+ dev = class_find_device(&spi_master_class, NULL, &bus_num,
__spi_master_match);
if (dev)
master = container_of(dev, struct spi_master, dev);
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c
index 6832da6f710..070c6219e2d 100644
--- a/drivers/spi/spi_mpc83xx.c
+++ b/drivers/spi/spi_mpc83xx.c
@@ -266,21 +266,24 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
cs->hw_mode |= SPMODE_LEN(bits_per_word);
- if ((mpc83xx_spi->spibrg / hz) >= 64) {
- pm = mpc83xx_spi->spibrg / (hz * 64) - 1;
- if (pm > 0x0f) {
- dev_err(&spi->dev, "Requested speed is too "
- "low: %d Hz. Will use %d Hz instead.\n",
- hz, mpc83xx_spi->spibrg / 1024);
- pm = 0x0f;
+ if ((mpc83xx_spi->spibrg / hz) > 64) {
+ pm = mpc83xx_spi->spibrg / (hz * 64);
+ if (pm > 16) {
+ cs->hw_mode |= SPMODE_DIV16;
+ pm /= 16;
+ if (pm > 16) {
+ dev_err(&spi->dev, "Requested speed is too "
+ "low: %d Hz. Will use %d Hz instead.\n",
+ hz, mpc83xx_spi->spibrg / 1024);
+ pm = 16;
+ }
}
- cs->hw_mode |= SPMODE_PM(pm) | SPMODE_DIV16;
- } else {
+ } else
pm = mpc83xx_spi->spibrg / (hz * 4);
- if (pm)
- pm--;
- cs->hw_mode |= SPMODE_PM(pm);
- }
+ if (pm)
+ pm--;
+
+ cs->hw_mode |= SPMODE_PM(pm);
regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode);
if (cs->hw_mode != regval) {
unsigned long flags;
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index ddbe1a5e970..e5e0cfed5e3 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -228,7 +228,6 @@ static int spidev_message(struct spidev_data *spidev,
* We walk the array of user-provided transfers, using each one
* to initialize a kernel version of the same transfer.
*/
- mutex_lock(&spidev->buf_lock);
buf = spidev->buffer;
total = 0;
for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;
@@ -296,14 +295,12 @@ static int spidev_message(struct spidev_data *spidev,
status = total;
done:
- mutex_unlock(&spidev->buf_lock);
kfree(k_xfers);
return status;
}
-static int
-spidev_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static long
+spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int err = 0;
int retval = 0;
@@ -341,6 +338,14 @@ spidev_ioctl(struct inode *inode, struct file *filp,
if (spi == NULL)
return -ESHUTDOWN;
+ /* use the buffer lock here for triple duty:
+ * - prevent I/O (from us) so calling spi_setup() is safe;
+ * - prevent concurrent SPI_IOC_WR_* from morphing
+ * data fields while SPI_IOC_RD_* reads them;
+ * - SPI_IOC_MESSAGE needs the buffer locked "normally".
+ */
+ mutex_lock(&spidev->buf_lock);
+
switch (cmd) {
/* read requests */
case SPI_IOC_RD_MODE:
@@ -456,6 +461,8 @@ spidev_ioctl(struct inode *inode, struct file *filp,
kfree(ioc);
break;
}
+
+ mutex_unlock(&spidev->buf_lock);
spi_dev_put(spi);
return retval;
}
@@ -533,7 +540,7 @@ static struct file_operations spidev_fops = {
*/
.write = spidev_write,
.read = spidev_read,
- .ioctl = spidev_ioctl,
+ .unlocked_ioctl = spidev_ioctl,
.open = spidev_open,
.release = spidev_release,
};
@@ -576,7 +583,8 @@ static int spidev_probe(struct spi_device *spi)
struct device *dev;
spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
- dev = device_create(spidev_class, &spi->dev, spidev->devt,
+ dev = device_create_drvdata(spidev_class, &spi->dev,
+ spidev->devt, spidev,
"spidev%d.%d",
spi->master->bus_num, spi->chip_select);
status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
@@ -586,7 +594,6 @@ static int spidev_probe(struct spi_device *spi)
}
if (status == 0) {
set_bit(minor, minors);
- spi_set_drvdata(spi, spidev);
list_add(&spidev->device_entry, &device_list);
}
mutex_unlock(&device_list_lock);
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 113a0468ffc..68d6f4988fb 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -353,11 +353,12 @@ static int __init xilinx_spi_probe(struct platform_device *dev)
goto put_master;
}
- xspi->irq = platform_get_irq(dev, 0);
- if (xspi->irq < 0) {
+ ret = platform_get_irq(dev, 0);
+ if (ret < 0) {
ret = -ENXIO;
goto unmap_io;
}
+ xspi->irq = ret;
master->bus_num = pdata->bus_num;
master->num_chipselect = pdata->num_chipselect;
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index 49cd9793404..ec7aeb502d1 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -6095,15 +6095,15 @@ static int capabilities_check(IXJ *j, struct phone_capability *pcreq)
return retval;
}
-static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd, unsigned long arg)
+static long do_ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long arg)
{
IXJ_TONE ti;
IXJ_FILTER jf;
IXJ_FILTER_RAW jfr;
void __user *argp = (void __user *)arg;
-
- unsigned int raise, mant;
+ struct inode *inode = file_p->f_path.dentry->d_inode;
unsigned int minor = iminor(inode);
+ unsigned int raise, mant;
int board = NUM(inode);
IXJ *j = get_ixj(NUM(inode));
@@ -6661,6 +6661,15 @@ static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd,
return retval;
}
+static long ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long arg)
+{
+ long ret;
+ lock_kernel();
+ ret = do_ixj_ioctl(file_p, cmd, arg);
+ unlock_kernel();
+ return ret;
+}
+
static int ixj_fasync(int fd, struct file *file_p, int mode)
{
IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode));
@@ -6674,7 +6683,7 @@ static const struct file_operations ixj_fops =
.read = ixj_enhanced_read,
.write = ixj_enhanced_write,
.poll = ixj_poll,
- .ioctl = ixj_ioctl,
+ .unlocked_ioctl = ixj_ioctl,
.release = ixj_release,
.fasync = ixj_fasync
};
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index a4aaab9c7dd..2e9079df26b 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -15,7 +15,7 @@ if UIO
config UIO_CIF
tristate "generic Hilscher CIF Card driver"
- depends on UIO && PCI
+ depends on PCI
default n
help
Driver for Hilscher CIF DeviceNet and Profibus cards. This
@@ -26,9 +26,15 @@ config UIO_CIF
To compile this driver as a module, choose M here: the module
will be called uio_cif.
+config UIO_PDRV
+ tristate "Userspace I/O platform driver"
+ help
+ Generic platform driver for Userspace I/O devices.
+
+ If you don't know what to do here, say N.
+
config UIO_SMX
tristate "SMX cryptengine UIO interface"
- depends on UIO
default n
help
Userspace IO interface to the Cryptography engine found on the
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index 18c45662431..e00ce0def1a 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_UIO) += uio.o
obj-$(CONFIG_UIO_CIF) += uio_cif.o
+obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o
obj-$(CONFIG_UIO_SMX) += uio_smx.o
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 5a7ca2e6094..3a6934bf713 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -427,6 +427,31 @@ static ssize_t uio_read(struct file *filep, char __user *buf,
return retval;
}
+static ssize_t uio_write(struct file *filep, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct uio_listener *listener = filep->private_data;
+ struct uio_device *idev = listener->dev;
+ ssize_t retval;
+ s32 irq_on;
+
+ if (idev->info->irq == UIO_IRQ_NONE)
+ return -EIO;
+
+ if (count != sizeof(s32))
+ return -EINVAL;
+
+ if (!idev->info->irqcontrol)
+ return -ENOSYS;
+
+ if (copy_from_user(&irq_on, buf, count))
+ return -EFAULT;
+
+ retval = idev->info->irqcontrol(idev->info, irq_on);
+
+ return retval ? retval : sizeof(s32);
+}
+
static int uio_find_mem_index(struct vm_area_struct *vma)
{
int mi;
@@ -546,6 +571,7 @@ static const struct file_operations uio_fops = {
.open = uio_open,
.release = uio_release,
.read = uio_read,
+ .write = uio_write,
.mmap = uio_mmap,
.poll = uio_poll,
.fasync = uio_fasync,
diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c
new file mode 100644
index 00000000000..5d0d2e85d98
--- /dev/null
+++ b/drivers/uio/uio_pdrv.c
@@ -0,0 +1,118 @@
+/*
+ * drivers/uio/uio_pdrv.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/platform_device.h>
+#include <linux/uio_driver.h>
+#include <linux/stringify.h>
+
+#define DRIVER_NAME "uio"
+
+struct uio_platdata {
+ struct uio_info *uioinfo;
+};
+
+static int uio_pdrv_probe(struct platform_device *pdev)
+{
+ struct uio_info *uioinfo = pdev->dev.platform_data;
+ struct uio_platdata *pdata;
+ struct uio_mem *uiomem;
+ int ret = -ENODEV;
+ int i;
+
+ if (!uioinfo || !uioinfo->name || !uioinfo->version) {
+ dev_dbg(&pdev->dev, "%s: err_uioinfo\n", __func__);
+ goto err_uioinfo;
+ }
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ ret = -ENOMEM;
+ dev_dbg(&pdev->dev, "%s: err_alloc_pdata\n", __func__);
+ goto err_alloc_pdata;
+ }
+
+ pdata->uioinfo = uioinfo;
+
+ uiomem = &uioinfo->mem[0];
+
+ for (i = 0; i < pdev->num_resources; ++i) {
+ struct resource *r = &pdev->resource[i];
+
+ if (r->flags != IORESOURCE_MEM)
+ continue;
+
+ if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
+ dev_warn(&pdev->dev, "device has more than "
+ __stringify(MAX_UIO_MAPS)
+ " I/O memory resources.\n");
+ break;
+ }
+
+ uiomem->memtype = UIO_MEM_PHYS;
+ uiomem->addr = r->start;
+ uiomem->size = r->end - r->start + 1;
+ ++uiomem;
+ }
+
+ while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) {
+ uiomem->size = 0;
+ ++uiomem;
+ }
+
+ pdata->uioinfo->priv = pdata;
+
+ ret = uio_register_device(&pdev->dev, pdata->uioinfo);
+
+ if (ret) {
+ kfree(pdata);
+err_alloc_pdata:
+err_uioinfo:
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, pdata);
+
+ return 0;
+}
+
+static int uio_pdrv_remove(struct platform_device *pdev)
+{
+ struct uio_platdata *pdata = platform_get_drvdata(pdev);
+
+ uio_unregister_device(pdata->uioinfo);
+
+ return 0;
+}
+
+static struct platform_driver uio_pdrv = {
+ .probe = uio_pdrv_probe,
+ .remove = uio_pdrv_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init uio_pdrv_init(void)
+{
+ return platform_driver_register(&uio_pdrv);
+}
+
+static void __exit uio_pdrv_exit(void)
+{
+ platform_driver_unregister(&uio_pdrv);
+}
+module_init(uio_pdrv_init);
+module_exit(uio_pdrv_exit);
+
+MODULE_AUTHOR("Uwe Kleine-Koenig");
+MODULE_DESCRIPTION("Userspace I/O platform driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 95ae6377d7e..0725b1871f2 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -732,13 +732,16 @@ static void acm_tty_unthrottle(struct tty_struct *tty)
tasklet_schedule(&acm->urb_task);
}
-static void acm_tty_break_ctl(struct tty_struct *tty, int state)
+static int acm_tty_break_ctl(struct tty_struct *tty, int state)
{
struct acm *acm = tty->driver_data;
+ int retval;
if (!ACM_READY(acm))
- return;
- if (acm_send_break(acm, state ? 0xffff : 0))
+ return -EINVAL;
+ retval = acm_send_break(acm, state ? 0xffff : 0);
+ if (retval < 0)
dbg("send break failed");
+ return retval;
}
static int acm_tty_tiocmget(struct tty_struct *tty, struct file *file)
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 54a350ccd03..20290c5b156 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1729,9 +1729,9 @@ static int usb_classdev_add(struct usb_device *dev)
{
struct device *cldev;
- cldev = device_create(usb_classdev_class, &dev->dev, dev->dev.devt,
- "usbdev%d.%d", dev->bus->busnum,
- dev->devnum);
+ cldev = device_create_drvdata(usb_classdev_class, &dev->dev,
+ dev->dev.devt, NULL, "usbdev%d.%d",
+ dev->bus->busnum, dev->devnum);
if (IS_ERR(cldev))
return PTR_ERR(cldev);
dev->usb_classdev = cldev;
@@ -1792,6 +1792,11 @@ int __init usb_devio_init(void)
usb_classdev_class = NULL;
goto out;
}
+ /* devices of this class shadow the major:minor of their parent
+ * device, so clear ->dev_kobj to prevent adding duplicate entries
+ * to /sys/dev
+ */
+ usb_classdev_class->dev_kobj = NULL;
usb_register_notify(&usbdev_nb);
#endif
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 913fb866789..6b1b229e38c 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -196,8 +196,9 @@ 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);
+ intf->usb_dev = device_create_drvdata(usb_class->class, &intf->dev,
+ MKDEV(USB_MAJOR, minor), NULL,
+ "%s", temp);
if (IS_ERR(intf->usb_dev)) {
down_write(&minor_rwsem);
usb_minors[intf->minor] = NULL;
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
index a973f2a50fb..c65d6229589 100644
--- a/drivers/usb/gadget/at91_udc.h
+++ b/drivers/usb/gadget/at91_udc.h
@@ -171,7 +171,7 @@ struct at91_request {
#endif
#define ERR(stuff...) pr_err("udc: " stuff)
-#define WARN(stuff...) pr_warning("udc: " stuff)
+#define WARNING(stuff...) pr_warning("udc: " stuff)
#define INFO(stuff...) pr_info("udc: " stuff)
#define DBG(stuff...) pr_debug("udc: " stuff)
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c
index d490d028950..a39a4b940c3 100644
--- a/drivers/usb/gadget/cdc2.c
+++ b/drivers/usb/gadget/cdc2.c
@@ -170,7 +170,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
* but if the controller isn't recognized at all then
* that assumption is a bit more likely to be wrong.
*/
- WARN(cdev, "controller '%s' not recognized; trying %s\n",
+ WARNING(cdev, "controller '%s' not recognized; trying %s\n",
gadget->name,
cdc_config_driver.label);
device_desc.bcdDevice =
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index d7aaaa29b1e..bcac2e68660 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -293,7 +293,7 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
* but if the controller isn't recognized at all then
* that assumption is a bit more likely to be wrong.
*/
- WARN(cdev, "controller '%s' not recognized; trying %s\n",
+ WARNING(cdev, "controller '%s' not recognized; trying %s\n",
gadget->name,
eth_config_driver.label);
device_desc.bcdDevice =
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 15c24edbb61..ea2c31d1808 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -308,7 +308,7 @@ MODULE_LICENSE("Dual BSD/GPL");
dev_vdbg(&(d)->gadget->dev , fmt , ## args)
#define ERROR(d, fmt, args...) \
dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARN(d, fmt, args...) \
+#define WARNING(d, fmt, args...) \
dev_warn(&(d)->gadget->dev , fmt , ## args)
#define INFO(d, fmt, args...) \
dev_info(&(d)->gadget->dev , fmt , ## args)
@@ -1091,7 +1091,7 @@ static int ep0_queue(struct fsg_dev *fsg)
if (rc != 0 && rc != -ESHUTDOWN) {
/* We can't do much more than wait for a reset */
- WARN(fsg, "error in submission: %s --> %d\n",
+ WARNING(fsg, "error in submission: %s --> %d\n",
fsg->ep0->name, rc);
}
return rc;
@@ -1227,7 +1227,7 @@ static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
/* Save the command for later */
if (fsg->cbbuf_cmnd_size)
- WARN(fsg, "CB[I] overwriting previous command\n");
+ WARNING(fsg, "CB[I] overwriting previous command\n");
fsg->cbbuf_cmnd_size = req->actual;
memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
@@ -1506,7 +1506,7 @@ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
* submissions if DMA is enabled. */
if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP &&
req->length == 0))
- WARN(fsg, "error in submission: %s --> %d\n",
+ WARNING(fsg, "error in submission: %s --> %d\n",
ep->name, rc);
}
}
@@ -2294,7 +2294,7 @@ static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
VDBG(fsg, "delayed bulk-in endpoint halt\n");
while (rc != 0) {
if (rc != -EAGAIN) {
- WARN(fsg, "usb_ep_set_halt -> %d\n", rc);
+ WARNING(fsg, "usb_ep_set_halt -> %d\n", rc);
rc = 0;
break;
}
@@ -2317,7 +2317,7 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
VDBG(fsg, "delayed bulk-in endpoint wedge\n");
while (rc != 0) {
if (rc != -EAGAIN) {
- WARN(fsg, "usb_ep_set_wedge -> %d\n", rc);
+ WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc);
rc = 0;
break;
}
@@ -3755,7 +3755,7 @@ static int __init check_parameters(struct fsg_dev *fsg)
if (gcnum >= 0)
mod_data.release = 0x0300 + gcnum;
else {
- WARN(fsg, "controller '%s' not recognized\n",
+ WARNING(fsg, "controller '%s' not recognized\n",
fsg->gadget->name);
mod_data.release = 0x0399;
}
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
index 1695382f30f..1cfccf102a2 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.c
+++ b/drivers/usb/gadget/fsl_usb2_udc.c
@@ -1538,7 +1538,7 @@ static void dtd_complete_irq(struct fsl_udc *udc)
/* If the ep is configured */
if (curr_ep->name == NULL) {
- WARN("Invalid EP?");
+ WARNING("Invalid EP?");
continue;
}
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index 98b1483ef6a..6131752a38b 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -552,7 +552,7 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length)
#endif
#define ERR(stuff...) pr_err("udc: " stuff)
-#define WARN(stuff...) pr_warning("udc: " stuff)
+#define WARNING(stuff...) pr_warning("udc: " stuff)
#define INFO(stuff...) pr_info("udc: " stuff)
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index 7f4d4828e3a..ea8651e3da1 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -138,8 +138,6 @@ static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req);
dev_vdbg(&(d)->gadget->dev , fmt , ## args)
#define ERROR(d, fmt, args...) \
dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARN(d, fmt, args...) \
- dev_warn(&(d)->gadget->dev , fmt , ## args)
#define INFO(d, fmt, args...) \
dev_info(&(d)->gadget->dev , fmt , ## args)
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 48f1c63b701..60aa04847b1 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1768,7 +1768,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* usb_gadget_driver_{register,unregister}() must change.
*/
if (the_controller) {
- WARN(dev, "ignoring %s\n", pci_name(pdev));
+ WARNING(dev, "ignoring %s\n", pci_name(pdev));
return -EBUSY;
}
if (!pdev->irq) {
diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h
index bc4eb1e0b50..566cb231905 100644
--- a/drivers/usb/gadget/goku_udc.h
+++ b/drivers/usb/gadget/goku_udc.h
@@ -285,7 +285,7 @@ struct goku_udc {
#define ERROR(dev,fmt,args...) \
xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARN(dev,fmt,args...) \
+#define WARNING(dev,fmt,args...) \
xprintk(dev , KERN_WARNING , fmt , ## args)
#define INFO(dev,fmt,args...) \
xprintk(dev , KERN_INFO , fmt , ## args)
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 04692d59fc1..f4585d3e90d 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -262,8 +262,6 @@ static const char *CHIP;
#define ERROR(dev,fmt,args...) \
xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARN(dev,fmt,args...) \
- xprintk(dev , KERN_WARNING , fmt , ## args)
#define INFO(dev,fmt,args...) \
xprintk(dev , KERN_INFO , fmt , ## args)
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index b67ab677af7..5cfb5ebf388 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -1007,7 +1007,7 @@ static void scan_dma_completions (struct net2280_ep *ep)
* 0122, and 0124; not all cases trigger the warning.
*/
if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) {
- WARN (ep->dev, "%s lost packet sync!\n",
+ WARNING (ep->dev, "%s lost packet sync!\n",
ep->ep.name);
req->req.status = -EOVERFLOW;
} else if ((tmp = readl (&ep->regs->ep_avail)) != 0) {
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
index 1f2af398a9a..81a71dbdc2c 100644
--- a/drivers/usb/gadget/net2280.h
+++ b/drivers/usb/gadget/net2280.h
@@ -272,7 +272,7 @@ static inline void net2280_led_shutdown (struct net2280 *dev)
#define ERROR(dev,fmt,args...) \
xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARN(dev,fmt,args...) \
+#define WARNING(dev,fmt,args...) \
xprintk(dev , KERN_WARNING , fmt , ## args)
#define INFO(dev,fmt,args...) \
xprintk(dev , KERN_INFO , fmt , ## args)
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 4b79a8509e8..395bd184448 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -1120,7 +1120,7 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value)
status = -EINVAL;
else if (value) {
if (ep->udc->ep0_set_config) {
- WARN("error changing config?\n");
+ WARNING("error changing config?\n");
omap_writew(UDC_CLR_CFG, UDC_SYSCON2);
}
omap_writew(UDC_STALL_CMD, UDC_SYSCON2);
@@ -1764,7 +1764,7 @@ do_stall:
u.r.bRequestType, u.r.bRequest, status);
if (udc->ep0_set_config) {
if (udc->ep0_reset_config)
- WARN("error resetting config?\n");
+ WARNING("error resetting config?\n");
else
omap_writew(UDC_CLR_CFG, UDC_SYSCON2);
}
@@ -3076,7 +3076,7 @@ static int omap_udc_suspend(struct platform_device *dev, pm_message_t message)
* which would prevent entry to deep sleep...
*/
if ((devstat & UDC_ATT) != 0 && (devstat & UDC_SUS) == 0) {
- WARN("session active; suspend requires disconnect\n");
+ WARNING("session active; suspend requires disconnect\n");
omap_pullup(&udc->gadget, 0);
}
diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h
index 8522bbb1227..29edc51b6b2 100644
--- a/drivers/usb/gadget/omap_udc.h
+++ b/drivers/usb/gadget/omap_udc.h
@@ -188,7 +188,7 @@ struct omap_udc {
#endif
#define ERR(stuff...) pr_err("udc: " stuff)
-#define WARN(stuff...) pr_warning("udc: " stuff)
+#define WARNING(stuff...) pr_warning("udc: " stuff)
#define INFO(stuff...) pr_info("udc: " stuff)
#define DBG(stuff...) pr_debug("udc: " stuff)
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 9caaec3ae9a..e0090085b78 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -179,7 +179,7 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR);
#define ERROR(dev, fmt, args...) \
xprintk(dev, KERN_ERR, fmt, ## args)
-#define WARN(dev, fmt, args...) \
+#define WARNING(dev, fmt, args...) \
xprintk(dev, KERN_WARNING, fmt, ## args)
#define INFO(dev, fmt, args...) \
xprintk(dev, KERN_INFO, fmt, ## args)
@@ -1360,8 +1360,8 @@ printer_bind(struct usb_gadget *gadget)
/* Setup the sysfs files for the printer gadget. */
- dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno,
- "g_printer");
+ dev->pdev = device_create_drvdata(usb_gadget_class, NULL,
+ g_printer_devno, NULL, "g_printer");
if (IS_ERR(dev->pdev)) {
ERROR(dev, "Failed to create device: g_printer\n");
goto fail;
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index fbd6289977c..7e6725d8997 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -152,9 +152,10 @@ static int is_vbus_present(void)
static void pullup_off(void)
{
struct pxa2xx_udc_mach_info *mach = the_controller->mach;
+ int off_level = mach->gpio_pullup_inverted;
if (mach->gpio_pullup)
- gpio_set_value(mach->gpio_pullup, 0);
+ gpio_set_value(mach->gpio_pullup, off_level);
else if (mach->udc_command)
mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
}
@@ -162,9 +163,10 @@ static void pullup_off(void)
static void pullup_on(void)
{
struct pxa2xx_udc_mach_info *mach = the_controller->mach;
+ int on_level = !mach->gpio_pullup_inverted;
if (mach->gpio_pullup)
- gpio_set_value(mach->gpio_pullup, 1);
+ gpio_set_value(mach->gpio_pullup, on_level);
else if (mach->udc_command)
mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
}
@@ -340,7 +342,7 @@ pxa25x_ep_free_request (struct usb_ep *_ep, struct usb_request *_req)
struct pxa25x_request *req;
req = container_of (_req, struct pxa25x_request, req);
- WARN_ON (!list_empty (&req->queue));
+ WARN_ON(!list_empty (&req->queue));
kfree(req);
}
@@ -1554,7 +1556,7 @@ config_change:
* tell us about config change events,
* so later ones may fail...
*/
- WARN("config change %02x fail %d?\n",
+ WARNING("config change %02x fail %d?\n",
u.r.bRequest, i);
return;
/* TODO experiment: if has_cfr,
@@ -2328,7 +2330,7 @@ static int pxa25x_udc_suspend(struct platform_device *dev, pm_message_t state)
unsigned long flags;
if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
- WARN("USB host won't detect disconnect!\n");
+ WARNING("USB host won't detect disconnect!\n");
udc->suspended = 1;
local_irq_save(flags);
diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/pxa25x_udc.h
index 4d11ece7c95..c8a13215e02 100644
--- a/drivers/usb/gadget/pxa25x_udc.h
+++ b/drivers/usb/gadget/pxa25x_udc.h
@@ -259,7 +259,7 @@ dump_state(struct pxa25x_udc *dev)
#define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0)
#define ERR(stuff...) pr_err("udc: " stuff)
-#define WARN(stuff...) pr_warning("udc: " stuff)
+#define WARNING(stuff...) pr_warning("udc: " stuff)
#define INFO(stuff...) pr_info("udc: " stuff)
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 5458f43a866..3791e627190 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -116,7 +116,6 @@ static inline int qlen(struct usb_gadget *gadget)
#undef DBG
#undef VDBG
#undef ERROR
-#undef WARN
#undef INFO
#define xprintk(d, level, fmt, args...) \
@@ -140,8 +139,6 @@ static inline int qlen(struct usb_gadget *gadget)
#define ERROR(dev, fmt, args...) \
xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARN(dev, fmt, args...) \
- xprintk(dev , KERN_WARNING , fmt , ## args)
#define INFO(dev, fmt, args...) \
xprintk(dev , KERN_INFO , fmt , ## args)
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 31178e10cbb..ce1ca0ba051 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -882,7 +882,7 @@ static void isp116x_endpoint_disable(struct usb_hcd *hcd,
for (i = 0; i < 100 && !list_empty(&hep->urb_list); i++)
msleep(3);
if (!list_empty(&hep->urb_list))
- WARN("ep %p not empty?\n", ep);
+ WARNING("ep %p not empty?\n", ep);
kfree(ep);
hep->hcpriv = NULL;
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h
index 595b90a9984..aa211bafcff 100644
--- a/drivers/usb/host/isp116x.h
+++ b/drivers/usb/host/isp116x.h
@@ -338,7 +338,7 @@ struct isp116x_ep {
#endif
#define ERR(stuff...) printk(KERN_ERR "116x: " stuff)
-#define WARN(stuff...) printk(KERN_WARNING "116x: " stuff)
+#define WARNING(stuff...) printk(KERN_WARNING "116x: " stuff)
#define INFO(stuff...) printk(KERN_INFO "116x: " stuff)
/* ------------------------------------------------- */
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 340d72da554..8a74bbb57d0 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1026,7 +1026,7 @@ sl811h_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
if (!list_empty(&hep->urb_list))
msleep(3);
if (!list_empty(&hep->urb_list))
- WARN("ep %p not empty?\n", ep);
+ WARNING("ep %p not empty?\n", ep);
kfree(ep);
hep->hcpriv = NULL;
diff --git a/drivers/usb/host/sl811.h b/drivers/usb/host/sl811.h
index 7690d98e42a..b6b8c1f233d 100644
--- a/drivers/usb/host/sl811.h
+++ b/drivers/usb/host/sl811.h
@@ -261,6 +261,6 @@ sl811_read_buf(struct sl811 *sl811, int addr, void *buf, size_t count)
#endif
#define ERR(stuff...) printk(KERN_ERR "sl811: " stuff)
-#define WARN(stuff...) printk(KERN_WARNING "sl811: " stuff)
+#define WARNING(stuff...) printk(KERN_WARNING "sl811: " stuff)
#define INFO(stuff...) printk(KERN_INFO "sl811: " stuff)
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 054dedd2812..b358c4e1cf2 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -81,7 +81,7 @@ static struct usb_device *testdev_to_usbdev (struct usbtest_dev *test)
#define ERROR(tdev, fmt, args...) \
dev_err(&(tdev)->intf->dev , fmt , ## args)
-#define WARN(tdev, fmt, args...) \
+#define WARNING(tdev, fmt, args...) \
dev_warn(&(tdev)->intf->dev , fmt , ## args)
/*-------------------------------------------------------------------------*/
@@ -1946,7 +1946,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
status = get_endpoints (dev, intf);
if (status < 0) {
- WARN(dev, "couldn't get endpoints, %d\n",
+ WARNING(dev, "couldn't get endpoints, %d\n",
status);
return status;
}
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index 293a46247c3..6566fc0a322 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -1162,8 +1162,9 @@ int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus)
if (minor >= MON_BIN_MAX_MINOR)
return 0;
- dev = device_create(mon_bin_class, ubus? ubus->controller: NULL,
- MKDEV(MAJOR(mon_bin_dev0), minor), "usbmon%d", minor);
+ dev = device_create_drvdata(mon_bin_class, ubus? ubus->controller: NULL,
+ MKDEV(MAJOR(mon_bin_dev0), minor), NULL,
+ "usbmon%d", minor);
if (IS_ERR(dev))
return 0;
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index db6f97a93c0..79ea98c66fa 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -272,7 +272,7 @@ static void aircable_read(struct work_struct *work)
* 64 bytes, to ensure I do not get throttled.
* Ask USB mailing list for better aproach.
*/
- tty = port->tty;
+ tty = port->port.tty;
if (!tty) {
schedule_work(&priv->rx_work);
@@ -378,13 +378,14 @@ static void aircable_shutdown(struct usb_serial *serial)
}
}
-static int aircable_write_room(struct usb_serial_port *port)
+static int aircable_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct aircable_private *priv = usb_get_serial_port_data(port);
return serial_buf_data_avail(priv->tx_buf);
}
-static int aircable_write(struct usb_serial_port *port,
+static int aircable_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *source, int count)
{
struct aircable_private *priv = usb_get_serial_port_data(port);
@@ -466,7 +467,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
if (status) {
dbg("%s - urb status = %d", __func__, status);
- if (!port->open_count) {
+ if (!port->port.count) {
dbg("%s - port is closed, exiting.", __func__);
return;
}
@@ -494,7 +495,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, urb->transfer_buffer);
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
if (urb->actual_length <= 2) {
/* This is an incomplete package */
@@ -528,7 +529,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
}
/* Schedule the next read _if_ we are still open */
- if (port->open_count) {
+ if (port->port.count) {
usb_fill_bulk_urb(port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
@@ -547,8 +548,9 @@ static void aircable_read_bulk_callback(struct urb *urb)
}
/* Based on ftdi_sio.c throttle */
-static void aircable_throttle(struct usb_serial_port *port)
+static void aircable_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct aircable_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -560,8 +562,9 @@ static void aircable_throttle(struct usb_serial_port *port)
}
/* Based on ftdi_sio.c unthrottle */
-static void aircable_unthrottle(struct usb_serial_port *port)
+static void aircable_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct aircable_private *priv = usb_get_serial_port_data(port);
int actually_throttled;
unsigned long flags;
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 77895c8f8f3..aec61880f36 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -158,12 +158,13 @@ cleanup:
return -ENOMEM;
}
-static void ark3116_set_termios(struct usb_serial_port *port,
+static void ark3116_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port,
struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct ark3116_private *priv = usb_get_serial_port_data(port);
- struct ktermios *termios = port->tty->termios;
+ struct ktermios *termios = tty->termios;
unsigned int cflag = termios->c_cflag;
unsigned long flags;
int baud;
@@ -177,8 +178,8 @@ static void ark3116_set_termios(struct usb_serial_port *port,
spin_lock_irqsave(&priv->lock, flags);
if (!priv->termios_initialized) {
- *(port->tty->termios) = tty_std_termios;
- port->tty->termios->c_cflag = B9600 | CS8
+ *termios = tty_std_termios;
+ termios->c_cflag = B9600 | CS8
| CREAD | HUPCL | CLOCAL;
termios->c_ispeed = 9600;
termios->c_ospeed = 9600;
@@ -192,7 +193,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
buf = kmalloc(1, GFP_KERNEL);
if (!buf) {
dbg("error kmalloc");
- *port->tty->termios = *old_termios;
+ *termios = *old_termios;
return;
}
@@ -243,7 +244,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
}
/* set baudrate */
- baud = tty_get_baud_rate(port->tty);
+ baud = tty_get_baud_rate(tty);
switch (baud) {
case 75:
@@ -262,11 +263,11 @@ static void ark3116_set_termios(struct usb_serial_port *port,
case 230400:
case 460800:
/* Report the resulting rate back to the caller */
- tty_encode_baud_rate(port->tty, baud, baud);
+ tty_encode_baud_rate(tty, baud, baud);
break;
/* set 9600 as default (if given baudrate is invalid for example) */
default:
- tty_encode_baud_rate(port->tty, 9600, 9600);
+ tty_encode_baud_rate(tty, 9600, 9600);
case 0:
baud = 9600;
}
@@ -317,7 +318,8 @@ static void ark3116_set_termios(struct usb_serial_port *port,
return;
}
-static int ark3116_open(struct usb_serial_port *port, struct file *filp)
+static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
@@ -332,7 +334,7 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp)
return -ENOMEM;
}
- result = usb_serial_generic_open(port, filp);
+ result = usb_serial_generic_open(tty, port, filp);
if (result)
goto err_out;
@@ -362,8 +364,8 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp)
ARK3116_RCV(serial, 124, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf);
/* initialise termios */
- if (port->tty)
- ark3116_set_termios(port, &tmp_termios);
+ if (tty)
+ ark3116_set_termios(tty, port, &tmp_termios);
err_out:
kfree(buf);
@@ -371,9 +373,10 @@ err_out:
return result;
}
-static int ark3116_ioctl(struct usb_serial_port *port, struct file *file,
+static int ark3116_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct serial_struct serstruct;
void __user *user_arg = (void __user *)arg;
@@ -403,8 +406,9 @@ static int ark3116_ioctl(struct usb_serial_port *port, struct file *file,
return -ENOIOCTLCMD;
}
-static int ark3116_tiocmget(struct usb_serial_port *port, struct file *file)
+static int ark3116_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
char *buf;
char temp;
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 0a322fc53d6..2ebe06c3405 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -7,13 +7,14 @@
* This program is largely derived from work by the linux-usb group
* and associated source files. Please see the usb/serial files for
* individual credits and copyrights.
- *
+ *
* 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.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
* TODO:
* -- Add true modem contol line query capability. Currently we track the
@@ -28,7 +29,8 @@
* compressed all the differnent device entries into 1.
*
* 30-May-2001 gkh
- * switched from using spinlock to a semaphore, which fixes lots of problems.
+ * switched from using spinlock to a semaphore, which fixes lots of
+ * problems.
*
* 08-Apr-2001 gb
* - Identify version on module load.
@@ -41,7 +43,7 @@
* - Added support for the old Belkin and Peracom devices.
* - Made the port able to be opened multiple times.
* - Added some defaults incase the line settings are things these devices
- * can't support.
+ * can't support.
*
* 18-Oct-2000 William Greathouse
* Released into the wild (linux-usb-devel)
@@ -72,7 +74,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include "belkin_sa.h"
@@ -87,16 +89,19 @@ static int debug;
#define DRIVER_DESC "USB Belkin Serial converter driver"
/* function prototypes for a Belkin USB Serial Adapter F5U103 */
-static int belkin_sa_startup (struct usb_serial *serial);
-static void belkin_sa_shutdown (struct usb_serial *serial);
-static int belkin_sa_open (struct usb_serial_port *port, struct file *filp);
-static void belkin_sa_close (struct usb_serial_port *port, struct file *filp);
-static void belkin_sa_read_int_callback (struct urb *urb);
-static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios * old);
-static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void belkin_sa_break_ctl (struct usb_serial_port *port, int break_state );
-static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file);
-static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
+static int belkin_sa_startup(struct usb_serial *serial);
+static void belkin_sa_shutdown(struct usb_serial *serial);
+static int belkin_sa_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void belkin_sa_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void belkin_sa_read_int_callback(struct urb *urb);
+static void belkin_sa_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios * old);
+static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state);
+static int belkin_sa_tiocmget(struct tty_struct *tty, struct file *file);
+static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
static struct usb_device_id id_table_combined [] = {
@@ -106,10 +111,10 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(GOHUBS_VID, GOHUBS_PID) },
{ USB_DEVICE(GOHUBS_VID, HANDYLINK_PID) },
{ USB_DEVICE(BELKIN_DOCKSTATION_VID, BELKIN_DOCKSTATION_PID) },
- { } /* Terminating entry */
+ { } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver belkin_driver = {
.name = "belkin",
@@ -131,8 +136,8 @@ static struct usb_serial_driver belkin_device = {
.num_ports = 1,
.open = belkin_sa_open,
.close = belkin_sa_close,
- .read_int_callback = belkin_sa_read_int_callback, /* How we get the status info */
- .ioctl = belkin_sa_ioctl,
+ .read_int_callback = belkin_sa_read_int_callback,
+ /* How we get the status info */
.set_termios = belkin_sa_set_termios,
.break_ctl = belkin_sa_break_ctl,
.tiocmget = belkin_sa_tiocmget,
@@ -160,12 +165,12 @@ struct belkin_sa_private {
#define WDR_TIMEOUT 5000 /* default urb timeout */
/* assumes that struct usb_serial *serial is available */
-#define BSA_USB_CMD(c,v) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), \
+#define BSA_USB_CMD(c, v) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), \
(c), BELKIN_SA_SET_REQUEST_TYPE, \
(v), 0, NULL, 0, WDR_TIMEOUT)
/* do some startup allocations not currently performed by usb_serial_probe() */
-static int belkin_sa_startup (struct usb_serial *serial)
+static int belkin_sa_startup(struct usb_serial *serial)
{
struct usb_device *dev = serial->dev;
struct belkin_sa_private *priv;
@@ -173,32 +178,35 @@ static int belkin_sa_startup (struct usb_serial *serial)
/* allocate the private data structure */
priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL);
if (!priv)
- return (-1); /* error */
+ return -1; /* error */
/* set initial values for control structures */
spin_lock_init(&priv->lock);
priv->control_state = 0;
priv->last_lsr = 0;
priv->last_msr = 0;
/* see comments at top of file */
- priv->bad_flow_control = (le16_to_cpu(dev->descriptor.bcdDevice) <= 0x0206) ? 1 : 0;
- info("bcdDevice: %04x, bfc: %d", le16_to_cpu(dev->descriptor.bcdDevice), priv->bad_flow_control);
+ priv->bad_flow_control =
+ (le16_to_cpu(dev->descriptor.bcdDevice) <= 0x0206) ? 1 : 0;
+ info("bcdDevice: %04x, bfc: %d",
+ le16_to_cpu(dev->descriptor.bcdDevice),
+ priv->bad_flow_control);
init_waitqueue_head(&serial->port[0]->write_wait);
usb_set_serial_port_data(serial->port[0], priv);
-
- return (0);
+
+ return 0;
}
-static void belkin_sa_shutdown (struct usb_serial *serial)
+static void belkin_sa_shutdown(struct usb_serial *serial)
{
struct belkin_sa_private *priv;
int i;
-
- dbg ("%s", __func__);
+
+ dbg("%s", __func__);
/* stop reads and writes on all ports */
- for (i=0; i < serial->num_ports; ++i) {
+ for (i = 0; i < serial->num_ports; ++i) {
/* My special items, the standard routines free my urbs */
priv = usb_get_serial_port_data(serial->port[i]);
kfree(priv);
@@ -206,7 +214,8 @@ static void belkin_sa_shutdown (struct usb_serial *serial)
}
-static int belkin_sa_open (struct usb_serial_port *port, struct file *filp)
+static int belkin_sa_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
int retval = 0;
@@ -235,7 +244,8 @@ exit:
} /* belkin_sa_open */
-static void belkin_sa_close (struct usb_serial_port *port, struct file *filp)
+static void belkin_sa_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
dbg("%s port %d", __func__, port->number);
@@ -246,7 +256,7 @@ static void belkin_sa_close (struct usb_serial_port *port, struct file *filp)
} /* belkin_sa_close */
-static void belkin_sa_read_int_callback (struct urb *urb)
+static void belkin_sa_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct belkin_sa_private *priv;
@@ -272,7 +282,8 @@ static void belkin_sa_read_int_callback (struct urb *urb)
goto exit;
}
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
/* Handle known interrupt data */
/* ignore data[0] and data[1] */
@@ -280,7 +291,7 @@ static void belkin_sa_read_int_callback (struct urb *urb)
priv = usb_get_serial_port_data(port);
spin_lock_irqsave(&priv->lock, flags);
priv->last_msr = data[BELKIN_SA_MSR_INDEX];
-
+
/* Record Control Line states */
if (priv->last_msr & BELKIN_SA_MSR_DSR)
priv->control_state |= TIOCM_DSR;
@@ -311,7 +322,7 @@ static void belkin_sa_read_int_callback (struct urb *urb)
* to look in to this before committing any code.
*/
if (priv->last_lsr & BELKIN_SA_LSR_ERR) {
- tty = port->tty;
+ tty = port->port.tty;
/* Overrun Error */
if (priv->last_lsr & BELKIN_SA_LSR_OE) {
}
@@ -328,13 +339,14 @@ static void belkin_sa_read_int_callback (struct urb *urb)
#endif
spin_unlock_irqrestore(&priv->lock, flags);
exit:
- retval = usb_submit_urb (urb, GFP_ATOMIC);
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- err ("%s - usb_submit_urb failed with result %d",
+ err("%s - usb_submit_urb failed with result %d",
__func__, retval);
}
-static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void belkin_sa_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct belkin_sa_private *priv = usb_get_serial_port_data(port);
@@ -347,8 +359,8 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
unsigned long control_state;
int bad_flow_control;
speed_t baud;
- struct ktermios *termios = port->tty->termios;
-
+ struct ktermios *termios = tty->termios;
+
iflag = termios->c_iflag;
cflag = termios->c_cflag;
@@ -359,25 +371,26 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
control_state = priv->control_state;
bad_flow_control = priv->bad_flow_control;
spin_unlock_irqrestore(&priv->lock, flags);
-
+
old_iflag = old_termios->c_iflag;
old_cflag = old_termios->c_cflag;
/* Set the baud rate */
if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
/* reassert DTR and (maybe) RTS on transition from B0 */
- if( (old_cflag&CBAUD) == B0 ) {
+ if ((old_cflag & CBAUD) == B0) {
control_state |= (TIOCM_DTR|TIOCM_RTS);
if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 1) < 0)
err("Set DTR error");
/* don't set RTS if using hardware flow control */
if (!(old_cflag & CRTSCTS))
- if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 1) < 0)
+ if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST
+ , 1) < 0)
err("Set RTS error");
}
}
- baud = tty_get_baud_rate(port->tty);
+ baud = tty_get_baud_rate(tty);
if (baud) {
urb_value = BELKIN_SA_BAUD(baud);
/* Clip to maximum speed */
@@ -387,12 +400,13 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
baud = BELKIN_SA_BAUD(urb_value);
/* Report the actual baud rate back to the caller */
- tty_encode_baud_rate(port->tty, baud, baud);
+ tty_encode_baud_rate(tty, baud, baud);
if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0)
err("Set baudrate error");
} else {
/* Disable flow control */
- if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, BELKIN_SA_FLOW_NONE) < 0)
+ if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST,
+ BELKIN_SA_FLOW_NONE) < 0)
err("Disable flowcontrol error");
/* Drop RTS and DTR */
control_state &= ~(TIOCM_DTR | TIOCM_RTS);
@@ -403,9 +417,10 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
}
/* set the parity */
- if( (cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD)) ) {
+ if ((cflag ^ old_cflag) & (PARENB | PARODD)) {
if (cflag & PARENB)
- urb_value = (cflag & PARODD) ? BELKIN_SA_PARITY_ODD : BELKIN_SA_PARITY_EVEN;
+ urb_value = (cflag & PARODD) ? BELKIN_SA_PARITY_ODD
+ : BELKIN_SA_PARITY_EVEN;
else
urb_value = BELKIN_SA_PARITY_NONE;
if (BSA_USB_CMD(BELKIN_SA_SET_PARITY_REQUEST, urb_value) < 0)
@@ -413,31 +428,40 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
}
/* set the number of data bits */
- if( (cflag&CSIZE) != (old_cflag&CSIZE) ) {
+ if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
switch (cflag & CSIZE) {
- case CS5: urb_value = BELKIN_SA_DATA_BITS(5); break;
- case CS6: urb_value = BELKIN_SA_DATA_BITS(6); break;
- case CS7: urb_value = BELKIN_SA_DATA_BITS(7); break;
- case CS8: urb_value = BELKIN_SA_DATA_BITS(8); break;
- default: dbg("CSIZE was not CS5-CS8, using default of 8");
- urb_value = BELKIN_SA_DATA_BITS(8);
- break;
+ case CS5:
+ urb_value = BELKIN_SA_DATA_BITS(5);
+ break;
+ case CS6:
+ urb_value = BELKIN_SA_DATA_BITS(6);
+ break;
+ case CS7:
+ urb_value = BELKIN_SA_DATA_BITS(7);
+ break;
+ case CS8:
+ urb_value = BELKIN_SA_DATA_BITS(8);
+ break;
+ default: dbg("CSIZE was not CS5-CS8, using default of 8");
+ urb_value = BELKIN_SA_DATA_BITS(8);
+ break;
}
if (BSA_USB_CMD(BELKIN_SA_SET_DATA_BITS_REQUEST, urb_value) < 0)
err("Set data bits error");
}
/* set the number of stop bits */
- if( (cflag&CSTOPB) != (old_cflag&CSTOPB) ) {
- urb_value = (cflag & CSTOPB) ? BELKIN_SA_STOP_BITS(2) : BELKIN_SA_STOP_BITS(1);
- if (BSA_USB_CMD(BELKIN_SA_SET_STOP_BITS_REQUEST, urb_value) < 0)
+ if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
+ urb_value = (cflag & CSTOPB) ? BELKIN_SA_STOP_BITS(2)
+ : BELKIN_SA_STOP_BITS(1);
+ if (BSA_USB_CMD(BELKIN_SA_SET_STOP_BITS_REQUEST,
+ urb_value) < 0)
err("Set stop bits error");
}
/* Set flow control */
- if( (iflag&IXOFF) != (old_iflag&IXOFF)
- || (iflag&IXON) != (old_iflag&IXON)
- || (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) {
+ if (((iflag ^ old_iflag) & (IXOFF | IXON)) ||
+ ((cflag ^ old_cflag) & CRTSCTS)) {
urb_value = 0;
if ((iflag & IXOFF) || (iflag & IXON))
urb_value |= (BELKIN_SA_FLOW_OXON | BELKIN_SA_FLOW_IXON);
@@ -463,8 +487,9 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
} /* belkin_sa_set_termios */
-static void belkin_sa_break_ctl( struct usb_serial_port *port, int break_state )
+static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
if (BSA_USB_CMD(BELKIN_SA_SET_BREAK_REQUEST, break_state ? 1 : 0) < 0)
@@ -472,12 +497,13 @@ static void belkin_sa_break_ctl( struct usb_serial_port *port, int break_state )
}
-static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file)
+static int belkin_sa_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct belkin_sa_private *priv = usb_get_serial_port_data(port);
unsigned long control_state;
unsigned long flags;
-
+
dbg("%s", __func__);
spin_lock_irqsave(&priv->lock, flags);
@@ -488,9 +514,10 @@ static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file)
}
-static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file,
+static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
struct belkin_sa_private *priv = usb_get_serial_port_data(port);
unsigned long control_state;
@@ -498,7 +525,7 @@ static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file,
int retval;
int rts = 0;
int dtr = 0;
-
+
dbg("%s", __func__);
spin_lock_irqsave(&priv->lock, flags);
@@ -540,29 +567,7 @@ exit:
}
-static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
-{
- switch (cmd) {
- case TIOCMIWAIT:
- /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
- /* TODO */
- return( 0 );
-
- case TIOCGICOUNT:
- /* return count of modemline transitions */
- /* TODO */
- return 0;
-
- default:
- dbg("belkin_sa_ioctl arg not supported - 0x%04x",cmd);
- return(-ENOIOCTLCMD);
- break;
- }
- return 0;
-} /* belkin_sa_ioctl */
-
-
-static int __init belkin_sa_init (void)
+static int __init belkin_sa_init(void)
{
int retval;
retval = usb_serial_register(&belkin_device);
@@ -582,17 +587,17 @@ failed_usb_serial_register:
static void __exit belkin_sa_exit (void)
{
- usb_deregister (&belkin_driver);
- usb_serial_deregister (&belkin_device);
+ usb_deregister(&belkin_driver);
+ usb_serial_deregister(&belkin_device);
}
-module_init (belkin_sa_init);
-module_exit (belkin_sa_exit);
+module_init(belkin_sa_init);
+module_exit(belkin_sa_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_VERSION( DRIVER_VERSION );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/belkin_sa.h b/drivers/usb/serial/belkin_sa.h
index 9116b92f462..c66a6730d38 100644
--- a/drivers/usb/serial/belkin_sa.h
+++ b/drivers/usb/serial/belkin_sa.h
@@ -7,13 +7,14 @@
* This program is largely derived from work by the linux-usb group
* and associated source files. Please see the usb/serial files for
* individual credits and copyrights.
- *
+ *
* 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.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
* 12-Mar-2001 gkh
* Added GoHubs GO-COM232 device id.
@@ -27,7 +28,7 @@
* adapter, so pardon any stupid mistakes. All of the information
* I am using to write this driver was acquired by using a modified
* UsbSnoop on Windows2000.
- *
+ *
*/
#ifndef __LINUX_USB_SERIAL_BSA_H
@@ -96,20 +97,20 @@
/*
* It seems that the interrupt pipe is closely modelled after the
- * 16550 register layout. This is probably because the adapter can
+ * 16550 register layout. This is probably because the adapter can
* be used in a "DOS" environment to simulate a standard hardware port.
*/
-#define BELKIN_SA_LSR_INDEX 2 /* Line Status Register */
+#define BELKIN_SA_LSR_INDEX 2 /* Line Status Register */
#define BELKIN_SA_LSR_RDR 0x01 /* receive data ready */
#define BELKIN_SA_LSR_OE 0x02 /* overrun error */
#define BELKIN_SA_LSR_PE 0x04 /* parity error */
#define BELKIN_SA_LSR_FE 0x08 /* framing error */
#define BELKIN_SA_LSR_BI 0x10 /* break indicator */
-#define BELKIN_SA_LSR_THE 0x20 /* transmit holding register empty */
+#define BELKIN_SA_LSR_THE 0x20 /* tx holding register empty */
#define BELKIN_SA_LSR_TE 0x40 /* transmit register empty */
#define BELKIN_SA_LSR_ERR 0x80 /* OE | PE | FE | BI */
-#define BELKIN_SA_MSR_INDEX 3 /* Modem Status Register */
+#define BELKIN_SA_MSR_INDEX 3 /* Modem Status Register */
#define BELKIN_SA_MSR_DCTS 0x01 /* Delta CTS */
#define BELKIN_SA_MSR_DDSR 0x02 /* Delta DSR */
#define BELKIN_SA_MSR_DRI 0x04 /* Delta RI */
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 0b14aea8ebd..83bbb5bca2e 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -15,7 +15,8 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-static int usb_serial_device_match (struct device *dev, struct device_driver *drv)
+static int usb_serial_device_match(struct device *dev,
+ struct device_driver *drv)
{
struct usb_serial_driver *driver;
const struct usb_serial_port *port;
@@ -46,7 +47,7 @@ static ssize_t show_port_number(struct device *dev,
static DEVICE_ATTR(port_number, S_IRUGO, show_port_number, NULL);
-static int usb_serial_device_probe (struct device *dev)
+static int usb_serial_device_probe(struct device *dev)
{
struct usb_serial_driver *driver;
struct usb_serial_port *port;
@@ -66,7 +67,7 @@ static int usb_serial_device_probe (struct device *dev)
retval = -EIO;
goto exit;
}
- retval = driver->port_probe (port);
+ retval = driver->port_probe(port);
module_put(driver->driver.owner);
if (retval)
goto exit;
@@ -77,8 +78,8 @@ static int usb_serial_device_probe (struct device *dev)
goto exit;
minor = port->number;
- tty_register_device (usb_serial_tty_driver, minor, dev);
- dev_info(&port->serial->dev->dev,
+ tty_register_device(usb_serial_tty_driver, minor, dev);
+ dev_info(&port->serial->dev->dev,
"%s converter now attached to ttyUSB%d\n",
driver->description, minor);
@@ -86,7 +87,7 @@ exit:
return retval;
}
-static int usb_serial_device_remove (struct device *dev)
+static int usb_serial_device_remove(struct device *dev)
{
struct usb_serial_driver *driver;
struct usb_serial_port *port;
@@ -94,9 +95,8 @@ static int usb_serial_device_remove (struct device *dev)
int minor;
port = to_usb_serial_port(dev);
- if (!port) {
+ if (!port)
return -ENODEV;
- }
device_remove_file(&port->dev, &dev_attr_port_number);
@@ -107,12 +107,12 @@ static int usb_serial_device_remove (struct device *dev)
retval = -EIO;
goto exit;
}
- retval = driver->port_remove (port);
+ retval = driver->port_remove(port);
module_put(driver->driver.owner);
}
exit:
minor = port->number;
- tty_unregister_device (usb_serial_tty_driver, minor);
+ tty_unregister_device(usb_serial_tty_driver, minor);
dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",
driver->description, minor);
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 1f7c86bd829..f61e3ca6430 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -232,7 +232,8 @@ error: kfree(priv);
}
/* open this device, set default parameters */
-static int ch341_open(struct usb_serial_port *port, struct file *filp)
+static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
struct usb_serial *serial = port->serial;
struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]);
@@ -256,7 +257,7 @@ static int ch341_open(struct usb_serial_port *port, struct file *filp)
if (r)
goto out;
- r = usb_serial_generic_open(port, filp);
+ r = usb_serial_generic_open(tty, port, filp);
out: return r;
}
@@ -264,11 +265,10 @@ out: return r;
/* Old_termios contains the original termios settings and
* tty->termios contains the new setting to be used.
*/
-static void ch341_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void ch341_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct ch341_private *priv = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
unsigned baud_rate;
dbg("ch341_set_termios()");
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 201184c3fb8..7b74238ad1c 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -6,7 +6,7 @@
* 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.
- *
+ *
* Thanks to Randy Dunlap for the original version of this code.
*
*/
@@ -67,7 +67,7 @@ static int usb_console_setup(struct console *co, char *options)
struct tty_struct *tty = NULL;
struct ktermios *termios = NULL, dummy;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
if (options) {
baud = simple_strtoul(options, NULL, 10);
@@ -81,55 +81,27 @@ static int usb_console_setup(struct console *co, char *options)
if (*s)
doflow = (*s++ == 'r');
}
+
+ /* Sane default */
+ if (baud == 0)
+ baud = 9600;
- /* build a cflag setting */
- switch (baud) {
- case 1200:
- cflag |= B1200;
- break;
- case 2400:
- cflag |= B2400;
- break;
- case 4800:
- cflag |= B4800;
- break;
- case 19200:
- cflag |= B19200;
- break;
- case 38400:
- cflag |= B38400;
- break;
- case 57600:
- cflag |= B57600;
- break;
- case 115200:
- cflag |= B115200;
- break;
- case 9600:
- default:
- cflag |= B9600;
- /*
- * Set this to a sane value to prevent a divide error
- */
- baud = 9600;
- break;
- }
switch (bits) {
- case 7:
- cflag |= CS7;
- break;
- default:
- case 8:
- cflag |= CS8;
- break;
+ case 7:
+ cflag |= CS7;
+ break;
+ default:
+ case 8:
+ cflag |= CS8;
+ break;
}
switch (parity) {
- case 'o': case 'O':
- cflag |= PARODD;
- break;
- case 'e': case 'E':
- cflag |= PARENB;
- break;
+ case 'o': case 'O':
+ cflag |= PARODD;
+ break;
+ case 'e': case 'E':
+ cflag |= PARENB;
+ break;
}
co->cflag = cflag;
@@ -140,17 +112,17 @@ static int usb_console_setup(struct console *co, char *options)
serial = usb_serial_get_by_index(co->index);
if (serial == NULL) {
/* no device is connected yet, sorry :( */
- err ("No USB device connected to ttyUSB%i", co->index);
+ err("No USB device connected to ttyUSB%i", co->index);
return -ENODEV;
}
port = serial->port[0];
- port->tty = NULL;
+ port->port.tty = NULL;
info->port = port;
-
- ++port->open_count;
- if (port->open_count == 1) {
+
+ ++port->port.count;
+ if (port->port.count == 1) {
if (serial->type->set_termios) {
/*
* allocate a fake tty so the driver can initialize
@@ -171,15 +143,15 @@ static int usb_console_setup(struct console *co, char *options)
}
memset(&dummy, 0, sizeof(struct ktermios));
tty->termios = termios;
- port->tty = tty;
+ port->port.tty = tty;
}
- /* only call the device specific open if this
+ /* only call the device specific open if this
* is the first time the port is opened */
if (serial->type->open)
- retval = serial->type->open(port, NULL);
+ retval = serial->type->open(NULL, port, NULL);
else
- retval = usb_serial_generic_open(port, NULL);
+ retval = usb_serial_generic_open(NULL, port, NULL);
if (retval) {
err("could not open USB console port");
@@ -188,9 +160,10 @@ static int usb_console_setup(struct console *co, char *options)
if (serial->type->set_termios) {
termios->c_cflag = cflag;
- serial->type->set_termios(port, &dummy);
+ tty_termios_encode_baud_rate(termios, baud, baud);
+ serial->type->set_termios(NULL, port, &dummy);
- port->tty = NULL;
+ port->port.tty = NULL;
kfree(termios);
kfree(tty);
}
@@ -203,15 +176,16 @@ out:
return retval;
free_termios:
kfree(termios);
- port->tty = NULL;
+ port->port.tty = NULL;
free_tty:
kfree(tty);
reset_open_count:
- port->open_count = 0;
+ port->port.count = 0;
goto out;
}
-static void usb_console_write(struct console *co, const char *buf, unsigned count)
+static void usb_console_write(struct console *co,
+ const char *buf, unsigned count)
{
static struct usbcons_info *info = &usbcons_info;
struct usb_serial_port *port = info->port;
@@ -227,8 +201,8 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun
dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
- if (!port->open_count) {
- dbg ("%s - port not opened", __func__);
+ if (!port->port.count) {
+ dbg("%s - port not opened", __func__);
return;
}
@@ -236,26 +210,29 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun
unsigned int i;
unsigned int lf;
/* search for LF so we can insert CR if necessary */
- for (i=0, lf=0 ; i < count ; i++) {
+ for (i = 0, lf = 0 ; i < count ; i++) {
if (*(buf + i) == 10) {
lf = 1;
i++;
break;
}
}
- /* pass on to the driver specific version of this function if it is available */
+ /* pass on to the driver specific version of this function if
+ it is available */
if (serial->type->write)
- retval = serial->type->write(port, buf, i);
+ retval = serial->type->write(NULL, port, buf, i);
else
- retval = usb_serial_generic_write(port, buf, i);
+ retval = usb_serial_generic_write(NULL, port, buf, i);
dbg("%s - return value : %d", __func__, retval);
if (lf) {
/* append CR after LF */
unsigned char cr = 13;
if (serial->type->write)
- retval = serial->type->write(port, &cr, 1);
+ retval = serial->type->write(NULL,
+ port, &cr, 1);
else
- retval = usb_serial_generic_write(port, &cr, 1);
+ retval = usb_serial_generic_write(NULL,
+ port, &cr, 1);
dbg("%s - return value : %d", __func__, retval);
}
buf += i;
@@ -273,18 +250,19 @@ static struct console usbcons = {
void usb_serial_console_disconnect(struct usb_serial *serial)
{
- if (serial && serial->port && serial->port[0] && serial->port[0] == usbcons_info.port) {
+ if (serial && serial->port && serial->port[0]
+ && serial->port[0] == usbcons_info.port) {
usb_serial_console_exit();
usb_serial_put(serial);
}
}
-void usb_serial_console_init (int serial_debug, int minor)
+void usb_serial_console_init(int serial_debug, int minor)
{
debug = serial_debug;
if (minor == 0) {
- /*
+ /*
* Call register_console() if this is the first device plugged
* in. If we call it earlier, then the callback to
* console_setup() will fail, as there is not a device seen by
@@ -293,21 +271,21 @@ void usb_serial_console_init (int serial_debug, int minor)
/*
* Register console.
* NOTES:
- * console_setup() is called (back) immediately (from register_console).
- * console_write() is called immediately from register_console iff
- * CON_PRINTBUFFER is set in flags.
+ * console_setup() is called (back) immediately (from
+ * register_console). console_write() is called immediately
+ * from register_console iff CON_PRINTBUFFER is set in flags.
*/
- dbg ("registering the USB serial console.");
+ dbg("registering the USB serial console.");
register_console(&usbcons);
}
}
-void usb_serial_console_exit (void)
+void usb_serial_console_exit(void)
{
if (usbcons_info.port) {
unregister_console(&usbcons);
- if (usbcons_info.port->open_count)
- usbcons_info.port->open_count--;
+ if (usbcons_info.port->port.count)
+ usbcons_info.port->port.count--;
usbcons_info.port = NULL;
}
}
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 2bc5576c443..442cba69cce 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -25,7 +25,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/usb.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb/serial.h>
/*
@@ -37,17 +37,20 @@
/*
* Function Prototypes
*/
-static int cp2101_open(struct usb_serial_port*, struct file*);
-static void cp2101_cleanup(struct usb_serial_port*);
-static void cp2101_close(struct usb_serial_port*, struct file*);
-static void cp2101_get_termios(struct usb_serial_port*);
-static void cp2101_set_termios(struct usb_serial_port*, struct ktermios*);
-static int cp2101_tiocmget (struct usb_serial_port *, struct file *);
-static int cp2101_tiocmset (struct usb_serial_port *, struct file *,
+static int cp2101_open(struct tty_struct *, struct usb_serial_port *,
+ struct file *);
+static void cp2101_cleanup(struct usb_serial_port *);
+static void cp2101_close(struct tty_struct *, struct usb_serial_port *,
+ struct file*);
+static void cp2101_get_termios(struct tty_struct *);
+static void cp2101_set_termios(struct tty_struct *, struct usb_serial_port *,
+ struct ktermios*);
+static int cp2101_tiocmget(struct tty_struct *, struct file *);
+static int cp2101_tiocmset(struct tty_struct *, struct file *,
unsigned int, unsigned int);
-static void cp2101_break_ctl(struct usb_serial_port*, int);
-static int cp2101_startup (struct usb_serial *);
-static void cp2101_shutdown(struct usb_serial*);
+static void cp2101_break_ctl(struct tty_struct *, int);
+static int cp2101_startup(struct usb_serial *);
+static void cp2101_shutdown(struct usb_serial *);
static int debug;
@@ -93,7 +96,7 @@ static struct usb_device_id id_table [] = {
{ } /* Terminating Entry */
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver cp2101_driver = {
.name = "cp2101",
@@ -182,7 +185,7 @@ static struct usb_serial_driver cp2101_device = {
* 'data' is a pointer to a pre-allocated array of integers large
* enough to hold 'size' bytes (with 4 bytes to each integer)
*/
-static int cp2101_get_config(struct usb_serial_port* port, u8 request,
+static int cp2101_get_config(struct usb_serial_port *port, u8 request,
unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
@@ -202,12 +205,12 @@ static int cp2101_get_config(struct usb_serial_port* port, u8 request,
request++;
/* Issue the request, attempting to read 'size' bytes */
- result = usb_control_msg (serial->dev,usb_rcvctrlpipe (serial->dev, 0),
+ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
request, REQTYPE_DEVICE_TO_HOST, 0x0000,
0, buf, size, 300);
/* Convert data into an array of integers */
- for (i=0; i<length; i++)
+ for (i = 0; i < length; i++)
data[i] = le32_to_cpu(buf[i]);
kfree(buf);
@@ -228,7 +231,7 @@ static int cp2101_get_config(struct usb_serial_port* port, u8 request,
* Values less than 16 bits wide are sent directly
* 'size' is specified in bytes.
*/
-static int cp2101_set_config(struct usb_serial_port* port, u8 request,
+static int cp2101_set_config(struct usb_serial_port *port, u8 request,
unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
@@ -250,12 +253,12 @@ static int cp2101_set_config(struct usb_serial_port* port, u8 request,
buf[i] = cpu_to_le32(data[i]);
if (size > 2) {
- result = usb_control_msg (serial->dev,
+ result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
request, REQTYPE_HOST_TO_DEVICE, 0x0000,
0, buf, size, 300);
} else {
- result = usb_control_msg (serial->dev,
+ result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
request, REQTYPE_HOST_TO_DEVICE, data[0],
0, NULL, 0, 300);
@@ -271,7 +274,7 @@ static int cp2101_set_config(struct usb_serial_port* port, u8 request,
}
/* Single data value */
- result = usb_control_msg (serial->dev,
+ result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
request, REQTYPE_HOST_TO_DEVICE, data[0],
0, NULL, 0, 300);
@@ -283,13 +286,14 @@ static int cp2101_set_config(struct usb_serial_port* port, u8 request,
* Convenience function for calling cp2101_set_config on single data values
* without requiring an integer pointer
*/
-static inline int cp2101_set_config_single(struct usb_serial_port* port,
+static inline int cp2101_set_config_single(struct usb_serial_port *port,
u8 request, unsigned int data)
{
return cp2101_set_config(port, request, &data, 2);
}
-static int cp2101_open (struct usb_serial_port *port, struct file *filp)
+static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
struct usb_serial *serial = port->serial;
int result;
@@ -303,7 +307,7 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
}
/* Start reading from the device */
- usb_fill_bulk_urb (port->read_urb, serial->dev,
+ usb_fill_bulk_urb(port->read_urb, serial->dev,
usb_rcvbulkpipe(serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
@@ -318,15 +322,15 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
}
/* Configure the termios structure */
- cp2101_get_termios(port);
+ cp2101_get_termios(tty);
/* Set the DTR and RTS pins low */
- cp2101_tiocmset(port, NULL, TIOCM_DTR | TIOCM_RTS, 0);
+ cp2101_tiocmset(tty, NULL, TIOCM_DTR | TIOCM_RTS, 0);
return 0;
}
-static void cp2101_cleanup (struct usb_serial_port *port)
+static void cp2101_cleanup(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
@@ -341,7 +345,8 @@ static void cp2101_cleanup (struct usb_serial_port *port)
}
}
-static void cp2101_close (struct usb_serial_port *port, struct file * filp)
+static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
dbg("%s - port %d", __func__, port->number);
@@ -362,19 +367,15 @@ static void cp2101_close (struct usb_serial_port *port, struct file * filp)
* from the device, corrects any unsupported values, and configures the
* termios structure to reflect the state of the device
*/
-static void cp2101_get_termios (struct usb_serial_port *port)
+static void cp2101_get_termios (struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned int cflag, modem_ctl[4];
unsigned int baud;
unsigned int bits;
dbg("%s - port %d", __func__, port->number);
- if (!port->tty || !port->tty->termios) {
- dbg("%s - no tty structures", __func__);
- return;
- }
-
cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2);
/* Convert to baudrate */
if (baud)
@@ -382,104 +383,102 @@ static void cp2101_get_termios (struct usb_serial_port *port)
dbg("%s - baud rate = %d", __func__, baud);
- tty_encode_baud_rate(port->tty, baud, baud);
- cflag = port->tty->termios->c_cflag;
+ tty_encode_baud_rate(tty, baud, baud);
+ cflag = tty->termios->c_cflag;
cp2101_get_config(port, CP2101_BITS, &bits, 2);
cflag &= ~CSIZE;
- switch(bits & BITS_DATA_MASK) {
- case BITS_DATA_5:
- dbg("%s - data bits = 5", __func__);
- cflag |= CS5;
- break;
- case BITS_DATA_6:
- dbg("%s - data bits = 6", __func__);
- cflag |= CS6;
- break;
- case BITS_DATA_7:
- dbg("%s - data bits = 7", __func__);
- cflag |= CS7;
- break;
- case BITS_DATA_8:
- dbg("%s - data bits = 8", __func__);
- cflag |= CS8;
- break;
- case BITS_DATA_9:
- dbg("%s - data bits = 9 (not supported, "
- "using 8 data bits)", __func__);
- cflag |= CS8;
- bits &= ~BITS_DATA_MASK;
- bits |= BITS_DATA_8;
- cp2101_set_config(port, CP2101_BITS, &bits, 2);
- break;
- default:
- dbg("%s - Unknown number of data bits, "
- "using 8", __func__);
- cflag |= CS8;
- bits &= ~BITS_DATA_MASK;
- bits |= BITS_DATA_8;
- cp2101_set_config(port, CP2101_BITS, &bits, 2);
- break;
+ switch (bits & BITS_DATA_MASK) {
+ case BITS_DATA_5:
+ dbg("%s - data bits = 5", __func__);
+ cflag |= CS5;
+ break;
+ case BITS_DATA_6:
+ dbg("%s - data bits = 6", __func__);
+ cflag |= CS6;
+ break;
+ case BITS_DATA_7:
+ dbg("%s - data bits = 7", __func__);
+ cflag |= CS7;
+ break;
+ case BITS_DATA_8:
+ dbg("%s - data bits = 8", __func__);
+ cflag |= CS8;
+ break;
+ case BITS_DATA_9:
+ dbg("%s - data bits = 9 (not supported, using 8 data bits)",
+ __func__);
+ cflag |= CS8;
+ bits &= ~BITS_DATA_MASK;
+ bits |= BITS_DATA_8;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
+ default:
+ dbg("%s - Unknown number of data bits, using 8", __func__);
+ cflag |= CS8;
+ bits &= ~BITS_DATA_MASK;
+ bits |= BITS_DATA_8;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
}
- switch(bits & BITS_PARITY_MASK) {
- case BITS_PARITY_NONE:
- dbg("%s - parity = NONE", __func__);
- cflag &= ~PARENB;
- break;
- case BITS_PARITY_ODD:
- dbg("%s - parity = ODD", __func__);
- cflag |= (PARENB|PARODD);
- break;
- case BITS_PARITY_EVEN:
- dbg("%s - parity = EVEN", __func__);
- cflag &= ~PARODD;
- cflag |= PARENB;
- break;
- case BITS_PARITY_MARK:
- dbg("%s - parity = MARK (not supported, "
- "disabling parity)", __func__);
- cflag &= ~PARENB;
- bits &= ~BITS_PARITY_MASK;
- cp2101_set_config(port, CP2101_BITS, &bits, 2);
- break;
- case BITS_PARITY_SPACE:
- dbg("%s - parity = SPACE (not supported, "
- "disabling parity)", __func__);
- cflag &= ~PARENB;
- bits &= ~BITS_PARITY_MASK;
- cp2101_set_config(port, CP2101_BITS, &bits, 2);
- break;
- default:
- dbg("%s - Unknown parity mode, "
- "disabling parity", __func__);
- cflag &= ~PARENB;
- bits &= ~BITS_PARITY_MASK;
- cp2101_set_config(port, CP2101_BITS, &bits, 2);
- break;
+ switch (bits & BITS_PARITY_MASK) {
+ case BITS_PARITY_NONE:
+ dbg("%s - parity = NONE", __func__);
+ cflag &= ~PARENB;
+ break;
+ case BITS_PARITY_ODD:
+ dbg("%s - parity = ODD", __func__);
+ cflag |= (PARENB|PARODD);
+ break;
+ case BITS_PARITY_EVEN:
+ dbg("%s - parity = EVEN", __func__);
+ cflag &= ~PARODD;
+ cflag |= PARENB;
+ break;
+ case BITS_PARITY_MARK:
+ dbg("%s - parity = MARK (not supported, disabling parity)",
+ __func__);
+ cflag &= ~PARENB;
+ bits &= ~BITS_PARITY_MASK;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
+ case BITS_PARITY_SPACE:
+ dbg("%s - parity = SPACE (not supported, disabling parity)",
+ __func__);
+ cflag &= ~PARENB;
+ bits &= ~BITS_PARITY_MASK;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
+ default:
+ dbg("%s - Unknown parity mode, disabling parity", __func__);
+ cflag &= ~PARENB;
+ bits &= ~BITS_PARITY_MASK;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
}
cflag &= ~CSTOPB;
- switch(bits & BITS_STOP_MASK) {
- case BITS_STOP_1:
- dbg("%s - stop bits = 1", __func__);
- break;
- case BITS_STOP_1_5:
- dbg("%s - stop bits = 1.5 (not supported, "
- "using 1 stop bit)", __func__);
- bits &= ~BITS_STOP_MASK;
- cp2101_set_config(port, CP2101_BITS, &bits, 2);
- break;
- case BITS_STOP_2:
- dbg("%s - stop bits = 2", __func__);
- cflag |= CSTOPB;
- break;
- default:
- dbg("%s - Unknown number of stop bits, "
- "using 1 stop bit", __func__);
- bits &= ~BITS_STOP_MASK;
- cp2101_set_config(port, CP2101_BITS, &bits, 2);
- break;
+ switch (bits & BITS_STOP_MASK) {
+ case BITS_STOP_1:
+ dbg("%s - stop bits = 1", __func__);
+ break;
+ case BITS_STOP_1_5:
+ dbg("%s - stop bits = 1.5 (not supported, using 1 stop bit)",
+ __func__);
+ bits &= ~BITS_STOP_MASK;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
+ case BITS_STOP_2:
+ dbg("%s - stop bits = 2", __func__);
+ cflag |= CSTOPB;
+ break;
+ default:
+ dbg("%s - Unknown number of stop bits, using 1 stop bit",
+ __func__);
+ bits &= ~BITS_STOP_MASK;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
}
cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16);
@@ -491,11 +490,11 @@ static void cp2101_get_termios (struct usb_serial_port *port)
cflag &= ~CRTSCTS;
}
- port->tty->termios->c_cflag = cflag;
+ tty->termios->c_cflag = cflag;
}
-static void cp2101_set_termios (struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void cp2101_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
unsigned int cflag, old_cflag;
unsigned int baud = 0, bits;
@@ -503,43 +502,41 @@ static void cp2101_set_termios (struct usb_serial_port *port,
dbg("%s - port %d", __func__, port->number);
- if (!port->tty || !port->tty->termios) {
- dbg("%s - no tty structures", __func__);
+ if (!tty)
return;
- }
- port->tty->termios->c_cflag &= ~CMSPAR;
- cflag = port->tty->termios->c_cflag;
+ tty->termios->c_cflag &= ~CMSPAR;
+ cflag = tty->termios->c_cflag;
old_cflag = old_termios->c_cflag;
- baud = tty_get_baud_rate(port->tty);
+ baud = tty_get_baud_rate(tty);
/* If the baud rate is to be updated*/
if (baud != tty_termios_baud_rate(old_termios)) {
switch (baud) {
- case 0:
- case 600:
- case 1200:
- case 1800:
- case 2400:
- case 4800:
- case 7200:
- case 9600:
- case 14400:
- case 19200:
- case 28800:
- case 38400:
- case 55854:
- case 57600:
- case 115200:
- case 127117:
- case 230400:
- case 460800:
- case 921600:
- case 3686400:
- break;
- default:
- baud = 9600;
- break;
+ case 0:
+ case 600:
+ case 1200:
+ case 1800:
+ case 2400:
+ case 4800:
+ case 7200:
+ case 9600:
+ case 14400:
+ case 19200:
+ case 28800:
+ case 38400:
+ case 55854:
+ case 57600:
+ case 115200:
+ case 127117:
+ case 230400:
+ case 460800:
+ case 921600:
+ case 3686400:
+ break;
+ default:
+ baud = 9600;
+ break;
}
if (baud) {
@@ -554,35 +551,35 @@ static void cp2101_set_termios (struct usb_serial_port *port,
}
}
/* Report back the resulting baud rate */
- tty_encode_baud_rate(port->tty, baud, baud);
+ tty_encode_baud_rate(tty, baud, baud);
/* If the number of data bits is to be updated */
if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
cp2101_get_config(port, CP2101_BITS, &bits, 2);
bits &= ~BITS_DATA_MASK;
switch (cflag & CSIZE) {
- case CS5:
- bits |= BITS_DATA_5;
- dbg("%s - data bits = 5", __func__);
- break;
- case CS6:
- bits |= BITS_DATA_6;
- dbg("%s - data bits = 6", __func__);
- break;
- case CS7:
- bits |= BITS_DATA_7;
- dbg("%s - data bits = 7", __func__);
- break;
- case CS8:
- bits |= BITS_DATA_8;
- dbg("%s - data bits = 8", __func__);
- break;
- /*case CS9:
- bits |= BITS_DATA_9;
- dbg("%s - data bits = 9", __func__);
- break;*/
- default:
- dev_err(&port->dev, "cp2101 driver does not "
+ case CS5:
+ bits |= BITS_DATA_5;
+ dbg("%s - data bits = 5", __func__);
+ break;
+ case CS6:
+ bits |= BITS_DATA_6;
+ dbg("%s - data bits = 6", __func__);
+ break;
+ case CS7:
+ bits |= BITS_DATA_7;
+ dbg("%s - data bits = 7", __func__);
+ break;
+ case CS8:
+ bits |= BITS_DATA_8;
+ dbg("%s - data bits = 8", __func__);
+ break;
+ /*case CS9:
+ bits |= BITS_DATA_9;
+ dbg("%s - data bits = 9", __func__);
+ break;*/
+ default:
+ dev_err(&port->dev, "cp2101 driver does not "
"support the number of bits requested,"
" using 8 bit mode\n");
bits |= BITS_DATA_8;
@@ -651,9 +648,10 @@ static void cp2101_set_termios (struct usb_serial_port *port,
}
-static int cp2101_tiocmset (struct usb_serial_port *port, struct file *file,
+static int cp2101_tiocmset (struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned int control = 0;
dbg("%s - port %d", __func__, port->number);
@@ -681,8 +679,9 @@ static int cp2101_tiocmset (struct usb_serial_port *port, struct file *file,
}
-static int cp2101_tiocmget (struct usb_serial_port *port, struct file *file)
+static int cp2101_tiocmget (struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned int control;
int result;
@@ -702,8 +701,9 @@ static int cp2101_tiocmget (struct usb_serial_port *port, struct file *file)
return result;
}
-static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
+static void cp2101_break_ctl (struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned int state;
dbg("%s - port %d", __func__, port->number);
@@ -712,30 +712,29 @@ static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
else
state = BREAK_ON;
dbg("%s - turning break %s", __func__,
- state==BREAK_OFF ? "off" : "on");
+ state == BREAK_OFF ? "off" : "on");
cp2101_set_config(port, CP2101_BREAK, &state, 2);
}
-static int cp2101_startup (struct usb_serial *serial)
+static int cp2101_startup(struct usb_serial *serial)
{
/* CP2101 buffers behave strangely unless device is reset */
usb_reset_device(serial->dev);
return 0;
}
-static void cp2101_shutdown (struct usb_serial *serial)
+static void cp2101_shutdown(struct usb_serial *serial)
{
int i;
dbg("%s", __func__);
/* Stop reads and writes on all ports */
- for (i=0; i < serial->num_ports; ++i) {
+ for (i = 0; i < serial->num_ports; ++i)
cp2101_cleanup(serial->port[i]);
- }
}
-static int __init cp2101_init (void)
+static int __init cp2101_init(void)
{
int retval;
@@ -755,10 +754,10 @@ static int __init cp2101_init (void)
return 0;
}
-static void __exit cp2101_exit (void)
+static void __exit cp2101_exit(void)
{
- usb_deregister (&cp2101_driver);
- usb_serial_deregister (&cp2101_device);
+ usb_deregister(&cp2101_driver);
+ usb_serial_deregister(&cp2101_device);
}
module_init(cp2101_init);
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index c164e2cf275..b4d72351cb9 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -37,7 +37,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -57,22 +57,25 @@ static int debug;
#define CYBERJACK_PRODUCT_ID 0x0100
/* Function prototypes */
-static int cyberjack_startup (struct usb_serial *serial);
-static void cyberjack_shutdown (struct usb_serial *serial);
-static int cyberjack_open (struct usb_serial_port *port, struct file *filp);
-static void cyberjack_close (struct usb_serial_port *port, struct file *filp);
-static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-static int cyberjack_write_room( struct usb_serial_port *port );
-static void cyberjack_read_int_callback (struct urb *urb);
-static void cyberjack_read_bulk_callback (struct urb *urb);
-static void cyberjack_write_bulk_callback (struct urb *urb);
+static int cyberjack_startup(struct usb_serial *serial);
+static void cyberjack_shutdown(struct usb_serial *serial);
+static int cyberjack_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void cyberjack_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static int cyberjack_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count);
+static int cyberjack_write_room(struct tty_struct *tty);
+static void cyberjack_read_int_callback(struct urb *urb);
+static void cyberjack_read_bulk_callback(struct urb *urb);
+static void cyberjack_write_bulk_callback(struct urb *urb);
static struct usb_device_id id_table [] = {
{ USB_DEVICE(CYBERJACK_VENDOR_ID, CYBERJACK_PRODUCT_ID) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver cyberjack_driver = {
.name = "cyberjack",
@@ -111,7 +114,7 @@ struct cyberjack_private {
};
/* do some startup allocations not currently performed by usb_serial_probe() */
-static int cyberjack_startup (struct usb_serial *serial)
+static int cyberjack_startup(struct usb_serial *serial)
{
struct cyberjack_private *priv;
int i;
@@ -135,20 +138,20 @@ static int cyberjack_startup (struct usb_serial *serial)
for (i = 0; i < serial->num_ports; ++i) {
int result;
serial->port[i]->interrupt_in_urb->dev = serial->dev;
- result = usb_submit_urb(serial->port[i]->interrupt_in_urb,
+ result = usb_submit_urb(serial->port[i]->interrupt_in_urb,
GFP_KERNEL);
if (result)
err(" usb_submit_urb(read int) failed");
dbg("%s - usb_submit_urb(int urb)", __func__);
}
- return( 0 );
+ return 0;
}
-static void cyberjack_shutdown (struct usb_serial *serial)
+static void cyberjack_shutdown(struct usb_serial *serial)
{
int i;
-
+
dbg("%s", __func__);
for (i = 0; i < serial->num_ports; ++i) {
@@ -158,8 +161,9 @@ static void cyberjack_shutdown (struct usb_serial *serial)
usb_set_serial_port_data(serial->port[i], NULL);
}
}
-
-static int cyberjack_open (struct usb_serial_port *port, struct file *filp)
+
+static int cyberjack_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct cyberjack_private *priv;
unsigned long flags;
@@ -167,14 +171,15 @@ static int cyberjack_open (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __func__, port->number);
- dbg("%s - usb_clear_halt", __func__ );
+ dbg("%s - usb_clear_halt", __func__);
usb_clear_halt(port->serial->dev, port->write_urb->pipe);
/* force low_latency on so that our tty_push actually forces
* the data through, otherwise it is scheduled, and with high
* data rates (like with OHCI) data can get lost.
*/
- port->tty->low_latency = 1;
+ if (tty)
+ tty->low_latency = 1;
priv = usb_get_serial_port_data(port);
spin_lock_irqsave(&priv->lock, flags);
@@ -186,7 +191,8 @@ static int cyberjack_open (struct usb_serial_port *port, struct file *filp)
return result;
}
-static void cyberjack_close (struct usb_serial_port *port, struct file *filp)
+static void cyberjack_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
dbg("%s - port %d", __func__, port->number);
@@ -197,7 +203,8 @@ static void cyberjack_close (struct usb_serial_port *port, struct file *filp)
}
}
-static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int cyberjack_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
struct cyberjack_private *priv = usb_get_serial_port_data(port);
@@ -223,7 +230,7 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
spin_lock_irqsave(&priv->lock, flags);
- if( (count+priv->wrfilled) > sizeof(priv->wrbuf) ) {
+ if (count+priv->wrfilled > sizeof(priv->wrbuf)) {
/* To much data for buffer. Reset buffer. */
priv->wrfilled = 0;
port->write_urb_busy = 0;
@@ -232,42 +239,43 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
}
/* Copy data */
- memcpy (priv->wrbuf+priv->wrfilled, buf, count);
+ memcpy(priv->wrbuf + priv->wrfilled, buf, count);
usb_serial_debug_data(debug, &port->dev, __func__, count,
- priv->wrbuf+priv->wrfilled);
+ priv->wrbuf + priv->wrfilled);
priv->wrfilled += count;
- if( priv->wrfilled >= 3 ) {
+ if (priv->wrfilled >= 3) {
wrexpected = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
dbg("%s - expected data: %d", __func__, wrexpected);
- } else {
+ } else
wrexpected = sizeof(priv->wrbuf);
- }
- if( priv->wrfilled >= wrexpected ) {
+ if (priv->wrfilled >= wrexpected) {
/* We have enough data to begin transmission */
int length;
dbg("%s - transmitting data (frame 1)", __func__);
- length = (wrexpected > port->bulk_out_size) ? port->bulk_out_size : wrexpected;
+ length = (wrexpected > port->bulk_out_size) ?
+ port->bulk_out_size : wrexpected;
- memcpy (port->write_urb->transfer_buffer, priv->wrbuf, length );
- priv->wrsent=length;
+ memcpy(port->write_urb->transfer_buffer, priv->wrbuf, length);
+ priv->wrsent = length;
/* set up our urb */
- usb_fill_bulk_urb(port->write_urb, serial->dev,
+ usb_fill_bulk_urb(port->write_urb, serial->dev,
usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, length,
- ((serial->type->write_bulk_callback) ?
- serial->type->write_bulk_callback :
- cyberjack_write_bulk_callback),
+ ((serial->type->write_bulk_callback) ?
+ serial->type->write_bulk_callback :
+ cyberjack_write_bulk_callback),
port);
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- err("%s - failed submitting write urb, error %d", __func__, result);
+ err("%s - failed submitting write urb, error %d",
+ __func__, result);
/* Throw away data. No better idea what to do with it. */
priv->wrfilled = 0;
priv->wrsent = 0;
@@ -276,12 +284,12 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
return 0;
}
- dbg("%s - priv->wrsent=%d", __func__,priv->wrsent);
- dbg("%s - priv->wrfilled=%d", __func__,priv->wrfilled);
+ dbg("%s - priv->wrsent=%d", __func__, priv->wrsent);
+ dbg("%s - priv->wrfilled=%d", __func__, priv->wrfilled);
- if( priv->wrsent>=priv->wrfilled ) {
+ if (priv->wrsent >= priv->wrfilled) {
dbg("%s - buffer cleaned", __func__);
- memset( priv->wrbuf, 0, sizeof(priv->wrbuf) );
+ memset(priv->wrbuf, 0, sizeof(priv->wrbuf));
priv->wrfilled = 0;
priv->wrsent = 0;
}
@@ -289,16 +297,16 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
spin_unlock_irqrestore(&priv->lock, flags);
- return (count);
-}
+ return count;
+}
-static int cyberjack_write_room( struct usb_serial_port *port )
+static int cyberjack_write_room(struct tty_struct *tty)
{
/* FIXME: .... */
return CYBERJACK_LOCAL_BUF_SIZE;
}
-static void cyberjack_read_int_callback( struct urb *urb )
+static void cyberjack_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct cyberjack_private *priv = usb_get_serial_port_data(port);
@@ -312,10 +320,11 @@ static void cyberjack_read_int_callback( struct urb *urb )
if (status)
return;
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
/* React only to interrupts signaling a bulk_in transfer */
- if( (urb->actual_length == 4) && (data[0] == 0x01) ) {
+ if (urb->actual_length == 4 && data[0] == 0x01) {
short old_rdtodo;
/* This is a announcement of coming bulk_ins. */
@@ -325,8 +334,8 @@ static void cyberjack_read_int_callback( struct urb *urb )
old_rdtodo = priv->rdtodo;
- if( (old_rdtodo+size)<(old_rdtodo) ) {
- dbg( "To many bulk_in urbs to do." );
+ if (old_rdtodo + size < old_rdtodo) {
+ dbg("To many bulk_in urbs to do.");
spin_unlock(&priv->lock);
goto resubmit;
}
@@ -338,10 +347,10 @@ static void cyberjack_read_int_callback( struct urb *urb )
spin_unlock(&priv->lock);
- if( !old_rdtodo ) {
+ if (!old_rdtodo) {
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
- if( result )
+ if (result)
err("%s - failed resubmitting read urb, error %d", __func__, result);
dbg("%s - usb_submit_urb(read urb)", __func__);
}
@@ -355,7 +364,7 @@ resubmit:
dbg("%s - usb_submit_urb(int urb)", __func__);
}
-static void cyberjack_read_bulk_callback (struct urb *urb)
+static void cyberjack_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct cyberjack_private *priv = usb_get_serial_port_data(port);
@@ -367,14 +376,15 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
dbg("%s - port %d", __func__, port->number);
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
if (status) {
dbg("%s - nonzero read bulk status received: %d",
__func__, status);
return;
}
- tty = port->tty;
+ tty = port->port.tty;
if (!tty) {
dbg("%s - ignoring since device not open\n", __func__);
return;
@@ -382,15 +392,16 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
if (urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
- tty_flip_buffer_push(tty);
+ tty_flip_buffer_push(tty);
}
spin_lock(&priv->lock);
/* Reduce urbs to do by one. */
- priv->rdtodo-=urb->actual_length;
+ priv->rdtodo -= urb->actual_length;
/* Just to be sure */
- if ( priv->rdtodo<0 ) priv->rdtodo = 0;
+ if (priv->rdtodo < 0)
+ priv->rdtodo = 0;
todo = priv->rdtodo;
spin_unlock(&priv->lock);
@@ -398,16 +409,17 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
dbg("%s - rdtodo: %d", __func__, todo);
/* Continue to read if we have still urbs to do. */
- if( todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) {
+ if (todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/) {
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d", __func__, result);
+ err("%s - failed resubmitting read urb, error %d",
+ __func__, result);
dbg("%s - usb_submit_urb(read urb)", __func__);
}
}
-static void cyberjack_write_bulk_callback (struct urb *urb)
+static void cyberjack_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct cyberjack_private *priv = usb_get_serial_port_data(port);
@@ -425,7 +437,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
spin_lock(&priv->lock);
/* only do something if we have more data to send */
- if( priv->wrfilled ) {
+ if (priv->wrfilled) {
int length, blksize, result;
dbg("%s - transmitting data (frame n)", __func__);
@@ -433,37 +445,39 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ?
port->bulk_out_size : (priv->wrfilled - priv->wrsent);
- memcpy (port->write_urb->transfer_buffer, priv->wrbuf + priv->wrsent,
- length );
- priv->wrsent+=length;
+ memcpy(port->write_urb->transfer_buffer,
+ priv->wrbuf + priv->wrsent, length);
+ priv->wrsent += length;
/* set up our urb */
- usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+ usb_fill_bulk_urb(port->write_urb, port->serial->dev,
usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, length,
- ((port->serial->type->write_bulk_callback) ?
- port->serial->type->write_bulk_callback :
- cyberjack_write_bulk_callback),
+ ((port->serial->type->write_bulk_callback) ?
+ port->serial->type->write_bulk_callback :
+ cyberjack_write_bulk_callback),
port);
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- err("%s - failed submitting write urb, error %d", __func__, result);
+ err("%s - failed submitting write urb, error %d",
+ __func__, result);
/* Throw away data. No better idea what to do with it. */
priv->wrfilled = 0;
priv->wrsent = 0;
goto exit;
}
- dbg("%s - priv->wrsent=%d", __func__,priv->wrsent);
- dbg("%s - priv->wrfilled=%d", __func__,priv->wrfilled);
+ dbg("%s - priv->wrsent=%d", __func__, priv->wrsent);
+ dbg("%s - priv->wrfilled=%d", __func__, priv->wrfilled);
blksize = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
- if( (priv->wrsent>=priv->wrfilled) || (priv->wrsent>=blksize) ) {
+ if (priv->wrsent >= priv->wrfilled ||
+ priv->wrsent >= blksize) {
dbg("%s - buffer cleaned", __func__);
- memset( priv->wrbuf, 0, sizeof(priv->wrbuf) );
+ memset(priv->wrbuf, 0, sizeof(priv->wrbuf));
priv->wrfilled = 0;
priv->wrsent = 0;
}
@@ -474,14 +488,14 @@ exit:
usb_serial_port_softint(port);
}
-static int __init cyberjack_init (void)
+static int __init cyberjack_init(void)
{
int retval;
retval = usb_serial_register(&cyberjack_device);
if (retval)
goto failed_usb_serial_register;
retval = usb_register(&cyberjack_driver);
- if (retval)
+ if (retval)
goto failed_usb_register;
info(DRIVER_VERSION " " DRIVER_AUTHOR);
@@ -494,18 +508,18 @@ failed_usb_serial_register:
return retval;
}
-static void __exit cyberjack_exit (void)
+static void __exit cyberjack_exit(void)
{
- usb_deregister (&cyberjack_driver);
- usb_serial_deregister (&cyberjack_device);
+ usb_deregister(&cyberjack_driver);
+ usb_serial_deregister(&cyberjack_device);
}
module_init(cyberjack_init);
module_exit(cyberjack_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_VERSION( DRIVER_VERSION );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 0230d3c0888..22837a3f2f8 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -2,7 +2,7 @@
* USB Cypress M8 driver
*
* Copyright (C) 2004
- * Lonnie Mendez (dignome@gmail.com)
+ * Lonnie Mendez (dignome@gmail.com)
* Copyright (C) 2003,2004
* Neil Whelchel (koyama@firstlight.net)
*
@@ -11,19 +11,21 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
* See http://geocities.com/i0xox0i for information on this driver and the
* earthmate usb device.
*
* Lonnie Mendez <dignome@gmail.com>
* 4-29-2005
- * Fixed problem where setting or retreiving the serial config would fail with
- * EPIPE. Removed CRTS toggling so the driver behaves more like other usbserial
- * adapters. Issued new interval of 1ms instead of the default 10ms. As a
- * result, transfer speed has been substantially increased. From avg. 850bps to
- * avg. 3300bps. initial termios has also been modified. Cleaned up code and
- * formatting issues so it is more readable. Replaced the C++ style comments.
+ * Fixed problem where setting or retreiving the serial config would fail
+ * with EPIPE. Removed CRTS toggling so the driver behaves more like
+ * other usbserial adapters. Issued new interval of 1ms instead of the
+ * default 10ms. As a result, transfer speed has been substantially
+ * increased from avg. 850bps to avg. 3300bps. initial termios has also
+ * been modified. Cleaned up code and formatting issues so it is more
+ * readable. Replaced the C++ style comments.
*
* Lonnie Mendez <dignome@gmail.com>
* 12-15-2004
@@ -42,10 +44,11 @@
*
*/
-/* Thanks to Neil Whelchel for writing the first cypress m8 implementation for linux. */
+/* Thanks to Neil Whelchel for writing the first cypress m8 implementation
+ for linux. */
/* Thanks to cypress for providing references for the hid reports. */
/* Thanks to Jiang Zhang for providing links and for general help. */
-/* Code originates and was built up from ftdi_sio, belkin, pl2303 and others. */
+/* Code originates and was built up from ftdi_sio, belkin, pl2303 and others.*/
#include <linux/kernel.h>
@@ -62,7 +65,7 @@
#include <linux/usb/serial.h>
#include <linux/serial.h>
#include <linux/delay.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "cypress_m8.h"
@@ -112,7 +115,7 @@ static struct usb_device_id id_table_combined [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver cypress_driver = {
.name = "cypress",
@@ -146,11 +149,13 @@ struct cypress_private {
__u8 rx_flags; /* throttling - used from whiteheat/ftdi_sio */
enum packet_format pkt_fmt; /* format to use for packet send / receive */
int get_cfg_unsafe; /* If true, the CYPRESS_GET_CONFIG is unsafe */
- int baud_rate; /* stores current baud rate in integer form */
+ int baud_rate; /* stores current baud rate in
+ integer form */
int isthrottled; /* if throttled, discard reads */
wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */
char prev_status, diff_status; /* used for TIOCMIWAIT */
- /* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */
+ /* we pass a pointer to this as the arguement sent to
+ cypress_set_termios old_termios */
struct ktermios tmp_termios; /* stores the old termios settings */
};
@@ -163,33 +168,41 @@ struct cypress_buf {
};
/* function prototypes for the Cypress USB to serial device */
-static int cypress_earthmate_startup (struct usb_serial *serial);
-static int cypress_hidcom_startup (struct usb_serial *serial);
-static int cypress_ca42v2_startup (struct usb_serial *serial);
-static void cypress_shutdown (struct usb_serial *serial);
-static int cypress_open (struct usb_serial_port *port, struct file *filp);
-static void cypress_close (struct usb_serial_port *port, struct file *filp);
-static int cypress_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-static void cypress_send (struct usb_serial_port *port);
-static int cypress_write_room (struct usb_serial_port *port);
-static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void cypress_set_termios (struct usb_serial_port *port, struct ktermios * old);
-static int cypress_tiocmget (struct usb_serial_port *port, struct file *file);
-static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
-static int cypress_chars_in_buffer (struct usb_serial_port *port);
-static void cypress_throttle (struct usb_serial_port *port);
-static void cypress_unthrottle (struct usb_serial_port *port);
-static void cypress_set_dead (struct usb_serial_port *port);
-static void cypress_read_int_callback (struct urb *urb);
-static void cypress_write_int_callback (struct urb *urb);
+static int cypress_earthmate_startup(struct usb_serial *serial);
+static int cypress_hidcom_startup(struct usb_serial *serial);
+static int cypress_ca42v2_startup(struct usb_serial *serial);
+static void cypress_shutdown(struct usb_serial *serial);
+static int cypress_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void cypress_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+static void cypress_send(struct usb_serial_port *port);
+static int cypress_write_room(struct tty_struct *tty);
+static int cypress_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static void cypress_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
+static int cypress_tiocmget(struct tty_struct *tty, struct file *file);
+static int cypress_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
+static int cypress_chars_in_buffer(struct tty_struct *tty);
+static void cypress_throttle(struct tty_struct *tty);
+static void cypress_unthrottle(struct tty_struct *tty);
+static void cypress_set_dead(struct usb_serial_port *port);
+static void cypress_read_int_callback(struct urb *urb);
+static void cypress_write_int_callback(struct urb *urb);
/* write buffer functions */
static struct cypress_buf *cypress_buf_alloc(unsigned int size);
-static void cypress_buf_free(struct cypress_buf *cb);
-static void cypress_buf_clear(struct cypress_buf *cb);
-static unsigned int cypress_buf_data_avail(struct cypress_buf *cb);
-static unsigned int cypress_buf_space_avail(struct cypress_buf *cb);
-static unsigned int cypress_buf_put(struct cypress_buf *cb, const char *buf, unsigned int count);
-static unsigned int cypress_buf_get(struct cypress_buf *cb, char *buf, unsigned int count);
+static void cypress_buf_free(struct cypress_buf *cb);
+static void cypress_buf_clear(struct cypress_buf *cb);
+static unsigned int cypress_buf_data_avail(struct cypress_buf *cb);
+static unsigned int cypress_buf_space_avail(struct cypress_buf *cb);
+static unsigned int cypress_buf_put(struct cypress_buf *cb,
+ const char *buf, unsigned int count);
+static unsigned int cypress_buf_get(struct cypress_buf *cb,
+ char *buf, unsigned int count);
static struct usb_serial_driver cypress_earthmate_device = {
@@ -247,7 +260,7 @@ static struct usb_serial_driver cypress_hidcom_device = {
static struct usb_serial_driver cypress_ca42v2_device = {
.driver = {
.owner = THIS_MODULE,
- .name = "nokiaca42v2",
+ .name = "nokiaca42v2",
},
.description = "Nokia CA-42 V2 Adapter",
.usb_driver = &cypress_driver,
@@ -322,8 +335,10 @@ static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate)
/* This function can either set or retrieve the current serial line settings */
-static int cypress_serial_control (struct usb_serial_port *port, speed_t baud_rate, int data_bits, int stop_bits,
- int parity_enable, int parity_type, int reset, int cypress_request_type)
+static int cypress_serial_control(struct tty_struct *tty,
+ struct usb_serial_port *port, speed_t baud_rate, int data_bits,
+ int stop_bits, int parity_enable, int parity_type, int reset,
+ int cypress_request_type)
{
int new_baudrate = 0, retval = 0, tries = 0;
struct cypress_private *priv;
@@ -331,111 +346,114 @@ static int cypress_serial_control (struct usb_serial_port *port, speed_t baud_ra
unsigned long flags;
dbg("%s", __func__);
-
+
priv = usb_get_serial_port_data(port);
if (!priv->comm_is_ok)
return -ENODEV;
- switch(cypress_request_type) {
- case CYPRESS_SET_CONFIG:
+ switch (cypress_request_type) {
+ case CYPRESS_SET_CONFIG:
+ new_baudrate = priv->baud_rate;
+ /* 0 means 'Hang up' so doesn't change the true bit rate */
+ if (baud_rate == 0)
new_baudrate = priv->baud_rate;
- /* 0 means 'Hang up' so doesn't change the true bit rate */
- if (baud_rate == 0)
- new_baudrate = priv->baud_rate;
- /* Change of speed ? */
- else if (baud_rate != priv->baud_rate) {
- dbg("%s - baud rate is changing", __func__);
- retval = analyze_baud_rate(port, baud_rate);
- if (retval >= 0) {
- new_baudrate = retval;
- dbg("%s - New baud rate set to %d",
- __func__, new_baudrate);
- }
- }
- dbg("%s - baud rate is being sent as %d", __func__, new_baudrate);
-
- memset(feature_buffer, 0, sizeof(feature_buffer));
- /* fill the feature_buffer with new configuration */
- *((u_int32_t *)feature_buffer) = new_baudrate;
-
- feature_buffer[4] |= data_bits; /* assign data bits in 2 bit space ( max 3 ) */
- /* 1 bit gap */
- feature_buffer[4] |= (stop_bits << 3); /* assign stop bits in 1 bit space */
- feature_buffer[4] |= (parity_enable << 4); /* assign parity flag in 1 bit space */
- feature_buffer[4] |= (parity_type << 5); /* assign parity type in 1 bit space */
- /* 1 bit gap */
- feature_buffer[4] |= (reset << 7); /* assign reset at end of byte, 1 bit space */
-
- dbg("%s - device is being sent this feature report:", __func__);
- dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__, feature_buffer[0], feature_buffer[1],
- feature_buffer[2], feature_buffer[3], feature_buffer[4]);
-
- do {
- retval = usb_control_msg(port->serial->dev,
- usb_sndctrlpipe(port->serial->dev, 0),
- HID_REQ_SET_REPORT,
- USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
- 0x0300, 0, feature_buffer,
- sizeof(feature_buffer), 500);
-
- if (tries++ >= 3)
- break;
-
- } while (retval != sizeof(feature_buffer) &&
- retval != -ENODEV);
-
- if (retval != sizeof(feature_buffer)) {
- err("%s - failed sending serial line settings - %d", __func__, retval);
- cypress_set_dead(port);
- } else {
- spin_lock_irqsave(&priv->lock, flags);
- priv->baud_rate = new_baudrate;
- priv->current_config = feature_buffer[4];
- spin_unlock_irqrestore(&priv->lock, flags);
- /* If we asked for a speed change encode it */
- if (baud_rate)
- tty_encode_baud_rate(port->tty,
- new_baudrate, new_baudrate);
- }
- break;
- case CYPRESS_GET_CONFIG:
- if (priv->get_cfg_unsafe) {
- /* Not implemented for this device,
- and if we try to do it we're likely
- to crash the hardware. */
- return -ENOTTY;
- }
- dbg("%s - retreiving serial line settings", __func__);
- /* set initial values in feature buffer */
- memset(feature_buffer, 0, sizeof(feature_buffer));
-
- do {
- retval = usb_control_msg(port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0),
- HID_REQ_GET_REPORT,
- USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
- 0x0300, 0, feature_buffer,
- sizeof(feature_buffer), 500);
-
- if (tries++ >= 3)
- break;
-
- } while (retval != sizeof(feature_buffer) &&
- retval != -ENODEV);
-
- if (retval != sizeof(feature_buffer)) {
- err("%s - failed to retrieve serial line settings - %d", __func__, retval);
- cypress_set_dead(port);
- return retval;
- } else {
- spin_lock_irqsave(&priv->lock, flags);
-
- /* store the config in one byte, and later use bit masks to check values */
- priv->current_config = feature_buffer[4];
- priv->baud_rate = *((u_int32_t *)feature_buffer);
- spin_unlock_irqrestore(&priv->lock, flags);
+ /* Change of speed ? */
+ else if (baud_rate != priv->baud_rate) {
+ dbg("%s - baud rate is changing", __func__);
+ retval = analyze_baud_rate(port, baud_rate);
+ if (retval >= 0) {
+ new_baudrate = retval;
+ dbg("%s - New baud rate set to %d",
+ __func__, new_baudrate);
}
+ }
+ dbg("%s - baud rate is being sent as %d",
+ __func__, new_baudrate);
+
+ memset(feature_buffer, 0, sizeof(feature_buffer));
+ /* fill the feature_buffer with new configuration */
+ *((u_int32_t *)feature_buffer) = new_baudrate;
+ feature_buffer[4] |= data_bits; /* assign data bits in 2 bit space ( max 3 ) */
+ /* 1 bit gap */
+ feature_buffer[4] |= (stop_bits << 3); /* assign stop bits in 1 bit space */
+ feature_buffer[4] |= (parity_enable << 4); /* assign parity flag in 1 bit space */
+ feature_buffer[4] |= (parity_type << 5); /* assign parity type in 1 bit space */
+ /* 1 bit gap */
+ feature_buffer[4] |= (reset << 7); /* assign reset at end of byte, 1 bit space */
+
+ dbg("%s - device is being sent this feature report:",
+ __func__);
+ dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__,
+ feature_buffer[0], feature_buffer[1],
+ feature_buffer[2], feature_buffer[3],
+ feature_buffer[4]);
+
+ do {
+ retval = usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
+ HID_REQ_SET_REPORT,
+ USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
+ 0x0300, 0, feature_buffer,
+ sizeof(feature_buffer), 500);
+
+ if (tries++ >= 3)
+ break;
+
+ } while (retval != sizeof(feature_buffer) &&
+ retval != -ENODEV);
+
+ if (retval != sizeof(feature_buffer)) {
+ err("%s - failed sending serial line settings - %d",
+ __func__, retval);
+ cypress_set_dead(port);
+ } else {
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->baud_rate = new_baudrate;
+ priv->current_config = feature_buffer[4];
+ spin_unlock_irqrestore(&priv->lock, flags);
+ /* If we asked for a speed change encode it */
+ if (baud_rate)
+ tty_encode_baud_rate(tty,
+ new_baudrate, new_baudrate);
+ }
+ break;
+ case CYPRESS_GET_CONFIG:
+ if (priv->get_cfg_unsafe) {
+ /* Not implemented for this device,
+ and if we try to do it we're likely
+ to crash the hardware. */
+ return -ENOTTY;
+ }
+ dbg("%s - retreiving serial line settings", __func__);
+ /* set initial values in feature buffer */
+ memset(feature_buffer, 0, sizeof(feature_buffer));
+
+ do {
+ retval = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ HID_REQ_GET_REPORT,
+ USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
+ 0x0300, 0, feature_buffer,
+ sizeof(feature_buffer), 500);
+
+ if (tries++ >= 3)
+ break;
+ } while (retval != sizeof(feature_buffer)
+ && retval != -ENODEV);
+
+ if (retval != sizeof(feature_buffer)) {
+ err("%s - failed to retrieve serial line settings - %d", __func__, retval);
+ cypress_set_dead(port);
+ return retval;
+ } else {
+ spin_lock_irqsave(&priv->lock, flags);
+ /* store the config in one byte, and later
+ use bit masks to check values */
+ priv->current_config = feature_buffer[4];
+ priv->baud_rate = *((u_int32_t *)feature_buffer);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
}
spin_lock_irqsave(&priv->lock, flags);
++priv->cmd_count;
@@ -468,14 +486,14 @@ static void cypress_set_dead(struct usb_serial_port *port)
*****************************************************************************/
-static int generic_startup (struct usb_serial *serial)
+static int generic_startup(struct usb_serial *serial)
{
struct cypress_private *priv;
struct usb_serial_port *port = serial->port[0];
dbg("%s - port %d", __func__, port->number);
- priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL);
+ priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
@@ -487,9 +505,9 @@ static int generic_startup (struct usb_serial *serial)
return -ENOMEM;
}
init_waitqueue_head(&priv->delta_msr_wait);
-
- usb_reset_configuration (serial->dev);
-
+
+ usb_reset_configuration(serial->dev);
+
priv->cmd_ctrl = 0;
priv->line_control = 0;
priv->termios_initialized = 0;
@@ -500,30 +518,30 @@ static int generic_startup (struct usb_serial *serial)
small. Otherwise we can use the slightly more compact
format. This is in accordance with the cypress_m8 serial
converter app note. */
- if (port->interrupt_out_size > 9) {
+ if (port->interrupt_out_size > 9)
priv->pkt_fmt = packet_format_1;
- } else {
+ else
priv->pkt_fmt = packet_format_2;
- }
+
if (interval > 0) {
priv->write_urb_interval = interval;
priv->read_urb_interval = interval;
dbg("%s - port %d read & write intervals forced to %d",
- __func__,port->number,interval);
+ __func__, port->number, interval);
} else {
priv->write_urb_interval = port->interrupt_out_urb->interval;
priv->read_urb_interval = port->interrupt_in_urb->interval;
dbg("%s - port %d intervals: read=%d write=%d",
- __func__,port->number,
- priv->read_urb_interval,priv->write_urb_interval);
+ __func__, port->number,
+ priv->read_urb_interval, priv->write_urb_interval);
}
usb_set_serial_port_data(port, priv);
-
+
return 0;
}
-static int cypress_earthmate_startup (struct usb_serial *serial)
+static int cypress_earthmate_startup(struct usb_serial *serial)
{
struct cypress_private *priv;
struct usb_serial_port *port = serial->port[0];
@@ -541,7 +559,8 @@ static int cypress_earthmate_startup (struct usb_serial *serial)
/* All Earthmate devices use the separated-count packet
format! Idiotic. */
priv->pkt_fmt = packet_format_1;
- if (serial->dev->descriptor.idProduct != cpu_to_le16(PRODUCT_ID_EARTHMATEUSB)) {
+ if (serial->dev->descriptor.idProduct !=
+ cpu_to_le16(PRODUCT_ID_EARTHMATEUSB)) {
/* The old original USB Earthmate seemed able to
handle GET_CONFIG requests; everything they've
produced since that time crashes if this command is
@@ -555,7 +574,7 @@ static int cypress_earthmate_startup (struct usb_serial *serial)
} /* cypress_earthmate_startup */
-static int cypress_hidcom_startup (struct usb_serial *serial)
+static int cypress_hidcom_startup(struct usb_serial *serial)
{
struct cypress_private *priv;
@@ -569,12 +588,12 @@ static int cypress_hidcom_startup (struct usb_serial *serial)
priv = usb_get_serial_port_data(serial->port[0]);
priv->chiptype = CT_CYPHIDCOM;
-
+
return 0;
} /* cypress_hidcom_startup */
-static int cypress_ca42v2_startup (struct usb_serial *serial)
+static int cypress_ca42v2_startup(struct usb_serial *serial)
{
struct cypress_private *priv;
@@ -593,11 +612,11 @@ static int cypress_ca42v2_startup (struct usb_serial *serial)
} /* cypress_ca42v2_startup */
-static void cypress_shutdown (struct usb_serial *serial)
+static void cypress_shutdown(struct usb_serial *serial)
{
struct cypress_private *priv;
- dbg ("%s - port %d", __func__, serial->port[0]->number);
+ dbg("%s - port %d", __func__, serial->port[0]->number);
/* all open ports are closed at this point */
@@ -611,7 +630,8 @@ static void cypress_shutdown (struct usb_serial *serial)
}
-static int cypress_open (struct usb_serial_port *port, struct file *filp)
+static int cypress_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
struct usb_serial *serial = port->serial;
@@ -636,37 +656,44 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
spin_unlock_irqrestore(&priv->lock, flags);
/* setting to zero could cause data loss */
- port->tty->low_latency = 1;
+ if (tty)
+ tty->low_latency = 1;
/* raise both lines and set termios */
spin_lock_irqsave(&priv->lock, flags);
priv->line_control = CONTROL_DTR | CONTROL_RTS;
priv->cmd_ctrl = 1;
spin_unlock_irqrestore(&priv->lock, flags);
- result = cypress_write(port, NULL, 0);
+ result = cypress_write(tty, port, NULL, 0);
if (result) {
- dev_err(&port->dev, "%s - failed setting the control lines - error %d\n", __func__, result);
+ dev_err(&port->dev,
+ "%s - failed setting the control lines - error %d\n",
+ __func__, result);
return result;
} else
dbg("%s - success setting the control lines", __func__);
- cypress_set_termios(port, &priv->tmp_termios);
+ if (tty)
+ cypress_set_termios(tty, port, &priv->tmp_termios);
/* setup the port and start reading from the device */
- if(!port->interrupt_in_urb){
+ if (!port->interrupt_in_urb) {
err("%s - interrupt_in_urb is empty!", __func__);
- return(-1);
+ return -1;
}
usb_fill_int_urb(port->interrupt_in_urb, serial->dev,
usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress),
- port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length,
+ port->interrupt_in_urb->transfer_buffer,
+ port->interrupt_in_urb->transfer_buffer_length,
cypress_read_int_callback, port, priv->read_urb_interval);
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
- if (result){
- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+ if (result) {
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, result);
cypress_set_dead(port);
}
@@ -674,7 +701,8 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
} /* cypress_open */
-static void cypress_close(struct usb_serial_port *port, struct file * filp)
+static void cypress_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned int c_cflag;
@@ -688,7 +716,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
spin_lock_irq(&priv->lock);
timeout = CYPRESS_CLOSING_WAIT;
init_waitqueue_entry(&wait, current);
- add_wait_queue(&port->tty->write_wait, &wait);
+ add_wait_queue(&tty->write_wait, &wait);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
if (cypress_buf_data_avail(priv->buf) == 0
@@ -701,7 +729,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
spin_lock_irq(&priv->lock);
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->tty->write_wait, &wait);
+ remove_wait_queue(&tty->write_wait, &wait);
/* clear out any remaining data in the buffer */
cypress_buf_clear(priv->buf);
spin_unlock_irq(&priv->lock);
@@ -713,19 +741,21 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
return;
}
/* wait for characters to drain from device */
- bps = tty_get_baud_rate(port->tty);
- if (bps > 1200)
- timeout = max((HZ*2560)/bps,HZ/10);
- else
- timeout = 2*HZ;
- schedule_timeout_interruptible(timeout);
+ if (tty) {
+ bps = tty_get_baud_rate(tty);
+ if (bps > 1200)
+ timeout = max((HZ * 2560) / bps, HZ / 10);
+ else
+ timeout = 2 * HZ;
+ schedule_timeout_interruptible(timeout);
+ }
dbg("%s - stopping urbs", __func__);
- usb_kill_urb (port->interrupt_in_urb);
- usb_kill_urb (port->interrupt_out_urb);
+ usb_kill_urb(port->interrupt_in_urb);
+ usb_kill_urb(port->interrupt_out_urb);
- if (port->tty) {
- c_cflag = port->tty->termios->c_cflag;
+ if (tty) {
+ c_cflag = tty->termios->c_cflag;
if (c_cflag & HUPCL) {
/* drop dtr and rts */
priv = usb_get_serial_port_data(port);
@@ -733,22 +763,23 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
priv->line_control = 0;
priv->cmd_ctrl = 1;
spin_unlock_irq(&priv->lock);
- cypress_write(port, NULL, 0);
+ cypress_write(tty, port, NULL, 0);
}
}
if (stats)
- dev_info (&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
- priv->bytes_in, priv->bytes_out, priv->cmd_count);
+ dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
+ priv->bytes_in, priv->bytes_out, priv->cmd_count);
mutex_unlock(&port->serial->disc_mutex);
} /* cypress_close */
-static int cypress_write(struct usb_serial_port *port, const unsigned char *buf, int count)
+static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
-
+
dbg("%s - port %d, %d bytes", __func__, port->number, count);
/* line control commands, which need to be executed immediately,
@@ -758,10 +789,10 @@ static int cypress_write(struct usb_serial_port *port, const unsigned char *buf,
count = 0;
goto finish;
}
-
+
if (!count)
return count;
-
+
spin_lock_irqsave(&priv->lock, flags);
count = cypress_buf_put(priv->buf, buf, count);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -778,13 +809,14 @@ static void cypress_send(struct usb_serial_port *port)
int count = 0, result, offset, actual_size;
struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
-
+
if (!priv->comm_is_ok)
return;
dbg("%s - port %d", __func__, port->number);
- dbg("%s - interrupt out size is %d", __func__, port->interrupt_out_size);
-
+ dbg("%s - interrupt out size is %d", __func__,
+ port->interrupt_out_size);
+
spin_lock_irqsave(&priv->lock, flags);
if (priv->write_urb_in_use) {
dbg("%s - can't write, urb in use", __func__);
@@ -794,7 +826,8 @@ static void cypress_send(struct usb_serial_port *port)
spin_unlock_irqrestore(&priv->lock, flags);
/* clear buffer */
- memset(port->interrupt_out_urb->transfer_buffer, 0, port->interrupt_out_size);
+ memset(port->interrupt_out_urb->transfer_buffer, 0,
+ port->interrupt_out_size);
spin_lock_irqsave(&priv->lock, flags);
switch (priv->pkt_fmt) {
@@ -825,9 +858,8 @@ static void cypress_send(struct usb_serial_port *port)
count = cypress_buf_get(priv->buf, &port->interrupt_out_buffer[offset],
port->interrupt_out_size-offset);
- if (count == 0) {
+ if (count == 0)
return;
- }
switch (priv->pkt_fmt) {
default:
@@ -851,26 +883,29 @@ send:
actual_size = count +
(priv->pkt_fmt == packet_format_1 ? 2 : 1);
- usb_serial_debug_data(debug, &port->dev, __func__, port->interrupt_out_size,
- port->interrupt_out_urb->transfer_buffer);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ port->interrupt_out_size,
+ port->interrupt_out_urb->transfer_buffer);
usb_fill_int_urb(port->interrupt_out_urb, port->serial->dev,
usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress),
port->interrupt_out_buffer, port->interrupt_out_size,
cypress_write_int_callback, port, priv->write_urb_interval);
- result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC);
+ result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__,
- result);
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, result);
priv->write_urb_in_use = 0;
cypress_set_dead(port);
}
spin_lock_irqsave(&priv->lock, flags);
- if (priv->cmd_ctrl) {
+ if (priv->cmd_ctrl)
priv->cmd_ctrl = 0;
- }
- priv->bytes_out += count; /* do not count the line control and size bytes */
+
+ /* do not count the line control and size bytes */
+ priv->bytes_out += count;
spin_unlock_irqrestore(&priv->lock, flags);
usb_serial_port_softint(port);
@@ -878,8 +913,9 @@ send:
/* returns how much space is available in the soft buffer */
-static int cypress_write_room(struct usb_serial_port *port)
+static int cypress_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
int room = 0;
unsigned long flags;
@@ -895,13 +931,14 @@ static int cypress_write_room(struct usb_serial_port *port)
}
-static int cypress_tiocmget (struct usb_serial_port *port, struct file *file)
+static int cypress_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
__u8 status, control;
unsigned int result = 0;
unsigned long flags;
-
+
dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags);
@@ -922,12 +959,13 @@ static int cypress_tiocmget (struct usb_serial_port *port, struct file *file)
}
-static int cypress_tiocmset (struct usb_serial_port *port, struct file *file,
+static int cypress_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
-
+
dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags);
@@ -942,63 +980,60 @@ static int cypress_tiocmset (struct usb_serial_port *port, struct file *file,
priv->cmd_ctrl = 1;
spin_unlock_irqrestore(&priv->lock, flags);
- return cypress_write(port, NULL, 0);
+ return cypress_write(tty, port, NULL, 0);
}
-static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+static int cypress_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
switch (cmd) {
- /* This code comes from drivers/char/serial.c and ftdi_sio.c */
- case TIOCMIWAIT:
- while (priv != NULL) {
- interruptible_sleep_on(&priv->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- else {
- char diff = priv->diff_status;
-
- if (diff == 0) {
- return -EIO; /* no change => error */
- }
-
- /* consume all events */
- priv->diff_status = 0;
-
- /* return 0 if caller wanted to know about these bits */
- if ( ((arg & TIOCM_RNG) && (diff & UART_RI)) ||
- ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
- ((arg & TIOCM_CD) && (diff & UART_CD)) ||
- ((arg & TIOCM_CTS) && (diff & UART_CTS)) ) {
- return 0;
- }
- /* otherwise caller can't care less about what happened,
- * and so we continue to wait for more events.
- */
- }
+ /* This code comes from drivers/char/serial.c and ftdi_sio.c */
+ case TIOCMIWAIT:
+ while (priv != NULL) {
+ interruptible_sleep_on(&priv->delta_msr_wait);
+ /* see if a signal did it */
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ else {
+ char diff = priv->diff_status;
+ if (diff == 0)
+ return -EIO; /* no change => error */
+
+ /* consume all events */
+ priv->diff_status = 0;
+
+ /* return 0 if caller wanted to know about
+ these bits */
+ if (((arg & TIOCM_RNG) && (diff & UART_RI)) ||
+ ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
+ ((arg & TIOCM_CD) && (diff & UART_CD)) ||
+ ((arg & TIOCM_CTS) && (diff & UART_CTS)))
+ return 0;
+ /* otherwise caller can't care less about what
+ * happened, and so we continue to wait for
+ * more events.
+ */
}
- return 0;
- break;
- default:
- break;
+ }
+ return 0;
+ default:
+ break;
}
-
dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __func__, cmd);
-
return -ENOIOCTLCMD;
} /* cypress_ioctl */
-static void cypress_set_termios (struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void cypress_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
- struct tty_struct *tty;
int data_bits, stop_bits, parity_type, parity_enable;
unsigned cflag, iflag;
unsigned long flags;
@@ -1007,8 +1042,6 @@ static void cypress_set_termios (struct usb_serial_port *port,
dbg("%s - port %d", __func__, port->number);
- tty = port->tty;
-
spin_lock_irqsave(&priv->lock, flags);
if (!priv->termios_initialized) {
if (priv->chiptype == CT_EARTHMATE) {
@@ -1060,28 +1093,24 @@ static void cypress_set_termios (struct usb_serial_port *port,
} else
parity_enable = parity_type = 0;
- if (cflag & CSIZE) {
- switch (cflag & CSIZE) {
- case CS5:
- data_bits = 0;
- break;
- case CS6:
- data_bits = 1;
- break;
- case CS7:
- data_bits = 2;
- break;
- case CS8:
- data_bits = 3;
- break;
- default:
- err("%s - CSIZE was set, but not CS5-CS8",
- __func__);
- data_bits = 3;
- }
- } else
+ switch (cflag & CSIZE) {
+ case CS5:
+ data_bits = 0;
+ break;
+ case CS6:
+ data_bits = 1;
+ break;
+ case CS7:
+ data_bits = 2;
+ break;
+ case CS8:
data_bits = 3;
-
+ break;
+ default:
+ err("%s - CSIZE was set, but not CS5-CS8",
+ __func__);
+ data_bits = 3;
+ }
spin_lock_irqsave(&priv->lock, flags);
oldlines = priv->line_control;
if ((cflag & CBAUD) == B0) {
@@ -1096,19 +1125,21 @@ static void cypress_set_termios (struct usb_serial_port *port,
"%d data_bits (+5)", __func__, stop_bits,
parity_enable, parity_type, data_bits);
- cypress_serial_control(port, tty_get_baud_rate(tty), data_bits, stop_bits,
- parity_enable, parity_type, 0, CYPRESS_SET_CONFIG);
+ cypress_serial_control(tty, port, tty_get_baud_rate(tty),
+ data_bits, stop_bits,
+ parity_enable, parity_type,
+ 0, CYPRESS_SET_CONFIG);
/* we perform a CYPRESS_GET_CONFIG so that the current settings are
* filled into the private structure this should confirm that all is
* working if it returns what we just set */
- cypress_serial_control(port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG);
+ cypress_serial_control(tty, port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG);
/* Here we can define custom tty settings for devices; the main tty
* termios flag base comes from empeg.c */
spin_lock_irqsave(&priv->lock, flags);
- if ( (priv->chiptype == CT_EARTHMATE) && (priv->baud_rate == 4800) ) {
+ if (priv->chiptype == CT_EARTHMATE && priv->baud_rate == 4800) {
dbg("Using custom termios settings for a baud rate of "
"4800bps.");
/* define custom termios settings for NMEA protocol */
@@ -1142,20 +1173,21 @@ static void cypress_set_termios (struct usb_serial_port *port,
/* if necessary, set lines */
if (linechange) {
priv->cmd_ctrl = 1;
- cypress_write(port, NULL, 0);
+ cypress_write(tty, port, NULL, 0);
}
} /* cypress_set_termios */
/* returns amount of data still left in soft buffer */
-static int cypress_chars_in_buffer(struct usb_serial_port *port)
+static int cypress_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
int chars = 0;
unsigned long flags;
dbg("%s - port %d", __func__, port->number);
-
+
spin_lock_irqsave(&priv->lock, flags);
chars = cypress_buf_data_avail(priv->buf);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1165,8 +1197,9 @@ static int cypress_chars_in_buffer(struct usb_serial_port *port)
}
-static void cypress_throttle (struct usb_serial_port *port)
+static void cypress_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -1178,8 +1211,9 @@ static void cypress_throttle (struct usb_serial_port *port)
}
-static void cypress_unthrottle (struct usb_serial_port *port)
+static void cypress_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
int actually_throttled, result;
unsigned long flags;
@@ -1232,12 +1266,13 @@ static void cypress_read_int_callback(struct urb *urb)
/* precursor to disconnect so just go away */
return;
case -EPIPE:
- usb_clear_halt(port->serial->dev,0x81);
+ usb_clear_halt(port->serial->dev, 0x81);
break;
default:
/* something ugly is going on... */
- dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n",
- __func__, status);
+ dev_err(&urb->dev->dev,
+ "%s - unexpected nonzero read status received: %d\n",
+ __func__, status);
cypress_set_dead(port);
return;
}
@@ -1251,7 +1286,7 @@ static void cypress_read_int_callback(struct urb *urb)
}
spin_unlock_irqrestore(&priv->lock, flags);
- tty = port->tty;
+ tty = port->port.tty;
if (!tty) {
dbg("%s - bad tty pointer - exiting", __func__);
return;
@@ -1285,8 +1320,8 @@ static void cypress_read_int_callback(struct urb *urb)
goto continue_read;
}
- usb_serial_debug_data (debug, &port->dev, __func__,
- urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
spin_lock_irqsave(&priv->lock, flags);
/* check to see if status has changed */
@@ -1327,7 +1362,7 @@ static void cypress_read_int_callback(struct urb *urb)
data[i]);
tty_insert_flip_char(tty, data[i], tty_flag);
}
- tty_flip_buffer_push(port->tty);
+ tty_flip_buffer_push(port->port.tty);
}
spin_lock_irqsave(&priv->lock, flags);
@@ -1339,13 +1374,14 @@ continue_read:
/* Continue trying to always read... unless the port has closed. */
- if (port->open_count > 0 && priv->comm_is_ok) {
+ if (port->port.count > 0 && priv->comm_is_ok) {
usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
usb_rcvintpipe(port->serial->dev,
port->interrupt_in_endpointAddress),
port->interrupt_in_urb->transfer_buffer,
port->interrupt_in_urb->transfer_buffer_length,
- cypress_read_int_callback, port, priv->read_urb_interval);
+ cypress_read_int_callback, port,
+ priv->read_urb_interval);
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
if (result) {
dev_err(&urb->dev->dev, "%s - failed resubmitting "
@@ -1369,42 +1405,43 @@ static void cypress_write_int_callback(struct urb *urb)
dbg("%s - port %d", __func__, port->number);
switch (status) {
- case 0:
- /* success */
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+ __func__, status);
+ priv->write_urb_in_use = 0;
+ return;
+ case -EPIPE: /* no break needed; clear halt and resubmit */
+ if (!priv->comm_is_ok)
break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
- priv->write_urb_in_use = 0;
+ usb_clear_halt(port->serial->dev, 0x02);
+ /* error in the urb, so we have to resubmit it */
+ dbg("%s - nonzero write bulk status received: %d",
+ __func__, status);
+ port->interrupt_out_urb->transfer_buffer_length = 1;
+ port->interrupt_out_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
+ if (!result)
return;
- case -EPIPE: /* no break needed; clear halt and resubmit */
- if (!priv->comm_is_ok)
- break;
- usb_clear_halt(port->serial->dev, 0x02);
- /* error in the urb, so we have to resubmit it */
- dbg("%s - nonzero write bulk status received: %d",
- __func__, status);
- port->interrupt_out_urb->transfer_buffer_length = 1;
- port->interrupt_out_urb->dev = port->serial->dev;
- result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
- if (!result)
- return;
- dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n",
- __func__, result);
- cypress_set_dead(port);
- break;
- default:
- dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n",
- __func__, status);
- cypress_set_dead(port);
- break;
+ dev_err(&urb->dev->dev,
+ "%s - failed resubmitting write urb, error %d\n",
+ __func__, result);
+ cypress_set_dead(port);
+ break;
+ default:
+ dev_err(&urb->dev->dev,
+ "%s - unexpected nonzero write status received: %d\n",
+ __func__, status);
+ cypress_set_dead(port);
+ break;
}
-
priv->write_urb_in_use = 0;
-
+
/* send any buffered data */
cypress_send(port);
}
@@ -1486,7 +1523,8 @@ static void cypress_buf_clear(struct cypress_buf *cb)
static unsigned int cypress_buf_data_avail(struct cypress_buf *cb)
{
if (cb != NULL)
- return ((cb->buf_size + cb->buf_put - cb->buf_get) % cb->buf_size);
+ return (cb->buf_size + cb->buf_put - cb->buf_get)
+ % cb->buf_size;
else
return 0;
}
@@ -1502,7 +1540,8 @@ static unsigned int cypress_buf_data_avail(struct cypress_buf *cb)
static unsigned int cypress_buf_space_avail(struct cypress_buf *cb)
{
if (cb != NULL)
- return ((cb->buf_size + cb->buf_get - cb->buf_put - 1) % cb->buf_size);
+ return (cb->buf_size + cb->buf_get - cb->buf_put - 1)
+ % cb->buf_size;
else
return 0;
}
@@ -1602,9 +1641,9 @@ static unsigned int cypress_buf_get(struct cypress_buf *cb, char *buf,
static int __init cypress_init(void)
{
int retval;
-
+
dbg("%s", __func__);
-
+
retval = usb_serial_register(&cypress_earthmate_device);
if (retval)
goto failed_em_register;
@@ -1632,23 +1671,23 @@ failed_em_register:
}
-static void __exit cypress_exit (void)
+static void __exit cypress_exit(void)
{
dbg("%s", __func__);
- usb_deregister (&cypress_driver);
- usb_serial_deregister (&cypress_earthmate_device);
- usb_serial_deregister (&cypress_hidcom_device);
- usb_serial_deregister (&cypress_ca42v2_device);
+ usb_deregister(&cypress_driver);
+ usb_serial_deregister(&cypress_earthmate_device);
+ usb_serial_deregister(&cypress_hidcom_device);
+ usb_serial_deregister(&cypress_ca42v2_device);
}
module_init(cypress_init);
module_exit(cypress_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_VERSION( DRIVER_VERSION );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/cypress_m8.h b/drivers/usb/serial/cypress_m8.h
index 0388065bb79..e772b01ac3a 100644
--- a/drivers/usb/serial/cypress_m8.h
+++ b/drivers/usb/serial/cypress_m8.h
@@ -54,7 +54,7 @@
#define UART_DSR 0x20 /* data set ready - flow control - device to host */
#define CONTROL_RTS 0x10 /* request to send - flow control - host to device */
#define UART_CTS 0x10 /* clear to send - flow control - device to host */
-#define UART_RI 0x10 /* ring indicator - modem - device to host */
+#define UART_RI 0x10 /* ring indicator - modem - device to host */
#define UART_CD 0x40 /* carrier detect - modem - device to host */
#define CYP_ERROR 0x08 /* received from input report - device to host */
/* Note - the below has nothing to to with the "feature report" reset */
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 28bc6fcf44f..240aad1acaa 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -15,7 +15,7 @@
* Al Borchers (borchers@steinerpoint.com)
*
* (12/03/2001) gkh
-* switched to using port->open_count instead of private version.
+* switched to using port->port.count instead of private version.
* Removed port->active
*
* (04/08/2001) gb
@@ -241,7 +241,7 @@
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/wait.h>
#include <linux/usb/serial.h>
@@ -441,22 +441,23 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
unsigned int modem_signals, int interruptible);
static int digi_transmit_idle(struct usb_serial_port *port,
unsigned long timeout);
-static void digi_rx_throttle (struct usb_serial_port *port);
-static void digi_rx_unthrottle (struct usb_serial_port *port);
-static void digi_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios);
-static void digi_break_ctl(struct usb_serial_port *port, int break_state);
-static int digi_ioctl(struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg);
-static int digi_tiocmget(struct usb_serial_port *port, struct file *file);
-static int digi_tiocmset(struct usb_serial_port *port, struct file *file,
+static void digi_rx_throttle(struct tty_struct *tty);
+static void digi_rx_unthrottle(struct tty_struct *tty);
+static void digi_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios);
+static void digi_break_ctl(struct tty_struct *tty, int break_state);
+static int digi_tiocmget(struct tty_struct *tty, struct file *file);
+static int digi_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
-static int digi_write(struct usb_serial_port *port, const unsigned char *buf, int count);
+static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
static void digi_write_bulk_callback(struct urb *urb);
-static int digi_write_room(struct usb_serial_port *port);
-static int digi_chars_in_buffer(struct usb_serial_port *port);
-static int digi_open(struct usb_serial_port *port, struct file *filp);
-static void digi_close(struct usb_serial_port *port, struct file *filp);
+static int digi_write_room(struct tty_struct *tty);
+static int digi_chars_in_buffer(struct tty_struct *tty);
+static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
static int digi_startup_device(struct usb_serial *serial);
static int digi_startup(struct usb_serial *serial);
static void digi_shutdown(struct usb_serial *serial);
@@ -485,7 +486,7 @@ static struct usb_device_id id_table_4 [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver digi_driver = {
.name = "digi_acceleport",
@@ -516,7 +517,6 @@ static struct usb_serial_driver digi_acceleport_2_device = {
.chars_in_buffer = digi_chars_in_buffer,
.throttle = digi_rx_throttle,
.unthrottle = digi_rx_unthrottle,
- .ioctl = digi_ioctl,
.set_termios = digi_set_termios,
.break_ctl = digi_break_ctl,
.tiocmget = digi_tiocmget,
@@ -543,7 +543,6 @@ static struct usb_serial_driver digi_acceleport_4_device = {
.chars_in_buffer = digi_chars_in_buffer,
.throttle = digi_rx_throttle,
.unthrottle = digi_rx_unthrottle,
- .ioctl = digi_ioctl,
.set_termios = digi_set_termios,
.break_ctl = digi_break_ctl,
.tiocmget = digi_tiocmget,
@@ -556,17 +555,17 @@ static struct usb_serial_driver digi_acceleport_4_device = {
/* Functions */
/*
-* Cond Wait Interruptible Timeout Irqrestore
-*
-* Do spin_unlock_irqrestore and interruptible_sleep_on_timeout
-* so that wake ups are not lost if they occur between the unlock
-* and the sleep. In other words, spin_unlock_irqrestore and
-* interruptible_sleep_on_timeout are "atomic" with respect to
-* wake ups. This is used to implement condition variables.
-*
-* interruptible_sleep_on_timeout is deprecated and has been replaced
-* with the equivalent code.
-*/
+ * Cond Wait Interruptible Timeout Irqrestore
+ *
+ * Do spin_unlock_irqrestore and interruptible_sleep_on_timeout
+ * so that wake ups are not lost if they occur between the unlock
+ * and the sleep. In other words, spin_unlock_irqrestore and
+ * interruptible_sleep_on_timeout are "atomic" with respect to
+ * wake ups. This is used to implement condition variables.
+ *
+ * interruptible_sleep_on_timeout is deprecated and has been replaced
+ * with the equivalent code.
+ */
static long cond_wait_interruptible_timeout_irqrestore(
wait_queue_head_t *q, long timeout,
@@ -585,15 +584,16 @@ __releases(lock)
/*
-* Digi Wakeup Write
-*
-* Wake up port, line discipline, and tty processes sleeping
-* on writes.
-*/
+ * Digi Wakeup Write
+ *
+ * Wake up port, line discipline, and tty processes sleeping
+ * on writes.
+ */
static void digi_wakeup_write_lock(struct work_struct *work)
{
- struct digi_port *priv = container_of(work, struct digi_port, dp_wakeup_work);
+ struct digi_port *priv =
+ container_of(work, struct digi_port, dp_wakeup_work);
struct usb_serial_port *port = priv->dp_port;
unsigned long flags;
@@ -604,20 +604,20 @@ static void digi_wakeup_write_lock(struct work_struct *work)
static void digi_wakeup_write(struct usb_serial_port *port)
{
- tty_wakeup(port->tty);
+ tty_wakeup(port->port.tty);
}
/*
-* Digi Write OOB Command
-*
-* Write commands on the out of band port. Commands are 4
-* bytes each, multiple commands can be sent at once, and
-* no command will be split across USB packets. Returns 0
-* if successful, -EINTR if interrupted while sleeping and
-* the interruptible flag is true, or a negative error
-* returned by usb_submit_urb.
-*/
+ * Digi Write OOB Command
+ *
+ * Write commands on the out of band port. Commands are 4
+ * bytes each, multiple commands can be sent at once, and
+ * no command will be split across USB packets. Returns 0
+ * if successful, -EINTR if interrupted while sleeping and
+ * the interruptible flag is true, or a negative error
+ * returned by usb_submit_urb.
+ */
static int digi_write_oob_command(struct usb_serial_port *port,
unsigned char *buf, int count, int interruptible)
@@ -632,8 +632,8 @@ static int digi_write_oob_command(struct usb_serial_port *port,
dbg("digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, count);
spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
- while(count > 0) {
- while(oob_port->write_urb->status == -EINPROGRESS
+ while (count > 0) {
+ while (oob_port->write_urb->status == -EINPROGRESS
|| oob_priv->dp_write_urb_in_use) {
cond_wait_interruptible_timeout_irqrestore(
&oob_port->write_wait, DIGI_RETRY_TIMEOUT,
@@ -650,7 +650,8 @@ static int digi_write_oob_command(struct usb_serial_port *port,
memcpy(oob_port->write_urb->transfer_buffer, buf, len);
oob_port->write_urb->transfer_buffer_length = len;
oob_port->write_urb->dev = port->serial->dev;
- if ((ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0) {
+ ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC);
+ if (ret == 0) {
oob_priv->dp_write_urb_in_use = 1;
count -= len;
buf += len;
@@ -665,16 +666,16 @@ static int digi_write_oob_command(struct usb_serial_port *port,
/*
-* Digi Write In Band Command
-*
-* Write commands on the given port. Commands are 4
-* bytes each, multiple commands can be sent at once, and
-* no command will be split across USB packets. If timeout
-* is non-zero, write in band command will return after
-* waiting unsuccessfully for the URB status to clear for
-* timeout ticks. Returns 0 if successful, or a negative
-* error returned by digi_write.
-*/
+ * Digi Write In Band Command
+ *
+ * Write commands on the given port. Commands are 4
+ * bytes each, multiple commands can be sent at once, and
+ * no command will be split across USB packets. If timeout
+ * is non-zero, write in band command will return after
+ * waiting unsuccessfully for the URB status to clear for
+ * timeout ticks. Returns 0 if successful, or a negative
+ * error returned by digi_write.
+ */
static int digi_write_inb_command(struct usb_serial_port *port,
unsigned char *buf, int count, unsigned long timeout)
@@ -694,9 +695,10 @@ static int digi_write_inb_command(struct usb_serial_port *port,
timeout = ULONG_MAX;
spin_lock_irqsave(&priv->dp_port_lock, flags);
- while(count > 0 && ret == 0) {
- while((port->write_urb->status == -EINPROGRESS
- || priv->dp_write_urb_in_use) && time_before(jiffies, timeout)) {
+ while (count > 0 && ret == 0) {
+ while ((port->write_urb->status == -EINPROGRESS
+ || priv->dp_write_urb_in_use)
+ && time_before(jiffies, timeout)) {
cond_wait_interruptible_timeout_irqrestore(
&port->write_wait, DIGI_RETRY_TIMEOUT,
&priv->dp_port_lock, flags);
@@ -727,7 +729,8 @@ static int digi_write_inb_command(struct usb_serial_port *port,
}
port->write_urb->dev = port->serial->dev;
- if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) {
+ ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (ret == 0) {
priv->dp_write_urb_in_use = 1;
priv->dp_out_buf_len = 0;
count -= len;
@@ -745,14 +748,14 @@ static int digi_write_inb_command(struct usb_serial_port *port,
/*
-* Digi Set Modem Signals
-*
-* Sets or clears DTR and RTS on the port, according to the
-* modem_signals argument. Use TIOCM_DTR and TIOCM_RTS flags
-* for the modem_signals argument. Returns 0 if successful,
-* -EINTR if interrupted while sleeping, or a non-zero error
-* returned by usb_submit_urb.
-*/
+ * Digi Set Modem Signals
+ *
+ * Sets or clears DTR and RTS on the port, according to the
+ * modem_signals argument. Use TIOCM_DTR and TIOCM_RTS flags
+ * for the modem_signals argument. Returns 0 if successful,
+ * -EINTR if interrupted while sleeping, or a non-zero error
+ * returned by usb_submit_urb.
+ */
static int digi_set_modem_signals(struct usb_serial_port *port,
unsigned int modem_signals, int interruptible)
@@ -760,7 +763,7 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
int ret;
struct digi_port *port_priv = usb_get_serial_port_data(port);
- struct usb_serial_port *oob_port = (struct usb_serial_port *)((struct digi_serial *)(usb_get_serial_data(port->serial)))->ds_oob_port;
+ struct usb_serial_port *oob_port = (struct usb_serial_port *) ((struct digi_serial *)(usb_get_serial_data(port->serial)))->ds_oob_port;
struct digi_port *oob_priv = usb_get_serial_port_data(oob_port);
unsigned char *data = oob_port->write_urb->transfer_buffer;
unsigned long flags = 0;
@@ -772,7 +775,8 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
spin_lock(&port_priv->dp_port_lock);
- while(oob_port->write_urb->status == -EINPROGRESS || oob_priv->dp_write_urb_in_use) {
+ while (oob_port->write_urb->status == -EINPROGRESS ||
+ oob_priv->dp_write_urb_in_use) {
spin_unlock(&port_priv->dp_port_lock);
cond_wait_interruptible_timeout_irqrestore(
&oob_port->write_wait, DIGI_RETRY_TIMEOUT,
@@ -784,17 +788,20 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
}
data[0] = DIGI_CMD_SET_DTR_SIGNAL;
data[1] = port_priv->dp_port_num;
- data[2] = (modem_signals&TIOCM_DTR) ? DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE;
+ data[2] = (modem_signals & TIOCM_DTR) ?
+ DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE;
data[3] = 0;
data[4] = DIGI_CMD_SET_RTS_SIGNAL;
data[5] = port_priv->dp_port_num;
- data[6] = (modem_signals&TIOCM_RTS) ? DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE;
+ data[6] = (modem_signals & TIOCM_RTS) ?
+ DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE;
data[7] = 0;
oob_port->write_urb->transfer_buffer_length = 8;
oob_port->write_urb->dev = port->serial->dev;
- if ((ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0) {
+ ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC);
+ if (ret == 0) {
oob_priv->dp_write_urb_in_use = 1;
port_priv->dp_modem_signals =
(port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS))
@@ -808,16 +815,16 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
}
/*
-* Digi Transmit Idle
-*
-* Digi transmit idle waits, up to timeout ticks, for the transmitter
-* to go idle. It returns 0 if successful or a negative error.
-*
-* There are race conditions here if more than one process is calling
-* digi_transmit_idle on the same port at the same time. However, this
-* is only called from close, and only one process can be in close on a
-* port at a time, so its ok.
-*/
+ * Digi Transmit Idle
+ *
+ * Digi transmit idle waits, up to timeout ticks, for the transmitter
+ * to go idle. It returns 0 if successful or a negative error.
+ *
+ * There are race conditions here if more than one process is calling
+ * digi_transmit_idle on the same port at the same time. However, this
+ * is only called from close, and only one process can be in close on a
+ * port at a time, so its ok.
+ */
static int digi_transmit_idle(struct usb_serial_port *port,
unsigned long timeout)
@@ -836,12 +843,13 @@ static int digi_transmit_idle(struct usb_serial_port *port,
timeout += jiffies;
- if ((ret = digi_write_inb_command(port, buf, 2, timeout - jiffies)) != 0)
+ ret = digi_write_inb_command(port, buf, 2, timeout - jiffies);
+ if (ret != 0)
return ret;
spin_lock_irqsave(&priv->dp_port_lock, flags);
- while(time_before(jiffies, timeout) && !priv->dp_transmit_idle) {
+ while (time_before(jiffies, timeout) && !priv->dp_transmit_idle) {
cond_wait_interruptible_timeout_irqrestore(
&priv->dp_transmit_idle_wait, DIGI_RETRY_TIMEOUT,
&priv->dp_port_lock, flags);
@@ -856,9 +864,10 @@ static int digi_transmit_idle(struct usb_serial_port *port,
}
-static void digi_rx_throttle(struct usb_serial_port *port)
+static void digi_rx_throttle(struct tty_struct *tty)
{
unsigned long flags;
+ struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
@@ -872,10 +881,11 @@ static void digi_rx_throttle(struct usb_serial_port *port)
}
-static void digi_rx_unthrottle(struct usb_serial_port *port)
+static void digi_rx_unthrottle(struct tty_struct *tty)
{
int ret = 0;
unsigned long flags;
+ struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
dbg("digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num);
@@ -900,26 +910,25 @@ static void digi_rx_unthrottle(struct usb_serial_port *port)
}
-static void digi_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void digi_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
-
struct digi_port *priv = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
unsigned int iflag = tty->termios->c_iflag;
unsigned int cflag = tty->termios->c_cflag;
unsigned int old_iflag = old_termios->c_iflag;
unsigned int old_cflag = old_termios->c_cflag;
unsigned char buf[32];
unsigned int modem_signals;
- int arg,ret;
+ int arg, ret;
int i = 0;
speed_t baud;
dbg("digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x", priv->dp_port_num, iflag, old_iflag, cflag, old_cflag);
/* set baud rate */
- if ((baud = tty_get_baud_rate(tty)) != tty_termios_baud_rate(old_termios)) {
+ baud = tty_get_baud_rate(tty);
+ if (baud != tty_termios_baud_rate(old_termios)) {
arg = -1;
/* reassert DTR and (maybe) RTS on transition from B0 */
@@ -933,30 +942,30 @@ static void digi_set_termios(struct usb_serial_port *port,
digi_set_modem_signals(port, modem_signals, 1);
}
switch (baud) {
- /* drop DTR and RTS on transition to B0 */
- case 0: digi_set_modem_signals(port, 0, 1); break;
- case 50: arg = DIGI_BAUD_50; break;
- case 75: arg = DIGI_BAUD_75; break;
- case 110: arg = DIGI_BAUD_110; break;
- case 150: arg = DIGI_BAUD_150; break;
- case 200: arg = DIGI_BAUD_200; break;
- case 300: arg = DIGI_BAUD_300; break;
- case 600: arg = DIGI_BAUD_600; break;
- case 1200: arg = DIGI_BAUD_1200; break;
- case 1800: arg = DIGI_BAUD_1800; break;
- case 2400: arg = DIGI_BAUD_2400; break;
- case 4800: arg = DIGI_BAUD_4800; break;
- case 9600: arg = DIGI_BAUD_9600; break;
- case 19200: arg = DIGI_BAUD_19200; break;
- case 38400: arg = DIGI_BAUD_38400; break;
- case 57600: arg = DIGI_BAUD_57600; break;
- case 115200: arg = DIGI_BAUD_115200; break;
- case 230400: arg = DIGI_BAUD_230400; break;
- case 460800: arg = DIGI_BAUD_460800; break;
- default:
- arg = DIGI_BAUD_9600;
- baud = 9600;
- break;
+ /* drop DTR and RTS on transition to B0 */
+ case 0: digi_set_modem_signals(port, 0, 1); break;
+ case 50: arg = DIGI_BAUD_50; break;
+ case 75: arg = DIGI_BAUD_75; break;
+ case 110: arg = DIGI_BAUD_110; break;
+ case 150: arg = DIGI_BAUD_150; break;
+ case 200: arg = DIGI_BAUD_200; break;
+ case 300: arg = DIGI_BAUD_300; break;
+ case 600: arg = DIGI_BAUD_600; break;
+ case 1200: arg = DIGI_BAUD_1200; break;
+ case 1800: arg = DIGI_BAUD_1800; break;
+ case 2400: arg = DIGI_BAUD_2400; break;
+ case 4800: arg = DIGI_BAUD_4800; break;
+ case 9600: arg = DIGI_BAUD_9600; break;
+ case 19200: arg = DIGI_BAUD_19200; break;
+ case 38400: arg = DIGI_BAUD_38400; break;
+ case 57600: arg = DIGI_BAUD_57600; break;
+ case 115200: arg = DIGI_BAUD_115200; break;
+ case 230400: arg = DIGI_BAUD_230400; break;
+ case 460800: arg = DIGI_BAUD_460800; break;
+ default:
+ arg = DIGI_BAUD_9600;
+ baud = 9600;
+ break;
}
if (arg != -1) {
buf[i++] = DIGI_CMD_SET_BAUD_RATE;
@@ -1082,14 +1091,16 @@ static void digi_set_termios(struct usb_serial_port *port,
buf[i++] = arg;
buf[i++] = 0;
}
- if ((ret = digi_write_oob_command(port, buf, i, 1)) != 0)
+ ret = digi_write_oob_command(port, buf, i, 1);
+ if (ret != 0)
dbg("digi_set_termios: write oob failed, ret=%d", ret);
tty_encode_baud_rate(tty, baud, baud);
}
-static void digi_break_ctl(struct usb_serial_port *port, int break_state)
+static void digi_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned char buf[4];
buf[0] = DIGI_CMD_BREAK_CONTROL;
@@ -1100,8 +1111,9 @@ static void digi_break_ctl(struct usb_serial_port *port, int break_state)
}
-static int digi_tiocmget(struct usb_serial_port *port, struct file *file)
+static int digi_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
unsigned int val;
unsigned long flags;
@@ -1115,9 +1127,10 @@ static int digi_tiocmget(struct usb_serial_port *port, struct file *file)
}
-static int digi_tiocmset(struct usb_serial_port *port, struct file *file,
+static int digi_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
unsigned int val;
unsigned long flags;
@@ -1131,30 +1144,11 @@ static int digi_tiocmset(struct usb_serial_port *port, struct file *file,
}
-static int digi_ioctl(struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct digi_port *priv = usb_get_serial_port_data(port);
- dbg("digi_ioctl: TOP: port=%d, cmd=0x%x", priv->dp_port_num, cmd);
-
- switch (cmd) {
- case TIOCMIWAIT:
- /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
- /* TODO */
- return 0;
- case TIOCGICOUNT:
- /* return count of modemline transitions */
- /* TODO */
- return 0;
- }
- return -ENOIOCTLCMD;
-
-}
-
-static int digi_write(struct usb_serial_port *port, const unsigned char *buf, int count)
+static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
- int ret,data_len,new_len;
+ int ret, data_len, new_len;
struct digi_port *priv = usb_get_serial_port_data(port);
unsigned char *data = port->write_urb->transfer_buffer;
unsigned long flags = 0;
@@ -1172,7 +1166,8 @@ static int digi_write(struct usb_serial_port *port, const unsigned char *buf, in
spin_lock_irqsave(&priv->dp_port_lock, flags);
/* wait for urb status clear to submit another urb */
- if (port->write_urb->status == -EINPROGRESS || priv->dp_write_urb_in_use) {
+ if (port->write_urb->status == -EINPROGRESS ||
+ priv->dp_write_urb_in_use) {
/* buffer data if count is 1 (probably put_char) if possible */
if (count == 1 && priv->dp_out_buf_len < DIGI_OUT_BUF_SIZE) {
priv->dp_out_buf[priv->dp_out_buf_len++] = *buf;
@@ -1207,7 +1202,8 @@ static int digi_write(struct usb_serial_port *port, const unsigned char *buf, in
/* copy in new data */
memcpy(data, buf, new_len);
- if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) {
+ ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (ret == 0) {
priv->dp_write_urb_in_use = 1;
ret = new_len;
priv->dp_out_buf_len = 0;
@@ -1221,7 +1217,7 @@ static int digi_write(struct usb_serial_port *port, const unsigned char *buf, in
dbg("digi_write: returning %d", ret);
return ret;
-}
+}
static void digi_write_bulk_callback(struct urb *urb)
{
@@ -1236,13 +1232,13 @@ static void digi_write_bulk_callback(struct urb *urb)
dbg("digi_write_bulk_callback: TOP, urb->status=%d", status);
/* port and serial sanity check */
- if (port == NULL || (priv=usb_get_serial_port_data(port)) == NULL) {
+ if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) {
err("%s: port or port->private is NULL, status=%d",
__func__, status);
return;
}
serial = port->serial;
- if (serial == NULL || (serial_priv=usb_get_serial_data(serial)) == NULL) {
+ if (serial == NULL || (serial_priv = usb_get_serial_data(serial)) == NULL) {
err("%s: serial or serial->private is NULL, status=%d",
__func__, status);
return;
@@ -1261,17 +1257,19 @@ static void digi_write_bulk_callback(struct urb *urb)
/* try to send any buffered data on this port, if it is open */
spin_lock(&priv->dp_port_lock);
priv->dp_write_urb_in_use = 0;
- if (port->open_count && port->write_urb->status != -EINPROGRESS
+ if (port->port.count && port->write_urb->status != -EINPROGRESS
&& priv->dp_out_buf_len > 0) {
*((unsigned char *)(port->write_urb->transfer_buffer))
= (unsigned char)DIGI_CMD_SEND_DATA;
- *((unsigned char *)(port->write_urb->transfer_buffer)+1)
+ *((unsigned char *)(port->write_urb->transfer_buffer) + 1)
= (unsigned char)priv->dp_out_buf_len;
- port->write_urb->transfer_buffer_length = priv->dp_out_buf_len+2;
+ port->write_urb->transfer_buffer_length =
+ priv->dp_out_buf_len + 2;
port->write_urb->dev = serial->dev;
- memcpy(port->write_urb->transfer_buffer+2, priv->dp_out_buf,
+ memcpy(port->write_urb->transfer_buffer + 2, priv->dp_out_buf,
priv->dp_out_buf_len);
- if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) {
+ ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (ret == 0) {
priv->dp_write_urb_in_use = 1;
priv->dp_out_buf_len = 0;
}
@@ -1288,16 +1286,17 @@ static void digi_write_bulk_callback(struct urb *urb)
__func__, ret, priv->dp_port_num);
}
-static int digi_write_room(struct usb_serial_port *port)
+static int digi_write_room(struct tty_struct *tty)
{
-
- int room;
+ struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
+ int room;
unsigned long flags = 0;
spin_lock_irqsave(&priv->dp_port_lock, flags);
- if (port->write_urb->status == -EINPROGRESS || priv->dp_write_urb_in_use)
+ if (port->write_urb->status == -EINPROGRESS ||
+ priv->dp_write_urb_in_use)
room = 0;
else
room = port->bulk_out_size - 2 - priv->dp_out_buf_len;
@@ -1308,12 +1307,11 @@ static int digi_write_room(struct usb_serial_port *port)
}
-static int digi_chars_in_buffer(struct usb_serial_port *port)
+static int digi_chars_in_buffer(struct tty_struct *tty)
{
-
+ struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
-
if (port->write_urb->status == -EINPROGRESS
|| priv->dp_write_urb_in_use) {
dbg("digi_chars_in_buffer: port=%d, chars=%d",
@@ -1329,7 +1327,8 @@ static int digi_chars_in_buffer(struct usb_serial_port *port)
}
-static int digi_open(struct usb_serial_port *port, struct file *filp)
+static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
int ret;
unsigned char buf[32];
@@ -1338,7 +1337,7 @@ static int digi_open(struct usb_serial_port *port, struct file *filp)
unsigned long flags = 0;
dbg("digi_open: TOP: port=%d, open_count=%d",
- priv->dp_port_num, port->open_count);
+ priv->dp_port_num, port->port.count);
/* be sure the device is started up */
if (digi_startup_device(port->serial) != 0)
@@ -1353,7 +1352,7 @@ static int digi_open(struct usb_serial_port *port, struct file *filp)
}
/* wait for a close in progress to finish */
- while(priv->dp_in_close) {
+ while (priv->dp_in_close) {
cond_wait_interruptible_timeout_irqrestore(
&priv->dp_close_wait, DIGI_RETRY_TIMEOUT,
&priv->dp_port_lock, flags);
@@ -1363,7 +1362,7 @@ static int digi_open(struct usb_serial_port *port, struct file *filp)
}
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
-
+
/* read modem signals automatically whenever they change */
buf[0] = DIGI_CMD_READ_INPUT_SIGNALS;
buf[1] = priv->dp_port_num;
@@ -1376,13 +1375,16 @@ static int digi_open(struct usb_serial_port *port, struct file *filp)
buf[6] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
buf[7] = 0;
- if ((ret = digi_write_oob_command(port, buf, 8, 1)) != 0)
+ ret = digi_write_oob_command(port, buf, 8, 1);
+ if (ret != 0)
dbg("digi_open: write oob failed, ret=%d", ret);
/* set termios settings */
- not_termios.c_cflag = ~port->tty->termios->c_cflag;
- not_termios.c_iflag = ~port->tty->termios->c_iflag;
- digi_set_termios(port, &not_termios);
+ if (tty) {
+ not_termios.c_cflag = ~tty->termios->c_cflag;
+ not_termios.c_iflag = ~tty->termios->c_iflag;
+ digi_set_termios(tty, port, &not_termios);
+ }
/* set DTR and RTS */
digi_set_modem_signals(port, TIOCM_DTR|TIOCM_RTS, 1);
@@ -1391,16 +1393,16 @@ static int digi_open(struct usb_serial_port *port, struct file *filp)
}
-static void digi_close(struct usb_serial_port *port, struct file *filp)
+static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
DEFINE_WAIT(wait);
int ret;
unsigned char buf[32];
- struct tty_struct *tty = port->tty;
struct digi_port *priv = usb_get_serial_port_data(port);
dbg("digi_close: TOP: port=%d, open_count=%d",
- priv->dp_port_num, port->open_count);
+ priv->dp_port_num, port->port.count);
mutex_lock(&port->serial->disc_mutex);
/* if disconnected, just clear flags */
@@ -1425,9 +1427,8 @@ static void digi_close(struct usb_serial_port *port, struct file *filp)
if (port->serial->dev) {
/* wait for transmit idle */
- if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) {
+ if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0)
digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
- }
/* drop DTR and RTS */
digi_set_modem_signals(port, 0, 0);
@@ -1461,11 +1462,13 @@ static void digi_close(struct usb_serial_port *port, struct file *filp)
buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
buf[19] = 0;
- if ((ret = digi_write_oob_command(port, buf, 20, 0)) != 0)
+ ret = digi_write_oob_command(port, buf, 20, 0);
+ if (ret != 0)
dbg("digi_close: write oob failed, ret=%d", ret);
/* wait for final commands on oob port to complete */
- prepare_to_wait(&priv->dp_flush_wait, &wait, TASK_INTERRUPTIBLE);
+ prepare_to_wait(&priv->dp_flush_wait, &wait,
+ TASK_INTERRUPTIBLE);
schedule_timeout(DIGI_CLOSE_TIMEOUT);
finish_wait(&priv->dp_flush_wait, &wait);
@@ -1485,15 +1488,15 @@ exit:
/*
-* Digi Startup Device
-*
-* Starts reads on all ports. Must be called AFTER startup, with
-* urbs initialized. Returns 0 if successful, non-zero error otherwise.
-*/
+ * Digi Startup Device
+ *
+ * Starts reads on all ports. Must be called AFTER startup, with
+ * urbs initialized. Returns 0 if successful, non-zero error otherwise.
+ */
static int digi_startup_device(struct usb_serial *serial)
{
- int i,ret = 0;
+ int i, ret = 0;
struct digi_serial *serial_priv = usb_get_serial_data(serial);
struct usb_serial_port *port;
@@ -1511,7 +1514,8 @@ static int digi_startup_device(struct usb_serial *serial)
for (i = 0; i < serial->type->num_ports + 1; i++) {
port = serial->port[i];
port->write_urb->dev = port->serial->dev;
- if ((ret = usb_submit_urb(port->read_urb, GFP_KERNEL)) != 0) {
+ ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (ret != 0) {
err("%s: usb_submit_urb failed, ret=%d, port=%d",
__func__, ret, i);
break;
@@ -1532,7 +1536,7 @@ static int digi_startup(struct usb_serial *serial)
/* allocate the private data structures for all ports */
/* number of regular ports + 1 for the out-of-band port */
- for(i = 0; i < serial->type->num_ports + 1; i++) {
+ for (i = 0; i < serial->type->num_ports + 1; i++) {
/* allocate port private structure */
priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL);
if (priv == NULL) {
@@ -1595,7 +1599,7 @@ static void digi_shutdown(struct usb_serial *serial)
/* free the private data structures for all ports */
/* number of regular ports + 1 for the out-of-band port */
- for(i = 0; i < serial->type->num_ports + 1; i++)
+ for (i = 0; i < serial->type->num_ports + 1; i++)
kfree(usb_get_serial_port_data(serial->port[i]));
kfree(usb_get_serial_data(serial));
}
@@ -1618,7 +1622,7 @@ static void digi_read_bulk_callback(struct urb *urb)
return;
}
if (port->serial == NULL ||
- (serial_priv=usb_get_serial_data(port->serial)) == NULL) {
+ (serial_priv = usb_get_serial_data(port->serial)) == NULL) {
err("%s: serial is bad or serial->private is NULL, status=%d",
__func__, status);
return;
@@ -1642,45 +1646,46 @@ static void digi_read_bulk_callback(struct urb *urb)
/* continue read */
urb->dev = port->serial->dev;
- if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret != 0) {
err("%s: failed resubmitting urb, ret=%d, port=%d",
__func__, ret, priv->dp_port_num);
}
}
-/*
-* Digi Read INB Callback
-*
-* Digi Read INB Callback handles reads on the in band ports, sending
-* the data on to the tty subsystem. When called we know port and
-* port->private are not NULL and port->serial has been validated.
-* It returns 0 if successful, 1 if successful but the port is
-* throttled, and -1 if the sanity checks failed.
-*/
+/*
+ * Digi Read INB Callback
+ *
+ * Digi Read INB Callback handles reads on the in band ports, sending
+ * the data on to the tty subsystem. When called we know port and
+ * port->private are not NULL and port->serial has been validated.
+ * It returns 0 if successful, 1 if successful but the port is
+ * throttled, and -1 if the sanity checks failed.
+ */
static int digi_read_inb_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
- struct tty_struct *tty = port->tty;
+ struct tty_struct *tty = port->port.tty;
struct digi_port *priv = usb_get_serial_port_data(port);
int opcode = ((unsigned char *)urb->transfer_buffer)[0];
int len = ((unsigned char *)urb->transfer_buffer)[1];
int port_status = ((unsigned char *)urb->transfer_buffer)[2];
- unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3;
- int flag,throttled;
+ unsigned char *data = ((unsigned char *)urb->transfer_buffer) + 3;
+ int flag, throttled;
int i;
int status = urb->status;
/* do not process callbacks on closed ports */
/* but do continue the read chain */
- if (port->open_count == 0)
+ if (port->port.count == 0)
return 0;
/* short/multiple packet check */
if (urb->actual_length != len + 2) {
- err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, "
+ err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, "
"port=%d, opcode=%d, len=%d, actual_length=%d, "
"status=%d", __func__, status, priv->dp_port_num,
opcode, len, urb->actual_length, port_status);
@@ -1722,8 +1727,9 @@ static int digi_read_inb_callback(struct urb *urb)
if (flag == TTY_NORMAL)
tty_insert_flip_string(tty, data, len);
else {
- for(i = 0; i < len; i++)
- tty_insert_flip_char(tty, data[i], flag);
+ for (i = 0; i < len; i++)
+ tty_insert_flip_char(tty,
+ data[i], flag);
}
tty_flip_buffer_push(tty);
}
@@ -1735,19 +1741,19 @@ static int digi_read_inb_callback(struct urb *urb)
else if (opcode != DIGI_CMD_RECEIVE_DATA)
dbg("%s: unknown opcode: %d", __func__, opcode);
- return(throttled ? 1 : 0);
+ return throttled ? 1 : 0;
}
-/*
-* Digi Read OOB Callback
-*
-* Digi Read OOB Callback handles reads on the out of band port.
-* When called we know port and port->private are not NULL and
-* the port->serial is valid. It returns 0 if successful, and
-* -1 if the sanity checks failed.
-*/
+/*
+ * Digi Read OOB Callback
+ *
+ * Digi Read OOB Callback handles reads on the out of band port.
+ * When called we know port and port->private are not NULL and
+ * the port->serial is valid. It returns 0 if successful, and
+ * -1 if the sanity checks failed.
+ */
static int digi_read_oob_callback(struct urb *urb)
{
@@ -1757,12 +1763,13 @@ static int digi_read_oob_callback(struct urb *urb)
struct digi_port *priv = usb_get_serial_port_data(port);
int opcode, line, status, val;
int i;
+ unsigned int rts;
dbg("digi_read_oob_callback: port=%d, len=%d",
priv->dp_port_num, urb->actual_length);
/* handle each oob command */
- for(i = 0; i < urb->actual_length - 3;) {
+ for (i = 0; i < urb->actual_length - 3;) {
opcode = ((unsigned char *)urb->transfer_buffer)[i++];
line = ((unsigned char *)urb->transfer_buffer)[i++];
status = ((unsigned char *)urb->transfer_buffer)[i++];
@@ -1776,27 +1783,29 @@ static int digi_read_oob_callback(struct urb *urb)
port = serial->port[line];
- if ((priv=usb_get_serial_port_data(port)) == NULL)
+ priv = usb_get_serial_port_data(port);
+ if (priv == NULL)
return -1;
+ rts = 0;
+ if (port->port.count)
+ rts = port->port.tty->termios->c_cflag & CRTSCTS;
+
if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
spin_lock(&priv->dp_port_lock);
/* convert from digi flags to termiox flags */
if (val & DIGI_READ_INPUT_SIGNALS_CTS) {
priv->dp_modem_signals |= TIOCM_CTS;
/* port must be open to use tty struct */
- if (port->open_count
- && port->tty->termios->c_cflag & CRTSCTS) {
- port->tty->hw_stopped = 0;
+ if (rts) {
+ port->port.tty->hw_stopped = 0;
digi_wakeup_write(port);
}
} else {
priv->dp_modem_signals &= ~TIOCM_CTS;
/* port must be open to use tty struct */
- if (port->open_count
- && port->tty->termios->c_cflag & CRTSCTS) {
- port->tty->hw_stopped = 1;
- }
+ if (rts)
+ port->port.tty->hw_stopped = 1;
}
if (val & DIGI_READ_INPUT_SIGNALS_DSR)
priv->dp_modem_signals |= TIOCM_DSR;
@@ -1833,7 +1842,7 @@ static int __init digi_init(void)
if (retval)
goto failed_acceleport_2_device;
retval = usb_serial_register(&digi_acceleport_4_device);
- if (retval)
+ if (retval)
goto failed_acceleport_4_device;
retval = usb_register(&digi_driver);
if (retval)
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index c5ec309a3cb..a6ab5b58d9c 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -11,36 +11,39 @@
* it under the terms of the GNU General Public License, as published by
* the Free Software Foundation, version 2.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
- *
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
+ *
* (07/16/2001) gb
- * remove unused code in empeg_close() (thanks to Oliver Neukum for pointing this
- * out) and rewrote empeg_set_termios().
- *
+ * remove unused code in empeg_close() (thanks to Oliver Neukum for
+ * pointing this out) and rewrote empeg_set_termios().
+ *
* (05/30/2001) gkh
- * switched from using spinlock to a semaphore, which fixes lots of problems.
+ * switched from using spinlock to a semaphore, which fixes lots of
+ * problems.
*
* (04/08/2001) gb
* Identify version on module load.
- *
+ *
* (01/22/2001) gb
- * Added write_room() and chars_in_buffer() support.
- *
+ * Added write_room() and chars_in_buffer() support.
+ *
* (12/21/2000) gb
* Moved termio stuff inside the port->active check.
* Moved MOD_DEC_USE_COUNT to end of empeg_close().
- *
+ *
* (12/03/2000) gb
- * Added port->tty->ldisc.set_termios(port->tty, NULL) to empeg_open()
- * This notifies the tty driver that the termios have changed.
- *
+ * Added port->port.tty->ldisc.set_termios(port->port.tty, NULL) to
+ * empeg_open(). This notifies the tty driver that the termios have
+ * changed.
+ *
* (11/13/2000) gb
- * Moved tty->low_latency = 1 from empeg_read_bulk_callback() to empeg_open()
- * (It only needs to be set once - Doh!)
- *
+ * Moved tty->low_latency = 1 from empeg_read_bulk_callback() to
+ * empeg_open() (It only needs to be set once - Doh!)
+ *
* (11/11/2000) gb
* Updated to work with id_table structure.
- *
+ *
* (11/04/2000) gb
* Forked this from visor.c, and hacked it up to work with an
* Empeg ltd. empeg-car player. Constructive criticism welcomed.
@@ -48,7 +51,7 @@
* use of his code, and for his guidance, advice and patience. :)
* A 'Thank You' is in order for John Ripley of Empeg ltd for his
* advice, and patience too.
- *
+ *
*/
#include <linux/kernel.h>
@@ -60,7 +63,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -77,31 +80,30 @@ static int debug;
#define EMPEG_PRODUCT_ID 0x0001
/* function prototypes for an empeg-car player */
-static int empeg_open (struct usb_serial_port *port, struct file *filp);
-static void empeg_close (struct usb_serial_port *port, struct file *filp);
-static int empeg_write (struct usb_serial_port *port,
- const unsigned char *buf,
- int count);
-static int empeg_write_room (struct usb_serial_port *port);
-static int empeg_chars_in_buffer (struct usb_serial_port *port);
-static void empeg_throttle (struct usb_serial_port *port);
-static void empeg_unthrottle (struct usb_serial_port *port);
-static int empeg_startup (struct usb_serial *serial);
-static void empeg_shutdown (struct usb_serial *serial);
-static int empeg_ioctl (struct usb_serial_port *port,
- struct file * file,
- unsigned int cmd,
- unsigned long arg);
-static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
-static void empeg_write_bulk_callback (struct urb *urb);
-static void empeg_read_bulk_callback (struct urb *urb);
+static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static int empeg_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf,
+ int count);
+static int empeg_write_room(struct tty_struct *tty);
+static int empeg_chars_in_buffer(struct tty_struct *tty);
+static void empeg_throttle(struct tty_struct *tty);
+static void empeg_unthrottle(struct tty_struct *tty);
+static int empeg_startup(struct usb_serial *serial);
+static void empeg_shutdown(struct usb_serial *serial);
+static void empeg_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios);
+static void empeg_write_bulk_callback(struct urb *urb);
+static void empeg_read_bulk_callback(struct urb *urb);
static struct usb_device_id id_table [] = {
{ USB_DEVICE(EMPEG_VENDOR_ID, EMPEG_PRODUCT_ID) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver empeg_driver = {
.name = "empeg",
@@ -125,7 +127,6 @@ static struct usb_serial_driver empeg_device = {
.unthrottle = empeg_unthrottle,
.attach = empeg_startup,
.shutdown = empeg_shutdown,
- .ioctl = empeg_ioctl,
.set_termios = empeg_set_termios,
.write = empeg_write,
.write_room = empeg_write_room,
@@ -145,7 +146,8 @@ static int bytes_out;
/******************************************************************************
* Empeg specific driver functions
******************************************************************************/
-static int empeg_open (struct usb_serial_port *port, struct file *filp)
+static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
struct usb_serial *serial = port->serial;
int result = 0;
@@ -153,7 +155,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __func__, port->number);
/* Force default termio settings */
- empeg_set_termios (port, NULL) ;
+ empeg_set_termios(tty, port, NULL) ;
bytes_in = 0;
bytes_out = 0;
@@ -161,7 +163,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
/* Start reading from the device */
usb_fill_bulk_urb(
port->read_urb,
- serial->dev,
+ serial->dev,
usb_rcvbulkpipe(serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
@@ -172,13 +174,16 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, result);
return result;
}
-static void empeg_close (struct usb_serial_port *port, struct file * filp)
+static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
dbg("%s - port %d", __func__, port->number);
@@ -189,7 +194,8 @@ static void empeg_close (struct usb_serial_port *port, struct file * filp)
}
-static int empeg_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int empeg_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
struct urb *urb;
@@ -203,11 +209,10 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
dbg("%s - port %d", __func__, port->number);
while (count > 0) {
-
/* try to find a free urb in our list of them */
urb = NULL;
- spin_lock_irqsave (&write_urb_pool_lock, flags);
+ spin_lock_irqsave(&write_urb_pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
if (write_urb_pool[i]->status != -EINPROGRESS) {
@@ -216,7 +221,7 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
}
}
- spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+ spin_unlock_irqrestore(&write_urb_pool_lock, flags);
if (urb == NULL) {
dbg("%s - no more free urbs", __func__);
@@ -224,25 +229,27 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
}
if (urb->transfer_buffer == NULL) {
- urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
+ urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
if (urb->transfer_buffer == NULL) {
- dev_err(&port->dev, "%s no more kernel memory...\n", __func__);
+ dev_err(&port->dev,
+ "%s no more kernel memory...\n",
+ __func__);
goto exit;
}
}
- transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE);
+ transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
- memcpy (urb->transfer_buffer, current_position, transfer_size);
+ memcpy(urb->transfer_buffer, current_position, transfer_size);
usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, urb->transfer_buffer);
/* build up our urb */
- usb_fill_bulk_urb (
+ usb_fill_bulk_urb(
urb,
serial->dev,
usb_sndbulkpipe(serial->dev,
- port->bulk_out_endpointAddress),
+ port->bulk_out_endpointAddress),
urb->transfer_buffer,
transfer_size,
empeg_write_bulk_callback,
@@ -262,66 +269,57 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
bytes_out += transfer_size;
}
-
exit:
return bytes_sent;
-
-}
+}
-static int empeg_write_room (struct usb_serial_port *port)
+static int empeg_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned long flags;
int i;
int room = 0;
dbg("%s - port %d", __func__, port->number);
- spin_lock_irqsave (&write_urb_pool_lock, flags);
-
+ spin_lock_irqsave(&write_urb_pool_lock, flags);
/* tally up the number of bytes available */
for (i = 0; i < NUM_URBS; ++i) {
- if (write_urb_pool[i]->status != -EINPROGRESS) {
+ if (write_urb_pool[i]->status != -EINPROGRESS)
room += URB_TRANSFER_BUFFER_SIZE;
- }
- }
-
- spin_unlock_irqrestore (&write_urb_pool_lock, flags);
-
+ }
+ spin_unlock_irqrestore(&write_urb_pool_lock, flags);
dbg("%s - returns %d", __func__, room);
-
- return (room);
+ return room;
}
-static int empeg_chars_in_buffer (struct usb_serial_port *port)
+static int empeg_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned long flags;
int i;
int chars = 0;
dbg("%s - port %d", __func__, port->number);
- spin_lock_irqsave (&write_urb_pool_lock, flags);
+ spin_lock_irqsave(&write_urb_pool_lock, flags);
/* tally up the number of bytes waiting */
for (i = 0; i < NUM_URBS; ++i) {
- if (write_urb_pool[i]->status == -EINPROGRESS) {
+ if (write_urb_pool[i]->status == -EINPROGRESS)
chars += URB_TRANSFER_BUFFER_SIZE;
- }
}
- spin_unlock_irqrestore (&write_urb_pool_lock, flags);
-
+ spin_unlock_irqrestore(&write_urb_pool_lock, flags);
dbg("%s - returns %d", __func__, chars);
-
- return (chars);
-
+ return chars;
}
-static void empeg_write_bulk_callback (struct urb *urb)
+static void empeg_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
int status = urb->status;
@@ -338,7 +336,7 @@ static void empeg_write_bulk_callback (struct urb *urb)
}
-static void empeg_read_bulk_callback (struct urb *urb)
+static void empeg_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct tty_struct *tty;
@@ -354,9 +352,9 @@ static void empeg_read_bulk_callback (struct urb *urb)
return;
}
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
-
- tty = port->tty;
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
+ tty = port->port.tty;
if (urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
@@ -368,7 +366,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
/* Continue trying to always read */
usb_fill_bulk_urb(
port->read_urb,
- port->serial->dev,
+ port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
@@ -379,38 +377,39 @@ static void empeg_read_bulk_callback (struct urb *urb)
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ dev_err(&urb->dev->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
return;
}
-static void empeg_throttle (struct usb_serial_port *port)
+static void empeg_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
usb_kill_urb(port->read_urb);
}
-static void empeg_unthrottle (struct usb_serial_port *port)
+static void empeg_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int result;
-
dbg("%s - port %d", __func__, port->number);
port->read_urb->dev = port->serial->dev;
-
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-
if (result)
- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
-
- return;
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, result);
}
-static int empeg_startup (struct usb_serial *serial)
+static int empeg_startup(struct usb_serial *serial)
{
int r;
@@ -422,7 +421,7 @@ static int empeg_startup (struct usb_serial *serial)
return -ENODEV;
}
dbg("%s - reset config", __func__);
- r = usb_reset_configuration (serial->dev);
+ r = usb_reset_configuration(serial->dev);
/* continue on with initialization */
return r;
@@ -430,34 +429,27 @@ static int empeg_startup (struct usb_serial *serial)
}
-static void empeg_shutdown (struct usb_serial *serial)
+static void empeg_shutdown(struct usb_serial *serial)
{
- dbg ("%s", __func__);
-}
-
-
-static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
-{
- dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
-
- return -ENOIOCTLCMD;
+ dbg("%s", __func__);
}
-static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void empeg_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
- struct ktermios *termios = port->tty->termios;
+ struct ktermios *termios = tty->termios;
dbg("%s - port %d", __func__, port->number);
/*
- * The empeg-car player wants these particular tty settings.
- * You could, for example, change the baud rate, however the
- * player only supports 115200 (currently), so there is really
- * no point in support for changes to the tty settings.
- * (at least for now)
- *
- * The default requirements for this device are:
- */
+ * The empeg-car player wants these particular tty settings.
+ * You could, for example, change the baud rate, however the
+ * player only supports 115200 (currently), so there is really
+ * no point in support for changes to the tty settings.
+ * (at least for now)
+ *
+ * The default requirements for this device are:
+ */
termios->c_iflag
&= ~(IGNBRK /* disable ignore break */
| BRKINT /* disable break causes interrupt */
@@ -491,18 +483,18 @@ static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *ol
* this is bad as it opens up the possibility of dropping bytes
* on the floor. We don't want to drop bytes on the floor. :)
*/
- port->tty->low_latency = 1;
- tty_encode_baud_rate(port->tty, 115200, 115200);
+ tty->low_latency = 1;
+ tty_encode_baud_rate(tty, 115200, 115200);
}
-static int __init empeg_init (void)
+static int __init empeg_init(void)
{
struct urb *urb;
int i, retval;
- /* create our write urb pool and transfer buffers */
- spin_lock_init (&write_urb_pool_lock);
+ /* create our write urb pool and transfer buffers */
+ spin_lock_init(&write_urb_pool_lock);
for (i = 0; i < NUM_URBS; ++i) {
urb = usb_alloc_urb(0, GFP_KERNEL);
write_urb_pool[i] = urb;
@@ -511,9 +503,10 @@ static int __init empeg_init (void)
continue;
}
- urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+ urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
+ GFP_KERNEL);
if (!urb->transfer_buffer) {
- err("%s - out of memory for urb buffers.",
+ err("%s - out of memory for urb buffers.",
__func__);
continue;
}
@@ -542,36 +535,36 @@ failed_usb_serial_register:
}
-static void __exit empeg_exit (void)
+static void __exit empeg_exit(void)
{
int i;
unsigned long flags;
usb_deregister(&empeg_driver);
- usb_serial_deregister (&empeg_device);
+ usb_serial_deregister(&empeg_device);
- spin_lock_irqsave (&write_urb_pool_lock, flags);
+ spin_lock_irqsave(&write_urb_pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
if (write_urb_pool[i]) {
- /* FIXME - uncomment the following usb_kill_urb call when
- * the host controllers get fixed to set urb->dev = NULL after
- * the urb is finished. Otherwise this call oopses. */
+ /* FIXME - uncomment the following usb_kill_urb call
+ * when the host controllers get fixed to set urb->dev
+ * = NULL after the urb is finished. Otherwise this
+ * call oopses. */
/* usb_kill_urb(write_urb_pool[i]); */
kfree(write_urb_pool[i]->transfer_buffer);
- usb_free_urb (write_urb_pool[i]);
+ usb_free_urb(write_urb_pool[i]);
}
}
-
- spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+ spin_unlock_irqrestore(&write_urb_pool_lock, flags);
}
module_init(empeg_init);
module_exit(empeg_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
index cc4fbd9d60b..711e84f6ed8 100644
--- a/drivers/usb/serial/ezusb.c
+++ b/drivers/usb/serial/ezusb.c
@@ -20,7 +20,8 @@
/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */
#define CPUCS_REG 0x7F92
-int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest)
+int ezusb_writememory(struct usb_serial *serial, int address,
+ unsigned char *data, int length, __u8 request)
{
int result;
unsigned char *transfer_buffer;
@@ -33,26 +34,27 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da
transfer_buffer = kmemdup(data, length, GFP_KERNEL);
if (!transfer_buffer) {
- dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, length);
+ dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n",
+ __func__, length);
return -ENOMEM;
}
- result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3000);
- kfree (transfer_buffer);
+ result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ request, 0x40, address, 0, transfer_buffer, length, 3000);
+ kfree(transfer_buffer);
return result;
}
+EXPORT_SYMBOL_GPL(ezusb_writememory);
-int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
+int ezusb_set_reset(struct usb_serial *serial, unsigned char reset_bit)
{
int response;
/* dbg("%s - %d", __func__, reset_bit); */
- response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
+ response = ezusb_writememory(serial, CPUCS_REG, &reset_bit, 1, 0xa0);
if (response < 0)
- dev_err(&serial->dev->dev, "%s- %d failed\n", __func__, reset_bit);
+ dev_err(&serial->dev->dev, "%s- %d failed\n",
+ __func__, reset_bit);
return response;
}
-
-
-EXPORT_SYMBOL_GPL(ezusb_writememory);
EXPORT_SYMBOL_GPL(ezusb_set_reset);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 0ff4a3971e4..83871725014 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -12,7 +12,8 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
* See http://ftdi-usb-sio.sourceforge.net for upto date testing info
* and extra documentation
@@ -25,7 +26,8 @@
/* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */
/* Thanx to FTDI for so kindly providing details of the protocol required */
/* to talk to the device */
-/* Thanx to gkh and the rest of the usb dev group for all code I have assimilated :-) */
+/* Thanx to gkh and the rest of the usb dev group for all code I have
+ assimilated :-) */
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -36,7 +38,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/serial.h>
#include <linux/usb/serial.h>
@@ -55,17 +57,22 @@ static __u16 product;
struct ftdi_private {
ftdi_chip_type_t chip_type;
- /* type of the device, either SIO or FT8U232AM */
+ /* type of device, either SIO or FT8U232AM */
int baud_base; /* baud base clock for divisor setting */
- int custom_divisor; /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */
+ int custom_divisor; /* custom_divisor kludge, this is for
+ baud_base (different from what goes to the
+ chip!) */
__u16 last_set_data_urb_value ;
- /* the last data state set - needed for doing a break */
- int write_offset; /* This is the offset in the usb data block to write the serial data -
- * it is different between devices
+ /* the last data state set - needed for doing
+ * a break
+ */
+ int write_offset; /* This is the offset in the usb data block to
+ * write the serial data - it varies between
+ * devices
*/
int flags; /* some ASYNC_xxxx flags are supported */
unsigned long last_dtr_rts; /* saved modem control outputs */
- wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
+ wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
char prev_status, diff_status; /* Used for TIOCMIWAIT */
__u8 rx_flags; /* receive state flags (throttling) */
spinlock_t rx_lock; /* spinlock for receive state */
@@ -76,8 +83,10 @@ struct ftdi_private {
__u16 interface; /* FT2232C port interface (0 for FT232/245) */
- speed_t force_baud; /* if non-zero, force the baud rate to this value */
- int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */
+ speed_t force_baud; /* if non-zero, force the baud rate to
+ this value */
+ int force_rtscts; /* if non-zero, force RTS-CTS to always
+ be enabled */
spinlock_t tx_lock; /* spinlock for transmit state */
unsigned long tx_bytes;
@@ -88,13 +97,14 @@ struct ftdi_private {
/* struct ftdi_sio_quirk is used by devices requiring special attention. */
struct ftdi_sio_quirk {
int (*probe)(struct usb_serial *);
- void (*port_probe)(struct ftdi_private *); /* Special settings for probed ports. */
+ /* Special settings for probed ports. */
+ void (*port_probe)(struct ftdi_private *);
};
-static int ftdi_jtag_probe (struct usb_serial *serial);
-static int ftdi_mtxorb_hack_setup (struct usb_serial *serial);
-static void ftdi_USB_UIRT_setup (struct ftdi_private *priv);
-static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv);
+static int ftdi_jtag_probe(struct usb_serial *serial);
+static int ftdi_mtxorb_hack_setup(struct usb_serial *serial);
+static void ftdi_USB_UIRT_setup(struct ftdi_private *priv);
+static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv);
static struct ftdi_sio_quirk ftdi_jtag_quirk = {
.probe = ftdi_jtag_probe,
@@ -174,270 +184,270 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0100_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0101_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0102_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0103_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0104_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0105_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0106_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0107_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0108_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0109_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0110_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0111_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0112_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0113_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0114_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0115_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0116_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0117_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0118_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0119_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0120_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0121_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0122_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0123_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0124_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0125_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0126_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0127_PID),
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0103_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0104_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0105_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0106_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0107_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0108_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0109_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0110_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0111_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0112_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0113_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0114_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0115_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0116_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0117_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0118_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0119_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0120_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0121_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0122_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0123_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0124_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0125_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0126_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0127_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0128_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0129_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012C_PID),
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0128_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0129_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012C_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0130_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0131_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0132_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0133_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0134_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0135_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0136_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0137_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0138_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0139_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0140_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0141_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0142_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0143_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0144_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0145_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0146_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0147_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0148_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0149_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0150_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0151_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0152_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0153_PID),
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0130_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0131_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0132_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0133_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0134_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0135_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0136_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0137_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0138_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0139_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0140_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0141_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0142_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0143_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0144_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0145_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0146_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0147_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0148_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0149_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0150_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0151_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0152_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0153_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0154_PID),
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0154_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0155_PID),
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0155_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0156_PID),
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0156_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0157_PID),
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0157_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0158_PID),
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0158_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0159_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0160_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0161_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0162_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0163_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0164_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0165_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0166_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0167_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0168_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0169_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0170_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0171_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0172_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0173_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0174_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0175_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0176_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0177_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0178_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0179_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0180_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0181_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0182_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0183_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0184_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0185_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0186_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0187_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0188_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0189_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0190_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0191_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0192_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0193_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0194_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0195_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0196_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0197_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0198_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0199_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A0_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A1_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A2_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A3_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A4_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A5_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A6_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A7_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A8_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A9_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AA_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AB_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AC_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AD_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AE_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AF_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B0_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B1_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B2_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B3_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B4_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B5_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B6_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B7_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B8_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B9_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BA_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BB_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BC_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BD_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BE_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BF_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C0_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C1_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C2_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C3_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C4_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C5_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C6_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C7_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C8_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C9_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CA_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CB_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CC_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CD_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CE_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CF_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D0_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D1_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D2_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D3_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D4_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D5_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D6_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D7_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D8_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D9_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DA_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DB_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DC_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DD_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DE_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DF_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E0_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E1_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E2_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E3_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E4_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E5_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E6_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E7_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E8_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E9_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EA_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EB_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EC_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01ED_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EE_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EF_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F0_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F1_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F2_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F3_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F4_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F5_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F6_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F7_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F8_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F9_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FA_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FB_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FC_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FD_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FE_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FF_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0159_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0160_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0161_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0162_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0163_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0164_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0165_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0166_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0167_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0168_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0169_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0170_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0171_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0172_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0173_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0174_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0175_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0176_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0177_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0178_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0179_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0180_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0181_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0182_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0183_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0184_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0185_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0186_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0187_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0188_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0189_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0190_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0191_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0192_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0193_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0194_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0195_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0196_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0197_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0198_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0199_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A0_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A1_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A2_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A3_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A4_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A5_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A6_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A7_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A8_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A9_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AA_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AB_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AC_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AD_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AE_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AF_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B0_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B1_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B2_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B3_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B4_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B5_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B6_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B7_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B8_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B9_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BA_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BB_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BC_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BD_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BE_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BF_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C0_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C1_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C2_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C3_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C4_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C5_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C6_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C7_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C8_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C9_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CA_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CB_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CC_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CD_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CE_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CF_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D0_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D1_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D2_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D3_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D4_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D5_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D6_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D7_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D8_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D9_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DA_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DB_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DC_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DD_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DE_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DF_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E0_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E1_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E2_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E3_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E4_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E5_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E6_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E7_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E8_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E9_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EA_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EB_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EC_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01ED_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EE_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EF_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F0_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F1_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F2_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F3_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F4_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F5_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F6_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F7_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F8_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F9_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FA_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FB_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FC_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FD_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FE_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FF_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) },
@@ -642,7 +652,7 @@ static struct usb_device_id id_table_combined [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver ftdi_driver = {
.name = "ftdi_sio",
@@ -678,30 +688,37 @@ static const char *ftdi_chip_name[] = {
| ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP)
/* function prototypes for a FTDI serial converter */
-static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id);
-static void ftdi_shutdown (struct usb_serial *serial);
-static int ftdi_sio_port_probe (struct usb_serial_port *port);
-static int ftdi_sio_port_remove (struct usb_serial_port *port);
-static int ftdi_open (struct usb_serial_port *port, struct file *filp);
-static void ftdi_close (struct usb_serial_port *port, struct file *filp);
-static int ftdi_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-static int ftdi_write_room (struct usb_serial_port *port);
-static int ftdi_chars_in_buffer (struct usb_serial_port *port);
-static void ftdi_write_bulk_callback (struct urb *urb);
-static void ftdi_read_bulk_callback (struct urb *urb);
-static void ftdi_process_read (struct work_struct *work);
-static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios * old);
-static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file);
-static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear);
-static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void ftdi_break_ctl (struct usb_serial_port *port, int break_state );
-static void ftdi_throttle (struct usb_serial_port *port);
-static void ftdi_unthrottle (struct usb_serial_port *port);
-
-static unsigned short int ftdi_232am_baud_base_to_divisor (int baud, int base);
-static unsigned short int ftdi_232am_baud_to_divisor (int baud);
-static __u32 ftdi_232bm_baud_base_to_divisor (int baud, int base);
-static __u32 ftdi_232bm_baud_to_divisor (int baud);
+static int ftdi_sio_probe(struct usb_serial *serial,
+ const struct usb_device_id *id);
+static void ftdi_shutdown(struct usb_serial *serial);
+static int ftdi_sio_port_probe(struct usb_serial_port *port);
+static int ftdi_sio_port_remove(struct usb_serial_port *port);
+static int ftdi_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void ftdi_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+static int ftdi_write_room(struct tty_struct *tty);
+static int ftdi_chars_in_buffer(struct tty_struct *tty);
+static void ftdi_write_bulk_callback(struct urb *urb);
+static void ftdi_read_bulk_callback(struct urb *urb);
+static void ftdi_process_read(struct work_struct *work);
+static void ftdi_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
+static int ftdi_tiocmget(struct tty_struct *tty, struct file *file);
+static int ftdi_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
+static int ftdi_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static void ftdi_break_ctl(struct tty_struct *tty, int break_state);
+static void ftdi_throttle(struct tty_struct *tty);
+static void ftdi_unthrottle(struct tty_struct *tty);
+
+static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base);
+static unsigned short int ftdi_232am_baud_to_divisor(int baud);
+static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base);
+static __u32 ftdi_232bm_baud_to_divisor(int baud);
static struct usb_serial_driver ftdi_sio_device = {
.driver = {
@@ -752,44 +769,54 @@ static struct usb_serial_driver ftdi_sio_device = {
static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base)
{
unsigned short int divisor;
- int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left
- if ((divisor3 & 0x7) == 7) divisor3 ++; // round x.7/8 up to x+1
+ /* divisor shifted 3 bits to the left */
+ int divisor3 = base / 2 / baud;
+ if ((divisor3 & 0x7) == 7)
+ divisor3++; /* round x.7/8 up to x+1 */
divisor = divisor3 >> 3;
divisor3 &= 0x7;
- if (divisor3 == 1) divisor |= 0xc000; else // 0.125
- if (divisor3 >= 4) divisor |= 0x4000; else // 0.5
- if (divisor3 != 0) divisor |= 0x8000; // 0.25
- if (divisor == 1) divisor = 0; /* special case for maximum baud rate */
+ if (divisor3 == 1)
+ divisor |= 0xc000;
+ else if (divisor3 >= 4)
+ divisor |= 0x4000;
+ else if (divisor3 != 0)
+ divisor |= 0x8000;
+ else if (divisor == 1)
+ divisor = 0; /* special case for maximum baud rate */
return divisor;
}
static unsigned short int ftdi_232am_baud_to_divisor(int baud)
{
- return(ftdi_232am_baud_base_to_divisor(baud, 48000000));
+ return ftdi_232am_baud_base_to_divisor(baud, 48000000);
}
static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base)
{
static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 };
__u32 divisor;
- int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left
+ /* divisor shifted 3 bits to the left */
+ int divisor3 = base / 2 / baud;
divisor = divisor3 >> 3;
divisor |= (__u32)divfrac[divisor3 & 0x7] << 14;
/* Deal with special cases for highest baud rates. */
- if (divisor == 1) divisor = 0; else // 1.0
- if (divisor == 0x4001) divisor = 1; // 1.5
+ if (divisor == 1)
+ divisor = 0;
+ else if (divisor == 0x4001)
+ divisor = 1;
return divisor;
}
static __u32 ftdi_232bm_baud_to_divisor(int baud)
{
- return(ftdi_232bm_baud_base_to_divisor(baud, 48000000));
+ return ftdi_232bm_baud_base_to_divisor(baud, 48000000);
}
#define set_mctrl(port, set) update_mctrl((port), (set), 0)
#define clear_mctrl(port, clear) update_mctrl((port), 0, (clear))
-static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned int clear)
+static int update_mctrl(struct usb_serial_port *port, unsigned int set,
+ unsigned int clear)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
char *buf;
@@ -843,42 +870,8 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned
}
-static __u32 get_ftdi_divisor(struct usb_serial_port * port);
-
-
-static int change_speed(struct usb_serial_port *port)
-{
- struct ftdi_private *priv = usb_get_serial_port_data(port);
- char *buf;
- __u16 urb_value;
- __u16 urb_index;
- __u32 urb_index_value;
- int rv;
-
- buf = kmalloc(1, GFP_NOIO);
- if (!buf)
- return -ENOMEM;
-
- urb_index_value = get_ftdi_divisor(port);
- urb_value = (__u16)urb_index_value;
- urb_index = (__u16)(urb_index_value >> 16);
- if (priv->interface) { /* FT2232C */
- urb_index = (__u16)((urb_index << 8) | priv->interface);
- }
-
- rv = usb_control_msg(port->serial->dev,
- usb_sndctrlpipe(port->serial->dev, 0),
- FTDI_SIO_SET_BAUDRATE_REQUEST,
- FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
- urb_value, urb_index,
- buf, 0, WDR_SHORT_TIMEOUT);
-
- kfree(buf);
- return rv;
-}
-
-
-static __u32 get_ftdi_divisor(struct usb_serial_port * port)
+static __u32 get_ftdi_divisor(struct tty_struct *tty,
+ struct usb_serial_port *port)
{ /* get_ftdi_divisor */
struct ftdi_private *priv = usb_get_serial_port_data(port);
__u32 div_value = 0;
@@ -886,48 +879,56 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
int baud;
/*
- * The logic involved in setting the baudrate can be cleanly split in 3 steps.
- * Obtaining the actual baud rate is a little tricky since unix traditionally
- * somehow ignored the possibility to set non-standard baud rates.
+ * The logic involved in setting the baudrate can be cleanly split into
+ * 3 steps.
* 1. Standard baud rates are set in tty->termios->c_cflag
- * 2. If these are not enough, you can set any speed using alt_speed as follows:
+ * 2. If these are not enough, you can set any speed using alt_speed as
+ * follows:
* - set tty->termios->c_cflag speed to B38400
* - set your real speed in tty->alt_speed; it gets ignored when
* alt_speed==0, (or)
- * - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
- * flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP], this just
- * sets alt_speed to (HI: 57600, VHI: 115200, SHI: 230400, WARP: 460800)
+ * - call TIOCSSERIAL ioctl with (struct serial_struct) set as
+ * follows:
+ * flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP],
+ * this just sets alt_speed to (HI: 57600, VHI: 115200,
+ * SHI: 230400, WARP: 460800)
* ** Steps 1, 2 are done courtesy of tty_get_baud_rate
* 3. You can also set baud rate by setting custom divisor as follows
* - set tty->termios->c_cflag speed to B38400
- * - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
+ * - call TIOCSSERIAL ioctl with (struct serial_struct) set as
+ * follows:
* o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST
* o custom_divisor set to baud_base / your_new_baudrate
- * ** Step 3 is done courtesy of code borrowed from serial.c - I should really
- * spend some time and separate+move this common code to serial.c, it is
- * replicated in nearly every serial driver you see.
+ * ** Step 3 is done courtesy of code borrowed from serial.c
+ * I should really spend some time and separate + move this common
+ * code to serial.c, it is replicated in nearly every serial driver
+ * you see.
*/
- /* 1. Get the baud rate from the tty settings, this observes alt_speed hack */
+ /* 1. Get the baud rate from the tty settings, this observes
+ alt_speed hack */
- baud = tty_get_baud_rate(port->tty);
+ baud = tty_get_baud_rate(tty);
dbg("%s - tty_get_baud_rate reports speed %d", __func__, baud);
- /* 2. Observe async-compatible custom_divisor hack, update baudrate if needed */
+ /* 2. Observe async-compatible custom_divisor hack, update baudrate
+ if needed */
if (baud == 38400 &&
((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
(priv->custom_divisor)) {
baud = priv->baud_base / priv->custom_divisor;
- dbg("%s - custom divisor %d sets baud rate to %d", __func__, priv->custom_divisor, baud);
+ dbg("%s - custom divisor %d sets baud rate to %d",
+ __func__, priv->custom_divisor, baud);
}
/* 3. Convert baudrate to device-specific divisor */
- if (!baud) baud = 9600;
- switch(priv->chip_type) {
+ if (!baud)
+ baud = 9600;
+ switch (priv->chip_type) {
case SIO: /* SIO chip */
- switch(baud) {
+ switch (baud) {
case 300: div_value = ftdi_sio_b300; break;
case 600: div_value = ftdi_sio_b600; break;
case 1200: div_value = ftdi_sio_b1200; break;
@@ -940,7 +941,8 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
case 115200: div_value = ftdi_sio_b115200; break;
} /* baud */
if (div_value == 0) {
- dbg("%s - Baudrate (%d) requested is not supported", __func__, baud);
+ dbg("%s - Baudrate (%d) requested is not supported",
+ __func__, baud);
div_value = ftdi_sio_b9600;
baud = 9600;
div_okay = 0;
@@ -950,7 +952,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
if (baud <= 3000000) {
div_value = ftdi_232am_baud_to_divisor(baud);
} else {
- dbg("%s - Baud rate too high!", __func__);
+ dbg("%s - Baud rate too high!", __func__);
baud = 9600;
div_value = ftdi_232am_baud_to_divisor(9600);
div_okay = 0;
@@ -962,7 +964,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
if (baud <= 3000000) {
div_value = ftdi_232bm_baud_to_divisor(baud);
} else {
- dbg("%s - Baud rate too high!", __func__);
+ dbg("%s - Baud rate too high!", __func__);
div_value = ftdi_232bm_baud_to_divisor(9600);
div_okay = 0;
baud = 9600;
@@ -976,12 +978,45 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
ftdi_chip_name[priv->chip_type]);
}
- tty_encode_baud_rate(port->tty, baud, baud);
- return(div_value);
+ tty_encode_baud_rate(tty, baud, baud);
+ return div_value;
+}
+
+static int change_speed(struct tty_struct *tty, struct usb_serial_port *port)
+{
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ char *buf;
+ __u16 urb_value;
+ __u16 urb_index;
+ __u32 urb_index_value;
+ int rv;
+
+ buf = kmalloc(1, GFP_NOIO);
+ if (!buf)
+ return -ENOMEM;
+
+ urb_index_value = get_ftdi_divisor(tty, port);
+ urb_value = (__u16)urb_index_value;
+ urb_index = (__u16)(urb_index_value >> 16);
+ if (priv->interface) { /* FT2232C */
+ urb_index = (__u16)((urb_index << 8) | priv->interface);
+ }
+
+ rv = usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
+ FTDI_SIO_SET_BAUDRATE_REQUEST,
+ FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
+ urb_value, urb_index,
+ buf, 0, WDR_SHORT_TIMEOUT);
+
+ kfree(buf);
+ return rv;
}
-static int get_serial_info(struct usb_serial_port * port, struct serial_struct __user * retinfo)
+
+static int get_serial_info(struct usb_serial_port *port,
+ struct serial_struct __user *retinfo)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
struct serial_struct tmp;
@@ -998,7 +1033,8 @@ static int get_serial_info(struct usb_serial_port * port, struct serial_struct _
} /* get_serial_info */
-static int set_serial_info(struct usb_serial_port * port, struct serial_struct __user * newinfo)
+static int set_serial_info(struct tty_struct *tty,
+ struct usb_serial_port *port, struct serial_struct __user *newinfo)
{ /* set_serial_info */
struct ftdi_private *priv = usb_get_serial_port_data(port);
struct serial_struct new_serial;
@@ -1006,7 +1042,7 @@ static int set_serial_info(struct usb_serial_port * port, struct serial_struct _
if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
return -EFAULT;
- old_priv = * priv;
+ old_priv = *priv;
/* Do error checking and permission checking */
@@ -1027,33 +1063,32 @@ static int set_serial_info(struct usb_serial_port * port, struct serial_struct _
/* Make the changes - these are privileged changes! */
priv->flags = ((priv->flags & ~ASYNC_FLAGS) |
- (new_serial.flags & ASYNC_FLAGS));
+ (new_serial.flags & ASYNC_FLAGS));
priv->custom_divisor = new_serial.custom_divisor;
- port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
check_and_exit:
if ((old_priv.flags & ASYNC_SPD_MASK) !=
(priv->flags & ASYNC_SPD_MASK)) {
if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- port->tty->alt_speed = 57600;
+ tty->alt_speed = 57600;
else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- port->tty->alt_speed = 115200;
+ tty->alt_speed = 115200;
else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- port->tty->alt_speed = 230400;
+ tty->alt_speed = 230400;
else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- port->tty->alt_speed = 460800;
+ tty->alt_speed = 460800;
else
- port->tty->alt_speed = 0;
+ tty->alt_speed = 0;
}
if (((old_priv.flags & ASYNC_SPD_MASK) !=
(priv->flags & ASYNC_SPD_MASK)) ||
(((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
(old_priv.custom_divisor != priv->custom_divisor))) {
- change_speed(port);
+ change_speed(tty, port);
}
-
- return (0);
+ return 0;
} /* set_serial_info */
@@ -1082,11 +1117,10 @@ static void ftdi_determine_type(struct usb_serial_port *port)
priv->chip_type = FT2232C;
/* Determine interface code. */
inter = serial->interface->altsetting->desc.bInterfaceNumber;
- if (inter == 0) {
+ if (inter == 0)
priv->interface = PIT_SIOA;
- } else {
+ else
priv->interface = PIT_SIOB;
- }
/* BM-type devices have a bug where bcdDevice gets set
* to 0x200 when iSerialNumber is 0. */
if (version < 0x500) {
@@ -1120,7 +1154,8 @@ static void ftdi_determine_type(struct usb_serial_port *port)
* ***************************************************************************
*/
-static ssize_t show_latency_timer(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_latency_timer(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1129,14 +1164,14 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a
int rv = 0;
- dbg("%s",__func__);
+ dbg("%s", __func__);
rv = usb_control_msg(udev,
usb_rcvctrlpipe(udev, 0),
FTDI_SIO_GET_LATENCY_TIMER_REQUEST,
FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE,
0, priv->interface,
- (char*) &latency, 1, WDR_TIMEOUT);
+ (char *) &latency, 1, WDR_TIMEOUT);
if (rv < 0) {
dev_err(dev, "Unable to read latency timer: %i\n", rv);
@@ -1146,8 +1181,9 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a
}
/* Write a new value of the latency timer, in units of milliseconds. */
-static ssize_t store_latency_timer(struct device *dev, struct device_attribute *attr, const char *valbuf,
- size_t count)
+static ssize_t store_latency_timer(struct device *dev,
+ struct device_attribute *attr, const char *valbuf,
+ size_t count)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1175,8 +1211,8 @@ static ssize_t store_latency_timer(struct device *dev, struct device_attribute *
/* Write an event character directly to the FTDI register. The ASCII
value is in the low 8 bits, with the enable bit in the 9th bit. */
-static ssize_t store_event_char(struct device *dev, struct device_attribute *attr, const char *valbuf,
- size_t count)
+static ssize_t store_event_char(struct device *dev,
+ struct device_attribute *attr, const char *valbuf, size_t count)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1202,7 +1238,8 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att
return count;
}
-static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer);
+static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer,
+ store_latency_timer);
static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char);
static int create_sysfs_attrs(struct usb_serial_port *port)
@@ -1210,7 +1247,7 @@ static int create_sysfs_attrs(struct usb_serial_port *port)
struct ftdi_private *priv = usb_get_serial_port_data(port);
int retval = 0;
- dbg("%s",__func__);
+ dbg("%s", __func__);
/* XXX I've no idea if the original SIO supports the event_char
* sysfs parameter, so I'm playing it safe. */
@@ -1232,7 +1269,7 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
- dbg("%s",__func__);
+ dbg("%s", __func__);
/* XXX see create_sysfs_attrs */
if (priv->chip_type != SIO) {
@@ -1253,9 +1290,11 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
*/
/* Probe function to check for special devices */
-static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id)
+static int ftdi_sio_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
{
- struct ftdi_sio_quirk *quirk = (struct ftdi_sio_quirk *)id->driver_info;
+ struct ftdi_sio_quirk *quirk =
+ (struct ftdi_sio_quirk *)id->driver_info;
if (quirk && quirk->probe) {
int ret = quirk->probe(serial);
@@ -1274,17 +1313,18 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial);
- dbg("%s",__func__);
+ dbg("%s", __func__);
priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);
- if (!priv){
- err("%s- kmalloc(%Zd) failed.", __func__, sizeof(struct ftdi_private));
+ if (!priv) {
+ err("%s- kmalloc(%Zd) failed.", __func__,
+ sizeof(struct ftdi_private));
return -ENOMEM;
}
spin_lock_init(&priv->rx_lock);
spin_lock_init(&priv->tx_lock);
- init_waitqueue_head(&priv->delta_msr_wait);
+ init_waitqueue_head(&priv->delta_msr_wait);
/* This will push the characters through immediately rather
than queue a task to deliver them */
priv->flags = ASYNC_LOW_LATENCY;
@@ -1294,9 +1334,9 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
/* Increase the size of read buffers */
kfree(port->bulk_in_buffer);
- port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL);
+ port->bulk_in_buffer = kmalloc(BUFSZ, GFP_KERNEL);
if (!port->bulk_in_buffer) {
- kfree (priv);
+ kfree(priv);
return -ENOMEM;
}
if (port->read_urb) {
@@ -1309,7 +1349,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
/* Free port's existing write urb and transfer buffer. */
if (port->write_urb) {
- usb_free_urb (port->write_urb);
+ usb_free_urb(port->write_urb);
port->write_urb = NULL;
}
kfree(port->bulk_out_buffer);
@@ -1317,7 +1357,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
usb_set_serial_port_data(port, priv);
- ftdi_determine_type (port);
+ ftdi_determine_type(port);
create_sysfs_attrs(port);
return 0;
}
@@ -1325,9 +1365,9 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
/* Setup for the USB-UIRT device, which requires hardwired
* baudrate (38400 gets mapped to 312500) */
/* Called from usbserial:serial_probe */
-static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
+static void ftdi_USB_UIRT_setup(struct ftdi_private *priv)
{
- dbg("%s",__func__);
+ dbg("%s", __func__);
priv->flags |= ASYNC_SPD_CUST;
priv->custom_divisor = 77;
@@ -1336,9 +1376,10 @@ static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
/* Setup for the HE-TIRA1 device, which requires hardwired
* baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */
-static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv)
+
+static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv)
{
- dbg("%s",__func__);
+ dbg("%s", __func__);
priv->flags |= ASYNC_SPD_CUST;
priv->custom_divisor = 240;
@@ -1356,7 +1397,7 @@ static int ftdi_jtag_probe(struct usb_serial *serial)
struct usb_device *udev = serial->dev;
struct usb_interface *interface = serial->interface;
- dbg("%s",__func__);
+ dbg("%s", __func__);
if (interface == udev->actconfig->interface[0]) {
info("Ignoring serial port reserved for JTAG");
@@ -1390,7 +1431,7 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
* calls __serial_close for each open of the port
* shutdown is called then (ie ftdi_shutdown)
*/
-static void ftdi_shutdown (struct usb_serial *serial)
+static void ftdi_shutdown(struct usb_serial *serial)
{
dbg("%s", __func__);
}
@@ -1404,7 +1445,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
remove_sysfs_attrs(port);
/* all open ports are closed at this point
- * (by usbserial.c:__serial_close, which calls ftdi_close)
+ * (by usbserial.c:__serial_close, which calls ftdi_close)
*/
if (priv) {
@@ -1415,7 +1456,8 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
return 0;
}
-static int ftdi_open (struct usb_serial_port *port, struct file *filp)
+static int ftdi_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{ /* ftdi_open */
struct usb_device *dev = port->serial->dev;
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1433,8 +1475,8 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
priv->rx_bytes = 0;
spin_unlock_irqrestore(&priv->rx_lock, flags);
- if (port->tty)
- port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ if (tty)
+ tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
/* No error checking for this (will get errors later anyway) */
/* See ftdi_sio.h for description of what is reset */
@@ -1448,8 +1490,8 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
This is same behaviour as serial.c/rs_open() - Kuba */
/* ftdi_set_termios will send usb control messages */
- if (port->tty)
- ftdi_set_termios(port, port->tty->termios);
+ if (tty)
+ ftdi_set_termios(tty, port, tty->termios);
/* FIXME: Flow control might be enabled, so it should be checked -
we have no control of defaults! */
@@ -1464,12 +1506,14 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
/* Start reading from the device */
priv->rx_processed = 0;
usb_fill_bulk_urb(port->read_urb, dev,
- usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
- ftdi_read_bulk_callback, port);
+ usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ ftdi_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
- err("%s - failed submitting read urb, error %d", __func__, result);
+ err("%s - failed submitting read urb, error %d",
+ __func__, result);
return result;
@@ -1485,16 +1529,17 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
*
*/
-static void ftdi_close (struct usb_serial_port *port, struct file *filp)
+static void ftdi_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{ /* ftdi_close */
- unsigned int c_cflag = port->tty->termios->c_cflag;
+ unsigned int c_cflag = tty->termios->c_cflag;
struct ftdi_private *priv = usb_get_serial_port_data(port);
char buf[1];
dbg("%s", __func__);
mutex_lock(&port->serial->disc_mutex);
- if (c_cflag & HUPCL && !port->serial->disconnected){
+ if (c_cflag & HUPCL && !port->serial->disconnected) {
/* Disable flow control */
if (usb_control_msg(port->serial->dev,
usb_sndctrlpipe(port->serial->dev, 0),
@@ -1527,7 +1572,7 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
*
* The new devices do not require this byte
*/
-static int ftdi_write (struct usb_serial_port *port,
+static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{ /* ftdi_write */
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1554,7 +1599,7 @@ static int ftdi_write (struct usb_serial_port *port,
spin_unlock_irqrestore(&priv->tx_lock, flags);
data_offset = priv->write_offset;
- dbg("data_offset set to %d",data_offset);
+ dbg("data_offset set to %d", data_offset);
/* Determine total transfer size */
transfer_size = count;
@@ -1565,7 +1610,7 @@ static int ftdi_write (struct usb_serial_port *port,
(PKTSZ - data_offset)));
}
- buffer = kmalloc (transfer_size, GFP_ATOMIC);
+ buffer = kmalloc(transfer_size, GFP_ATOMIC);
if (!buffer) {
err("%s ran out of kernel memory for urb ...", __func__);
count = -ENOMEM;
@@ -1581,20 +1626,20 @@ static int ftdi_write (struct usb_serial_port *port,
/* Copy data */
if (data_offset > 0) {
- /* Original sio requires control byte at start of each packet. */
+ /* Original sio requires control byte at start of
+ each packet. */
int user_pktsz = PKTSZ - data_offset;
int todo = count;
unsigned char *first_byte = buffer;
const unsigned char *current_position = buf;
while (todo > 0) {
- if (user_pktsz > todo) {
+ if (user_pktsz > todo)
user_pktsz = todo;
- }
/* Write the control byte at the front of the packet*/
*first_byte = 1 | ((user_pktsz) << 2);
/* Copy data for packet */
- memcpy (first_byte + data_offset,
+ memcpy(first_byte + data_offset,
current_position, user_pktsz);
first_byte += user_pktsz + data_offset;
current_position += user_pktsz;
@@ -1603,20 +1648,23 @@ static int ftdi_write (struct usb_serial_port *port,
} else {
/* No control byte required. */
/* Copy in the data to send */
- memcpy (buffer, buf, count);
+ memcpy(buffer, buf, count);
}
- usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, buffer);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ transfer_size, buffer);
/* fill the buffer and send it */
usb_fill_bulk_urb(urb, port->serial->dev,
- usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress),
- buffer, transfer_size,
- ftdi_write_bulk_callback, port);
+ usb_sndbulkpipe(port->serial->dev,
+ port->bulk_out_endpointAddress),
+ buffer, transfer_size,
+ ftdi_write_bulk_callback, port);
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
- err("%s - failed submitting write urb, error %d", __func__, status);
+ err("%s - failed submitting write urb, error %d",
+ __func__, status);
count = status;
goto error;
} else {
@@ -1635,7 +1683,7 @@ static int ftdi_write (struct usb_serial_port *port,
error:
usb_free_urb(urb);
error_no_urb:
- kfree (buffer);
+ kfree(buffer);
error_no_buffer:
spin_lock_irqsave(&priv->tx_lock, flags);
priv->tx_outstanding_urbs--;
@@ -1646,7 +1694,7 @@ error_no_buffer:
/* This function may get called when the device is closed */
-static void ftdi_write_bulk_callback (struct urb *urb)
+static void ftdi_write_bulk_callback(struct urb *urb)
{
unsigned long flags;
struct usb_serial_port *port = urb->context;
@@ -1656,7 +1704,7 @@ static void ftdi_write_bulk_callback (struct urb *urb)
int status = urb->status;
/* free up the transfer buffer, as usb_free_urb() does not do this */
- kfree (urb->transfer_buffer);
+ kfree(urb->transfer_buffer);
dbg("%s - port %d", __func__, port->number);
@@ -1686,8 +1734,9 @@ static void ftdi_write_bulk_callback (struct urb *urb)
} /* ftdi_write_bulk_callback */
-static int ftdi_write_room( struct usb_serial_port *port )
+static int ftdi_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
int room;
unsigned long flags;
@@ -1707,11 +1756,11 @@ static int ftdi_write_room( struct usb_serial_port *port )
}
spin_unlock_irqrestore(&priv->tx_lock, flags);
return room;
-} /* ftdi_write_room */
-
+}
-static int ftdi_chars_in_buffer (struct usb_serial_port *port)
-{ /* ftdi_chars_in_buffer */
+static int ftdi_chars_in_buffer(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
int buffered;
unsigned long flags;
@@ -1726,12 +1775,10 @@ static int ftdi_chars_in_buffer (struct usb_serial_port *port)
buffered = 0;
}
return buffered;
-} /* ftdi_chars_in_buffer */
-
-
+}
-static void ftdi_read_bulk_callback (struct urb *urb)
-{ /* ftdi_read_bulk_callback */
+static void ftdi_read_bulk_callback(struct urb *urb)
+{
struct usb_serial_port *port = urb->context;
struct tty_struct *tty;
struct ftdi_private *priv;
@@ -1740,19 +1787,21 @@ static void ftdi_read_bulk_callback (struct urb *urb)
int status = urb->status;
if (urb->number_of_packets > 0) {
- err("%s transfer_buffer_length %d actual_length %d number of packets %d",__func__,
- urb->transfer_buffer_length, urb->actual_length, urb->number_of_packets );
- err("%s transfer_flags %x ", __func__,urb->transfer_flags );
+ err("%s transfer_buffer_length %d actual_length %d number of packets %d",
+ __func__,
+ urb->transfer_buffer_length,
+ urb->actual_length, urb->number_of_packets);
+ err("%s transfer_flags %x ", __func__, urb->transfer_flags);
}
dbg("%s - port %d", __func__, port->number);
- if (port->open_count <= 0)
+ if (port->port.count <= 0)
return;
- tty = port->tty;
+ tty = port->port.tty;
if (!tty) {
- dbg("%s - bad tty pointer - exiting",__func__);
+ dbg("%s - bad tty pointer - exiting", __func__);
return;
}
@@ -1762,14 +1811,13 @@ static void ftdi_read_bulk_callback (struct urb *urb)
return;
}
- if (urb != port->read_urb) {
+ if (urb != port->read_urb)
err("%s - Not my urb!", __func__);
- }
if (status) {
- /* This will happen at close every time so it is a dbg not an err */
- dbg("(this is ok on close) nonzero read bulk status received: "
- "%d", status);
+ /* This will happen at close every time so it is a dbg not an
+ err */
+ dbg("(this is ok on close) nonzero read bulk status received: %d", status);
return;
}
@@ -1785,7 +1833,7 @@ static void ftdi_read_bulk_callback (struct urb *urb)
} /* ftdi_read_bulk_callback */
-static void ftdi_process_read (struct work_struct *work)
+static void ftdi_process_read(struct work_struct *work)
{ /* ftdi_process_read */
struct ftdi_private *priv =
container_of(work, struct ftdi_private, rx_work.work);
@@ -1803,12 +1851,12 @@ static void ftdi_process_read (struct work_struct *work)
dbg("%s - port %d", __func__, port->number);
- if (port->open_count <= 0)
+ if (port->port.count <= 0)
return;
- tty = port->tty;
+ tty = port->port.tty;
if (!tty) {
- dbg("%s - bad tty pointer - exiting",__func__);
+ dbg("%s - bad tty pointer - exiting", __func__);
return;
}
@@ -1832,11 +1880,11 @@ static void ftdi_process_read (struct work_struct *work)
urb->actual_length - priv->rx_processed);
} else {
/* The first two bytes of every read packet are status */
- if (urb->actual_length > 2) {
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
- } else {
- dbg("Status only: %03oo %03oo",data[0],data[1]);
- }
+ if (urb->actual_length > 2)
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
+ else
+ dbg("Status only: %03oo %03oo", data[0], data[1]);
}
@@ -1846,16 +1894,19 @@ static void ftdi_process_read (struct work_struct *work)
/* if CD is dropped and the line is not CLOCAL then we should hangup */
need_flip = 0;
- for (packet_offset = priv->rx_processed; packet_offset < urb->actual_length; packet_offset += PKTSZ) {
+ for (packet_offset = priv->rx_processed;
+ packet_offset < urb->actual_length; packet_offset += PKTSZ) {
int length;
- /* Compare new line status to the old one, signal if different */
- /* N.B. packet may be processed more than once, but differences
- * are only processed once. */
+ /* Compare new line status to the old one, signal if different/
+ N.B. packet may be processed more than once, but differences
+ are only processed once. */
if (priv != NULL) {
- char new_status = data[packet_offset+0] & FTDI_STATUS_B0_MASK;
+ char new_status = data[packet_offset + 0] &
+ FTDI_STATUS_B0_MASK;
if (new_status != priv->prev_status) {
- priv->diff_status |= new_status ^ priv->prev_status;
+ priv->diff_status |=
+ new_status ^ priv->prev_status;
wake_up_interruptible(&priv->delta_msr_wait);
priv->prev_status = new_status;
}
@@ -1872,30 +1923,31 @@ static void ftdi_process_read (struct work_struct *work)
break;
}
if (tty_buffer_request_room(tty, length) < length) {
- /* break out & wait for throttling/unthrottling to happen */
+ /* break out & wait for throttling/unthrottling to
+ happen */
dbg("%s - receive room low", __func__);
break;
}
/* Handle errors and break */
error_flag = TTY_NORMAL;
- /* Although the device uses a bitmask and hence can have multiple */
- /* errors on a packet - the order here sets the priority the */
- /* error is returned to the tty layer */
+ /* Although the device uses a bitmask and hence can have
+ multiple errors on a packet - the order here sets the
+ priority the error is returned to the tty layer */
- if ( data[packet_offset+1] & FTDI_RS_OE ) {
+ if (data[packet_offset+1] & FTDI_RS_OE) {
error_flag = TTY_OVERRUN;
dbg("OVERRRUN error");
}
- if ( data[packet_offset+1] & FTDI_RS_BI ) {
+ if (data[packet_offset+1] & FTDI_RS_BI) {
error_flag = TTY_BREAK;
dbg("BREAK received");
}
- if ( data[packet_offset+1] & FTDI_RS_PE ) {
+ if (data[packet_offset+1] & FTDI_RS_PE) {
error_flag = TTY_PARITY;
dbg("PARITY error");
}
- if ( data[packet_offset+1] & FTDI_RS_FE ) {
+ if (data[packet_offset+1] & FTDI_RS_FE) {
error_flag = TTY_FRAME;
dbg("FRAMING error");
}
@@ -1904,7 +1956,8 @@ static void ftdi_process_read (struct work_struct *work)
/* Note that the error flag is duplicated for
every character received since we don't know
which character it applied to */
- tty_insert_flip_char(tty, data[packet_offset+i], error_flag);
+ tty_insert_flip_char(tty,
+ data[packet_offset + i], error_flag);
}
need_flip = 1;
}
@@ -1912,19 +1965,19 @@ static void ftdi_process_read (struct work_struct *work)
#ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW
/* if a parity error is detected you get status packets forever
until a character is sent without a parity error.
- This doesn't work well since the application receives a never
- ending stream of bad data - even though new data hasn't been sent.
- Therefore I (bill) have taken this out.
+ This doesn't work well since the application receives a
+ never ending stream of bad data - even though new data
+ hasn't been sent. Therefore I (bill) have taken this out.
However - this might make sense for framing errors and so on
so I am leaving the code in for now.
*/
else {
- if (error_flag != TTY_NORMAL){
+ if (error_flag != TTY_NORMAL) {
dbg("error_flag is not normal");
- /* In this case it is just status - if that is an error send a bad character */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ /* In this case it is just status - if that is
+ an error send a bad character */
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
tty_flip_buffer_push(tty);
- }
tty_insert_flip_char(tty, 0xff, error_flag);
need_flip = 1;
}
@@ -1933,9 +1986,8 @@ static void ftdi_process_read (struct work_struct *work)
} /* "for(packet_offset=0..." */
/* Low latency */
- if (need_flip) {
+ if (need_flip)
tty_flip_buffer_push(tty);
- }
if (packet_offset < urb->actual_length) {
/* not completely processed - record progress */
@@ -1954,12 +2006,11 @@ static void ftdi_process_read (struct work_struct *work)
}
spin_unlock_irqrestore(&priv->rx_lock, flags);
/* if the port is closed stop trying to read */
- if (port->open_count > 0){
+ if (port->port.count > 0)
/* delay processing of remainder */
schedule_delayed_work(&priv->rx_work, 1);
- } else {
+ else
dbg("%s - port is closed", __func__);
- }
return;
}
@@ -1967,24 +2018,26 @@ static void ftdi_process_read (struct work_struct *work)
priv->rx_processed = 0;
/* if the port is closed stop trying to read */
- if (port->open_count > 0){
+ if (port->port.count > 0) {
/* Continue trying to always read */
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,
- ftdi_read_bulk_callback, port);
+ usb_rcvbulkpipe(port->serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ ftdi_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d", __func__, result);
+ err("%s - failed resubmitting read urb, error %d",
+ __func__, result);
}
-
- return;
} /* ftdi_process_read */
-static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
+static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
__u16 urb_value = 0;
char buf[1];
@@ -1993,22 +2046,23 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
/* see drivers/char/tty_io.c to see it used */
/* last_set_data_urb_value NEVER has the break bit set in it */
- if (break_state) {
+ if (break_state)
urb_value = priv->last_set_data_urb_value | FTDI_SIO_SET_BREAK;
- } else {
+ else
urb_value = priv->last_set_data_urb_value;
- }
-
- if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
- FTDI_SIO_SET_DATA_REQUEST,
- FTDI_SIO_SET_DATA_REQUEST_TYPE,
- urb_value , priv->interface,
- buf, 0, WDR_TIMEOUT) < 0) {
- err("%s FAILED to enable/disable break state (state was %d)", __func__,break_state);
+ if (usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
+ FTDI_SIO_SET_DATA_REQUEST,
+ FTDI_SIO_SET_DATA_REQUEST_TYPE,
+ urb_value , priv->interface,
+ buf, 0, WDR_TIMEOUT) < 0) {
+ err("%s FAILED to enable/disable break state (state was %d)",
+ __func__, break_state);
}
- dbg("%s break state is %d - urb is %d", __func__,break_state, urb_value);
+ dbg("%s break state is %d - urb is %d", __func__,
+ break_state, urb_value);
}
@@ -2018,26 +2072,28 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
* WARNING: set_termios calls this with old_termios in kernel space
*/
-static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void ftdi_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{ /* ftdi_termios */
struct usb_device *dev = port->serial->dev;
struct ftdi_private *priv = usb_get_serial_port_data(port);
- struct ktermios *termios = port->tty->termios;
+ struct ktermios *termios = tty->termios;
unsigned int cflag = termios->c_cflag;
__u16 urb_value; /* will hold the new flags */
char buf[1]; /* Perhaps I should dynamically alloc this? */
- // Added for xon/xoff support
+ /* Added for xon/xoff support */
unsigned int iflag = termios->c_iflag;
unsigned char vstop;
unsigned char vstart;
dbg("%s", __func__);
- /* Force baud rate if this device requires it, unless it is set to B0. */
+ /* Force baud rate if this device requires it, unless it is set to
+ B0. */
if (priv->force_baud && ((termios->c_cflag & CBAUD) != B0)) {
dbg("%s: forcing baud rate for this device", __func__);
- tty_encode_baud_rate(port->tty, priv->force_baud,
+ tty_encode_baud_rate(tty, priv->force_baud,
priv->force_baud);
}
@@ -2053,8 +2109,8 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
not - so just do the change regardless - should be able to
compare old_termios and tty->termios */
/* NOTE These routines can get interrupted by
- ftdi_sio_read_bulk_callback - need to examine what this
- means - don't see any problems yet */
+ ftdi_sio_read_bulk_callback - need to examine what this means -
+ don't see any problems yet */
/* Set number of data bits, parity, stop bits */
@@ -2078,8 +2134,8 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
}
}
- /* This is needed by the break command since it uses the same command - but is
- * or'ed with this value */
+ /* This is needed by the break command since it uses the same command
+ - but is or'ed with this value */
priv->last_set_data_urb_value = urb_value;
if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -2091,7 +2147,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
}
/* Now do the baudrate */
- if ((cflag & CBAUD) == B0 ) {
+ if ((cflag & CBAUD) == B0) {
/* Disable flow control */
if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
@@ -2104,13 +2160,11 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
} else {
/* set the baudrate determined before */
- if (change_speed(port)) {
+ if (change_speed(tty, port))
err("%s urb failed to set baudrate", __func__);
- }
/* Ensure RTS and DTR are raised when baudrate changed from 0 */
- if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) {
+ if (!old_termios || (old_termios->c_cflag & CBAUD) == B0)
set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
- }
}
/* Set flow control */
@@ -2130,18 +2184,22 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
/*
* Xon/Xoff code
*
- * Check the IXOFF status in the iflag component of the termios structure
- * if IXOFF is not set, the pre-xon/xoff code is executed.
- */
+ * Check the IXOFF status in the iflag component of the
+ * termios structure. If IXOFF is not set, the pre-xon/xoff
+ * code is executed.
+ */
if (iflag & IXOFF) {
- dbg("%s request to enable xonxoff iflag=%04x",__func__,iflag);
- // Try to enable the XON/XOFF on the ftdi_sio
- // Set the vstart and vstop -- could have been done up above where
- // a lot of other dereferencing is done but that would be very
- // inefficient as vstart and vstop are not always needed
+ dbg("%s request to enable xonxoff iflag=%04x",
+ __func__, iflag);
+ /* Try to enable the XON/XOFF on the ftdi_sio
+ * Set the vstart and vstop -- could have been done up
+ * above where a lot of other dereferencing is done but
+ * that would be very inefficient as vstart and vstop
+ * are not always needed.
+ */
vstart = termios->c_cc[VSTART];
vstop = termios->c_cc[VSTOP];
- urb_value=(vstop << 8) | (vstart);
+ urb_value = (vstop << 8) | (vstart);
if (usb_control_msg(dev,
usb_sndctrlpipe(dev, 0),
@@ -2153,8 +2211,9 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
err("urb failed to set to xon/xoff flow control");
}
} else {
- /* else clause to only run if cfag ! CRTSCTS and iflag ! XOFF */
- /* CHECKME Assuming XON/XOFF handled by tty stack - not by device */
+ /* else clause to only run if cflag ! CRTSCTS and iflag
+ * ! XOFF. CHECKME Assuming XON/XOFF handled by tty
+ * stack - not by device */
dbg("%s Turning off hardware flow control", __func__);
if (usb_control_msg(dev,
usb_sndctrlpipe(dev, 0),
@@ -2168,11 +2227,11 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
}
return;
-} /* ftdi_termios */
-
+}
-static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
+static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
unsigned char buf[2];
int ret;
@@ -2181,32 +2240,35 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
switch (priv->chip_type) {
case SIO:
/* Request the status from the device */
- if ((ret = usb_control_msg(port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0),
- FTDI_SIO_GET_MODEM_STATUS_REQUEST,
- FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
- 0, 0,
- buf, 1, WDR_TIMEOUT)) < 0 ) {
+ ret = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST,
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+ 0, 0,
+ buf, 1, WDR_TIMEOUT);
+ if (ret < 0) {
err("%s Could not get modem status of device - err: %d", __func__,
ret);
- return(ret);
+ return ret;
}
break;
case FT8U232AM:
case FT232BM:
case FT2232C:
case FT232RL:
- /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
- format as the data returned from the in point */
- if ((ret = usb_control_msg(port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0),
- FTDI_SIO_GET_MODEM_STATUS_REQUEST,
- FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
- 0, priv->interface,
- buf, 2, WDR_TIMEOUT)) < 0 ) {
+ /* the 8U232AM returns a two byte value (the sio is a 1 byte
+ value) - in the same format as the data returned from the in
+ point */
+ ret = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST,
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+ 0, priv->interface,
+ buf, 2, WDR_TIMEOUT);
+ if (ret < 0) {
err("%s Could not get modem status of device - err: %d", __func__,
ret);
- return(ret);
+ return ret;
}
break;
default:
@@ -2221,15 +2283,19 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
priv->last_dtr_rts;
}
-static int ftdi_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear)
+static int ftdi_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s TIOCMSET", __func__);
return update_mctrl(port, set, clear);
}
-static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+static int ftdi_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
dbg("%s cmd 0x%04x", __func__, cmd);
@@ -2238,10 +2304,12 @@ static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigne
switch (cmd) {
case TIOCGSERIAL: /* gets serial port data */
- return get_serial_info(port, (struct serial_struct __user *) arg);
+ return get_serial_info(port,
+ (struct serial_struct __user *) arg);
case TIOCSSERIAL: /* sets serial port data */
- return set_serial_info(port, (struct serial_struct __user *) arg);
+ return set_serial_info(tty, port,
+ (struct serial_struct __user *) arg);
/*
* Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
@@ -2260,45 +2328,41 @@ static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigne
else {
char diff = priv->diff_status;
- if (diff == 0) {
+ if (diff == 0)
return -EIO; /* no change => error */
- }
/* Consume all events */
priv->diff_status = 0;
- /* Return 0 if caller wanted to know about these bits */
- if ( ((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) ||
- ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) ||
- ((arg & TIOCM_CD) && (diff & FTDI_RS0_RLSD)) ||
- ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS)) ) {
+ /* Return 0 if caller wanted to know about
+ these bits */
+ if (((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) ||
+ ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) ||
+ ((arg & TIOCM_CD) && (diff & FTDI_RS0_RLSD)) ||
+ ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS))) {
return 0;
}
/*
- * Otherwise caller can't care less about what happened,
- * and so we continue to wait for more events.
+ * Otherwise caller can't care less about what
+ * happened,and so we continue to wait for more
+ * events.
*/
}
}
- return(0);
- break;
+ return 0;
default:
break;
-
}
-
-
- /* This is not necessarily an error - turns out the higher layers will do
- * some ioctls itself (see comment above)
+ /* This is not necessarily an error - turns out the higher layers
+ * will do some ioctls themselves (see comment above)
*/
dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __func__, cmd);
+ return -ENOIOCTLCMD;
+}
- return(-ENOIOCTLCMD);
-} /* ftdi_ioctl */
-
-
-static void ftdi_throttle (struct usb_serial_port *port)
+static void ftdi_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -2310,8 +2374,9 @@ static void ftdi_throttle (struct usb_serial_port *port)
}
-static void ftdi_unthrottle (struct usb_serial_port *port)
+static void ftdi_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
int actually_throttled;
unsigned long flags;
@@ -2327,7 +2392,7 @@ static void ftdi_unthrottle (struct usb_serial_port *port)
schedule_delayed_work(&priv->rx_work, 0);
}
-static int __init ftdi_init (void)
+static int __init ftdi_init(void)
{
int retval;
@@ -2357,13 +2422,13 @@ failed_sio_register:
}
-static void __exit ftdi_exit (void)
+static void __exit ftdi_exit(void)
{
dbg("%s", __func__);
- usb_deregister (&ftdi_driver);
- usb_serial_deregister (&ftdi_sio_device);
+ usb_deregister(&ftdi_driver);
+ usb_serial_deregister(&ftdi_sio_device);
}
@@ -2371,8 +2436,8 @@ static void __exit ftdi_exit (void)
module_init(ftdi_init);
module_exit(ftdi_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 8302eca893e..a577ea44dcf 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -1,20 +1,20 @@
/*
- * Definitions for the FTDI USB Single Port Serial Converter -
- * known as FTDI_SIO (Serial Input/Output application of the chipset)
+ * Definitions for the FTDI USB Single Port Serial Converter -
+ * known as FTDI_SIO (Serial Input/Output application of the chipset)
*
* The example I have is known as the USC-1000 which is available from
* http://www.dse.co.nz - cat no XH4214 It looks similar to this:
* http://www.dansdata.com/usbser.htm but I can't be sure There are other
* USC-1000s which don't look like my device though so beware!
*
- * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side,
+ * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side,
* USB on the other.
*
* Thanx to FTDI (http://www.ftdi.co.uk) for so kindly providing details
* of the protocol required to talk to the device and ongoing assistence
* during development.
*
- * Bill Ryder - bryder@sgi.com formerly of Silicon Graphics, Inc.- wrote the
+ * Bill Ryder - bryder@sgi.com formerly of Silicon Graphics, Inc.- wrote the
* FTDI_SIO implementation.
*
* Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais
@@ -472,7 +472,7 @@
/*
* DSS-20 Sync Station for Sony Ericsson P800
*/
-#define FTDI_DSS20_PID 0xFC82
+#define FTDI_DSS20_PID 0xFC82
/*
* Home Electronics (www.home-electro.com) USB gadgets
@@ -884,7 +884,7 @@
/*
* BmRequestType: 0100 0000B
* bRequest: FTDI_SIO_RESET
- * wValue: Control Value
+ * wValue: Control Value
* 0 = Reset SIO
* 1 = Purge RX buffer
* 2 = Purge TX buffer
@@ -952,7 +952,7 @@
* 101 - add .625 to divisor
* 110 - add .750 to divisor
* 111 - add .875 to divisor
- * Bits 15 to 0 of the 17-bit divisor are placed in the urb value. Bit 16 is
+ * Bits 15 to 0 of the 17-bit divisor are placed in the urb value. Bit 16 is
* placed in bit 0 of the urb index.
*
* Note that there are a couple of special cases to support the highest baud
@@ -971,8 +971,8 @@ typedef enum {
} ftdi_chip_type_t;
typedef enum {
- ftdi_sio_b300 = 0,
- ftdi_sio_b600 = 1,
+ ftdi_sio_b300 = 0,
+ ftdi_sio_b600 = 1,
ftdi_sio_b1200 = 2,
ftdi_sio_b2400 = 3,
ftdi_sio_b4800 = 4,
@@ -981,7 +981,7 @@ typedef enum {
ftdi_sio_b38400 = 7,
ftdi_sio_b57600 = 8,
ftdi_sio_b115200 = 9
-} FTDI_SIO_baudrate_t ;
+} FTDI_SIO_baudrate_t;
/*
* The ftdi_8U232AM_xxMHz_byyy constants have been removed. The encoded divisor values
@@ -990,19 +990,19 @@ typedef enum {
#define FTDI_SIO_SET_DATA_REQUEST FTDI_SIO_SET_DATA
#define FTDI_SIO_SET_DATA_REQUEST_TYPE 0x40
-#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8 )
-#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8 )
-#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8 )
-#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8 )
-#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8 )
-#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11 )
-#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11 )
-#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11 )
+#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8)
+#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8)
+#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8)
+#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8)
+#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8)
+#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11)
+#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11)
+#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11)
#define FTDI_SIO_SET_BREAK (0x1 << 14)
/* FTDI_SIO_SET_DATA */
/*
- * BmRequestType: 0100 0000B
+ * BmRequestType: 0100 0000B
* bRequest: FTDI_SIO_SET_DATA
* wValue: Data characteristics (see below)
* wIndex: Port
@@ -1035,7 +1035,7 @@ typedef enum {
#define FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE 0x40
#define FTDI_SIO_SET_MODEM_CTRL_REQUEST FTDI_SIO_MODEM_CTRL
-/*
+/*
* BmRequestType: 0100 0000B
* bRequest: FTDI_SIO_MODEM_CTRL
* wValue: ControlValue (see below)
@@ -1049,11 +1049,11 @@ typedef enum {
*/
#define FTDI_SIO_SET_DTR_MASK 0x1
-#define FTDI_SIO_SET_DTR_HIGH ( 1 | ( FTDI_SIO_SET_DTR_MASK << 8))
-#define FTDI_SIO_SET_DTR_LOW ( 0 | ( FTDI_SIO_SET_DTR_MASK << 8))
+#define FTDI_SIO_SET_DTR_HIGH (1 | (FTDI_SIO_SET_DTR_MASK << 8))
+#define FTDI_SIO_SET_DTR_LOW (0 | (FTDI_SIO_SET_DTR_MASK << 8))
#define FTDI_SIO_SET_RTS_MASK 0x2
-#define FTDI_SIO_SET_RTS_HIGH ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 ))
-#define FTDI_SIO_SET_RTS_LOW ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 ))
+#define FTDI_SIO_SET_RTS_HIGH (2 | (FTDI_SIO_SET_RTS_MASK << 8))
+#define FTDI_SIO_SET_RTS_LOW (0 | (FTDI_SIO_SET_RTS_MASK << 8))
/*
* ControlValue
@@ -1076,7 +1076,7 @@ typedef enum {
/* FTDI_SIO_SET_FLOW_CTRL */
#define FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE 0x40
#define FTDI_SIO_SET_FLOW_CTRL_REQUEST FTDI_SIO_SET_FLOW_CTRL
-#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0
+#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0
#define FTDI_SIO_RTS_CTS_HS (0x1 << 8)
#define FTDI_SIO_DTR_DSR_HS (0x2 << 8)
#define FTDI_SIO_XON_XOFF_HS (0x4 << 8)
@@ -1085,7 +1085,7 @@ typedef enum {
* bRequest: FTDI_SIO_SET_FLOW_CTRL
* wValue: Xoff/Xon
* wIndex: Protocol/Port - hIndex is protocl / lIndex is port
- * wLength: 0
+ * wLength: 0
* Data: None
*
* hIndex protocol is:
@@ -1101,10 +1101,10 @@ typedef enum {
*
* A value of zero in the hIndex field disables handshaking
*
- * If Xon/Xoff handshaking is specified, the hValue field should contain the XOFF character
+ * If Xon/Xoff handshaking is specified, the hValue field should contain the XOFF character
* and the lValue field contains the XON character.
- */
-
+ */
+
/*
* FTDI_SIO_GET_LATENCY_TIMER
*
@@ -1118,7 +1118,7 @@ typedef enum {
#define FTDI_SIO_GET_LATENCY_TIMER_REQUEST FTDI_SIO_GET_LATENCY_TIMER
#define FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE 0xC0
-/*
+/*
* BmRequestType: 1100 0000b
* bRequest: FTDI_SIO_GET_LATENCY_TIMER
* wValue: 0
@@ -1127,7 +1127,7 @@ typedef enum {
* Data: latency (on return)
*/
-/*
+/*
* FTDI_SIO_SET_LATENCY_TIMER
*
* Set the timeout interval. The FTDI collects data from the slave
@@ -1140,7 +1140,7 @@ typedef enum {
#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST FTDI_SIO_SET_LATENCY_TIMER
#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE 0x40
-/*
+/*
* BmRequestType: 0100 0000b
* bRequest: FTDI_SIO_SET_LATENCY_TIMER
* wValue: Latency (milliseconds)
@@ -1155,7 +1155,7 @@ typedef enum {
*/
/*
- * FTDI_SIO_SET_EVENT_CHAR
+ * FTDI_SIO_SET_EVENT_CHAR
*
* Set the special event character for the specified communications port.
* If the device sees this character it will immediately return the
@@ -1168,7 +1168,7 @@ typedef enum {
#define FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE 0x40
-/*
+/*
* BmRequestType: 0100 0000b
* bRequest: FTDI_SIO_SET_EVENT_CHAR
* wValue: EventChar
@@ -1184,12 +1184,12 @@ typedef enum {
* B9..15 Reserved
*
*/
-
+
/* FTDI_SIO_SET_ERROR_CHAR */
/* Set the parity error replacement character for the specified communications port */
-/*
+/*
* BmRequestType: 0100 0000b
* bRequest: FTDI_SIO_SET_EVENT_CHAR
* wValue: Error Char
@@ -1215,15 +1215,15 @@ typedef enum {
#define FTDI_SIO_DSR_MASK 0x20
#define FTDI_SIO_RI_MASK 0x40
#define FTDI_SIO_RLSD_MASK 0x80
-/*
+/*
* BmRequestType: 1100 0000b
* bRequest: FTDI_SIO_GET_MODEM_STATUS
* wValue: zero
* wIndex: Port
* wLength: 1
* Data: Status
- *
- * One byte of data is returned
+ *
+ * One byte of data is returned
* B0..3 0
* B4 CTS
* 0 = inactive
@@ -1236,15 +1236,15 @@ typedef enum {
* 1 = active
* B7 Receive Line Signal Detect (RLSD)
* 0 = inactive
- * 1 = active
+ * 1 = active
*/
-/* Descriptors returned by the device
- *
+/* Descriptors returned by the device
+ *
* Device Descriptor
- *
+ *
* Offset Field Size Value Description
* 0 bLength 1 0x12 Size of descriptor in bytes
* 1 bDescriptorType 1 0x01 DEVICE Descriptor Type
@@ -1260,9 +1260,9 @@ typedef enum {
* 15 iProduct 1 0x02 Index of prod string desc
* 16 iSerialNumber 1 0x02 Index of serial nmr string desc
* 17 bNumConfigurations 1 0x01 Number of possible configurations
- *
+ *
* Configuration Descriptor
- *
+ *
* Offset Field Size Value
* 0 bLength 1 0x09 Size of descriptor in bytes
* 1 bDescriptorType 1 0x02 CONFIGURATION Descriptor Type
@@ -1272,9 +1272,9 @@ typedef enum {
* 6 iConfiguration 1 0x02 Index of config string descriptor
* 7 bmAttributes 1 0x20 Config characteristics Remote Wakeup
* 8 MaxPower 1 0x1E Max power consumption
- *
+ *
* Interface Descriptor
- *
+ *
* Offset Field Size Value
* 0 bLength 1 0x09 Size of descriptor in bytes
* 1 bDescriptorType 1 0x04 INTERFACE Descriptor Type
@@ -1285,9 +1285,9 @@ typedef enum {
* 6 bInterfaceSubClass 1 0xFF Subclass Code
* 7 bInterfaceProtocol 1 0xFF Protocol Code
* 8 iInterface 1 0x02 Index of interface string description
- *
+ *
* IN Endpoint Descriptor
- *
+ *
* Offset Field Size Value
* 0 bLength 1 0x07 Size of descriptor in bytes
* 1 bDescriptorType 1 0x05 ENDPOINT descriptor type
@@ -1295,9 +1295,9 @@ typedef enum {
* 3 bmAttributes 1 0x02 Endpoint attributes - Bulk
* 4 bNumEndpoints 2 0x0040 maximum packet size
* 5 bInterval 1 0x00 Interval for polling endpoint
- *
+ *
* OUT Endpoint Descriptor
- *
+ *
* Offset Field Size Value
* 0 bLength 1 0x07 Size of descriptor in bytes
* 1 bDescriptorType 1 0x05 ENDPOINT descriptor type
@@ -1305,17 +1305,17 @@ typedef enum {
* 3 bmAttributes 1 0x02 Endpoint attributes - Bulk
* 4 bNumEndpoints 2 0x0040 maximum packet size
* 5 bInterval 1 0x00 Interval for polling endpoint
- *
+ *
* DATA FORMAT
- *
+ *
* IN Endpoint
- *
+ *
* The device reserves the first two bytes of data on this endpoint to contain the current
* values of the modem and line status registers. In the absence of data, the device
* generates a message consisting of these two status bytes every 40 ms
- *
+ *
* Byte 0: Modem Status
- *
+ *
* Offset Description
* B0 Reserved - must be 1
* B1 Reserved - must be 0
@@ -1325,9 +1325,9 @@ typedef enum {
* B5 Data Set Ready (DSR)
* B6 Ring Indicator (RI)
* B7 Receive Line Signal Detect (RLSD)
- *
+ *
* Byte 1: Line Status
- *
+ *
* Offset Description
* B0 Data Ready (DR)
* B1 Overrun Error (OE)
@@ -1337,7 +1337,7 @@ typedef enum {
* B5 Transmitter Holding Register (THRE)
* B6 Transmitter Empty (TEMT)
* B7 Error in RCVR FIFO
- *
+ *
*/
#define FTDI_RS0_CTS (1 << 4)
#define FTDI_RS0_DSR (1 << 5)
@@ -1355,17 +1355,17 @@ typedef enum {
/*
* OUT Endpoint
- *
+ *
* This device reserves the first bytes of data on this endpoint contain the length
* and port identifier of the message. For the FTDI USB Serial converter the port
* identifier is always 1.
- *
+ *
* Byte 0: Line Status
- *
+ *
* Offset Description
* B0 Reserved - must be 1
* B1 Reserved - must be 0
* B2..7 Length of message - (not including Byte 0)
- *
+ *
*/
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
index e8ba2cb5995..d30f736d2cc 100644
--- a/drivers/usb/serial/funsoft.c
+++ b/drivers/usb/serial/funsoft.c
@@ -14,7 +14,7 @@
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
static int debug;
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 8ce5a56a48e..2e663f1afd5 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -33,7 +33,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/atomic.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -44,7 +44,7 @@
static int initial_mode = 1;
/* debug flag */
-static int debug = 0;
+static int debug;
#define GARMIN_VENDOR_ID 0x091E
@@ -56,7 +56,7 @@ static int debug = 0;
#define VERSION_MINOR 31
#define _STR(s) #s
-#define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b)
+#define _DRIVER_VERSION(a, b) "v" _STR(a) "." _STR(b)
#define DRIVER_VERSION _DRIVER_VERSION(VERSION_MAJOR, VERSION_MINOR)
#define DRIVER_AUTHOR "hermann kneissel"
#define DRIVER_DESC "garmin gps driver"
@@ -65,37 +65,37 @@ static int debug = 0;
#define EINVPKT 1000 /* invalid packet structure */
-// size of the header of a packet using the usb protocol
+/* size of the header of a packet using the usb protocol */
#define GARMIN_PKTHDR_LENGTH 12
-// max. possible size of a packet using the serial protocol
-#define MAX_SERIAL_PKT_SIZ (3+255+3)
+/* max. possible size of a packet using the serial protocol */
+#define MAX_SERIAL_PKT_SIZ (3 + 255 + 3)
-// max. possible size of a packet with worst case stuffing
-#define MAX_SERIAL_PKT_SIZ_STUFFED MAX_SERIAL_PKT_SIZ+256
+/* max. possible size of a packet with worst case stuffing */
+#define MAX_SERIAL_PKT_SIZ_STUFFED (MAX_SERIAL_PKT_SIZ + 256)
-// size of a buffer able to hold a complete (no stuffing) packet
-// (the document protocol does not contain packets with a larger
-// size, but in theory a packet may be 64k+12 bytes - if in
-// later protocol versions larger packet sizes occur, this value
-// should be increased accordingly, so the input buffer is always
-// large enough the store a complete packet inclusive header)
-#define GPS_IN_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ)
+/* size of a buffer able to hold a complete (no stuffing) packet
+ * (the document protocol does not contain packets with a larger
+ * size, but in theory a packet may be 64k+12 bytes - if in
+ * later protocol versions larger packet sizes occur, this value
+ * should be increased accordingly, so the input buffer is always
+ * large enough the store a complete packet inclusive header) */
+#define GPS_IN_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ)
-// size of a buffer able to hold a complete (incl. stuffing) packet
-#define GPS_OUT_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ_STUFFED)
+/* size of a buffer able to hold a complete (incl. stuffing) packet */
+#define GPS_OUT_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ_STUFFED)
-// where to place the packet id of a serial packet, so we can
-// prepend the usb-packet header without the need to move the
-// packets data
+/* where to place the packet id of a serial packet, so we can
+ * prepend the usb-packet header without the need to move the
+ * packets data */
#define GSP_INITIAL_OFFSET (GARMIN_PKTHDR_LENGTH-2)
-// max. size of incoming private packets (header+1 param)
+/* max. size of incoming private packets (header+1 param) */
#define PRIVPKTSIZ (GARMIN_PKTHDR_LENGTH+4)
#define GARMIN_LAYERID_TRANSPORT 0
#define GARMIN_LAYERID_APPL 20
-// our own layer-id to use for some control mechanisms
+/* our own layer-id to use for some control mechanisms */
#define GARMIN_LAYERID_PRIVATE 0x01106E4B
#define GARMIN_PKTID_PVT_DATA 51
@@ -103,7 +103,7 @@ static int debug = 0;
#define CMND_ABORT_TRANSFER 0
-// packet ids used in private layer
+/* packet ids used in private layer */
#define PRIV_PKTID_SET_DEBUG 1
#define PRIV_PKTID_SET_MODE 2
#define PRIV_PKTID_INFO_REQ 3
@@ -121,7 +121,8 @@ static int debug = 0;
struct garmin_packet {
struct list_head list;
int seq;
- int size; // the real size of the data array, always > 0
+ /* the real size of the data array, always > 0 */
+ int size;
__u8 data[1];
};
@@ -164,7 +165,7 @@ struct garmin_data {
#define MODE_NATIVE 0
#define MODE_GARMIN_SERIAL 1
-// Flags used in garmin_data.flags:
+/* Flags used in garmin_data.flags: */
#define FLAGS_SESSION_REPLY_MASK 0x00C0
#define FLAGS_SESSION_REPLY1_SEEN 0x0080
#define FLAGS_SESSION_REPLY2_SEEN 0x0040
@@ -185,7 +186,7 @@ struct garmin_data {
/* function prototypes */
-static void gsp_next_packet(struct garmin_data * garmin_data_p);
+static void gsp_next_packet(struct garmin_data *garmin_data_p);
static int garmin_write_bulk(struct usb_serial_port *port,
const unsigned char *buf, int count,
int dismiss_ack);
@@ -217,12 +218,13 @@ static unsigned char const PRIVATE_REQ[]
static struct usb_device_id id_table [] = {
- /* the same device id seems to be used by all usb enabled gps devices */
- { USB_DEVICE(GARMIN_VENDOR_ID, 3 ) },
+ /* the same device id seems to be used by all
+ usb enabled GPS devices */
+ { USB_DEVICE(GARMIN_VENDOR_ID, 3) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver garmin_driver = {
.name = "garmin_gps",
@@ -233,9 +235,10 @@ static struct usb_driver garmin_driver = {
};
-static inline int noResponseFromAppLayer(struct garmin_data * garmin_data_p)
+static inline int noResponseFromAppLayer(struct garmin_data *garmin_data_p)
{
- return atomic_read(&garmin_data_p->req_count) == atomic_read(&garmin_data_p->resp_count);
+ return atomic_read(&garmin_data_p->req_count) ==
+ atomic_read(&garmin_data_p->resp_count);
}
@@ -261,10 +264,10 @@ static inline int getDataLength(const __u8 *usbPacket)
*/
static inline int isAbortTrfCmnd(const unsigned char *buf)
{
- if (0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ,
- sizeof(GARMIN_STOP_TRANSFER_REQ)) ||
- 0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ_V2,
- sizeof(GARMIN_STOP_TRANSFER_REQ_V2)))
+ if (0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ,
+ sizeof(GARMIN_STOP_TRANSFER_REQ)) ||
+ 0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ_V2,
+ sizeof(GARMIN_STOP_TRANSFER_REQ_V2)))
return 1;
else
return 0;
@@ -275,11 +278,11 @@ static inline int isAbortTrfCmnd(const unsigned char *buf)
static void send_to_tty(struct usb_serial_port *port,
char *data, unsigned int actual_length)
{
- struct tty_struct *tty = port->tty;
+ struct tty_struct *tty = port->port.tty;
if (tty && actual_length) {
- usb_serial_debug_data(debug, &port->dev,
+ usb_serial_debug_data(debug, &port->dev,
__func__, actual_length, data);
tty_buffer_request_room(tty, actual_length);
@@ -296,7 +299,7 @@ static void send_to_tty(struct usb_serial_port *port,
/*
* queue a received (usb-)packet for later processing
*/
-static int pkt_add(struct garmin_data * garmin_data_p,
+static int pkt_add(struct garmin_data *garmin_data_p,
unsigned char *data, unsigned int data_length)
{
int state = 0;
@@ -307,7 +310,7 @@ static int pkt_add(struct garmin_data * garmin_data_p,
/* process only packets containg data ... */
if (data_length) {
pkt = kmalloc(sizeof(struct garmin_packet)+data_length,
- GFP_ATOMIC);
+ GFP_ATOMIC);
if (pkt == NULL) {
dev_err(&garmin_data_p->port->dev, "out of memory\n");
return 0;
@@ -325,16 +328,15 @@ static int pkt_add(struct garmin_data * garmin_data_p,
/* in serial mode, if someone is waiting for data from
the device, iconvert and send the next packet to tty. */
- if (result && (state == STATE_GSP_WAIT_DATA)) {
+ if (result && (state == STATE_GSP_WAIT_DATA))
gsp_next_packet(garmin_data_p);
- }
}
return result;
}
/* get the next pending packet */
-static struct garmin_packet *pkt_pop(struct garmin_data * garmin_data_p)
+static struct garmin_packet *pkt_pop(struct garmin_data *garmin_data_p)
{
unsigned long flags;
struct garmin_packet *result = NULL;
@@ -350,7 +352,7 @@ static struct garmin_packet *pkt_pop(struct garmin_data * garmin_data_p)
/* free up all queued data */
-static void pkt_clear(struct garmin_data * garmin_data_p)
+static void pkt_clear(struct garmin_data *garmin_data_p)
{
unsigned long flags;
struct garmin_packet *result = NULL;
@@ -372,7 +374,7 @@ static void pkt_clear(struct garmin_data * garmin_data_p)
******************************************************************************/
/* send an ack packet back to the tty */
-static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
+static int gsp_send_ack(struct garmin_data *garmin_data_p, __u8 pkt_id)
{
__u8 pkt[10];
__u8 cksum = 0;
@@ -391,9 +393,8 @@ static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
*ptr++ = pkt_id;
cksum += pkt_id;
- if (pkt_id == DLE) {
+ if (pkt_id == DLE)
*ptr++ = DLE;
- }
*ptr++ = 0;
*ptr++ = 0xFF & (-cksum);
@@ -415,12 +416,12 @@ static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
* at GSP_INITIAL_OFFSET.
*
* count - number of bytes in the input buffer including space reserved for
- * the usb header: GSP_INITIAL_OFFSET + number of bytes in packet
+ * the usb header: GSP_INITIAL_OFFSET + number of bytes in packet
* (including pkt-id, data-length a. cksum)
*/
-static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
+static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count)
{
- const __u8* recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
+ const __u8 *recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
__le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;
int cksum = 0;
@@ -440,8 +441,8 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
cksum += *recpkt++;
cksum += *recpkt++;
- // sanity check, remove after test ...
- if ((__u8*)&(usbdata[3]) != recpkt) {
+ /* sanity check, remove after test ... */
+ if ((__u8 *)&(usbdata[3]) != recpkt) {
dbg("%s - ptr mismatch %p - %p",
__func__, &(usbdata[4]), recpkt);
return -EINVPKT;
@@ -462,7 +463,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
usbdata[1] = __cpu_to_le32(pktid);
usbdata[2] = __cpu_to_le32(size);
- garmin_write_bulk (garmin_data_p->port, garmin_data_p->inbuffer,
+ garmin_write_bulk(garmin_data_p->port, garmin_data_p->inbuffer,
GARMIN_PKTHDR_LENGTH+size, 0);
/* if this was an abort-transfer command, flush all
@@ -495,7 +496,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
* if the input is an abort command, drop all queued data.
*/
-static int gsp_receive(struct garmin_data * garmin_data_p,
+static int gsp_receive(struct garmin_data *garmin_data_p,
const unsigned char *buf, int count)
{
unsigned long flags;
@@ -504,10 +505,11 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
int i = 0;
__u8 *dest;
int size;
- // dleSeen: set if last byte read was a DLE
+ /* dleSeen: set if last byte read was a DLE */
int dleSeen;
- // skip: if set, skip incoming data until possible start of
- // new packet
+ /* skip: if set, skip incoming data until possible start of
+ * new packet
+ */
int skip;
__u8 data;
@@ -521,14 +523,13 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
dbg("%s - dle=%d skip=%d size=%d count=%d",
__func__, dleSeen, skip, size, count);
- if (size == 0) {
+ if (size == 0)
size = GSP_INITIAL_OFFSET;
- }
while (offs < count) {
data = *(buf+offs);
- offs ++;
+ offs++;
if (data == DLE) {
if (skip) { /* start of a new pkt */
@@ -554,9 +555,8 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
ack_or_nak_seen = NAK;
dbg("NAK packet complete.");
} else {
- dbg("packet complete "
- "- id=0x%X.",
- 0xFF & data);
+ dbg("packet complete - id=0x%X.",
+ 0xFF & data);
gsp_rec_packet(garmin_data_p, size);
}
@@ -589,7 +589,7 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
garmin_data_p->insize = size;
- // copy flags back to structure
+ /* copy flags back to structure */
if (skip)
garmin_data_p->flags |= FLAGS_GSP_SKIP;
else
@@ -600,16 +600,13 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
else
garmin_data_p->flags &= ~FLAGS_GSP_DLESEEN;
- if (ack_or_nak_seen) {
+ if (ack_or_nak_seen)
garmin_data_p->state = STATE_GSP_WAIT_DATA;
- }
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
- if (ack_or_nak_seen) {
+ if (ack_or_nak_seen)
gsp_next_packet(garmin_data_p);
- }
-
return count;
}
@@ -623,7 +620,7 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
*
* return <0 on error, 0 if packet is incomplete or > 0 if packet was sent
*/
-static int gsp_send(struct garmin_data * garmin_data_p,
+static int gsp_send(struct garmin_data *garmin_data_p,
const unsigned char *buf, int count)
{
const unsigned char *src;
@@ -631,11 +628,11 @@ static int gsp_send(struct garmin_data * garmin_data_p,
int pktid = 0;
int datalen = 0;
int cksum = 0;
- int i=0;
+ int i = 0;
int k;
dbg("%s - state %d - %d bytes.", __func__,
- garmin_data_p->state, count);
+ garmin_data_p->state, count);
k = garmin_data_p->outsize;
if ((k+count) > GPS_OUT_BUFSIZ) {
@@ -650,7 +647,7 @@ static int gsp_send(struct garmin_data * garmin_data_p,
if (k >= GARMIN_PKTHDR_LENGTH) {
pktid = getPacketId(garmin_data_p->outbuffer);
- datalen= getDataLength(garmin_data_p->outbuffer);
+ datalen = getDataLength(garmin_data_p->outbuffer);
i = GARMIN_PKTHDR_LENGTH + datalen;
if (k < i)
return 0;
@@ -658,19 +655,18 @@ static int gsp_send(struct garmin_data * garmin_data_p,
return 0;
}
- dbg("%s - %d bytes in buffer, %d bytes in pkt.", __func__,
- k, i);
+ dbg("%s - %d bytes in buffer, %d bytes in pkt.", __func__, k, i);
/* garmin_data_p->outbuffer now contains a complete packet */
usb_serial_debug_data(debug, &garmin_data_p->port->dev,
- __func__, k, garmin_data_p->outbuffer);
+ __func__, k, garmin_data_p->outbuffer);
garmin_data_p->outsize = 0;
if (GARMIN_LAYERID_APPL != getLayerId(garmin_data_p->outbuffer)) {
- dbg("not an application packet (%d)",
- getLayerId(garmin_data_p->outbuffer));
+ dbg("not an application packet (%d)",
+ getLayerId(garmin_data_p->outbuffer));
return -1;
}
@@ -688,14 +684,14 @@ static int gsp_send(struct garmin_data * garmin_data_p,
k = 0;
src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH;
- for (i=0; i<datalen; i++) {
+ for (i = 0; i < datalen; i++) {
if (*src++ == DLE)
k++;
}
src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH;
if (k > (GARMIN_PKTHDR_LENGTH-2)) {
- /* can't add stuffing DLEs in place, move data to end
+ /* can't add stuffing DLEs in place, move data to end
of buffer ... */
dst = garmin_data_p->outbuffer+GPS_OUT_BUFSIZ-datalen;
memcpy(dst, src, datalen);
@@ -712,14 +708,14 @@ static int gsp_send(struct garmin_data * garmin_data_p,
if (datalen == DLE)
*dst++ = DLE;
- for (i=0; i<datalen; i++) {
+ for (i = 0; i < datalen; i++) {
__u8 c = *src++;
*dst++ = c;
cksum += c;
if (c == DLE)
*dst++ = DLE;
}
-
+
cksum = 0xFF & -cksum;
*dst++ = cksum;
if (cksum == DLE)
@@ -744,7 +740,7 @@ static int gsp_send(struct garmin_data * garmin_data_p,
/*
* Process the next pending data packet - if there is one
*/
-static void gsp_next_packet(struct garmin_data * garmin_data_p)
+static void gsp_next_packet(struct garmin_data *garmin_data_p)
{
struct garmin_packet *pkt = NULL;
@@ -774,17 +770,17 @@ static void gsp_next_packet(struct garmin_data * garmin_data_p)
* buf contains the data read, it may span more than one packet
* or even incomplete packets
*/
-static int nat_receive(struct garmin_data * garmin_data_p,
+static int nat_receive(struct garmin_data *garmin_data_p,
const unsigned char *buf, int count)
{
unsigned long flags;
- __u8 * dest;
+ __u8 *dest;
int offs = 0;
int result = count;
int len;
while (offs < count) {
- // if buffer contains header, copy rest of data
+ /* if buffer contains header, copy rest of data */
if (garmin_data_p->insize >= GARMIN_PKTHDR_LENGTH)
len = GARMIN_PKTHDR_LENGTH
+getDataLength(garmin_data_p->inbuffer);
@@ -792,9 +788,9 @@ static int nat_receive(struct garmin_data * garmin_data_p,
len = GARMIN_PKTHDR_LENGTH;
if (len >= GPS_IN_BUFSIZ) {
- /* seem to be an invalid packet, ignore rest of input */
- dbg("%s - packet size too large: %d",
- __func__, len);
+ /* seems to be an invalid packet, ignore rest
+ of input */
+ dbg("%s - packet size too large: %d", __func__, len);
garmin_data_p->insize = 0;
count = 0;
result = -EINVPKT;
@@ -804,7 +800,7 @@ static int nat_receive(struct garmin_data * garmin_data_p,
len = (count-offs);
if (len > 0) {
dest = garmin_data_p->inbuffer
- +garmin_data_p->insize;
+ + garmin_data_p->insize;
memcpy(dest, buf+offs, len);
garmin_data_p->insize += len;
offs += len;
@@ -816,17 +812,19 @@ static int nat_receive(struct garmin_data * garmin_data_p,
len = GARMIN_PKTHDR_LENGTH+
getDataLength(garmin_data_p->inbuffer);
if (garmin_data_p->insize >= len) {
- garmin_write_bulk (garmin_data_p->port,
- garmin_data_p->inbuffer,
- len, 0);
+ garmin_write_bulk(garmin_data_p->port,
+ garmin_data_p->inbuffer,
+ len, 0);
garmin_data_p->insize = 0;
/* if this was an abort-transfer command,
flush all queued data. */
if (isAbortTrfCmnd(garmin_data_p->inbuffer)) {
- spin_lock_irqsave(&garmin_data_p->lock, flags);
+ spin_lock_irqsave(&garmin_data_p->lock,
+ flags);
garmin_data_p->flags |= FLAGS_DROP_DATA;
- spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+ spin_unlock_irqrestore(
+ &garmin_data_p->lock, flags);
pkt_clear(garmin_data_p);
}
}
@@ -842,7 +840,7 @@ static int nat_receive(struct garmin_data * garmin_data_p,
static void priv_status_resp(struct usb_serial_port *port)
{
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
__le32 *pkt = (__le32 *)garmin_data_p->privpkt;
pkt[0] = __cpu_to_le32(GARMIN_LAYERID_PRIVATE);
@@ -852,7 +850,7 @@ static void priv_status_resp(struct usb_serial_port *port)
pkt[4] = __cpu_to_le32(garmin_data_p->mode);
pkt[5] = __cpu_to_le32(garmin_data_p->serial_num);
- send_to_tty(port, (__u8*)pkt, 6*4);
+ send_to_tty(port, (__u8 *)pkt, 6 * 4);
}
@@ -864,7 +862,7 @@ static int process_resetdev_request(struct usb_serial_port *port)
{
unsigned long flags;
int status;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->flags &= ~(CLEAR_HALT_REQUIRED);
@@ -872,8 +870,8 @@ static int process_resetdev_request(struct usb_serial_port *port)
garmin_data_p->serial_num = 0;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
- usb_kill_urb (port->interrupt_in_urb);
- dbg("%s - usb_reset_device", __func__ );
+ usb_kill_urb(port->interrupt_in_urb);
+ dbg("%s - usb_reset_device", __func__);
status = usb_reset_device(port->serial->dev);
if (status)
dbg("%s - usb_reset_device failed: %d",
@@ -886,7 +884,7 @@ static int process_resetdev_request(struct usb_serial_port *port)
/*
* clear all cached data
*/
-static int garmin_clear(struct garmin_data * garmin_data_p)
+static int garmin_clear(struct garmin_data *garmin_data_p)
{
unsigned long flags;
int status = 0;
@@ -896,8 +894,7 @@ static int garmin_clear(struct garmin_data * garmin_data_p)
if (port != NULL && atomic_read(&garmin_data_p->resp_count)) {
/* send a terminate command */
status = garmin_write_bulk(port, GARMIN_STOP_TRANSFER_REQ,
- sizeof(GARMIN_STOP_TRANSFER_REQ),
- 1);
+ sizeof(GARMIN_STOP_TRANSFER_REQ), 1);
}
/* flush all queued data */
@@ -920,28 +917,26 @@ static int garmin_init_session(struct usb_serial_port *port)
{
unsigned long flags;
struct usb_serial *serial = port->serial;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
int status = 0;
if (status == 0) {
- usb_kill_urb (port->interrupt_in_urb);
+ usb_kill_urb(port->interrupt_in_urb);
dbg("%s - adding interrupt input", __func__);
port->interrupt_in_urb->dev = serial->dev;
status = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (status)
dev_err(&serial->dev->dev,
- "%s - failed submitting interrupt urb,"
- " error %d\n",
- __func__, status);
+ "%s - failed submitting interrupt urb, error %d\n",
+ __func__, status);
}
if (status == 0) {
dbg("%s - starting session ...", __func__);
garmin_data_p->state = STATE_ACTIVE;
status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ,
- sizeof(GARMIN_START_SESSION_REQ),
- 0);
+ sizeof(GARMIN_START_SESSION_REQ), 0);
if (status >= 0) {
@@ -951,14 +946,14 @@ static int garmin_init_session(struct usb_serial_port *port)
/* not needed, but the win32 driver does it too ... */
status = garmin_write_bulk(port,
- GARMIN_START_SESSION_REQ2,
- sizeof(GARMIN_START_SESSION_REQ2),
- 0);
+ GARMIN_START_SESSION_REQ2,
+ sizeof(GARMIN_START_SESSION_REQ2), 0);
if (status >= 0) {
status = 0;
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->ignorePkts++;
- spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+ spin_unlock_irqrestore(&garmin_data_p->lock,
+ flags);
}
}
}
@@ -970,11 +965,12 @@ static int garmin_init_session(struct usb_serial_port *port)
-static int garmin_open (struct usb_serial_port *port, struct file *filp)
+static int garmin_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
unsigned long flags;
int status = 0;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
dbg("%s - port %d", __func__, port->number);
@@ -983,8 +979,8 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp)
* through, otherwise it is scheduled, and with high data rates (like
* with OHCI) data can get lost.
*/
- if (port->tty)
- port->tty->low_latency = 1;
+ if (tty)
+ tty->low_latency = 1;
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->mode = initial_mode;
@@ -995,23 +991,22 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp)
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
/* shutdown any bulk reads that might be going on */
- usb_kill_urb (port->write_urb);
- usb_kill_urb (port->read_urb);
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->read_urb);
- if (garmin_data_p->state == STATE_RESET) {
+ if (garmin_data_p->state == STATE_RESET)
status = garmin_init_session(port);
- }
garmin_data_p->state = STATE_ACTIVE;
-
return status;
}
-static void garmin_close (struct usb_serial_port *port, struct file * filp)
+static void garmin_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
dbg("%s - port %d - mode=%d state=%d flags=0x%X", __func__,
port->number, garmin_data_p->mode,
@@ -1025,8 +1020,8 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp)
garmin_clear(garmin_data_p);
/* shutdown our urbs */
- usb_kill_urb (port->read_urb);
- usb_kill_urb (port->write_urb);
+ usb_kill_urb(port->read_urb);
+ usb_kill_urb(port->write_urb);
if (!port->serial->disconnected) {
if (noResponseFromAppLayer(garmin_data_p) ||
@@ -1042,21 +1037,22 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp)
mutex_unlock(&port->serial->disc_mutex);
}
-
-static void garmin_write_bulk_callback (struct urb *urb)
+static void garmin_write_bulk_callback(struct urb *urb)
{
unsigned long flags;
struct usb_serial_port *port = urb->context;
int status = urb->status;
if (port) {
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p =
+ usb_get_serial_port_data(port);
dbg("%s - port %d", __func__, port->number);
if (GARMIN_LAYERID_APPL == getLayerId(urb->transfer_buffer)
&& (garmin_data_p->mode == MODE_GARMIN_SERIAL)) {
- gsp_send_ack(garmin_data_p, ((__u8 *)urb->transfer_buffer)[4]);
+ gsp_send_ack(garmin_data_p,
+ ((__u8 *)urb->transfer_buffer)[4]);
}
if (status) {
@@ -1070,20 +1066,21 @@ static void garmin_write_bulk_callback (struct urb *urb)
usb_serial_port_softint(port);
}
- /* Ignore errors that resulted from garmin_write_bulk with dismiss_ack=1 */
+ /* Ignore errors that resulted from garmin_write_bulk with
+ dismiss_ack = 1 */
/* free up the transfer buffer, as usb_free_urb() does not do this */
- kfree (urb->transfer_buffer);
+ kfree(urb->transfer_buffer);
}
-static int garmin_write_bulk (struct usb_serial_port *port,
+static int garmin_write_bulk(struct usb_serial_port *port,
const unsigned char *buf, int count,
int dismiss_ack)
{
unsigned long flags;
struct usb_serial *serial = port->serial;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
struct urb *urb;
unsigned char *buffer;
int status;
@@ -1095,7 +1092,7 @@ static int garmin_write_bulk (struct usb_serial_port *port,
garmin_data_p->flags &= ~FLAGS_DROP_DATA;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
- buffer = kmalloc (count, GFP_ATOMIC);
+ buffer = kmalloc(count, GFP_ATOMIC);
if (!buffer) {
dev_err(&port->dev, "out of memory\n");
return -ENOMEM;
@@ -1104,17 +1101,17 @@ static int garmin_write_bulk (struct usb_serial_port *port,
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
dev_err(&port->dev, "no more free urbs\n");
- kfree (buffer);
+ kfree(buffer);
return -ENOMEM;
}
- memcpy (buffer, buf, count);
+ memcpy(buffer, buf, count);
usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
- usb_fill_bulk_urb (urb, serial->dev,
- usb_sndbulkpipe (serial->dev,
- port->bulk_out_endpointAddress),
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ port->bulk_out_endpointAddress),
buffer, count,
garmin_write_bulk_callback,
dismiss_ack ? NULL : port);
@@ -1132,33 +1129,29 @@ static int garmin_write_bulk (struct usb_serial_port *port,
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
dev_err(&port->dev,
- "%s - usb_submit_urb(write bulk) "
- "failed with status = %d\n",
+ "%s - usb_submit_urb(write bulk) failed with status = %d\n",
__func__, status);
count = status;
}
/* we are done with this urb, so let the host driver
* really free it when it is finished with it */
- usb_free_urb (urb);
+ usb_free_urb(urb);
return count;
}
-
-
-static int garmin_write (struct usb_serial_port *port,
- const unsigned char *buf, int count)
+static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
int pktid, pktsiz, len;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
__le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
usb_serial_debug_data(debug, &port->dev, __func__, count, buf);
/* check for our private packets */
if (count >= GARMIN_PKTHDR_LENGTH) {
-
len = PRIVPKTSIZ;
if (count < len)
len = count;
@@ -1169,15 +1162,16 @@ static int garmin_write (struct usb_serial_port *port,
pktid = getPacketId(garmin_data_p->privpkt);
if (count == (GARMIN_PKTHDR_LENGTH+pktsiz)
- && GARMIN_LAYERID_PRIVATE == getLayerId(garmin_data_p->privpkt)) {
+ && GARMIN_LAYERID_PRIVATE ==
+ getLayerId(garmin_data_p->privpkt)) {
dbg("%s - processing private request %d",
__func__, pktid);
- // drop all unfinished transfers
+ /* drop all unfinished transfers */
garmin_clear(garmin_data_p);
- switch(pktid) {
+ switch (pktid) {
case PRIV_PKTID_SET_DEBUG:
if (pktsiz != 4)
@@ -1226,44 +1220,31 @@ static int garmin_write (struct usb_serial_port *port,
}
-static int garmin_write_room (struct usb_serial_port *port)
+static int garmin_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
/*
* Report back the bytes currently available in the output buffer.
*/
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
return GPS_OUT_BUFSIZ-garmin_data_p->outsize;
}
-static int garmin_chars_in_buffer (struct usb_serial_port *port)
-{
- /*
- * Report back the number of bytes currently in our input buffer.
- * Will this lock up the driver - the buffer contains an incomplete
- * package which will not be written to the device until it
- * has been completed ?
- */
- //struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
- //return garmin_data_p->insize;
- return 0;
-}
-
-
-static void garmin_read_process(struct garmin_data * garmin_data_p,
+static void garmin_read_process(struct garmin_data *garmin_data_p,
unsigned char *data, unsigned data_length)
{
if (garmin_data_p->flags & FLAGS_DROP_DATA) {
/* abort-transfer cmd is actice */
dbg("%s - pkt dropped", __func__);
} else if (garmin_data_p->state != STATE_DISCONNECTED &&
- garmin_data_p->state != STATE_RESET ) {
+ garmin_data_p->state != STATE_RESET) {
/* remember any appl.layer packets, so we know
if a reset is required or not when closing
the device */
if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY,
- sizeof(GARMIN_APP_LAYER_REPLY))) {
+ sizeof(GARMIN_APP_LAYER_REPLY))) {
atomic_inc(&garmin_data_p->resp_count);
}
@@ -1273,9 +1254,8 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
if (garmin_data_p->flags & FLAGS_QUEUING) {
pkt_add(garmin_data_p, data, data_length);
} else if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
- if (getLayerId(data) == GARMIN_LAYERID_APPL) {
+ if (getLayerId(data) == GARMIN_LAYERID_APPL)
pkt_add(garmin_data_p, data, data_length);
- }
} else {
send_to_tty(garmin_data_p->port, data, data_length);
}
@@ -1283,12 +1263,12 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
}
-static void garmin_read_bulk_callback (struct urb *urb)
+static void garmin_read_bulk_callback(struct urb *urb)
{
unsigned long flags;
struct usb_serial_port *port = urb->context;
struct usb_serial *serial = port->serial;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
int retval;
@@ -1306,7 +1286,7 @@ static void garmin_read_bulk_callback (struct urb *urb)
return;
}
- usb_serial_debug_data(debug, &port->dev,
+ usb_serial_debug_data(debug, &port->dev,
__func__, urb->actual_length, data);
garmin_read_process(garmin_data_p, data, urb->actual_length);
@@ -1340,13 +1320,13 @@ static void garmin_read_bulk_callback (struct urb *urb)
}
-static void garmin_read_int_callback (struct urb *urb)
+static void garmin_read_int_callback(struct urb *urb)
{
unsigned long flags;
int retval;
struct usb_serial_port *port = urb->context;
struct usb_serial *serial = port->serial;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
@@ -1372,30 +1352,31 @@ static void garmin_read_int_callback (struct urb *urb)
if (urb->actual_length == sizeof(GARMIN_BULK_IN_AVAIL_REPLY) &&
0 == memcmp(data, GARMIN_BULK_IN_AVAIL_REPLY,
- sizeof(GARMIN_BULK_IN_AVAIL_REPLY))) {
+ sizeof(GARMIN_BULK_IN_AVAIL_REPLY))) {
dbg("%s - bulk data available.", __func__);
if (0 == (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
/* bulk data available */
- usb_fill_bulk_urb (port->read_urb, serial->dev,
- usb_rcvbulkpipe (serial->dev,
- port->bulk_in_endpointAddress),
+ usb_fill_bulk_urb(port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
garmin_read_bulk_callback, port);
retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (retval) {
dev_err(&port->dev,
- "%s - failed submitting read urb, error %d\n",
- __func__, retval);
+ "%s - failed submitting read urb, error %d\n",
+ __func__, retval);
} else {
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE;
/* do not send this packet to the user */
garmin_data_p->ignorePkts = 1;
- spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+ spin_unlock_irqrestore(&garmin_data_p->lock,
+ flags);
}
} else {
/* bulk-in transfer still active */
@@ -1406,15 +1387,15 @@ static void garmin_read_int_callback (struct urb *urb)
} else if (urb->actual_length == (4+sizeof(GARMIN_START_SESSION_REPLY))
&& 0 == memcmp(data, GARMIN_START_SESSION_REPLY,
- sizeof(GARMIN_START_SESSION_REPLY))) {
+ sizeof(GARMIN_START_SESSION_REPLY))) {
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->flags |= FLAGS_SESSION_REPLY1_SEEN;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
/* save the serial number */
- garmin_data_p->serial_num
- = __le32_to_cpup((__le32*)(data+GARMIN_PKTHDR_LENGTH));
+ garmin_data_p->serial_num = __le32_to_cpup(
+ (__le32 *)(data+GARMIN_PKTHDR_LENGTH));
dbg("%s - start-of-session reply seen - serial %u.",
__func__, garmin_data_p->serial_num);
@@ -1433,7 +1414,7 @@ static void garmin_read_int_callback (struct urb *urb)
}
port->interrupt_in_urb->dev = port->serial->dev;
- retval = usb_submit_urb (urb, GFP_ATOMIC);
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
dev_err(&urb->dev->dev,
"%s - Error %d submitting interrupt urb\n",
@@ -1446,7 +1427,7 @@ static void garmin_read_int_callback (struct urb *urb)
* and then sets a timer to call itself again until all queued data
* is sent.
*/
-static int garmin_flush_queue(struct garmin_data * garmin_data_p)
+static int garmin_flush_queue(struct garmin_data *garmin_data_p)
{
unsigned long flags;
struct garmin_packet *pkt;
@@ -1468,10 +1449,11 @@ static int garmin_flush_queue(struct garmin_data * garmin_data_p)
}
-static void garmin_throttle (struct usb_serial_port *port)
+static void garmin_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
unsigned long flags;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
dbg("%s - port %d", __func__, port->number);
/* set flag, data received will be put into a queue
@@ -1482,10 +1464,11 @@ static void garmin_throttle (struct usb_serial_port *port)
}
-static void garmin_unthrottle (struct usb_serial_port *port)
+static void garmin_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
unsigned long flags;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
int status;
dbg("%s - port %d", __func__, port->number);
@@ -1507,8 +1490,6 @@ static void garmin_unthrottle (struct usb_serial_port *port)
}
}
-
-
/*
* The timer is currently only used to send queued packets to
* the tty in cases where the protocol provides no own handshaking
@@ -1526,11 +1507,11 @@ static void timeout_handler(unsigned long data)
-static int garmin_attach (struct usb_serial *serial)
+static int garmin_attach(struct usb_serial *serial)
{
int status = 0;
struct usb_serial_port *port = serial->port[0];
- struct garmin_data * garmin_data_p = NULL;
+ struct garmin_data *garmin_data_p = NULL;
dbg("%s", __func__);
@@ -1542,7 +1523,7 @@ static int garmin_attach (struct usb_serial *serial)
init_timer(&garmin_data_p->timer);
spin_lock_init(&garmin_data_p->lock);
INIT_LIST_HEAD(&garmin_data_p->pktlist);
- //garmin_data_p->timer.expires = jiffies + session_timeout;
+ /* garmin_data_p->timer.expires = jiffies + session_timeout; */
garmin_data_p->timer.data = (unsigned long)garmin_data_p;
garmin_data_p->timer.function = timeout_handler;
garmin_data_p->port = port;
@@ -1556,16 +1537,16 @@ static int garmin_attach (struct usb_serial *serial)
}
-static void garmin_shutdown (struct usb_serial *serial)
+static void garmin_shutdown(struct usb_serial *serial)
{
struct usb_serial_port *port = serial->port[0];
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
dbg("%s", __func__);
- usb_kill_urb (port->interrupt_in_urb);
+ usb_kill_urb(port->interrupt_in_urb);
del_timer_sync(&garmin_data_p->timer);
- kfree (garmin_data_p);
+ kfree(garmin_data_p);
usb_set_serial_port_data(port, NULL);
}
@@ -1588,7 +1569,6 @@ static struct usb_serial_driver garmin_device = {
.shutdown = garmin_shutdown,
.write = garmin_write,
.write_room = garmin_write_room,
- .chars_in_buffer = garmin_chars_in_buffer,
.write_bulk_callback = garmin_write_bulk_callback,
.read_bulk_callback = garmin_read_bulk_callback,
.read_int_callback = garmin_read_int_callback,
@@ -1596,7 +1576,7 @@ static struct usb_serial_driver garmin_device = {
-static int __init garmin_init (void)
+static int __init garmin_init(void)
{
int retval;
@@ -1616,10 +1596,10 @@ failed_garmin_register:
}
-static void __exit garmin_exit (void)
+static void __exit garmin_exit(void)
{
- usb_deregister (&garmin_driver);
- usb_serial_deregister (&garmin_device);
+ usb_deregister(&garmin_driver);
+ usb_serial_deregister(&garmin_device);
}
@@ -1628,8 +1608,8 @@ static void __exit garmin_exit (void)
module_init(garmin_init);
module_exit(garmin_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IWUSR | S_IRUGO);
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 537f12a027c..fe84c88ec20 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -18,7 +18,7 @@
#include <linux/moduleparam.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
static int debug;
@@ -81,7 +81,7 @@ static int generic_probe(struct usb_interface *interface,
}
#endif
-int usb_serial_generic_register (int _debug)
+int usb_serial_generic_register(int _debug)
{
int retval = 0;
@@ -89,10 +89,11 @@ int usb_serial_generic_register (int _debug)
#ifdef CONFIG_USB_SERIAL_GENERIC
generic_device_ids[0].idVendor = vendor;
generic_device_ids[0].idProduct = product;
- generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
+ generic_device_ids[0].match_flags =
+ USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
/* register our generic driver with ourselves */
- retval = usb_serial_register (&usb_serial_generic_device);
+ retval = usb_serial_register(&usb_serial_generic_device);
if (retval)
goto exit;
retval = usb_register(&generic_driver);
@@ -103,16 +104,17 @@ exit:
return retval;
}
-void usb_serial_generic_deregister (void)
+void usb_serial_generic_deregister(void)
{
#ifdef CONFIG_USB_SERIAL_GENERIC
/* remove our generic driver */
usb_deregister(&generic_driver);
- usb_serial_deregister (&usb_serial_generic_device);
+ usb_serial_deregister(&usb_serial_generic_device);
#endif
}
-int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
+int usb_serial_generic_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
int result = 0;
@@ -120,11 +122,11 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __func__, port->number);
- /* force low_latency on so that our tty_push actually forces the data through,
- otherwise it is scheduled, and with high data rates (like with OHCI) data
- can get lost. */
- if (port->tty)
- port->tty->low_latency = 1;
+ /* force low_latency on so that our tty_push actually forces the data
+ through, otherwise it is scheduled, and with high data rates (like
+ with OHCI) data can get lost. */
+ if (tty)
+ tty->low_latency = 1;
/* clear the throttle flags */
spin_lock_irqsave(&port->lock, flags);
@@ -135,8 +137,9 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
/* if we have a bulk endpoint, start reading from it */
if (serial->num_bulk_in) {
/* Start reading from the device */
- usb_fill_bulk_urb (port->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+ usb_fill_bulk_urb(port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
((serial->type->read_bulk_callback) ?
@@ -145,14 +148,16 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
}
return result;
}
EXPORT_SYMBOL_GPL(usb_serial_generic_open);
-static void generic_cleanup (struct usb_serial_port *port)
+static void generic_cleanup(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
@@ -182,7 +187,7 @@ int usb_serial_generic_resume(struct usb_serial *serial)
#endif
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
- if (port->open_count && port->read_urb) {
+ if (port->port.count && port->read_urb) {
r = usb_submit_urb(port->read_urb, GFP_NOIO);
if (r < 0)
c++;
@@ -192,13 +197,15 @@ int usb_serial_generic_resume(struct usb_serial *serial)
return c ? -EIO : 0;
}
-void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp)
+void usb_serial_generic_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
dbg("%s - port %d", __func__, port->number);
- generic_cleanup (port);
+ generic_cleanup(port);
}
-int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *buf, int count)
+int usb_serial_generic_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
int result;
@@ -208,7 +215,7 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
if (count == 0) {
dbg("%s - write request of 0 bytes", __func__);
- return (0);
+ return 0;
}
/* only do something if we have a bulk out endpoint */
@@ -223,27 +230,32 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
port->write_urb_busy = 1;
spin_unlock_irqrestore(&port->lock, flags);
- count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+ count = (count > port->bulk_out_size) ?
+ port->bulk_out_size : count;
- memcpy (port->write_urb->transfer_buffer, buf, count);
+ memcpy(port->write_urb->transfer_buffer, buf, count);
data = port->write_urb->transfer_buffer;
usb_serial_debug_data(debug, &port->dev, __func__, count, data);
/* set up our urb */
- usb_fill_bulk_urb (port->write_urb, serial->dev,
- usb_sndbulkpipe (serial->dev,
- port->bulk_out_endpointAddress),
+ usb_fill_bulk_urb(port->write_urb, serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, count,
- ((serial->type->write_bulk_callback) ?
+ ((serial->type->write_bulk_callback) ?
serial->type->write_bulk_callback :
- usb_serial_generic_write_bulk_callback), port);
+ usb_serial_generic_write_bulk_callback),
+ port);
/* send the data out the bulk port */
port->write_urb_busy = 1;
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
- /* don't have to grab the lock here, as we will retry if != 0 */
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, result);
+ /* don't have to grab the lock here, as we will
+ retry if != 0 */
port->write_urb_busy = 0;
} else
result = count;
@@ -255,8 +267,9 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
return 0;
}
-int usb_serial_generic_write_room (struct usb_serial_port *port)
+int usb_serial_generic_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
int room = 0;
@@ -272,8 +285,9 @@ int usb_serial_generic_write_room (struct usb_serial_port *port)
return room;
}
-int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
+int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
int chars = 0;
@@ -286,7 +300,7 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
}
dbg("%s - returns %d", __func__, chars);
- return (chars);
+ return chars;
}
@@ -297,24 +311,26 @@ static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)
int result;
/* Continue reading from device */
- usb_fill_bulk_urb (urb, serial->dev,
- usb_rcvbulkpipe (serial->dev,
- port->bulk_in_endpointAddress),
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
urb->transfer_buffer,
urb->transfer_buffer_length,
- ((serial->type->read_bulk_callback) ?
- serial->type->read_bulk_callback :
+ ((serial->type->read_bulk_callback) ?
+ serial->type->read_bulk_callback :
usb_serial_generic_read_bulk_callback), port);
result = usb_submit_urb(urb, mem_flags);
if (result)
- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
}
/* Push data to tty layer and resubmit the bulk read URB */
-static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
+static void flush_and_resubmit_read_urb(struct usb_serial_port *port)
{
struct urb *urb = port->read_urb;
- struct tty_struct *tty = port->tty;
+ struct tty_struct *tty = port->port.tty;
int room;
/* Push data to tty */
@@ -329,7 +345,7 @@ static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
resubmit_read_urb(port, GFP_ATOMIC);
}
-void usb_serial_generic_read_bulk_callback (struct urb *urb)
+void usb_serial_generic_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
@@ -344,20 +360,21 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb)
return;
}
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
/* Throttle the device if requested by tty */
spin_lock_irqsave(&port->lock, flags);
- if (!(port->throttled = port->throttle_req)) {
+ port->throttled = port->throttle_req;
+ if (!port->throttled) {
spin_unlock_irqrestore(&port->lock, flags);
flush_and_resubmit_read_urb(port);
- } else {
+ } else
spin_unlock_irqrestore(&port->lock, flags);
- }
}
EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
-void usb_serial_generic_write_bulk_callback (struct urb *urb)
+void usb_serial_generic_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
int status = urb->status;
@@ -374,8 +391,9 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb)
}
EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
-void usb_serial_generic_throttle (struct usb_serial_port *port)
+void usb_serial_generic_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned long flags;
dbg("%s - port %d", __func__, port->number);
@@ -387,8 +405,9 @@ void usb_serial_generic_throttle (struct usb_serial_port *port)
spin_unlock_irqrestore(&port->lock, flags);
}
-void usb_serial_generic_unthrottle (struct usb_serial_port *port)
+void usb_serial_generic_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int was_throttled;
unsigned long flags;
@@ -406,15 +425,14 @@ void usb_serial_generic_unthrottle (struct usb_serial_port *port)
}
}
-void usb_serial_generic_shutdown (struct usb_serial *serial)
+void usb_serial_generic_shutdown(struct usb_serial *serial)
{
int i;
dbg("%s", __func__);
/* stop reads and writes on all ports */
- for (i=0; i < serial->num_ports; ++i) {
+ for (i = 0; i < serial->num_ports; ++i)
generic_cleanup(serial->port[i]);
- }
}
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index 75b88b356eb..ab905869e95 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -9,7 +9,8 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*/
#include <linux/kernel.h>
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 2fd449bcfa3..bfa508ddb0f 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -44,7 +44,7 @@
#include <linux/wait.h>
#include <linux/firmware.h>
#include <linux/ihex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include "io_edgeport.h"
@@ -66,16 +66,16 @@
/* receive port state */
enum RXSTATE {
- EXPECT_HDR1 = 0, /* Expect header byte 1 */
- EXPECT_HDR2 = 1, /* Expect header byte 2 */
- EXPECT_DATA = 2, /* Expect 'RxBytesRemaining' data */
- EXPECT_HDR3 = 3, /* Expect header byte 3 (for status hdrs only) */
+ EXPECT_HDR1 = 0, /* Expect header byte 1 */
+ EXPECT_HDR2 = 1, /* Expect header byte 2 */
+ EXPECT_DATA = 2, /* Expect 'RxBytesRemaining' data */
+ EXPECT_HDR3 = 3, /* Expect header byte 3 (for status hdrs only) */
};
-/* Transmit Fifo
- * This Transmit queue is an extension of the edgeport Rx buffer.
- * The maximum amount of data buffered in both the edgeport
+/* Transmit Fifo
+ * This Transmit queue is an extension of the edgeport Rx buffer.
+ * The maximum amount of data buffered in both the edgeport
* Rx buffer (maxTxCredits) and this buffer will never exceed maxTxCredits.
*/
struct TxFifo {
@@ -132,12 +132,12 @@ struct edgeport_serial {
int is_epic; /* flag if EPiC device or not */
__u8 interrupt_in_endpoint; /* the interrupt endpoint handle */
- unsigned char * interrupt_in_buffer; /* the buffer we use for the interrupt endpoint */
- struct urb * interrupt_read_urb; /* our interrupt urb */
+ unsigned char *interrupt_in_buffer; /* the buffer we use for the interrupt endpoint */
+ struct urb *interrupt_read_urb; /* our interrupt urb */
__u8 bulk_in_endpoint; /* the bulk in endpoint handle */
- unsigned char * bulk_in_buffer; /* the buffer we use for the bulk in endpoint */
- struct urb * read_urb; /* our bulk read urb */
+ unsigned char *bulk_in_buffer; /* the buffer we use for the bulk in endpoint */
+ struct urb *read_urb; /* our bulk read urb */
bool read_in_progress;
spinlock_t es_lock;
@@ -162,16 +162,17 @@ struct divisor_table_entry {
__u16 Divisor;
};
-//
-// Define table of divisors for Rev A EdgePort/4 hardware
-// These assume a 3.6864MHz crystal, the standard /16, and
-// MCR.7 = 0.
-//
+/*
+ * Define table of divisors for Rev A EdgePort/4 hardware
+ * These assume a 3.6864MHz crystal, the standard /16, and
+ * MCR.7 = 0.
+ */
+
static const struct divisor_table_entry divisor_table[] = {
- { 50, 4608},
- { 75, 3072},
- { 110, 2095}, /* 2094.545455 => 230450 => .0217 % over */
- { 134, 1713}, /* 1713.011152 => 230398.5 => .00065% under */
+ { 50, 4608},
+ { 75, 3072},
+ { 110, 2095}, /* 2094.545455 => 230450 => .0217 % over */
+ { 134, 1713}, /* 1713.011152 => 230398.5 => .00065% under */
{ 150, 1536},
{ 300, 768},
{ 600, 384},
@@ -194,64 +195,86 @@ static int debug;
static int low_latency = 1; /* tty low latency flag, on by default */
-static atomic_t CmdUrbs; /* Number of outstanding Command Write Urbs */
+static atomic_t CmdUrbs; /* Number of outstanding Command Write Urbs */
/* local function prototypes */
/* function prototypes for all URB callbacks */
-static void edge_interrupt_callback (struct urb *urb);
-static void edge_bulk_in_callback (struct urb *urb);
-static void edge_bulk_out_data_callback (struct urb *urb);
-static void edge_bulk_out_cmd_callback (struct urb *urb);
+static void edge_interrupt_callback(struct urb *urb);
+static void edge_bulk_in_callback(struct urb *urb);
+static void edge_bulk_out_data_callback(struct urb *urb);
+static void edge_bulk_out_cmd_callback(struct urb *urb);
/* function prototypes for the usbserial callbacks */
-static int edge_open (struct usb_serial_port *port, struct file *filp);
-static void edge_close (struct usb_serial_port *port, struct file *filp);
-static int edge_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-static int edge_write_room (struct usb_serial_port *port);
-static int edge_chars_in_buffer (struct usb_serial_port *port);
-static void edge_throttle (struct usb_serial_port *port);
-static void edge_unthrottle (struct usb_serial_port *port);
-static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
-static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);
-static void edge_break (struct usb_serial_port *port, int break_state);
-static int edge_tiocmget (struct usb_serial_port *port, struct file *file);
-static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
-static int edge_startup (struct usb_serial *serial);
-static void edge_shutdown (struct usb_serial *serial);
-
+static int edge_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static void edge_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+static int edge_write_room(struct tty_struct *tty);
+static int edge_chars_in_buffer(struct tty_struct *tty);
+static void edge_throttle(struct tty_struct *tty);
+static void edge_unthrottle(struct tty_struct *tty);
+static void edge_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port,
+ struct ktermios *old_termios);
+static int edge_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static void edge_break(struct tty_struct *tty, int break_state);
+static int edge_tiocmget(struct tty_struct *tty, struct file *file);
+static int edge_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
+static int edge_startup(struct usb_serial *serial);
+static void edge_shutdown(struct usb_serial *serial);
#include "io_tables.h" /* all of the devices that this driver supports */
/* function prototypes for all of our local functions */
-static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char *buffer, __u16 bufferLength);
-static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3);
-static void edge_tty_recv (struct device *dev, struct tty_struct *tty, unsigned char *data, int length);
-static void handle_new_msr (struct edgeport_port *edge_port, __u8 newMsr);
-static void handle_new_lsr (struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data);
-static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param);
-static int calc_baud_rate_divisor (int baud_rate, int *divisor);
-static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate);
-static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios);
-static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue);
-static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int writeLength);
-static void send_more_port_data (struct edgeport_serial *edge_serial, struct edgeport_port *edge_port);
-
-static int sram_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data);
-static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data);
-static int rom_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data);
-static void get_manufacturing_desc (struct edgeport_serial *edge_serial);
-static void get_boot_desc (struct edgeport_serial *edge_serial);
-static void load_application_firmware (struct edgeport_serial *edge_serial);
-
-static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size);
-
-
-// ************************************************************************
-// ************************************************************************
-// ************************************************************************
-// ************************************************************************
+
+static void process_rcvd_data(struct edgeport_serial *edge_serial,
+ unsigned char *buffer, __u16 bufferLength);
+static void process_rcvd_status(struct edgeport_serial *edge_serial,
+ __u8 byte2, __u8 byte3);
+static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
+ unsigned char *data, int length);
+static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr);
+static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,
+ __u8 lsr, __u8 data);
+static int send_iosp_ext_cmd(struct edgeport_port *edge_port, __u8 command,
+ __u8 param);
+static int calc_baud_rate_divisor(int baud_rate, int *divisor);
+static int send_cmd_write_baud_rate(struct edgeport_port *edge_port,
+ int baudRate);
+static void change_port_settings(struct tty_struct *tty,
+ struct edgeport_port *edge_port,
+ struct ktermios *old_termios);
+static int send_cmd_write_uart_register(struct edgeport_port *edge_port,
+ __u8 regNum, __u8 regValue);
+static int write_cmd_usb(struct edgeport_port *edge_port,
+ unsigned char *buffer, int writeLength);
+static void send_more_port_data(struct edgeport_serial *edge_serial,
+ struct edgeport_port *edge_port);
+
+static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
+ __u16 length, const __u8 *data);
+static int rom_read(struct usb_serial *serial, __u16 extAddr, __u16 addr,
+ __u16 length, __u8 *data);
+static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
+ __u16 length, const __u8 *data);
+static void get_manufacturing_desc(struct edgeport_serial *edge_serial);
+static void get_boot_desc(struct edgeport_serial *edge_serial);
+static void load_application_firmware(struct edgeport_serial *edge_serial);
+
+static void unicode_to_ascii(char *string, int buflen,
+ __le16 *unicode, int unicode_size);
+
+
+/* ************************************************************************ */
+/* ************************************************************************ */
+/* ************************************************************************ */
+/* ************************************************************************ */
/************************************************************************
* *
@@ -261,7 +284,7 @@ static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unic
* embedded in this driver *
* *
************************************************************************/
-static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
+static void update_edgeport_E2PROM(struct edgeport_serial *edge_serial)
{
__u32 BootCurVer;
__u32 BootNewVer;
@@ -275,16 +298,14 @@ static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
int response;
switch (edge_serial->product_info.iDownloadFile) {
- case EDGE_DOWNLOAD_FILE_I930:
- fw_name = "edgeport/boot.fw";
- break;
-
- case EDGE_DOWNLOAD_FILE_80251:
- fw_name = "edgeport/boot2.fw";
- break;
-
- default:
- return;
+ case EDGE_DOWNLOAD_FILE_I930:
+ fw_name = "edgeport/boot.fw";
+ break;
+ case EDGE_DOWNLOAD_FILE_80251:
+ fw_name = "edgeport/boot2.fw";
+ break;
+ default:
+ return;
}
response = request_ihex_firmware(&fw, fw_name,
@@ -300,7 +321,7 @@ static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
BootMinorVersion = rec->data[1];
BootBuildNumber = (rec->data[2] << 8) | rec->data[3];
- // Check Boot Image Version
+ /* Check Boot Image Version */
BootCurVer = (edge_serial->boot_descriptor.MajorVersion << 24) +
(edge_serial->boot_descriptor.MinorVersion << 16) +
le16_to_cpu(edge_serial->boot_descriptor.BuildNumber);
@@ -352,29 +373,29 @@ static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
* Get string descriptor from device *
* *
************************************************************************/
-static int get_string (struct usb_device *dev, int Id, char *string, int buflen)
+static int get_string(struct usb_device *dev, int Id, char *string, int buflen)
{
struct usb_string_descriptor StringDesc;
struct usb_string_descriptor *pStringDesc;
- dbg("%s - USB String ID = %d", __func__, Id );
+ dbg("%s - USB String ID = %d", __func__, Id);
- if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) {
+ if (!usb_get_descriptor(dev, USB_DT_STRING, Id,
+ &StringDesc, sizeof(StringDesc)))
return 0;
- }
- pStringDesc = kmalloc (StringDesc.bLength, GFP_KERNEL);
-
- if (!pStringDesc) {
+ pStringDesc = kmalloc(StringDesc.bLength, GFP_KERNEL);
+ if (!pStringDesc)
return 0;
- }
- if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc, StringDesc.bLength )) {
+ if (!usb_get_descriptor(dev, USB_DT_STRING, Id,
+ pStringDesc, StringDesc.bLength)) {
kfree(pStringDesc);
return 0;
}
- unicode_to_ascii(string, buflen, pStringDesc->wData, pStringDesc->bLength/2);
+ unicode_to_ascii(string, buflen,
+ pStringDesc->wData, pStringDesc->bLength/2);
kfree(pStringDesc);
dbg("%s - USB String %s", __func__, string);
@@ -388,24 +409,24 @@ static int get_string (struct usb_device *dev, int Id, char *string, int buflen)
* Get string descriptor from device
*
************************************************************************/
-static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_descriptor **pRetDesc)
+static int get_string_desc(struct usb_device *dev, int Id,
+ struct usb_string_descriptor **pRetDesc)
{
struct usb_string_descriptor StringDesc;
struct usb_string_descriptor *pStringDesc;
- dbg("%s - USB String ID = %d", __func__, Id );
+ dbg("%s - USB String ID = %d", __func__, Id);
- if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) {
+ if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc,
+ sizeof(StringDesc)))
return 0;
- }
- pStringDesc = kmalloc (StringDesc.bLength, GFP_KERNEL);
-
- if (!pStringDesc) {
+ pStringDesc = kmalloc(StringDesc.bLength, GFP_KERNEL);
+ if (!pStringDesc)
return -1;
- }
- if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc, StringDesc.bLength )) {
+ if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc,
+ StringDesc.bLength)) {
kfree(pStringDesc);
return -1;
}
@@ -417,25 +438,30 @@ static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_de
static void dump_product_info(struct edgeport_product_info *product_info)
{
- // Dump Product Info structure
+ /* Dump Product Info structure */
dbg("**Product Information:");
- dbg(" ProductId %x", product_info->ProductId );
- dbg(" NumPorts %d", product_info->NumPorts );
- dbg(" ProdInfoVer %d", product_info->ProdInfoVer );
+ dbg(" ProductId %x", product_info->ProductId);
+ dbg(" NumPorts %d", product_info->NumPorts);
+ dbg(" ProdInfoVer %d", product_info->ProdInfoVer);
dbg(" IsServer %d", product_info->IsServer);
- dbg(" IsRS232 %d", product_info->IsRS232 );
- dbg(" IsRS422 %d", product_info->IsRS422 );
- dbg(" IsRS485 %d", product_info->IsRS485 );
- dbg(" RomSize %d", product_info->RomSize );
- dbg(" RamSize %d", product_info->RamSize );
- dbg(" CpuRev %x", product_info->CpuRev );
+ dbg(" IsRS232 %d", product_info->IsRS232);
+ dbg(" IsRS422 %d", product_info->IsRS422);
+ dbg(" IsRS485 %d", product_info->IsRS485);
+ dbg(" RomSize %d", product_info->RomSize);
+ dbg(" RamSize %d", product_info->RamSize);
+ dbg(" CpuRev %x", product_info->CpuRev);
dbg(" BoardRev %x", product_info->BoardRev);
dbg(" BootMajorVersion %d.%d.%d", product_info->BootMajorVersion,
product_info->BootMinorVersion,
le16_to_cpu(product_info->BootBuildNumber));
- dbg(" ManufactureDescDate %d/%d/%d", product_info->ManufactureDescDate[0],
- product_info->ManufactureDescDate[1],
- product_info->ManufactureDescDate[2]+1900);
+ dbg(" FirmwareMajorVersion %d.%d.%d",
+ product_info->FirmwareMajorVersion,
+ product_info->FirmwareMinorVersion,
+ le16_to_cpu(product_info->FirmwareBuildNumber));
+ dbg(" ManufactureDescDate %d/%d/%d",
+ product_info->ManufactureDescDate[0],
+ product_info->ManufactureDescDate[1],
+ product_info->ManufactureDescDate[2]+1900);
dbg(" iDownloadFile 0x%x", product_info->iDownloadFile);
dbg(" EpicVer %d", product_info->EpicVer);
}
@@ -444,55 +470,60 @@ static void get_product_info(struct edgeport_serial *edge_serial)
{
struct edgeport_product_info *product_info = &edge_serial->product_info;
- memset (product_info, 0, sizeof(struct edgeport_product_info));
-
- product_info->ProductId = (__u16)(le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ~ION_DEVICE_ID_80251_NETCHIP);
- product_info->NumPorts = edge_serial->manuf_descriptor.NumPorts;
- product_info->ProdInfoVer = 0;
-
- product_info->RomSize = edge_serial->manuf_descriptor.RomSize;
- product_info->RamSize = edge_serial->manuf_descriptor.RamSize;
- product_info->CpuRev = edge_serial->manuf_descriptor.CpuRev;
- product_info->BoardRev = edge_serial->manuf_descriptor.BoardRev;
-
- product_info->BootMajorVersion = edge_serial->boot_descriptor.MajorVersion;
- product_info->BootMinorVersion = edge_serial->boot_descriptor.MinorVersion;
- product_info->BootBuildNumber = edge_serial->boot_descriptor.BuildNumber;
-
- memcpy(product_info->ManufactureDescDate, edge_serial->manuf_descriptor.DescDate, sizeof(edge_serial->manuf_descriptor.DescDate));
-
- // check if this is 2nd generation hardware
- if (le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ION_DEVICE_ID_80251_NETCHIP) {
- product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_80251;
- } else {
- product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_I930;
- }
-
- // Determine Product type and set appropriate flags
+ memset(product_info, 0, sizeof(struct edgeport_product_info));
+
+ product_info->ProductId = (__u16)(le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ~ION_DEVICE_ID_80251_NETCHIP);
+ product_info->NumPorts = edge_serial->manuf_descriptor.NumPorts;
+ product_info->ProdInfoVer = 0;
+
+ product_info->RomSize = edge_serial->manuf_descriptor.RomSize;
+ product_info->RamSize = edge_serial->manuf_descriptor.RamSize;
+ product_info->CpuRev = edge_serial->manuf_descriptor.CpuRev;
+ product_info->BoardRev = edge_serial->manuf_descriptor.BoardRev;
+
+ product_info->BootMajorVersion =
+ edge_serial->boot_descriptor.MajorVersion;
+ product_info->BootMinorVersion =
+ edge_serial->boot_descriptor.MinorVersion;
+ product_info->BootBuildNumber =
+ edge_serial->boot_descriptor.BuildNumber;
+
+ memcpy(product_info->ManufactureDescDate,
+ edge_serial->manuf_descriptor.DescDate,
+ sizeof(edge_serial->manuf_descriptor.DescDate));
+
+ /* check if this is 2nd generation hardware */
+ if (le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct)
+ & ION_DEVICE_ID_80251_NETCHIP)
+ product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_80251;
+ else
+ product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_I930;
+
+ /* Determine Product type and set appropriate flags */
switch (DEVICE_ID_FROM_USB_PRODUCT_ID(product_info->ProductId)) {
- case ION_DEVICE_ID_EDGEPORT_COMPATIBLE:
- case ION_DEVICE_ID_EDGEPORT_4T:
- case ION_DEVICE_ID_EDGEPORT_4:
- case ION_DEVICE_ID_EDGEPORT_2:
- case ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU:
- case ION_DEVICE_ID_EDGEPORT_8:
- case ION_DEVICE_ID_EDGEPORT_421:
- case ION_DEVICE_ID_EDGEPORT_21:
- case ION_DEVICE_ID_EDGEPORT_2_DIN:
- case ION_DEVICE_ID_EDGEPORT_4_DIN:
- case ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU:
- product_info->IsRS232 = 1;
- break;
+ case ION_DEVICE_ID_EDGEPORT_COMPATIBLE:
+ case ION_DEVICE_ID_EDGEPORT_4T:
+ case ION_DEVICE_ID_EDGEPORT_4:
+ case ION_DEVICE_ID_EDGEPORT_2:
+ case ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU:
+ case ION_DEVICE_ID_EDGEPORT_8:
+ case ION_DEVICE_ID_EDGEPORT_421:
+ case ION_DEVICE_ID_EDGEPORT_21:
+ case ION_DEVICE_ID_EDGEPORT_2_DIN:
+ case ION_DEVICE_ID_EDGEPORT_4_DIN:
+ case ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU:
+ product_info->IsRS232 = 1;
+ break;
- case ION_DEVICE_ID_EDGEPORT_2I: // Edgeport/2 RS422/RS485
- product_info->IsRS422 = 1;
- product_info->IsRS485 = 1;
- break;
+ case ION_DEVICE_ID_EDGEPORT_2I: /* Edgeport/2 RS422/RS485 */
+ product_info->IsRS422 = 1;
+ product_info->IsRS485 = 1;
+ break;
- case ION_DEVICE_ID_EDGEPORT_8I: // Edgeport/4 RS422
- case ION_DEVICE_ID_EDGEPORT_4I: // Edgeport/4 RS422
- product_info->IsRS422 = 1;
- break;
+ case ION_DEVICE_ID_EDGEPORT_8I: /* Edgeport/4 RS422 */
+ case ION_DEVICE_ID_EDGEPORT_4I: /* Edgeport/4 RS422 */
+ product_info->IsRS422 = 1;
+ break;
}
dump_product_info(product_info);
@@ -520,32 +551,32 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
ep->is_epic = 1;
memset(product_info, 0, sizeof(struct edgeport_product_info));
- product_info->NumPorts = epic->NumPorts;
- product_info->ProdInfoVer = 0;
- product_info->FirmwareMajorVersion = epic->MajorVersion;
- product_info->FirmwareMinorVersion = epic->MinorVersion;
- product_info->FirmwareBuildNumber = epic->BuildNumber;
- product_info->iDownloadFile = epic->iDownloadFile;
- product_info->EpicVer = epic->EpicVer;
- product_info->Epic = epic->Supports;
- product_info->ProductId = ION_DEVICE_ID_EDGEPORT_COMPATIBLE;
+ product_info->NumPorts = epic->NumPorts;
+ product_info->ProdInfoVer = 0;
+ product_info->FirmwareMajorVersion = epic->MajorVersion;
+ product_info->FirmwareMinorVersion = epic->MinorVersion;
+ product_info->FirmwareBuildNumber = epic->BuildNumber;
+ product_info->iDownloadFile = epic->iDownloadFile;
+ product_info->EpicVer = epic->EpicVer;
+ product_info->Epic = epic->Supports;
+ product_info->ProductId = ION_DEVICE_ID_EDGEPORT_COMPATIBLE;
dump_product_info(product_info);
bits = &ep->epic_descriptor.Supports;
dbg("**EPIC descriptor:");
dbg(" VendEnableSuspend: %s", bits->VendEnableSuspend ? "TRUE": "FALSE");
- dbg(" IOSPOpen : %s", bits->IOSPOpen ? "TRUE": "FALSE" );
- dbg(" IOSPClose : %s", bits->IOSPClose ? "TRUE": "FALSE" );
- dbg(" IOSPChase : %s", bits->IOSPChase ? "TRUE": "FALSE" );
- dbg(" IOSPSetRxFlow : %s", bits->IOSPSetRxFlow ? "TRUE": "FALSE" );
- dbg(" IOSPSetTxFlow : %s", bits->IOSPSetTxFlow ? "TRUE": "FALSE" );
- dbg(" IOSPSetXChar : %s", bits->IOSPSetXChar ? "TRUE": "FALSE" );
- dbg(" IOSPRxCheck : %s", bits->IOSPRxCheck ? "TRUE": "FALSE" );
- dbg(" IOSPSetClrBreak : %s", bits->IOSPSetClrBreak ? "TRUE": "FALSE" );
- dbg(" IOSPWriteMCR : %s", bits->IOSPWriteMCR ? "TRUE": "FALSE" );
- dbg(" IOSPWriteLCR : %s", bits->IOSPWriteLCR ? "TRUE": "FALSE" );
- dbg(" IOSPSetBaudRate : %s", bits->IOSPSetBaudRate ? "TRUE": "FALSE" );
- dbg(" TrueEdgeport : %s", bits->TrueEdgeport ? "TRUE": "FALSE" );
+ dbg(" IOSPOpen : %s", bits->IOSPOpen ? "TRUE": "FALSE");
+ dbg(" IOSPClose : %s", bits->IOSPClose ? "TRUE": "FALSE");
+ dbg(" IOSPChase : %s", bits->IOSPChase ? "TRUE": "FALSE");
+ dbg(" IOSPSetRxFlow : %s", bits->IOSPSetRxFlow ? "TRUE": "FALSE");
+ dbg(" IOSPSetTxFlow : %s", bits->IOSPSetTxFlow ? "TRUE": "FALSE");
+ dbg(" IOSPSetXChar : %s", bits->IOSPSetXChar ? "TRUE": "FALSE");
+ dbg(" IOSPRxCheck : %s", bits->IOSPRxCheck ? "TRUE": "FALSE");
+ dbg(" IOSPSetClrBreak : %s", bits->IOSPSetClrBreak ? "TRUE": "FALSE");
+ dbg(" IOSPWriteMCR : %s", bits->IOSPWriteMCR ? "TRUE": "FALSE");
+ dbg(" IOSPWriteLCR : %s", bits->IOSPWriteLCR ? "TRUE": "FALSE");
+ dbg(" IOSPSetBaudRate : %s", bits->IOSPSetBaudRate ? "TRUE": "FALSE");
+ dbg(" TrueEdgeport : %s", bits->TrueEdgeport ? "TRUE": "FALSE");
}
return result;
@@ -561,10 +592,10 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
/*****************************************************************************
* edge_interrupt_callback
- * this is the callback function for when we have received data on the
+ * this is the callback function for when we have received data on the
* interrupt endpoint.
*****************************************************************************/
-static void edge_interrupt_callback (struct urb *urb)
+static void edge_interrupt_callback(struct urb *urb)
{
struct edgeport_serial *edge_serial = urb->context;
struct edgeport_port *edge_port;
@@ -589,17 +620,17 @@ static void edge_interrupt_callback (struct urb *urb)
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
- __func__, status);
+ dbg("%s - nonzero urb status received: %d", __func__, status);
goto exit;
}
- // process this interrupt-read even if there are no ports open
+ /* process this interrupt-read even if there are no ports open */
if (length) {
- usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, length, data);
+ usb_serial_debug_data(debug, &edge_serial->serial->dev->dev,
+ __func__, length, data);
if (length > 1) {
bytes_avail = data[0] | (data[1] << 8);
@@ -613,7 +644,8 @@ static void edge_interrupt_callback (struct urb *urb)
dbg("%s - posting a read", __func__);
edge_serial->read_in_progress = true;
- /* we have pending bytes on the bulk in pipe, send a request */
+ /* we have pending bytes on the
+ bulk in pipe, send a request */
edge_serial->read_urb->dev = edge_serial->serial->dev;
result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
if (result) {
@@ -627,7 +659,8 @@ static void edge_interrupt_callback (struct urb *urb)
/* grab the txcredits for the ports if available */
position = 2;
portNumber = 0;
- while ((position < length) && (portNumber < edge_serial->serial->num_ports)) {
+ while ((position < length) &&
+ (portNumber < edge_serial->serial->num_ports)) {
txCredits = data[position] | (data[position+1] << 8);
if (txCredits) {
port = edge_serial->serial->port[portNumber];
@@ -636,14 +669,19 @@ static void edge_interrupt_callback (struct urb *urb)
spin_lock(&edge_port->ep_lock);
edge_port->txCredits += txCredits;
spin_unlock(&edge_port->ep_lock);
- dbg("%s - txcredits for port%d = %d", __func__, portNumber, edge_port->txCredits);
-
- /* tell the tty driver that something has changed */
- if (edge_port->port->tty)
- tty_wakeup(edge_port->port->tty);
-
- // Since we have more credit, check if more data can be sent
- send_more_port_data(edge_serial, edge_port);
+ dbg("%s - txcredits for port%d = %d",
+ __func__, portNumber,
+ edge_port->txCredits);
+
+ /* tell the tty driver that something
+ has changed */
+ if (edge_port->port->port.tty)
+ tty_wakeup(edge_port->port->port.tty);
+
+ /* Since we have more credit, check
+ if more data can be sent */
+ send_more_port_data(edge_serial,
+ edge_port);
}
}
position += 2;
@@ -652,19 +690,20 @@ static void edge_interrupt_callback (struct urb *urb)
}
exit:
- result = usb_submit_urb (urb, GFP_ATOMIC);
- if (result) {
- dev_err(&urb->dev->dev, "%s - Error %d submitting control urb\n", __func__, result);
- }
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result)
+ dev_err(&urb->dev->dev,
+ "%s - Error %d submitting control urb\n",
+ __func__, result);
}
/*****************************************************************************
* edge_bulk_in_callback
- * this is the callback function for when we have received data on the
+ * this is the callback function for when we have received data on the
* bulk in endpoint.
*****************************************************************************/
-static void edge_bulk_in_callback (struct urb *urb)
+static void edge_bulk_in_callback(struct urb *urb)
{
struct edgeport_serial *edge_serial = urb->context;
unsigned char *data = urb->transfer_buffer;
@@ -689,16 +728,18 @@ static void edge_bulk_in_callback (struct urb *urb)
raw_data_length = urb->actual_length;
- usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, raw_data_length, data);
+ usb_serial_debug_data(debug, &edge_serial->serial->dev->dev,
+ __func__, raw_data_length, data);
spin_lock(&edge_serial->es_lock);
/* decrement our rxBytes available by the number that we just got */
edge_serial->rxBytesAvail -= raw_data_length;
- dbg("%s - Received = %d, rxBytesAvail %d", __func__, raw_data_length, edge_serial->rxBytesAvail);
+ dbg("%s - Received = %d, rxBytesAvail %d", __func__,
+ raw_data_length, edge_serial->rxBytesAvail);
- process_rcvd_data (edge_serial, data, urb->actual_length);
+ process_rcvd_data(edge_serial, data, urb->actual_length);
/* check to see if there's any more data for us to read */
if (edge_serial->rxBytesAvail > 0) {
@@ -721,10 +762,10 @@ static void edge_bulk_in_callback (struct urb *urb)
/*****************************************************************************
* edge_bulk_out_data_callback
- * this is the callback function for when we have finished sending serial data
- * on the bulk out endpoint.
+ * this is the callback function for when we have finished sending
+ * serial data on the bulk out endpoint.
*****************************************************************************/
-static void edge_bulk_out_data_callback (struct urb *urb)
+static void edge_bulk_out_data_callback(struct urb *urb)
{
struct edgeport_port *edge_port = urb->context;
struct tty_struct *tty;
@@ -737,27 +778,29 @@ static void edge_bulk_out_data_callback (struct urb *urb)
__func__, status);
}
- tty = edge_port->port->tty;
+ tty = edge_port->port->port.tty;
if (tty && edge_port->open) {
- /* let the tty driver wakeup if it has a special write_wakeup function */
+ /* let the tty driver wakeup if it has a special
+ write_wakeup function */
tty_wakeup(tty);
}
- // Release the Write URB
+ /* Release the Write URB */
edge_port->write_in_progress = false;
- // Check if more data needs to be sent
- send_more_port_data((struct edgeport_serial *)(usb_get_serial_data(edge_port->port->serial)), edge_port);
+ /* Check if more data needs to be sent */
+ send_more_port_data((struct edgeport_serial *)
+ (usb_get_serial_data(edge_port->port->serial)), edge_port);
}
/*****************************************************************************
* BulkOutCmdCallback
- * this is the callback function for when we have finished sending a command
- * on the bulk out endpoint.
+ * this is the callback function for when we have finished sending a
+ * command on the bulk out endpoint.
*****************************************************************************/
-static void edge_bulk_out_cmd_callback (struct urb *urb)
+static void edge_bulk_out_cmd_callback(struct urb *urb)
{
struct edgeport_port *edge_port = urb->context;
struct tty_struct *tty;
@@ -766,22 +809,24 @@ static void edge_bulk_out_cmd_callback (struct urb *urb)
dbg("%s", __func__);
atomic_dec(&CmdUrbs);
- dbg("%s - FREE URB %p (outstanding %d)", __func__, urb, atomic_read(&CmdUrbs));
+ dbg("%s - FREE URB %p (outstanding %d)", __func__,
+ urb, atomic_read(&CmdUrbs));
/* clean up the transfer buffer */
kfree(urb->transfer_buffer);
/* Free the command urb */
- usb_free_urb (urb);
+ usb_free_urb(urb);
if (status) {
- dbg("%s - nonzero write bulk status received: %d", __func__, status);
+ dbg("%s - nonzero write bulk status received: %d",
+ __func__, status);
return;
}
/* Get pointer to tty */
- tty = edge_port->port->tty;
+ tty = edge_port->port->port.tty;
/* tell the tty driver that something has changed */
if (tty && edge_port->open)
@@ -803,7 +848,8 @@ static void edge_bulk_out_cmd_callback (struct urb *urb)
* If successful, we return 0
* Otherwise we return a negative error number.
*****************************************************************************/
-static int edge_open (struct usb_serial_port *port, struct file * filp)
+static int edge_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct usb_serial *serial;
@@ -815,55 +861,62 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
if (edge_port == NULL)
return -ENODEV;
- if (port->tty)
- port->tty->low_latency = low_latency;
+ if (tty)
+ tty->low_latency = low_latency;
- /* see if we've set up our endpoint info yet (can't set it up in edge_startup
- as the structures were not set up at that time.) */
+ /* see if we've set up our endpoint info yet (can't set it up
+ in edge_startup as the structures were not set up at that time.) */
serial = port->serial;
edge_serial = usb_get_serial_data(serial);
- if (edge_serial == NULL) {
+ if (edge_serial == NULL)
return -ENODEV;
- }
if (edge_serial->interrupt_in_buffer == NULL) {
struct usb_serial_port *port0 = serial->port[0];
-
+
/* not set up yet, so do it now */
- edge_serial->interrupt_in_buffer = port0->interrupt_in_buffer;
- edge_serial->interrupt_in_endpoint = port0->interrupt_in_endpointAddress;
+ edge_serial->interrupt_in_buffer =
+ port0->interrupt_in_buffer;
+ edge_serial->interrupt_in_endpoint =
+ port0->interrupt_in_endpointAddress;
edge_serial->interrupt_read_urb = port0->interrupt_in_urb;
edge_serial->bulk_in_buffer = port0->bulk_in_buffer;
- edge_serial->bulk_in_endpoint = port0->bulk_in_endpointAddress;
+ edge_serial->bulk_in_endpoint =
+ port0->bulk_in_endpointAddress;
edge_serial->read_urb = port0->read_urb;
- edge_serial->bulk_out_endpoint = port0->bulk_out_endpointAddress;
-
+ edge_serial->bulk_out_endpoint =
+ port0->bulk_out_endpointAddress;
+
/* set up our interrupt urb */
usb_fill_int_urb(edge_serial->interrupt_read_urb,
- serial->dev,
- usb_rcvintpipe(serial->dev,
- port0->interrupt_in_endpointAddress),
- port0->interrupt_in_buffer,
- edge_serial->interrupt_read_urb->transfer_buffer_length,
- edge_interrupt_callback, edge_serial,
- edge_serial->interrupt_read_urb->interval);
-
+ serial->dev,
+ usb_rcvintpipe(serial->dev,
+ port0->interrupt_in_endpointAddress),
+ port0->interrupt_in_buffer,
+ edge_serial->interrupt_read_urb->transfer_buffer_length,
+ edge_interrupt_callback, edge_serial,
+ edge_serial->interrupt_read_urb->interval);
+
/* set up our bulk in urb */
usb_fill_bulk_urb(edge_serial->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev,
- port0->bulk_in_endpointAddress),
- port0->bulk_in_buffer,
- edge_serial->read_urb->transfer_buffer_length,
- edge_bulk_in_callback, edge_serial);
+ usb_rcvbulkpipe(serial->dev,
+ port0->bulk_in_endpointAddress),
+ port0->bulk_in_buffer,
+ edge_serial->read_urb->transfer_buffer_length,
+ edge_bulk_in_callback, edge_serial);
edge_serial->read_in_progress = false;
/* start interrupt read for this edgeport
- * this interrupt will continue as long as the edgeport is connected */
- response = usb_submit_urb (edge_serial->interrupt_read_urb, GFP_KERNEL);
+ * this interrupt will continue as long
+ * as the edgeport is connected */
+ response = usb_submit_urb(edge_serial->interrupt_read_urb,
+ GFP_KERNEL);
if (response) {
- dev_err(&port->dev, "%s - Error %d submitting control urb\n", __func__, response);
+ dev_err(&port->dev,
+ "%s - Error %d submitting control urb\n",
+ __func__, response);
}
}
-
+
/* initialize our wait queues */
init_waitqueue_head(&edge_port->wait_open);
init_waitqueue_head(&edge_port->wait_chase);
@@ -871,26 +924,29 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
init_waitqueue_head(&edge_port->wait_command);
/* initialize our icount structure */
- memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount));
+ memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
/* initialize our port settings */
- edge_port->txCredits = 0; /* Can't send any data yet */
- edge_port->shadowMCR = MCR_MASTER_IE; /* Must always set this bit to enable ints! */
+ edge_port->txCredits = 0; /* Can't send any data yet */
+ /* Must always set this bit to enable ints! */
+ edge_port->shadowMCR = MCR_MASTER_IE;
edge_port->chaseResponsePending = false;
/* send a open port command */
edge_port->openPending = true;
edge_port->open = false;
- response = send_iosp_ext_cmd (edge_port, IOSP_CMD_OPEN_PORT, 0);
+ response = send_iosp_ext_cmd(edge_port, IOSP_CMD_OPEN_PORT, 0);
if (response < 0) {
- dev_err(&port->dev, "%s - error sending open port command\n", __func__);
+ dev_err(&port->dev, "%s - error sending open port command\n",
+ __func__);
edge_port->openPending = false;
return -ENODEV;
}
/* now wait for the port to be completely opened */
- wait_event_timeout(edge_port->wait_open, !edge_port->openPending, OPEN_TIMEOUT);
+ wait_event_timeout(edge_port->wait_open, !edge_port->openPending,
+ OPEN_TIMEOUT);
if (!edge_port->open) {
/* open timed out */
@@ -904,25 +960,26 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
edge_port->txfifo.tail = 0;
edge_port->txfifo.count = 0;
edge_port->txfifo.size = edge_port->maxTxCredits;
- edge_port->txfifo.fifo = kmalloc (edge_port->maxTxCredits, GFP_KERNEL);
+ edge_port->txfifo.fifo = kmalloc(edge_port->maxTxCredits, GFP_KERNEL);
if (!edge_port->txfifo.fifo) {
dbg("%s - no memory", __func__);
- edge_close (port, filp);
+ edge_close(tty, port, filp);
return -ENOMEM;
}
/* Allocate a URB for the write */
- edge_port->write_urb = usb_alloc_urb (0, GFP_KERNEL);
+ edge_port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
edge_port->write_in_progress = false;
if (!edge_port->write_urb) {
dbg("%s - no memory", __func__);
- edge_close (port, filp);
+ edge_close(tty, port, filp);
return -ENOMEM;
}
- dbg("%s(%d) - Initialize TX fifo to %d bytes", __func__, port->number, edge_port->maxTxCredits);
+ dbg("%s(%d) - Initialize TX fifo to %d bytes",
+ __func__, port->number, edge_port->maxTxCredits);
dbg("%s exited", __func__);
@@ -948,27 +1005,28 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
int loop = 10;
while (1) {
- // Save Last credits
+ /* Save Last credits */
lastCredits = edge_port->txCredits;
- // Did we get our Chase response
+ /* Did we get our Chase response */
if (!edge_port->chaseResponsePending) {
dbg("%s - Got Chase Response", __func__);
- // did we get all of our credit back?
- if (edge_port->txCredits == edge_port->maxTxCredits ) {
+ /* did we get all of our credit back? */
+ if (edge_port->txCredits == edge_port->maxTxCredits) {
dbg("%s - Got all credits", __func__);
return;
}
}
- // Block the thread for a while
- prepare_to_wait(&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE);
+ /* Block the thread for a while */
+ prepare_to_wait(&edge_port->wait_chase, &wait,
+ TASK_UNINTERRUPTIBLE);
schedule_timeout(timeout);
finish_wait(&edge_port->wait_chase, &wait);
if (lastCredits == edge_port->txCredits) {
- // No activity.. count down.
+ /* No activity.. count down. */
loop--;
if (loop == 0) {
edge_port->chaseResponsePending = false;
@@ -976,8 +1034,9 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
return;
}
} else {
- // Reset timeout value back to 10 seconds
- dbg("%s - Last %d, Current %d", __func__, lastCredits, edge_port->txCredits);
+ /* Reset timeout value back to 10 seconds */
+ dbg("%s - Last %d, Current %d", __func__,
+ lastCredits, edge_port->txCredits);
loop = 10;
}
}
@@ -994,7 +1053,7 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
* 3. A timeout of 3 seconds without activity has expired
*
************************************************************************/
-static void block_until_tx_empty (struct edgeport_port *edge_port)
+static void block_until_tx_empty(struct edgeport_port *edge_port)
{
DEFINE_WAIT(wait);
struct TxFifo *fifo = &edge_port->txfifo;
@@ -1003,31 +1062,32 @@ static void block_until_tx_empty (struct edgeport_port *edge_port)
int loop = 30;
while (1) {
- // Save Last count
+ /* Save Last count */
lastCount = fifo->count;
- // Is the Edgeport Buffer empty?
+ /* Is the Edgeport Buffer empty? */
if (lastCount == 0) {
dbg("%s - TX Buffer Empty", __func__);
return;
}
- // Block the thread for a while
- prepare_to_wait (&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE);
+ /* Block the thread for a while */
+ prepare_to_wait(&edge_port->wait_chase, &wait,
+ TASK_UNINTERRUPTIBLE);
schedule_timeout(timeout);
finish_wait(&edge_port->wait_chase, &wait);
dbg("%s wait", __func__);
if (lastCount == fifo->count) {
- // No activity.. count down.
+ /* No activity.. count down. */
loop--;
if (loop == 0) {
dbg("%s - TIMEOUT", __func__);
return;
}
} else {
- // Reset timeout value back to seconds
+ /* Reset timeout value back to seconds */
loop = 30;
}
}
@@ -1038,20 +1098,21 @@ static void block_until_tx_empty (struct edgeport_port *edge_port)
* edge_close
* this function is called by the tty driver when a port is closed
*****************************************************************************/
-static void edge_close (struct usb_serial_port *port, struct file * filp)
+static void edge_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct edgeport_serial *edge_serial;
struct edgeport_port *edge_port;
int status;
dbg("%s - port %d", __func__, port->number);
-
+
edge_serial = usb_get_serial_data(port->serial);
edge_port = usb_get_serial_port_data(port);
- if ((edge_serial == NULL) || (edge_port == NULL))
+ if (edge_serial == NULL || edge_port == NULL)
return;
-
- // block until tx is empty
+
+ /* block until tx is empty */
block_until_tx_empty(edge_port);
edge_port->closePending = true;
@@ -1063,13 +1124,12 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
edge_port->chaseResponsePending = true;
dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__);
- status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
- if (status == 0) {
- // block until chase finished
+ status = send_iosp_ext_cmd(edge_port, IOSP_CMD_CHASE_PORT, 0);
+ if (status == 0)
+ /* block until chase finished */
block_until_chase_response(edge_port);
- } else {
+ else
edge_port->chaseResponsePending = false;
- }
}
if ((!edge_serial->is_epic) ||
@@ -1077,10 +1137,10 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
(edge_serial->epic_descriptor.Supports.IOSPClose))) {
/* close the port */
dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __func__);
- send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);
+ send_iosp_ext_cmd(edge_port, IOSP_CMD_CLOSE_PORT, 0);
}
- //port->close = true;
+ /* port->close = true; */
edge_port->closePending = false;
edge_port->open = false;
edge_port->openPending = false;
@@ -1088,7 +1148,8 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
usb_kill_urb(edge_port->write_urb);
if (edge_port->write_urb) {
- /* if this urb had a transfer buffer already (old transfer) free it */
+ /* if this urb had a transfer buffer already
+ (old transfer) free it */
kfree(edge_port->write_urb->transfer_buffer);
usb_free_urb(edge_port->write_urb);
edge_port->write_urb = NULL;
@@ -1097,16 +1158,17 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
edge_port->txfifo.fifo = NULL;
dbg("%s exited", __func__);
-}
+}
/*****************************************************************************
* SerialWrite
- * this function is called by the tty driver when data should be written to
- * the port.
- * If successful, we return the number of bytes written, otherwise we return
- * a negative error number.
+ * this function is called by the tty driver when data should be written
+ * to the port.
+ * If successful, we return the number of bytes written, otherwise we
+ * return a negative error number.
*****************************************************************************/
-static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count)
+static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *data, int count)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct TxFifo *fifo;
@@ -1121,66 +1183,76 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
if (edge_port == NULL)
return -ENODEV;
- // get a pointer to the Tx fifo
+ /* get a pointer to the Tx fifo */
fifo = &edge_port->txfifo;
spin_lock_irqsave(&edge_port->ep_lock, flags);
- // calculate number of bytes to put in fifo
- copySize = min ((unsigned int)count, (edge_port->txCredits - fifo->count));
+ /* calculate number of bytes to put in fifo */
+ copySize = min((unsigned int)count,
+ (edge_port->txCredits - fifo->count));
- dbg("%s(%d) of %d byte(s) Fifo room %d -- will copy %d bytes", __func__,
- port->number, count, edge_port->txCredits - fifo->count, copySize);
+ dbg("%s(%d) of %d byte(s) Fifo room %d -- will copy %d bytes",
+ __func__, port->number, count,
+ edge_port->txCredits - fifo->count, copySize);
- /* catch writes of 0 bytes which the tty driver likes to give us, and when txCredits is empty */
+ /* catch writes of 0 bytes which the tty driver likes to give us,
+ and when txCredits is empty */
if (copySize == 0) {
dbg("%s - copySize = Zero", __func__);
goto finish_write;
}
- // queue the data
- // since we can never overflow the buffer we do not have to check for full condition
-
- // the copy is done is two parts -- first fill to the end of the buffer
- // then copy the reset from the start of the buffer
-
+ /* queue the data
+ * since we can never overflow the buffer we do not have to check for a
+ * full condition
+ *
+ * the copy is done is two parts -- first fill to the end of the buffer
+ * then copy the reset from the start of the buffer
+ */
bytesleft = fifo->size - fifo->head;
- firsthalf = min (bytesleft, copySize);
- dbg("%s - copy %d bytes of %d into fifo ", __func__, firsthalf, bytesleft);
+ firsthalf = min(bytesleft, copySize);
+ dbg("%s - copy %d bytes of %d into fifo ", __func__,
+ firsthalf, bytesleft);
/* now copy our data */
memcpy(&fifo->fifo[fifo->head], data, firsthalf);
- usb_serial_debug_data(debug, &port->dev, __func__, firsthalf, &fifo->fifo[fifo->head]);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ firsthalf, &fifo->fifo[fifo->head]);
- // update the index and size
+ /* update the index and size */
fifo->head += firsthalf;
fifo->count += firsthalf;
- // wrap the index
- if (fifo->head == fifo->size) {
+ /* wrap the index */
+ if (fifo->head == fifo->size)
fifo->head = 0;
- }
secondhalf = copySize-firsthalf;
if (secondhalf) {
dbg("%s - copy rest of data %d", __func__, secondhalf);
memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf);
- usb_serial_debug_data(debug, &port->dev, __func__, secondhalf, &fifo->fifo[fifo->head]);
- // update the index and size
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ secondhalf, &fifo->fifo[fifo->head]);
+ /* update the index and size */
fifo->count += secondhalf;
fifo->head += secondhalf;
- // No need to check for wrap since we can not get to end of fifo in this part
+ /* No need to check for wrap since we can not get to end of
+ * the fifo in this part
+ */
}
finish_write:
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
- send_more_port_data((struct edgeport_serial *)usb_get_serial_data(port->serial), edge_port);
+ send_more_port_data((struct edgeport_serial *)
+ usb_get_serial_data(port->serial), edge_port);
- dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __func__, copySize, edge_port->txCredits, fifo->count);
+ dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __func__,
+ copySize, edge_port->txCredits, fifo->count);
- return copySize;
+ return copySize;
}
@@ -1197,7 +1269,8 @@ finish_write:
* can transmit more.
*
************************************************************************/
-static void send_more_port_data(struct edgeport_serial *edge_serial, struct edgeport_port *edge_port)
+static void send_more_port_data(struct edgeport_serial *edge_serial,
+ struct edgeport_port *edge_port)
{
struct TxFifo *fifo = &edge_port->txfifo;
struct urb *urb;
@@ -1216,67 +1289,78 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
if (edge_port->write_in_progress ||
!edge_port->open ||
(fifo->count == 0)) {
- dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d", __func__, edge_port->port->number, fifo->count, edge_port->write_in_progress);
+ dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d",
+ __func__, edge_port->port->number,
+ fifo->count, edge_port->write_in_progress);
goto exit_send;
}
- // since the amount of data in the fifo will always fit into the
- // edgeport buffer we do not need to check the write length
-
- // Do we have enough credits for this port to make it worthwhile
- // to bother queueing a write. If it's too small, say a few bytes,
- // it's better to wait for more credits so we can do a larger
- // write.
- if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits,EDGE_FW_BULK_MAX_PACKET_SIZE)) {
- dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", __func__, edge_port->port->number, fifo->count, edge_port->txCredits );
+ /* since the amount of data in the fifo will always fit into the
+ * edgeport buffer we do not need to check the write length
+ *
+ * Do we have enough credits for this port to make it worthwhile
+ * to bother queueing a write. If it's too small, say a few bytes,
+ * it's better to wait for more credits so we can do a larger write.
+ */
+ if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits, EDGE_FW_BULK_MAX_PACKET_SIZE)) {
+ dbg("%s(%d) Not enough credit - fifo %d TxCredit %d",
+ __func__, edge_port->port->number, fifo->count,
+ edge_port->txCredits);
goto exit_send;
}
- // lock this write
+ /* lock this write */
edge_port->write_in_progress = true;
- // get a pointer to the write_urb
+ /* get a pointer to the write_urb */
urb = edge_port->write_urb;
/* make sure transfer buffer is freed */
kfree(urb->transfer_buffer);
urb->transfer_buffer = NULL;
- /* build the data header for the buffer and port that we are about to send out */
+ /* build the data header for the buffer and port that we are about
+ to send out */
count = fifo->count;
- buffer = kmalloc (count+2, GFP_ATOMIC);
+ buffer = kmalloc(count+2, GFP_ATOMIC);
if (buffer == NULL) {
- dev_err(&edge_port->port->dev, "%s - no more kernel memory...\n", __func__);
+ dev_err(&edge_port->port->dev,
+ "%s - no more kernel memory...\n", __func__);
edge_port->write_in_progress = false;
goto exit_send;
}
- buffer[0] = IOSP_BUILD_DATA_HDR1 (edge_port->port->number - edge_port->port->serial->minor, count);
- buffer[1] = IOSP_BUILD_DATA_HDR2 (edge_port->port->number - edge_port->port->serial->minor, count);
+ buffer[0] = IOSP_BUILD_DATA_HDR1(edge_port->port->number
+ - edge_port->port->serial->minor, count);
+ buffer[1] = IOSP_BUILD_DATA_HDR2(edge_port->port->number
+ - edge_port->port->serial->minor, count);
/* now copy our data */
bytesleft = fifo->size - fifo->tail;
- firsthalf = min (bytesleft, count);
+ firsthalf = min(bytesleft, count);
memcpy(&buffer[2], &fifo->fifo[fifo->tail], firsthalf);
fifo->tail += firsthalf;
fifo->count -= firsthalf;
- if (fifo->tail == fifo->size) {
+ if (fifo->tail == fifo->size)
fifo->tail = 0;
- }
secondhalf = count-firsthalf;
if (secondhalf) {
- memcpy(&buffer[2+firsthalf], &fifo->fifo[fifo->tail], secondhalf);
+ memcpy(&buffer[2+firsthalf], &fifo->fifo[fifo->tail],
+ secondhalf);
fifo->tail += secondhalf;
fifo->count -= secondhalf;
}
if (count)
- usb_serial_debug_data(debug, &edge_port->port->dev, __func__, count, &buffer[2]);
+ usb_serial_debug_data(debug, &edge_port->port->dev,
+ __func__, count, &buffer[2]);
/* fill up the urb with all of our data and submit it */
- usb_fill_bulk_urb (urb, edge_serial->serial->dev,
- usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint),
- buffer, count+2, edge_bulk_out_data_callback, edge_port);
+ usb_fill_bulk_urb(urb, edge_serial->serial->dev,
+ usb_sndbulkpipe(edge_serial->serial->dev,
+ edge_serial->bulk_out_endpoint),
+ buffer, count+2,
+ edge_bulk_out_data_callback, edge_port);
/* decrement the number of credits we have by the number we just sent */
edge_port->txCredits -= count;
@@ -1286,14 +1370,17 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
/* something went wrong */
- dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", __func__, status);
+ dev_err(&edge_port->port->dev,
+ "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n",
+ __func__, status);
edge_port->write_in_progress = false;
/* revert the credits as something bad happened. */
edge_port->txCredits += count;
edge_port->icount.tx -= count;
}
- dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d", __func__, count, edge_port->txCredits, fifo->count);
+ dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d",
+ __func__, count, edge_port->txCredits, fifo->count);
exit_send:
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
@@ -1302,14 +1389,14 @@ exit_send:
/*****************************************************************************
* edge_write_room
- * this function is called by the tty driver when it wants to know how many
- * bytes of data we can accept for a specific port.
- * If successful, we return the amount of room that we have for this port
- * (the txCredits),
- * Otherwise we return a negative error number.
+ * this function is called by the tty driver when it wants to know how
+ * many bytes of data we can accept for a specific port. If successful,
+ * we return the amount of room that we have for this port (the txCredits)
+ * otherwise we return a negative error number.
*****************************************************************************/
-static int edge_write_room (struct usb_serial_port *port)
+static int edge_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int room;
unsigned long flags;
@@ -1317,18 +1404,18 @@ static int edge_write_room (struct usb_serial_port *port)
dbg("%s", __func__);
if (edge_port == NULL)
- return -ENODEV;
+ return 0;
if (edge_port->closePending)
- return -ENODEV;
+ return 0;
dbg("%s - port %d", __func__, port->number);
if (!edge_port->open) {
dbg("%s - port not opened", __func__);
- return -EINVAL;
+ return 0;
}
- // total of both buffers is still txCredit
+ /* total of both buffers is still txCredit */
spin_lock_irqsave(&edge_port->ep_lock, flags);
room = edge_port->txCredits - edge_port->txfifo.count;
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
@@ -1340,15 +1427,16 @@ static int edge_write_room (struct usb_serial_port *port)
/*****************************************************************************
* edge_chars_in_buffer
- * this function is called by the tty driver when it wants to know how many
- * bytes of data we currently have outstanding in the port (data that has
- * been written, but hasn't made it out the port yet)
- * If successful, we return the number of bytes left to be written in the
- * system,
+ * this function is called by the tty driver when it wants to know how
+ * many bytes of data we currently have outstanding in the port (data that
+ * has been written, but hasn't made it out the port yet)
+ * If successful, we return the number of bytes left to be written in the
+ * system,
* Otherwise we return a negative error number.
*****************************************************************************/
-static int edge_chars_in_buffer (struct usb_serial_port *port)
+static int edge_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int num_chars;
unsigned long flags;
@@ -1356,20 +1444,22 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
dbg("%s", __func__);
if (edge_port == NULL)
- return -ENODEV;
+ return 0;
if (edge_port->closePending)
- return -ENODEV;
+ return 0;
if (!edge_port->open) {
dbg("%s - port not opened", __func__);
- return -EINVAL;
+ return 0;
}
spin_lock_irqsave(&edge_port->ep_lock, flags);
- num_chars = edge_port->maxTxCredits - edge_port->txCredits + edge_port->txfifo.count;
+ num_chars = edge_port->maxTxCredits - edge_port->txCredits +
+ edge_port->txfifo.count;
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
if (num_chars) {
- dbg("%s(port %d) - returns %d", __func__, port->number, num_chars);
+ dbg("%s(port %d) - returns %d", __func__,
+ port->number, num_chars);
}
return num_chars;
@@ -1381,10 +1471,10 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
* this function is called by the tty driver when it wants to stop the data
* being read from the port.
*****************************************************************************/
-static void edge_throttle (struct usb_serial_port *port)
+static void edge_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct tty_struct *tty;
int status;
dbg("%s - port %d", __func__, port->number);
@@ -1397,28 +1487,21 @@ static void edge_throttle (struct usb_serial_port *port)
return;
}
- tty = port->tty;
- if (!tty) {
- dbg ("%s - no tty available", __func__);
- return;
- }
-
/* if we are implementing XON/XOFF, send the stop character */
if (I_IXOFF(tty)) {
unsigned char stop_char = STOP_CHAR(tty);
- status = edge_write (port, &stop_char, 1);
- if (status <= 0) {
+ status = edge_write(tty, port, &stop_char, 1);
+ if (status <= 0)
return;
- }
}
/* if we are implementing RTS/CTS, toggle that line */
if (tty->termios->c_cflag & CRTSCTS) {
edge_port->shadowMCR &= ~MCR_RTS;
- status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);
- if (status != 0) {
+ status = send_cmd_write_uart_register(edge_port, MCR,
+ edge_port->shadowMCR);
+ if (status != 0)
return;
- }
}
return;
@@ -1427,13 +1510,13 @@ static void edge_throttle (struct usb_serial_port *port)
/*****************************************************************************
* edge_unthrottle
- * this function is called by the tty driver when it wants to resume the data
- * being read from the port (called after SerialThrottle is called)
+ * this function is called by the tty driver when it wants to resume the
+ * data being read from the port (called after SerialThrottle is called)
*****************************************************************************/
-static void edge_unthrottle (struct usb_serial_port *port)
+static void edge_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct tty_struct *tty;
int status;
dbg("%s - port %d", __func__, port->number);
@@ -1446,43 +1529,31 @@ static void edge_unthrottle (struct usb_serial_port *port)
return;
}
- tty = port->tty;
- if (!tty) {
- dbg ("%s - no tty available", __func__);
- return;
- }
-
/* if we are implementing XON/XOFF, send the start character */
if (I_IXOFF(tty)) {
unsigned char start_char = START_CHAR(tty);
- status = edge_write (port, &start_char, 1);
- if (status <= 0) {
+ status = edge_write(tty, port, &start_char, 1);
+ if (status <= 0)
return;
- }
}
-
/* if we are implementing RTS/CTS, toggle that line */
if (tty->termios->c_cflag & CRTSCTS) {
edge_port->shadowMCR |= MCR_RTS;
- status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);
- if (status != 0) {
- return;
- }
+ send_cmd_write_uart_register(edge_port, MCR,
+ edge_port->shadowMCR);
}
-
- return;
}
/*****************************************************************************
* SerialSetTermios
- * this function is called by the tty driver when it wants to change the termios structure
+ * this function is called by the tty driver when it wants to change
+ * the termios structure
*****************************************************************************/
-static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void edge_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
- /* FIXME: This function appears unused ?? */
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
unsigned int cflag;
cflag = tty->termios->c_cflag;
@@ -1502,9 +1573,7 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
}
/* change the port settings to the new ones specified */
- change_port_settings (edge_port, old_termios);
-
- return;
+ change_port_settings(tty, edge_port, old_termios);
}
@@ -1516,9 +1585,10 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
* release the bus after transmitting. This must be done when
* the transmit shift register is empty, not be done when the
* transmit holding register is empty. This functionality
- * allows an RS485 driver to be written in user space.
+ * allows an RS485 driver to be written in user space.
*****************************************************************************/
-static int get_lsr_info(struct edgeport_port *edge_port, unsigned int __user *value)
+static int get_lsr_info(struct edgeport_port *edge_port,
+ unsigned int __user *value)
{
unsigned int result = 0;
unsigned long flags;
@@ -1536,25 +1606,10 @@ static int get_lsr_info(struct edgeport_port *edge_port, unsigned int __user *va
return 0;
}
-static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int __user *value)
-{
- unsigned int result = 0;
- struct tty_struct *tty = edge_port->port->tty;
-
- if (!tty)
- return -ENOIOCTLCMD;
-
- result = tty->read_cnt;
-
- dbg("%s(%d) = %d", __func__, edge_port->port->number, result);
- if (copy_to_user(value, &result, sizeof(int)))
- return -EFAULT;
- //return 0;
- return -ENOIOCTLCMD;
-}
-
-static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear)
+static int edge_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int mcr;
@@ -1582,8 +1637,9 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig
return 0;
}
-static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
+static int edge_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int result = 0;
unsigned int msr;
@@ -1606,7 +1662,8 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
return result;
}
-static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct __user *retinfo)
+static int get_serial_info(struct edgeport_port *edge_port,
+ struct serial_struct __user *retinfo)
{
struct serial_struct tmp;
@@ -1624,9 +1681,6 @@ static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct
tmp.baud_base = 9600;
tmp.close_delay = 5*HZ;
tmp.closing_wait = 30*HZ;
-// tmp.custom_divisor = state->custom_divisor;
-// tmp.hub6 = state->hub6;
-// tmp.io_type = state->io_type;
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
return -EFAULT;
@@ -1639,8 +1693,10 @@ static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct
* SerialIoctl
* this function handles any ioctl calls to the driver
*****************************************************************************/
-static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
+static int edge_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
DEFINE_WAIT(wait);
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct async_icount cnow;
@@ -1650,71 +1706,61 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
switch (cmd) {
- // return number of bytes available
- case TIOCINQ:
- dbg("%s (%d) TIOCINQ", __func__, port->number);
- return get_number_bytes_avail(edge_port, (unsigned int __user *) arg);
- break;
-
- case TIOCSERGETLSR:
- dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
- return get_lsr_info(edge_port, (unsigned int __user *) arg);
- return 0;
-
- case TIOCGSERIAL:
- dbg("%s (%d) TIOCGSERIAL", __func__, port->number);
- return get_serial_info(edge_port, (struct serial_struct __user *) arg);
-
- case TIOCSSERIAL:
- dbg("%s (%d) TIOCSSERIAL", __func__, port->number);
- break;
-
- case TIOCMIWAIT:
- dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
- cprev = edge_port->icount;
- while (1) {
- prepare_to_wait(&edge_port->delta_msr_wait, &wait, TASK_INTERRUPTIBLE);
- schedule();
- finish_wait(&edge_port->delta_msr_wait, &wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- cnow = edge_port->icount;
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
- return 0;
- }
- cprev = cnow;
+ case TIOCSERGETLSR:
+ dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
+ return get_lsr_info(edge_port, (unsigned int __user *) arg);
+
+ case TIOCGSERIAL:
+ dbg("%s (%d) TIOCGSERIAL", __func__, port->number);
+ return get_serial_info(edge_port, (struct serial_struct __user *) arg);
+
+ case TIOCMIWAIT:
+ dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
+ cprev = edge_port->icount;
+ while (1) {
+ prepare_to_wait(&edge_port->delta_msr_wait,
+ &wait, TASK_INTERRUPTIBLE);
+ schedule();
+ finish_wait(&edge_port->delta_msr_wait, &wait);
+ /* see if a signal did it */
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ cnow = edge_port->icount;
+ if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+ cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+ return -EIO; /* no change => error */
+ if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+ ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
+ return 0;
}
- /* NOTREACHED */
- break;
+ cprev = cnow;
+ }
+ /* NOTREACHED */
+ break;
- case TIOCGICOUNT:
- cnow = edge_port->icount;
- memset(&icount, 0, sizeof(icount));
- icount.cts = cnow.cts;
- icount.dsr = cnow.dsr;
- icount.rng = cnow.rng;
- icount.dcd = cnow.dcd;
- icount.rx = cnow.rx;
- icount.tx = cnow.tx;
- icount.frame = cnow.frame;
- icount.overrun = cnow.overrun;
- icount.parity = cnow.parity;
- icount.brk = cnow.brk;
- icount.buf_overrun = cnow.buf_overrun;
-
- dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, port->number, icount.rx, icount.tx );
- if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
- return -EFAULT;
- return 0;
+ case TIOCGICOUNT:
+ cnow = edge_port->icount;
+ memset(&icount, 0, sizeof(icount));
+ icount.cts = cnow.cts;
+ icount.dsr = cnow.dsr;
+ icount.rng = cnow.rng;
+ icount.dcd = cnow.dcd;
+ icount.rx = cnow.rx;
+ icount.tx = cnow.tx;
+ icount.frame = cnow.frame;
+ icount.overrun = cnow.overrun;
+ icount.parity = cnow.parity;
+ icount.brk = cnow.brk;
+ icount.buf_overrun = cnow.buf_overrun;
+
+ dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d",
+ __func__, port->number, icount.rx, icount.tx);
+ if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
+ return -EFAULT;
+ return 0;
}
-
return -ENOIOCTLCMD;
}
@@ -1723,8 +1769,9 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
* SerialBreak
* this function sends a break to the port
*****************************************************************************/
-static void edge_break (struct usb_serial_port *port, int break_state)
+static void edge_break(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct edgeport_serial *edge_serial = usb_get_serial_data(port->serial);
int status;
@@ -1736,9 +1783,9 @@ static void edge_break (struct usb_serial_port *port, int break_state)
edge_port->chaseResponsePending = true;
dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__);
- status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
+ status = send_iosp_ext_cmd(edge_port, IOSP_CMD_CHASE_PORT, 0);
if (status == 0) {
- // block until chase finished
+ /* block until chase finished */
block_until_chase_response(edge_port);
} else {
edge_port->chaseResponsePending = false;
@@ -1750,14 +1797,16 @@ static void edge_break (struct usb_serial_port *port, int break_state)
(edge_serial->epic_descriptor.Supports.IOSPSetClrBreak))) {
if (break_state == -1) {
dbg("%s - Sending IOSP_CMD_SET_BREAK", __func__);
- status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0);
+ status = send_iosp_ext_cmd(edge_port,
+ IOSP_CMD_SET_BREAK, 0);
} else {
dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __func__);
- status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CLEAR_BREAK, 0);
- }
- if (status) {
- dbg("%s - error sending break set/clear command.", __func__);
+ status = send_iosp_ext_cmd(edge_port,
+ IOSP_CMD_CLEAR_BREAK, 0);
}
+ if (status)
+ dbg("%s - error sending break set/clear command.",
+ __func__);
}
return;
@@ -1768,7 +1817,8 @@ static void edge_break (struct usb_serial_port *port, int break_state)
* process_rcvd_data
* this function handles the data received on the bulk in pipe.
*****************************************************************************/
-static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char * buffer, __u16 bufferLength)
+static void process_rcvd_data(struct edgeport_serial *edge_serial,
+ unsigned char *buffer, __u16 bufferLength)
{
struct usb_serial_port *port;
struct edgeport_port *edge_port;
@@ -1789,105 +1839,123 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
lastBufferLength = bufferLength;
switch (edge_serial->rxState) {
- case EXPECT_HDR1:
- edge_serial->rxHeader1 = *buffer;
- ++buffer;
- --bufferLength;
+ case EXPECT_HDR1:
+ edge_serial->rxHeader1 = *buffer;
+ ++buffer;
+ --bufferLength;
- if (bufferLength == 0) {
- edge_serial->rxState = EXPECT_HDR2;
+ if (bufferLength == 0) {
+ edge_serial->rxState = EXPECT_HDR2;
+ break;
+ }
+ /* otherwise, drop on through */
+ case EXPECT_HDR2:
+ edge_serial->rxHeader2 = *buffer;
+ ++buffer;
+ --bufferLength;
+
+ dbg("%s - Hdr1=%02X Hdr2=%02X", __func__,
+ edge_serial->rxHeader1, edge_serial->rxHeader2);
+ /* Process depending on whether this header is
+ * data or status */
+
+ if (IS_CMD_STAT_HDR(edge_serial->rxHeader1)) {
+ /* Decode this status header and go to
+ * EXPECT_HDR1 (if we can process the status
+ * with only 2 bytes), or go to EXPECT_HDR3 to
+ * get the third byte. */
+ edge_serial->rxPort =
+ IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
+ edge_serial->rxStatusCode =
+ IOSP_GET_STATUS_CODE(
+ edge_serial->rxHeader1);
+
+ if (!IOSP_STATUS_IS_2BYTE(
+ edge_serial->rxStatusCode)) {
+ /* This status needs additional bytes.
+ * Save what we have and then wait for
+ * more data.
+ */
+ edge_serial->rxStatusParam
+ = edge_serial->rxHeader2;
+ edge_serial->rxState = EXPECT_HDR3;
break;
}
- /* otherwise, drop on through */
-
- case EXPECT_HDR2:
- edge_serial->rxHeader2 = *buffer;
- ++buffer;
- --bufferLength;
-
- dbg("%s - Hdr1=%02X Hdr2=%02X", __func__, edge_serial->rxHeader1, edge_serial->rxHeader2);
-
- // Process depending on whether this header is
- // data or status
-
- if (IS_CMD_STAT_HDR(edge_serial->rxHeader1)) {
- // Decode this status header and goto EXPECT_HDR1 (if we
- // can process the status with only 2 bytes), or goto
- // EXPECT_HDR3 to get the third byte.
-
- edge_serial->rxPort = IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
- edge_serial->rxStatusCode = IOSP_GET_STATUS_CODE(edge_serial->rxHeader1);
-
- if (!IOSP_STATUS_IS_2BYTE(edge_serial->rxStatusCode)) {
- // This status needs additional bytes. Save what we have
- // and then wait for more data.
- edge_serial->rxStatusParam = edge_serial->rxHeader2;
-
- edge_serial->rxState = EXPECT_HDR3;
- break;
- }
+ /* We have all the header bytes, process the
+ status now */
+ process_rcvd_status(edge_serial,
+ edge_serial->rxHeader2, 0);
+ edge_serial->rxState = EXPECT_HDR1;
+ break;
+ } else {
+ edge_serial->rxPort =
+ IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
+ edge_serial->rxBytesRemaining =
+ IOSP_GET_HDR_DATA_LEN(
+ edge_serial->rxHeader1,
+ edge_serial->rxHeader2);
+ dbg("%s - Data for Port %u Len %u",
+ __func__,
+ edge_serial->rxPort,
+ edge_serial->rxBytesRemaining);
+
+ /* ASSERT(DevExt->RxPort < DevExt->NumPorts);
+ * ASSERT(DevExt->RxBytesRemaining <
+ * IOSP_MAX_DATA_LENGTH);
+ */
- // We have all the header bytes, process the status now
- process_rcvd_status (edge_serial, edge_serial->rxHeader2, 0);
- edge_serial->rxState = EXPECT_HDR1;
+ if (bufferLength == 0) {
+ edge_serial->rxState = EXPECT_DATA;
break;
- } else {
- edge_serial->rxPort = IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
- edge_serial->rxBytesRemaining = IOSP_GET_HDR_DATA_LEN(edge_serial->rxHeader1, edge_serial->rxHeader2);
-
- dbg("%s - Data for Port %u Len %u", __func__, edge_serial->rxPort, edge_serial->rxBytesRemaining);
-
- //ASSERT( DevExt->RxPort < DevExt->NumPorts );
- //ASSERT( DevExt->RxBytesRemaining < IOSP_MAX_DATA_LENGTH );
-
- if (bufferLength == 0 ) {
- edge_serial->rxState = EXPECT_DATA;
- break;
- }
- // Else, drop through
}
+ /* Else, drop through */
+ }
+ case EXPECT_DATA: /* Expect data */
+ if (bufferLength < edge_serial->rxBytesRemaining) {
+ rxLen = bufferLength;
+ /* Expect data to start next buffer */
+ edge_serial->rxState = EXPECT_DATA;
+ } else {
+ /* BufLen >= RxBytesRemaining */
+ rxLen = edge_serial->rxBytesRemaining;
+ /* Start another header next time */
+ edge_serial->rxState = EXPECT_HDR1;
+ }
- case EXPECT_DATA: // Expect data
-
- if (bufferLength < edge_serial->rxBytesRemaining) {
- rxLen = bufferLength;
- edge_serial->rxState = EXPECT_DATA; // Expect data to start next buffer
- } else {
- // BufLen >= RxBytesRemaining
- rxLen = edge_serial->rxBytesRemaining;
- edge_serial->rxState = EXPECT_HDR1; // Start another header next time
- }
+ bufferLength -= rxLen;
+ edge_serial->rxBytesRemaining -= rxLen;
- bufferLength -= rxLen;
- edge_serial->rxBytesRemaining -= rxLen;
-
- /* spit this data back into the tty driver if this port is open */
- if (rxLen) {
- port = edge_serial->serial->port[edge_serial->rxPort];
- edge_port = usb_get_serial_port_data(port);
- if (edge_port->open) {
- tty = edge_port->port->tty;
- if (tty) {
- dbg("%s - Sending %d bytes to TTY for port %d", __func__, rxLen, edge_serial->rxPort);
- edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen);
- }
- edge_port->icount.rx += rxLen;
+ /* spit this data back into the tty driver if this
+ port is open */
+ if (rxLen) {
+ port = edge_serial->serial->port[
+ edge_serial->rxPort];
+ edge_port = usb_get_serial_port_data(port);
+ if (edge_port->open) {
+ tty = edge_port->port->port.tty;
+ if (tty) {
+ dbg("%s - Sending %d bytes to TTY for port %d",
+ __func__, rxLen, edge_serial->rxPort);
+ edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen);
}
- buffer += rxLen;
+ edge_port->icount.rx += rxLen;
}
+ buffer += rxLen;
+ }
+ break;
- break;
-
- case EXPECT_HDR3: // Expect 3rd byte of status header
- edge_serial->rxHeader3 = *buffer;
- ++buffer;
- --bufferLength;
-
- // We have all the header bytes, process the status now
- process_rcvd_status (edge_serial, edge_serial->rxStatusParam, edge_serial->rxHeader3);
- edge_serial->rxState = EXPECT_HDR1;
- break;
-
+ case EXPECT_HDR3: /* Expect 3rd byte of status header */
+ edge_serial->rxHeader3 = *buffer;
+ ++buffer;
+ --bufferLength;
+
+ /* We have all the header bytes, process the
+ status now */
+ process_rcvd_status(edge_serial,
+ edge_serial->rxStatusParam,
+ edge_serial->rxHeader3);
+ edge_serial->rxState = EXPECT_HDR1;
+ break;
}
}
}
@@ -1895,9 +1963,11 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
/*****************************************************************************
* process_rcvd_status
- * this function handles the any status messages received on the bulk in pipe.
+ * this function handles the any status messages received on the
+ * bulk in pipe.
*****************************************************************************/
-static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3)
+static void process_rcvd_status(struct edgeport_serial *edge_serial,
+ __u8 byte2, __u8 byte3)
{
struct usb_serial_port *port;
struct edgeport_port *edge_port;
@@ -1907,7 +1977,9 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
port = edge_serial->serial->port[edge_serial->rxPort];
edge_port = usb_get_serial_port_data(port);
if (edge_port == NULL) {
- dev_err(&edge_serial->serial->dev->dev, "%s - edge_port == NULL for port %d\n", __func__, edge_serial->rxPort);
+ dev_err(&edge_serial->serial->dev->dev,
+ "%s - edge_port == NULL for port %d\n",
+ __func__, edge_serial->rxPort);
return;
}
@@ -1915,22 +1987,28 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
if (code == IOSP_EXT_STATUS) {
switch (byte2) {
- case IOSP_EXT_STATUS_CHASE_RSP:
- // we want to do EXT status regardless of port open/closed
- dbg("%s - Port %u EXT CHASE_RSP Data = %02x", __func__, edge_serial->rxPort, byte3 );
- // Currently, the only EXT_STATUS is Chase, so process here instead of one more call
- // to one more subroutine. If/when more EXT_STATUS, there'll be more work to do.
- // Also, we currently clear flag and close the port regardless of content of above's Byte3.
- // We could choose to do something else when Byte3 says Timeout on Chase from Edgeport,
- // like wait longer in block_until_chase_response, but for now we don't.
- edge_port->chaseResponsePending = false;
- wake_up (&edge_port->wait_chase);
- return;
+ case IOSP_EXT_STATUS_CHASE_RSP:
+ /* we want to do EXT status regardless of port
+ * open/closed */
+ dbg("%s - Port %u EXT CHASE_RSP Data = %02x",
+ __func__, edge_serial->rxPort, byte3);
+ /* Currently, the only EXT_STATUS is Chase, so process
+ * here instead of one more call to one more subroutine
+ * If/when more EXT_STATUS, there'll be more work to do
+ * Also, we currently clear flag and close the port
+ * regardless of content of above's Byte3.
+ * We could choose to do something else when Byte3 says
+ * Timeout on Chase from Edgeport, like wait longer in
+ * block_until_chase_response, but for now we don't.
+ */
+ edge_port->chaseResponsePending = false;
+ wake_up(&edge_port->wait_chase);
+ return;
- case IOSP_EXT_STATUS_RX_CHECK_RSP:
- dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __func__, edge_serial->rxPort, byte3 );
- //Port->RxCheckRsp = true;
- return;
+ case IOSP_EXT_STATUS_RX_CHECK_RSP:
+ dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __func__, edge_serial->rxPort, byte3);
+ /* Port->RxCheckRsp = true; */
+ return;
}
}
@@ -1938,11 +2016,14 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
edge_port->txCredits = GET_TX_BUFFER_SIZE(byte3);
edge_port->maxTxCredits = edge_port->txCredits;
dbg("%s - Port %u Open Response Inital MSR = %02x TxBufferSize = %d", __func__, edge_serial->rxPort, byte2, edge_port->txCredits);
- handle_new_msr (edge_port, byte2);
+ handle_new_msr(edge_port, byte2);
- /* send the current line settings to the port so we are in sync with any further termios calls */
- if (edge_port->port->tty)
- change_port_settings (edge_port, edge_port->port->tty->termios);
+ /* send the current line settings to the port so we are
+ in sync with any further termios calls */
+ /* FIXME: locking on tty */
+ if (edge_port->port->port.tty)
+ change_port_settings(edge_port->port->port.tty,
+ edge_port, edge_port->port->port.tty->termios);
/* we have completed the open */
edge_port->openPending = false;
@@ -1951,45 +2032,49 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
return;
}
- // If port is closed, silently discard all rcvd status. We can
- // have cases where buffered status is received AFTER the close
- // port command is sent to the Edgeport.
- if (!edge_port->open || edge_port->closePending) {
+ /* If port is closed, silently discard all rcvd status. We can
+ * have cases where buffered status is received AFTER the close
+ * port command is sent to the Edgeport.
+ */
+ if (!edge_port->open || edge_port->closePending)
return;
- }
switch (code) {
- // Not currently sent by Edgeport
- case IOSP_STATUS_LSR:
- dbg("%s - Port %u LSR Status = %02x", __func__, edge_serial->rxPort, byte2);
- handle_new_lsr(edge_port, false, byte2, 0);
- break;
+ /* Not currently sent by Edgeport */
+ case IOSP_STATUS_LSR:
+ dbg("%s - Port %u LSR Status = %02x",
+ __func__, edge_serial->rxPort, byte2);
+ handle_new_lsr(edge_port, false, byte2, 0);
+ break;
- case IOSP_STATUS_LSR_DATA:
- dbg("%s - Port %u LSR Status = %02x, Data = %02x", __func__, edge_serial->rxPort, byte2, byte3);
- // byte2 is LSR Register
- // byte3 is broken data byte
- handle_new_lsr(edge_port, true, byte2, byte3);
- break;
- //
- // case IOSP_EXT_4_STATUS:
- // dbg("%s - Port %u LSR Status = %02x Data = %02x", __func__, edge_serial->rxPort, byte2, byte3);
- // break;
- //
- case IOSP_STATUS_MSR:
- dbg("%s - Port %u MSR Status = %02x", __func__, edge_serial->rxPort, byte2);
-
- // Process this new modem status and generate appropriate
- // events, etc, based on the new status. This routine
- // also saves the MSR in Port->ShadowMsr.
- handle_new_msr(edge_port, byte2);
- break;
+ case IOSP_STATUS_LSR_DATA:
+ dbg("%s - Port %u LSR Status = %02x, Data = %02x",
+ __func__, edge_serial->rxPort, byte2, byte3);
+ /* byte2 is LSR Register */
+ /* byte3 is broken data byte */
+ handle_new_lsr(edge_port, true, byte2, byte3);
+ break;
+ /*
+ * case IOSP_EXT_4_STATUS:
+ * dbg("%s - Port %u LSR Status = %02x Data = %02x",
+ * __func__, edge_serial->rxPort, byte2, byte3);
+ * break;
+ */
+ case IOSP_STATUS_MSR:
+ dbg("%s - Port %u MSR Status = %02x",
+ __func__, edge_serial->rxPort, byte2);
+ /*
+ * Process this new modem status and generate appropriate
+ * events, etc, based on the new status. This routine
+ * also saves the MSR in Port->ShadowMsr.
+ */
+ handle_new_msr(edge_port, byte2);
+ break;
- default:
- dbg("%s - Unrecognized IOSP status code %u\n", __func__, code);
- break;
+ default:
+ dbg("%s - Unrecognized IOSP status code %u\n", __func__, code);
+ break;
}
-
return;
}
@@ -1998,7 +2083,8 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
* edge_tty_recv
* this function passes data on to the tty flip buffer
*****************************************************************************/
-static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length)
+static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
+ unsigned char *data, int length)
{
int cnt;
@@ -2007,7 +2093,7 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
if (cnt < length) {
dev_err(dev, "%s - dropping data, %d bytes lost\n",
__func__, length - cnt);
- if(cnt == 0)
+ if (cnt == 0)
break;
}
tty_insert_flip_string(tty, data, cnt);
@@ -2029,22 +2115,19 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
dbg("%s %02x", __func__, newMsr);
- if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
+ if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |
+ EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
icount = &edge_port->icount;
/* update input line counters */
- if (newMsr & EDGEPORT_MSR_DELTA_CTS) {
+ if (newMsr & EDGEPORT_MSR_DELTA_CTS)
icount->cts++;
- }
- if (newMsr & EDGEPORT_MSR_DELTA_DSR) {
+ if (newMsr & EDGEPORT_MSR_DELTA_DSR)
icount->dsr++;
- }
- if (newMsr & EDGEPORT_MSR_DELTA_CD) {
+ if (newMsr & EDGEPORT_MSR_DELTA_CD)
icount->dcd++;
- }
- if (newMsr & EDGEPORT_MSR_DELTA_RI) {
+ if (newMsr & EDGEPORT_MSR_DELTA_RI)
icount->rng++;
- }
wake_up_interruptible(&edge_port->delta_msr_wait);
}
@@ -2059,42 +2142,41 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
* handle_new_lsr
* this function handles any change to the lsr register for a port.
*****************************************************************************/
-static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data)
+static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,
+ __u8 lsr, __u8 data)
{
- __u8 newLsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
- struct async_icount *icount;
+ __u8 newLsr = (__u8) (lsr & (__u8)
+ (LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
+ struct async_icount *icount;
dbg("%s - %02x", __func__, newLsr);
edge_port->shadowLSR = lsr;
if (newLsr & LSR_BREAK) {
- //
- // Parity and Framing errors only count if they
- // occur exclusive of a break being
- // received.
- //
+ /*
+ * Parity and Framing errors only count if they
+ * occur exclusive of a break being
+ * received.
+ */
newLsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK);
}
/* Place LSR data byte into Rx buffer */
- if (lsrData && edge_port->port->tty)
- edge_tty_recv(&edge_port->port->dev, edge_port->port->tty, &data, 1);
+ if (lsrData && edge_port->port->port.tty)
+ edge_tty_recv(&edge_port->port->dev,
+ edge_port->port->port.tty, &data, 1);
/* update input line counters */
icount = &edge_port->icount;
- if (newLsr & LSR_BREAK) {
+ if (newLsr & LSR_BREAK)
icount->brk++;
- }
- if (newLsr & LSR_OVER_ERR) {
+ if (newLsr & LSR_OVER_ERR)
icount->overrun++;
- }
- if (newLsr & LSR_PAR_ERR) {
+ if (newLsr & LSR_PAR_ERR)
icount->parity++;
- }
- if (newLsr & LSR_FRM_ERR) {
+ if (newLsr & LSR_FRM_ERR)
icount->frame++;
- }
return;
}
@@ -2102,12 +2184,13 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, __u8 l
/****************************************************************************
* sram_write
- * writes a number of bytes to the Edgeport device's sram starting at the
+ * writes a number of bytes to the Edgeport device's sram starting at the
* given address.
* If successful returns the number of bytes written, otherwise it returns
* a negative error number of the problem.
****************************************************************************/
-static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data)
+static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
+ __u16 length, const __u8 *data)
{
int result;
__u16 current_length;
@@ -2115,32 +2198,37 @@ static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u1
dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
- transfer_buffer = kmalloc (64, GFP_KERNEL);
+ transfer_buffer = kmalloc(64, GFP_KERNEL);
if (!transfer_buffer) {
- dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
+ dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n",
+ __func__, 64);
return -ENOMEM;
}
/* need to split these writes up into 64 byte chunks */
result = 0;
while (length > 0) {
- if (length > 64) {
+ if (length > 64)
current_length = 64;
- } else {
+ else
current_length = length;
- }
-// dbg("%s - writing %x, %x, %d", __func__, extAddr, addr, current_length);
- memcpy (transfer_buffer, data, current_length);
- result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_RAM,
- 0x40, addr, extAddr, transfer_buffer, current_length, 300);
+
+/* dbg("%s - writing %x, %x, %d", __func__,
+ extAddr, addr, current_length); */
+ memcpy(transfer_buffer, data, current_length);
+ result = usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ USB_REQUEST_ION_WRITE_RAM,
+ 0x40, addr, extAddr, transfer_buffer,
+ current_length, 300);
if (result < 0)
break;
length -= current_length;
addr += current_length;
data += current_length;
- }
+ }
- kfree (transfer_buffer);
+ kfree(transfer_buffer);
return result;
}
@@ -2152,40 +2240,45 @@ static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u1
* If successful returns the number of bytes written, otherwise it returns
* a negative error number of the problem.
****************************************************************************/
-static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data)
+static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
+ __u16 length, const __u8 *data)
{
int result;
__u16 current_length;
unsigned char *transfer_buffer;
-// dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
+/* dbg("%s - %x, %x, %d", __func__, extAddr, addr, length); */
- transfer_buffer = kmalloc (64, GFP_KERNEL);
+ transfer_buffer = kmalloc(64, GFP_KERNEL);
if (!transfer_buffer) {
- dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
+ dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n",
+ __func__, 64);
return -ENOMEM;
}
/* need to split these writes up into 64 byte chunks */
result = 0;
while (length > 0) {
- if (length > 64) {
+ if (length > 64)
current_length = 64;
- } else {
+ else
current_length = length;
- }
-// dbg("%s - writing %x, %x, %d", __func__, extAddr, addr, current_length);
- memcpy (transfer_buffer, data, current_length);
- result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_ROM,
- 0x40, addr, extAddr, transfer_buffer, current_length, 300);
+/* dbg("%s - writing %x, %x, %d", __func__,
+ extAddr, addr, current_length); */
+ memcpy(transfer_buffer, data, current_length);
+ result = usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ USB_REQUEST_ION_WRITE_ROM, 0x40,
+ addr, extAddr,
+ transfer_buffer, current_length, 300);
if (result < 0)
break;
length -= current_length;
addr += current_length;
data += current_length;
- }
+ }
- kfree (transfer_buffer);
+ kfree(transfer_buffer);
return result;
}
@@ -2197,7 +2290,8 @@ static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16
* If successful returns the number of bytes read, otherwise it returns
* a negative error number of the problem.
****************************************************************************/
-static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data)
+static int rom_read(struct usb_serial *serial, __u16 extAddr,
+ __u16 addr, __u16 length, __u8 *data)
{
int result;
__u16 current_length;
@@ -2205,32 +2299,36 @@ static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16
dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
- transfer_buffer = kmalloc (64, GFP_KERNEL);
+ transfer_buffer = kmalloc(64, GFP_KERNEL);
if (!transfer_buffer) {
- dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
+ dev_err(&serial->dev->dev,
+ "%s - kmalloc(%d) failed.\n", __func__, 64);
return -ENOMEM;
}
/* need to split these reads up into 64 byte chunks */
result = 0;
while (length > 0) {
- if (length > 64) {
+ if (length > 64)
current_length = 64;
- } else {
+ else
current_length = length;
- }
-// dbg("%s - %x, %x, %d", __func__, extAddr, addr, current_length);
- result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), USB_REQUEST_ION_READ_ROM,
- 0xC0, addr, extAddr, transfer_buffer, current_length, 300);
+/* dbg("%s - %x, %x, %d", __func__,
+ extAddr, addr, current_length); */
+ result = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ USB_REQUEST_ION_READ_ROM,
+ 0xC0, addr, extAddr, transfer_buffer,
+ current_length, 300);
if (result < 0)
break;
- memcpy (data, transfer_buffer, current_length);
+ memcpy(data, transfer_buffer, current_length);
length -= current_length;
addr += current_length;
data += current_length;
- }
+ }
- kfree (transfer_buffer);
+ kfree(transfer_buffer);
return result;
}
@@ -2239,7 +2337,8 @@ static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16
* send_iosp_ext_cmd
* Is used to send a IOSP message to the Edgeport device
****************************************************************************/
-static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param)
+static int send_iosp_ext_cmd(struct edgeport_port *edge_port,
+ __u8 command, __u8 param)
{
unsigned char *buffer;
unsigned char *currentCommand;
@@ -2248,19 +2347,20 @@ static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u
dbg("%s - %d, %d", __func__, command, param);
- buffer = kmalloc (10, GFP_ATOMIC);
+ buffer = kmalloc(10, GFP_ATOMIC);
if (!buffer) {
- dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __func__, 10);
+ dev_err(&edge_port->port->dev,
+ "%s - kmalloc(%d) failed.\n", __func__, 10);
return -ENOMEM;
}
currentCommand = buffer;
- MAKE_CMD_EXT_CMD (&currentCommand, &length,
- edge_port->port->number - edge_port->port->serial->minor,
- command, param);
+ MAKE_CMD_EXT_CMD(&currentCommand, &length,
+ edge_port->port->number - edge_port->port->serial->minor,
+ command, param);
- status = write_cmd_usb (edge_port, buffer, length);
+ status = write_cmd_usb(edge_port, buffer, length);
if (status) {
/* something bad happened, let's free up the memory */
kfree(buffer);
@@ -2274,43 +2374,50 @@ static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u
* write_cmd_usb
* this function writes the given buffer out to the bulk write endpoint.
*****************************************************************************/
-static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int length)
+static int write_cmd_usb(struct edgeport_port *edge_port,
+ unsigned char *buffer, int length)
{
- struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial);
+ struct edgeport_serial *edge_serial =
+ usb_get_serial_data(edge_port->port->serial);
int status = 0;
struct urb *urb;
int timeout;
- usb_serial_debug_data(debug, &edge_port->port->dev, __func__, length, buffer);
+ usb_serial_debug_data(debug, &edge_port->port->dev,
+ __func__, length, buffer);
/* Allocate our next urb */
- urb = usb_alloc_urb (0, GFP_ATOMIC);
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb)
return -ENOMEM;
atomic_inc(&CmdUrbs);
- dbg("%s - ALLOCATE URB %p (outstanding %d)", __func__, urb, atomic_read(&CmdUrbs));
+ dbg("%s - ALLOCATE URB %p (outstanding %d)",
+ __func__, urb, atomic_read(&CmdUrbs));
- usb_fill_bulk_urb (urb, edge_serial->serial->dev,
- usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint),
- buffer, length, edge_bulk_out_cmd_callback, edge_port);
+ usb_fill_bulk_urb(urb, edge_serial->serial->dev,
+ usb_sndbulkpipe(edge_serial->serial->dev,
+ edge_serial->bulk_out_endpoint),
+ buffer, length, edge_bulk_out_cmd_callback, edge_port);
edge_port->commandPending = true;
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
/* something went wrong */
- dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write command) failed, status = %d\n", __func__, status);
+ dev_err(&edge_port->port->dev,
+ "%s - usb_submit_urb(write command) failed, status = %d\n",
+ __func__, status);
usb_kill_urb(urb);
usb_free_urb(urb);
atomic_dec(&CmdUrbs);
return status;
}
- // wait for command to finish
+ /* wait for command to finish */
timeout = COMMAND_TIMEOUT;
#if 0
- wait_event (&edge_port->wait_command, !edge_port->commandPending);
+ wait_event(&edge_port->wait_command, !edge_port->commandPending);
if (edge_port->commandPending) {
/* command timed out */
@@ -2327,15 +2434,18 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
* this function sends the proper command to change the baud rate of the
* specified port.
*****************************************************************************/
-static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate)
+static int send_cmd_write_baud_rate(struct edgeport_port *edge_port,
+ int baudRate)
{
- struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial);
+ struct edgeport_serial *edge_serial =
+ usb_get_serial_data(edge_port->port->serial);
unsigned char *cmdBuffer;
unsigned char *currCmd;
int cmdLen = 0;
int divisor;
int status;
- unsigned char number = edge_port->port->number - edge_port->port->serial->minor;
+ unsigned char number =
+ edge_port->port->number - edge_port->port->serial->minor;
if (edge_serial->is_epic &&
!edge_serial->epic_descriptor.Supports.IOSPSetBaudRate) {
@@ -2344,36 +2454,40 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa
return 0;
}
- dbg("%s - port = %d, baud = %d", __func__, edge_port->port->number, baudRate);
+ dbg("%s - port = %d, baud = %d", __func__,
+ edge_port->port->number, baudRate);
- status = calc_baud_rate_divisor (baudRate, &divisor);
+ status = calc_baud_rate_divisor(baudRate, &divisor);
if (status) {
- dev_err(&edge_port->port->dev, "%s - bad baud rate\n", __func__);
+ dev_err(&edge_port->port->dev, "%s - bad baud rate\n",
+ __func__);
return status;
}
- // Alloc memory for the string of commands.
- cmdBuffer = kmalloc (0x100, GFP_ATOMIC);
+ /* Alloc memory for the string of commands. */
+ cmdBuffer = kmalloc(0x100, GFP_ATOMIC);
if (!cmdBuffer) {
- dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __func__, 0x100);
+ dev_err(&edge_port->port->dev,
+ "%s - kmalloc(%d) failed.\n", __func__, 0x100);
return -ENOMEM;
}
currCmd = cmdBuffer;
- // Enable access to divisor latch
- MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, LCR, LCR_DL_ENABLE );
+ /* Enable access to divisor latch */
+ MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, number, LCR, LCR_DL_ENABLE);
- // Write the divisor itself
- MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, DLL, LOW8 (divisor) );
- MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, DLM, HIGH8(divisor) );
+ /* Write the divisor itself */
+ MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, number, DLL, LOW8(divisor));
+ MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, number, DLM, HIGH8(divisor));
- // Restore original value to disable access to divisor latch
- MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, LCR, edge_port->shadowLCR);
+ /* Restore original value to disable access to divisor latch */
+ MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, number, LCR,
+ edge_port->shadowLCR);
- status = write_cmd_usb(edge_port, cmdBuffer, cmdLen );
+ status = write_cmd_usb(edge_port, cmdBuffer, cmdLen);
if (status) {
/* something bad happened, let's free up the memory */
- kfree (cmdBuffer);
+ kfree(cmdBuffer);
}
return status;
@@ -2385,7 +2499,7 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa
* this function calculates the proper baud rate divisor for the specified
* baud rate.
*****************************************************************************/
-static int calc_baud_rate_divisor (int baudrate, int *divisor)
+static int calc_baud_rate_divisor(int baudrate, int *divisor)
{
int i;
__u16 custom;
@@ -2394,17 +2508,17 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor)
dbg("%s - %d", __func__, baudrate);
for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
- if ( divisor_table[i].BaudRate == baudrate ) {
+ if (divisor_table[i].BaudRate == baudrate) {
*divisor = divisor_table[i].Divisor;
return 0;
}
}
- // We have tried all of the standard baud rates
- // lets try to calculate the divisor for this baud rate
- // Make sure the baud rate is reasonable
+ /* We have tried all of the standard baud rates
+ * lets try to calculate the divisor for this baud rate
+ * Make sure the baud rate is reasonable */
if (baudrate > 50 && baudrate < 230400) {
- // get divisor
+ /* get divisor */
custom = (__u16)((230400L + baudrate/2) / baudrate);
*divisor = custom;
@@ -2419,17 +2533,20 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor)
/*****************************************************************************
* send_cmd_write_uart_register
- * this function builds up a uart register message and sends to to the device.
+ * this function builds up a uart register message and sends to to the device.
*****************************************************************************/
-static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue)
+static int send_cmd_write_uart_register(struct edgeport_port *edge_port,
+ __u8 regNum, __u8 regValue)
{
- struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial);
+ struct edgeport_serial *edge_serial =
+ usb_get_serial_data(edge_port->port->serial);
unsigned char *cmdBuffer;
unsigned char *currCmd;
unsigned long cmdLen = 0;
int status;
- dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __func__, regValue);
+ dbg("%s - write to %s register 0x%02x",
+ (regNum == MCR) ? "MCR" : "LCR", __func__, regValue);
if (edge_serial->is_epic &&
!edge_serial->epic_descriptor.Supports.IOSPWriteMCR &&
@@ -2441,27 +2558,26 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
if (edge_serial->is_epic &&
!edge_serial->epic_descriptor.Supports.IOSPWriteLCR &&
regNum == LCR) {
- dbg ("SendCmdWriteUartReg - Not writing to LCR Register");
+ dbg("SendCmdWriteUartReg - Not writing to LCR Register");
return 0;
}
- // Alloc memory for the string of commands.
- cmdBuffer = kmalloc (0x10, GFP_ATOMIC);
- if (cmdBuffer == NULL ) {
+ /* Alloc memory for the string of commands. */
+ cmdBuffer = kmalloc(0x10, GFP_ATOMIC);
+ if (cmdBuffer == NULL)
return -ENOMEM;
- }
currCmd = cmdBuffer;
- // Build a cmd in the buffer to write the given register
- MAKE_CMD_WRITE_REG (&currCmd, &cmdLen,
- edge_port->port->number - edge_port->port->serial->minor,
- regNum, regValue);
+ /* Build a cmd in the buffer to write the given register */
+ MAKE_CMD_WRITE_REG(&currCmd, &cmdLen,
+ edge_port->port->number - edge_port->port->serial->minor,
+ regNum, regValue);
status = write_cmd_usb(edge_port, cmdBuffer, cmdLen);
if (status) {
/* something bad happened, let's free up the memory */
- kfree (cmdBuffer);
+ kfree(cmdBuffer);
}
return status;
@@ -2470,16 +2586,15 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
/*****************************************************************************
* change_port_settings
- * This routine is called to set the UART on the device to match the specified
- * new settings.
+ * This routine is called to set the UART on the device to match the
+ * specified new settings.
*****************************************************************************/
-#ifndef CMSPAR
-#define CMSPAR 0
-#endif
-static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios)
+
+static void change_port_settings(struct tty_struct *tty,
+ struct edgeport_port *edge_port, struct ktermios *old_termios)
{
- struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial);
- struct tty_struct *tty;
+ struct edgeport_serial *edge_serial =
+ usb_get_serial_data(edge_port->port->serial);
int baud;
unsigned cflag;
__u8 mask = 0xff;
@@ -2498,21 +2613,26 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
return;
}
- tty = edge_port->port->tty;
- if ((!tty) ||
- (!tty->termios)) {
- dbg("%s - no tty structures", __func__);
- return;
- }
-
cflag = tty->termios->c_cflag;
switch (cflag & CSIZE) {
- case CS5: lData = LCR_BITS_5; mask = 0x1f; dbg("%s - data bits = 5", __func__); break;
- case CS6: lData = LCR_BITS_6; mask = 0x3f; dbg("%s - data bits = 6", __func__); break;
- case CS7: lData = LCR_BITS_7; mask = 0x7f; dbg("%s - data bits = 7", __func__); break;
- default:
- case CS8: lData = LCR_BITS_8; dbg("%s - data bits = 8", __func__); break;
+ case CS5:
+ lData = LCR_BITS_5; mask = 0x1f;
+ dbg("%s - data bits = 5", __func__);
+ break;
+ case CS6:
+ lData = LCR_BITS_6; mask = 0x3f;
+ dbg("%s - data bits = 6", __func__);
+ break;
+ case CS7:
+ lData = LCR_BITS_7; mask = 0x7f;
+ dbg("%s - data bits = 7", __func__);
+ break;
+ default:
+ case CS8:
+ lData = LCR_BITS_8;
+ dbg("%s - data bits = 8", __func__);
+ break;
}
lParity = LCR_PAR_NONE;
@@ -2554,7 +2674,8 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
dbg("%s - RTS/CTS is disabled", __func__);
}
- /* if we are implementing XON/XOFF, set the start and stop character in the device */
+ /* if we are implementing XON/XOFF, set the start and stop character
+ in the device */
if (I_IXOFF(tty) || I_IXON(tty)) {
unsigned char stop_char = STOP_CHAR(tty);
unsigned char start_char = START_CHAR(tty);
@@ -2562,14 +2683,17 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
if ((!edge_serial->is_epic) ||
((edge_serial->is_epic) &&
(edge_serial->epic_descriptor.Supports.IOSPSetXChar))) {
- send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_XON_CHAR, start_char);
- send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char);
+ send_iosp_ext_cmd(edge_port,
+ IOSP_CMD_SET_XON_CHAR, start_char);
+ send_iosp_ext_cmd(edge_port,
+ IOSP_CMD_SET_XOFF_CHAR, stop_char);
}
/* if we are implementing INBOUND XON/XOFF */
if (I_IXOFF(tty)) {
rxFlow |= IOSP_RX_FLOW_XON_XOFF;
- dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __func__, start_char, stop_char);
+ dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+ __func__, start_char, stop_char);
} else {
dbg("%s - INBOUND XON/XOFF is disabled", __func__);
}
@@ -2577,7 +2701,8 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
/* if we are implementing OUTBOUND XON/XOFF */
if (I_IXON(tty)) {
txFlow |= IOSP_TX_FLOW_XON_XOFF;
- dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __func__, start_char, stop_char);
+ dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+ __func__, start_char, stop_char);
} else {
dbg("%s - OUTBOUND XON/XOFF is disabled", __func__);
}
@@ -2600,20 +2725,20 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
edge_port->validDataMask = mask;
/* Send the updated LCR value to the EdgePort */
- status = send_cmd_write_uart_register(edge_port, LCR, edge_port->shadowLCR);
- if (status != 0) {
+ status = send_cmd_write_uart_register(edge_port, LCR,
+ edge_port->shadowLCR);
+ if (status != 0)
return;
- }
/* set up the MCR register and send it to the EdgePort */
edge_port->shadowMCR = MCR_MASTER_IE;
- if (cflag & CBAUD) {
+ if (cflag & CBAUD)
edge_port->shadowMCR |= (MCR_DTR | MCR_RTS);
- }
- status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);
- if (status != 0) {
+
+ status = send_cmd_write_uart_register(edge_port, MCR,
+ edge_port->shadowMCR);
+ if (status != 0)
return;
- }
/* Determine divisor based on baud rate */
baud = tty_get_baud_rate(tty);
@@ -2623,7 +2748,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
}
dbg("%s - baud rate = %d", __func__, baud);
- status = send_cmd_write_baud_rate (edge_port, baud);
+ status = send_cmd_write_baud_rate(edge_port, baud);
if (status == -1) {
/* Speed change was not possible - put back the old speed */
baud = tty_termios_baud_rate(old_termios);
@@ -2640,7 +2765,8 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
* ASCII range, but it's only for debugging...
* NOTE: expects the unicode in LE format
****************************************************************************/
-static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size)
+static void unicode_to_ascii(char *string, int buflen,
+ __le16 *unicode, int unicode_size)
{
int i;
@@ -2659,75 +2785,99 @@ static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unic
/****************************************************************************
* get_manufacturing_desc
- * reads in the manufacturing descriptor and stores it into the serial
+ * reads in the manufacturing descriptor and stores it into the serial
* structure.
****************************************************************************/
-static void get_manufacturing_desc (struct edgeport_serial *edge_serial)
+static void get_manufacturing_desc(struct edgeport_serial *edge_serial)
{
int response;
dbg("getting manufacturer descriptor");
- response = rom_read (edge_serial->serial, (EDGE_MANUF_DESC_ADDR & 0xffff0000) >> 16,
- (__u16)(EDGE_MANUF_DESC_ADDR & 0x0000ffff), EDGE_MANUF_DESC_LEN,
- (__u8 *)(&edge_serial->manuf_descriptor));
+ response = rom_read(edge_serial->serial,
+ (EDGE_MANUF_DESC_ADDR & 0xffff0000) >> 16,
+ (__u16)(EDGE_MANUF_DESC_ADDR & 0x0000ffff),
+ EDGE_MANUF_DESC_LEN,
+ (__u8 *)(&edge_serial->manuf_descriptor));
- if (response < 1) {
- dev_err(&edge_serial->serial->dev->dev, "error in getting manufacturer descriptor\n");
- } else {
+ if (response < 1)
+ dev_err(&edge_serial->serial->dev->dev,
+ "error in getting manufacturer descriptor\n");
+ else {
char string[30];
dbg("**Manufacturer Descriptor");
- dbg(" RomSize: %dK", edge_serial->manuf_descriptor.RomSize);
- dbg(" RamSize: %dK", edge_serial->manuf_descriptor.RamSize);
- dbg(" CpuRev: %d", edge_serial->manuf_descriptor.CpuRev);
- dbg(" BoardRev: %d", edge_serial->manuf_descriptor.BoardRev);
- dbg(" NumPorts: %d", edge_serial->manuf_descriptor.NumPorts);
- dbg(" DescDate: %d/%d/%d", edge_serial->manuf_descriptor.DescDate[0], edge_serial->manuf_descriptor.DescDate[1], edge_serial->manuf_descriptor.DescDate[2]+1900);
+ dbg(" RomSize: %dK",
+ edge_serial->manuf_descriptor.RomSize);
+ dbg(" RamSize: %dK",
+ edge_serial->manuf_descriptor.RamSize);
+ dbg(" CpuRev: %d",
+ edge_serial->manuf_descriptor.CpuRev);
+ dbg(" BoardRev: %d",
+ edge_serial->manuf_descriptor.BoardRev);
+ dbg(" NumPorts: %d",
+ edge_serial->manuf_descriptor.NumPorts);
+ dbg(" DescDate: %d/%d/%d",
+ edge_serial->manuf_descriptor.DescDate[0],
+ edge_serial->manuf_descriptor.DescDate[1],
+ edge_serial->manuf_descriptor.DescDate[2]+1900);
unicode_to_ascii(string, sizeof(string),
- edge_serial->manuf_descriptor.SerialNumber,
- edge_serial->manuf_descriptor.SerNumLength/2);
+ edge_serial->manuf_descriptor.SerialNumber,
+ edge_serial->manuf_descriptor.SerNumLength/2);
dbg(" SerialNumber: %s", string);
unicode_to_ascii(string, sizeof(string),
- edge_serial->manuf_descriptor.AssemblyNumber,
- edge_serial->manuf_descriptor.AssemblyNumLength/2);
+ edge_serial->manuf_descriptor.AssemblyNumber,
+ edge_serial->manuf_descriptor.AssemblyNumLength/2);
dbg(" AssemblyNumber: %s", string);
unicode_to_ascii(string, sizeof(string),
edge_serial->manuf_descriptor.OemAssyNumber,
edge_serial->manuf_descriptor.OemAssyNumLength/2);
dbg(" OemAssyNumber: %s", string);
- dbg(" UartType: %d", edge_serial->manuf_descriptor.UartType);
- dbg(" IonPid: %d", edge_serial->manuf_descriptor.IonPid);
- dbg(" IonConfig: %d", edge_serial->manuf_descriptor.IonConfig);
+ dbg(" UartType: %d",
+ edge_serial->manuf_descriptor.UartType);
+ dbg(" IonPid: %d",
+ edge_serial->manuf_descriptor.IonPid);
+ dbg(" IonConfig: %d",
+ edge_serial->manuf_descriptor.IonConfig);
}
}
/****************************************************************************
* get_boot_desc
- * reads in the bootloader descriptor and stores it into the serial
+ * reads in the bootloader descriptor and stores it into the serial
* structure.
****************************************************************************/
-static void get_boot_desc (struct edgeport_serial *edge_serial)
+static void get_boot_desc(struct edgeport_serial *edge_serial)
{
int response;
dbg("getting boot descriptor");
- response = rom_read (edge_serial->serial, (EDGE_BOOT_DESC_ADDR & 0xffff0000) >> 16,
- (__u16)(EDGE_BOOT_DESC_ADDR & 0x0000ffff), EDGE_BOOT_DESC_LEN,
- (__u8 *)(&edge_serial->boot_descriptor));
+ response = rom_read(edge_serial->serial,
+ (EDGE_BOOT_DESC_ADDR & 0xffff0000) >> 16,
+ (__u16)(EDGE_BOOT_DESC_ADDR & 0x0000ffff),
+ EDGE_BOOT_DESC_LEN,
+ (__u8 *)(&edge_serial->boot_descriptor));
- if (response < 1) {
- dev_err(&edge_serial->serial->dev->dev, "error in getting boot descriptor\n");
- } else {
+ if (response < 1)
+ dev_err(&edge_serial->serial->dev->dev,
+ "error in getting boot descriptor\n");
+ else {
dbg("**Boot Descriptor:");
- dbg(" BootCodeLength: %d", le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength));
- dbg(" MajorVersion: %d", edge_serial->boot_descriptor.MajorVersion);
- dbg(" MinorVersion: %d", edge_serial->boot_descriptor.MinorVersion);
- dbg(" BuildNumber: %d", le16_to_cpu(edge_serial->boot_descriptor.BuildNumber));
- dbg(" Capabilities: 0x%x", le16_to_cpu(edge_serial->boot_descriptor.Capabilities));
- dbg(" UConfig0: %d", edge_serial->boot_descriptor.UConfig0);
- dbg(" UConfig1: %d", edge_serial->boot_descriptor.UConfig1);
+ dbg(" BootCodeLength: %d",
+ le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength));
+ dbg(" MajorVersion: %d",
+ edge_serial->boot_descriptor.MajorVersion);
+ dbg(" MinorVersion: %d",
+ edge_serial->boot_descriptor.MinorVersion);
+ dbg(" BuildNumber: %d",
+ le16_to_cpu(edge_serial->boot_descriptor.BuildNumber));
+ dbg(" Capabilities: 0x%x",
+ le16_to_cpu(edge_serial->boot_descriptor.Capabilities));
+ dbg(" UConfig0: %d",
+ edge_serial->boot_descriptor.UConfig0);
+ dbg(" UConfig1: %d",
+ edge_serial->boot_descriptor.UConfig1);
}
}
@@ -2736,7 +2886,7 @@ static void get_boot_desc (struct edgeport_serial *edge_serial)
* load_application_firmware
* This is called to load the application firmware to the device
****************************************************************************/
-static void load_application_firmware (struct edgeport_serial *edge_serial)
+static void load_application_firmware(struct edgeport_serial *edge_serial)
{
const struct ihex_binrec *rec;
const struct firmware *fw;
@@ -2813,7 +2963,7 @@ static void load_application_firmware (struct edgeport_serial *edge_serial)
/****************************************************************************
* edge_startup
****************************************************************************/
-static int edge_startup (struct usb_serial *serial)
+static int edge_startup(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial;
struct edgeport_port *edge_port;
@@ -2855,10 +3005,10 @@ static int edge_startup (struct usb_serial *serial)
sizeof(struct edge_compatibility_bits));
/* get the manufacturing descriptor for this device */
- get_manufacturing_desc (edge_serial);
+ get_manufacturing_desc(edge_serial);
/* get the boot descriptor */
- get_boot_desc (edge_serial);
+ get_boot_desc(edge_serial);
get_product_info(edge_serial);
}
@@ -2879,41 +3029,43 @@ static int edge_startup (struct usb_serial *serial)
/* If not an EPiC device */
if (!edge_serial->is_epic) {
/* now load the application firmware into this device */
- load_application_firmware (edge_serial);
+ load_application_firmware(edge_serial);
dbg("%s - time 2 %ld", __func__, jiffies);
/* Check current Edgeport EEPROM and update if necessary */
- update_edgeport_E2PROM (edge_serial);
+ update_edgeport_E2PROM(edge_serial);
dbg("%s - time 3 %ld", __func__, jiffies);
/* set the configuration to use #1 */
-// dbg("set_configuration 1");
-// usb_set_configuration (dev, 1);
+/* dbg("set_configuration 1"); */
+/* usb_set_configuration (dev, 1); */
}
dbg(" FirmwareMajorVersion %d.%d.%d",
edge_serial->product_info.FirmwareMajorVersion,
edge_serial->product_info.FirmwareMinorVersion,
le16_to_cpu(edge_serial->product_info.FirmwareBuildNumber));
- /* we set up the pointers to the endpoints in the edge_open function,
+ /* we set up the pointers to the endpoints in the edge_open function,
* as the structures aren't created yet. */
/* set up our port private structures */
for (i = 0; i < serial->num_ports; ++i) {
- edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL);
+ edge_port = kmalloc(sizeof(struct edgeport_port), GFP_KERNEL);
if (edge_port == NULL) {
- dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ dev_err(&serial->dev->dev, "%s - Out of memory\n",
+ __func__);
for (j = 0; j < i; ++j) {
- kfree (usb_get_serial_port_data(serial->port[j]));
- usb_set_serial_port_data(serial->port[j], NULL);
+ kfree(usb_get_serial_port_data(serial->port[j]));
+ usb_set_serial_port_data(serial->port[j],
+ NULL);
}
usb_set_serial_data(serial, NULL);
kfree(edge_serial);
return -ENOMEM;
}
- memset (edge_port, 0, sizeof(struct edgeport_port));
+ memset(edge_port, 0, sizeof(struct edgeport_port));
spin_lock_init(&edge_port->ep_lock);
edge_port->port = serial->port[i];
usb_set_serial_port_data(serial->port[i], edge_port);
@@ -2922,14 +3074,16 @@ static int edge_startup (struct usb_serial *serial)
response = 0;
if (edge_serial->is_epic) {
- /* EPIC thing, set up our interrupt polling now and our read urb, so
- * that the device knows it really is connected. */
+ /* EPIC thing, set up our interrupt polling now and our read
+ * urb, so that the device knows it really is connected. */
interrupt_in_found = bulk_in_found = bulk_out_found = false;
- for (i = 0; i < serial->interface->altsetting[0].desc.bNumEndpoints; ++i) {
+ for (i = 0; i < serial->interface->altsetting[0]
+ .desc.bNumEndpoints; ++i) {
struct usb_endpoint_descriptor *endpoint;
int buffer_size;
- endpoint = &serial->interface->altsetting[0].endpoint[i].desc;
+ endpoint = &serial->interface->altsetting[0].
+ endpoint[i].desc;
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
if (!interrupt_in_found &&
(usb_endpoint_is_int_in(endpoint))) {
@@ -2937,58 +3091,67 @@ static int edge_startup (struct usb_serial *serial)
dbg("found interrupt in");
/* not set up yet, so do it now */
- edge_serial->interrupt_read_urb = usb_alloc_urb(0, GFP_KERNEL);
+ edge_serial->interrupt_read_urb =
+ usb_alloc_urb(0, GFP_KERNEL);
if (!edge_serial->interrupt_read_urb) {
err("out of memory");
return -ENOMEM;
}
- edge_serial->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+ edge_serial->interrupt_in_buffer =
+ kmalloc(buffer_size, GFP_KERNEL);
if (!edge_serial->interrupt_in_buffer) {
err("out of memory");
usb_free_urb(edge_serial->interrupt_read_urb);
return -ENOMEM;
}
- edge_serial->interrupt_in_endpoint = endpoint->bEndpointAddress;
+ edge_serial->interrupt_in_endpoint =
+ endpoint->bEndpointAddress;
/* set up our interrupt urb */
- usb_fill_int_urb(edge_serial->interrupt_read_urb,
- dev,
- usb_rcvintpipe(dev, endpoint->bEndpointAddress),
- edge_serial->interrupt_in_buffer,
- buffer_size,
- edge_interrupt_callback,
- edge_serial,
- endpoint->bInterval);
+ usb_fill_int_urb(
+ edge_serial->interrupt_read_urb,
+ dev,
+ usb_rcvintpipe(dev,
+ endpoint->bEndpointAddress),
+ edge_serial->interrupt_in_buffer,
+ buffer_size,
+ edge_interrupt_callback,
+ edge_serial,
+ endpoint->bInterval);
interrupt_in_found = true;
}
if (!bulk_in_found &&
- (usb_endpoint_is_bulk_in(endpoint))) {
+ (usb_endpoint_is_bulk_in(endpoint))) {
/* we found a bulk in endpoint */
dbg("found bulk in");
/* not set up yet, so do it now */
- edge_serial->read_urb = usb_alloc_urb(0, GFP_KERNEL);
+ edge_serial->read_urb =
+ usb_alloc_urb(0, GFP_KERNEL);
if (!edge_serial->read_urb) {
err("out of memory");
return -ENOMEM;
}
- edge_serial->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+ edge_serial->bulk_in_buffer =
+ kmalloc(buffer_size, GFP_KERNEL);
if (!edge_serial->bulk_in_buffer) {
- err ("out of memory");
+ err("out of memory");
usb_free_urb(edge_serial->read_urb);
return -ENOMEM;
}
- edge_serial->bulk_in_endpoint = endpoint->bEndpointAddress;
+ edge_serial->bulk_in_endpoint =
+ endpoint->bEndpointAddress;
/* set up our bulk in urb */
usb_fill_bulk_urb(edge_serial->read_urb, dev,
- usb_rcvbulkpipe(dev, endpoint->bEndpointAddress),
- edge_serial->bulk_in_buffer,
- le16_to_cpu(endpoint->wMaxPacketSize),
- edge_bulk_in_callback,
- edge_serial);
+ usb_rcvbulkpipe(dev,
+ endpoint->bEndpointAddress),
+ edge_serial->bulk_in_buffer,
+ le16_to_cpu(endpoint->wMaxPacketSize),
+ edge_bulk_in_callback,
+ edge_serial);
bulk_in_found = true;
}
@@ -2996,21 +3159,24 @@ static int edge_startup (struct usb_serial *serial)
(usb_endpoint_is_bulk_out(endpoint))) {
/* we found a bulk out endpoint */
dbg("found bulk out");
- edge_serial->bulk_out_endpoint = endpoint->bEndpointAddress;
+ edge_serial->bulk_out_endpoint =
+ endpoint->bEndpointAddress;
bulk_out_found = true;
}
}
if (!interrupt_in_found || !bulk_in_found || !bulk_out_found) {
- err ("Error - the proper endpoints were not found!");
+ err("Error - the proper endpoints were not found!");
return -ENODEV;
}
/* start interrupt read for this edgeport this interrupt will
* continue as long as the edgeport is connected */
- response = usb_submit_urb(edge_serial->interrupt_read_urb, GFP_KERNEL);
+ response = usb_submit_urb(edge_serial->interrupt_read_urb,
+ GFP_KERNEL);
if (response)
- err("%s - Error %d submitting control urb", __func__, response);
+ err("%s - Error %d submitting control urb",
+ __func__, response);
}
return response;
}
@@ -3020,7 +3186,7 @@ static int edge_startup (struct usb_serial *serial)
* edge_shutdown
* This function is called whenever the device is removed from the usb bus.
****************************************************************************/
-static void edge_shutdown (struct usb_serial *serial)
+static void edge_shutdown(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
int i;
@@ -3028,8 +3194,8 @@ static void edge_shutdown (struct usb_serial *serial)
dbg("%s", __func__);
/* stop reads and writes on all ports */
- for (i=0; i < serial->num_ports; ++i) {
- kfree (usb_get_serial_port_data(serial->port[i]));
+ for (i = 0; i < serial->num_ports; ++i) {
+ kfree(usb_get_serial_port_data(serial->port[i]));
usb_set_serial_port_data(serial->port[i], NULL);
}
/* free up our endpoint stuff */
@@ -3069,7 +3235,7 @@ static int __init edgeport_init(void)
if (retval)
goto failed_epic_device_register;
retval = usb_register(&io_driver);
- if (retval)
+ if (retval)
goto failed_usb_register;
atomic_set(&CmdUrbs, 0);
info(DRIVER_DESC " " DRIVER_VERSION);
@@ -3094,19 +3260,19 @@ failed_2port_device_register:
****************************************************************************/
static void __exit edgeport_exit (void)
{
- usb_deregister (&io_driver);
- usb_serial_deregister (&edgeport_2port_device);
- usb_serial_deregister (&edgeport_4port_device);
- usb_serial_deregister (&edgeport_8port_device);
- usb_serial_deregister (&epic_device);
+ usb_deregister(&io_driver);
+ usb_serial_deregister(&edgeport_2port_device);
+ usb_serial_deregister(&edgeport_4port_device);
+ usb_serial_deregister(&edgeport_8port_device);
+ usb_serial_deregister(&epic_device);
}
module_init(edgeport_init);
module_exit(edgeport_exit);
/* Module information */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("edgeport/boot.fw");
MODULE_FIRMWARE("edgeport/boot2.fw");
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index 2ec85893f27..7eb9d67b81b 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -8,7 +8,7 @@
* 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.
- *
+ *
*/
#ifndef IO_TABLES_H
@@ -90,10 +90,10 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A758) },
{ USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A794) },
{ USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A225) },
- { } /* Terminating entry */
+ { } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver io_driver = {
.name = "io_edgeport",
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index a58822a14a8..cb4c54316cf 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -243,9 +243,9 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
static void stop_read(struct edgeport_port *edge_port);
static int restart_read(struct edgeport_port *edge_port);
-static void edge_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios);
-static void edge_send(struct usb_serial_port *port);
+static void edge_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios);
+static void edge_send(struct tty_struct *tty);
/* sysfs attributes */
static int edge_create_sysfs_attrs(struct usb_serial_port *port);
@@ -572,7 +572,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
int flush)
{
int baud_rate;
- struct tty_struct *tty = port->port->tty;
+ struct tty_struct *tty = port->port->port.tty;
wait_queue_t wait;
unsigned long flags;
@@ -1554,7 +1554,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
/* Save the new modem status */
edge_port->shadow_msr = msr & 0xf0;
- tty = edge_port->port->tty;
+ tty = edge_port->port->port.tty;
/* handle CTS flow control */
if (tty && C_CRTSCTS(tty)) {
if (msr & EDGEPORT_MSR_CTS) {
@@ -1587,9 +1587,8 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK);
/* Place LSR data byte into Rx buffer */
- if (lsr_data && edge_port->port->tty)
- edge_tty_recv(&edge_port->port->dev, edge_port->port->tty,
- &data, 1);
+ if (lsr_data && edge_port->port->port.tty)
+ edge_tty_recv(&edge_port->port->dev, edge_port->port->port.tty, &data, 1);
/* update input line counters */
icount = &edge_port->icount;
@@ -1750,7 +1749,7 @@ static void edge_bulk_in_callback(struct urb *urb)
++data;
}
- tty = edge_port->port->tty;
+ tty = edge_port->port->port.tty;
if (tty && urb->actual_length) {
usb_serial_debug_data(debug, &edge_port->port->dev,
__func__, urb->actual_length, data);
@@ -1819,10 +1818,11 @@ static void edge_bulk_out_callback(struct urb *urb)
}
/* send any buffered data */
- edge_send(port);
+ edge_send(port->port.tty);
}
-static int edge_open(struct usb_serial_port *port, struct file *filp)
+static int edge_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct edgeport_serial *edge_serial;
@@ -1838,7 +1838,8 @@ static int edge_open(struct usb_serial_port *port, struct file *filp)
if (edge_port == NULL)
return -ENODEV;
- port->tty->low_latency = low_latency;
+ if (tty)
+ tty->low_latency = low_latency;
port_number = port->number - port->serial->minor;
switch (port_number) {
@@ -1874,7 +1875,8 @@ static int edge_open(struct usb_serial_port *port, struct file *filp)
}
/* set up the port settings */
- edge_set_termios(port, port->tty->termios);
+ if (tty)
+ edge_set_termios(tty, port, port->port.tty->termios);
/* open up the port */
@@ -2000,7 +2002,8 @@ release_es_lock:
return status;
}
-static void edge_close(struct usb_serial_port *port, struct file *filp)
+static void edge_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct edgeport_serial *edge_serial;
struct edgeport_port *edge_port;
@@ -2048,8 +2051,8 @@ static void edge_close(struct usb_serial_port *port, struct file *filp)
dbg("%s - exited", __func__);
}
-static int edge_write(struct usb_serial_port *port, const unsigned char *data,
- int count)
+static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *data, int count)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned long flags;
@@ -2070,16 +2073,16 @@ static int edge_write(struct usb_serial_port *port, const unsigned char *data,
count = edge_buf_put(edge_port->ep_out_buf, data, count);
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
- edge_send(port);
+ edge_send(tty);
return count;
}
-static void edge_send(struct usb_serial_port *port)
+static void edge_send(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int count, result;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
unsigned long flags;
@@ -2133,8 +2136,9 @@ static void edge_send(struct usb_serial_port *port)
tty_wakeup(tty);
}
-static int edge_write_room(struct usb_serial_port *port)
+static int edge_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int room = 0;
unsigned long flags;
@@ -2154,8 +2158,9 @@ static int edge_write_room(struct usb_serial_port *port)
return room;
}
-static int edge_chars_in_buffer(struct usb_serial_port *port)
+static int edge_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int chars = 0;
unsigned long flags;
@@ -2175,10 +2180,10 @@ static int edge_chars_in_buffer(struct usb_serial_port *port)
return chars;
}
-static void edge_throttle(struct usb_serial_port *port)
+static void edge_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
int status;
dbg("%s - port %d", __func__, port->number);
@@ -2189,11 +2194,10 @@ static void edge_throttle(struct usb_serial_port *port)
/* if we are implementing XON/XOFF, send the stop character */
if (I_IXOFF(tty)) {
unsigned char stop_char = STOP_CHAR(tty);
- status = edge_write(port, &stop_char, 1);
- if (status <= 0)
- dev_err(&port->dev,
- "%s - failed to write stop character, %d\n",
- __func__, status);
+ status = edge_write(tty, port, &stop_char, 1);
+ if (status <= 0) {
+ dev_err(&port->dev, "%s - failed to write stop character, %d\n", __func__, status);
+ }
}
/* if we are implementing RTS/CTS, stop reads */
@@ -2203,10 +2207,10 @@ static void edge_throttle(struct usb_serial_port *port)
}
-static void edge_unthrottle(struct usb_serial_port *port)
+static void edge_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
int status;
dbg("%s - port %d", __func__, port->number);
@@ -2217,11 +2221,10 @@ static void edge_unthrottle(struct usb_serial_port *port)
/* if we are implementing XON/XOFF, send the start character */
if (I_IXOFF(tty)) {
unsigned char start_char = START_CHAR(tty);
- status = edge_write(port, &start_char, 1);
- if (status <= 0)
- dev_err(&port->dev,
- "%s - failed to write start character, %d\n",
- __func__, status);
+ status = edge_write(tty, port, &start_char, 1);
+ if (status <= 0) {
+ dev_err(&port->dev, "%s - failed to write start character, %d\n", __func__, status);
+ }
}
/* if we are implementing RTS/CTS, restart reads */
/* are the Edgeport will assert the RTS line */
@@ -2271,11 +2274,10 @@ static int restart_read(struct edgeport_port *edge_port)
return status;
}
-static void change_port_settings(struct edgeport_port *edge_port,
- struct ktermios *old_termios)
+static void change_port_settings(struct tty_struct *tty,
+ struct edgeport_port *edge_port, struct ktermios *old_termios)
{
struct ump_uart_config *config;
- struct tty_struct *tty;
int baud;
unsigned cflag;
int status;
@@ -2284,9 +2286,7 @@ static void change_port_settings(struct edgeport_port *edge_port,
dbg("%s - port %d", __func__, edge_port->port->number);
- tty = edge_port->port->tty;
-
- config = kmalloc(sizeof(*config), GFP_KERNEL);
+ config = kmalloc (sizeof (*config), GFP_KERNEL);
if (!config) {
*tty->termios = *old_termios;
dev_err(&edge_port->port->dev, "%s - out of memory\n",
@@ -2419,11 +2419,13 @@ static void change_port_settings(struct edgeport_port *edge_port,
return;
}
-static void edge_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void edge_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
+ unsigned int cflag;
+
+ cflag = tty->termios->c_cflag;
dbg("%s - clfag %08x iflag %08x", __func__,
tty->termios->c_cflag, tty->termios->c_iflag);
@@ -2434,12 +2436,14 @@ static void edge_set_termios(struct usb_serial_port *port,
if (edge_port == NULL)
return;
/* change the port settings to the new ones specified */
- change_port_settings(edge_port, old_termios);
+ change_port_settings(tty, edge_port, old_termios);
+ return;
}
-static int edge_tiocmset(struct usb_serial_port *port, struct file *file,
+static int edge_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int mcr;
unsigned long flags;
@@ -2469,8 +2473,9 @@ static int edge_tiocmset(struct usb_serial_port *port, struct file *file,
return 0;
}
-static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
+static int edge_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int result = 0;
unsigned int msr;
@@ -2522,9 +2527,10 @@ static int get_serial_info(struct edgeport_port *edge_port,
return 0;
}
-static int edge_ioctl(struct usb_serial_port *port, struct file *file,
+static int edge_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct async_icount cnow;
struct async_icount cprev;
@@ -2569,18 +2575,19 @@ static int edge_ioctl(struct usb_serial_port *port, struct file *file,
return -ENOIOCTLCMD;
}
-static void edge_break(struct usb_serial_port *port, int on)
+static void edge_break(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int status;
int bv = 0; /* Off */
- dbg("%s - state = %d", __func__, on);
+ dbg("%s - state = %d", __func__, break_state);
/* chase the port close */
chase_port(edge_port, 0, 0);
- if (on == -1)
+ if (break_state == -1)
bv = 1; /* On */
status = ti_do_config(edge_port, UMPC_SET_CLR_BREAK, bv);
if (status)
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 80d9ec5570d..832a5a4f3cb 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -53,7 +53,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include "ipaq.h"
@@ -74,19 +74,21 @@ static int connect_retries = KP_RETRIES;
static int initial_wait;
/* Function prototypes for an ipaq */
-static int ipaq_open (struct usb_serial_port *port, struct file *filp);
-static void ipaq_close (struct usb_serial_port *port, struct file *filp);
-static int ipaq_startup (struct usb_serial *serial);
-static void ipaq_shutdown (struct usb_serial *serial);
-static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf,
- int count);
-static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *buf,
- int count);
+static int ipaq_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void ipaq_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static int ipaq_startup(struct usb_serial *serial);
+static void ipaq_shutdown(struct usb_serial *serial);
+static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+static int ipaq_write_bulk(struct usb_serial_port *port,
+ const unsigned char *buf, int count);
static void ipaq_write_gather(struct usb_serial_port *port);
-static void ipaq_read_bulk_callback (struct urb *urb);
+static void ipaq_read_bulk_callback(struct urb *urb);
static void ipaq_write_bulk_callback(struct urb *urb);
-static int ipaq_write_room(struct usb_serial_port *port);
-static int ipaq_chars_in_buffer(struct usb_serial_port *port);
+static int ipaq_write_room(struct tty_struct *tty);
+static int ipaq_chars_in_buffer(struct tty_struct *tty);
static void ipaq_destroy_lists(struct usb_serial_port *port);
@@ -550,7 +552,7 @@ static struct usb_device_id ipaq_id_table [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, ipaq_id_table);
+MODULE_DEVICE_TABLE(usb, ipaq_id_table);
static struct usb_driver ipaq_driver = {
.name = "ipaq",
@@ -591,7 +593,8 @@ static spinlock_t write_list_lock;
static int bytes_in;
static int bytes_out;
-static int ipaq_open(struct usb_serial_port *port, struct file *filp)
+static int ipaq_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
struct ipaq_private *priv;
@@ -617,9 +620,9 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
for (i = 0; i < URBDATA_QUEUE_MAX / PACKET_SIZE; i++) {
pkt = kmalloc(sizeof(struct ipaq_packet), GFP_KERNEL);
- if (pkt == NULL) {
+ if (pkt == NULL)
goto enomem;
- }
+
pkt->data = kmalloc(PACKET_SIZE, GFP_KERNEL);
if (pkt->data == NULL) {
kfree(pkt);
@@ -637,10 +640,12 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
* discipline instead of queueing.
*/
- port->tty->low_latency = 1;
- port->tty->raw = 1;
- port->tty->real_raw = 1;
-
+ if (tty) {
+ tty->low_latency = 1;
+ /* FIXME: These two are bogus */
+ tty->raw = 1;
+ tty->real_raw = 1;
+ }
/*
* Lose the small buffers usbserial provides. Make larger ones.
*/
@@ -662,8 +667,9 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
port->read_urb->transfer_buffer = port->bulk_in_buffer;
port->write_urb->transfer_buffer = port->bulk_out_buffer;
port->read_urb->transfer_buffer_length = URBDATA_SIZE;
- port->bulk_out_size = port->write_urb->transfer_buffer_length = URBDATA_SIZE;
-
+ port->bulk_out_size = port->write_urb->transfer_buffer_length
+ = URBDATA_SIZE;
+
msleep(1000*initial_wait);
/*
@@ -692,13 +698,15 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
/* Start reading from the device */
usb_fill_bulk_urb(port->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
- ipaq_read_bulk_callback, port);
+ usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ ipaq_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result) {
- err("%s - failed submitting read urb, error %d", __func__, result);
+ err("%s - failed submitting read urb, error %d",
+ __func__, result);
goto error;
}
@@ -714,12 +722,13 @@ error:
}
-static void ipaq_close(struct usb_serial_port *port, struct file *filp)
+static void ipaq_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct ipaq_private *priv = usb_get_serial_port_data(port);
dbg("%s - port %d", __func__, port->number);
-
+
/*
* shut down bulk read and write
*/
@@ -729,7 +738,8 @@ static void ipaq_close(struct usb_serial_port *port, struct file *filp)
kfree(priv);
usb_set_serial_port_data(port, NULL);
- /* Uncomment the following line if you want to see some statistics in your syslog */
+ /* Uncomment the following line if you want to see some statistics
+ * in your syslog */
/* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */
}
@@ -749,9 +759,10 @@ static void ipaq_read_bulk_callback(struct urb *urb)
return;
}
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
@@ -760,18 +771,20 @@ static void ipaq_read_bulk_callback(struct urb *urb)
}
/* Continue trying to always read */
- 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,
- ipaq_read_bulk_callback, port);
+ 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,
+ ipaq_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d", __func__, result);
+ err("%s - failed resubmitting read urb, error %d",
+ __func__, result);
return;
}
-static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf,
- int count)
+static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
const unsigned char *current_position = buf;
int bytes_sent = 0;
@@ -781,9 +794,8 @@ static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf,
while (count > 0) {
transfer_size = min(count, PACKET_SIZE);
- if (ipaq_write_bulk(port, current_position, transfer_size)) {
+ if (ipaq_write_bulk(port, current_position, transfer_size))
break;
- }
current_position += transfer_size;
bytes_sent += transfer_size;
count -= transfer_size;
@@ -791,10 +803,10 @@ static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf,
}
return bytes_sent;
-}
+}
-static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *buf,
- int count)
+static int ipaq_write_bulk(struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct ipaq_private *priv = usb_get_serial_port_data(port);
struct ipaq_packet *pkt = NULL;
@@ -831,9 +843,9 @@ static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *bu
ipaq_write_gather(port);
spin_unlock_irqrestore(&write_list_lock, flags);
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
- if (result) {
- err("%s - failed submitting write urb, error %d", __func__, result);
- }
+ if (result)
+ err("%s - failed submitting write urb, error %d",
+ __func__, result);
} else {
spin_unlock_irqrestore(&write_list_lock, flags);
}
@@ -860,16 +872,15 @@ static void ipaq_write_gather(struct usb_serial_port *port)
list_move(&pkt->list, &priv->freelist);
priv->free_len += PACKET_SIZE;
}
- if (room == 0) {
+ if (room == 0)
break;
- }
}
count = URBDATA_SIZE - room;
- usb_fill_bulk_urb(port->write_urb, serial->dev,
- usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
- port->write_urb->transfer_buffer, count, ipaq_write_bulk_callback,
- port);
+ usb_fill_bulk_urb(port->write_urb, serial->dev,
+ usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer, count,
+ ipaq_write_bulk_callback, port);
return;
}
@@ -894,9 +905,9 @@ static void ipaq_write_bulk_callback(struct urb *urb)
ipaq_write_gather(port);
spin_unlock_irqrestore(&write_list_lock, flags);
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
- if (result) {
- err("%s - failed submitting write urb, error %d", __func__, result);
- }
+ if (result)
+ err("%s - failed submitting write urb, error %d",
+ __func__, result);
} else {
priv->active = 0;
spin_unlock_irqrestore(&write_list_lock, flags);
@@ -905,16 +916,18 @@ static void ipaq_write_bulk_callback(struct urb *urb)
usb_serial_port_softint(port);
}
-static int ipaq_write_room(struct usb_serial_port *port)
+static int ipaq_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ipaq_private *priv = usb_get_serial_port_data(port);
dbg("%s - freelen %d", __func__, priv->free_len);
return priv->free_len;
}
-static int ipaq_chars_in_buffer(struct usb_serial_port *port)
+static int ipaq_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ipaq_private *priv = usb_get_serial_port_data(port);
dbg("%s - queuelen %d", __func__, priv->queue_len);
@@ -945,7 +958,7 @@ static int ipaq_startup(struct usb_serial *serial)
serial->dev->actconfig->desc.bConfigurationValue);
return -ENODEV;
}
- return usb_reset_configuration (serial->dev);
+ return usb_reset_configuration(serial->dev);
}
static void ipaq_shutdown(struct usb_serial *serial)
@@ -958,7 +971,7 @@ static int __init ipaq_init(void)
int retval;
spin_lock_init(&write_list_lock);
retval = usb_serial_register(&ipaq_device);
- if (retval)
+ if (retval)
goto failed_usb_serial_register;
info(DRIVER_DESC " " DRIVER_VERSION);
if (vendor) {
@@ -968,7 +981,7 @@ static int __init ipaq_init(void)
retval = usb_register(&ipaq_driver);
if (retval)
goto failed_usb_register;
-
+
return 0;
failed_usb_register:
usb_serial_deregister(&ipaq_device);
@@ -987,8 +1000,8 @@ static void __exit ipaq_exit(void)
module_init(ipaq_init);
module_exit(ipaq_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
@@ -1001,7 +1014,9 @@ module_param(product, ushort, 0);
MODULE_PARM_DESC(product, "User specified USB idProduct");
module_param(connect_retries, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(connect_retries, "Maximum number of connect retries (one second each)");
+MODULE_PARM_DESC(connect_retries,
+ "Maximum number of connect retries (one second each)");
module_param(initial_wait, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(initial_wait, "Time to wait before attempting a connection (in seconds)");
+MODULE_PARM_DESC(initial_wait,
+ "Time to wait before attempting a connection (in seconds)");
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index bc85ca5c1c3..a842025b9b5 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -10,27 +10,27 @@
* (at your option) any later version.
*
* All information about the device was acquired using SnoopyPro
- * on MSFT's O/S, and examing the MSFT drivers' debug output
+ * on MSFT's O/S, and examing the MSFT drivers' debug output
* (insanely left _on_ in the enduser version)
*
* It was written out of frustration with the IPWireless USB modem
* supplied by Axity3G/Sentech South Africa not supporting
* Linux whatsoever.
*
- * Nobody provided any proprietary information that was not already
+ * Nobody provided any proprietary information that was not already
* available for this device.
- *
- * The modem adheres to the "3GPP TS 27.007 AT command set for 3G
- * User Equipment (UE)" standard, available from
+ *
+ * The modem adheres to the "3GPP TS 27.007 AT command set for 3G
+ * User Equipment (UE)" standard, available from
* http://www.3gpp.org/ftp/Specs/html-info/27007.htm
*
* The code was only tested the IPWireless handheld modem distributed
* in South Africa by Sentech.
- *
+ *
* It may work for Woosh Inc in .nz too, as it appears they use the
* same kit.
*
- * There is still some work to be done in terms of handling
+ * There is still some work to be done in terms of handling
* DCD, DTR, RTS, CTS which are currently faked.
* It's good enough for PPP at this point. It's based off all kinds of
* code found in usb/serial and usb/class
@@ -47,7 +47,7 @@
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
/*
* Version Information
@@ -64,7 +64,7 @@
/* Message sizes */
#define EVENT_BUFFER_SIZE 0xFF
-#define CHAR2INT16(c1,c0) (((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff))
+#define CHAR2INT16(c1, c0) (((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff))
#define NUM_BULK_URBS 24
#define NUM_CONTROL_URBS 16
@@ -94,33 +94,34 @@ enum {
/* data bits */
#define ipw_dtb_7 0x700
-#define ipw_dtb_8 0x810 // ok so the define is misleading, I know, but forces 8,n,1
- // I mean, is there a point to any other setting these days? :)
+#define ipw_dtb_8 0x810 /* ok so the define is misleading, I know, but forces 8,n,1 */
+ /* I mean, is there a point to any other setting these days? :) */
/* usb control request types : */
-#define IPW_SIO_RXCTL 0x00 // control bulk rx channel transmissions, value=1/0 (on/off)
-#define IPW_SIO_SET_BAUD 0x01 // set baud, value=requested ipw_sio_bxxxx
-#define IPW_SIO_SET_LINE 0x03 // set databits, parity. value=ipw_dtb_x
-#define IPW_SIO_SET_PIN 0x03 // set/clear dtr/rts value=ipw_pin_xxx
-#define IPW_SIO_POLL 0x08 // get serial port status byte, call with value=0
-#define IPW_SIO_INIT 0x11 // initializes ? value=0 (appears as first thing todo on open)
-#define IPW_SIO_PURGE 0x12 // purge all transmissions?, call with value=numchar_to_purge
-#define IPW_SIO_HANDFLOW 0x13 // set xon/xoff limits value=0, and a buffer of 0x10 bytes
-#define IPW_SIO_SETCHARS 0x13 // set the flowcontrol special chars, value=0, buf=6 bytes,
- // last 2 bytes contain flowcontrol chars e.g. 00 00 00 00 11 13
+#define IPW_SIO_RXCTL 0x00 /* control bulk rx channel transmissions, value=1/0 (on/off) */
+#define IPW_SIO_SET_BAUD 0x01 /* set baud, value=requested ipw_sio_bxxxx */
+#define IPW_SIO_SET_LINE 0x03 /* set databits, parity. value=ipw_dtb_x */
+#define IPW_SIO_SET_PIN 0x03 /* set/clear dtr/rts value=ipw_pin_xxx */
+#define IPW_SIO_POLL 0x08 /* get serial port status byte, call with value=0 */
+#define IPW_SIO_INIT 0x11 /* initializes ? value=0 (appears as first thing todo on open) */
+#define IPW_SIO_PURGE 0x12 /* purge all transmissions?, call with value=numchar_to_purge */
+#define IPW_SIO_HANDFLOW 0x13 /* set xon/xoff limits value=0, and a buffer of 0x10 bytes */
+#define IPW_SIO_SETCHARS 0x13 /* set the flowcontrol special chars, value=0, buf=6 bytes, */
+ /* last 2 bytes contain flowcontrol chars e.g. 00 00 00 00 11 13 */
/* values used for request IPW_SIO_SET_PIN */
#define IPW_PIN_SETDTR 0x101
#define IPW_PIN_SETRTS 0x202
#define IPW_PIN_CLRDTR 0x100
-#define IPW_PIN_CLRRTS 0x200 // unconfirmed
+#define IPW_PIN_CLRRTS 0x200 /* unconfirmed */
/* values used for request IPW_SIO_RXCTL */
#define IPW_RXBULK_ON 1
#define IPW_RXBULK_OFF 0
/* various 16 byte hardcoded transferbuffers used by flow control */
-#define IPW_BYTES_FLOWINIT { 0x01, 0, 0, 0, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+#define IPW_BYTES_FLOWINIT { 0x01, 0, 0, 0, 0x40, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0 }
/* Interpretation of modem status lines */
/* These need sorting out by individually connecting pins and checking
@@ -132,17 +133,6 @@ enum {
#define IPW_CTS ((1<<5) | (1<<4))
#define IPW_WANTS_TO_SEND 0x30
-//#define IPW_DTR /* Data Terminal Ready */
-//#define IPW_CTS /* Clear To Send */
-//#define IPW_CD /* Carrier Detect */
-//#define IPW_DSR /* Data Set Ready */
-//#define IPW_RxD /* Receive pin */
-
-//#define IPW_LE
-//#define IPW_RTS
-//#define IPW_ST
-//#define IPW_SR
-//#define IPW_RI /* Ring Indicator */
static struct usb_device_id usb_ipw_ids[] = {
{ USB_DEVICE(IPW_VID, IPW_PID) },
@@ -177,9 +167,10 @@ static void ipw_read_bulk_callback(struct urb *urb)
return;
}
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
@@ -187,19 +178,22 @@ static void ipw_read_bulk_callback(struct urb *urb)
}
/* Continue trying to always read */
- usb_fill_bulk_urb (port->read_urb, port->serial->dev,
- usb_rcvbulkpipe(port->serial->dev,
+ 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,
- ipw_read_bulk_callback, port);
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ ipw_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
return;
}
-static int ipw_open(struct usb_serial_port *port, struct file *filp)
+static int ipw_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_device *dev = port->serial->dev;
u8 buf_flow_static[16] = IPW_BYTES_FLOWINIT;
@@ -212,29 +206,33 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
if (!buf_flow_init)
return -ENOMEM;
- if (port->tty)
- port->tty->low_latency = 1;
-
- /* --1: Tell the modem to initialize (we think) From sniffs this is always the
- * first thing that gets sent to the modem during opening of the device */
- dbg("%s: Sending SIO_INIT (we guess)",__func__);
- result = usb_control_msg(dev, usb_sndctrlpipe(dev,0),
- IPW_SIO_INIT,
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- 0,
- 0, /* index */
- NULL,
- 0,
- 100000);
+ if (tty)
+ tty->low_latency = 1;
+
+ /* --1: Tell the modem to initialize (we think) From sniffs this is
+ * always the first thing that gets sent to the modem during
+ * opening of the device */
+ dbg("%s: Sending SIO_INIT (we guess)", __func__);
+ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ IPW_SIO_INIT,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ 0,
+ 0, /* index */
+ NULL,
+ 0,
+ 100000);
if (result < 0)
- dev_err(&port->dev, "Init of modem failed (error = %d)\n", result);
+ dev_err(&port->dev,
+ "Init of modem failed (error = %d)\n", result);
/* reset the bulk pipes */
- usb_clear_halt(dev, usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress));
- usb_clear_halt(dev, usb_sndbulkpipe(dev, port->bulk_out_endpointAddress));
+ usb_clear_halt(dev,
+ usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress));
+ usb_clear_halt(dev,
+ usb_sndbulkpipe(dev, port->bulk_out_endpointAddress));
- /*--2: Start reading from the device */
- dbg("%s: setting up bulk read callback",__func__);
+ /*--2: Start reading from the device */
+ dbg("%s: setting up bulk read callback", __func__);
usb_fill_bulk_urb(port->read_urb, dev,
usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
port->bulk_in_buffer,
@@ -242,66 +240,72 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
ipw_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result < 0)
- dbg("%s - usb_submit_urb(read bulk) failed with status %d", __func__, result);
+ dbg("%s - usb_submit_urb(read bulk) failed with status %d",
+ __func__, result);
/*--3: Tell the modem to open the floodgates on the rx bulk channel */
- dbg("%s:asking modem for RxRead (RXBULK_ON)",__func__);
+ dbg("%s:asking modem for RxRead (RXBULK_ON)", __func__);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- IPW_SIO_RXCTL,
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- IPW_RXBULK_ON,
- 0, /* index */
- NULL,
- 0,
- 100000);
- if (result < 0)
- dev_err(&port->dev, "Enabling bulk RxRead failed (error = %d)\n", result);
+ IPW_SIO_RXCTL,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ IPW_RXBULK_ON,
+ 0, /* index */
+ NULL,
+ 0,
+ 100000);
+ if (result < 0)
+ dev_err(&port->dev,
+ "Enabling bulk RxRead failed (error = %d)\n", result);
/*--4: setup the initial flowcontrol */
- dbg("%s:setting init flowcontrol (%s)",__func__,buf_flow_init);
+ dbg("%s:setting init flowcontrol (%s)", __func__, buf_flow_init);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- IPW_SIO_HANDFLOW,
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- 0,
- 0,
- buf_flow_init,
- 0x10,
- 200000);
+ IPW_SIO_HANDFLOW,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ 0,
+ 0,
+ buf_flow_init,
+ 0x10,
+ 200000);
if (result < 0)
- dev_err(&port->dev, "initial flowcontrol failed (error = %d)\n", result);
+ dev_err(&port->dev,
+ "initial flowcontrol failed (error = %d)\n", result);
/*--5: raise the dtr */
- dbg("%s:raising dtr",__func__);
+ dbg("%s:raising dtr", __func__);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- IPW_SIO_SET_PIN,
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- IPW_PIN_SETDTR,
- 0,
- NULL,
- 0,
- 200000);
+ IPW_SIO_SET_PIN,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ IPW_PIN_SETDTR,
+ 0,
+ NULL,
+ 0,
+ 200000);
if (result < 0)
- dev_err(&port->dev, "setting dtr failed (error = %d)\n", result);
+ dev_err(&port->dev,
+ "setting dtr failed (error = %d)\n", result);
/*--6: raise the rts */
- dbg("%s:raising rts",__func__);
+ dbg("%s:raising rts", __func__);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- IPW_SIO_SET_PIN,
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- IPW_PIN_SETRTS,
- 0,
- NULL,
- 0,
- 200000);
+ IPW_SIO_SET_PIN,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ IPW_PIN_SETRTS,
+ 0,
+ NULL,
+ 0,
+ 200000);
if (result < 0)
- dev_err(&port->dev, "setting dtr failed (error = %d)\n", result);
-
+ dev_err(&port->dev,
+ "setting dtr failed (error = %d)\n", result);
+
kfree(buf_flow_init);
return 0;
}
-static void ipw_close(struct usb_serial_port *port, struct file * filp)
+static void ipw_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_device *dev = port->serial->dev;
int result;
@@ -312,56 +316,62 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
}
/*--1: drop the dtr */
- dbg("%s:dropping dtr",__func__);
+ dbg("%s:dropping dtr", __func__);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- IPW_SIO_SET_PIN,
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- IPW_PIN_CLRDTR,
- 0,
- NULL,
- 0,
- 200000);
+ IPW_SIO_SET_PIN,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ IPW_PIN_CLRDTR,
+ 0,
+ NULL,
+ 0,
+ 200000);
if (result < 0)
- dev_err(&port->dev, "dropping dtr failed (error = %d)\n", result);
+ dev_err(&port->dev, "dropping dtr failed (error = %d)\n",
+ result);
/*--2: drop the rts */
- dbg("%s:dropping rts",__func__);
+ dbg("%s:dropping rts", __func__);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- IPW_SIO_SET_PIN, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- IPW_PIN_CLRRTS,
- 0,
- NULL,
- 0,
- 200000);
+ IPW_SIO_SET_PIN, USB_TYPE_VENDOR |
+ USB_RECIP_INTERFACE | USB_DIR_OUT,
+ IPW_PIN_CLRRTS,
+ 0,
+ NULL,
+ 0,
+ 200000);
if (result < 0)
- dev_err(&port->dev, "dropping rts failed (error = %d)\n", result);
+ dev_err(&port->dev,
+ "dropping rts failed (error = %d)\n", result);
/*--3: purge */
- dbg("%s:sending purge",__func__);
+ dbg("%s:sending purge", __func__);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- IPW_SIO_PURGE, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- 0x03,
- 0,
- NULL,
- 0,
- 200000);
+ IPW_SIO_PURGE, USB_TYPE_VENDOR |
+ USB_RECIP_INTERFACE | USB_DIR_OUT,
+ 0x03,
+ 0,
+ NULL,
+ 0,
+ 200000);
if (result < 0)
dev_err(&port->dev, "purge failed (error = %d)\n", result);
- /* send RXBULK_off (tell modem to stop transmitting bulk data on rx chan) */
+ /* send RXBULK_off (tell modem to stop transmitting bulk data on
+ rx chan) */
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- IPW_SIO_RXCTL,
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- IPW_RXBULK_OFF,
- 0, /* index */
- NULL,
- 0,
- 100000);
+ IPW_SIO_RXCTL,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ IPW_RXBULK_OFF,
+ 0, /* index */
+ NULL,
+ 0,
+ 100000);
if (result < 0)
- dev_err(&port->dev, "Disabling bulk RxRead failed (error = %d)\n", result);
+ dev_err(&port->dev,
+ "Disabling bulk RxRead failed (error = %d)\n", result);
/* shutdown any in-flight urbs that we know about */
usb_kill_urb(port->read_urb);
@@ -384,13 +394,14 @@ static void ipw_write_bulk_callback(struct urb *urb)
usb_serial_port_softint(port);
}
-static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int count)
+static int ipw_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct usb_device *dev = port->serial->dev;
int ret;
dbg("%s: TOP: count=%d, in_interrupt=%ld", __func__,
- count, in_interrupt() );
+ count, in_interrupt());
if (count == 0) {
dbg("%s - write request of 0 bytes", __func__);
@@ -421,13 +432,14 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int
ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (ret != 0) {
port->write_urb_busy = 0;
- dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __func__, ret);
+ dbg("%s - usb_submit_urb(write bulk) failed with error = %d",
+ __func__, ret);
return ret;
}
dbg("%s returning %d", __func__, count);
return count;
-}
+}
static int ipw_probe(struct usb_serial_port *port)
{
@@ -486,8 +498,8 @@ module_init(usb_ipw_init);
module_exit(usb_ipw_exit);
/* Module information */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 0063c11c808..e59155c6607 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -85,15 +85,17 @@ static int buffer_size;
/* if overridden by the user, then use the specified number of XBOFs */
static int xbof = -1;
-static int ir_startup(struct usb_serial *serial);
-static int ir_open(struct usb_serial_port *port, struct file *filep);
-static void ir_close(struct usb_serial_port *port, struct file *filep);
-static int ir_write(struct usb_serial_port *port,
- const unsigned char *buf, int count);
-static void ir_write_bulk_callback(struct urb *urb);
-static void ir_read_bulk_callback(struct urb *urb);
-static void ir_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios);
+static int ir_startup (struct usb_serial *serial);
+static int ir_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filep);
+static void ir_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filep);
+static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+static void ir_write_bulk_callback (struct urb *urb);
+static void ir_read_bulk_callback (struct urb *urb);
+static void ir_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios);
/* Not that this lot means you can only have one per system */
static u8 ir_baud;
@@ -295,7 +297,8 @@ static int ir_startup(struct usb_serial *serial)
return 0;
}
-static int ir_open(struct usb_serial_port *port, struct file *filp)
+static int ir_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
char *buffer;
int result = 0;
@@ -343,7 +346,8 @@ static int ir_open(struct usb_serial_port *port, struct file *filp)
return result;
}
-static void ir_close(struct usb_serial_port *port, struct file *filp)
+static void ir_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file * filp)
{
dbg("%s - port %d", __func__, port->number);
@@ -351,8 +355,8 @@ static void ir_close(struct usb_serial_port *port, struct file *filp)
usb_kill_urb(port->read_urb);
}
-static int ir_write(struct usb_serial_port *port,
- const unsigned char *buf, int count)
+static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
unsigned char *transfer_buffer;
int result;
@@ -360,11 +364,6 @@ static int ir_write(struct usb_serial_port *port,
dbg("%s - port = %d, count = %d", __func__, port->number, count);
- if (!port->tty) {
- dev_err(&port->dev, "%s - no tty???\n", __func__);
- return 0;
- }
-
if (count == 0)
return 0;
@@ -450,14 +449,13 @@ static void ir_read_bulk_callback(struct urb *urb)
dbg("%s - port %d", __func__, port->number);
- if (!port->open_count) {
+ if (!port->port.count) {
dbg("%s - port closed.", __func__);
return;
}
switch (status) {
case 0: /* Successful */
-
/*
* The first byte of the packet we get from the device
* contains a busy indicator and baud rate change.
@@ -465,19 +463,11 @@ static void ir_read_bulk_callback(struct urb *urb)
*/
if ((*data & 0x0f) > 0)
ir_baud = *data & 0x0f;
-
- usb_serial_debug_data(
- debug,
- &port->dev,
- __func__,
- urb->actual_length,
- data);
-
- tty = port->tty;
-
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
+ tty = port->port.tty;
if (tty_buffer_request_room(tty, urb->actual_length - 1)) {
- tty_insert_flip_string(tty, data + 1,
- urb->actual_length - 1);
+ tty_insert_flip_string(tty, data+1, urb->actual_length - 1);
tty_flip_buffer_push(tty);
}
@@ -488,11 +478,10 @@ static void ir_read_bulk_callback(struct urb *urb)
*/
case -EPROTO: /* taking inspiration from pl2303.c */
-
- /* Continue trying to always read */
+ /* Continue trying to always read */
usb_fill_bulk_urb(
port->read_urb,
- port->serial->dev,
+ port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
@@ -502,23 +491,19 @@ static void ir_read_bulk_callback(struct urb *urb)
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- dev_err(&port->dev,
- "%s - failed resubmitting read urb, error %d\n",
+ dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
__func__, result);
- break;
-
+ break ;
default:
dbg("%s - nonzero read bulk status received: %d",
- __func__,
- status);
- break;
+ __func__, status);
+ break ;
}
-
return;
}
-static void ir_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void ir_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
unsigned char *transfer_buffer;
int result;
@@ -527,7 +512,7 @@ static void ir_set_termios(struct usb_serial_port *port,
dbg("%s - port %d", __func__, port->number);
- baud = tty_get_baud_rate(port->tty);
+ baud = tty_get_baud_rate(tty);
/*
* FIXME, we should compare the baud request against the
@@ -600,8 +585,8 @@ static void ir_set_termios(struct usb_serial_port *port,
__func__, result);
/* Only speed changes are supported */
- tty_termios_copy_hw(port->tty->termios, old_termios);
- tty_encode_baud_rate(port->tty, baud, baud);
+ tty_termios_copy_hw(tty->termios, old_termios);
+ tty_encode_baud_rate(tty, baud, baud);
}
static int __init ir_init(void)
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index a01e987c7d3..ddff37fa633 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -144,9 +144,10 @@ static void iuu_shutdown(struct usb_serial *serial)
}
}
-static int iuu_tiocmset(struct usb_serial_port *port, struct file *file,
+static int iuu_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct iuu_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -171,8 +172,9 @@ static int iuu_tiocmset(struct usb_serial_port *port, struct file *file,
* When no card , the reader respond with TIOCM_CD
* This is known as CD autodetect mechanism
*/
-static int iuu_tiocmget(struct usb_serial_port *port, struct file *file)
+static int iuu_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct iuu_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int rc;
@@ -316,11 +318,10 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
port->bulk_out_endpointAddress), buf,
count, &actual, HZ * 1);
- if (status != IUU_OPERATION_OK) {
+ if (status != IUU_OPERATION_OK)
dbg("%s - error = %2x", __func__, status);
- } else {
+ else
dbg("%s - write OK !", __func__);
- }
return status;
}
@@ -340,12 +341,10 @@ static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
port->bulk_in_endpointAddress), buf,
count, &actual, HZ * 1);
- if (status != IUU_OPERATION_OK) {
+ if (status != IUU_OPERATION_OK)
dbg("%s - error = %2x", __func__, status);
- } else {
+ else
dbg("%s - read OK !", __func__);
- }
-
return status;
}
@@ -630,7 +629,7 @@ static void read_buf_callback(struct urb *urb)
}
dbg("%s - %i chars to write", __func__, urb->actual_length);
- tty = port->tty;
+ tty = port->port.tty;
if (data == NULL)
dbg("%s - data is NULL !!!", __func__);
if (tty && urb->actual_length && data) {
@@ -752,11 +751,10 @@ static void iuu_uart_read_callback(struct urb *urb)
/* if nothing to write call again rxcmd */
dbg("%s - rxcmd recall", __func__);
iuu_led_activity_off(urb);
- return;
}
-static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf,
- int count)
+static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const u8 *buf, int count)
{
struct iuu_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -769,14 +767,14 @@ static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf,
if (priv->writelen > 0) {
/* buffer already filled but not commited */
spin_unlock_irqrestore(&priv->lock, flags);
- return (0);
+ return 0;
}
/* fill the buffer */
memcpy(priv->writebuf, buf, count);
priv->writelen = count;
spin_unlock_irqrestore(&priv->lock, flags);
- return (count);
+ return count;
}
static void read_rxcmd_callback(struct urb *urb)
@@ -948,7 +946,8 @@ static int set_control_lines(struct usb_device *dev, u8 value)
return 0;
}
-static void iuu_close(struct usb_serial_port *port, struct file *filp)
+static void iuu_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
/* iuu_led (port,255,0,0,0); */
struct usb_serial *serial;
@@ -964,8 +963,8 @@ static void iuu_close(struct usb_serial_port *port, struct file *filp)
iuu_uart_off(port);
if (serial->dev) {
- if (port->tty) {
- c_cflag = port->tty->termios->c_cflag;
+ if (tty) {
+ c_cflag = tty->termios->c_cflag;
if (c_cflag & HUPCL) {
/* drop DTR and RTS */
priv = usb_get_serial_port_data(port);
@@ -989,7 +988,8 @@ static void iuu_close(struct usb_serial_port *port, struct file *filp)
}
}
-static int iuu_open(struct usb_serial_port *port, struct file *filp)
+static int iuu_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
u8 *buf;
@@ -1036,15 +1036,17 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp)
/* set the termios structure */
spin_lock_irqsave(&priv->lock, flags);
- if (!priv->termios_initialized) {
- *(port->tty->termios) = tty_std_termios;
- port->tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
- | TIOCM_CTS | CSTOPB | PARENB;
- port->tty->termios->c_lflag = 0;
- port->tty->termios->c_oflag = 0;
- port->tty->termios->c_iflag = 0;
+ if (tty && !priv->termios_initialized) {
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
+ | TIOCM_CTS | CSTOPB | PARENB;
+ tty->termios->c_ispeed = 9600;
+ tty->termios->c_ospeed = 9600;
+ tty->termios->c_lflag = 0;
+ tty->termios->c_oflag = 0;
+ tty->termios->c_iflag = 0;
priv->termios_initialized = 1;
- port->tty->low_latency = 1;
+ tty->low_latency = 1;
priv->poll = 0;
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1148,7 +1150,7 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp)
if (result) {
dev_err(&port->dev, "%s - failed submitting read urb,"
" error %d\n", __func__, result);
- iuu_close(port, NULL);
+ iuu_close(tty, port, NULL);
return -EPROTO;
} else {
dbg("%s - rxcmd OK", __func__);
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 11e439b90ea..704716f6f6d 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -1,29 +1,29 @@
/*
Keyspan USB to Serial Converter driver
-
+
(C) Copyright (C) 2000-2001 Hugh Blemings <hugh@blemings.org>
(C) Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.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.
See http://misc.nu/hugh/keyspan.html for more information.
-
+
Code in this driver inspired by and in a number of places taken
from Brian Warner's original Keyspan-PDA driver.
This driver has been put together with the support of Innosys, Inc.
and Keyspan, Inc the manufacturers of the Keyspan USB-serial products.
Thanks Guys :)
-
+
Thanks to Paulus for miscellaneous tidy ups, some largish chunks
of much nicer and/or completely new code and (perhaps most uniquely)
having the patience to sit down and explain why and where he'd changed
- stuff.
-
- Tip 'o the hat to IBM (and previously Linuxcare :) for supporting
+ stuff.
+
+ Tip 'o the hat to IBM (and previously Linuxcare :) for supporting
staff in their work on open source projects.
Change History
@@ -70,21 +70,21 @@
Thu May 31 11:56:42 PDT 2001 gkh
switched from using spinlock to a semaphore
-
+
(04/08/2001) gb
Identify version on module load.
-
+
(11/01/2000) Adam J. Richter
usb_device_id table support.
-
+
Tue Oct 10 23:15:33 EST 2000 Hugh
Merged Paul's changes with my USA-49W mods. Work in progress
still...
-
+
Wed Jul 19 14:00:42 EST 2000 gkh
Added module_init and module_exit functions to handle the fact that
this driver is a loadable module now.
-
+
Tue Jul 18 16:14:52 EST 2000 Hugh
Basic character input/output for USA-19 now mostly works,
fixed at 9600 baud for the moment.
@@ -107,7 +107,7 @@
#include <linux/spinlock.h>
#include <linux/firmware.h>
#include <linux/ihex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include "keyspan.h"
@@ -132,15 +132,15 @@ struct keyspan_serial_private {
struct urb *instat_urb;
char instat_buf[INSTAT_BUFLEN];
- /* added to support 49wg, where data from all 4 ports comes in on 1 EP */
- /* and high-speed supported */
+ /* added to support 49wg, where data from all 4 ports comes in
+ on 1 EP and high-speed supported */
struct urb *indat_urb;
char indat_buf[INDAT49W_BUFLEN];
/* XXX this one probably will need a lock */
struct urb *glocont_urb;
char glocont_buf[GLOCONT_BUFLEN];
- char ctrl_buf[8]; // for EP0 control message
+ char ctrl_buf[8]; /* for EP0 control message */
};
struct keyspan_port_private {
@@ -186,19 +186,19 @@ struct keyspan_port_private {
int resend_cont; /* need to resend control packet */
};
-
/* Include Keyspan message headers. All current Keyspan Adapters
make use of one of five message formats which are referred
- to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and within this driver. */
+ to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and
+ within this driver. */
#include "keyspan_usa26msg.h"
#include "keyspan_usa28msg.h"
#include "keyspan_usa49msg.h"
#include "keyspan_usa90msg.h"
#include "keyspan_usa67msg.h"
-
+
/* Functions used by new usb-serial code. */
-static int __init keyspan_init (void)
+static int __init keyspan_init(void)
{
int retval;
retval = usb_serial_register(&keyspan_pre_device);
@@ -214,7 +214,7 @@ static int __init keyspan_init (void)
if (retval)
goto failed_4port_device_register;
retval = usb_register(&keyspan_driver);
- if (retval)
+ if (retval)
goto failed_usb_register;
info(DRIVER_VERSION ":" DRIVER_DESC);
@@ -232,35 +232,24 @@ failed_pre_device_register:
return retval;
}
-static void __exit keyspan_exit (void)
+static void __exit keyspan_exit(void)
{
- usb_deregister (&keyspan_driver);
- usb_serial_deregister (&keyspan_pre_device);
- usb_serial_deregister (&keyspan_1port_device);
- usb_serial_deregister (&keyspan_2port_device);
- usb_serial_deregister (&keyspan_4port_device);
+ usb_deregister(&keyspan_driver);
+ usb_serial_deregister(&keyspan_pre_device);
+ usb_serial_deregister(&keyspan_1port_device);
+ usb_serial_deregister(&keyspan_2port_device);
+ usb_serial_deregister(&keyspan_4port_device);
}
module_init(keyspan_init);
module_exit(keyspan_exit);
-static void keyspan_rx_throttle (struct usb_serial_port *port)
-{
- dbg("%s - port %d", __func__, port->number);
-}
-
-
-static void keyspan_rx_unthrottle (struct usb_serial_port *port)
-{
- dbg("%s - port %d", __func__, port->number);
-}
-
-
-static void keyspan_break_ctl (struct usb_serial_port *port, int break_state)
+static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct keyspan_port_private *p_priv;
- dbg("%s", __func__);
+ dbg("%s", __func__);
p_priv = usb_get_serial_port_data(port);
@@ -273,14 +262,13 @@ static void keyspan_break_ctl (struct usb_serial_port *port, int break_state)
}
-static void keyspan_set_termios (struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void keyspan_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
int baud_rate, device_port;
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
unsigned int cflag;
- struct tty_struct *tty = port->tty;
dbg("%s", __func__);
@@ -292,7 +280,7 @@ static void keyspan_set_termios (struct usb_serial_port *port,
/* Baud rate calculation takes baud rate as an integer
so other rates can be generated if desired. */
baud_rate = tty_get_baud_rate(tty);
- /* If no match or invalid, don't change */
+ /* If no match or invalid, don't change */
if (d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
/* FIXME - more to do here to ensure rate changes cleanly */
@@ -312,35 +300,32 @@ static void keyspan_set_termios (struct usb_serial_port *port,
keyspan_send_setup(port, 0);
}
-static int keyspan_tiocmget(struct usb_serial_port *port, struct file *file)
+static int keyspan_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
+ struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
unsigned int value;
- struct keyspan_port_private *p_priv;
- p_priv = usb_get_serial_port_data(port);
-
value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
((p_priv->dtr_state) ? TIOCM_DTR : 0) |
((p_priv->cts_state) ? TIOCM_CTS : 0) |
((p_priv->dsr_state) ? TIOCM_DSR : 0) |
((p_priv->dcd_state) ? TIOCM_CAR : 0) |
- ((p_priv->ri_state) ? TIOCM_RNG : 0);
+ ((p_priv->ri_state) ? TIOCM_RNG : 0);
return value;
}
-static int keyspan_tiocmset(struct usb_serial_port *port, struct file *file,
+static int keyspan_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- struct keyspan_port_private *p_priv;
+ struct usb_serial_port *port = tty->driver_data;
+ struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
- p_priv = usb_get_serial_port_data(port);
-
if (set & TIOCM_RTS)
p_priv->rts_state = 1;
if (set & TIOCM_DTR)
p_priv->dtr_state = 1;
-
if (clear & TIOCM_RTS)
p_priv->rts_state = 0;
if (clear & TIOCM_DTR)
@@ -349,35 +334,29 @@ static int keyspan_tiocmset(struct usb_serial_port *port, struct file *file,
return 0;
}
-static int keyspan_ioctl(struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return -ENOIOCTLCMD;
-}
-
- /* Write function is similar for the four protocols used
- with only a minor change for usa90 (usa19hs) required */
-static int keyspan_write(struct usb_serial_port *port,
- const unsigned char *buf, int count)
+/* Write function is similar for the four protocols used
+ with only a minor change for usa90 (usa19hs) required */
+static int keyspan_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
int flip;
int left, todo;
struct urb *this_urb;
- int err, maxDataLen, dataOffset;
+ int err, maxDataLen, dataOffset;
p_priv = usb_get_serial_port_data(port);
d_details = p_priv->device_details;
if (d_details->msg_format == msg_usa90) {
- maxDataLen = 64;
+ maxDataLen = 64;
dataOffset = 0;
} else {
maxDataLen = 63;
dataOffset = 1;
}
-
+
dbg("%s - for port %d (%d chars), flip=%d",
__func__, port->number, count, p_priv->out_flip);
@@ -387,37 +366,40 @@ static int keyspan_write(struct usb_serial_port *port,
todo = maxDataLen;
flip = p_priv->out_flip;
-
+
/* Check we have a valid urb/endpoint before we use it... */
- if ((this_urb = p_priv->out_urbs[flip]) == NULL) {
+ this_urb = p_priv->out_urbs[flip];
+ if (this_urb == NULL) {
/* no bulk out, so return 0 bytes written */
dbg("%s - no output urb :(", __func__);
return count;
}
- dbg("%s - endpoint %d flip %d", __func__, usb_pipeendpoint(this_urb->pipe), flip);
+ dbg("%s - endpoint %d flip %d",
+ __func__, usb_pipeendpoint(this_urb->pipe), flip);
if (this_urb->status == -EINPROGRESS) {
- if (time_before(jiffies, p_priv->tx_start_time[flip] + 10 * HZ))
+ if (time_before(jiffies,
+ p_priv->tx_start_time[flip] + 10 * HZ))
break;
usb_unlink_urb(this_urb);
break;
}
- /* First byte in buffer is "last flag" (except for usa19hx) - unused so
- for now so set to zero */
+ /* First byte in buffer is "last flag" (except for usa19hx)
+ - unused so for now so set to zero */
((char *)this_urb->transfer_buffer)[0] = 0;
- memcpy (this_urb->transfer_buffer + dataOffset, buf, todo);
+ memcpy(this_urb->transfer_buffer + dataOffset, buf, todo);
buf += todo;
/* send the data out the bulk port */
this_urb->transfer_buffer_length = todo + dataOffset;
this_urb->dev = port->serial->dev;
- if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(this_urb, GFP_ATOMIC);
+ if (err != 0)
dbg("usb_submit_urb(write bulk) failed (%d)", err);
- }
p_priv->tx_start_time[flip] = jiffies;
/* Flip for next time if usa26 or usa28 interface
@@ -437,7 +419,7 @@ static void usa26_indat_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
endpoint = usb_pipeendpoint(urb->pipe);
@@ -448,17 +430,18 @@ static void usa26_indat_callback(struct urb *urb)
}
port = urb->context;
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
/* 0x80 bit is error flag */
if ((data[0] & 0x80) == 0) {
- /* no errors on individual bytes, only possible overrun err*/
+ /* no errors on individual bytes, only
+ possible overrun err */
if (data[0] & RXERROR_OVERRUN)
- err = TTY_OVERRUN;
- else err = 0;
- for (i = 1; i < urb->actual_length ; ++i) {
+ err = TTY_OVERRUN;
+ else
+ err = 0;
+ for (i = 1; i < urb->actual_length ; ++i)
tty_insert_flip_char(tty, data[i], err);
- }
} else {
/* some bytes had errors, every byte has status */
dbg("%s - RX error!!!!", __func__);
@@ -476,17 +459,19 @@ static void usa26_indat_callback(struct urb *urb)
}
tty_flip_buffer_push(tty);
}
-
- /* Resubmit urb so we continue receiving */
+
+ /* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
- if (port->open_count)
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
- }
+ if (port->port.count) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
+ dbg("%s - resubmit read urb failed. (%d)",
+ __func__, err);
+ }
return;
}
- /* Outdat handling is common for all devices */
+/* Outdat handling is common for all devices */
static void usa2x_outdat_callback(struct urb *urb)
{
struct usb_serial_port *port;
@@ -494,16 +479,16 @@ static void usa2x_outdat_callback(struct urb *urb)
port = urb->context;
p_priv = usb_get_serial_port_data(port);
- dbg ("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
+ dbg("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
- if (port->open_count)
+ if (port->port.count)
usb_serial_port_softint(port);
}
static void usa26_inack_callback(struct urb *urb)
{
- dbg ("%s", __func__);
-
+ dbg("%s", __func__);
+
}
static void usa26_outcont_callback(struct urb *urb)
@@ -515,8 +500,9 @@ static void usa26_outcont_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
- dbg ("%s - sending setup", __func__);
- keyspan_usa26_send_setup(port->serial, port, p_priv->resend_cont - 1);
+ dbg("%s - sending setup", __func__);
+ keyspan_usa26_send_setup(port->serial, port,
+ p_priv->resend_cont - 1);
}
}
@@ -552,14 +538,14 @@ static void usa26_instat_callback(struct urb *urb)
/* Now do something useful with the data */
- /* Check port number from message and retrieve private data */
+ /* Check port number from message and retrieve private data */
if (msg->port >= serial->num_ports) {
- dbg ("%s - Unexpected port number %d", __func__, msg->port);
+ dbg("%s - Unexpected port number %d", __func__, msg->port);
goto exit;
}
port = serial->port[msg->port];
p_priv = usb_get_serial_port_data(port);
-
+
/* Update handshaking pin state information */
old_dcd_state = p_priv->dcd_state;
p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
@@ -567,39 +553,38 @@ static void usa26_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (port->tty && !C_CLOCAL(port->tty)
+ if (port->port.tty && !C_CLOCAL(port->port.tty)
&& old_dcd_state != p_priv->dcd_state) {
if (old_dcd_state)
- tty_hangup(port->tty);
+ tty_hangup(port->port.tty);
/* else */
/* wake_up_interruptible(&p_priv->open_wait); */
}
-
+
/* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
dbg("%s - resubmit read urb failed. (%d)", __func__, err);
- }
exit: ;
}
static void usa26_glocont_callback(struct urb *urb)
{
- dbg ("%s", __func__);
-
+ dbg("%s", __func__);
}
static void usa28_indat_callback(struct urb *urb)
{
- int i, err;
+ int err;
struct usb_serial_port *port;
struct tty_struct *tty;
unsigned char *data;
struct keyspan_port_private *p_priv;
int status = urb->status;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
port = urb->context;
p_priv = usb_get_serial_port_data(port);
@@ -619,20 +604,20 @@ static void usa28_indat_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
data = urb->transfer_buffer;
- tty = port->tty;
+ tty = port->port.tty;
if (urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
/* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
- if (port->open_count)
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
- }
+ if (port->port.count) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
+ dbg("%s - resubmit read urb failed. (%d)",
+ __func__, err);
+ }
p_priv->in_flip ^= 1;
urb = p_priv->in_urbs[p_priv->in_flip];
@@ -641,7 +626,7 @@ static void usa28_indat_callback(struct urb *urb)
static void usa28_inack_callback(struct urb *urb)
{
- dbg ("%s", __func__);
+ dbg("%s", __func__);
}
static void usa28_outcont_callback(struct urb *urb)
@@ -653,8 +638,9 @@ static void usa28_outcont_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
- dbg ("%s - sending setup", __func__);
- keyspan_usa28_send_setup(port->serial, port, p_priv->resend_cont - 1);
+ dbg("%s - sending setup", __func__);
+ keyspan_usa28_send_setup(port->serial, port,
+ p_priv->resend_cont - 1);
}
}
@@ -684,19 +670,18 @@ static void usa28_instat_callback(struct urb *urb)
/*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__
data[0], data[1], data[2], data[3], data[4], data[5],
data[6], data[7], data[8], data[9], data[10], data[11]);*/
-
- /* Now do something useful with the data */
- msg = (struct keyspan_usa28_portStatusMessage *)data;
+ /* Now do something useful with the data */
+ msg = (struct keyspan_usa28_portStatusMessage *)data;
- /* Check port number from message and retrieve private data */
+ /* Check port number from message and retrieve private data */
if (msg->port >= serial->num_ports) {
- dbg ("%s - Unexpected port number %d", __func__, msg->port);
+ dbg("%s - Unexpected port number %d", __func__, msg->port);
goto exit;
}
port = serial->port[msg->port];
p_priv = usb_get_serial_port_data(port);
-
+
/* Update handshaking pin state information */
old_dcd_state = p_priv->dcd_state;
p_priv->cts_state = ((msg->cts) ? 1 : 0);
@@ -704,25 +689,25 @@ static void usa28_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (port->tty && !C_CLOCAL(port->tty)
+ if (port->port.tty && !C_CLOCAL(port->port.tty)
&& old_dcd_state != p_priv->dcd_state) {
if (old_dcd_state)
- tty_hangup(port->tty);
+ tty_hangup(port->port.tty);
/* else */
/* wake_up_interruptible(&p_priv->open_wait); */
}
/* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
dbg("%s - resubmit read urb failed. (%d)", __func__, err);
- }
exit: ;
}
static void usa28_glocont_callback(struct urb *urb)
{
- dbg ("%s", __func__);
+ dbg("%s", __func__);
}
@@ -733,7 +718,7 @@ static void usa49_glocont_callback(struct urb *urb)
struct keyspan_port_private *p_priv;
int i;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
serial = urb->context;
for (i = 0; i < serial->num_ports; ++i) {
@@ -741,8 +726,9 @@ static void usa49_glocont_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
- dbg ("%s - sending setup", __func__);
- keyspan_usa49_send_setup(serial, port, p_priv->resend_cont - 1);
+ dbg("%s - sending setup", __func__);
+ keyspan_usa49_send_setup(serial, port,
+ p_priv->resend_cont - 1);
break;
}
}
@@ -761,7 +747,7 @@ static void usa49_instat_callback(struct urb *urb)
int old_dcd_state;
int status = urb->status;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
serial = urb->context;
@@ -770,7 +756,8 @@ static void usa49_instat_callback(struct urb *urb)
return;
}
- if (urb->actual_length != sizeof(struct keyspan_usa49_portStatusMessage)) {
+ if (urb->actual_length !=
+ sizeof(struct keyspan_usa49_portStatusMessage)) {
dbg("%s - bad length %d", __func__, urb->actual_length);
goto exit;
}
@@ -778,18 +765,19 @@ static void usa49_instat_callback(struct urb *urb)
/*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __func__,
data[0], data[1], data[2], data[3], data[4], data[5],
data[6], data[7], data[8], data[9], data[10]);*/
-
- /* Now do something useful with the data */
+
+ /* Now do something useful with the data */
msg = (struct keyspan_usa49_portStatusMessage *)data;
- /* Check port number from message and retrieve private data */
+ /* Check port number from message and retrieve private data */
if (msg->portNumber >= serial->num_ports) {
- dbg ("%s - Unexpected port number %d", __func__, msg->portNumber);
+ dbg("%s - Unexpected port number %d",
+ __func__, msg->portNumber);
goto exit;
}
port = serial->port[msg->portNumber];
p_priv = usb_get_serial_port_data(port);
-
+
/* Update handshaking pin state information */
old_dcd_state = p_priv->dcd_state;
p_priv->cts_state = ((msg->cts) ? 1 : 0);
@@ -797,26 +785,26 @@ static void usa49_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (port->tty && !C_CLOCAL(port->tty)
+ if (port->port.tty && !C_CLOCAL(port->port.tty)
&& old_dcd_state != p_priv->dcd_state) {
if (old_dcd_state)
- tty_hangup(port->tty);
+ tty_hangup(port->port.tty);
/* else */
/* wake_up_interruptible(&p_priv->open_wait); */
}
- /* Resubmit urb so we continue receiving */
+ /* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
dbg("%s - resubmit read urb failed. (%d)", __func__, err);
- }
exit: ;
}
static void usa49_inack_callback(struct urb *urb)
{
- dbg ("%s", __func__);
+ dbg("%s", __func__);
}
static void usa49_indat_callback(struct urb *urb)
@@ -828,7 +816,7 @@ static void usa49_indat_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
endpoint = usb_pipeendpoint(urb->pipe);
@@ -839,14 +827,13 @@ static void usa49_indat_callback(struct urb *urb)
}
port = urb->context;
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
/* 0x80 bit is error flag */
if ((data[0] & 0x80) == 0) {
/* no error on any byte */
- for (i = 1; i < urb->actual_length ; ++i) {
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_insert_flip_string(tty, data + 1,
+ urb->actual_length - 1);
} else {
/* some bytes had errors, every byte has status */
for (i = 0; i + 1 < urb->actual_length; i += 2) {
@@ -863,13 +850,15 @@ static void usa49_indat_callback(struct urb *urb)
}
tty_flip_buffer_push(tty);
}
-
- /* Resubmit urb so we continue receiving */
+
+ /* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
- if (port->open_count)
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
- }
+ if (port->port.count) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
+ dbg("%s - resubmit read urb failed. (%d)",
+ __func__, err);
+ }
}
static void usa49wg_indat_callback(struct urb *urb)
@@ -881,7 +870,7 @@ static void usa49wg_indat_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
serial = urb->context;
@@ -899,12 +888,12 @@ static void usa49wg_indat_callback(struct urb *urb)
/* Check port number from message*/
if (data[i] >= serial->num_ports) {
- dbg ("%s - Unexpected port number %d",
+ dbg("%s - Unexpected port number %d",
__func__, data[i]);
return;
}
port = serial->port[data[i++]];
- tty = port->tty;
+ tty = port->port.tty;
len = data[i++];
/* 0x80 bit is error flag */
@@ -912,7 +901,7 @@ static void usa49wg_indat_callback(struct urb *urb)
/* no error on any byte */
i++;
for (x = 1; x < len ; ++x)
- if (port->open_count)
+ if (port->port.count)
tty_insert_flip_char(tty,
data[i++], 0);
else
@@ -930,13 +919,13 @@ static void usa49wg_indat_callback(struct urb *urb)
if (stat & RXERROR_PARITY)
flag |= TTY_PARITY;
/* XXX should handle break (0x10) */
- if (port->open_count)
+ if (port->port.count)
tty_insert_flip_char(tty,
data[i+1], flag);
i += 2;
}
}
- if (port->open_count)
+ if (port->port.count)
tty_flip_buffer_push(tty);
}
}
@@ -952,7 +941,7 @@ static void usa49wg_indat_callback(struct urb *urb)
/* not used, usa-49 doesn't have per-port control endpoints */
static void usa49_outcont_callback(struct urb *urb)
{
- dbg ("%s", __func__);
+ dbg("%s", __func__);
}
static void usa90_indat_callback(struct urb *urb)
@@ -965,7 +954,7 @@ static void usa90_indat_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
endpoint = usb_pipeendpoint(urb->pipe);
@@ -978,29 +967,26 @@ static void usa90_indat_callback(struct urb *urb)
port = urb->context;
p_priv = usb_get_serial_port_data(port);
- tty = port->tty;
+ tty = port->port.tty;
if (urb->actual_length) {
-
/* if current mode is DMA, looks like usa28 format
- otherwise looks like usa26 data format */
+ otherwise looks like usa26 data format */
- if (p_priv->baud > 57600) {
- for (i = 0; i < urb->actual_length ; ++i)
- tty_insert_flip_char(tty, data[i], 0);
- }
+ if (p_priv->baud > 57600)
+ tty_insert_flip_string(tty, data, urb->actual_length);
else {
-
/* 0x80 bit is error flag */
if ((data[0] & 0x80) == 0) {
- /* no errors on individual bytes, only possible overrun err*/
+ /* no errors on individual bytes, only
+ possible overrun err*/
if (data[0] & RXERROR_OVERRUN)
- err = TTY_OVERRUN;
- else err = 0;
- for (i = 1; i < urb->actual_length ; ++i)
- tty_insert_flip_char(tty, data[i], err);
-
- }
- else {
+ err = TTY_OVERRUN;
+ else
+ err = 0;
+ for (i = 1; i < urb->actual_length ; ++i)
+ tty_insert_flip_char(tty, data[i],
+ err);
+ } else {
/* some bytes had errors, every byte has status */
dbg("%s - RX error!!!!", __func__);
for (i = 0; i + 1 < urb->actual_length; i += 2) {
@@ -1012,19 +998,22 @@ static void usa90_indat_callback(struct urb *urb)
if (stat & RXERROR_PARITY)
flag |= TTY_PARITY;
/* XXX should handle break (0x10) */
- tty_insert_flip_char(tty, data[i+1], flag);
+ tty_insert_flip_char(tty, data[i+1],
+ flag);
}
}
}
tty_flip_buffer_push(tty);
}
-
+
/* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
- if (port->open_count)
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
- }
+ if (port->port.count) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
+ dbg("%s - resubmit read urb failed. (%d)",
+ __func__, err);
+ }
return;
}
@@ -1056,7 +1045,7 @@ static void usa90_instat_callback(struct urb *urb)
port = serial->port[0];
p_priv = usb_get_serial_port_data(port);
-
+
/* Update handshaking pin state information */
old_dcd_state = p_priv->dcd_state;
p_priv->cts_state = ((msg->cts) ? 1 : 0);
@@ -1064,19 +1053,19 @@ static void usa90_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (port->tty && !C_CLOCAL(port->tty)
+ if (port->port.tty && !C_CLOCAL(port->port.tty)
&& old_dcd_state != p_priv->dcd_state) {
if (old_dcd_state)
- tty_hangup(port->tty);
+ tty_hangup(port->port.tty);
/* else */
/* wake_up_interruptible(&p_priv->open_wait); */
}
-
+
/* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
dbg("%s - resubmit read urb failed. (%d)", __func__, err);
- }
exit:
;
}
@@ -1090,8 +1079,9 @@ static void usa90_outcont_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
- dbg ("%s - sending setup", __func__);
- keyspan_usa90_send_setup(port->serial, port, p_priv->resend_cont - 1);
+ dbg("%s - sending setup", __func__);
+ keyspan_usa90_send_setup(port->serial, port,
+ p_priv->resend_cont - 1);
}
}
@@ -1107,7 +1097,7 @@ static void usa67_instat_callback(struct urb *urb)
int old_dcd_state;
int status = urb->status;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
serial = urb->context;
@@ -1116,7 +1106,8 @@ static void usa67_instat_callback(struct urb *urb)
return;
}
- if (urb->actual_length != sizeof(struct keyspan_usa67_portStatusMessage)) {
+ if (urb->actual_length !=
+ sizeof(struct keyspan_usa67_portStatusMessage)) {
dbg("%s - bad length %d", __func__, urb->actual_length);
return;
}
@@ -1127,7 +1118,7 @@ static void usa67_instat_callback(struct urb *urb)
/* Check port number from message and retrieve private data */
if (msg->port >= serial->num_ports) {
- dbg ("%s - Unexpected port number %d", __func__, msg->port);
+ dbg("%s - Unexpected port number %d", __func__, msg->port);
return;
}
@@ -1139,10 +1130,10 @@ static void usa67_instat_callback(struct urb *urb)
p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
- if (port->tty && !C_CLOCAL(port->tty)
+ if (port->port.tty && !C_CLOCAL(port->port.tty)
&& old_dcd_state != p_priv->dcd_state) {
if (old_dcd_state)
- tty_hangup(port->tty);
+ tty_hangup(port->port.tty);
/* else */
/* wake_up_interruptible(&p_priv->open_wait); */
}
@@ -1161,7 +1152,7 @@ static void usa67_glocont_callback(struct urb *urb)
struct keyspan_port_private *p_priv;
int i;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
serial = urb->context;
for (i = 0; i < serial->num_ports; ++i) {
@@ -1169,7 +1160,7 @@ static void usa67_glocont_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
- dbg ("%s - sending setup", __func__);
+ dbg("%s - sending setup", __func__);
keyspan_usa67_send_setup(serial, port,
p_priv->resend_cont - 1);
break;
@@ -1177,8 +1168,9 @@ static void usa67_glocont_callback(struct urb *urb)
}
}
-static int keyspan_write_room (struct usb_serial_port *port)
+static int keyspan_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
int flip;
@@ -1191,32 +1183,30 @@ static int keyspan_write_room (struct usb_serial_port *port)
/* FIXME: locking */
if (d_details->msg_format == msg_usa90)
- data_len = 64;
+ data_len = 64;
else
data_len = 63;
flip = p_priv->out_flip;
/* Check both endpoints to see if any are available. */
- if ((this_urb = p_priv->out_urbs[flip]) != NULL) {
+ this_urb = p_priv->out_urbs[flip];
+ if (this_urb != NULL) {
if (this_urb->status != -EINPROGRESS)
- return (data_len);
- flip = (flip + 1) & d_details->outdat_endp_flip;
- if ((this_urb = p_priv->out_urbs[flip]) != NULL)
+ return data_len;
+ flip = (flip + 1) & d_details->outdat_endp_flip;
+ this_urb = p_priv->out_urbs[flip];
+ if (this_urb != NULL) {
if (this_urb->status != -EINPROGRESS)
- return (data_len);
+ return data_len;
+ }
}
return 0;
}
-static int keyspan_chars_in_buffer (struct usb_serial_port *port)
-{
- return 0;
-}
-
-
-static int keyspan_open (struct usb_serial_port *port, struct file *filp)
+static int keyspan_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct keyspan_port_private *p_priv;
struct keyspan_serial_private *s_priv;
@@ -1225,7 +1215,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
int i, err;
int baud_rate, device_port;
struct urb *urb;
- unsigned int cflag;
+ unsigned int cflag = 0;
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
@@ -1247,50 +1237,53 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
/* Reset low level data toggle and start reading from endpoints */
for (i = 0; i < 2; i++) {
- if ((urb = p_priv->in_urbs[i]) == NULL)
+ urb = p_priv->in_urbs[i];
+ if (urb == NULL)
continue;
urb->dev = serial->dev;
- /* make sure endpoint data toggle is synchronized with the device */
-
+ /* make sure endpoint data toggle is synchronized
+ with the device */
usb_clear_halt(urb->dev, urb->pipe);
-
- if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
- dbg("%s - submit urb %d failed (%d)", __func__, i, err);
- }
+ err = usb_submit_urb(urb, GFP_KERNEL);
+ if (err != 0)
+ dbg("%s - submit urb %d failed (%d)",
+ __func__, i, err);
}
/* Reset low level data toggle on out endpoints */
for (i = 0; i < 2; i++) {
- if ((urb = p_priv->out_urbs[i]) == NULL)
+ urb = p_priv->out_urbs[i];
+ if (urb == NULL)
continue;
urb->dev = serial->dev;
- /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */
+ /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ usb_pipeout(urb->pipe), 0); */
}
/* get the terminal config for the setup message now so we don't
* need to send 2 of them */
- cflag = port->tty->termios->c_cflag;
device_port = port->number - port->serial->minor;
-
- /* Baud rate calculation takes baud rate as an integer
- so other rates can be generated if desired. */
- baud_rate = tty_get_baud_rate(port->tty);
- /* If no match or invalid, leave as default */
- if (baud_rate >= 0
- && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
- NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
- p_priv->baud = baud_rate;
+ if (tty) {
+ cflag = tty->termios->c_cflag;
+ /* Baud rate calculation takes baud rate as an integer
+ so other rates can be generated if desired. */
+ baud_rate = tty_get_baud_rate(tty);
+ /* If no match or invalid, leave as default */
+ if (baud_rate >= 0
+ && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
+ NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
+ p_priv->baud = baud_rate;
+ }
}
-
/* set CTS/RTS handshake etc. */
p_priv->cflag = cflag;
p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
keyspan_send_setup(port, 1);
- //mdelay(100);
- //keyspan_set_termios(port, NULL);
+ /* mdelay(100); */
+ /* keyspan_set_termios(port, NULL); */
return 0;
}
@@ -1301,7 +1294,8 @@ static inline void stop_urb(struct urb *urb)
usb_kill_urb(urb);
}
-static void keyspan_close(struct usb_serial_port *port, struct file *filp)
+static void keyspan_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
int i;
struct usb_serial *serial = port->serial;
@@ -1311,15 +1305,15 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp)
dbg("%s", __func__);
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
-
+
p_priv->rts_state = 0;
p_priv->dtr_state = 0;
-
+
if (serial->dev) {
keyspan_send_setup(port, 2);
/* pilot-xfer seems to work best with this delay */
mdelay(100);
- // keyspan_set_termios(port, NULL);
+ /* keyspan_set_termios(port, NULL); */
}
/*while (p_priv->outcont_urb->status == -EINPROGRESS) {
@@ -1338,11 +1332,11 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp)
stop_urb(p_priv->out_urbs[i]);
}
}
- port->tty = NULL;
+ port->port.tty = NULL;
}
- /* download the firmware to a pre-renumeration device */
-static int keyspan_fake_startup (struct usb_serial *serial)
+/* download the firmware to a pre-renumeration device */
+static int keyspan_fake_startup(struct usb_serial *serial)
{
int response;
const struct ihex_binrec *record;
@@ -1352,10 +1346,11 @@ static int keyspan_fake_startup (struct usb_serial *serial)
dbg("Keyspan startup version %04x product %04x",
le16_to_cpu(serial->dev->descriptor.bcdDevice),
le16_to_cpu(serial->dev->descriptor.idProduct));
-
- if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000) != 0x8000) {
+
+ if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
+ != 0x8000) {
dbg("Firmware already loaded. Quitting.");
- return(1);
+ return 1;
}
/* Select firmware image on the basis of idProduct */
@@ -1379,11 +1374,11 @@ static int keyspan_fake_startup (struct usb_serial *serial)
case keyspan_usa19_pre_product_id:
fw_name = "keyspan/usa19.fw";
break;
-
+
case keyspan_usa19qi_pre_product_id:
fw_name = "keyspan/usa19qi.fw";
break;
-
+
case keyspan_mpr_pre_product_id:
fw_name = "keyspan/mpr.fw";
break;
@@ -1391,15 +1386,15 @@ static int keyspan_fake_startup (struct usb_serial *serial)
case keyspan_usa19qw_pre_product_id:
fw_name = "keyspan/usa19qw.fw";
break;
-
+
case keyspan_usa18x_pre_product_id:
fw_name = "keyspan/usa18x.fw";
break;
-
+
case keyspan_usa19w_pre_product_id:
fw_name = "keyspan/usa19w.fw";
break;
-
+
case keyspan_usa49w_pre_product_id:
fw_name = "keyspan/usa49w.fw";
break;
@@ -1431,8 +1426,7 @@ static int keyspan_fake_startup (struct usb_serial *serial)
(unsigned char *)record->data,
be16_to_cpu(record->len), 0xa0);
if (response < 0) {
- dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan"
- "firmware (%d %04X %p %d)\n",
+ dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan firmware (%d %04X %p %d)\n",
response, be32_to_cpu(record->addr),
record->data, be16_to_cpu(record->len));
break;
@@ -1445,7 +1439,7 @@ static int keyspan_fake_startup (struct usb_serial *serial)
response = ezusb_set_reset(serial, 0);
/* we don't want this device to have a driver assigned to it. */
- return (1);
+ return 1;
}
/* Helper functions used by keyspan_setup_urbs */
@@ -1467,7 +1461,7 @@ static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *se
return NULL;
}
-static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint,
+static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
int dir, void *ctx, char *buf, int len,
void (*callback)(struct urb *))
{
@@ -1478,10 +1472,10 @@ static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint,
if (endpoint == -1)
return NULL; /* endpoint not needed */
- dbg ("%s - alloc for endpoint %d.", __func__, endpoint);
+ dbg("%s - alloc for endpoint %d.", __func__, endpoint);
urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
if (urb == NULL) {
- dbg ("%s - alloc for endpoint %d failed.", __func__, endpoint);
+ dbg("%s - alloc for endpoint %d failed.", __func__, endpoint);
return NULL;
}
@@ -1554,7 +1548,7 @@ static struct callbacks {
}, {
/* msg_usa90 callbacks */
.instat_callback = usa90_instat_callback,
- .glocont_callback = usa28_glocont_callback,
+ .glocont_callback = usa28_glocont_callback,
.indat_callback = usa90_indat_callback,
.outdat_callback = usa2x_outdat_callback,
.inack_callback = usa28_inack_callback,
@@ -1582,16 +1576,16 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
struct callbacks *cback;
int endp;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
s_priv = usb_get_serial_data(serial);
d_details = s_priv->device_details;
- /* Setup values for the various callback routines */
+ /* Setup values for the various callback routines */
cback = &keyspan_callbacks[d_details->msg_format];
- /* Allocate and set up urbs for each one that is in use,
- starting with instat endpoints */
+ /* Allocate and set up urbs for each one that is in use,
+ starting with instat endpoints */
s_priv->instat_urb = keyspan_setup_urb
(serial, d_details->instat_endpoint, USB_DIR_IN,
serial, s_priv->instat_buf, INSTAT_BUFLEN,
@@ -1607,8 +1601,8 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
cback->glocont_callback);
- /* Setup endpoints for each port specific thing */
- for (i = 0; i < d_details->num_ports; i ++) {
+ /* Setup endpoints for each port specific thing */
+ for (i = 0; i < d_details->num_ports; i++) {
port = serial->port[i];
p_priv = usb_get_serial_port_data(port);
@@ -1644,8 +1638,7 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
(serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
port, p_priv->outcont_buffer, 64,
cback->outcont_callback);
- }
-
+ }
}
/* usa19 function doesn't require prescaler */
@@ -1653,46 +1646,39 @@ static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
u8 *rate_low, u8 *prescaler, int portnum)
{
u32 b16, /* baud rate times 16 (actual rate used internally) */
- div, /* divisor */
+ div, /* divisor */
cnt; /* inverse of divisor (programmed into 8051) */
-
- dbg ("%s - %d.", __func__, baud_rate);
-
- /* prevent divide by zero... */
- if( (b16 = (baud_rate * 16L)) == 0) {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
- /* Any "standard" rate over 57k6 is marginal on the USA-19
- as we run out of divisor resolution. */
- if (baud_rate > 57600) {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
-
- /* calculate the divisor and the counter (its inverse) */
- if( (div = (baudclk / b16)) == 0) {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
- else {
+ dbg("%s - %d.", __func__, baud_rate);
+
+ /* prevent divide by zero... */
+ b16 = baud_rate * 16L;
+ if (b16 == 0)
+ return KEYSPAN_INVALID_BAUD_RATE;
+ /* Any "standard" rate over 57k6 is marginal on the USA-19
+ as we run out of divisor resolution. */
+ if (baud_rate > 57600)
+ return KEYSPAN_INVALID_BAUD_RATE;
+
+ /* calculate the divisor and the counter (its inverse) */
+ div = baudclk / b16;
+ if (div == 0)
+ return KEYSPAN_INVALID_BAUD_RATE;
+ else
cnt = 0 - div;
- }
- if(div > 0xffff) {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
+ if (div > 0xffff)
+ return KEYSPAN_INVALID_BAUD_RATE;
- /* return the counter values if non-null */
- if (rate_low) {
+ /* return the counter values if non-null */
+ if (rate_low)
*rate_low = (u8) (cnt & 0xff);
- }
- if (rate_hi) {
+ if (rate_hi)
*rate_hi = (u8) ((cnt >> 8) & 0xff);
- }
- if (rate_low && rate_hi) {
- dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low);
- }
-
- return (KEYSPAN_BAUD_RATE_OK);
+ if (rate_low && rate_hi)
+ dbg("%s - %d %02x %02x.",
+ __func__, baud_rate, *rate_hi, *rate_low);
+ return KEYSPAN_BAUD_RATE_OK;
}
/* usa19hs function doesn't require prescaler */
@@ -1700,34 +1686,35 @@ static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
u8 *rate_low, u8 *prescaler, int portnum)
{
u32 b16, /* baud rate times 16 (actual rate used internally) */
- div; /* divisor */
-
- dbg ("%s - %d.", __func__, baud_rate);
+ div; /* divisor */
- /* prevent divide by zero... */
- if( (b16 = (baud_rate * 16L)) == 0)
- return (KEYSPAN_INVALID_BAUD_RATE);
-
+ dbg("%s - %d.", __func__, baud_rate);
+ /* prevent divide by zero... */
+ b16 = baud_rate * 16L;
+ if (b16 == 0)
+ return KEYSPAN_INVALID_BAUD_RATE;
- /* calculate the divisor */
- if( (div = (baudclk / b16)) == 0)
- return (KEYSPAN_INVALID_BAUD_RATE);
+ /* calculate the divisor */
+ div = baudclk / b16;
+ if (div == 0)
+ return KEYSPAN_INVALID_BAUD_RATE;
- if(div > 0xffff)
- return (KEYSPAN_INVALID_BAUD_RATE);
+ if (div > 0xffff)
+ return KEYSPAN_INVALID_BAUD_RATE;
- /* return the counter values if non-null */
- if (rate_low)
+ /* return the counter values if non-null */
+ if (rate_low)
*rate_low = (u8) (div & 0xff);
-
- if (rate_hi)
+
+ if (rate_hi)
*rate_hi = (u8) ((div >> 8) & 0xff);
-
- if (rate_low && rate_hi)
- dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low);
-
- return (KEYSPAN_BAUD_RATE_OK);
+
+ if (rate_low && rate_hi)
+ dbg("%s - %d %02x %02x.",
+ __func__, baud_rate, *rate_hi, *rate_low);
+
+ return KEYSPAN_BAUD_RATE_OK;
}
static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
@@ -1735,64 +1722,61 @@ static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
{
u32 b16, /* baud rate times 16 (actual rate used internally) */
clk, /* clock with 13/8 prescaler */
- div, /* divisor using 13/8 prescaler */
+ div, /* divisor using 13/8 prescaler */
res, /* resulting baud rate using 13/8 prescaler */
diff, /* error using 13/8 prescaler */
smallest_diff;
u8 best_prescaler;
int i;
- dbg ("%s - %d.", __func__, baud_rate);
+ dbg("%s - %d.", __func__, baud_rate);
- /* prevent divide by zero */
- if( (b16 = baud_rate * 16L) == 0) {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
+ /* prevent divide by zero */
+ b16 = baud_rate * 16L;
+ if (b16 == 0)
+ return KEYSPAN_INVALID_BAUD_RATE;
- /* Calculate prescaler by trying them all and looking
- for best fit */
-
- /* start with largest possible difference */
+ /* Calculate prescaler by trying them all and looking
+ for best fit */
+
+ /* start with largest possible difference */
smallest_diff = 0xffffffff;
/* 0 is an invalid prescaler, used as a flag */
best_prescaler = 0;
- for(i = 8; i <= 0xff; ++i) {
+ for (i = 8; i <= 0xff; ++i) {
clk = (baudclk * 8) / (u32) i;
-
- if( (div = clk / b16) == 0) {
+
+ div = clk / b16;
+ if (div == 0)
continue;
- }
res = clk / div;
- diff= (res > b16) ? (res-b16) : (b16-res);
+ diff = (res > b16) ? (res-b16) : (b16-res);
- if(diff < smallest_diff) {
+ if (diff < smallest_diff) {
best_prescaler = i;
smallest_diff = diff;
}
}
- if(best_prescaler == 0) {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
+ if (best_prescaler == 0)
+ return KEYSPAN_INVALID_BAUD_RATE;
clk = (baudclk * 8) / (u32) best_prescaler;
div = clk / b16;
- /* return the divisor and prescaler if non-null */
- if (rate_low) {
+ /* return the divisor and prescaler if non-null */
+ if (rate_low)
*rate_low = (u8) (div & 0xff);
- }
- if (rate_hi) {
+ if (rate_hi)
*rate_hi = (u8) ((div >> 8) & 0xff);
- }
if (prescaler) {
*prescaler = best_prescaler;
/* dbg("%s - %d %d", __func__, *prescaler, div); */
}
- return (KEYSPAN_BAUD_RATE_OK);
+ return KEYSPAN_BAUD_RATE_OK;
}
/* USA-28 supports different maximum baud rates on each port */
@@ -1800,57 +1784,51 @@ static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
u8 *rate_low, u8 *prescaler, int portnum)
{
u32 b16, /* baud rate times 16 (actual rate used internally) */
- div, /* divisor */
+ div, /* divisor */
cnt; /* inverse of divisor (programmed into 8051) */
- dbg ("%s - %d.", __func__, baud_rate);
+ dbg("%s - %d.", __func__, baud_rate);
/* prevent divide by zero */
- if ((b16 = baud_rate * 16L) == 0)
- return (KEYSPAN_INVALID_BAUD_RATE);
-
- /* calculate the divisor and the counter (its inverse) */
- if ((div = (KEYSPAN_USA28_BAUDCLK / b16)) == 0) {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
- else {
+ b16 = baud_rate * 16L;
+ if (b16 == 0)
+ return KEYSPAN_INVALID_BAUD_RATE;
+
+ /* calculate the divisor and the counter (its inverse) */
+ div = KEYSPAN_USA28_BAUDCLK / b16;
+ if (div == 0)
+ return KEYSPAN_INVALID_BAUD_RATE;
+ else
cnt = 0 - div;
- }
- /* check for out of range, based on portnum,
- and return result */
- if(portnum == 0) {
- if(div > 0xffff)
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
- else {
- if(portnum == 1) {
- if(div > 0xff) {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
- }
- else {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
+ /* check for out of range, based on portnum,
+ and return result */
+ if (portnum == 0) {
+ if (div > 0xffff)
+ return KEYSPAN_INVALID_BAUD_RATE;
+ } else {
+ if (portnum == 1) {
+ if (div > 0xff)
+ return KEYSPAN_INVALID_BAUD_RATE;
+ } else
+ return KEYSPAN_INVALID_BAUD_RATE;
}
/* return the counter values if not NULL
(port 1 will ignore retHi) */
- if (rate_low) {
+ if (rate_low)
*rate_low = (u8) (cnt & 0xff);
- }
- if (rate_hi) {
+ if (rate_hi)
*rate_hi = (u8) ((cnt >> 8) & 0xff);
- }
- dbg ("%s - %d OK.", __func__, baud_rate);
- return (KEYSPAN_BAUD_RATE_OK);
+ dbg("%s - %d OK.", __func__, baud_rate);
+ return KEYSPAN_BAUD_RATE_OK;
}
static int keyspan_usa26_send_setup(struct usb_serial *serial,
struct usb_serial_port *port,
int reset_port)
{
- struct keyspan_usa26_portControlMessage msg;
+ struct keyspan_usa26_portControlMessage msg;
struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
@@ -1858,7 +1836,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
struct urb *this_urb;
int device_port, err;
- dbg ("%s reset=%d", __func__, reset_port);
+ dbg("%s reset=%d", __func__, reset_port);
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
@@ -1881,22 +1859,22 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
if ((reset_port + 1) > p_priv->resend_cont)
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
- /* dbg ("%s - already writing", __func__); */
+ /* dbg("%s - already writing", __func__); */
mdelay(5);
- return(-1);
+ return -1;
}
- memset(&msg, 0, sizeof (struct keyspan_usa26_portControlMessage));
-
- /* Only set baud rate if it's changed */
+ memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
+
+ /* Only set baud rate if it's changed */
if (p_priv->old_baud != p_priv->baud) {
p_priv->old_baud = p_priv->baud;
msg.setClocking = 0xff;
if (d_details->calculate_baud_rate
(p_priv->baud, d_details->baudclk, &msg.baudHi,
- &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
- dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
- p_priv->baud);
+ &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
+ dbg("%s - Invalid baud rate %d requested, using 9600.",
+ __func__, p_priv->baud);
msg.baudLo = 0;
msg.baudHi = 125; /* Values for 9600 baud */
msg.prescaler = 10;
@@ -1922,7 +1900,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
if (p_priv->cflag & PARENB) {
/* note USA_PARITY_NONE == 0 */
msg.lcr |= (p_priv->cflag & PARODD)?
- USA_PARITY_ODD: USA_PARITY_EVEN;
+ USA_PARITY_ODD : USA_PARITY_EVEN;
}
msg.setLcr = 0xff;
@@ -1963,7 +1941,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
/* Sending intermediate configs */
else {
- msg._txOn = (! p_priv->break_on);
+ msg._txOn = (!p_priv->break_on);
msg._txOff = 0;
msg.txFlush = 0;
msg.txBreak = (p_priv->break_on);
@@ -1975,23 +1953,23 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
msg.resetDataToggle = 0x0;
}
- /* Do handshaking outputs */
+ /* Do handshaking outputs */
msg.setTxTriState_setRts = 0xff;
msg.txTriState_rts = p_priv->rts_state;
msg.setHskoa_setDtr = 0xff;
msg.hskoa_dtr = p_priv->dtr_state;
-
+
p_priv->resend_cont = 0;
- memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
-
+ memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
+
/* send the data out the device on control endpoint */
this_urb->transfer_buffer_length = sizeof(msg);
this_urb->dev = serial->dev;
- if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(this_urb, GFP_ATOMIC);
+ if (err != 0)
dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
- }
#if 0
else {
dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__
@@ -2007,14 +1985,14 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
struct usb_serial_port *port,
int reset_port)
{
- struct keyspan_usa28_portControlMessage msg;
+ struct keyspan_usa28_portControlMessage msg;
struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
struct urb *this_urb;
int device_port, err;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
@@ -2022,7 +2000,8 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
device_port = port->number - port->serial->minor;
/* only do something if we have a bulk out endpoint */
- if ((this_urb = p_priv->outcont_urb) == NULL) {
+ this_urb = p_priv->outcont_urb;
+ if (this_urb == NULL) {
dbg("%s - oops no urb.", __func__);
return -1;
}
@@ -2032,17 +2011,18 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
if ((reset_port + 1) > p_priv->resend_cont)
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
- dbg ("%s already writing", __func__);
+ dbg("%s already writing", __func__);
mdelay(5);
- return(-1);
+ return -1;
}
- memset(&msg, 0, sizeof (struct keyspan_usa28_portControlMessage));
+ memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
msg.setBaudRate = 1;
if (d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
- &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
- dbg("%s - Invalid baud rate requested %d.", __func__, p_priv->baud);
+ &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
+ dbg("%s - Invalid baud rate requested %d.",
+ __func__, p_priv->baud);
msg.baudLo = 0xff;
msg.baudHi = 0xb2; /* Values for 9600 baud */
}
@@ -2053,7 +2033,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
msg.xonFlowControl = 0;
- /* Do handshaking outputs, DTR is inverted relative to RTS */
+ /* Do handshaking outputs, DTR is inverted relative to RTS */
msg.rts = p_priv->rts_state;
msg.dtr = p_priv->dtr_state;
@@ -2095,7 +2075,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
}
/* Sending intermediate configs */
else {
- msg._txOn = (! p_priv->break_on);
+ msg._txOn = (!p_priv->break_on);
msg._txOff = 0;
msg.txFlush = 0;
msg.txForceXoff = 0;
@@ -2109,15 +2089,15 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
}
p_priv->resend_cont = 0;
- memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
+ memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
/* send the data out the device on control endpoint */
this_urb->transfer_buffer_length = sizeof(msg);
this_urb->dev = serial->dev;
- if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(this_urb, GFP_ATOMIC);
+ if (err != 0)
dbg("%s - usb_submit_urb(setup) failed", __func__);
- }
#if 0
else {
dbg("%s - usb_submit_urb(setup) OK %d bytes", __func__,
@@ -2140,7 +2120,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
struct urb *this_urb;
int err, device_port;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
@@ -2151,7 +2131,9 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
/* Work out which port within the device is being setup */
device_port = port->number - port->serial->minor;
- dbg("%s - endpoint %d port %d (%d)",__func__, usb_pipeendpoint(this_urb->pipe), port->number, device_port);
+ dbg("%s - endpoint %d port %d (%d)",
+ __func__, usb_pipeendpoint(this_urb->pipe),
+ port->number, device_port);
/* Make sure we have an urb then send the message */
if (this_urb == NULL) {
@@ -2165,30 +2147,30 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
- /* dbg ("%s - already writing", __func__); */
+ /* dbg("%s - already writing", __func__); */
mdelay(5);
- return(-1);
+ return -1;
}
- memset(&msg, 0, sizeof (struct keyspan_usa49_portControlMessage));
+ memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
/*msg.portNumber = port->number;*/
msg.portNumber = device_port;
-
- /* Only set baud rate if it's changed */
+
+ /* Only set baud rate if it's changed */
if (p_priv->old_baud != p_priv->baud) {
p_priv->old_baud = p_priv->baud;
msg.setClocking = 0xff;
if (d_details->calculate_baud_rate
(p_priv->baud, d_details->baudclk, &msg.baudHi,
- &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
- dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
- p_priv->baud);
+ &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
+ dbg("%s - Invalid baud rate %d requested, using 9600.",
+ __func__, p_priv->baud);
msg.baudLo = 0;
msg.baudHi = 125; /* Values for 9600 baud */
msg.prescaler = 10;
}
- //msg.setPrescaler = 0xff;
+ /* msg.setPrescaler = 0xff; */
}
msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
@@ -2209,19 +2191,19 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
if (p_priv->cflag & PARENB) {
/* note USA_PARITY_NONE == 0 */
msg.lcr |= (p_priv->cflag & PARODD)?
- USA_PARITY_ODD: USA_PARITY_EVEN;
+ USA_PARITY_ODD : USA_PARITY_EVEN;
}
msg.setLcr = 0xff;
msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
msg.xonFlowControl = 0;
msg.setFlowControl = 0xff;
-
+
msg.forwardingLength = 16;
msg.xonChar = 17;
msg.xoffChar = 19;
- /* Opening port */
+ /* Opening port */
if (reset_port == 1) {
msg._txOn = 1;
msg._txOff = 0;
@@ -2253,7 +2235,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
}
/* Sending intermediate configs */
else {
- msg._txOn = (! p_priv->break_on);
+ msg._txOn = (!p_priv->break_on);
msg._txOff = 0;
msg.txFlush = 0;
msg.txBreak = (p_priv->break_on);
@@ -2267,16 +2249,17 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
msg.disablePort = 0;
}
- /* Do handshaking outputs */
+ /* Do handshaking outputs */
msg.setRts = 0xff;
msg.rts = p_priv->rts_state;
msg.setDtr = 0xff;
msg.dtr = p_priv->dtr_state;
-
+
p_priv->resend_cont = 0;
- /* if the device is a 49wg, we send control message on usb control EP 0 */
+ /* if the device is a 49wg, we send control message on usb
+ control EP 0 */
if (d_details->product_id == keyspan_usa49wg_product_id) {
dr = (void *)(s_priv->ctrl_buf);
@@ -2286,23 +2269,24 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
dr->wIndex = 0;
dr->wLength = cpu_to_le16(sizeof(msg));
- memcpy (s_priv->glocont_buf, &msg, sizeof(msg));
+ memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
- usb_fill_control_urb(this_urb, serial->dev, usb_sndctrlpipe(serial->dev, 0),
- (unsigned char *)dr, s_priv->glocont_buf, sizeof(msg),
- usa49_glocont_callback, serial);
+ usb_fill_control_urb(this_urb, serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ (unsigned char *)dr, s_priv->glocont_buf,
+ sizeof(msg), usa49_glocont_callback, serial);
} else {
memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
-
+
/* send the data out the device on control endpoint */
this_urb->transfer_buffer_length = sizeof(msg);
this_urb->dev = serial->dev;
}
- if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(this_urb, GFP_ATOMIC);
+ if (err != 0)
dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
- }
#if 0
else {
dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__,
@@ -2318,7 +2302,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
struct usb_serial_port *port,
int reset_port)
{
- struct keyspan_usa90_portControlMessage msg;
+ struct keyspan_usa90_portControlMessage msg;
struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
@@ -2326,14 +2310,15 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
int err;
u8 prescaler;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
d_details = s_priv->device_details;
/* only do something if we have a bulk out endpoint */
- if ((this_urb = p_priv->outcont_urb) == NULL) {
+ this_urb = p_priv->outcont_urb;
+ if (this_urb == NULL) {
dbg("%s - oops no urb.", __func__);
return -1;
}
@@ -2343,24 +2328,24 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
if ((reset_port + 1) > p_priv->resend_cont)
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
- dbg ("%s already writing", __func__);
+ dbg("%s already writing", __func__);
mdelay(5);
- return(-1);
+ return -1;
}
- memset(&msg, 0, sizeof (struct keyspan_usa90_portControlMessage));
+ memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
- /* Only set baud rate if it's changed */
+ /* Only set baud rate if it's changed */
if (p_priv->old_baud != p_priv->baud) {
p_priv->old_baud = p_priv->baud;
msg.setClocking = 0x01;
if (d_details->calculate_baud_rate
(p_priv->baud, d_details->baudclk, &msg.baudHi,
- &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE ) {
- dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
- p_priv->baud);
+ &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
+ dbg("%s - Invalid baud rate %d requested, using 9600.",
+ __func__, p_priv->baud);
p_priv->baud = 9600;
- d_details->calculate_baud_rate (p_priv->baud, d_details->baudclk,
+ d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
&msg.baudHi, &msg.baudLo, &prescaler, 0);
}
msg.setRxMode = 1;
@@ -2368,13 +2353,10 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
}
/* modes must always be correctly specified */
- if (p_priv->baud > 57600)
- {
+ if (p_priv->baud > 57600) {
msg.rxMode = RXMODE_DMA;
msg.txMode = TXMODE_DMA;
- }
- else
- {
+ } else {
msg.rxMode = RXMODE_BYHAND;
msg.txMode = TXMODE_BYHAND;
}
@@ -2397,7 +2379,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
if (p_priv->cflag & PARENB) {
/* note USA_PARITY_NONE == 0 */
msg.lcr |= (p_priv->cflag & PARODD)?
- USA_PARITY_ODD: USA_PARITY_EVEN;
+ USA_PARITY_ODD : USA_PARITY_EVEN;
}
if (p_priv->old_cflag != p_priv->cflag) {
p_priv->old_cflag = p_priv->cflag;
@@ -2408,47 +2390,46 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
msg.txFlowControl = TXFLOW_CTS;
msg.setTxFlowControl = 0x01;
msg.setRxFlowControl = 0x01;
-
+
msg.rxForwardingLength = 16;
- msg.rxForwardingTimeout = 16;
+ msg.rxForwardingTimeout = 16;
msg.txAckSetting = 0;
msg.xonChar = 17;
msg.xoffChar = 19;
- /* Opening port */
+ /* Opening port */
if (reset_port == 1) {
msg.portEnabled = 1;
msg.rxFlush = 1;
msg.txBreak = (p_priv->break_on);
}
/* Closing port */
- else if (reset_port == 2) {
+ else if (reset_port == 2)
msg.portEnabled = 0;
- }
/* Sending intermediate configs */
else {
- if (port->open_count)
+ if (port->port.count)
msg.portEnabled = 1;
msg.txBreak = (p_priv->break_on);
}
- /* Do handshaking outputs */
+ /* Do handshaking outputs */
msg.setRts = 0x01;
msg.rts = p_priv->rts_state;
msg.setDtr = 0x01;
msg.dtr = p_priv->dtr_state;
-
+
p_priv->resend_cont = 0;
- memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
-
+ memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
+
/* send the data out the device on control endpoint */
this_urb->transfer_buffer_length = sizeof(msg);
this_urb->dev = serial->dev;
- if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(this_urb, GFP_ATOMIC);
+ if (err != 0)
dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
- }
return 0;
}
@@ -2463,7 +2444,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
struct urb *this_urb;
int err, device_port;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
@@ -2486,9 +2467,9 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
if ((reset_port + 1) > p_priv->resend_cont)
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
- /* dbg ("%s - already writing", __func__); */
+ /* dbg("%s - already writing", __func__); */
mdelay(5);
- return(-1);
+ return -1;
}
memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
@@ -2501,9 +2482,9 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
msg.setClocking = 0xff;
if (d_details->calculate_baud_rate
(p_priv->baud, d_details->baudclk, &msg.baudHi,
- &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
- dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
- p_priv->baud);
+ &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
+ dbg("%s - Invalid baud rate %d requested, using 9600.",
+ __func__, p_priv->baud);
msg.baudLo = 0;
msg.baudHi = 125; /* Values for 9600 baud */
msg.prescaler = 10;
@@ -2529,7 +2510,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
if (p_priv->cflag & PARENB) {
/* note USA_PARITY_NONE == 0 */
msg.lcr |= (p_priv->cflag & PARODD)?
- USA_PARITY_ODD: USA_PARITY_EVEN;
+ USA_PARITY_ODD : USA_PARITY_EVEN;
}
msg.setLcr = 0xff;
@@ -2566,7 +2547,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
msg.resetDataToggle = 0;
} else {
/* Sending intermediate configs */
- msg._txOn = (! p_priv->break_on);
+ msg._txOn = (!p_priv->break_on);
msg._txOff = 0;
msg.txFlush = 0;
msg.txBreak = (p_priv->break_on);
@@ -2606,7 +2587,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
struct keyspan_serial_private *s_priv;
const struct keyspan_device_details *d_details;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
s_priv = usb_get_serial_data(serial);
d_details = s_priv->device_details;
@@ -2633,7 +2614,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
/* Gets called by the "real" driver (ie once firmware is loaded
and renumeration has taken place. */
-static int keyspan_startup (struct usb_serial *serial)
+static int keyspan_startup(struct usb_serial *serial)
{
int i, err;
struct usb_serial_port *port;
@@ -2644,17 +2625,20 @@ static int keyspan_startup (struct usb_serial *serial)
dbg("%s", __func__);
for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
- if (d_details->product_id == le16_to_cpu(serial->dev->descriptor.idProduct))
+ if (d_details->product_id ==
+ le16_to_cpu(serial->dev->descriptor.idProduct))
break;
if (d_details == NULL) {
- dev_err(&serial->dev->dev, "%s - unknown product id %x\n", __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
+ dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
+ __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
return 1;
}
/* Setup private data for serial driver */
s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
if (!s_priv) {
- dbg("%s - kmalloc for keyspan_serial_private failed.", __func__);
+ dbg("%s - kmalloc for keyspan_serial_private failed.",
+ __func__);
return -ENOMEM;
}
@@ -2664,10 +2648,11 @@ static int keyspan_startup (struct usb_serial *serial)
/* Now setup per port private data */
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
- p_priv = kzalloc(sizeof(struct keyspan_port_private), GFP_KERNEL);
+ p_priv = kzalloc(sizeof(struct keyspan_port_private),
+ GFP_KERNEL);
if (!p_priv) {
dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i);
- return (1);
+ return 1;
}
p_priv->device_details = d_details;
usb_set_serial_port_data(port, p_priv);
@@ -2689,11 +2674,11 @@ static int keyspan_startup (struct usb_serial *serial)
dbg("%s - submit indat urb failed %d", __func__,
err);
}
-
+
return 0;
}
-static void keyspan_shutdown (struct usb_serial *serial)
+static void keyspan_shutdown(struct usb_serial *serial)
{
int i, j;
struct usb_serial_port *port;
@@ -2745,8 +2730,8 @@ static void keyspan_shutdown (struct usb_serial *serial)
}
}
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("keyspan/usa28.fw");
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 8bf72639b14..38b4582e073 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -35,17 +35,18 @@
/* Function prototypes for Keyspan serial converter */
-static int keyspan_open (struct usb_serial_port *port,
+static int keyspan_open (struct tty_struct *tty,
+ struct usb_serial_port *port,
struct file *filp);
-static void keyspan_close (struct usb_serial_port *port,
+static void keyspan_close (struct tty_struct *tty,
+ struct usb_serial_port *port,
struct file *filp);
static int keyspan_startup (struct usb_serial *serial);
static void keyspan_shutdown (struct usb_serial *serial);
-static void keyspan_rx_throttle (struct usb_serial_port *port);
-static void keyspan_rx_unthrottle (struct usb_serial_port *port);
-static int keyspan_write_room (struct usb_serial_port *port);
+static int keyspan_write_room (struct tty_struct *tty);
-static int keyspan_write (struct usb_serial_port *port,
+static int keyspan_write (struct tty_struct *tty,
+ struct usb_serial_port *port,
const unsigned char *buf,
int count);
@@ -53,18 +54,14 @@ static void keyspan_send_setup (struct usb_serial_port *port,
int reset_port);
-static int keyspan_chars_in_buffer (struct usb_serial_port *port);
-static int keyspan_ioctl (struct usb_serial_port *port,
- struct file *file,
- unsigned int cmd,
- unsigned long arg);
-static void keyspan_set_termios (struct usb_serial_port *port,
+static void keyspan_set_termios (struct tty_struct *tty,
+ struct usb_serial_port *port,
struct ktermios *old);
-static void keyspan_break_ctl (struct usb_serial_port *port,
+static void keyspan_break_ctl (struct tty_struct *tty,
int break_state);
-static int keyspan_tiocmget (struct usb_serial_port *port,
+static int keyspan_tiocmget (struct tty_struct *tty,
struct file *file);
-static int keyspan_tiocmset (struct usb_serial_port *port,
+static int keyspan_tiocmset (struct tty_struct *tty,
struct file *file, unsigned int set,
unsigned int clear);
static int keyspan_fake_startup (struct usb_serial *serial);
@@ -567,10 +564,6 @@ static struct usb_serial_driver keyspan_1port_device = {
.close = keyspan_close,
.write = keyspan_write,
.write_room = keyspan_write_room,
- .chars_in_buffer = keyspan_chars_in_buffer,
- .throttle = keyspan_rx_throttle,
- .unthrottle = keyspan_rx_unthrottle,
- .ioctl = keyspan_ioctl,
.set_termios = keyspan_set_termios,
.break_ctl = keyspan_break_ctl,
.tiocmget = keyspan_tiocmget,
@@ -591,10 +584,6 @@ static struct usb_serial_driver keyspan_2port_device = {
.close = keyspan_close,
.write = keyspan_write,
.write_room = keyspan_write_room,
- .chars_in_buffer = keyspan_chars_in_buffer,
- .throttle = keyspan_rx_throttle,
- .unthrottle = keyspan_rx_unthrottle,
- .ioctl = keyspan_ioctl,
.set_termios = keyspan_set_termios,
.break_ctl = keyspan_break_ctl,
.tiocmget = keyspan_tiocmget,
@@ -615,10 +604,6 @@ static struct usb_serial_driver keyspan_4port_device = {
.close = keyspan_close,
.write = keyspan_write,
.write_room = keyspan_write_room,
- .chars_in_buffer = keyspan_chars_in_buffer,
- .throttle = keyspan_rx_throttle,
- .unthrottle = keyspan_rx_unthrottle,
- .ioctl = keyspan_ioctl,
.set_termios = keyspan_set_termios,
.break_ctl = keyspan_break_ctl,
.tiocmget = keyspan_tiocmget,
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 60b3e22bd63..040040a267d 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -10,8 +10,9 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
- *
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
+ *
* (09/07/2001) gkh
* cleaned up the Xircom support. Added ids for Entregra device which is
* the same as the Xircom device. Enabled the code to be compiled for
@@ -21,23 +22,24 @@
* support for Xircom PGSDB9
*
* (05/31/2001) gkh
- * switched from using spinlock to a semaphore, which fixes lots of problems.
+ * switched from using spinlock to a semaphore, which fixes lots of
+ * problems.
*
* (04/08/2001) gb
* Identify version on module load.
- *
+ *
* (11/01/2000) Adam J. Richter
* usb_device_id table support
- *
+ *
* (10/05/2000) gkh
* Fixed bug with urb->dev not being set properly, now that the usb
* core needs it.
- *
+ *
* (08/28/2000) gkh
* Added locks for SMP safeness.
- * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
+ * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
* than once.
- *
+ *
* (07/20/2000) borchers
* - keyspan_pda_write no longer sleeps if it is called on interrupt time;
* PPP and the line discipline with stty echo on can call write on
@@ -55,14 +57,14 @@
* than done directly from the callback to avoid the race in write_chan
* - keyspan_pda_chars_in_buffer also indicates its buffer is full if the
* urb status is -EINPROGRESS, meaning it cannot write at the moment
- *
+ *
* (07/19/2000) gkh
* Added module_init and module_exit functions to handle the fact that this
* driver is a loadable module now.
*
* (03/26/2000) gkh
* Split driver up into device specific pieces.
- *
+ *
*/
@@ -78,7 +80,7 @@
#include <linux/workqueue.h>
#include <linux/firmware.h>
#include <linux/ihex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -135,7 +137,7 @@ static struct usb_device_id id_table_combined [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver keyspan_pda_driver = {
.name = "keyspan_pda",
@@ -159,9 +161,9 @@ static struct usb_device_id id_table_fake [] = {
#ifdef XIRCOM
static struct usb_device_id id_table_fake_xircom [] = {
- { USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID) },
- { USB_DEVICE(ENTREGRA_VENDOR_ID, ENTREGRA_FAKE_ID) },
- { }
+ { USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID) },
+ { USB_DEVICE(ENTREGRA_VENDOR_ID, ENTREGRA_FAKE_ID) },
+ { }
};
#endif
@@ -171,7 +173,7 @@ static void keyspan_pda_wakeup_write(struct work_struct *work)
container_of(work, struct keyspan_pda_private, wakeup_work);
struct usb_serial_port *port = priv->port;
- tty_wakeup(port->tty);
+ tty_wakeup(port->port.tty);
}
static void keyspan_pda_request_unthrottle(struct work_struct *work)
@@ -184,7 +186,7 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work)
dbg(" request_unthrottle");
/* ask the device to tell us when the tx buffer becomes
sufficiently empty */
- result = usb_control_msg(serial->dev,
+ result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
7, /* request_unthrottle */
USB_TYPE_VENDOR | USB_RECIP_INTERFACE
@@ -195,17 +197,16 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work)
0,
2000);
if (result < 0)
- dbg("%s - error %d from usb_control_msg",
+ dbg("%s - error %d from usb_control_msg",
__func__, result);
}
-static void keyspan_pda_rx_interrupt (struct urb *urb)
+static void keyspan_pda_rx_interrupt(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
- struct tty_struct *tty = port->tty;
+ struct tty_struct *tty = port->port.tty;
unsigned char *data = urb->transfer_buffer;
- int i;
int retval;
int status = urb->status;
struct keyspan_pda_private *priv;
@@ -228,14 +229,13 @@ static void keyspan_pda_rx_interrupt (struct urb *urb)
goto exit;
}
- /* see if the message is data or a status interrupt */
+ /* see if the message is data or a status interrupt */
switch (data[0]) {
case 0:
/* rest of message is rx data */
if (urb->actual_length) {
- for (i = 1; i < urb->actual_length ; ++i) {
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_insert_flip_string(tty, data + 1,
+ urb->actual_length - 1);
tty_flip_buffer_push(tty);
}
break;
@@ -259,14 +259,14 @@ static void keyspan_pda_rx_interrupt (struct urb *urb)
}
exit:
- retval = usb_submit_urb (urb, GFP_ATOMIC);
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- err ("%s - usb_submit_urb failed with result %d",
+ err("%s - usb_submit_urb failed with result %d",
__func__, retval);
}
-static void keyspan_pda_rx_throttle (struct usb_serial_port *port)
+static void keyspan_pda_rx_throttle(struct tty_struct *tty)
{
/* stop receiving characters. We just turn off the URB request, and
let chars pile up in the device. If we're doing hardware
@@ -274,14 +274,15 @@ static void keyspan_pda_rx_throttle (struct usb_serial_port *port)
fills up. If we're doing XON/XOFF, this would be a good time to
send an XOFF, although it might make sense to foist that off
upon the device too. */
-
+ struct usb_serial_port *port = tty->driver_data;
dbg("keyspan_pda_rx_throttle port %d", port->number);
usb_kill_urb(port->interrupt_in_urb);
}
-static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port)
+static void keyspan_pda_rx_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
/* just restart the receive interrupt URB */
dbg("keyspan_pda_rx_unthrottle port %d", port->number);
port->interrupt_in_urb->dev = port->serial->dev;
@@ -291,32 +292,52 @@ static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port)
}
-static speed_t keyspan_pda_setbaud (struct usb_serial *serial, speed_t baud)
+static speed_t keyspan_pda_setbaud(struct usb_serial *serial, speed_t baud)
{
int rc;
int bindex;
- switch(baud) {
- case 110: bindex = 0; break;
- case 300: bindex = 1; break;
- case 1200: bindex = 2; break;
- case 2400: bindex = 3; break;
- case 4800: bindex = 4; break;
- case 9600: bindex = 5; break;
- case 19200: bindex = 6; break;
- case 38400: bindex = 7; break;
- case 57600: bindex = 8; break;
- case 115200: bindex = 9; break;
- default:
- bindex = 5; /* Default to 9600 */
- baud = 9600;
+ switch (baud) {
+ case 110:
+ bindex = 0;
+ break;
+ case 300:
+ bindex = 1;
+ break;
+ case 1200:
+ bindex = 2;
+ break;
+ case 2400:
+ bindex = 3;
+ break;
+ case 4800:
+ bindex = 4;
+ break;
+ case 9600:
+ bindex = 5;
+ break;
+ case 19200:
+ bindex = 6;
+ break;
+ case 38400:
+ bindex = 7;
+ break;
+ case 57600:
+ bindex = 8;
+ break;
+ case 115200:
+ bindex = 9;
+ break;
+ default:
+ bindex = 5; /* Default to 9600 */
+ baud = 9600;
}
/* rather than figure out how to sleep while waiting for this
to complete, I just use the "legacy" API. */
rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
0, /* set baud */
- USB_TYPE_VENDOR
+ USB_TYPE_VENDOR
| USB_RECIP_INTERFACE
| USB_DIR_OUT, /* type */
bindex, /* value */
@@ -330,8 +351,9 @@ static speed_t keyspan_pda_setbaud (struct usb_serial *serial, speed_t baud)
}
-static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state)
+static void keyspan_pda_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
int value;
int result;
@@ -341,11 +363,11 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state
else
value = 0; /* clear break */
result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- 4, /* set break */
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- value, 0, NULL, 0, 2000);
+ 4, /* set break */
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ value, 0, NULL, 0, 2000);
if (result < 0)
- dbg("%s - error %d from usb_control_msg",
+ dbg("%s - error %d from usb_control_msg",
__func__, result);
/* there is something funky about this.. the TCSBRK that 'cu' performs
ought to translate into a break_ctl(-1),break_ctl(0) pair HZ/4
@@ -354,8 +376,8 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state
}
-static void keyspan_pda_set_termios (struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void keyspan_pda_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
speed_t speed;
@@ -380,7 +402,7 @@ static void keyspan_pda_set_termios (struct usb_serial_port *port,
For now, just do baud. */
- speed = tty_get_baud_rate(port->tty);
+ speed = tty_get_baud_rate(tty);
speed = keyspan_pda_setbaud(serial, speed);
if (speed == 0) {
@@ -390,8 +412,8 @@ static void keyspan_pda_set_termios (struct usb_serial_port *port,
}
/* Only speed can change so copy the old h/w parameters
then encode the new speed */
- tty_termios_copy_hw(port->tty->termios, old_termios);
- tty_encode_baud_rate(port->tty, speed, speed);
+ tty_termios_copy_hw(tty->termios, old_termios);
+ tty_encode_baud_rate(tty, speed, speed);
}
@@ -425,8 +447,9 @@ static int keyspan_pda_set_modem_info(struct usb_serial *serial,
return rc;
}
-static int keyspan_pda_tiocmget(struct usb_serial_port *port, struct file *file)
+static int keyspan_pda_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
int rc;
unsigned char status;
@@ -445,9 +468,10 @@ static int keyspan_pda_tiocmget(struct usb_serial_port *port, struct file *file)
return value;
}
-static int keyspan_pda_tiocmset(struct usb_serial_port *port, struct file *file,
+static int keyspan_pda_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
int rc;
unsigned char status;
@@ -469,23 +493,8 @@ static int keyspan_pda_tiocmset(struct usb_serial_port *port, struct file *file,
return rc;
}
-static int keyspan_pda_ioctl(struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- switch (cmd) {
- case TIOCMIWAIT:
- /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
- /* TODO */
- case TIOCGICOUNT:
- /* return count of modemline transitions */
- return 0; /* TODO */
- }
-
- return -ENOIOCTLCMD;
-}
-
-static int keyspan_pda_write(struct usb_serial_port *port,
- const unsigned char *buf, int count)
+static int keyspan_pda_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
int request_unthrottle = 0;
@@ -501,10 +510,10 @@ static int keyspan_pda_write(struct usb_serial_port *port,
select() or poll() too) until we receive that unthrottle interrupt.
Block if we can't write anything at all, otherwise write as much as
we can. */
- dbg("keyspan_pda_write(%d)",count);
+ dbg("keyspan_pda_write(%d)", count);
if (count == 0) {
dbg(" write request of 0 bytes");
- return (0);
+ return 0;
}
/* we might block because of:
@@ -531,7 +540,7 @@ static int keyspan_pda_write(struct usb_serial_port *port,
scheduler time, since usb_control_msg() sleeps. */
if (count > priv->tx_room && !in_interrupt()) {
unsigned char room;
- rc = usb_control_msg(serial->dev,
+ rc = usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
6, /* write_room */
USB_TYPE_VENDOR | USB_RECIP_INTERFACE
@@ -562,7 +571,7 @@ static int keyspan_pda_write(struct usb_serial_port *port,
if (count) {
/* now transfer data */
- memcpy (port->write_urb->transfer_buffer, buf, count);
+ memcpy(port->write_urb->transfer_buffer, buf, count);
/* send the data out the bulk port */
port->write_urb->transfer_buffer_length = count;
@@ -574,8 +583,7 @@ static int keyspan_pda_write(struct usb_serial_port *port,
dbg(" usb_submit_urb(write bulk) failed");
goto exit;
}
- }
- else {
+ } else {
/* There wasn't any room left, so we are throttled until
the buffer empties a bit */
request_unthrottle = 1;
@@ -594,7 +602,7 @@ exit:
}
-static void keyspan_pda_write_bulk_callback (struct urb *urb)
+static void keyspan_pda_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct keyspan_pda_private *priv;
@@ -607,22 +615,21 @@ static void keyspan_pda_write_bulk_callback (struct urb *urb)
}
-static int keyspan_pda_write_room (struct usb_serial_port *port)
+static int keyspan_pda_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct keyspan_pda_private *priv;
-
priv = usb_get_serial_port_data(port);
-
/* used by n_tty.c for processing of tabs and such. Giving it our
conservative guess is probably good enough, but needs testing by
running a console through the device. */
-
- return (priv->tx_room);
+ return priv->tx_room;
}
-static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port)
+static int keyspan_pda_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct keyspan_pda_private *priv;
unsigned long flags;
int ret = 0;
@@ -640,7 +647,8 @@ static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port)
}
-static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
+static int keyspan_pda_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
unsigned char room;
@@ -672,8 +680,8 @@ static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
/* the normal serial device seems to always turn on DTR and RTS here,
so do the same */
- if (port->tty->termios->c_cflag & CBAUD)
- keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) );
+ if (tty && (tty->termios->c_cflag & CBAUD))
+ keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2));
else
keyspan_pda_set_modem_info(serial, 0);
@@ -690,13 +698,15 @@ error:
}
-static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp)
+static void keyspan_pda_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
if (serial->dev) {
- /* the normal serial device seems to always shut off DTR and RTS now */
- if (port->tty->termios->c_cflag & HUPCL)
+ /* the normal serial device seems to always shut
+ off DTR and RTS now */
+ if (tty->termios->c_cflag & HUPCL)
keyspan_pda_set_modem_info(serial, 0);
/* shutdown our bulk reads and writes */
@@ -707,7 +717,7 @@ static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp)
/* download the firmware to a "fake" device (pre-renumeration) */
-static int keyspan_pda_fake_startup (struct usb_serial *serial)
+static int keyspan_pda_fake_startup(struct usb_serial *serial)
{
int response;
const char *fw_name;
@@ -756,10 +766,10 @@ static int keyspan_pda_fake_startup (struct usb_serial *serial)
response = ezusb_set_reset(serial, 0);
/* we want this device to fail to have a driver assigned to it. */
- return (1);
+ return 1;
}
-static int keyspan_pda_startup (struct usb_serial *serial)
+static int keyspan_pda_startup(struct usb_serial *serial)
{
struct keyspan_pda_private *priv;
@@ -769,20 +779,20 @@ static int keyspan_pda_startup (struct usb_serial *serial)
priv = kmalloc(sizeof(struct keyspan_pda_private), GFP_KERNEL);
if (!priv)
- return (1); /* error */
+ return 1; /* error */
usb_set_serial_port_data(serial->port[0], priv);
init_waitqueue_head(&serial->port[0]->write_wait);
INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write);
INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle);
priv->serial = serial;
priv->port = serial->port[0];
- return (0);
+ return 0;
}
-static void keyspan_pda_shutdown (struct usb_serial *serial)
+static void keyspan_pda_shutdown(struct usb_serial *serial)
{
dbg("%s", __func__);
-
+
kfree(usb_get_serial_port_data(serial->port[0]));
}
@@ -832,7 +842,6 @@ static struct usb_serial_driver keyspan_pda_device = {
.chars_in_buffer = keyspan_pda_chars_in_buffer,
.throttle = keyspan_pda_rx_throttle,
.unthrottle = keyspan_pda_rx_unthrottle,
- .ioctl = keyspan_pda_ioctl,
.set_termios = keyspan_pda_set_termios,
.break_ctl = keyspan_pda_break_ctl,
.tiocmget = keyspan_pda_tiocmget,
@@ -842,7 +851,7 @@ static struct usb_serial_driver keyspan_pda_device = {
};
-static int __init keyspan_pda_init (void)
+static int __init keyspan_pda_init(void)
{
int retval;
retval = usb_serial_register(&keyspan_pda_device);
@@ -863,7 +872,7 @@ static int __init keyspan_pda_init (void)
goto failed_usb_register;
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
-failed_usb_register:
+failed_usb_register:
#ifdef XIRCOM
usb_serial_deregister(&xircom_pgs_fake_device);
failed_xircom_register:
@@ -880,15 +889,15 @@ failed_pda_register:
}
-static void __exit keyspan_pda_exit (void)
+static void __exit keyspan_pda_exit(void)
{
- usb_deregister (&keyspan_pda_driver);
- usb_serial_deregister (&keyspan_pda_device);
+ usb_deregister(&keyspan_pda_driver);
+ usb_serial_deregister(&keyspan_pda_device);
#ifdef KEYSPAN
- usb_serial_deregister (&keyspan_pda_fake_device);
+ usb_serial_deregister(&keyspan_pda_fake_device);
#endif
#ifdef XIRCOM
- usb_serial_deregister (&xircom_pgs_fake_device);
+ usb_serial_deregister(&xircom_pgs_fake_device);
#endif
}
@@ -896,8 +905,8 @@ static void __exit keyspan_pda_exit (void)
module_init(keyspan_pda_init);
module_exit(keyspan_pda_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 79787eda952..b84dddc7112 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -15,12 +15,12 @@
* Neither Palm, nor their contractor (MCCI) or their supplier (KLSI) provided
* information that was not already available.
*
- * It seems that KLSI bought some silicon-design information from ScanLogic,
+ * It seems that KLSI bought some silicon-design information from ScanLogic,
* whose SL11R processor is at the core of the KL5KUSB chipset from KLSI.
* KLSI has firmware available for their devices; it is probable that the
* firmware differs from that used by KLSI in their products. If you have an
- * original KLSI device and can provide some information on it, I would be
- * most interested in adding support for it here. If you have any information
+ * original KLSI device and can provide some information on it, I would be
+ * most interested in adding support for it here. If you have any information
* on the protocol used (or find errors in my reverse-engineered stuff), please
* let me know.
*
@@ -40,7 +40,7 @@
* 0.2 - TIOCMGET works, so autopilot(1) can be used!
* 0.1 - can be used to to pilot-xfer -p /dev/ttyUSB0 -l
*
- * The driver skeleton is mainly based on mct_u232.c and various other
+ * The driver skeleton is mainly based on mct_u232.c and various other
* pieces of code shamelessly copied from the drivers/usb/serial/ directory.
*/
@@ -53,7 +53,7 @@
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/unaligned.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -72,33 +72,25 @@ static int debug;
/*
* Function prototypes
*/
-static int klsi_105_startup (struct usb_serial *serial);
-static void klsi_105_shutdown (struct usb_serial *serial);
-static int klsi_105_open (struct usb_serial_port *port,
- struct file *filp);
-static void klsi_105_close (struct usb_serial_port *port,
- struct file *filp);
-static int klsi_105_write (struct usb_serial_port *port,
- const unsigned char *buf,
- int count);
-static void klsi_105_write_bulk_callback (struct urb *urb);
-static int klsi_105_chars_in_buffer (struct usb_serial_port *port);
-static int klsi_105_write_room (struct usb_serial_port *port);
-
-static void klsi_105_read_bulk_callback (struct urb *urb);
-static void klsi_105_set_termios (struct usb_serial_port *port,
- struct ktermios *old);
-static void klsi_105_throttle (struct usb_serial_port *port);
-static void klsi_105_unthrottle (struct usb_serial_port *port);
-/*
-static void klsi_105_break_ctl (struct usb_serial_port *port,
- int break_state );
- */
-static int klsi_105_tiocmget (struct usb_serial_port *port,
- struct file *file);
-static int klsi_105_tiocmset (struct usb_serial_port *port,
- struct file *file, unsigned int set,
- unsigned int clear);
+static int klsi_105_startup(struct usb_serial *serial);
+static void klsi_105_shutdown(struct usb_serial *serial);
+static int klsi_105_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void klsi_105_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static int klsi_105_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count);
+static void klsi_105_write_bulk_callback(struct urb *urb);
+static int klsi_105_chars_in_buffer(struct tty_struct *tty);
+static int klsi_105_write_room(struct tty_struct *tty);
+static void klsi_105_read_bulk_callback(struct urb *urb);
+static void klsi_105_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
+static void klsi_105_throttle(struct tty_struct *tty);
+static void klsi_105_unthrottle(struct tty_struct *tty);
+static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file);
+static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
/*
* All of the device info needed for the KLSI converters.
@@ -109,7 +101,7 @@ static struct usb_device_id id_table [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver kl5kusb105d_driver = {
.name = "kl5kusb105d",
@@ -134,7 +126,7 @@ static struct usb_serial_driver kl5kusb105d_device = {
.write_bulk_callback = klsi_105_write_bulk_callback,
.chars_in_buffer = klsi_105_chars_in_buffer,
.write_room = klsi_105_write_room,
- .read_bulk_callback =klsi_105_read_bulk_callback,
+ .read_bulk_callback = klsi_105_read_bulk_callback,
.set_termios = klsi_105_set_termios,
/*.break_ctl = klsi_105_break_ctl,*/
.tiocmget = klsi_105_tiocmget,
@@ -161,7 +153,7 @@ struct klsi_105_private {
struct ktermios termios;
unsigned long line_state; /* modem line settings */
/* write pool */
- struct urb * write_urb_pool[NUM_URBS];
+ struct urb *write_urb_pool[NUM_URBS];
spinlock_t lock;
unsigned long bytes_in;
unsigned long bytes_out;
@@ -180,15 +172,15 @@ static int klsi_105_chg_port_settings(struct usb_serial_port *port,
{
int rc;
- rc = usb_control_msg(port->serial->dev,
- usb_sndctrlpipe(port->serial->dev, 0),
- KL5KUSB105A_SIO_SET_DATA,
- USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_INTERFACE,
- 0, /* value */
- 0, /* index */
- settings,
- sizeof(struct klsi_105_port_settings),
- KLSI_TIMEOUT);
+ rc = usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
+ KL5KUSB105A_SIO_SET_DATA,
+ USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_INTERFACE,
+ 0, /* value */
+ 0, /* index */
+ settings,
+ sizeof(struct klsi_105_port_settings),
+ KLSI_TIMEOUT);
if (rc < 0)
err("Change port settings failed (error = %d)", rc);
info("%s - %d byte block, baudrate %x, databits %d, u1 %d, u2 %d",
@@ -196,7 +188,7 @@ static int klsi_105_chg_port_settings(struct usb_serial_port *port,
settings->pktlen,
settings->baudrate, settings->databits,
settings->unknown1, settings->unknown2);
- return rc;
+ return rc;
} /* klsi_105_chg_port_settings */
/* translate a 16-bit status value from the device to linux's TIO bits */
@@ -210,9 +202,9 @@ static unsigned long klsi_105_status2linestate(const __u16 status)
return res;
}
-/*
+/*
* Read line control via vendor command and return result through
- * *line_state_p
+ * *line_state_p
*/
/* It seems that the status buffer has always only 2 bytes length */
#define KLSI_STATUSBUF_LEN 2
@@ -220,14 +212,14 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
unsigned long *line_state_p)
{
int rc;
- __u8 status_buf[KLSI_STATUSBUF_LEN] = { -1,-1};
+ __u8 status_buf[KLSI_STATUSBUF_LEN] = { -1, -1};
__u16 status;
info("%s - sending SIO Poll request", __func__);
- rc = usb_control_msg(port->serial->dev,
+ rc = usb_control_msg(port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0),
KL5KUSB105A_SIO_POLL,
- USB_TYPE_VENDOR | USB_DIR_IN,
+ USB_TYPE_VENDOR | USB_DIR_IN,
0, /* value */
0, /* index */
status_buf, KLSI_STATUSBUF_LEN,
@@ -243,8 +235,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
*line_state_p = klsi_105_status2linestate(status);
}
-
- return rc;
+ return rc;
}
@@ -252,7 +243,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
* Driver's tty interface functions
*/
-static int klsi_105_startup (struct usb_serial *serial)
+static int klsi_105_startup(struct usb_serial *serial)
{
struct klsi_105_private *priv;
int i, j;
@@ -262,7 +253,7 @@ static int klsi_105_startup (struct usb_serial *serial)
*/
/* allocate the private data structure */
- for (i=0; i<serial->num_ports; i++) {
+ for (i = 0; i < serial->num_ports; i++) {
priv = kmalloc(sizeof(struct klsi_105_private),
GFP_KERNEL);
if (!priv) {
@@ -283,9 +274,9 @@ static int klsi_105_startup (struct usb_serial *serial)
priv->bytes_out = 0;
usb_set_serial_port_data(serial->port[i], priv);
- spin_lock_init (&priv->lock);
- for (j=0; j<NUM_URBS; j++) {
- struct urb* urb = usb_alloc_urb(0, GFP_KERNEL);
+ spin_lock_init(&priv->lock);
+ for (j = 0; j < NUM_URBS; j++) {
+ struct urb *urb = usb_alloc_urb(0, GFP_KERNEL);
priv->write_urb_pool[j] = urb;
if (urb == NULL) {
@@ -293,10 +284,11 @@ static int klsi_105_startup (struct usb_serial *serial)
goto err_cleanup;
}
- urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE,
- GFP_KERNEL);
+ urb->transfer_buffer =
+ kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
if (!urb->transfer_buffer) {
- err("%s - out of memory for urb buffers.", __func__);
+ err("%s - out of memory for urb buffers.",
+ __func__);
goto err_cleanup;
}
}
@@ -304,13 +296,13 @@ static int klsi_105_startup (struct usb_serial *serial)
/* priv->termios is left uninitalized until port opening */
init_waitqueue_head(&serial->port[i]->write_wait);
}
-
+
return 0;
err_cleanup:
for (; i >= 0; i--) {
priv = usb_get_serial_port_data(serial->port[i]);
- for (j=0; j < NUM_URBS; j++) {
+ for (j = 0; j < NUM_URBS; j++) {
if (priv->write_urb_pool[j]) {
kfree(priv->write_urb_pool[j]->transfer_buffer);
usb_free_urb(priv->write_urb_pool[j]);
@@ -322,22 +314,23 @@ err_cleanup:
} /* klsi_105_startup */
-static void klsi_105_shutdown (struct usb_serial *serial)
+static void klsi_105_shutdown(struct usb_serial *serial)
{
int i;
-
+
dbg("%s", __func__);
/* stop reads and writes on all ports */
- for (i=0; i < serial->num_ports; ++i) {
- struct klsi_105_private *priv = usb_get_serial_port_data(serial->port[i]);
+ for (i = 0; i < serial->num_ports; ++i) {
+ struct klsi_105_private *priv =
+ usb_get_serial_port_data(serial->port[i]);
unsigned long flags;
if (priv) {
/* kill our write urb pool */
int j;
struct urb **write_urbs = priv->write_urb_pool;
- spin_lock_irqsave(&priv->lock,flags);
+ spin_lock_irqsave(&priv->lock, flags);
for (j = 0; j < NUM_URBS; j++) {
if (write_urbs[j]) {
@@ -349,19 +342,18 @@ static void klsi_105_shutdown (struct usb_serial *serial)
* oopses. */
/* usb_kill_urb(write_urbs[j]); */
kfree(write_urbs[j]->transfer_buffer);
- usb_free_urb (write_urbs[j]);
+ usb_free_urb(write_urbs[j]);
}
}
-
- spin_unlock_irqrestore (&priv->lock, flags);
-
+ spin_unlock_irqrestore(&priv->lock, flags);
kfree(priv);
usb_set_serial_port_data(serial->port[i], NULL);
}
}
} /* klsi_105_shutdown */
-static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
+static int klsi_105_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct klsi_105_private *priv = usb_get_serial_port_data(port);
int retval = 0;
@@ -375,11 +367,11 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
/* force low_latency on so that our tty_push actually forces
* the data through
- * port->tty->low_latency = 1; */
+ * tty->low_latency = 1; */
/* Do a defined restart:
* Set up sane default baud rate and send the 'READ_ON'
- * vendor command.
+ * vendor command.
* FIXME: set modem line control (how?)
* Then read the modem line control and store values in
* priv->line_state.
@@ -390,24 +382,24 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
cfg.unknown1 = 0;
cfg.unknown2 = 1;
klsi_105_chg_port_settings(port, &cfg);
-
+
/* set up termios structure */
- spin_lock_irqsave (&priv->lock, flags);
- priv->termios.c_iflag = port->tty->termios->c_iflag;
- priv->termios.c_oflag = port->tty->termios->c_oflag;
- priv->termios.c_cflag = port->tty->termios->c_cflag;
- priv->termios.c_lflag = port->tty->termios->c_lflag;
- for (i=0; i<NCCS; i++)
- priv->termios.c_cc[i] = port->tty->termios->c_cc[i];
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->termios.c_iflag = tty->termios->c_iflag;
+ priv->termios.c_oflag = tty->termios->c_oflag;
+ priv->termios.c_cflag = tty->termios->c_cflag;
+ priv->termios.c_lflag = tty->termios->c_lflag;
+ for (i = 0; i < NCCS; i++)
+ priv->termios.c_cc[i] = tty->termios->c_cc[i];
priv->cfg.pktlen = cfg.pktlen;
priv->cfg.baudrate = cfg.baudrate;
priv->cfg.databits = cfg.databits;
priv->cfg.unknown1 = cfg.unknown1;
priv->cfg.unknown2 = cfg.unknown2;
- spin_unlock_irqrestore (&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
/* READ_ON and urb submission */
- usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
@@ -423,7 +415,7 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
}
rc = usb_control_msg(port->serial->dev,
- usb_sndctrlpipe(port->serial->dev,0),
+ usb_sndctrlpipe(port->serial->dev, 0),
KL5KUSB105A_SIO_CONFIGURE,
USB_TYPE_VENDOR|USB_DIR_OUT|USB_RECIP_INTERFACE,
KL5KUSB105A_SIO_CONFIGURE_READ_ON,
@@ -434,14 +426,14 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
if (rc < 0) {
err("Enabling read failed (error = %d)", rc);
retval = rc;
- } else
+ } else
dbg("%s - enabled reading", __func__);
rc = klsi_105_get_line_state(port, &line_state);
if (rc >= 0) {
- spin_lock_irqsave (&priv->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
priv->line_state = line_state;
- spin_unlock_irqrestore (&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
dbg("%s - read line state 0x%lx", __func__, line_state);
retval = 0;
} else
@@ -452,7 +444,8 @@ exit:
} /* klsi_105_open */
-static void klsi_105_close (struct usb_serial_port *port, struct file *filp)
+static void klsi_105_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct klsi_105_private *priv = usb_get_serial_port_data(port);
int rc;
@@ -462,14 +455,14 @@ static void klsi_105_close (struct usb_serial_port *port, struct file *filp)
mutex_lock(&port->serial->disc_mutex);
if (!port->serial->disconnected) {
/* send READ_OFF */
- rc = usb_control_msg (port->serial->dev,
- usb_sndctrlpipe(port->serial->dev, 0),
- KL5KUSB105A_SIO_CONFIGURE,
- USB_TYPE_VENDOR | USB_DIR_OUT,
- KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
- 0, /* index */
- NULL, 0,
- KLSI_TIMEOUT);
+ rc = usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
+ KL5KUSB105A_SIO_CONFIGURE,
+ USB_TYPE_VENDOR | USB_DIR_OUT,
+ KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
+ 0, /* index */
+ NULL, 0,
+ KLSI_TIMEOUT);
if (rc < 0)
err("Disabling read failed (error = %d)", rc);
}
@@ -482,23 +475,24 @@ static void klsi_105_close (struct usb_serial_port *port, struct file *filp)
/* FIXME */
/* wgg - do I need this? I think so. */
usb_kill_urb(port->interrupt_in_urb);
- info("kl5kusb105 port stats: %ld bytes in, %ld bytes out", priv->bytes_in, priv->bytes_out);
+ info("kl5kusb105 port stats: %ld bytes in, %ld bytes out",
+ priv->bytes_in, priv->bytes_out);
} /* klsi_105_close */
/* We need to write a complete 64-byte data block and encode the
- * number actually sent in the first double-byte, LSB-order. That
+ * number actually sent in the first double-byte, LSB-order. That
* leaves at most 62 bytes of payload.
*/
#define KLSI_105_DATA_OFFSET 2 /* in the bulk urb data block */
-static int klsi_105_write (struct usb_serial_port *port,
- const unsigned char *buf, int count)
+static int klsi_105_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct klsi_105_private *priv = usb_get_serial_port_data(port);
int result, size;
- int bytes_sent=0;
+ int bytes_sent = 0;
dbg("%s - port %d", __func__, port->number);
@@ -507,34 +501,37 @@ static int klsi_105_write (struct usb_serial_port *port,
struct urb *urb = NULL;
unsigned long flags;
int i;
- /* since the pool is per-port we might not need the spin lock !? */
- spin_lock_irqsave (&priv->lock, flags);
- for (i=0; i<NUM_URBS; i++) {
+ /* since the pool is per-port we might not need
+ the spin lock !? */
+ spin_lock_irqsave(&priv->lock, flags);
+ for (i = 0; i < NUM_URBS; i++) {
if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
urb = priv->write_urb_pool[i];
dbg("%s - using pool URB %d", __func__, i);
break;
}
}
- spin_unlock_irqrestore (&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
- if (urb==NULL) {
+ if (urb == NULL) {
dbg("%s - no more free urbs", __func__);
goto exit;
}
if (urb->transfer_buffer == NULL) {
- urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
+ urb->transfer_buffer =
+ kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
if (urb->transfer_buffer == NULL) {
err("%s - no more kernel memory...", __func__);
goto exit;
}
}
- size = min (count, port->bulk_out_size - KLSI_105_DATA_OFFSET);
- size = min (size, URB_TRANSFER_BUFFER_SIZE - KLSI_105_DATA_OFFSET);
+ size = min(count, port->bulk_out_size - KLSI_105_DATA_OFFSET);
+ size = min(size, URB_TRANSFER_BUFFER_SIZE -
+ KLSI_105_DATA_OFFSET);
- memcpy (urb->transfer_buffer + KLSI_105_DATA_OFFSET, buf, size);
+ memcpy(urb->transfer_buffer + KLSI_105_DATA_OFFSET, buf, size);
/* write payload size into transfer buffer */
((__u8 *)urb->transfer_buffer)[0] = (__u8) (size & 0xFF);
@@ -552,7 +549,8 @@ static int klsi_105_write (struct usb_serial_port *port,
/* send the data out the bulk port */
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
- err("%s - failed submitting write urb, error %d", __func__, result);
+ err("%s - failed submitting write urb, error %d",
+ __func__, result);
goto exit;
}
buf += size;
@@ -561,12 +559,12 @@ static int klsi_105_write (struct usb_serial_port *port,
}
exit:
/* lockless, but it's for debug info only... */
- priv->bytes_out+=bytes_sent;
+ priv->bytes_out += bytes_sent;
return bytes_sent; /* that's how much we wrote */
} /* klsi_105_write */
-static void klsi_105_write_bulk_callback ( struct urb *urb)
+static void klsi_105_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
int status = urb->status;
@@ -584,50 +582,50 @@ static void klsi_105_write_bulk_callback ( struct urb *urb)
/* return number of characters currently in the writing process */
-static int klsi_105_chars_in_buffer (struct usb_serial_port *port)
+static int klsi_105_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int chars = 0;
int i;
unsigned long flags;
struct klsi_105_private *priv = usb_get_serial_port_data(port);
- spin_lock_irqsave (&priv->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
- if (priv->write_urb_pool[i]->status == -EINPROGRESS) {
+ if (priv->write_urb_pool[i]->status == -EINPROGRESS)
chars += URB_TRANSFER_BUFFER_SIZE;
- }
}
- spin_unlock_irqrestore (&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
dbg("%s - returns %d", __func__, chars);
- return (chars);
+ return chars;
}
-static int klsi_105_write_room (struct usb_serial_port *port)
+static int klsi_105_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned long flags;
int i;
int room = 0;
struct klsi_105_private *priv = usb_get_serial_port_data(port);
- spin_lock_irqsave (&priv->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
- if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
+ if (priv->write_urb_pool[i]->status != -EINPROGRESS)
room += URB_TRANSFER_BUFFER_SIZE;
- }
}
- spin_unlock_irqrestore (&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
dbg("%s - returns %d", __func__, room);
- return (room);
+ return room;
}
-static void klsi_105_read_bulk_callback (struct urb *urb)
+static void klsi_105_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct klsi_105_private *priv = usb_get_serial_port_data(port);
@@ -660,13 +658,13 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
} else {
int bytes_sent = ((__u8 *) data)[0] +
((unsigned int) ((__u8 *) data)[1] << 8);
- tty = port->tty;
+ tty = port->port.tty;
/* we should immediately resubmit the URB, before attempting
* to pass the data on to the tty layer. But that needs locking
* against re-entry an then mixed-up data because of
* intermixed tty_flip_buffer_push()s
* FIXME
- */
+ */
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, data);
@@ -686,7 +684,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
priv->bytes_in += bytes_sent;
}
/* Continue trying to always read */
- usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
@@ -695,15 +693,16 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
port);
rc = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (rc)
- err("%s - failed resubmitting read urb, error %d", __func__, rc);
+ err("%s - failed resubmitting read urb, error %d",
+ __func__, rc);
} /* klsi_105_read_bulk_callback */
-static void klsi_105_set_termios (struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void klsi_105_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port,
+ struct ktermios *old_termios)
{
struct klsi_105_private *priv = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
unsigned int iflag = tty->termios->c_iflag;
unsigned int old_iflag = old_termios->c_iflag;
unsigned int cflag = tty->termios->c_cflag;
@@ -711,65 +710,63 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
struct klsi_105_port_settings cfg;
unsigned long flags;
speed_t baud;
-
+
/* lock while we are modifying the settings */
- spin_lock_irqsave (&priv->lock, flags);
-
+ spin_lock_irqsave(&priv->lock, flags);
+
/*
* Update baud rate
*/
baud = tty_get_baud_rate(tty);
- if( (cflag & CBAUD) != (old_cflag & CBAUD) ) {
- /* reassert DTR and (maybe) RTS on transition from B0 */
- if( (old_cflag & CBAUD) == B0 ) {
+ if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
+ /* reassert DTR and (maybe) RTS on transition from B0 */
+ if ((old_cflag & CBAUD) == B0) {
dbg("%s: baud was B0", __func__);
#if 0
priv->control_state |= TIOCM_DTR;
/* don't set RTS if using hardware flow control */
- if (!(old_cflag & CRTSCTS)) {
+ if (!(old_cflag & CRTSCTS))
priv->control_state |= TIOCM_RTS;
- }
mct_u232_set_modem_ctrl(serial, priv->control_state);
#endif
}
}
- switch(baud) {
- case 0: /* handled below */
- break;
- case 1200:
- priv->cfg.baudrate = kl5kusb105a_sio_b1200;
- break;
- case 2400:
- priv->cfg.baudrate = kl5kusb105a_sio_b2400;
- break;
- case 4800:
- priv->cfg.baudrate = kl5kusb105a_sio_b4800;
- break;
- case 9600:
- priv->cfg.baudrate = kl5kusb105a_sio_b9600;
- break;
- case 19200:
- priv->cfg.baudrate = kl5kusb105a_sio_b19200;
- break;
- case 38400:
- priv->cfg.baudrate = kl5kusb105a_sio_b38400;
- break;
- case 57600:
- priv->cfg.baudrate = kl5kusb105a_sio_b57600;
- break;
- case 115200:
- priv->cfg.baudrate = kl5kusb105a_sio_b115200;
- break;
- default:
- dbg("KLSI USB->Serial converter:"
- " unsupported baudrate request, using default"
- " of 9600");
+ switch (baud) {
+ case 0: /* handled below */
+ break;
+ case 1200:
+ priv->cfg.baudrate = kl5kusb105a_sio_b1200;
+ break;
+ case 2400:
+ priv->cfg.baudrate = kl5kusb105a_sio_b2400;
+ break;
+ case 4800:
+ priv->cfg.baudrate = kl5kusb105a_sio_b4800;
+ break;
+ case 9600:
+ priv->cfg.baudrate = kl5kusb105a_sio_b9600;
+ break;
+ case 19200:
+ priv->cfg.baudrate = kl5kusb105a_sio_b19200;
+ break;
+ case 38400:
+ priv->cfg.baudrate = kl5kusb105a_sio_b38400;
+ break;
+ case 57600:
+ priv->cfg.baudrate = kl5kusb105a_sio_b57600;
+ break;
+ case 115200:
+ priv->cfg.baudrate = kl5kusb105a_sio_b115200;
+ break;
+ default:
+ dbg("KLSI USB->Serial converter:"
+ " unsupported baudrate request, using default of 9600");
priv->cfg.baudrate = kl5kusb105a_sio_b9600;
- baud = 9600;
- break;
+ baud = 9600;
+ break;
}
- if ((cflag & CBAUD) == B0 ) {
+ if ((cflag & CBAUD) == B0) {
dbg("%s: baud is B0", __func__);
/* Drop RTS and DTR */
/* maybe this should be simulated by sending read
@@ -778,7 +775,7 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
;
#if 0
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
- mct_u232_set_modem_ctrl(serial, priv->control_state);
+ mct_u232_set_modem_ctrl(serial, priv->control_state);
#endif
}
tty_encode_baud_rate(tty, baud, baud);
@@ -788,11 +785,11 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
switch (cflag & CSIZE) {
case CS5:
dbg("%s - 5 bits/byte not supported", __func__);
- spin_unlock_irqrestore (&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
return ;
case CS6:
dbg("%s - 6 bits/byte not supported", __func__);
- spin_unlock_irqrestore (&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
return ;
case CS7:
priv->cfg.databits = kl5kusb105a_dtb_7;
@@ -811,8 +808,7 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
* Update line control register (LCR)
*/
if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
- || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
-
+ || (cflag & CSTOPB) != (old_cflag & CSTOPB)) {
/* Not currently supported */
tty->termios->c_cflag &= ~(PARENB|PARODD|CSTOPB);
#if 0
@@ -833,20 +829,18 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
#endif
;
}
-
/*
* Set flow control: well, I do not really now how to handle DTR/RTS.
* Just do what we have seen with SniffUSB on Win98.
*/
- if( (iflag & IXOFF) != (old_iflag & IXOFF)
+ if ((iflag & IXOFF) != (old_iflag & IXOFF)
|| (iflag & IXON) != (old_iflag & IXON)
- || (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) {
-
+ || (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
/* Not currently supported */
tty->termios->c_cflag &= ~CRTSCTS;
/* Drop DTR/RTS if no flow control otherwise assert */
#if 0
- if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )
+ if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
priv->control_state |= TIOCM_DTR | TIOCM_RTS;
else
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
@@ -854,19 +848,21 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
#endif
;
}
- memcpy (&cfg, &priv->cfg, sizeof(cfg));
- spin_unlock_irqrestore (&priv->lock, flags);
-
+ memcpy(&cfg, &priv->cfg, sizeof(cfg));
+ spin_unlock_irqrestore(&priv->lock, flags);
+
/* now commit changes to device */
klsi_105_chg_port_settings(port, &cfg);
} /* klsi_105_set_termios */
#if 0
-static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
+static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
- struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+ struct mct_u232_private *priv =
+ (struct mct_u232_private *)port->private;
unsigned char lcr = priv->last_lcr;
dbg("%sstate=%d", __func__, break_state);
@@ -878,8 +874,9 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
} /* mct_u232_break_ctl */
#endif
-static int klsi_105_tiocmget (struct usb_serial_port *port, struct file *file)
+static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct klsi_105_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int rc;
@@ -893,18 +890,18 @@ static int klsi_105_tiocmget (struct usb_serial_port *port, struct file *file)
return rc;
}
- spin_lock_irqsave (&priv->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
priv->line_state = line_state;
- spin_unlock_irqrestore (&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
dbg("%s - read line state 0x%lx", __func__, line_state);
return (int)line_state;
}
-static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
- unsigned int set, unsigned int clear)
+static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
int retval = -EINVAL;
-
+
dbg("%s", __func__);
/* if this ever gets implemented, it should be done something like this:
@@ -929,14 +926,16 @@ static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
return retval;
}
-static void klsi_105_throttle (struct usb_serial_port *port)
+static void klsi_105_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
usb_kill_urb(port->read_urb);
}
-static void klsi_105_unthrottle (struct usb_serial_port *port)
+static void klsi_105_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int result;
dbg("%s - port %d", __func__, port->number);
@@ -950,7 +949,7 @@ static void klsi_105_unthrottle (struct usb_serial_port *port)
-static int __init klsi_105_init (void)
+static int __init klsi_105_init(void)
{
int retval;
retval = usb_serial_register(&kl5kusb105d_device);
@@ -969,19 +968,19 @@ failed_usb_serial_register:
}
-static void __exit klsi_105_exit (void)
+static void __exit klsi_105_exit(void)
{
- usb_deregister (&kl5kusb105d_driver);
- usb_serial_deregister (&kl5kusb105d_device);
+ usb_deregister(&kl5kusb105d_driver);
+ usb_serial_deregister(&kl5kusb105d_device);
}
-module_init (klsi_105_init);
-module_exit (klsi_105_exit);
+module_init(klsi_105_init);
+module_exit(klsi_105_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 693f00da7c0..deba28ec77e 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -1,7 +1,7 @@
/*
* KOBIL USB Smart Card Terminal Driver
*
- * Copyright (C) 2002 KOBIL Systems GmbH
+ * Copyright (C) 2002 KOBIL Systems GmbH
* Author: Thomas Wahrenbruch
*
* Contact: linuxusb@kobil.de
@@ -20,7 +20,7 @@
*
* Supported readers: USB TWIN, KAAN Standard Plus and SecOVID Reader Plus
* (Adapter K), B1 Professional and KAAN Professional (Adapter B)
- *
+ *
* (21/05/2004) tw
* Fix bug with P'n'P readers
*
@@ -44,7 +44,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include <linux/ioctl.h>
@@ -68,21 +68,24 @@ static int debug;
/* Function prototypes */
-static int kobil_startup (struct usb_serial *serial);
-static void kobil_shutdown (struct usb_serial *serial);
-static int kobil_open (struct usb_serial_port *port, struct file *filp);
-static void kobil_close (struct usb_serial_port *port, struct file *filp);
-static int kobil_write (struct usb_serial_port *port,
+static int kobil_startup(struct usb_serial *serial);
+static void kobil_shutdown(struct usb_serial *serial);
+static int kobil_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void kobil_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
-static int kobil_write_room(struct usb_serial_port *port);
-static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
+static int kobil_write_room(struct tty_struct *tty);
+static int kobil_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
-static int kobil_tiocmget(struct usb_serial_port *port, struct file *file);
-static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
+static int kobil_tiocmget(struct tty_struct *tty, struct file *file);
+static int kobil_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
-static void kobil_read_int_callback( struct urb *urb );
-static void kobil_write_callback( struct urb *purb );
-static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old);
+static void kobil_read_int_callback(struct urb *urb);
+static void kobil_write_callback(struct urb *purb);
+static void kobil_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
static struct usb_device_id id_table [] = {
@@ -94,7 +97,7 @@ static struct usb_device_id id_table [] = {
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver kobil_driver = {
.name = "kobil",
@@ -131,14 +134,14 @@ static struct usb_serial_driver kobil_device = {
struct kobil_private {
int write_int_endpoint_address;
int read_int_endpoint_address;
- unsigned char buf[KOBIL_BUF_LENGTH]; // buffer for the APDU to send
- int filled; // index of the last char in buf
- int cur_pos; // index of the next char to send in buf
+ unsigned char buf[KOBIL_BUF_LENGTH]; /* buffer for the APDU to send */
+ int filled; /* index of the last char in buf */
+ int cur_pos; /* index of the next char to send in buf */
__u16 device_type;
};
-static int kobil_startup (struct usb_serial *serial)
+static int kobil_startup(struct usb_serial *serial)
{
int i;
struct kobil_private *priv;
@@ -149,20 +152,20 @@ static int kobil_startup (struct usb_serial *serial)
struct usb_host_endpoint *endpoint;
priv = kmalloc(sizeof(struct kobil_private), GFP_KERNEL);
- if (!priv){
+ if (!priv)
return -ENOMEM;
- }
priv->filled = 0;
priv->cur_pos = 0;
priv->device_type = le16_to_cpu(serial->dev->descriptor.idProduct);
- switch (priv->device_type){
+ switch (priv->device_type) {
case KOBIL_ADAPTER_B_PRODUCT_ID:
printk(KERN_DEBUG "KOBIL B1 PRO / KAAN PRO detected\n");
break;
case KOBIL_ADAPTER_K_PRODUCT_ID:
- printk(KERN_DEBUG "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n");
+ printk(KERN_DEBUG
+ "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n");
break;
case KOBIL_USBTWIN_PRODUCT_ID:
printk(KERN_DEBUG "KOBIL USBTWIN detected\n");
@@ -173,44 +176,48 @@ static int kobil_startup (struct usb_serial *serial)
}
usb_set_serial_port_data(serial->port[0], priv);
- // search for the necessary endpoints
+ /* search for the necessary endpoints */
pdev = serial->dev;
- actconfig = pdev->actconfig;
- interface = actconfig->interface[0];
+ actconfig = pdev->actconfig;
+ interface = actconfig->interface[0];
altsetting = interface->cur_altsetting;
- endpoint = altsetting->endpoint;
-
- for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
+ endpoint = altsetting->endpoint;
+
+ for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
endpoint = &altsetting->endpoint[i];
if (usb_endpoint_is_int_out(&endpoint->desc)) {
- dbg("%s Found interrupt out endpoint. Address: %d", __func__, endpoint->desc.bEndpointAddress);
- priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress;
- }
+ dbg("%s Found interrupt out endpoint. Address: %d",
+ __func__, endpoint->desc.bEndpointAddress);
+ priv->write_int_endpoint_address =
+ endpoint->desc.bEndpointAddress;
+ }
if (usb_endpoint_is_int_in(&endpoint->desc)) {
- dbg("%s Found interrupt in endpoint. Address: %d", __func__, endpoint->desc.bEndpointAddress);
- priv->read_int_endpoint_address = endpoint->desc.bEndpointAddress;
- }
+ dbg("%s Found interrupt in endpoint. Address: %d",
+ __func__, endpoint->desc.bEndpointAddress);
+ priv->read_int_endpoint_address =
+ endpoint->desc.bEndpointAddress;
+ }
}
return 0;
}
-static void kobil_shutdown (struct usb_serial *serial)
+static void kobil_shutdown(struct usb_serial *serial)
{
int i;
dbg("%s - port %d", __func__, serial->port[0]->number);
- for (i=0; i < serial->num_ports; ++i) {
- while (serial->port[i]->open_count > 0) {
- kobil_close (serial->port[i], NULL);
- }
+ for (i = 0; i < serial->num_ports; ++i) {
+ while (serial->port[i]->port.count > 0)
+ kobil_close(NULL, serial->port[i], NULL);
kfree(usb_get_serial_port_data(serial->port[i]));
usb_set_serial_port_data(serial->port[i], NULL);
}
}
-static int kobil_open (struct usb_serial_port *port, struct file *filp)
+static int kobil_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
int result = 0;
struct kobil_private *priv;
@@ -221,7 +228,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __func__, port->number);
priv = usb_get_serial_port_data(port);
- // someone sets the dev to 0 if the close method has been called
+ /* someone sets the dev to 0 if the close method has been called */
port->interrupt_in_urb->dev = port->serial->dev;
@@ -229,100 +236,115 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
* the data through, otherwise it is scheduled, and with high
* data rates (like with OHCI) data can get lost.
*/
- port->tty->low_latency = 1;
-
- // without this, every push_tty_char is echoed :-(
- port->tty->termios->c_lflag = 0;
- port->tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE);
- port->tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
- port->tty->termios->c_oflag &= ~ONLCR; // do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D)
-
- // allocate memory for transfer buffer
+ if (tty) {
+ tty->low_latency = 1;
+
+ /* Default to echo off and other sane device settings */
+ tty->termios->c_lflag = 0;
+ tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN |
+ XCASE);
+ tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
+ /* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */
+ tty->termios->c_oflag &= ~ONLCR;
+ }
+ /* allocate memory for transfer buffer */
transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
- if (! transfer_buffer) {
+ if (!transfer_buffer)
return -ENOMEM;
- }
-
- // allocate write_urb
- if (!port->write_urb) {
- dbg("%s - port %d Allocating port->write_urb", __func__, port->number);
- port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
+
+ /* allocate write_urb */
+ if (!port->write_urb) {
+ dbg("%s - port %d Allocating port->write_urb",
+ __func__, port->number);
+ port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port->write_urb) {
- dbg("%s - port %d usb_alloc_urb failed", __func__, port->number);
+ dbg("%s - port %d usb_alloc_urb failed",
+ __func__, port->number);
kfree(transfer_buffer);
return -ENOMEM;
}
}
- // allocate memory for write_urb transfer buffer
- port->write_urb->transfer_buffer = kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
- if (! port->write_urb->transfer_buffer) {
+ /* allocate memory for write_urb transfer buffer */
+ port->write_urb->transfer_buffer =
+ kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
+ if (!port->write_urb->transfer_buffer) {
kfree(transfer_buffer);
usb_free_urb(port->write_urb);
port->write_urb = NULL;
return -ENOMEM;
- }
-
- // get hardware version
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_GetMisc,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
- SUSBCR_MSC_GetHWVersion,
- 0,
- transfer_buffer,
- transfer_buffer_length,
- KOBIL_TIMEOUT
+ }
+
+ /* get hardware version */
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_GetMisc,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
+ SUSBCR_MSC_GetHWVersion,
+ 0,
+ transfer_buffer,
+ transfer_buffer_length,
+ KOBIL_TIMEOUT
+ );
+ dbg("%s - port %d Send get_HW_version URB returns: %i",
+ __func__, port->number, result);
+ dbg("Harware version: %i.%i.%i",
+ transfer_buffer[0], transfer_buffer[1], transfer_buffer[2]);
+
+ /* get firmware version */
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_GetMisc,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
+ SUSBCR_MSC_GetFWVersion,
+ 0,
+ transfer_buffer,
+ transfer_buffer_length,
+ KOBIL_TIMEOUT
+ );
+ dbg("%s - port %d Send get_FW_version URB returns: %i",
+ __func__, port->number, result);
+ dbg("Firmware version: %i.%i.%i",
+ transfer_buffer[0], transfer_buffer[1], transfer_buffer[2]);
+
+ if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
+ priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
+ /* Setting Baudrate, Parity and Stopbits */
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_SetBaudRateParityAndStopBits,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+ SUSBCR_SBR_9600 | SUSBCR_SPASB_EvenParity |
+ SUSBCR_SPASB_1StopBit,
+ 0,
+ transfer_buffer,
+ 0,
+ KOBIL_TIMEOUT
);
- dbg("%s - port %d Send get_HW_version URB returns: %i", __func__, port->number, result);
- dbg("Harware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] );
-
- // get firmware version
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_GetMisc,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
- SUSBCR_MSC_GetFWVersion,
- 0,
- transfer_buffer,
- transfer_buffer_length,
- KOBIL_TIMEOUT
+ dbg("%s - port %d Send set_baudrate URB returns: %i",
+ __func__, port->number, result);
+
+ /* reset all queues */
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_Misc,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+ SUSBCR_MSC_ResetAllQueues,
+ 0,
+ transfer_buffer,
+ 0,
+ KOBIL_TIMEOUT
);
- dbg("%s - port %d Send get_FW_version URB returns: %i", __func__, port->number, result);
- dbg("Firmware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] );
-
- if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
- // Setting Baudrate, Parity and Stopbits
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_SetBaudRateParityAndStopBits,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
- SUSBCR_SBR_9600 | SUSBCR_SPASB_EvenParity | SUSBCR_SPASB_1StopBit,
- 0,
- transfer_buffer,
- 0,
- KOBIL_TIMEOUT
- );
- dbg("%s - port %d Send set_baudrate URB returns: %i", __func__, port->number, result);
-
- // reset all queues
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_Misc,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
- SUSBCR_MSC_ResetAllQueues,
- 0,
- transfer_buffer,
- 0,
- KOBIL_TIMEOUT
- );
- dbg("%s - port %d Send reset_all_queues URB returns: %i", __func__, port->number, result);
+ dbg("%s - port %d Send reset_all_queues URB returns: %i",
+ __func__, port->number, result);
}
- if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
+ if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
+ priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
- // start reading (Adapter B 'cause PNP string)
- result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC );
- dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
+ /* start reading (Adapter B 'cause PNP string) */
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ dbg("%s - port %d Send read URB returns: %i",
+ __func__, port->number, result);
}
kfree(transfer_buffer);
@@ -330,13 +352,14 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
}
-static void kobil_close (struct usb_serial_port *port, struct file *filp)
+static void kobil_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
dbg("%s - port %d", __func__, port->number);
if (port->write_urb) {
usb_kill_urb(port->write_urb);
- usb_free_urb( port->write_urb );
+ usb_free_urb(port->write_urb);
port->write_urb = NULL;
}
usb_kill_urb(port->interrupt_in_urb);
@@ -350,7 +373,7 @@ static void kobil_read_int_callback(struct urb *urb)
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
-// char *dbg_data;
+/* char *dbg_data; */
dbg("%s - port %d", __func__, port->number);
@@ -360,51 +383,53 @@ static void kobil_read_int_callback(struct urb *urb)
return;
}
- tty = port->tty;
+ tty = port->port.tty;
if (urb->actual_length) {
- // BEGIN DEBUG
+ /* BEGIN DEBUG */
/*
- dbg_data = kzalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL);
+ dbg_data = kzalloc((3 * purb->actual_length + 10)
+ * sizeof(char), GFP_KERNEL);
if (! dbg_data) {
- return;
+ return;
}
- for (i = 0; i < purb->actual_length; i++) {
- sprintf(dbg_data +3*i, "%02X ", data[i]);
+ for (i = 0; i < purb->actual_length; i++) {
+ sprintf(dbg_data +3*i, "%02X ", data[i]);
}
- dbg(" <-- %s", dbg_data );
+ dbg(" <-- %s", dbg_data);
kfree(dbg_data);
*/
- // END DEBUG
+ /* END DEBUG */
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
-
- // someone sets the dev to 0 if the close method has been called
+ /* someone sets the dev to 0 if the close method has been called */
port->interrupt_in_urb->dev = port->serial->dev;
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
- dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
+ dbg("%s - port %d Send read URB returns: %i",
+ __func__, port->number, result);
}
-static void kobil_write_callback( struct urb *purb )
+static void kobil_write_callback(struct urb *purb)
{
}
-static int kobil_write (struct usb_serial_port *port,
+static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
int length = 0;
int result = 0;
int todo = 0;
- struct kobil_private * priv;
+ struct kobil_private *priv;
if (count == 0) {
- dbg("%s - port %d write request of 0 bytes", __func__, port->number);
+ dbg("%s - port %d write request of 0 bytes",
+ __func__, port->number);
return 0;
}
@@ -415,106 +440,113 @@ static int kobil_write (struct usb_serial_port *port,
return -ENOMEM;
}
- // Copy data to buffer
- memcpy (priv->buf + priv->filled, buf, count);
-
- usb_serial_debug_data(debug, &port->dev, __func__, count, priv->buf + priv->filled);
-
+ /* Copy data to buffer */
+ memcpy(priv->buf + priv->filled, buf, count);
+ usb_serial_debug_data(debug, &port->dev, __func__, count,
+ priv->buf + priv->filled);
priv->filled = priv->filled + count;
-
- // only send complete block. TWIN, KAAN SIM and adapter K use the same protocol.
- if ( ((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) ||
- ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4))) ) {
-
- // stop reading (except TWIN and KAAN SIM)
- if ( (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) )
+ /* only send complete block. TWIN, KAAN SIM and adapter K
+ use the same protocol. */
+ if (((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) ||
+ ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4)))) {
+ /* stop reading (except TWIN and KAAN SIM) */
+ if ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID)
+ || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID))
usb_kill_urb(port->interrupt_in_urb);
todo = priv->filled - priv->cur_pos;
- while(todo > 0) {
- // max 8 byte in one urb (endpoint size)
+ while (todo > 0) {
+ /* max 8 byte in one urb (endpoint size) */
length = (todo < 8) ? todo : 8;
- // copy data to transfer buffer
- memcpy(port->write_urb->transfer_buffer, priv->buf + priv->cur_pos, length );
- usb_fill_int_urb( port->write_urb,
- port->serial->dev,
- usb_sndintpipe(port->serial->dev, priv->write_int_endpoint_address),
- port->write_urb->transfer_buffer,
- length,
- kobil_write_callback,
- port,
- 8
- );
+ /* copy data to transfer buffer */
+ memcpy(port->write_urb->transfer_buffer,
+ priv->buf + priv->cur_pos, length);
+ usb_fill_int_urb(port->write_urb,
+ port->serial->dev,
+ usb_sndintpipe(port->serial->dev,
+ priv->write_int_endpoint_address),
+ port->write_urb->transfer_buffer,
+ length,
+ kobil_write_callback,
+ port,
+ 8
+ );
priv->cur_pos = priv->cur_pos + length;
- result = usb_submit_urb( port->write_urb, GFP_NOIO );
- dbg("%s - port %d Send write URB returns: %i", __func__, port->number, result);
+ result = usb_submit_urb(port->write_urb, GFP_NOIO);
+ dbg("%s - port %d Send write URB returns: %i",
+ __func__, port->number, result);
todo = priv->filled - priv->cur_pos;
- if (todo > 0) {
+ if (todo > 0)
msleep(24);
- }
+ }
- } // end while
-
priv->filled = 0;
priv->cur_pos = 0;
- // someone sets the dev to 0 if the close method has been called
+ /* someone sets the dev to 0 if the close method
+ has been called */
port->interrupt_in_urb->dev = port->serial->dev;
-
- // start reading (except TWIN and KAAN SIM)
- if ( (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) ) {
- // someone sets the dev to 0 if the close method has been called
+
+ /* start reading (except TWIN and KAAN SIM) */
+ if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
+ priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
+ /* someone sets the dev to 0 if the close method has
+ been called */
port->interrupt_in_urb->dev = port->serial->dev;
-
- result = usb_submit_urb( port->interrupt_in_urb, GFP_NOIO );
- dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
+
+ result = usb_submit_urb(port->interrupt_in_urb,
+ GFP_NOIO);
+ dbg("%s - port %d Send read URB returns: %i",
+ __func__, port->number, result);
}
}
return count;
}
-static int kobil_write_room (struct usb_serial_port *port)
+static int kobil_write_room(struct tty_struct *tty)
{
- //dbg("%s - port %d", __func__, port->number);
+ /* dbg("%s - port %d", __func__, port->number); */
+ /* FIXME */
return 8;
}
-static int kobil_tiocmget(struct usb_serial_port *port, struct file *file)
+static int kobil_tiocmget(struct tty_struct *tty, struct file *file)
{
- struct kobil_private * priv;
+ struct usb_serial_port *port = tty->driver_data;
+ struct kobil_private *priv;
int result;
unsigned char *transfer_buffer;
int transfer_buffer_length = 8;
priv = usb_get_serial_port_data(port);
- if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) {
- // This device doesn't support ioctl calls
+ if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID
+ || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
+ /* This device doesn't support ioctl calls */
return -EINVAL;
}
- // allocate memory for transfer buffer
+ /* allocate memory for transfer buffer */
transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
- if (!transfer_buffer) {
+ if (!transfer_buffer)
return -ENOMEM;
- }
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_GetStatusLineState,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
- 0,
- 0,
- transfer_buffer,
- transfer_buffer_length,
- KOBIL_TIMEOUT);
-
- dbg("%s - port %d Send get_status_line_state URB returns: %i. Statusline: %02x",
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_GetStatusLineState,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
+ 0,
+ 0,
+ transfer_buffer,
+ transfer_buffer_length,
+ KOBIL_TIMEOUT);
+
+ dbg("%s - port %d Send get_status_line_state URB returns: %i. Statusline: %02x",
__func__, port->number, result, transfer_buffer[0]);
result = 0;
@@ -524,10 +556,11 @@ static int kobil_tiocmget(struct usb_serial_port *port, struct file *file)
return result;
}
-static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
+static int kobil_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- struct kobil_private * priv;
+ struct usb_serial_port *port = tty->driver_data;
+ struct kobil_private *priv;
int result;
int dtr = 0;
int rts = 0;
@@ -536,16 +569,16 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
/* FIXME: locking ? */
priv = usb_get_serial_port_data(port);
- if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) {
- // This device doesn't support ioctl calls
+ if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID
+ || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
+ /* This device doesn't support ioctl calls */
return -EINVAL;
}
- // allocate memory for transfer buffer
+ /* allocate memory for transfer buffer */
transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
- if (! transfer_buffer) {
+ if (!transfer_buffer)
return -ENOMEM;
- }
if (set & TIOCM_RTS)
rts = 1;
@@ -558,66 +591,77 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) {
if (dtr != 0)
- dbg("%s - port %d Setting DTR", __func__, port->number);
+ dbg("%s - port %d Setting DTR",
+ __func__, port->number);
else
- dbg("%s - port %d Clearing DTR", __func__, port->number);
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_SetStatusLinesOrQueues,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
- ((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR),
- 0,
- transfer_buffer,
- 0,
- KOBIL_TIMEOUT);
+ dbg("%s - port %d Clearing DTR",
+ __func__, port->number);
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_SetStatusLinesOrQueues,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+ ((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR),
+ 0,
+ transfer_buffer,
+ 0,
+ KOBIL_TIMEOUT);
} else {
if (rts != 0)
- dbg("%s - port %d Setting RTS", __func__, port->number);
+ dbg("%s - port %d Setting RTS",
+ __func__, port->number);
else
- dbg("%s - port %d Clearing RTS", __func__, port->number);
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_SetStatusLinesOrQueues,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
- ((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS),
- 0,
- transfer_buffer,
- 0,
- KOBIL_TIMEOUT);
+ dbg("%s - port %d Clearing RTS",
+ __func__, port->number);
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_SetStatusLinesOrQueues,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+ ((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS),
+ 0,
+ transfer_buffer,
+ 0,
+ KOBIL_TIMEOUT);
}
- dbg("%s - port %d Send set_status_line URB returns: %i", __func__, port->number, result);
+ dbg("%s - port %d Send set_status_line URB returns: %i",
+ __func__, port->number, result);
kfree(transfer_buffer);
return (result < 0) ? result : 0;
}
-static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old)
+static void kobil_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old)
{
- struct kobil_private * priv;
+ struct kobil_private *priv;
int result;
unsigned short urb_val = 0;
- int c_cflag = port->tty->termios->c_cflag;
+ int c_cflag = tty->termios->c_cflag;
speed_t speed;
- void * settings;
+ void *settings;
priv = usb_get_serial_port_data(port);
- if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)
- // This device doesn't support ioctl calls
+ if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
+ priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
+ /* This device doesn't support ioctl calls */
+ *tty->termios = *old;
return;
+ }
- switch (speed = tty_get_baud_rate(port->tty)) {
- case 1200:
- urb_val = SUSBCR_SBR_1200;
- break;
- default:
- speed = 9600;
- case 9600:
- urb_val = SUSBCR_SBR_9600;
- break;
+ speed = tty_get_baud_rate(tty);
+ switch (speed) {
+ case 1200:
+ urb_val = SUSBCR_SBR_1200;
+ break;
+ default:
+ speed = 9600;
+ case 9600:
+ urb_val = SUSBCR_SBR_9600;
+ break;
}
- urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : SUSBCR_SPASB_1StopBit;
+ urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits :
+ SUSBCR_SPASB_1StopBit;
settings = kzalloc(50, GFP_KERNEL);
- if (! settings)
+ if (!settings)
return;
sprintf(settings, "%d ", speed);
@@ -634,66 +678,69 @@ static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old
urb_val |= SUSBCR_SPASB_NoParity;
strcat(settings, "No Parity");
}
- port->tty->termios->c_cflag &= ~CMSPAR;
- tty_encode_baud_rate(port->tty, speed, speed);
-
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_SetBaudRateParityAndStopBits,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
- urb_val,
- 0,
- settings,
- 0,
- KOBIL_TIMEOUT
+ tty->termios->c_cflag &= ~CMSPAR;
+ tty_encode_baud_rate(tty, speed, speed);
+
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_SetBaudRateParityAndStopBits,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+ urb_val,
+ 0,
+ settings,
+ 0,
+ KOBIL_TIMEOUT
);
kfree(settings);
}
-static int kobil_ioctl(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+static int kobil_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
- struct kobil_private * priv = usb_get_serial_port_data(port);
+ struct usb_serial_port *port = tty->driver_data;
+ struct kobil_private *priv = usb_get_serial_port_data(port);
unsigned char *transfer_buffer;
int transfer_buffer_length = 8;
int result;
- if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)
- // This device doesn't support ioctl calls
- return 0;
+ if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
+ priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)
+ /* This device doesn't support ioctl calls */
+ return -ENOIOCTLCMD;
switch (cmd) {
- case TCFLSH: // 0x540B
+ case TCFLSH:
transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL);
- if (! transfer_buffer)
- return -ENOBUFS;
-
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_Misc,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
- SUSBCR_MSC_ResetAllQueues,
- 0,
- NULL,//transfer_buffer,
- 0,
- KOBIL_TIMEOUT
+ if (!transfer_buffer)
+ return -ENOBUFS;
+
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_Misc,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+ SUSBCR_MSC_ResetAllQueues,
+ 0,
+ NULL, /* transfer_buffer, */
+ 0,
+ KOBIL_TIMEOUT
);
-
+
dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __func__, port->number, result);
kfree(transfer_buffer);
- return (result < 0) ? -EFAULT : 0;
+ return (result < 0) ? -EIO: 0;
default:
return -ENOIOCTLCMD;
}
}
-static int __init kobil_init (void)
+static int __init kobil_init(void)
{
int retval;
retval = usb_serial_register(&kobil_device);
if (retval)
goto failed_usb_serial_register;
retval = usb_register(&kobil_driver);
- if (retval)
+ if (retval)
goto failed_usb_register;
info(DRIVER_VERSION " " DRIVER_AUTHOR);
@@ -707,18 +754,18 @@ failed_usb_serial_register:
}
-static void __exit kobil_exit (void)
+static void __exit kobil_exit(void)
{
- usb_deregister (&kobil_driver);
- usb_serial_deregister (&kobil_device);
+ usb_deregister(&kobil_driver);
+ usb_serial_deregister(&kobil_device);
}
module_init(kobil_init);
module_exit(kobil_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE( "GPL" );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 5fc2cef30e3..0ded8bd6ec8 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -33,10 +33,11 @@
* - Fixed an endianess problem with the baudrate selection for PowerPC.
*
* 06-Dec-2001 Martin Hamilton <martinh@gnu.org>
- * Added support for the Belkin F5U109 DB9 adaptor
+ * - Added support for the Belkin F5U109 DB9 adaptor
*
* 30-May-2001 Greg Kroah-Hartman
- * switched from using spinlock to a semaphore, which fixes lots of problems.
+ * - switched from using spinlock to a semaphore, which fixes lots of
+ * problems.
*
* 04-May-2001 Stelian Pop
* - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes
@@ -49,7 +50,7 @@
* 08-Apr-2001 gb
* - Identify version on module load.
*
- * 06-Jan-2001 Cornel Ciocirlan
+ * 06-Jan-2001 Cornel Ciocirlan
* - Added support for Sitecom U232-P25 model (Product Id 0x0230)
* - Added support for D-Link DU-H3SP USB BAY (Product Id 0x0200)
*
@@ -59,8 +60,8 @@
* (lots of things will change if/when the usb-serial core changes to
* handle these issues.
*
- * 27-Nov-2000 Wolfgang Grandegger
- * A version for kernel 2.4.0-test10 released to the Linux community
+ * 27-Nov-2000 Wolfgang Grandegge
+ * A version for kernel 2.4.0-test10 released to the Linux community
* (via linux-usb-devel).
*/
@@ -73,7 +74,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include "mct_u232.h"
@@ -90,28 +91,21 @@ static int debug;
/*
* Function prototypes
*/
-static int mct_u232_startup (struct usb_serial *serial);
-static void mct_u232_shutdown (struct usb_serial *serial);
-static int mct_u232_open (struct usb_serial_port *port,
- struct file *filp);
-static void mct_u232_close (struct usb_serial_port *port,
- struct file *filp);
-static void mct_u232_read_int_callback (struct urb *urb);
-static void mct_u232_set_termios (struct usb_serial_port *port,
- struct ktermios * old);
-static int mct_u232_ioctl (struct usb_serial_port *port,
- struct file * file,
- unsigned int cmd,
- unsigned long arg);
-static void mct_u232_break_ctl (struct usb_serial_port *port,
- int break_state );
-static int mct_u232_tiocmget (struct usb_serial_port *port,
- struct file *file);
-static int mct_u232_tiocmset (struct usb_serial_port *port,
- struct file *file, unsigned int set,
- unsigned int clear);
-static void mct_u232_throttle (struct usb_serial_port *port);
-static void mct_u232_unthrottle (struct usb_serial_port *port);
+static int mct_u232_startup(struct usb_serial *serial);
+static void mct_u232_shutdown(struct usb_serial *serial);
+static int mct_u232_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void mct_u232_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void mct_u232_read_int_callback(struct urb *urb);
+static void mct_u232_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
+static void mct_u232_break_ctl(struct tty_struct *tty, int break_state);
+static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file);
+static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
+static void mct_u232_throttle(struct tty_struct *tty);
+static void mct_u232_unthrottle(struct tty_struct *tty);
/*
@@ -125,7 +119,7 @@ static struct usb_device_id id_table_combined [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver mct_u232_driver = {
.name = "mct_u232",
@@ -149,7 +143,6 @@ static struct usb_serial_driver mct_u232_device = {
.throttle = mct_u232_throttle,
.unthrottle = mct_u232_unthrottle,
.read_int_callback = mct_u232_read_int_callback,
- .ioctl = mct_u232_ioctl,
.set_termios = mct_u232_set_termios,
.break_ctl = mct_u232_break_ctl,
.tiocmget = mct_u232_tiocmget,
@@ -180,23 +173,34 @@ struct mct_u232_private {
* Later day 2.6.0-test kernels have new baud rates like B230400 which
* we do not know how to support. We ignore them for the moment.
*/
-static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value, speed_t *result)
+static int mct_u232_calculate_baud_rate(struct usb_serial *serial,
+ speed_t value, speed_t *result)
{
*result = value;
if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID
- || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) {
+ || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) {
switch (value) {
- case 300: return 0x01;
- case 600: return 0x02; /* this one not tested */
- case 1200: return 0x03;
- case 2400: return 0x04;
- case 4800: return 0x06;
- case 9600: return 0x08;
- case 19200: return 0x09;
- case 38400: return 0x0a;
- case 57600: return 0x0b;
- case 115200: return 0x0c;
+ case 300:
+ return 0x01;
+ case 600:
+ return 0x02; /* this one not tested */
+ case 1200:
+ return 0x03;
+ case 2400:
+ return 0x04;
+ case 4800:
+ return 0x06;
+ case 9600:
+ return 0x08;
+ case 19200:
+ return 0x09;
+ case 38400:
+ return 0x0a;
+ case 57600:
+ return 0x0b;
+ case 115200:
+ return 0x0c;
default:
*result = 9600;
return 0x08;
@@ -224,26 +228,27 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value
}
}
-static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_port *port,
- speed_t value)
+static int mct_u232_set_baud_rate(struct tty_struct *tty,
+ struct usb_serial *serial, struct usb_serial_port *port, speed_t value)
{
__le32 divisor;
- int rc;
- unsigned char zero_byte = 0;
- unsigned char cts_enable_byte = 0;
- speed_t speed;
-
- divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value, &speed));
-
- rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- MCT_U232_SET_BAUD_RATE_REQUEST,
- MCT_U232_SET_REQUEST_TYPE,
- 0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
- WDR_TIMEOUT);
+ int rc;
+ unsigned char zero_byte = 0;
+ unsigned char cts_enable_byte = 0;
+ speed_t speed;
+
+ divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value,
+ &speed));
+
+ rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ MCT_U232_SET_BAUD_RATE_REQUEST,
+ MCT_U232_SET_REQUEST_TYPE,
+ 0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
+ WDR_TIMEOUT);
if (rc < 0) /*FIXME: What value speed results */
err("Set BAUD RATE %d failed (error = %d)", value, rc);
else
- tty_encode_baud_rate(port->tty, speed, speed);
+ tty_encode_baud_rate(tty, speed, speed);
dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor);
/* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
@@ -258,55 +263,55 @@ static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_p
whether data will be transmitted to a device which is not asserting
the 'CTS' signal. If the second message's data byte is zero, data
will be transmitted even if 'CTS' is not asserted (i.e. no hardware
- flow control). if the second message's data byte is nonzero (a value
- of 1 is used by this driver), data will not be transmitted to a device
- which is not asserting 'CTS'.
+ flow control). if the second message's data byte is nonzero (a
+ value of 1 is used by this driver), data will not be transmitted to
+ a device which is not asserting 'CTS'.
*/
rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- MCT_U232_SET_UNKNOWN1_REQUEST,
- MCT_U232_SET_REQUEST_TYPE,
- 0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE,
- WDR_TIMEOUT);
+ MCT_U232_SET_UNKNOWN1_REQUEST,
+ MCT_U232_SET_REQUEST_TYPE,
+ 0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE,
+ WDR_TIMEOUT);
if (rc < 0)
- err("Sending USB device request code %d failed (error = %d)",
+ err("Sending USB device request code %d failed (error = %d)",
MCT_U232_SET_UNKNOWN1_REQUEST, rc);
- if (port && C_CRTSCTS(port->tty)) {
+ if (port && C_CRTSCTS(tty))
cts_enable_byte = 1;
- }
- dbg("set_baud_rate: send second control message, data = %02X", cts_enable_byte);
+ dbg("set_baud_rate: send second control message, data = %02X",
+ cts_enable_byte);
rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- MCT_U232_SET_CTS_REQUEST,
- MCT_U232_SET_REQUEST_TYPE,
- 0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE,
- WDR_TIMEOUT);
+ MCT_U232_SET_CTS_REQUEST,
+ MCT_U232_SET_REQUEST_TYPE,
+ 0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE,
+ WDR_TIMEOUT);
if (rc < 0)
- err("Sending USB device request code %d failed (error = %d)",
- MCT_U232_SET_CTS_REQUEST, rc);
+ err("Sending USB device request code %d failed (error = %d)",
+ MCT_U232_SET_CTS_REQUEST, rc);
- return rc;
+ return rc;
} /* mct_u232_set_baud_rate */
static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
{
- int rc;
- rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- MCT_U232_SET_LINE_CTRL_REQUEST,
- MCT_U232_SET_REQUEST_TYPE,
- 0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
- WDR_TIMEOUT);
+ int rc;
+ rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ MCT_U232_SET_LINE_CTRL_REQUEST,
+ MCT_U232_SET_REQUEST_TYPE,
+ 0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
+ WDR_TIMEOUT);
if (rc < 0)
err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc);
dbg("set_line_ctrl: 0x%x", lcr);
- return rc;
+ return rc;
} /* mct_u232_set_line_ctrl */
static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
unsigned int control_state)
{
- int rc;
+ int rc;
unsigned char mcr = MCT_U232_MCR_NONE;
if (control_state & TIOCM_DTR)
@@ -314,37 +319,39 @@ static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
if (control_state & TIOCM_RTS)
mcr |= MCT_U232_MCR_RTS;
- rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- MCT_U232_SET_MODEM_CTRL_REQUEST,
- MCT_U232_SET_REQUEST_TYPE,
- 0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
- WDR_TIMEOUT);
+ rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ MCT_U232_SET_MODEM_CTRL_REQUEST,
+ MCT_U232_SET_REQUEST_TYPE,
+ 0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
+ WDR_TIMEOUT);
if (rc < 0)
err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc);
dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr);
- return rc;
+ return rc;
} /* mct_u232_set_modem_ctrl */
-static int mct_u232_get_modem_stat(struct usb_serial *serial, unsigned char *msr)
+static int mct_u232_get_modem_stat(struct usb_serial *serial,
+ unsigned char *msr)
{
- int rc;
- rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
- MCT_U232_GET_MODEM_STAT_REQUEST,
- MCT_U232_GET_REQUEST_TYPE,
- 0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
- WDR_TIMEOUT);
+ int rc;
+ rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ MCT_U232_GET_MODEM_STAT_REQUEST,
+ MCT_U232_GET_REQUEST_TYPE,
+ 0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
+ WDR_TIMEOUT);
if (rc < 0) {
err("Get MODEM STATus failed (error = %d)", rc);
*msr = 0;
}
dbg("get_modem_stat: 0x%x", *msr);
- return rc;
+ return rc;
} /* mct_u232_get_modem_stat */
-static void mct_u232_msr_to_state(unsigned int *control_state, unsigned char msr)
+static void mct_u232_msr_to_state(unsigned int *control_state,
+ unsigned char msr)
{
- /* Translate Control Line states */
+ /* Translate Control Line states */
if (msr & MCT_U232_MSR_DSR)
*control_state |= TIOCM_DSR;
else
@@ -361,14 +368,14 @@ static void mct_u232_msr_to_state(unsigned int *control_state, unsigned char msr
*control_state |= TIOCM_CD;
else
*control_state &= ~TIOCM_CD;
- dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state);
+ dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state);
} /* mct_u232_msr_to_state */
/*
* Driver's tty interface functions
*/
-static int mct_u232_startup (struct usb_serial *serial)
+static int mct_u232_startup(struct usb_serial *serial)
{
struct mct_u232_private *priv;
struct usb_serial_port *port, *rport;
@@ -390,18 +397,18 @@ static int mct_u232_startup (struct usb_serial *serial)
rport->interrupt_in_urb = NULL;
port->read_urb->context = port;
- return (0);
+ return 0;
} /* mct_u232_startup */
-static void mct_u232_shutdown (struct usb_serial *serial)
+static void mct_u232_shutdown(struct usb_serial *serial)
{
struct mct_u232_private *priv;
int i;
-
+
dbg("%s", __func__);
- for (i=0; i < serial->num_ports; ++i) {
+ for (i = 0; i < serial->num_ports; ++i) {
/* My special items, the standard routines free my urbs */
priv = usb_get_serial_port_data(serial->port[i]);
if (priv) {
@@ -411,7 +418,8 @@ static void mct_u232_shutdown (struct usb_serial *serial)
}
} /* mct_u232_shutdown */
-static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
+static int mct_u232_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
@@ -428,21 +436,22 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
* it seems to be able to accept only 16 bytes (and that's what
* SniffUSB says too...)
*/
- if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID)
+ if (le16_to_cpu(serial->dev->descriptor.idProduct)
+ == MCT_U232_SITECOM_PID)
port->bulk_out_size = 16;
- /* Do a defined restart: the normal serial device seems to
+ /* Do a defined restart: the normal serial device seems to
* always turn on DTR and RTS here, so do the same. I'm not
* sure if this is really necessary. But it should not harm
* either.
*/
spin_lock_irqsave(&priv->lock, flags);
- if (port->tty->termios->c_cflag & CBAUD)
+ if (tty && (tty->termios->c_cflag & CBAUD))
priv->control_state = TIOCM_DTR | TIOCM_RTS;
else
priv->control_state = 0;
-
- priv->last_lcr = (MCT_U232_DATA_BITS_8 |
+
+ priv->last_lcr = (MCT_U232_DATA_BITS_8 |
MCT_U232_PARITY_NONE |
MCT_U232_STOP_BITS_1);
control_state = priv->control_state;
@@ -481,15 +490,16 @@ error:
} /* mct_u232_open */
-static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
+static void mct_u232_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
unsigned int c_cflag;
unsigned int control_state;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
dbg("%s port %d", __func__, port->number);
- if (port->tty) {
- c_cflag = port->tty->termios->c_cflag;
+ if (tty) {
+ c_cflag = tty->termios->c_cflag;
mutex_lock(&port->serial->disc_mutex);
if (c_cflag & HUPCL && !port->serial->disconnected) {
/* drop DTR and RTS */
@@ -512,7 +522,7 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
} /* mct_u232_close */
-static void mct_u232_read_int_callback (struct urb *urb)
+static void mct_u232_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
@@ -545,36 +555,34 @@ static void mct_u232_read_int_callback (struct urb *urb)
return;
}
- dbg("%s - port %d", __func__, port->number);
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ dbg("%s - port %d", __func__, port->number);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
/*
* Work-a-round: handle the 'usual' bulk-in pipe here
*/
if (urb->transfer_buffer_length > 2) {
- int i;
- tty = port->tty;
+ tty = port->port.tty;
if (urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
goto exit;
}
-
+
/*
* The interrupt-in pipe signals exceptional conditions (modem line
* signal changes and errors). data[0] holds MSR, data[1] holds LSR.
*/
spin_lock_irqsave(&priv->lock, flags);
priv->last_msr = data[MCT_U232_MSR_INDEX];
-
+
/* Record Control Line states */
mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
#if 0
- /* Not yet handled. See belin_sa.c for further information */
+ /* Not yet handled. See belkin_sa.c for further information */
/* Now to report any errors */
priv->last_lsr = data[MCT_U232_LSR_INDEX];
/*
@@ -583,7 +591,7 @@ static void mct_u232_read_int_callback (struct urb *urb)
* to look in to this before committing any code.
*/
if (priv->last_lsr & MCT_U232_LSR_ERR) {
- tty = port->tty;
+ tty = port->port.tty;
/* Overrun Error */
if (priv->last_lsr & MCT_U232_LSR_OE) {
}
@@ -600,18 +608,19 @@ static void mct_u232_read_int_callback (struct urb *urb)
#endif
spin_unlock_irqrestore(&priv->lock, flags);
exit:
- retval = usb_submit_urb (urb, GFP_ATOMIC);
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- err ("%s - usb_submit_urb failed with result %d",
+ err("%s - usb_submit_urb failed with result %d",
__func__, retval);
} /* mct_u232_read_int_callback */
-static void mct_u232_set_termios (struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void mct_u232_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port,
+ struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
- struct ktermios *termios = port->tty->termios;
+ struct ktermios *termios = tty->termios;
unsigned int cflag = termios->c_cflag;
unsigned int old_cflag = old_termios->c_cflag;
unsigned long flags;
@@ -631,20 +640,20 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
* Premature optimization is the root of all evil.
*/
- /* reassert DTR and RTS on transition from B0 */
+ /* reassert DTR and RTS on transition from B0 */
if ((old_cflag & CBAUD) == B0) {
dbg("%s: baud was B0", __func__);
control_state |= TIOCM_DTR | TIOCM_RTS;
mct_u232_set_modem_ctrl(serial, control_state);
}
- mct_u232_set_baud_rate(serial, port, tty_get_baud_rate(port->tty));
+ mct_u232_set_baud_rate(tty, serial, port, tty_get_baud_rate(tty));
- if ((cflag & CBAUD) == B0 ) {
+ if ((cflag & CBAUD) == B0) {
dbg("%s: baud is B0", __func__);
/* Drop RTS and DTR */
control_state &= ~(TIOCM_DTR | TIOCM_RTS);
- mct_u232_set_modem_ctrl(serial, control_state);
+ mct_u232_set_modem_ctrl(serial, control_state);
}
/*
@@ -689,8 +698,9 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
spin_unlock_irqrestore(&priv->lock, flags);
} /* mct_u232_set_termios */
-static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
+static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned char lcr;
@@ -709,12 +719,13 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
} /* mct_u232_break_ctl */
-static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file)
+static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned int control_state;
unsigned long flags;
-
+
dbg("%s", __func__);
spin_lock_irqsave(&priv->lock, flags);
@@ -724,14 +735,15 @@ static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file)
return control_state;
}
-static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
+static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned int control_state;
unsigned long flags;
-
+
dbg("%s", __func__);
spin_lock_irqsave(&priv->lock, flags);
@@ -751,77 +763,50 @@ static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
return mct_u232_set_modem_ctrl(serial, control_state);
}
-static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- dbg("%scmd=0x%x", __func__, cmd);
-
- /* Based on code from acm.c and others */
- switch (cmd) {
- case TIOCMIWAIT:
- /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
- /* TODO */
- return( 0 );
-
- case TIOCGICOUNT:
- /* return count of modemline transitions */
- /* TODO */
- return 0;
-
- default:
- dbg("%s: arg not supported - 0x%04x", __func__,cmd);
- return(-ENOIOCTLCMD);
- break;
- }
- return 0;
-} /* mct_u232_ioctl */
-
-static void mct_u232_throttle (struct usb_serial_port *port)
+static void mct_u232_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int control_state;
- struct tty_struct *tty;
- tty = port->tty;
dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags);
priv->rx_flags |= THROTTLED;
if (C_CRTSCTS(tty)) {
- priv->control_state &= ~TIOCM_RTS;
- control_state = priv->control_state;
- spin_unlock_irqrestore(&priv->lock, flags);
- (void) mct_u232_set_modem_ctrl(port->serial, control_state);
+ priv->control_state &= ~TIOCM_RTS;
+ control_state = priv->control_state;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ (void) mct_u232_set_modem_ctrl(port->serial, control_state);
} else {
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
}
-static void mct_u232_unthrottle (struct usb_serial_port *port)
+static void mct_u232_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int control_state;
- struct tty_struct *tty;
dbg("%s - port %d", __func__, port->number);
- tty = port->tty;
spin_lock_irqsave(&priv->lock, flags);
if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
- priv->rx_flags &= ~THROTTLED;
- priv->control_state |= TIOCM_RTS;
- control_state = priv->control_state;
- spin_unlock_irqrestore(&priv->lock, flags);
- (void) mct_u232_set_modem_ctrl(port->serial, control_state);
+ priv->rx_flags &= ~THROTTLED;
+ priv->control_state |= TIOCM_RTS;
+ control_state = priv->control_state;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ (void) mct_u232_set_modem_ctrl(port->serial, control_state);
} else {
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
}
-static int __init mct_u232_init (void)
+static int __init mct_u232_init(void)
{
int retval;
retval = usb_serial_register(&mct_u232_device);
@@ -839,18 +824,17 @@ failed_usb_serial_register:
}
-static void __exit mct_u232_exit (void)
+static void __exit mct_u232_exit(void)
{
- usb_deregister (&mct_u232_driver);
- usb_serial_deregister (&mct_u232_device);
+ usb_deregister(&mct_u232_driver);
+ usb_serial_deregister(&mct_u232_device);
}
-
-module_init (mct_u232_init);
+module_init(mct_u232_init);
module_exit(mct_u232_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 50f1fe26333..7c4917d77c0 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -33,7 +33,7 @@
#include <linux/serial_reg.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
/*
@@ -64,8 +64,7 @@
#define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */
/* This structure holds all of the local port information */
-struct moschip_port
-{
+struct moschip_port {
__u8 shadowLCR; /* last LCR value received */
__u8 shadowMCR; /* last MCR value received */
__u8 shadowMSR; /* last MSR value received */
@@ -76,8 +75,7 @@ struct moschip_port
};
/* This structure holds all of the individual serial device information */
-struct moschip_serial
-{
+struct moschip_serial {
int interrupt_started;
};
@@ -88,7 +86,7 @@ static int debug;
#define MOSCHIP_DEVICE_ID_7715 0x7715
static struct usb_device_id moschip_port_id_table [] = {
- { USB_DEVICE(USB_VENDOR_ID_MOSCHIP,MOSCHIP_DEVICE_ID_7720) },
+ { USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7720) },
{ } /* terminating entry */
};
MODULE_DEVICE_TABLE(usb, moschip_port_id_table);
@@ -108,7 +106,7 @@ static void mos7720_interrupt_callback(struct urb *urb)
__u8 sp1;
__u8 sp2;
- dbg("%s"," : Entering\n");
+ dbg("%s", " : Entering\n");
switch (status) {
case 0:
@@ -208,7 +206,7 @@ static void mos7720_bulk_in_callback(struct urb *urb)
mos7720_port = urb->context;
if (!mos7720_port) {
- dbg("%s","NULL mos7720_port pointer \n");
+ dbg("%s", "NULL mos7720_port pointer \n");
return ;
}
@@ -218,7 +216,7 @@ static void mos7720_bulk_in_callback(struct urb *urb)
data = urb->transfer_buffer;
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
@@ -264,7 +262,7 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)
dbg("Entering .........");
- tty = mos7720_port->port->tty;
+ tty = mos7720_port->port->port.tty;
if (tty && mos7720_port->open)
tty_wakeup(tty);
@@ -284,17 +282,16 @@ static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value,
__u16 size = 0x0000;
if (value < MOS_MAX_PORT) {
- if (product == MOSCHIP_DEVICE_ID_7715) {
+ if (product == MOSCHIP_DEVICE_ID_7715)
value = value*0x100+0x100;
- } else {
+ else
value = value*0x100+0x200;
- }
} else {
value = 0x0000;
if ((product == MOSCHIP_DEVICE_ID_7715) &&
(index != 0x08)) {
dbg("serial->product== MOSCHIP_DEVICE_ID_7715");
- //index = 0x01 ;
+ /* index = 0x01 ; */
}
}
@@ -308,19 +305,20 @@ static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value,
request = (__u8)MOS_READ;
requesttype = (__u8)0xC0;
size = 0x01;
- pipe = usb_rcvctrlpipe(serial->dev,0);
+ pipe = usb_rcvctrlpipe(serial->dev, 0);
}
status = usb_control_msg(serial->dev, pipe, request, requesttype,
value, index, data, size, MOS_WDR_TIMEOUT);
if (status < 0)
- dbg("Command Write failed Value %x index %x\n",value,index);
+ dbg("Command Write failed Value %x index %x\n", value, index);
return status;
}
-static int mos7720_open(struct usb_serial_port *port, struct file * filp)
+static int mos7720_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial;
struct usb_serial_port *port0;
@@ -351,7 +349,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
/* Initialising the write urb pool */
for (j = 0; j < NUM_URBS; ++j) {
- urb = usb_alloc_urb(0,GFP_KERNEL);
+ urb = usb_alloc_urb(0, GFP_KERNEL);
mos7720_port->write_urb_pool[j] = urb;
if (urb == NULL) {
@@ -385,7 +383,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
*/
port_number = port->number - port->serial->minor;
send_mos_cmd(port->serial, MOS_READ, port_number, UART_LSR, &data);
- dbg("SS::%p LSR:%x\n",mos7720_port, data);
+ dbg("SS::%p LSR:%x\n", mos7720_port, data);
dbg("Check:Sending Command ..........");
@@ -402,10 +400,10 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
data = 0xCF;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data);
data = 0x03;
- mos7720_port->shadowLCR = data;
+ mos7720_port->shadowLCR = data;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
data = 0x0b;
- mos7720_port->shadowMCR = data;
+ mos7720_port->shadowMCR = data;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
data = 0x0b;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
@@ -420,7 +418,8 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
data = 0x03;
send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data);
data = 0x00;
- send_mos_cmd(port->serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data);
+ send_mos_cmd(port->serial, MOS_WRITE, MOS_MAX_PORT,
+ port_number + 1, &data);
*/
data = 0x00;
send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data);
@@ -429,28 +428,26 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
data = 0x83;
- mos7720_port->shadowLCR = data;
+ mos7720_port->shadowLCR = data;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
data = 0x0c;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data);
data = 0x00;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
data = 0x03;
- mos7720_port->shadowLCR = data;
+ mos7720_port->shadowLCR = data;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
data = 0x0c;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
data = 0x0c;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
-//Matrix
-
/* force low_latency on so that our tty_push actually forces *
* the data through,otherwise it is scheduled, and with *
* high data rates (like with OHCI) data can get lost. */
- if (port->tty)
- port->tty->low_latency = 1;
+ if (tty)
+ tty->low_latency = 1;
/* see if we've set up our endpoint info yet *
* (can't set it up in mos7720_startup as the *
@@ -465,15 +462,15 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
/* set up our interrupt urb */
usb_fill_int_urb(port0->interrupt_in_urb, serial->dev,
- usb_rcvintpipe(serial->dev,
- port->interrupt_in_endpointAddress),
- port0->interrupt_in_buffer,
- port0->interrupt_in_urb->transfer_buffer_length,
- mos7720_interrupt_callback, mos7720_port,
- port0->interrupt_in_urb->interval);
+ usb_rcvintpipe(serial->dev,
+ port->interrupt_in_endpointAddress),
+ port0->interrupt_in_buffer,
+ port0->interrupt_in_urb->transfer_buffer_length,
+ mos7720_interrupt_callback, mos7720_port,
+ port0->interrupt_in_urb->interval);
/* start interrupt read for this mos7720 this interrupt *
- * will continue as long as the mos7720 is connected */
+ * will continue as long as the mos7720 is connected */
dbg("Submit URB over !!!");
response = usb_submit_urb(port0->interrupt_in_urb, GFP_KERNEL);
if (response)
@@ -485,14 +482,14 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
/* set up our bulk in urb */
usb_fill_bulk_urb(port->read_urb, serial->dev,
usb_rcvbulkpipe(serial->dev,
- port->bulk_in_endpointAddress),
+ port->bulk_in_endpointAddress),
port->bulk_in_buffer,
port->read_urb->transfer_buffer_length,
mos7720_bulk_in_callback, mos7720_port);
response = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (response)
- dev_err(&port->dev,
- "%s - Error %d submitting read urb\n", __func__, response);
+ dev_err(&port->dev, "%s - Error %d submitting read urb\n",
+ __func__, response);
/* initialize our icount structure */
memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount));
@@ -515,8 +512,9 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
* system,
* Otherwise we return a negative error number.
*/
-static int mos7720_chars_in_buffer(struct usb_serial_port *port)
+static int mos7720_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int i;
int chars = 0;
struct moschip_port *mos7720_port;
@@ -530,14 +528,16 @@ static int mos7720_chars_in_buffer(struct usb_serial_port *port)
}
for (i = 0; i < NUM_URBS; ++i) {
- if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status == -EINPROGRESS)
+ if (mos7720_port->write_urb_pool[i] &&
+ mos7720_port->write_urb_pool[i]->status == -EINPROGRESS)
chars += URB_TRANSFER_BUFFER_SIZE;
}
dbg("%s - returns %d", __func__, chars);
return chars;
}
-static void mos7720_close(struct usb_serial_port *port, struct file *filp)
+static void mos7720_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial;
struct moschip_port *mos7720_port;
@@ -575,12 +575,12 @@ static void mos7720_close(struct usb_serial_port *port, struct file *filp)
* been disconnected */
if (!serial->disconnected) {
data = 0x00;
- send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
- 0x04, &data);
+ send_mos_cmd(serial, MOS_WRITE,
+ port->number - port->serial->minor, 0x04, &data);
data = 0x00;
- send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
- 0x01, &data);
+ send_mos_cmd(serial, MOS_WRITE,
+ port->number - port->serial->minor, 0x01, &data);
}
mutex_unlock(&serial->disc_mutex);
mos7720_port->open = 0;
@@ -588,9 +588,10 @@ static void mos7720_close(struct usb_serial_port *port, struct file *filp)
dbg("Leaving %s", __func__);
}
-static void mos7720_break(struct usb_serial_port *port, int break_state)
+static void mos7720_break(struct tty_struct *tty, int break_state)
{
- unsigned char data;
+ struct usb_serial_port *port = tty->driver_data;
+ unsigned char data;
struct usb_serial *serial;
struct moschip_port *mos7720_port;
@@ -621,8 +622,9 @@ static void mos7720_break(struct usb_serial_port *port, int break_state)
* If successful, we return the amount of room that we have for this port
* Otherwise we return a negative error number.
*/
-static int mos7720_write_room(struct usb_serial_port *port)
+static int mos7720_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7720_port;
int room = 0;
int i;
@@ -637,7 +639,8 @@ static int mos7720_write_room(struct usb_serial_port *port)
/* FIXME: Locking */
for (i = 0; i < NUM_URBS; ++i) {
- if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)
+ if (mos7720_port->write_urb_pool[i] &&
+ mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)
room += URB_TRANSFER_BUFFER_SIZE;
}
@@ -645,8 +648,8 @@ static int mos7720_write_room(struct usb_serial_port *port)
return room;
}
-static int mos7720_write(struct usb_serial_port *port,
- const unsigned char *data, int count)
+static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *data, int count)
{
int status;
int i;
@@ -672,9 +675,10 @@ static int mos7720_write(struct usb_serial_port *port,
urb = NULL;
for (i = 0; i < NUM_URBS; ++i) {
- if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) {
+ if (mos7720_port->write_urb_pool[i] &&
+ mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) {
urb = mos7720_port->write_urb_pool[i];
- dbg("URB:%d",i);
+ dbg("URB:%d", i);
break;
}
}
@@ -692,7 +696,7 @@ static int mos7720_write(struct usb_serial_port *port,
goto exit;
}
}
- transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE);
+ transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
memcpy(urb->transfer_buffer, current_position, transfer_size);
usb_serial_debug_data(debug, &port->dev, __func__, transfer_size,
@@ -701,12 +705,12 @@ static int mos7720_write(struct usb_serial_port *port,
/* fill urb with data and submit */
usb_fill_bulk_urb(urb, serial->dev,
usb_sndbulkpipe(serial->dev,
- port->bulk_out_endpointAddress),
+ port->bulk_out_endpointAddress),
urb->transfer_buffer, transfer_size,
mos7720_bulk_out_data_callback, mos7720_port);
/* send it down the pipe */
- status = usb_submit_urb(urb,GFP_ATOMIC);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
err("%s - usb_submit_urb(write bulk) failed with status = %d",
__func__, status);
@@ -719,10 +723,10 @@ exit:
return bytes_sent;
}
-static void mos7720_throttle(struct usb_serial_port *port)
+static void mos7720_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7720_port;
- struct tty_struct *tty;
int status;
dbg("%s- port %d\n", __func__, port->number);
@@ -739,16 +743,10 @@ static void mos7720_throttle(struct usb_serial_port *port)
dbg("%s: Entering ..........", __func__);
- tty = port->tty;
- if (!tty) {
- dbg("%s - no tty available", __func__);
- return;
- }
-
/* if we are implementing XON/XOFF, send the stop character */
if (I_IXOFF(tty)) {
unsigned char stop_char = STOP_CHAR(tty);
- status = mos7720_write(port, &stop_char, 1);
+ status = mos7720_write(tty, port, &stop_char, 1);
if (status <= 0)
return;
}
@@ -764,11 +762,11 @@ static void mos7720_throttle(struct usb_serial_port *port)
}
}
-static void mos7720_unthrottle(struct usb_serial_port *port)
+static void mos7720_unthrottle(struct tty_struct *tty)
{
- struct tty_struct *tty;
- int status;
+ struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7720_port = usb_get_serial_port_data(port);
+ int status;
if (mos7720_port == NULL)
return;
@@ -780,16 +778,10 @@ static void mos7720_unthrottle(struct usb_serial_port *port)
dbg("%s: Entering ..........", __func__);
- tty = port->tty;
- if (!tty) {
- dbg("%s - no tty available", __func__);
- return;
- }
-
/* if we are implementing XON/XOFF, send the start character */
if (I_IXOFF(tty)) {
unsigned char start_char = START_CHAR(tty);
- status = mos7720_write(port, &start_char, 1);
+ status = mos7720_write(tty, port, &start_char, 1);
if (status <= 0)
return;
}
@@ -819,9 +811,9 @@ static int set_higher_rates(struct moschip_port *mos7720_port,
port = mos7720_port->port;
serial = port->serial;
- /***********************************************
- * Init Sequence for higher rates
- ***********************************************/
+ /***********************************************
+ * Init Sequence for higher rates
+ ***********************************************/
dbg("Sending Setting Commands ..........");
port_number = port->number - port->serial->minor;
@@ -832,7 +824,7 @@ static int set_higher_rates(struct moschip_port *mos7720_port,
data = 0x0CF;
send_mos_cmd(serial, MOS_WRITE, port->number, 0x02, &data);
data = 0x00b;
- mos7720_port->shadowMCR = data;
+ mos7720_port->shadowMCR = data;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
data = 0x00b;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
@@ -843,12 +835,12 @@ static int set_higher_rates(struct moschip_port *mos7720_port,
send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
- /***********************************************
- * Set for higher rates *
- ***********************************************/
+ /***********************************************
+ * Set for higher rates *
+ ***********************************************/
data = baud * 0x10;
- send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1,&data);
+ send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data);
data = 0x003;
send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data);
@@ -856,34 +848,33 @@ static int set_higher_rates(struct moschip_port *mos7720_port,
send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
data = 0x02b;
- mos7720_port->shadowMCR = data;
+ mos7720_port->shadowMCR = data;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
data = 0x02b;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
- /***********************************************
- * Set DLL/DLM
- ***********************************************/
+ /***********************************************
+ * Set DLL/DLM
+ ***********************************************/
data = mos7720_port->shadowLCR | UART_LCR_DLAB;
- mos7720_port->shadowLCR = data;
+ mos7720_port->shadowLCR = data;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
data = 0x001; /* DLL */
- send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data);
+ send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data);
data = 0x000; /* DLM */
- send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
+ send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
data = mos7720_port->shadowLCR & ~UART_LCR_DLAB;
- mos7720_port->shadowLCR = data;
+ mos7720_port->shadowLCR = data;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
return 0;
}
/* baud rate information */
-struct divisor_table_entry
-{
+struct divisor_table_entry {
__u32 baudrate;
__u16 divisor;
};
@@ -932,8 +923,8 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor)
}
}
- /* After trying for all the standard baud rates *
- * Try calculating the divisor for this baud rate */
+ /* After trying for all the standard baud rates *
+ * Try calculating the divisor for this baud rate */
if (baudrate > 75 && baudrate < 230400) {
/* get the divisor */
custom = (__u16)(230400L / baudrate);
@@ -945,7 +936,7 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor)
custom++;
*divisor = custom;
- dbg("Baud %d = %d",baudrate, custom);
+ dbg("Baud %d = %d", baudrate, custom);
return 0;
}
@@ -979,29 +970,29 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port,
number = port->number - port->serial->minor;
dbg("%s - port = %d, baud = %d", __func__, port->number, baudrate);
- /* Calculate the Divisor */
+ /* Calculate the Divisor */
status = calc_baud_rate_divisor(baudrate, &divisor);
if (status) {
err("%s - bad baud rate", __func__);
return status;
}
- /* Enable access to divisor latch */
- data = mos7720_port->shadowLCR | UART_LCR_DLAB;
- mos7720_port->shadowLCR = data;
- send_mos_cmd(serial, MOS_WRITE, number, UART_LCR, &data);
+ /* Enable access to divisor latch */
+ data = mos7720_port->shadowLCR | UART_LCR_DLAB;
+ mos7720_port->shadowLCR = data;
+ send_mos_cmd(serial, MOS_WRITE, number, UART_LCR, &data);
/* Write the divisor */
data = ((unsigned char)(divisor & 0xff));
- send_mos_cmd(serial, MOS_WRITE, number, 0x00, &data);
+ send_mos_cmd(serial, MOS_WRITE, number, 0x00, &data);
data = ((unsigned char)((divisor & 0xff00) >> 8));
- send_mos_cmd(serial, MOS_WRITE, number, 0x01, &data);
+ send_mos_cmd(serial, MOS_WRITE, number, 0x01, &data);
- /* Disable access to divisor latch */
- data = mos7720_port->shadowLCR & ~UART_LCR_DLAB;
- mos7720_port->shadowLCR = data;
- send_mos_cmd(serial, MOS_WRITE, number, 0x03, &data);
+ /* Disable access to divisor latch */
+ data = mos7720_port->shadowLCR & ~UART_LCR_DLAB;
+ mos7720_port->shadowLCR = data;
+ send_mos_cmd(serial, MOS_WRITE, number, 0x03, &data);
return status;
}
@@ -1011,12 +1002,12 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port,
* This routine is called to set the UART on the device to match
* the specified new settings.
*/
-static void change_port_settings(struct moschip_port *mos7720_port,
+static void change_port_settings(struct tty_struct *tty,
+ struct moschip_port *mos7720_port,
struct ktermios *old_termios)
{
struct usb_serial_port *port;
struct usb_serial *serial;
- struct tty_struct *tty;
int baud;
unsigned cflag;
unsigned iflag;
@@ -1042,8 +1033,6 @@ static void change_port_settings(struct moschip_port *mos7720_port,
return;
}
- tty = mos7720_port->port->tty;
-
dbg("%s: Entering ..........", __func__);
lData = UART_LCR_WLEN8;
@@ -1106,29 +1095,31 @@ static void change_port_settings(struct moschip_port *mos7720_port,
#define LCR_PAR_MASK 0x38 /* Mask for parity field */
/* Update the LCR with the correct value */
- mos7720_port->shadowLCR &= ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
+ mos7720_port->shadowLCR &=
+ ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
mos7720_port->shadowLCR |= (lData | lParity | lStop);
/* Disable Interrupts */
data = 0x00;
- send_mos_cmd(serial,MOS_WRITE,port->number - port->serial->minor, UART_IER, &data);
+ send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
+ UART_IER, &data);
data = 0x00;
- send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);
+ send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);
data = 0xcf;
- send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);
+ send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);
/* Send the updated LCR value to the mos7720 */
data = mos7720_port->shadowLCR;
- send_mos_cmd(serial, MOS_WRITE, port_number, UART_LCR, &data);
+ send_mos_cmd(serial, MOS_WRITE, port_number, UART_LCR, &data);
- data = 0x00b;
- mos7720_port->shadowMCR = data;
- send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
- data = 0x00b;
- send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
+ data = 0x00b;
+ mos7720_port->shadowMCR = data;
+ send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
+ data = 0x00b;
+ send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
/* set up the MCR register and send it to the mos7720 */
mos7720_port->shadowMCR = UART_MCR_OUT2;
@@ -1137,9 +1128,8 @@ static void change_port_settings(struct moschip_port *mos7720_port,
if (cflag & CRTSCTS) {
mos7720_port->shadowMCR |= (UART_MCR_XONANY);
-
- /* To set hardware flow control to the specified *
- * serial port, in SP1/2_CONTROL_REG */
+ /* To set hardware flow control to the specified *
+ * serial port, in SP1/2_CONTROL_REG */
if (port->number) {
data = 0x001;
send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT,
@@ -1198,14 +1188,13 @@ static void change_port_settings(struct moschip_port *mos7720_port,
* this function is called by the tty driver when it wants to change the
* termios structure.
*/
-static void mos7720_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void mos7720_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
int status;
unsigned int cflag;
struct usb_serial *serial;
struct moschip_port *mos7720_port;
- struct tty_struct *tty;
serial = port->serial;
@@ -1214,15 +1203,12 @@ static void mos7720_set_termios(struct usb_serial_port *port,
if (mos7720_port == NULL)
return;
- tty = port->tty;
-
-
if (!mos7720_port->open) {
dbg("%s - port not opened", __func__);
return;
}
- dbg("%s\n","setting termios - ASPIRE");
+ dbg("%s\n", "setting termios - ASPIRE");
cflag = tty->termios->c_cflag;
@@ -1237,14 +1223,14 @@ static void mos7720_set_termios(struct usb_serial_port *port,
dbg("%s - port %d", __func__, port->number);
/* change the port settings to the new ones specified */
- change_port_settings(mos7720_port, old_termios);
+ change_port_settings(tty, mos7720_port, old_termios);
- if(!port->read_urb) {
- dbg("%s","URB KILLED !!!!!\n");
+ if (!port->read_urb) {
+ dbg("%s", "URB KILLED !!!!!\n");
return;
}
- if(port->read_urb->status != -EINPROGRESS) {
+ if (port->read_urb->status != -EINPROGRESS) {
port->read_urb->dev = serial->dev;
status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (status)
@@ -1264,13 +1250,13 @@ static void mos7720_set_termios(struct usb_serial_port *port,
* transmit holding register is empty. This functionality
* allows an RS485 driver to be written in user space.
*/
-static int get_lsr_info(struct moschip_port *mos7720_port,
- unsigned int __user *value)
+static int get_lsr_info(struct tty_struct *tty,
+ struct moschip_port *mos7720_port, unsigned int __user *value)
{
int count;
unsigned int result = 0;
- count = mos7720_chars_in_buffer(mos7720_port->port);
+ count = mos7720_chars_in_buffer(tty);
if (count == 0) {
dbg("%s -- Empty", __func__);
result = TIOCSER_TEMT;
@@ -1290,7 +1276,7 @@ static int get_number_bytes_avail(struct moschip_port *mos7720_port,
unsigned int __user *value)
{
unsigned int result = 0;
- struct tty_struct *tty = mos7720_port->port->tty;
+ struct tty_struct *tty = mos7720_port->port->port.tty;
if (!tty)
return -ENOIOCTLCMD;
@@ -1316,7 +1302,7 @@ static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
if (mos7720_port == NULL)
return -1;
- port = (struct usb_serial_port*)mos7720_port->port;
+ port = (struct usb_serial_port *)mos7720_port->port;
mcr = mos7720_port->shadowMCR;
if (copy_from_user(&arg, value, sizeof(int)))
@@ -1397,7 +1383,7 @@ static int get_serial_info(struct moschip_port *mos7720_port,
tmp.port = mos7720_port->port->number;
tmp.irq = 0;
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
- tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
+ tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
tmp.baud_base = 9600;
tmp.close_delay = 5*HZ;
tmp.closing_wait = 30*HZ;
@@ -1407,9 +1393,10 @@ static int get_serial_info(struct moschip_port *mos7720_port,
return 0;
}
-static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
+static int mos7720_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7720_port;
struct async_icount cnow;
struct async_icount cprev;
@@ -1431,14 +1418,16 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
case TIOCSERGETLSR:
dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
- return get_lsr_info(mos7720_port, (unsigned int __user *)arg);
+ return get_lsr_info(tty, mos7720_port,
+ (unsigned int __user *)arg);
return 0;
+ /* FIXME: These should be using the mode methods */
case TIOCMBIS:
case TIOCMBIC:
case TIOCMSET:
- dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__,
- port->number);
+ dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET",
+ __func__, port->number);
return set_modem_info(mos7720_port, cmd,
(unsigned int __user *)arg);
@@ -1452,10 +1441,6 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
return get_serial_info(mos7720_port,
(struct serial_struct __user *)arg);
- case TIOCSSERIAL:
- dbg("%s (%d) TIOCSSERIAL", __func__, port->number);
- break;
-
case TIOCMIWAIT:
dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
cprev = mos7720_port->icount;
@@ -1469,7 +1454,7 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
return 0;
}
cprev = cnow;
@@ -1492,7 +1477,7 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
icount.buf_overrun = cnow.buf_overrun;
dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
- port->number, icount.rx, icount.tx );
+ port->number, icount.rx, icount.tx);
if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
return -EFAULT;
return 0;
@@ -1543,7 +1528,8 @@ static int mos7720_startup(struct usb_serial *serial)
/* Initialize all port interrupt end point to port 0 int
* endpoint. Our device has only one interrupt endpoint
* comman to all ports */
- serial->port[i]->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress;
+ serial->port[i]->interrupt_in_endpointAddress =
+ serial->port[0]->interrupt_in_endpointAddress;
mos7720_port->port = serial->port[i];
usb_set_serial_port_data(serial->port[i], mos7720_port);
@@ -1555,13 +1541,15 @@ static int mos7720_startup(struct usb_serial *serial)
/* setting configuration feature to one */
usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- (__u8)0x03, 0x00,0x01,0x00, NULL, 0x00, 5*HZ);
+ (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ);
- send_mos_cmd(serial,MOS_READ,0x00, UART_LSR, &data); // LSR For Port 1
- dbg("LSR:%x",data);
+ /* LSR For Port 1 */
+ send_mos_cmd(serial, MOS_READ, 0x00, UART_LSR, &data);
+ dbg("LSR:%x", data);
- send_mos_cmd(serial,MOS_READ,0x01, UART_LSR, &data); // LSR For Port 2
- dbg("LSR:%x",data);
+ /* LSR For Port 2 */
+ send_mos_cmd(serial, MOS_READ, 0x01, UART_LSR, &data);
+ dbg("LSR:%x", data);
return 0;
}
@@ -1571,7 +1559,7 @@ static void mos7720_shutdown(struct usb_serial *serial)
int i;
/* free private structure allocated for serial port */
- for (i=0; i < serial->num_ports; ++i) {
+ for (i = 0; i < serial->num_ports; ++i) {
kfree(usb_get_serial_port_data(serial->port[i]));
usb_set_serial_port_data(serial->port[i], NULL);
}
@@ -1651,8 +1639,8 @@ module_init(moschip7720_init);
module_exit(moschip7720_exit);
/* Module information */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 78f2f6db494..09d82062b97 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -33,7 +33,7 @@
#include <linux/serial.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
/*
* Version Information
@@ -82,8 +82,8 @@
* Defines used for sending commands to port
*/
-#define WAIT_FOR_EVER (HZ * 0 ) /* timeout urb is wait for ever */
-#define MOS_WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
+#define WAIT_FOR_EVER (HZ * 0) /* timeout urb is wait for ever */
+#define MOS_WDR_TIMEOUT (HZ * 5) /* default urb timeout */
#define MOS_PORT1 0x0200
#define MOS_PORT2 0x0300
@@ -102,8 +102,8 @@
#define MAX_NAME_LEN 64
-#define ZLP_REG1 0x3A //Zero_Flag_Reg1 58
-#define ZLP_REG5 0x3E //Zero_Flag_Reg5 62
+#define ZLP_REG1 0x3A /* Zero_Flag_Reg1 58 */
+#define ZLP_REG5 0x3E /* Zero_Flag_Reg5 62 */
/* For higher baud Rates use TIOCEXBAUD */
#define TIOCEXBAUD 0x5462
@@ -142,7 +142,7 @@
#define MOS_MSR_DELTA_RI 0x40
#define MOS_MSR_DELTA_CD 0x80
-// Serial Port register Address
+/* Serial Port register Address */
#define INTERRUPT_ENABLE_REGISTER ((__u16)(0x01))
#define FIFO_CONTROL_REGISTER ((__u16)(0x02))
#define LINE_CONTROL_REGISTER ((__u16)(0x03))
@@ -201,11 +201,11 @@ struct moschip_port {
struct async_icount icount;
struct usb_serial_port *port; /* loop back to the owner of this object */
- /*Offsets */
+ /* Offsets */
__u8 SpRegOffset;
__u8 ControlRegOffset;
__u8 DcrRegOffset;
- //for processing control URBS in interrupt context
+ /* for processing control URBS in interrupt context */
struct urb *control_urb;
struct usb_ctrlrequest *dr;
char *ctrl_buf;
@@ -244,7 +244,7 @@ static int mos7840_set_reg_sync(struct usb_serial_port *port, __u16 reg,
*/
static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg,
- __u16 * val)
+ __u16 *val)
{
struct usb_device *dev = port->serial->dev;
int ret = 0;
@@ -269,16 +269,15 @@ static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg,
struct usb_device *dev = port->serial->dev;
val = val & 0x00ff;
- // For the UART control registers, the application number need to be Or'ed
+ /* For the UART control registers, the application number need
+ to be Or'ed */
if (port->serial->num_ports == 4) {
- val |=
- (((__u16) port->number - (__u16) (port->serial->minor)) +
- 1) << 8;
+ val |= (((__u16) port->number -
+ (__u16) (port->serial->minor)) + 1) << 8;
dbg("mos7840_set_uart_reg application number is %x\n", val);
} else {
if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) {
- val |=
- (((__u16) port->number -
+ val |= (((__u16) port->number -
(__u16) (port->serial->minor)) + 1) << 8;
dbg("mos7840_set_uart_reg application number is %x\n",
val);
@@ -302,14 +301,15 @@ static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg,
* by passing usb_rcvctrlpipe function as parameter.
*/
static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg,
- __u16 * val)
+ __u16 *val)
{
struct usb_device *dev = port->serial->dev;
int ret = 0;
__u16 Wval;
- //dbg("application number is %4x \n",(((__u16)port->number - (__u16)(port->serial->minor))+1)<<8);
- /*Wval is same as application number */
+ /* dbg("application number is %4x \n",
+ (((__u16)port->number - (__u16)(port->serial->minor))+1)<<8); */
+ /* Wval is same as application number */
if (port->serial->num_ports == 4) {
Wval =
(((__u16) port->number - (__u16) (port->serial->minor)) +
@@ -317,14 +317,12 @@ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg,
dbg("mos7840_get_uart_reg application number is %x\n", Wval);
} else {
if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) {
- Wval =
- (((__u16) port->number -
+ Wval = (((__u16) port->number -
(__u16) (port->serial->minor)) + 1) << 8;
dbg("mos7840_get_uart_reg application number is %x\n",
Wval);
} else {
- Wval =
- (((__u16) port->number -
+ Wval = (((__u16) port->number -
(__u16) (port->serial->minor)) + 2) << 8;
dbg("mos7840_get_uart_reg application number is %x\n",
Wval);
@@ -406,11 +404,11 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
dbg("%s - %02x", __func__, new_lsr);
if (new_lsr & SERIAL_LSR_BI) {
- //
- // Parity and Framing errors only count if they
- // occur exclusive of a break being
- // received.
- //
+ /*
+ * Parity and Framing errors only count if they
+ * occur exclusive of a break being
+ * received.
+ */
new_lsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI);
}
@@ -492,7 +490,7 @@ exit:
}
static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
- __u16 * val)
+ __u16 *val)
{
struct usb_device *dev = mcs->port->serial->dev;
struct usb_ctrlrequest *dr = mcs->dr;
@@ -501,7 +499,7 @@ static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
dr->bRequestType = MCS_RD_RTYPE;
dr->bRequest = MCS_RDREQ;
- dr->wValue = cpu_to_le16(Wval); //0;
+ dr->wValue = cpu_to_le16(Wval); /* 0 */
dr->wIndex = cpu_to_le16(reg);
dr->wLength = cpu_to_le16(2);
@@ -607,7 +605,8 @@ static void mos7840_interrupt_callback(struct urb *urb)
}
}
}
- if (!(rv < 0)) /* the completion handler for the control urb will resubmit */
+ if (!(rv < 0))
+ /* the completion handler for the control urb will resubmit */
return;
exit:
result = usb_submit_urb(urb, GFP_ATOMIC);
@@ -656,8 +655,8 @@ static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port,
if (!port ||
mos7840_port_paranoia_check(port, function) ||
mos7840_serial_paranoia_check(port->serial, function)) {
- /* then say that we don't have a valid usb_serial thing, which will
- * end up genrating -ENODEV return values */
+ /* then say that we don't have a valid usb_serial thing,
+ * which will end up genrating -ENODEV return values */
return NULL;
}
@@ -710,7 +709,7 @@ static void mos7840_bulk_in_callback(struct urb *urb)
dbg("%s", "Entering ........... \n");
if (urb->actual_length) {
- tty = mos7840_port->port->tty;
+ tty = mos7840_port->port->port.tty;
if (tty) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
@@ -741,8 +740,8 @@ static void mos7840_bulk_in_callback(struct urb *urb)
/*****************************************************************************
* mos7840_bulk_out_data_callback
- * this is the callback function for when we have finished sending serial data
- * on the bulk out endpoint.
+ * this is the callback function for when we have finished sending
+ * serial data on the bulk out endpoint.
*****************************************************************************/
static void mos7840_bulk_out_data_callback(struct urb *urb)
@@ -774,7 +773,7 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
dbg("%s \n", "Entering .........");
- tty = mos7840_port->port->tty;
+ tty = mos7840_port->port->port.tty;
if (tty && mos7840_port->open)
tty_wakeup(tty);
@@ -804,7 +803,8 @@ static int mos7840_serial_probe(struct usb_serial *serial,
* Otherwise we return a negative error number.
*****************************************************************************/
-static int mos7840_open(struct usb_serial_port *port, struct file *filp)
+static int mos7840_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
int response;
int j;
@@ -847,7 +847,8 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
continue;
}
- urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+ urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
+ GFP_KERNEL);
if (!urb->transfer_buffer) {
usb_free_urb(urb);
mos7840_port->write_urb_pool[j] = NULL;
@@ -868,9 +869,8 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
* 0x08 : SP1/2 Control Reg
*****************************************************************************/
-//NEED to check the following Block
+ /* NEED to check the following Block */
- status = 0;
Data = 0x0;
status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
if (status < 0) {
@@ -890,36 +890,35 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
dbg("writing Spreg failed\n");
return -1;
}
-//End of block to be checked
+ /* End of block to be checked */
- status = 0;
Data = 0x0;
- status =
- mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+ status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset,
+ &Data);
if (status < 0) {
dbg("Reading Controlreg failed\n");
return -1;
}
- Data |= 0x08; //Driver done bit
- Data |= 0x20; //rx_disable
- status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+ Data |= 0x08; /* Driver done bit */
+ Data |= 0x20; /* rx_disable */
+ status = mos7840_set_reg_sync(port,
+ mos7840_port->ControlRegOffset, Data);
if (status < 0) {
dbg("writing Controlreg failed\n");
return -1;
}
- //do register settings here
- // Set all regs to the device default values.
- ////////////////////////////////////
- // First Disable all interrupts.
- ////////////////////////////////////
-
+ /* do register settings here */
+ /* Set all regs to the device default values. */
+ /***********************************
+ * First Disable all interrupts.
+ ***********************************/
Data = 0x00;
status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
if (status < 0) {
dbg("disableing interrupts failed\n");
return -1;
}
- // Set FIFO_CONTROL_REGISTER to the default value
+ /* Set FIFO_CONTROL_REGISTER to the default value */
Data = 0x00;
status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
if (status < 0) {
@@ -946,90 +945,73 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
mos7840_port->shadowLCR = Data;
- Data |= SERIAL_LCR_DLAB; //data latch enable in LCR 0x80
+ Data |= SERIAL_LCR_DLAB; /* data latch enable in LCR 0x80 */
status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
Data = 0x0c;
- status = 0;
status = mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data);
Data = 0x0;
- status = 0;
status = mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data);
Data = 0x00;
- status = 0;
status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
Data = Data & ~SERIAL_LCR_DLAB;
- status = 0;
status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
mos7840_port->shadowLCR = Data;
- //clearing Bulkin and Bulkout Fifo
+ /* clearing Bulkin and Bulkout Fifo */
Data = 0x0;
- status = 0;
status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
Data = Data | 0x0c;
- status = 0;
status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
Data = Data & ~0x0c;
- status = 0;
status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
- //Finally enable all interrupts
- Data = 0x0;
+ /* Finally enable all interrupts */
Data = 0x0c;
- status = 0;
status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
- //clearing rx_disable
+ /* clearing rx_disable */
Data = 0x0;
- status = 0;
- status =
- mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+ status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset,
+ &Data);
Data = Data & ~0x20;
- status = 0;
- status =
- mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+ status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset,
+ Data);
- // rx_negate
+ /* rx_negate */
Data = 0x0;
- status = 0;
- status =
- mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+ status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset,
+ &Data);
Data = Data | 0x10;
- status = 0;
- status =
- mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+ status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset,
+ Data);
/* force low_latency on so that our tty_push actually forces *
* the data through,otherwise it is scheduled, and with *
* high data rates (like with OHCI) data can get lost. */
+ if (tty)
+ tty->low_latency = 1;
- if (port->tty)
- port->tty->low_latency = 1;
-/* Check to see if we've set up our endpoint info yet *
- * (can't set it up in mos7840_startup as the structures *
- * were not set up at that time.) */
+ /* Check to see if we've set up our endpoint info yet *
+ * (can't set it up in mos7840_startup as the structures *
+ * were not set up at that time.) */
if (port0->open_ports == 1) {
if (serial->port[0]->interrupt_in_buffer == NULL) {
-
/* set up interrupt urb */
-
usb_fill_int_urb(serial->port[0]->interrupt_in_urb,
- serial->dev,
- usb_rcvintpipe(serial->dev,
- serial->port[0]->
- interrupt_in_endpointAddress),
- serial->port[0]->interrupt_in_buffer,
- serial->port[0]->interrupt_in_urb->
- transfer_buffer_length,
- mos7840_interrupt_callback,
- serial,
- serial->port[0]->interrupt_in_urb->
- interval);
+ serial->dev,
+ usb_rcvintpipe(serial->dev,
+ serial->port[0]->interrupt_in_endpointAddress),
+ serial->port[0]->interrupt_in_buffer,
+ serial->port[0]->interrupt_in_urb->
+ transfer_buffer_length,
+ mos7840_interrupt_callback,
+ serial,
+ serial->port[0]->interrupt_in_urb->interval);
/* start interrupt read for mos7840 *
* will continue as long as mos7840 is connected */
@@ -1084,14 +1066,16 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
/* initialize our port settings */
- mos7840_port->shadowMCR = MCR_MASTER_IE; /* Must set to enable ints! */
+ /* Must set to enable ints! */
+ mos7840_port->shadowMCR = MCR_MASTER_IE;
/* send a open port command */
mos7840_port->open = 1;
- //mos7840_change_port_settings(mos7840_port,old_termios);
+ /* mos7840_change_port_settings(mos7840_port,old_termios); */
mos7840_port->icount.tx = 0;
mos7840_port->icount.rx = 0;
- dbg("\n\nusb_serial serial:%p mos7840_port:%p\n usb_serial_port port:%p\n\n", serial, mos7840_port, port);
+ dbg("\n\nusb_serial serial:%p mos7840_port:%p\n usb_serial_port port:%p\n\n",
+ serial, mos7840_port, port);
return 0;
@@ -1104,11 +1088,12 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
* been written, but hasn't made it out the port yet)
* If successful, we return the number of bytes left to be written in the
* system,
- * Otherwise we return a negative error number.
+ * Otherwise we return zero.
*****************************************************************************/
-static int mos7840_chars_in_buffer(struct usb_serial_port *port)
+static int mos7840_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int i;
int chars = 0;
unsigned long flags;
@@ -1118,22 +1103,20 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port)
if (mos7840_port_paranoia_check(port, __func__)) {
dbg("%s", "Invalid port \n");
- return -1;
+ return 0;
}
mos7840_port = mos7840_get_port_private(port);
if (mos7840_port == NULL) {
dbg("%s \n", "mos7840_break:leaving ...........");
- return -1;
+ return 0;
}
- spin_lock_irqsave(&mos7840_port->pool_lock,flags);
- for (i = 0; i < NUM_URBS; ++i) {
- if (mos7840_port->busy[i]) {
+ spin_lock_irqsave(&mos7840_port->pool_lock, flags);
+ for (i = 0; i < NUM_URBS; ++i)
+ if (mos7840_port->busy[i])
chars += URB_TRANSFER_BUFFER_SIZE;
- }
- }
- spin_unlock_irqrestore(&mos7840_port->pool_lock,flags);
+ spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
dbg("%s - returns %d", __func__, chars);
return chars;
@@ -1149,7 +1132,8 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port)
* 3. A timeout of 3 seconds without activity has expired
*
************************************************************************/
-static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
+static void mos7840_block_until_tx_empty(struct tty_struct *tty,
+ struct moschip_port *mos7840_port)
{
int timeout = HZ / 10;
int wait = 30;
@@ -1157,12 +1141,11 @@ static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
while (1) {
- count = mos7840_chars_in_buffer(mos7840_port->port);
+ count = mos7840_chars_in_buffer(tty);
/* Check for Buffer status */
- if (count <= 0) {
+ if (count <= 0)
return;
- }
/* Block the thread for a while */
interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
@@ -1185,7 +1168,8 @@ static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
* this function is called by the tty driver when a port is closed
*****************************************************************************/
-static void mos7840_close(struct usb_serial_port *port, struct file *filp)
+static void mos7840_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial;
struct moschip_port *mos7840_port;
@@ -1226,32 +1210,28 @@ static void mos7840_close(struct usb_serial_port *port, struct file *filp)
}
}
- if (serial->dev) {
+ if (serial->dev)
/* flush and block until tx is empty */
- mos7840_block_until_tx_empty(mos7840_port);
- }
+ mos7840_block_until_tx_empty(tty, mos7840_port);
/* While closing port, shutdown all bulk read, write *
* and interrupt read if they exists */
if (serial->dev) {
-
if (mos7840_port->write_urb) {
dbg("%s", "Shutdown bulk write\n");
usb_kill_urb(mos7840_port->write_urb);
}
-
if (mos7840_port->read_urb) {
dbg("%s", "Shutdown bulk read\n");
usb_kill_urb(mos7840_port->read_urb);
}
if ((&mos7840_port->control_urb)) {
dbg("%s", "Shutdown control read\n");
- // usb_kill_urb (mos7840_port->control_urb);
-
+ /*/ usb_kill_urb (mos7840_port->control_urb); */
}
}
-// if(mos7840_port->ctrl_buf != NULL)
-// kfree(mos7840_port->ctrl_buf);
+/* if(mos7840_port->ctrl_buf != NULL) */
+/* kfree(mos7840_port->ctrl_buf); */
port0->open_ports--;
dbg("mos7840_num_open_ports in close%d:in port%d\n",
port0->open_ports, port->number);
@@ -1264,10 +1244,8 @@ static void mos7840_close(struct usb_serial_port *port, struct file *filp)
if (mos7840_port->write_urb) {
/* if this urb had a transfer buffer already (old tx) free it */
-
- if (mos7840_port->write_urb->transfer_buffer != NULL) {
+ if (mos7840_port->write_urb->transfer_buffer != NULL)
kfree(mos7840_port->write_urb->transfer_buffer);
- }
usb_free_urb(mos7840_port->write_urb);
}
@@ -1293,20 +1271,19 @@ static void mos7840_close(struct usb_serial_port *port, struct file *filp)
*
************************************************************************/
-static void mos7840_block_until_chase_response(struct moschip_port
- *mos7840_port)
+static void mos7840_block_until_chase_response(struct tty_struct *tty,
+ struct moschip_port *mos7840_port)
{
int timeout = 1 * HZ;
int wait = 10;
int count;
while (1) {
- count = mos7840_chars_in_buffer(mos7840_port->port);
+ count = mos7840_chars_in_buffer(tty);
/* Check for Buffer status */
- if (count <= 0) {
+ if (count <= 0)
return;
- }
/* Block the thread for a while */
interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
@@ -1328,8 +1305,9 @@ static void mos7840_block_until_chase_response(struct moschip_port
* mos7840_break
* this function sends a break to the port
*****************************************************************************/
-static void mos7840_break(struct usb_serial_port *port, int break_state)
+static void mos7840_break(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned char data;
struct usb_serial *serial;
struct moschip_port *mos7840_port;
@@ -1350,21 +1328,17 @@ static void mos7840_break(struct usb_serial_port *port, int break_state)
mos7840_port = mos7840_get_port_private(port);
- if (mos7840_port == NULL) {
+ if (mos7840_port == NULL)
return;
- }
-
- if (serial->dev) {
+ if (serial->dev)
/* flush and block until tx is empty */
- mos7840_block_until_chase_response(mos7840_port);
- }
+ mos7840_block_until_chase_response(tty, mos7840_port);
- if (break_state == -1) {
+ if (break_state == -1)
data = mos7840_port->shadowLCR | LCR_SET_BREAK;
- } else {
+ else
data = mos7840_port->shadowLCR & ~LCR_SET_BREAK;
- }
mos7840_port->shadowLCR = data;
dbg("mcs7840_break mos7840_port->shadowLCR is %x\n",
@@ -1383,8 +1357,9 @@ static void mos7840_break(struct usb_serial_port *port, int break_state)
* Otherwise we return a negative error number.
*****************************************************************************/
-static int mos7840_write_room(struct usb_serial_port *port)
+static int mos7840_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int i;
int room = 0;
unsigned long flags;
@@ -1406,9 +1381,8 @@ static int mos7840_write_room(struct usb_serial_port *port)
spin_lock_irqsave(&mos7840_port->pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
- if (!mos7840_port->busy[i]) {
+ if (!mos7840_port->busy[i])
room += URB_TRANSFER_BUFFER_SIZE;
- }
}
spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
@@ -1426,7 +1400,7 @@ static int mos7840_write_room(struct usb_serial_port *port)
* return a negative error number.
*****************************************************************************/
-static int mos7840_write(struct usb_serial_port *port,
+static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *data, int count)
{
int status;
@@ -1438,45 +1412,41 @@ static int mos7840_write(struct usb_serial_port *port,
struct moschip_port *mos7840_port;
struct usb_serial *serial;
struct urb *urb;
- //__u16 Data;
+ /* __u16 Data; */
const unsigned char *current_position = data;
unsigned char *data1;
dbg("%s \n", "entering ...........");
- //dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",mos7840_port->shadowLCR);
+ /* dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",
+ mos7840_port->shadowLCR); */
#ifdef NOTMOS7840
Data = 0x00;
- status = 0;
status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
mos7840_port->shadowLCR = Data;
dbg("mos7840_write: LINE_CONTROL_REGISTER is %x\n", Data);
dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",
mos7840_port->shadowLCR);
- //Data = 0x03;
- //status = mos7840_set_uart_reg(port,LINE_CONTROL_REGISTER,Data);
- //mos7840_port->shadowLCR=Data;//Need to add later
+ /* Data = 0x03; */
+ /* status = mos7840_set_uart_reg(port,LINE_CONTROL_REGISTER,Data); */
+ /* mos7840_port->shadowLCR=Data;//Need to add later */
- Data |= SERIAL_LCR_DLAB; //data latch enable in LCR 0x80
- status = 0;
+ Data |= SERIAL_LCR_DLAB; /* data latch enable in LCR 0x80 */
status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
- //Data = 0x0c;
- //status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,Data);
+ /* Data = 0x0c; */
+ /* status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,Data); */
Data = 0x00;
- status = 0;
status = mos7840_get_uart_reg(port, DIVISOR_LATCH_LSB, &Data);
dbg("mos7840_write:DLL value is %x\n", Data);
Data = 0x0;
- status = 0;
status = mos7840_get_uart_reg(port, DIVISOR_LATCH_MSB, &Data);
dbg("mos7840_write:DLM value is %x\n", Data);
Data = Data & ~SERIAL_LCR_DLAB;
dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",
mos7840_port->shadowLCR);
- status = 0;
status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
#endif
@@ -1555,8 +1525,7 @@ static int mos7840_write(struct usb_serial_port *port,
mos7840_port->icount.tx += transfer_size;
smp_wmb();
dbg("mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx);
- exit:
-
+exit:
return bytes_sent;
}
@@ -1567,10 +1536,10 @@ static int mos7840_write(struct usb_serial_port *port,
* being read from the port.
*****************************************************************************/
-static void mos7840_throttle(struct usb_serial_port *port)
+static void mos7840_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7840_port;
- struct tty_struct *tty;
int status;
if (mos7840_port_paranoia_check(port, __func__)) {
@@ -1592,32 +1561,20 @@ static void mos7840_throttle(struct usb_serial_port *port)
dbg("%s", "Entering .......... \n");
- tty = port->tty;
- if (!tty) {
- dbg("%s - no tty available", __func__);
- return;
- }
-
/* if we are implementing XON/XOFF, send the stop character */
if (I_IXOFF(tty)) {
unsigned char stop_char = STOP_CHAR(tty);
- status = mos7840_write(port, &stop_char, 1);
- if (status <= 0) {
+ status = mos7840_write(tty, port, &stop_char, 1);
+ if (status <= 0)
return;
- }
}
-
/* if we are implementing RTS/CTS, toggle that line */
if (tty->termios->c_cflag & CRTSCTS) {
mos7840_port->shadowMCR &= ~MCR_RTS;
- status = 0;
- status =
- mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
+ status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
mos7840_port->shadowMCR);
-
- if (status < 0) {
+ if (status < 0)
return;
- }
}
return;
@@ -1625,12 +1582,13 @@ static void mos7840_throttle(struct usb_serial_port *port)
/*****************************************************************************
* mos7840_unthrottle
- * this function is called by the tty driver when it wants to resume the data
- * being read from the port (called after SerialThrottle is called)
+ * this function is called by the tty driver when it wants to resume
+ * the data being read from the port (called after mos7840_throttle is
+ * called)
*****************************************************************************/
-static void mos7840_unthrottle(struct usb_serial_port *port)
+static void mos7840_unthrottle(struct tty_struct *tty)
{
- struct tty_struct *tty;
+ struct usb_serial_port *port = tty->driver_data;
int status;
struct moschip_port *mos7840_port = mos7840_get_port_private(port);
@@ -1649,43 +1607,32 @@ static void mos7840_unthrottle(struct usb_serial_port *port)
dbg("%s", "Entering .......... \n");
- tty = port->tty;
- if (!tty) {
- dbg("%s - no tty available", __func__);
- return;
- }
-
/* if we are implementing XON/XOFF, send the start character */
if (I_IXOFF(tty)) {
unsigned char start_char = START_CHAR(tty);
- status = mos7840_write(port, &start_char, 1);
- if (status <= 0) {
+ status = mos7840_write(tty, port, &start_char, 1);
+ if (status <= 0)
return;
- }
}
/* if we are implementing RTS/CTS, toggle that line */
if (tty->termios->c_cflag & CRTSCTS) {
mos7840_port->shadowMCR |= MCR_RTS;
- status = 0;
- status =
- mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
+ status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
mos7840_port->shadowMCR);
- if (status < 0) {
+ if (status < 0)
return;
- }
}
-
- return;
}
-static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file)
+static int mos7840_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7840_port;
unsigned int result;
__u16 msr;
__u16 mcr;
- int status = 0;
+ int status;
mos7840_port = mos7840_get_port_private(port);
dbg("%s - port %d", __func__, port->number);
@@ -1708,9 +1655,10 @@ static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file)
return result;
}
-static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file,
+static int mos7840_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7840_port;
unsigned int mcr;
int status;
@@ -1755,7 +1703,7 @@ static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file,
* baud rate.
*****************************************************************************/
static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor,
- __u16 * clk_sel_val)
+ __u16 *clk_sel_val)
{
dbg("%s - %d", __func__, baudRate);
@@ -1807,9 +1755,8 @@ static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor,
/* Check for round off */
round1 = (__u16) (2304000L / baudrate);
round = (__u16) (round1 - (custom * 10));
- if (round > 4) {
+ if (round > 4)
custom++;
- }
*divisor = custom;
dbg(" Baud %d = %d\n", baudrate, custom);
@@ -1857,16 +1804,15 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
dbg("%s - port = %d, baud = %d", __func__,
mos7840_port->port->number, baudRate);
- //reset clk_uart_sel in spregOffset
+ /* reset clk_uart_sel in spregOffset */
if (baudRate > 115200) {
#ifdef HW_flow_control
- //NOTE: need to see the pther register to modify
- //setting h/w flow control bit to 1;
- status = 0;
+ /* NOTE: need to see the pther register to modify */
+ /* setting h/w flow control bit to 1 */
Data = 0x2b;
mos7840_port->shadowMCR = Data;
- status =
- mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+ status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
+ Data);
if (status < 0) {
dbg("Writing spreg failed in set_serial_baud\n");
return -1;
@@ -1875,12 +1821,11 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
} else {
#ifdef HW_flow_control
- //setting h/w flow control bit to 0;
- status = 0;
+ / *setting h/w flow control bit to 0 */
Data = 0xb;
mos7840_port->shadowMCR = Data;
- status =
- mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+ status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
+ Data);
if (status < 0) {
dbg("Writing spreg failed in set_serial_baud\n");
return -1;
@@ -1889,25 +1834,20 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
}
- if (1) //baudRate <= 115200)
- {
+ if (1) { /* baudRate <= 115200) */
clk_sel_val = 0x0;
Data = 0x0;
- status = 0;
- status =
- mos7840_calc_baud_rate_divisor(baudRate, &divisor,
+ status = mos7840_calc_baud_rate_divisor(baudRate, &divisor,
&clk_sel_val);
- status =
- mos7840_get_reg_sync(port, mos7840_port->SpRegOffset,
- &Data);
+ status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset,
+ &Data);
if (status < 0) {
dbg("reading spreg failed in set_serial_baud\n");
return -1;
}
Data = (Data & 0x8f) | clk_sel_val;
- status = 0;
- status =
- mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+ status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset,
+ Data);
if (status < 0) {
dbg("Writing spreg failed in set_serial_baud\n");
return -1;
@@ -1939,7 +1879,6 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
}
-
return status;
}
@@ -1949,10 +1888,9 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
* the specified new settings.
*****************************************************************************/
-static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
- struct ktermios *old_termios)
+static void mos7840_change_port_settings(struct tty_struct *tty,
+ struct moschip_port *mos7840_port, struct ktermios *old_termios)
{
- struct tty_struct *tty;
int baud;
unsigned cflag;
unsigned iflag;
@@ -1988,8 +1926,6 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
return;
}
- tty = mos7840_port->port->tty;
-
dbg("%s", "Entering .......... \n");
lData = LCR_BITS_8;
@@ -2033,9 +1969,8 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
dbg("%s - parity = none", __func__);
}
- if (cflag & CMSPAR) {
+ if (cflag & CMSPAR)
lParity = lParity | 0x20;
- }
/* Change the Stop bit */
if (cflag & CSTOPB) {
@@ -2077,16 +2012,13 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
/* set up the MCR register and send it to the mos7840 */
mos7840_port->shadowMCR = MCR_MASTER_IE;
- if (cflag & CBAUD) {
+ if (cflag & CBAUD)
mos7840_port->shadowMCR |= (MCR_DTR | MCR_RTS);
- }
- if (cflag & CRTSCTS) {
+ if (cflag & CRTSCTS)
mos7840_port->shadowMCR |= (MCR_XON_ANY);
-
- } else {
+ else
mos7840_port->shadowMCR &= ~(MCR_XON_ANY);
- }
Data = mos7840_port->shadowMCR;
mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
@@ -2131,14 +2063,14 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
* the termios structure
*****************************************************************************/
-static void mos7840_set_termios(struct usb_serial_port *port,
+static void mos7840_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port,
struct ktermios *old_termios)
{
int status;
unsigned int cflag;
struct usb_serial *serial;
struct moschip_port *mos7840_port;
- struct tty_struct *tty;
dbg("mos7840_set_termios: START\n");
if (mos7840_port_paranoia_check(port, __func__)) {
dbg("%s", "Invalid port \n");
@@ -2157,8 +2089,6 @@ static void mos7840_set_termios(struct usb_serial_port *port,
if (mos7840_port == NULL)
return;
- tty = port->tty;
-
if (!mos7840_port->open) {
dbg("%s - port not opened", __func__);
return;
@@ -2176,7 +2106,7 @@ static void mos7840_set_termios(struct usb_serial_port *port,
/* change the port settings to the new ones specified */
- mos7840_change_port_settings(mos7840_port, old_termios);
+ mos7840_change_port_settings(tty, mos7840_port, old_termios);
if (!mos7840_port->read_urb) {
dbg("%s", "URB KILLED !!!!!\n");
@@ -2205,13 +2135,13 @@ static void mos7840_set_termios(struct usb_serial_port *port,
* allows an RS485 driver to be written in user space.
*****************************************************************************/
-static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,
+static int mos7840_get_lsr_info(struct tty_struct *tty,
unsigned int __user *value)
{
int count;
unsigned int result = 0;
- count = mos7840_chars_in_buffer(mos7840_port->port);
+ count = mos7840_chars_in_buffer(tty);
if (count == 0) {
dbg("%s -- Empty", __func__);
result = TIOCSER_TEMT;
@@ -2227,6 +2157,8 @@ static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,
* function to set modem info
*****************************************************************************/
+/* FIXME: Should be using the model control hooks */
+
static int mos7840_set_modem_info(struct moschip_port *mos7840_port,
unsigned int cmd, unsigned int __user *value)
{
@@ -2282,7 +2214,6 @@ static int mos7840_set_modem_info(struct moschip_port *mos7840_port,
mos7840_port->shadowMCR = mcr;
Data = mos7840_port->shadowMCR;
- status = 0;
status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
if (status < 0) {
dbg("setting MODEM_CONTROL_REGISTER Failed\n");
@@ -2303,10 +2234,8 @@ static int mos7840_get_modem_info(struct moschip_port *mos7840_port,
unsigned int result = 0;
__u16 msr;
unsigned int mcr = mos7840_port->shadowMCR;
- int status = 0;
- status =
- mos7840_get_uart_reg(mos7840_port->port, MODEM_STATUS_REGISTER,
- &msr);
+ mos7840_get_uart_reg(mos7840_port->port,
+ MODEM_STATUS_REGISTER, &msr);
result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) /* 0x002 */
|((mcr & MCR_RTS) ? TIOCM_RTS : 0) /* 0x004 */
|((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0) /* 0x020 */
@@ -2359,12 +2288,12 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
* this function handles any ioctl calls to the driver
*****************************************************************************/
-static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
+static int mos7840_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
void __user *argp = (void __user *)arg;
struct moschip_port *mos7840_port;
- struct tty_struct *tty;
struct async_icount cnow;
struct async_icount cprev;
@@ -2381,8 +2310,6 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
if (mos7840_port == NULL)
return -1;
- tty = mos7840_port->port->tty;
-
dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
switch (cmd) {
@@ -2390,9 +2317,10 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
case TIOCSERGETLSR:
dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
- return mos7840_get_lsr_info(mos7840_port, argp);
+ return mos7840_get_lsr_info(tty, argp);
return 0;
+ /* FIXME: use the modem hooks and remove this */
case TIOCMBIS:
case TIOCMBIC:
case TIOCMSET:
@@ -2418,7 +2346,7 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
cprev = mos7840_port->icount;
while (1) {
- //interruptible_sleep_on(&mos7840_port->delta_msr_wait);
+ /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */
mos7840_port->delta_msr_cond = 0;
wait_event_interruptible(mos7840_port->delta_msr_wait,
(mos7840_port->
@@ -2463,13 +2391,9 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
if (copy_to_user(argp, &icount, sizeof(icount)))
return -EFAULT;
return 0;
-
- case TIOCEXBAUD:
- return 0;
default:
break;
}
-
return -ENOIOCTLCMD;
}
@@ -2527,8 +2451,9 @@ static int mos7840_startup(struct usb_serial *serial)
goto error;
}
- /* Initialize all port interrupt end point to port 0 int endpoint *
- * Our device has only one interrupt end point comman to all port */
+ /* Initialize all port interrupt end point to port 0 int
+ * endpoint. Our device has only one interrupt end point
+ * common to all port */
mos7840_port->port = serial->port[i];
mos7840_set_port_private(serial->port[i], mos7840_port);
@@ -2564,27 +2489,23 @@ static int mos7840_startup(struct usb_serial *serial)
mos7840_port->DcrRegOffset = 0x1c;
}
mos7840_dump_serial_port(mos7840_port);
-
mos7840_set_port_private(serial->port[i], mos7840_port);
- //enable rx_disable bit in control register
-
- status =
- mos7840_get_reg_sync(serial->port[i],
- mos7840_port->ControlRegOffset, &Data);
+ /* enable rx_disable bit in control register */
+ status = mos7840_get_reg_sync(serial->port[i],
+ mos7840_port->ControlRegOffset, &Data);
if (status < 0) {
dbg("Reading ControlReg failed status-0x%x\n", status);
break;
} else
dbg("ControlReg Reading success val is %x, status%d\n",
Data, status);
- Data |= 0x08; //setting driver done bit
- Data |= 0x04; //sp1_bit to have cts change reflect in modem status reg
+ Data |= 0x08; /* setting driver done bit */
+ Data |= 0x04; /* sp1_bit to have cts change reflect in
+ modem status reg */
- //Data |= 0x20; //rx_disable bit
- status = 0;
- status =
- mos7840_set_reg_sync(serial->port[i],
+ /* Data |= 0x20; //rx_disable bit */
+ status = mos7840_set_reg_sync(serial->port[i],
mos7840_port->ControlRegOffset, Data);
if (status < 0) {
dbg("Writing ControlReg failed(rx_disable) status-0x%x\n", status);
@@ -2593,13 +2514,11 @@ static int mos7840_startup(struct usb_serial *serial)
dbg("ControlReg Writing success(rx_disable) status%d\n",
status);
- //Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 and 0x24 in DCR3
+ /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2
+ and 0x24 in DCR3 */
Data = 0x01;
- status = 0;
- status =
- mos7840_set_reg_sync(serial->port[i],
- (__u16) (mos7840_port->DcrRegOffset +
- 0), Data);
+ status = mos7840_set_reg_sync(serial->port[i],
+ (__u16) (mos7840_port->DcrRegOffset + 0), Data);
if (status < 0) {
dbg("Writing DCR0 failed status-0x%x\n", status);
break;
@@ -2607,11 +2526,8 @@ static int mos7840_startup(struct usb_serial *serial)
dbg("DCR0 Writing success status%d\n", status);
Data = 0x05;
- status = 0;
- status =
- mos7840_set_reg_sync(serial->port[i],
- (__u16) (mos7840_port->DcrRegOffset +
- 1), Data);
+ status = mos7840_set_reg_sync(serial->port[i],
+ (__u16) (mos7840_port->DcrRegOffset + 1), Data);
if (status < 0) {
dbg("Writing DCR1 failed status-0x%x\n", status);
break;
@@ -2619,22 +2535,17 @@ static int mos7840_startup(struct usb_serial *serial)
dbg("DCR1 Writing success status%d\n", status);
Data = 0x24;
- status = 0;
- status =
- mos7840_set_reg_sync(serial->port[i],
- (__u16) (mos7840_port->DcrRegOffset +
- 2), Data);
+ status = mos7840_set_reg_sync(serial->port[i],
+ (__u16) (mos7840_port->DcrRegOffset + 2), Data);
if (status < 0) {
dbg("Writing DCR2 failed status-0x%x\n", status);
break;
} else
dbg("DCR2 Writing success status%d\n", status);
- // write values in clkstart0x0 and clkmulti 0x20
+ /* write values in clkstart0x0 and clkmulti 0x20 */
Data = 0x0;
- status = 0;
- status =
- mos7840_set_reg_sync(serial->port[i],
+ status = mos7840_set_reg_sync(serial->port[i],
CLK_START_VALUE_REGISTER, Data);
if (status < 0) {
dbg("Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
@@ -2643,9 +2554,8 @@ static int mos7840_startup(struct usb_serial *serial)
dbg("CLK_START_VALUE_REGISTER Writing success status%d\n", status);
Data = 0x20;
- status =
- mos7840_set_reg_sync(serial->port[i], CLK_MULTI_REGISTER,
- Data);
+ status = mos7840_set_reg_sync(serial->port[i],
+ CLK_MULTI_REGISTER, Data);
if (status < 0) {
dbg("Writing CLK_MULTI_REGISTER failed status-0x%x\n",
status);
@@ -2654,11 +2564,10 @@ static int mos7840_startup(struct usb_serial *serial)
dbg("CLK_MULTI_REGISTER Writing success status%d\n",
status);
- //write value 0x0 to scratchpad register
+ /* write value 0x0 to scratchpad register */
Data = 0x00;
- status =
- mos7840_set_uart_reg(serial->port[i], SCRATCH_PAD_REGISTER,
- Data);
+ status = mos7840_set_uart_reg(serial->port[i],
+ SCRATCH_PAD_REGISTER, Data);
if (status < 0) {
dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x\n",
status);
@@ -2667,21 +2576,17 @@ static int mos7840_startup(struct usb_serial *serial)
dbg("SCRATCH_PAD_REGISTER Writing success status%d\n",
status);
- //Zero Length flag register
+ /* Zero Length flag register */
if ((mos7840_port->port_num != 1)
&& (serial->num_ports == 2)) {
Data = 0xff;
- status = 0;
status = mos7840_set_reg_sync(serial->port[i],
- (__u16) (ZLP_REG1 +
- ((__u16)
- mos7840_port->
- port_num)),
- Data);
+ (__u16) (ZLP_REG1 +
+ ((__u16)mos7840_port->port_num)), Data);
dbg("ZLIP offset%x\n",
(__u16) (ZLP_REG1 +
- ((__u16) mos7840_port->port_num)));
+ ((__u16) mos7840_port->port_num)));
if (status < 0) {
dbg("Writing ZLP_REG%d failed status-0x%x\n",
i + 2, status);
@@ -2691,13 +2596,9 @@ static int mos7840_startup(struct usb_serial *serial)
i + 2, status);
} else {
Data = 0xff;
- status = 0;
status = mos7840_set_reg_sync(serial->port[i],
- (__u16) (ZLP_REG1 +
- ((__u16)
- mos7840_port->
- port_num) -
- 0x1), Data);
+ (__u16) (ZLP_REG1 +
+ ((__u16)mos7840_port->port_num) - 0x1), Data);
dbg("ZLIP offset%x\n",
(__u16) (ZLP_REG1 +
((__u16) mos7840_port->port_num) - 0x1));
@@ -2712,14 +2613,16 @@ static int mos7840_startup(struct usb_serial *serial)
}
mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
- mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
- if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || !mos7840_port->dr) {
+ mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest),
+ GFP_KERNEL);
+ if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf ||
+ !mos7840_port->dr) {
status = -ENOMEM;
goto error;
}
}
- //Zero Length flag enable
+ /* Zero Length flag enable */
Data = 0x0f;
status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
if (status < 0) {
@@ -2762,7 +2665,7 @@ static void mos7840_shutdown(struct usb_serial *serial)
return;
}
- /* check for the ports to be closed,close the ports and disconnect */
+ /* check for the ports to be closed,close the ports and disconnect */
/* free private structure allocated for serial port *
* stop reads and writes on all ports */
@@ -2843,20 +2746,12 @@ static int __init moschip7840_init(void)
/* Register with the usb */
retval = usb_register(&io_driver);
-
- if (retval)
- goto failed_usb_register;
-
if (retval == 0) {
dbg("%s\n", "Leaving...");
return 0;
}
-
- failed_usb_register:
usb_serial_deregister(&moschip7840_4port_device);
-
- failed_port_device_register:
-
+failed_port_device_register:
return retval;
}
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index 43c8894353b..d6736531a0f 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -64,7 +64,7 @@ static void navman_read_int_callback(struct urb *urb)
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, data);
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
@@ -79,7 +79,8 @@ exit:
__func__, result);
}
-static int navman_open(struct usb_serial_port *port, struct file *filp)
+static int navman_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
int result = 0;
@@ -96,14 +97,15 @@ static int navman_open(struct usb_serial_port *port, struct file *filp)
return result;
}
-static void navman_close(struct usb_serial_port *port, struct file *filp)
+static void navman_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
dbg("%s - port %d", __func__, port->number);
usb_kill_urb(port->interrupt_in_urb);
}
-static int navman_write(struct usb_serial_port *port,
+static int navman_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
dbg("%s - port %d", __func__, port->number);
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 7b7422f4947..ae8e227f3db 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -5,26 +5,28 @@
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
* Please report both successes and troubles to the author at omninet@kroah.com
- *
+ *
* (05/30/2001) gkh
- * switched from using spinlock to a semaphore, which fixes lots of problems.
+ * switched from using spinlock to a semaphore, which fixes lots of
+ * problems.
*
* (04/08/2001) gb
* Identify version on module load.
*
* (11/01/2000) Adam J. Richter
* usb_device_id table support
- *
+ *
* (10/05/2000) gkh
* Fixed bug with urb->dev not being set properly, now that the usb
* core needs it.
- *
+ *
* (08/28/2000) gkh
* Added locks for SMP safeness.
- * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
+ * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
* than once.
* Fixed potential race in omninet_write_bulk_callback
*
@@ -43,7 +45,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -58,25 +60,29 @@ static int debug;
#define ZYXEL_VENDOR_ID 0x0586
#define ZYXEL_OMNINET_ID 0x1000
-#define BT_IGNITIONPRO_ID 0x2000 /* This one seems to be a re-branded ZyXEL device */
+/* This one seems to be a re-branded ZyXEL device */
+#define BT_IGNITIONPRO_ID 0x2000
/* function prototypes */
-static int omninet_open (struct usb_serial_port *port, struct file *filp);
-static void omninet_close (struct usb_serial_port *port, struct file *filp);
-static void omninet_read_bulk_callback (struct urb *urb);
-static void omninet_write_bulk_callback (struct urb *urb);
-static int omninet_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-static int omninet_write_room (struct usb_serial_port *port);
-static void omninet_shutdown (struct usb_serial *serial);
-static int omninet_attach (struct usb_serial *serial);
-
-static struct usb_device_id id_table [] = {
+static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static void omninet_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static void omninet_read_bulk_callback(struct urb *urb);
+static void omninet_write_bulk_callback(struct urb *urb);
+static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+static int omninet_write_room(struct tty_struct *tty);
+static void omninet_shutdown(struct usb_serial *serial);
+static int omninet_attach(struct usb_serial *serial);
+
+static struct usb_device_id id_table[] = {
{ USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
{ USB_DEVICE(ZYXEL_VENDOR_ID, BT_IGNITIONPRO_ID) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver omninet_driver = {
.name = "omninet",
@@ -130,34 +136,34 @@ static struct usb_serial_driver zyxel_omninet_device = {
*
*/
-struct omninet_header
-{
+struct omninet_header {
__u8 oh_seq;
__u8 oh_len;
__u8 oh_xxx;
__u8 oh_pad;
};
-struct omninet_data
-{
- __u8 od_outseq; // Sequence number for bulk_out URBs
+struct omninet_data {
+ __u8 od_outseq; /* Sequence number for bulk_out URBs */
};
-static int omninet_attach (struct usb_serial *serial)
+static int omninet_attach(struct usb_serial *serial)
{
struct omninet_data *od;
struct usb_serial_port *port = serial->port[0];
- od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
- if( !od ) {
- err("%s- kmalloc(%Zd) failed.", __func__, sizeof(struct omninet_data));
+ od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL);
+ if (!od) {
+ err("%s- kmalloc(%Zd) failed.",
+ __func__, sizeof(struct omninet_data));
return -ENOMEM;
}
usb_set_serial_port_data(port, od);
return 0;
}
-static int omninet_open (struct usb_serial_port *port, struct file *filp)
+static int omninet_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
struct usb_serial_port *wport;
@@ -166,22 +172,24 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __func__, port->number);
wport = serial->port[1];
- wport->tty = port->tty;
+ wport->port.tty = tty; /* FIXME */
/* Start reading from the device */
- usb_fill_bulk_urb(port->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
- omninet_read_bulk_callback, port);
+ usb_fill_bulk_urb(port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ omninet_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
- if (result) {
- err("%s - failed submitting read urb, error %d", __func__, result);
- }
-
+ if (result)
+ err("%s - failed submitting read urb, error %d",
+ __func__, result);
return result;
}
-static void omninet_close (struct usb_serial_port *port, struct file * filp)
+static void omninet_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
dbg("%s - port %d", __func__, port->number);
usb_kill_urb(port->read_urb);
@@ -192,14 +200,14 @@ static void omninet_close (struct usb_serial_port *port, struct file * filp)
#define OMNINET_HEADERLEN sizeof(struct omninet_header)
#define OMNINET_BULKOUTSIZE (64 - OMNINET_HEADERLEN)
-static void omninet_read_bulk_callback (struct urb *urb)
+static void omninet_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
struct omninet_header *header = (struct omninet_header *) &data[0];
int status = urb->status;
- int i;
int result;
+ int i;
dbg("%s - port %d", __func__, port->number);
@@ -209,42 +217,46 @@ static void omninet_read_bulk_callback (struct urb *urb)
return;
}
- if ((debug) && (header->oh_xxx != 0x30)) {
+ if (debug && header->oh_xxx != 0x30) {
if (urb->actual_length) {
- printk (KERN_DEBUG __FILE__ ": omninet_read %d: ", header->oh_len);
- for (i = 0; i < (header->oh_len + OMNINET_HEADERLEN); i++) {
- printk ("%.2x ", data[i]);
- }
- printk ("\n");
+ printk(KERN_DEBUG __FILE__
+ ": omninet_read %d: ", header->oh_len);
+ for (i = 0; i < (header->oh_len +
+ OMNINET_HEADERLEN); i++)
+ printk("%.2x ", data[i]);
+ printk("\n");
}
}
if (urb->actual_length && header->oh_len) {
- for (i = 0; i < header->oh_len; i++) {
- tty_insert_flip_char(port->tty, data[OMNINET_DATAOFFSET + i], 0);
- }
- tty_flip_buffer_push(port->tty);
+ tty_insert_flip_string(port->port.tty,
+ data + OMNINET_DATAOFFSET, header->oh_len);
+ tty_flip_buffer_push(port->port.tty);
}
/* Continue trying to always read */
- usb_fill_bulk_urb(urb, port->serial->dev,
- usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress),
- urb->transfer_buffer, urb->transfer_buffer_length,
- omninet_read_bulk_callback, port);
+ usb_fill_bulk_urb(urb, port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
+ port->bulk_in_endpointAddress),
+ urb->transfer_buffer, urb->transfer_buffer_length,
+ omninet_read_bulk_callback, port);
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d", __func__, result);
+ err("%s - failed resubmitting read urb, error %d",
+ __func__, result);
return;
}
-static int omninet_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
- struct usb_serial *serial = port->serial;
- struct usb_serial_port *wport = serial->port[1];
+ struct usb_serial *serial = port->serial;
+ struct usb_serial_port *wport = serial->port[1];
- struct omninet_data *od = usb_get_serial_port_data(port);
- struct omninet_header *header = (struct omninet_header *) wport->write_urb->transfer_buffer;
+ struct omninet_data *od = usb_get_serial_port_data(port);
+ struct omninet_header *header = (struct omninet_header *)
+ wport->write_urb->transfer_buffer;
int result;
@@ -252,7 +264,7 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
if (count == 0) {
dbg("%s - write request of 0 bytes", __func__);
- return (0);
+ return 0;
}
spin_lock_bh(&wport->lock);
@@ -266,9 +278,11 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count;
- memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count);
+ memcpy(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET,
+ buf, count);
- usb_serial_debug_data(debug, &port->dev, __func__, count, wport->write_urb->transfer_buffer);
+ usb_serial_debug_data(debug, &port->dev, __func__, count,
+ wport->write_urb->transfer_buffer);
header->oh_seq = od->od_outseq++;
header->oh_len = count;
@@ -282,7 +296,8 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
if (result) {
wport->write_urb_busy = 0;
- err("%s - failed submitting write urb, error %d", __func__, result);
+ err("%s - failed submitting write urb, error %d",
+ __func__, result);
} else
result = count;
@@ -290,8 +305,9 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
}
-static int omninet_write_room (struct usb_serial_port *port)
+static int omninet_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
struct usb_serial_port *wport = serial->port[1];
@@ -303,12 +319,13 @@ static int omninet_write_room (struct usb_serial_port *port)
dbg("%s - returns %d", __func__, room);
- return (room);
+ return room;
}
-static void omninet_write_bulk_callback (struct urb *urb)
+static void omninet_write_bulk_callback(struct urb *urb)
{
-/* struct omninet_header *header = (struct omninet_header *) urb->transfer_buffer; */
+/* struct omninet_header *header = (struct omninet_header *)
+ urb->transfer_buffer; */
struct usb_serial_port *port = urb->context;
int status = urb->status;
@@ -325,18 +342,18 @@ static void omninet_write_bulk_callback (struct urb *urb)
}
-static void omninet_shutdown (struct usb_serial *serial)
+static void omninet_shutdown(struct usb_serial *serial)
{
struct usb_serial_port *wport = serial->port[1];
struct usb_serial_port *port = serial->port[0];
- dbg ("%s", __func__);
+ dbg("%s", __func__);
usb_kill_urb(wport->write_urb);
kfree(usb_get_serial_port_data(port));
}
-static int __init omninet_init (void)
+static int __init omninet_init(void)
{
int retval;
retval = usb_serial_register(&zyxel_omninet_device);
@@ -354,18 +371,18 @@ failed_usb_serial_register:
}
-static void __exit omninet_exit (void)
+static void __exit omninet_exit(void)
{
- usb_deregister (&omninet_driver);
- usb_serial_deregister (&zyxel_omninet_device);
+ usb_deregister(&omninet_driver);
+ usb_serial_deregister(&zyxel_omninet_device);
}
module_init(omninet_init);
module_exit(omninet_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 1e936a1cbe0..e4eca95f2b0 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -43,29 +43,25 @@
#include <linux/usb/serial.h>
/* Function prototypes */
-static int option_open(struct usb_serial_port *port, struct file *filp);
-static void option_close(struct usb_serial_port *port, struct file *filp);
+static int option_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static void option_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
static int option_startup(struct usb_serial *serial);
static void option_shutdown(struct usb_serial *serial);
-static void option_rx_throttle(struct usb_serial_port *port);
-static void option_rx_unthrottle(struct usb_serial_port *port);
-static int option_write_room(struct usb_serial_port *port);
+static int option_write_room(struct tty_struct *tty);
static void option_instat_callback(struct urb *urb);
-static int option_write(struct usb_serial_port *port,
+static int option_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
-
-static int option_chars_in_buffer(struct usb_serial_port *port);
-static int option_ioctl(struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg);
-static void option_set_termios(struct usb_serial_port *port,
- struct ktermios *old);
-static void option_break_ctl(struct usb_serial_port *port, int break_state);
-static int option_tiocmget(struct usb_serial_port *port, struct file *file);
-static int option_tiocmset(struct usb_serial_port *port, struct file *file,
+static int option_chars_in_buffer(struct tty_struct *tty);
+static void option_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
+static int option_tiocmget(struct tty_struct *tty, struct file *file);
+static int option_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
-static int option_send_setup(struct usb_serial_port *port);
+static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *port);
/* Vendor and product IDs */
#define OPTION_VENDOR_ID 0x0AF0
@@ -342,11 +338,7 @@ static struct usb_serial_driver option_1port_device = {
.write = option_write,
.write_room = option_write_room,
.chars_in_buffer = option_chars_in_buffer,
- .throttle = option_rx_throttle,
- .unthrottle = option_rx_unthrottle,
- .ioctl = option_ioctl,
.set_termios = option_set_termios,
- .break_ctl = option_break_ctl,
.tiocmget = option_tiocmget,
.tiocmset = option_tiocmset,
.attach = option_startup,
@@ -403,47 +395,32 @@ static int __init option_init(void)
return 0;
failed_driver_register:
- usb_serial_deregister (&option_1port_device);
+ usb_serial_deregister(&option_1port_device);
failed_1port_device_register:
return retval;
}
static void __exit option_exit(void)
{
- usb_deregister (&option_driver);
- usb_serial_deregister (&option_1port_device);
+ usb_deregister(&option_driver);
+ usb_serial_deregister(&option_1port_device);
}
module_init(option_init);
module_exit(option_exit);
-static void option_rx_throttle(struct usb_serial_port *port)
-{
- dbg("%s", __func__);
-}
-
-static void option_rx_unthrottle(struct usb_serial_port *port)
-{
- dbg("%s", __func__);
-}
-
-static void option_break_ctl(struct usb_serial_port *port, int break_state)
-{
- /* Unfortunately, I don't know how to send a break */
- dbg("%s", __func__);
-}
-
-static void option_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void option_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
dbg("%s", __func__);
/* Doesn't support option setting */
- tty_termios_copy_hw(port->tty->termios, old_termios);
- option_send_setup(port);
+ tty_termios_copy_hw(tty->termios, old_termios);
+ option_send_setup(tty, port);
}
-static int option_tiocmget(struct usb_serial_port *port, struct file *file)
+static int option_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned int value;
struct option_port_private *portdata;
@@ -459,9 +436,10 @@ static int option_tiocmget(struct usb_serial_port *port, struct file *file)
return value;
}
-static int option_tiocmset(struct usb_serial_port *port, struct file *file,
+static int option_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct option_port_private *portdata;
portdata = usb_get_serial_port_data(port);
@@ -476,17 +454,11 @@ static int option_tiocmset(struct usb_serial_port *port, struct file *file,
portdata->rts_state = 0;
if (clear & TIOCM_DTR)
portdata->dtr_state = 0;
- return option_send_setup(port);
-}
-
-static int option_ioctl(struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return -ENOIOCTLCMD;
+ return option_send_setup(tty, port);
}
/* Write */
-static int option_write(struct usb_serial_port *port,
+static int option_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
struct option_port_private *portdata;
@@ -501,7 +473,7 @@ static int option_write(struct usb_serial_port *port,
i = 0;
left = count;
- for (i=0; left > 0 && i < N_OUT_URB; i++) {
+ for (i = 0; left > 0 && i < N_OUT_URB; i++) {
todo = left;
if (todo > OUT_BUFLEN)
todo = OUT_BUFLEN;
@@ -522,7 +494,7 @@ static int option_write(struct usb_serial_port *port,
usb_pipeendpoint(this_urb->pipe), i);
/* send the data */
- memcpy (this_urb->transfer_buffer, buf, todo);
+ memcpy(this_urb->transfer_buffer, buf, todo);
this_urb->transfer_buffer_length = todo;
this_urb->dev = port->serial->dev;
@@ -562,7 +534,7 @@ static void option_indat_callback(struct urb *urb)
dbg("%s: nonzero status: %d on endpoint %02x.",
__func__, status, endpoint);
} else {
- tty = port->tty;
+ tty = port->port.tty;
if (urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
@@ -572,7 +544,7 @@ static void option_indat_callback(struct urb *urb)
}
/* Resubmit urb so we continue receiving */
- if (port->open_count && status != -ESHUTDOWN) {
+ if (port->port.count && status != -ESHUTDOWN) {
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
printk(KERN_ERR "%s: resubmit read urb failed. "
@@ -613,7 +585,7 @@ static void option_instat_callback(struct urb *urb)
struct usb_serial *serial = port->serial;
dbg("%s", __func__);
- dbg("%s: urb %p port %p has data %p", __func__,urb,port,portdata);
+ dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata);
if (status == 0) {
struct usb_ctrlrequest *req_pkt =
@@ -638,12 +610,12 @@ static void option_instat_callback(struct urb *urb)
portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
portdata->ri_state = ((signals & 0x08) ? 1 : 0);
- if (port->tty && !C_CLOCAL(port->tty) &&
+ if (port->port.tty && !C_CLOCAL(port->port.tty) &&
old_dcd_state && !portdata->dcd_state)
- tty_hangup(port->tty);
+ tty_hangup(port->port.tty);
} else {
dbg("%s: type %x req %x", __func__,
- req_pkt->bRequestType,req_pkt->bRequest);
+ req_pkt->bRequestType, req_pkt->bRequest);
}
} else
dbg("%s: error %d", __func__, status);
@@ -658,8 +630,9 @@ static void option_instat_callback(struct urb *urb)
}
}
-static int option_write_room(struct usb_serial_port *port)
+static int option_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct option_port_private *portdata;
int i;
int data_len = 0;
@@ -668,7 +641,7 @@ static int option_write_room(struct usb_serial_port *port)
portdata = usb_get_serial_port_data(port);
- for (i=0; i < N_OUT_URB; i++) {
+ for (i = 0; i < N_OUT_URB; i++) {
this_urb = portdata->out_urbs[i];
if (this_urb && !test_bit(i, &portdata->out_busy))
data_len += OUT_BUFLEN;
@@ -678,8 +651,9 @@ static int option_write_room(struct usb_serial_port *port)
return data_len;
}
-static int option_chars_in_buffer(struct usb_serial_port *port)
+static int option_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct option_port_private *portdata;
int i;
int data_len = 0;
@@ -687,7 +661,7 @@ static int option_chars_in_buffer(struct usb_serial_port *port)
portdata = usb_get_serial_port_data(port);
- for (i=0; i < N_OUT_URB; i++) {
+ for (i = 0; i < N_OUT_URB; i++) {
this_urb = portdata->out_urbs[i];
/* FIXME: This locking is insufficient as this_urb may
go unused during the test */
@@ -698,7 +672,8 @@ static int option_chars_in_buffer(struct usb_serial_port *port)
return data_len;
}
-static int option_open(struct usb_serial_port *port, struct file *filp)
+static int option_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct option_port_private *portdata;
struct usb_serial *serial = port->serial;
@@ -716,7 +691,7 @@ static int option_open(struct usb_serial_port *port, struct file *filp)
/* Reset low level data toggle and start reading from endpoints */
for (i = 0; i < N_IN_URB; i++) {
urb = portdata->in_urbs[i];
- if (! urb)
+ if (!urb)
continue;
if (urb->dev != serial->dev) {
dbg("%s: dev %p != %p", __func__,
@@ -741,21 +716,23 @@ static int option_open(struct usb_serial_port *port, struct file *filp)
/* Reset low level data toggle on out endpoints */
for (i = 0; i < N_OUT_URB; i++) {
urb = portdata->out_urbs[i];
- if (! urb)
+ if (!urb)
continue;
urb->dev = serial->dev;
/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
usb_pipeout(urb->pipe), 0); */
}
- port->tty->low_latency = 1;
+ if (tty)
+ tty->low_latency = 1;
- option_send_setup(port);
+ option_send_setup(tty, port);
- return (0);
+ return 0;
}
-static void option_close(struct usb_serial_port *port, struct file *filp)
+static void option_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
int i;
struct usb_serial *serial = port->serial;
@@ -770,7 +747,7 @@ static void option_close(struct usb_serial_port *port, struct file *filp)
if (serial->dev) {
mutex_lock(&serial->disc_mutex);
if (!serial->disconnected)
- option_send_setup(port);
+ option_send_setup(tty, port);
mutex_unlock(&serial->disc_mutex);
/* Stop reading/writing urbs */
@@ -779,7 +756,7 @@ static void option_close(struct usb_serial_port *port, struct file *filp)
for (i = 0; i < N_OUT_URB; i++)
usb_kill_urb(portdata->out_urbs[i]);
}
- port->tty = NULL;
+ port->port.tty = NULL; /* FIXME */
}
/* Helper functions used by option_setup_urbs */
@@ -809,7 +786,7 @@ static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
/* Setup urbs */
static void option_setup_urbs(struct usb_serial *serial)
{
- int i,j;
+ int i, j;
struct usb_serial_port *port;
struct option_port_private *portdata;
@@ -819,18 +796,22 @@ static void option_setup_urbs(struct usb_serial *serial)
port = serial->port[i];
portdata = usb_get_serial_port_data(port);
- /* Do indat endpoints first */
+ /* Do indat endpoints first */
for (j = 0; j < N_IN_URB; ++j) {
- portdata->in_urbs[j] = option_setup_urb (serial,
- port->bulk_in_endpointAddress, USB_DIR_IN, port,
- portdata->in_buffer[j], IN_BUFLEN, option_indat_callback);
+ portdata->in_urbs[j] = option_setup_urb(serial,
+ port->bulk_in_endpointAddress,
+ USB_DIR_IN, port,
+ portdata->in_buffer[j],
+ IN_BUFLEN, option_indat_callback);
}
/* outdat endpoints */
for (j = 0; j < N_OUT_URB; ++j) {
- portdata->out_urbs[j] = option_setup_urb (serial,
- port->bulk_out_endpointAddress, USB_DIR_OUT, port,
- portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback);
+ portdata->out_urbs[j] = option_setup_urb(serial,
+ port->bulk_out_endpointAddress,
+ USB_DIR_OUT, port,
+ portdata->out_buffer[j],
+ OUT_BUFLEN, option_outdat_callback);
}
}
}
@@ -841,7 +822,8 @@ static void option_setup_urbs(struct usb_serial *serial)
* This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
* CDC.
*/
-static int option_send_setup(struct usb_serial_port *port)
+static int option_send_setup(struct tty_struct *tty,
+ struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct option_port_private *portdata;
@@ -850,7 +832,7 @@ static int option_send_setup(struct usb_serial_port *port)
portdata = usb_get_serial_port_data(port);
- if (port->tty) {
+ if (tty) {
int val = 0;
if (portdata->dtr_state)
val |= 0x01;
@@ -858,10 +840,9 @@ static int option_send_setup(struct usb_serial_port *port)
val |= 0x02;
return usb_control_msg(serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
- 0x22,0x21,val,ifNum,NULL,0,USB_CTRL_SET_TIMEOUT);
+ usb_rcvctrlpipe(serial->dev, 0),
+ 0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT);
}
-
return 0;
}
@@ -881,7 +862,7 @@ static int option_startup(struct usb_serial *serial)
if (!portdata) {
dbg("%s: kmalloc for option_port_private (%d) failed!.",
__func__, i);
- return (1);
+ return 1;
}
for (j = 0; j < N_IN_URB; j++) {
@@ -900,17 +881,15 @@ static int option_startup(struct usb_serial *serial)
usb_set_serial_port_data(port, portdata);
- if (! port->interrupt_in_urb)
+ if (!port->interrupt_in_urb)
continue;
err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (err)
dbg("%s: submit irq_in urb failed %d",
__func__, err);
}
-
option_setup_urbs(serial);
-
- return (0);
+ return 0;
bail_out_error2:
for (j = 0; j < N_OUT_URB; j++)
@@ -949,7 +928,8 @@ static void option_shutdown(struct usb_serial *serial)
for (j = 0; j < N_IN_URB; j++) {
if (portdata->in_urbs[j]) {
usb_free_urb(portdata->in_urbs[j]);
- free_page((unsigned long)portdata->in_buffer[j]);
+ free_page((unsigned long)
+ portdata->in_buffer[j]);
portdata->in_urbs[j] = NULL;
}
}
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index a9625c180dc..81db5715ee2 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -25,7 +25,8 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
* TODO:
* - implement correct flushing for ioctls and oti6858_close()
@@ -49,7 +50,7 @@
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "oti6858.h"
#define OTI6858_DESCRIPTION \
@@ -135,27 +136,28 @@ struct oti6858_control_pkt {
#define OTI6858_CTRL_PKT_SIZE sizeof(struct oti6858_control_pkt)
#define OTI6858_CTRL_EQUALS_PENDING(a, priv) \
- ( ((a)->divisor == (priv)->pending_setup.divisor) \
+ (((a)->divisor == (priv)->pending_setup.divisor) \
&& ((a)->control == (priv)->pending_setup.control) \
- && ((a)->frame_fmt == (priv)->pending_setup.frame_fmt) )
+ && ((a)->frame_fmt == (priv)->pending_setup.frame_fmt))
/* function prototypes */
-static int oti6858_open(struct usb_serial_port *port, struct file *filp);
-static void oti6858_close(struct usb_serial_port *port, struct file *filp);
-static void oti6858_set_termios(struct usb_serial_port *port,
- struct ktermios *old);
-static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+static int oti6858_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void oti6858_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void oti6858_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
+static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
static void oti6858_read_int_callback(struct urb *urb);
static void oti6858_read_bulk_callback(struct urb *urb);
static void oti6858_write_bulk_callback(struct urb *urb);
-static int oti6858_write(struct usb_serial_port *port,
+static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
-static int oti6858_write_room(struct usb_serial_port *port);
-static void oti6858_break_ctl(struct usb_serial_port *port, int break_state);
-static int oti6858_chars_in_buffer(struct usb_serial_port *port);
-static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file);
-static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
+static int oti6858_write_room(struct tty_struct *tty);
+static int oti6858_chars_in_buffer(struct tty_struct *tty);
+static int oti6858_tiocmget(struct tty_struct *tty, struct file *file);
+static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
static int oti6858_startup(struct usb_serial *serial);
static void oti6858_shutdown(struct usb_serial *serial);
@@ -184,7 +186,6 @@ static struct usb_serial_driver oti6858_device = {
.close = oti6858_close,
.write = oti6858_write,
.ioctl = oti6858_ioctl,
- .break_ctl = oti6858_break_ctl,
.set_termios = oti6858_set_termios,
.tiocmget = oti6858_tiocmget,
.tiocmset = oti6858_tiocmset,
@@ -220,7 +221,7 @@ struct oti6858_private {
struct delayed_work delayed_setup_work;
wait_queue_head_t intr_wait;
- struct usb_serial_port *port; /* USB port with which associated */
+ struct usb_serial_port *port; /* USB port with which associated */
};
#undef dbg
@@ -229,7 +230,8 @@ struct oti6858_private {
static void setup_line(struct work_struct *work)
{
- struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_setup_work.work);
+ struct oti6858_private *priv = container_of(work,
+ struct oti6858_private, delayed_setup_work.work);
struct usb_serial_port *port = priv->port;
struct oti6858_control_pkt *new_setup;
unsigned long flags;
@@ -237,10 +239,12 @@ static void setup_line(struct work_struct *work)
dbg("%s(port = %d)", __func__, port->number);
- if ((new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
+ new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL);
+ if (new_setup == NULL) {
dev_err(&port->dev, "%s(): out of memory!\n", __func__);
/* we will try again */
- schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
+ schedule_delayed_work(&priv->delayed_setup_work,
+ msecs_to_jiffies(2));
return;
}
@@ -256,7 +260,8 @@ static void setup_line(struct work_struct *work)
dev_err(&port->dev, "%s(): error reading status\n", __func__);
kfree(new_setup);
/* we will try again */
- schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
+ schedule_delayed_work(&priv->delayed_setup_work,
+ msecs_to_jiffies(2));
return;
}
@@ -297,7 +302,8 @@ static void setup_line(struct work_struct *work)
void send_data(struct work_struct *work)
{
- struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_write_work.work);
+ struct oti6858_private *priv = container_of(work,
+ struct oti6858_private, delayed_write_work.work);
struct usb_serial_port *port = priv->port;
int count = 0, result;
unsigned long flags;
@@ -308,7 +314,8 @@ void send_data(struct work_struct *work)
spin_lock_irqsave(&priv->lock, flags);
if (priv->flags.write_urb_in_use) {
spin_unlock_irqrestore(&priv->lock, flags);
- schedule_delayed_work(&priv->delayed_write_work, msecs_to_jiffies(2));
+ schedule_delayed_work(&priv->delayed_write_work,
+ msecs_to_jiffies(2));
return;
}
priv->flags.write_urb_in_use = 1;
@@ -359,8 +366,8 @@ void send_data(struct work_struct *work)
static int oti6858_startup(struct usb_serial *serial)
{
- struct usb_serial_port *port = serial->port[0];
- struct oti6858_private *priv;
+ struct usb_serial_port *port = serial->port[0];
+ struct oti6858_private *priv;
int i;
for (i = 0; i < serial->num_ports; ++i) {
@@ -375,8 +382,8 @@ static int oti6858_startup(struct usb_serial *serial)
spin_lock_init(&priv->lock);
init_waitqueue_head(&priv->intr_wait);
-// INIT_WORK(&priv->setup_work, setup_line, serial->port[i]);
-// INIT_WORK(&priv->write_work, send_data, serial->port[i]);
+/* INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); */
+/* INIT_WORK(&priv->write_work, send_data, serial->port[i]); */
priv->port = port;
INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
@@ -395,7 +402,7 @@ static int oti6858_startup(struct usb_serial *serial)
return -ENOMEM;
}
-static int oti6858_write(struct usb_serial_port *port,
+static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
struct oti6858_private *priv = usb_get_serial_port_data(port);
@@ -413,8 +420,9 @@ static int oti6858_write(struct usb_serial_port *port,
return count;
}
-static int oti6858_write_room(struct usb_serial_port *port)
+static int oti6858_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct oti6858_private *priv = usb_get_serial_port_data(port);
int room = 0;
unsigned long flags;
@@ -428,8 +436,9 @@ static int oti6858_write_room(struct usb_serial_port *port)
return room;
}
-static int oti6858_chars_in_buffer(struct usb_serial_port *port)
+static int oti6858_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct oti6858_private *priv = usb_get_serial_port_data(port);
int chars = 0;
unsigned long flags;
@@ -443,8 +452,8 @@ static int oti6858_chars_in_buffer(struct usb_serial_port *port)
return chars;
}
-static void oti6858_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void oti6858_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct oti6858_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -455,22 +464,22 @@ static void oti6858_set_termios(struct usb_serial_port *port,
dbg("%s(port = %d)", __func__, port->number);
- if (!port->tty || !port->tty->termios) {
+ if (!tty) {
dbg("%s(): no tty structures", __func__);
return;
}
spin_lock_irqsave(&priv->lock, flags);
if (!priv->flags.termios_initialized) {
- *(port->tty->termios) = tty_std_termios;
- port->tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios->c_ispeed = 38400;
+ tty->termios->c_ospeed = 38400;
priv->flags.termios_initialized = 1;
- port->tty->termios->c_ispeed = 38400;
- port->tty->termios->c_ospeed = 38400;
}
spin_unlock_irqrestore(&priv->lock, flags);
- cflag = port->tty->termios->c_cflag;
+ cflag = tty->termios->c_cflag;
spin_lock_irqsave(&priv->lock, flags);
divisor = priv->pending_setup.divisor;
@@ -480,19 +489,19 @@ static void oti6858_set_termios(struct usb_serial_port *port,
frame_fmt &= ~FMT_DATA_BITS_MASK;
switch (cflag & CSIZE) {
- case CS5:
- frame_fmt |= FMT_DATA_BITS_5;
- break;
- case CS6:
- frame_fmt |= FMT_DATA_BITS_6;
- break;
- case CS7:
- frame_fmt |= FMT_DATA_BITS_7;
- break;
- default:
- case CS8:
- frame_fmt |= FMT_DATA_BITS_8;
- break;
+ case CS5:
+ frame_fmt |= FMT_DATA_BITS_5;
+ break;
+ case CS6:
+ frame_fmt |= FMT_DATA_BITS_6;
+ break;
+ case CS7:
+ frame_fmt |= FMT_DATA_BITS_7;
+ break;
+ default:
+ case CS8:
+ frame_fmt |= FMT_DATA_BITS_8;
+ break;
}
/* manufacturer claims that this device can work with baud rates
@@ -500,7 +509,7 @@ static void oti6858_set_termios(struct usb_serial_port *port,
* guarantee that any other baud rate will work (especially
* the higher ones)
*/
- br = tty_get_baud_rate(port->tty);
+ br = tty_get_baud_rate(tty);
if (br == 0) {
divisor = 0;
} else {
@@ -511,23 +520,21 @@ static void oti6858_set_termios(struct usb_serial_port *port,
new_divisor = (96000000 + 8 * br) / (16 * br);
real_br = 96000000 / (16 * new_divisor);
divisor = cpu_to_le16(new_divisor);
- tty_encode_baud_rate(port->tty, real_br, real_br);
+ tty_encode_baud_rate(tty, real_br, real_br);
}
frame_fmt &= ~FMT_STOP_BITS_MASK;
- if ((cflag & CSTOPB) != 0) {
+ if ((cflag & CSTOPB) != 0)
frame_fmt |= FMT_STOP_BITS_2;
- } else {
+ else
frame_fmt |= FMT_STOP_BITS_1;
- }
frame_fmt &= ~FMT_PARITY_MASK;
if ((cflag & PARENB) != 0) {
- if ((cflag & PARODD) != 0) {
+ if ((cflag & PARODD) != 0)
frame_fmt |= FMT_PARITY_ODD;
- } else {
+ else
frame_fmt |= FMT_PARITY_EVEN;
- }
} else {
frame_fmt |= FMT_PARITY_NONE;
}
@@ -564,7 +571,8 @@ static void oti6858_set_termios(struct usb_serial_port *port,
spin_unlock_irqrestore(&priv->lock, flags);
}
-static int oti6858_open(struct usb_serial_port *port, struct file *filp)
+static int oti6858_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct oti6858_private *priv = usb_get_serial_port_data(port);
struct ktermios tmp_termios;
@@ -578,10 +586,11 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
usb_clear_halt(serial->dev, port->write_urb->pipe);
usb_clear_halt(serial->dev, port->read_urb->pipe);
- if (port->open_count != 1)
+ if (port->port.count != 1)
return 0;
- if ((buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
+ buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL);
+ if (buf == NULL) {
dev_err(&port->dev, "%s(): out of memory!\n", __func__);
return -ENOMEM;
}
@@ -617,18 +626,19 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
if (result != 0) {
dev_err(&port->dev, "%s(): usb_submit_urb() failed"
" with error %d\n", __func__, result);
- oti6858_close(port, NULL);
+ oti6858_close(tty, port, NULL);
return -EPROTO;
}
/* setup termios */
- if (port->tty)
- oti6858_set_termios(port, &tmp_termios);
+ if (tty)
+ oti6858_set_termios(tty, port, &tmp_termios);
return 0;
}
-static void oti6858_close(struct usb_serial_port *port, struct file *filp)
+static void oti6858_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct oti6858_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -641,7 +651,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
spin_lock_irqsave(&priv->lock, flags);
timeout = 30 * HZ; /* PL2303_CLOSING_WAIT */
init_waitqueue_entry(&wait, current);
- add_wait_queue(&port->tty->write_wait, &wait);
+ add_wait_queue(&tty->write_wait, &wait);
dbg("%s(): entering wait loop", __func__);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
@@ -654,7 +664,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
spin_lock_irqsave(&priv->lock, flags);
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->tty->write_wait, &wait);
+ remove_wait_queue(&tty->write_wait, &wait);
dbg("%s(): after wait loop", __func__);
/* clear out any remaining data in the buffer */
@@ -669,7 +679,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
/* data is in the buffer to compute a delay */
/* that is not unnecessarily long) */
/* FIXME
- bps = tty_get_baud_rate(port->tty);
+ bps = tty_get_baud_rate(tty);
if (bps > 1200)
timeout = max((HZ*2560)/bps,HZ/10);
else
@@ -690,7 +700,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
usb_kill_urb(port->interrupt_in_urb);
/*
- if (port->tty && (port->tty->termios->c_cflag) & HUPCL) {
+ if (tty && (tty->termios->c_cflag) & HUPCL) {
// drop DTR and RTS
spin_lock_irqsave(&priv->lock, flags);
priv->pending_setup.control &= ~CONTROL_MASK;
@@ -699,9 +709,10 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
*/
}
-static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
+static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct oti6858_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
u8 control;
@@ -724,16 +735,16 @@ static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
if ((clear & TIOCM_DTR) != 0)
control &= ~CONTROL_DTR_HIGH;
- if (control != priv->pending_setup.control) {
+ if (control != priv->pending_setup.control)
priv->pending_setup.control = control;
- }
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
-static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file)
+static int oti6858_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct oti6858_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned pin_state;
@@ -779,7 +790,8 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
spin_unlock_irqrestore(&priv->lock, flags);
while (1) {
- wait_event_interruptible(priv->intr_wait, priv->status.pin_state != prev);
+ wait_event_interruptible(priv->intr_wait,
+ priv->status.pin_state != prev);
if (signal_pending(current))
return -ERESTARTSYS;
@@ -789,12 +801,11 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
changed = prev ^ status;
/* FIXME: check if this is correct (active high/low) */
- if ( ((arg & TIOCM_RNG) && (changed & PIN_RI)) ||
- ((arg & TIOCM_DSR) && (changed & PIN_DSR)) ||
- ((arg & TIOCM_CD) && (changed & PIN_DCD)) ||
- ((arg & TIOCM_CTS) && (changed & PIN_CTS))) {
- return 0;
- }
+ if (((arg & TIOCM_RNG) && (changed & PIN_RI)) ||
+ ((arg & TIOCM_DSR) && (changed & PIN_DSR)) ||
+ ((arg & TIOCM_CD) && (changed & PIN_DCD)) ||
+ ((arg & TIOCM_CTS) && (changed & PIN_CTS)))
+ return 0;
prev = status;
}
@@ -802,56 +813,25 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
return 0;
}
-static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
- void __user *user_arg = (void __user *) arg;
- unsigned int x;
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)",
__func__, port->number, cmd, arg);
switch (cmd) {
- case TIOCMBIS:
- if (copy_from_user(&x, user_arg, sizeof(x)))
- return -EFAULT;
- return oti6858_tiocmset(port, NULL, x, 0);
-
- case TIOCMBIC:
- if (copy_from_user(&x, user_arg, sizeof(x)))
- return -EFAULT;
- return oti6858_tiocmset(port, NULL, 0, x);
-
- case TIOCMIWAIT:
- dbg("%s(): TIOCMIWAIT", __func__);
- return wait_modem_info(port, arg);
-
- default:
- dbg("%s(): 0x%04x not supported", __func__, cmd);
- break;
+ case TIOCMIWAIT:
+ dbg("%s(): TIOCMIWAIT", __func__);
+ return wait_modem_info(port, arg);
+ default:
+ dbg("%s(): 0x%04x not supported", __func__, cmd);
+ break;
}
-
return -ENOIOCTLCMD;
}
-static void oti6858_break_ctl(struct usb_serial_port *port, int break_state)
-{
- int state;
-
- dbg("%s(port = %d)", __func__, port->number);
-
- state = (break_state == 0) ? 0 : 1;
- dbg("%s(): turning break %s", __func__, state ? "on" : "off");
-
- /* FIXME */
-/*
- result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
- BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
- 0, NULL, 0, 100);
- if (result != 0)
- dbg("%s(): error sending break", __func__);
- */
-}
static void oti6858_shutdown(struct usb_serial *serial)
{
@@ -964,7 +944,7 @@ static void oti6858_read_int_callback(struct urb *urb)
spin_lock_irqsave(&priv->lock, flags);
if (priv->flags.write_urb_in_use == 0
&& oti6858_buf_data_avail(priv->buf) != 0) {
- schedule_delayed_work(&priv->delayed_write_work,0);
+ schedule_delayed_work(&priv->delayed_write_work, 0);
resubmit = 0;
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -973,7 +953,7 @@ static void oti6858_read_int_callback(struct urb *urb)
if (resubmit) {
int result;
-// dbg("%s(): submitting interrupt urb", __func__);
+/* dbg("%s(): submitting interrupt urb", __func__); */
urb->dev = port->serial->dev;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result != 0) {
@@ -1002,14 +982,16 @@ static void oti6858_read_bulk_callback(struct urb *urb)
spin_unlock_irqrestore(&priv->lock, flags);
if (status != 0) {
- if (!port->open_count) {
+ if (!port->port.count) {
dbg("%s(): port is closed, exiting", __func__);
return;
}
/*
if (status == -EPROTO) {
- // PL2303 mysteriously fails with -EPROTO reschedule the read
- dbg("%s - caught -EPROTO, resubmitting the urb", __func__);
+ * PL2303 mysteriously fails with -EPROTO reschedule
+ the read *
+ dbg("%s - caught -EPROTO, resubmitting the urb",
+ __func__);
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
@@ -1020,14 +1002,14 @@ static void oti6858_read_bulk_callback(struct urb *urb)
return;
}
- tty = port->tty;
+ tty = port->port.tty;
if (tty != NULL && urb->actual_length > 0) {
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
- // schedule the interrupt urb if we are still open */
- if (port->open_count != 0) {
+ /* schedule the interrupt urb if we are still open */
+ if (port->port.count != 0) {
port->interrupt_in_urb->dev = port->serial->dev;
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
if (result != 0) {
@@ -1078,7 +1060,7 @@ static void oti6858_write_bulk_callback(struct urb *urb)
priv->flags.write_urb_in_use = 0;
- // schedule the interrupt urb if we are still open */
+ /* schedule the interrupt urb if we are still open */
port->interrupt_in_urb->dev = port->serial->dev;
dbg("%s(): submitting interrupt urb", __func__);
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
@@ -1153,7 +1135,7 @@ static unsigned int oti6858_buf_data_avail(struct oti6858_buf *pb)
{
if (pb == NULL)
return 0;
- return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+ return (pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size;
}
/*
@@ -1166,7 +1148,7 @@ static unsigned int oti6858_buf_space_avail(struct oti6858_buf *pb)
{
if (pb == NULL)
return 0;
- return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+ return (pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size;
}
/*
@@ -1253,13 +1235,12 @@ static int __init oti6858_init(void)
{
int retval;
- if ((retval = usb_serial_register(&oti6858_device)) == 0) {
- if ((retval = usb_register(&oti6858_driver)) != 0)
+ retval = usb_serial_register(&oti6858_device);
+ if (retval == 0) {
+ retval = usb_register(&oti6858_driver);
+ if (retval)
usb_serial_deregister(&oti6858_device);
- else
- return 0;
}
-
return retval;
}
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 2a0dd1b50dc..2c9c446ad62 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -10,7 +10,8 @@
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
*/
@@ -25,7 +26,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include "pl2303.h"
@@ -116,7 +117,7 @@ static struct usb_driver pl2303_driver = {
#define CONTROL_RTS 0x02
#define BREAK_REQUEST_TYPE 0x21
-#define BREAK_REQUEST 0x23
+#define BREAK_REQUEST 0x23
#define BREAK_ON 0xffff
#define BREAK_OFF 0x0000
@@ -222,7 +223,7 @@ static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
if (pb == NULL)
return 0;
- return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+ return (pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size;
}
/*
@@ -236,7 +237,7 @@ static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
if (pb == NULL)
return 0;
- return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+ return (pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size;
}
/*
@@ -395,7 +396,7 @@ static int pl2303_startup(struct usb_serial *serial)
cleanup:
kfree(buf);
- for (--i; i>=0; --i) {
+ for (--i; i >= 0; --i) {
priv = usb_get_serial_port_data(serial->port[i]);
pl2303_buf_free(priv->buf);
kfree(priv);
@@ -407,7 +408,7 @@ cleanup:
static int set_control_lines(struct usb_device *dev, u8 value)
{
int retval;
-
+
retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
value, 0, NULL, 0, 100);
@@ -452,14 +453,14 @@ static void pl2303_send(struct usb_serial_port *port)
dev_err(&port->dev, "%s - failed submitting write urb,"
" error %d\n", __func__, result);
priv->write_urb_in_use = 0;
- // TODO: reschedule pl2303_send
+ /* TODO: reschedule pl2303_send */
}
usb_serial_port_softint(port);
}
-static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf,
- int count)
+static int pl2303_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -478,8 +479,9 @@ static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf,
return count;
}
-static int pl2303_write_room(struct usb_serial_port *port)
+static int pl2303_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct pl2303_private *priv = usb_get_serial_port_data(port);
int room = 0;
unsigned long flags;
@@ -494,8 +496,9 @@ static int pl2303_write_room(struct usb_serial_port *port)
return room;
}
-static int pl2303_chars_in_buffer(struct usb_serial_port *port)
+static int pl2303_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct pl2303_private *priv = usb_get_serial_port_data(port);
int chars = 0;
unsigned long flags;
@@ -510,8 +513,8 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port)
return chars;
}
-static void pl2303_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void pl2303_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -526,11 +529,10 @@ static void pl2303_set_termios(struct usb_serial_port *port,
spin_lock_irqsave(&priv->lock, flags);
if (!priv->termios_initialized) {
- *(port->tty->termios) = tty_std_termios;
- port->tty->termios->c_cflag = B9600 | CS8 | CREAD |
- HUPCL | CLOCAL;
- port->tty->termios->c_ispeed = 9600;
- port->tty->termios->c_ospeed = 9600;
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios->c_ispeed = 9600;
+ tty->termios->c_ospeed = 9600;
priv->termios_initialized = 1;
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -539,16 +541,16 @@ static void pl2303_set_termios(struct usb_serial_port *port,
serial settings even to the same values as before. Thus
we actually need to filter in this specific case */
- if (!tty_termios_hw_change(port->tty->termios, old_termios))
+ if (!tty_termios_hw_change(tty->termios, old_termios))
return;
- cflag = port->tty->termios->c_cflag;
+ cflag = tty->termios->c_cflag;
buf = kzalloc(7, GFP_KERNEL);
if (!buf) {
dev_err(&port->dev, "%s - out of memory.\n", __func__);
/* Report back no change occurred */
- *port->tty->termios = *old_termios;
+ *tty->termios = *old_termios;
return;
}
@@ -560,16 +562,24 @@ static void pl2303_set_termios(struct usb_serial_port *port,
if (cflag & CSIZE) {
switch (cflag & CSIZE) {
- case CS5: buf[6] = 5; break;
- case CS6: buf[6] = 6; break;
- case CS7: buf[6] = 7; break;
- default:
- case CS8: buf[6] = 8; break;
+ case CS5:
+ buf[6] = 5;
+ break;
+ case CS6:
+ buf[6] = 6;
+ break;
+ case CS7:
+ buf[6] = 7;
+ break;
+ default:
+ case CS8:
+ buf[6] = 8;
+ break;
}
dbg("%s - data bits = %d", __func__, buf[6]);
}
- baud = tty_get_baud_rate(port->tty);;
+ baud = tty_get_baud_rate(tty);
dbg("%s - baud = %d", __func__, baud);
if (baud) {
buf[0] = baud & 0xff;
@@ -646,12 +656,13 @@ static void pl2303_set_termios(struct usb_serial_port *port,
/* FIXME: Need to read back resulting baud rate */
if (baud)
- tty_encode_baud_rate(port->tty, baud, baud);
+ tty_encode_baud_rate(tty, baud, baud);
kfree(buf);
}
-static void pl2303_close(struct usb_serial_port *port, struct file *filp)
+static void pl2303_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -666,7 +677,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
spin_lock_irqsave(&priv->lock, flags);
timeout = PL2303_CLOSING_WAIT;
init_waitqueue_entry(&wait, current);
- add_wait_queue(&port->tty->write_wait, &wait);
+ add_wait_queue(&tty->write_wait, &wait);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
if (pl2303_buf_data_avail(priv->buf) == 0 ||
@@ -678,7 +689,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
spin_lock_irqsave(&priv->lock, flags);
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->tty->write_wait, &wait);
+ remove_wait_queue(&tty->write_wait, &wait);
/* clear out any remaining data in the buffer */
pl2303_buf_clear(priv->buf);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -690,9 +701,9 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
/* for lower rates we should really know how much */
/* data is in the buffer to compute a delay */
/* that is not unnecessarily long) */
- bps = tty_get_baud_rate(port->tty);
+ bps = tty_get_baud_rate(tty);
if (bps > 1200)
- timeout = max((HZ*2560)/bps,HZ/10);
+ timeout = max((HZ*2560)/bps, HZ/10);
else
timeout = 2*HZ;
schedule_timeout_interruptible(timeout);
@@ -703,8 +714,8 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
usb_kill_urb(port->read_urb);
usb_kill_urb(port->interrupt_in_urb);
- if (port->tty) {
- c_cflag = port->tty->termios->c_cflag;
+ if (tty) {
+ c_cflag = tty->termios->c_cflag;
if (c_cflag & HUPCL) {
/* drop DTR and RTS */
spin_lock_irqsave(&priv->lock, flags);
@@ -715,7 +726,8 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
}
}
-static int pl2303_open(struct usb_serial_port *port, struct file *filp)
+static int pl2303_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
@@ -734,11 +746,10 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
}
/* Setup termios */
- if (port->tty) {
- pl2303_set_termios(port, &tmp_termios);
- }
+ if (tty)
+ pl2303_set_termios(tty, port, &tmp_termios);
- //FIXME: need to assert RTS and DTR if CRTSCTS off
+ /* FIXME: need to assert RTS and DTR if CRTSCTS off */
dbg("%s - submitting read urb", __func__);
port->read_urb->dev = serial->dev;
@@ -746,7 +757,7 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
if (result) {
dev_err(&port->dev, "%s - failed submitting read urb,"
" error %d\n", __func__, result);
- pl2303_close(port, NULL);
+ pl2303_close(tty, port, NULL);
return -EPROTO;
}
@@ -756,15 +767,16 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
if (result) {
dev_err(&port->dev, "%s - failed submitting interrupt urb,"
" error %d\n", __func__, result);
- pl2303_close(port, NULL);
+ pl2303_close(tty, port, NULL);
return -EPROTO;
}
return 0;
}
-static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file,
+static int pl2303_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
u8 control;
@@ -787,8 +799,9 @@ static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file,
return set_control_lines(port->serial->dev, control);
}
-static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file)
+static int pl2303_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int mcr;
@@ -839,12 +852,12 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
status = priv->line_status;
spin_unlock_irqrestore(&priv->lock, flags);
- changed=prevstatus^status;
+ changed = prevstatus ^ status;
if (((arg & TIOCM_RNG) && (changed & UART_RING)) ||
((arg & TIOCM_DSR) && (changed & UART_DSR)) ||
((arg & TIOCM_CD) && (changed & UART_DCD)) ||
- ((arg & TIOCM_CTS) && (changed & UART_CTS)) ) {
+ ((arg & TIOCM_CTS) && (changed & UART_CTS))) {
return 0;
}
prevstatus = status;
@@ -853,26 +866,26 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
return 0;
}
-static int pl2303_ioctl(struct usb_serial_port *port, struct file *file,
+static int pl2303_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
switch (cmd) {
- case TIOCMIWAIT:
- dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
- return wait_modem_info(port, arg);
-
- default:
- dbg("%s not supported = 0x%04x", __func__, cmd);
- break;
+ case TIOCMIWAIT:
+ dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
+ return wait_modem_info(port, arg);
+ default:
+ dbg("%s not supported = 0x%04x", __func__, cmd);
+ break;
}
-
return -ENOIOCTLCMD;
}
-static void pl2303_break_ctl(struct usb_serial_port *port, int break_state)
+static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
u16 state;
int result;
@@ -883,7 +896,8 @@ static void pl2303_break_ctl(struct usb_serial_port *port, int break_state)
state = BREAK_OFF;
else
state = BREAK_ON;
- dbg("%s - turning break %s", __func__, state==BREAK_OFF ? "off" : "on");
+ dbg("%s - turning break %s", __func__,
+ state == BREAK_OFF ? "off" : "on");
result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
@@ -937,7 +951,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
if (actual_length < length)
return;
- /* Save off the uart status for others to look at */
+ /* Save off the uart status for others to look at */
spin_lock_irqsave(&priv->lock, flags);
priv->line_status = data[status_idx];
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1001,7 +1015,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
if (status) {
dbg("%s - urb status = %d", __func__, status);
- if (!port->open_count) {
+ if (!port->port.count) {
dbg("%s - port is closed, exiting.", __func__);
return;
}
@@ -1036,7 +1050,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
/* break takes precedence over parity, */
/* which takes precedence over framing errors */
- if (line_status & UART_BREAK_ERROR )
+ if (line_status & UART_BREAK_ERROR)
tty_flag = TTY_BREAK;
else if (line_status & UART_PARITY_ERROR)
tty_flag = TTY_PARITY;
@@ -1044,7 +1058,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
tty_flag = TTY_FRAME;
dbg("%s - tty_flag = %d", __func__, tty_flag);
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length + 1);
/* overrun is special, not associated with a char */
@@ -1056,7 +1070,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
}
/* Schedule the next read _if_ we are still open */
- if (port->open_count) {
+ if (port->port.count) {
urb->dev = port->serial->dev;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index 94bddf06ea4..def52d07a4e 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -13,24 +13,25 @@
* Stuart Lynne <sl@lineo.com>, Tom Rushworth <tbr@lineo.com>
*/
-/*
- * The encapsultaion is designed to overcome difficulties with some USB hardware.
+/*
+ * The encapsultaion is designed to overcome difficulties with some USB
+ * hardware.
*
* While the USB protocol has a CRC over the data while in transit, i.e. while
- * being carried over the bus, there is no end to end protection. If the hardware
- * has any problems getting the data into or out of the USB transmit and receive
- * FIFO's then data can be lost.
+ * being carried over the bus, there is no end to end protection. If the
+ * hardware has any problems getting the data into or out of the USB transmit
+ * and receive FIFO's then data can be lost.
*
- * This protocol adds a two byte trailer to each USB packet to specify the number
- * of bytes of valid data and a 10 bit CRC that will allow the receiver to verify
- * that the entire USB packet was received without error.
+ * This protocol adds a two byte trailer to each USB packet to specify the
+ * number of bytes of valid data and a 10 bit CRC that will allow the receiver
+ * to verify that the entire USB packet was received without error.
*
- * Because in this case the sender and receiver are the class and function drivers
- * there is now end to end protection.
+ * Because in this case the sender and receiver are the class and function
+ * drivers there is now end to end protection.
*
- * There is an additional option that can be used to force all transmitted packets
- * to be padded to the maximum packet size. This provides a work around for some
- * devices which have problems with small USB packets.
+ * There is an additional option that can be used to force all transmitted
+ * packets to be padded to the maximum packet size. This provides a work
+ * around for some devices which have problems with small USB packets.
*
* Assuming a packetsize of N:
*
@@ -44,11 +45,12 @@
* | Data Length | 10 bit CRC |
* + 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 | 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 +
*
- * The 10 bit CRC is computed across the sent data, followed by the trailer with
- * the length set and the CRC set to zero. The CRC is then OR'd into the trailer.
+ * The 10 bit CRC is computed across the sent data, followed by the trailer
+ * with the length set and the CRC set to zero. The CRC is then OR'd into
+ * the trailer.
*
- * When received a 10 bit CRC is computed over the entire frame including the trailer
- * and should be equal to zero.
+ * When received a 10 bit CRC is computed over the entire frame including
+ * the trailer and should be equal to zero.
*
* Two module parameters are used to control the encapsulation, if both are
* turned of the module works as a simple serial device with NO
@@ -69,7 +71,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -86,12 +88,12 @@ static int padded = CONFIG_USB_SERIAL_SAFE_PADDED;
#define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com"
#define DRIVER_DESC "USB Safe Encapsulated Serial"
-MODULE_AUTHOR (DRIVER_AUTHOR);
-MODULE_DESCRIPTION (DRIVER_DESC);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-static __u16 vendor; // no default
-static __u16 product; // no default
+static __u16 vendor; /* no default */
+static __u16 product; /* no default */
module_param(vendor, ushort, 0);
MODULE_PARM_DESC(vendor, "User specified USB idVendor (required)");
module_param(product, ushort, 0);
@@ -122,30 +124,31 @@ MODULE_PARM_DESC(padded, "Pad to full wMaxPacketSize On/Off");
#define LINEO_SAFESERIAL_CRC_PADDED 0x02
-#define MY_USB_DEVICE(vend,prod,dc,ic,isc) \
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_CLASS | \
- USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS, \
- .idVendor = (vend), \
- .idProduct = (prod),\
- .bDeviceClass = (dc),\
- .bInterfaceClass = (ic), \
- .bInterfaceSubClass = (isc),
+#define MY_USB_DEVICE(vend, prod, dc, ic, isc) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+ USB_DEVICE_ID_MATCH_DEV_CLASS | \
+ USB_DEVICE_ID_MATCH_INT_CLASS | \
+ USB_DEVICE_ID_MATCH_INT_SUBCLASS, \
+ .idVendor = (vend), \
+ .idProduct = (prod),\
+ .bDeviceClass = (dc),\
+ .bInterfaceClass = (ic), \
+ .bInterfaceSubClass = (isc),
static struct usb_device_id id_table[] = {
- {MY_USB_DEVICE (0x49f, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Itsy
- {MY_USB_DEVICE (0x3f0, 0x2101, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Calypso
- {MY_USB_DEVICE (0x4dd, 0x8001, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Iris
- {MY_USB_DEVICE (0x4dd, 0x8002, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Collie
- {MY_USB_DEVICE (0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Collie
- {MY_USB_DEVICE (0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Collie
- {MY_USB_DEVICE (0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Sharp tmp
- // extra null entry for module
- // vendor/produc parameters
- {MY_USB_DEVICE (0, 0, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
- {} // terminating entry
+ {MY_USB_DEVICE(0x49f, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Itsy */
+ {MY_USB_DEVICE(0x3f0, 0x2101, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Calypso */
+ {MY_USB_DEVICE(0x4dd, 0x8001, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Iris */
+ {MY_USB_DEVICE(0x4dd, 0x8002, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Collie */
+ {MY_USB_DEVICE(0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Collie */
+ {MY_USB_DEVICE(0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Collie */
+ {MY_USB_DEVICE(0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Sharp tmp */
+ /* extra null entry for module vendor/produc parameters */
+ {MY_USB_DEVICE(0, 0, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
+ {} /* terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver safe_driver = {
.name = "safe_serial",
@@ -156,29 +159,45 @@ static struct usb_driver safe_driver = {
};
static const __u16 crc10_table[256] = {
- 0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff, 0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
- 0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce, 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf,
- 0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d, 0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c,
- 0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f, 0x2ac, 0x352, 0x161, 0x107, 0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad,
- 0x0c4, 0x2f7, 0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b, 0x3c5, 0x1f6, 0x190, 0x3a3, 0x15c, 0x36f, 0x309, 0x13a,
- 0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a, 0x3f4, 0x1c7, 0x1a1, 0x392, 0x16d, 0x35e, 0x338, 0x10b,
- 0x0a6, 0x295, 0x2f3, 0x0c0, 0x23f, 0x00c, 0x06a, 0x259, 0x3a7, 0x194, 0x1f2, 0x3c1, 0x13e, 0x30d, 0x36b, 0x158,
- 0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268, 0x396, 0x1a5, 0x1c3, 0x3f0, 0x10f, 0x33c, 0x35a, 0x169,
- 0x188, 0x3bb, 0x3dd, 0x1ee, 0x311, 0x122, 0x144, 0x377, 0x289, 0x0ba, 0x0dc, 0x2ef, 0x010, 0x223, 0x245, 0x076,
- 0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346, 0x2b8, 0x08b, 0x0ed, 0x2de, 0x021, 0x212, 0x274, 0x047,
- 0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373, 0x140, 0x126, 0x315, 0x2eb, 0x0d8, 0x0be, 0x28d, 0x072, 0x241, 0x227, 0x014,
- 0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324, 0x2da, 0x0e9, 0x08f, 0x2bc, 0x043, 0x270, 0x216, 0x025,
- 0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6, 0x180, 0x3b3, 0x24d, 0x07e, 0x018, 0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2,
- 0x17d, 0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382, 0x27c, 0x04f, 0x029, 0x21a, 0x0e5, 0x2d6, 0x2b0, 0x083,
- 0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2, 0x3d1, 0x22f, 0x01c, 0x07a, 0x249, 0x0b6, 0x285, 0x2e3, 0x0d0,
- 0x11f, 0x32c, 0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0, 0x21e, 0x02d, 0x04b, 0x278, 0x087, 0x2b4, 0x2d2, 0x0e1,
+ 0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff,
+ 0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
+ 0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce,
+ 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf,
+ 0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d,
+ 0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c,
+ 0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f, 0x2ac,
+ 0x352, 0x161, 0x107, 0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad,
+ 0x0c4, 0x2f7, 0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b,
+ 0x3c5, 0x1f6, 0x190, 0x3a3, 0x15c, 0x36f, 0x309, 0x13a,
+ 0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a,
+ 0x3f4, 0x1c7, 0x1a1, 0x392, 0x16d, 0x35e, 0x338, 0x10b,
+ 0x0a6, 0x295, 0x2f3, 0x0c0, 0x23f, 0x00c, 0x06a, 0x259,
+ 0x3a7, 0x194, 0x1f2, 0x3c1, 0x13e, 0x30d, 0x36b, 0x158,
+ 0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268,
+ 0x396, 0x1a5, 0x1c3, 0x3f0, 0x10f, 0x33c, 0x35a, 0x169,
+ 0x188, 0x3bb, 0x3dd, 0x1ee, 0x311, 0x122, 0x144, 0x377,
+ 0x289, 0x0ba, 0x0dc, 0x2ef, 0x010, 0x223, 0x245, 0x076,
+ 0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346,
+ 0x2b8, 0x08b, 0x0ed, 0x2de, 0x021, 0x212, 0x274, 0x047,
+ 0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373, 0x140, 0x126, 0x315,
+ 0x2eb, 0x0d8, 0x0be, 0x28d, 0x072, 0x241, 0x227, 0x014,
+ 0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324,
+ 0x2da, 0x0e9, 0x08f, 0x2bc, 0x043, 0x270, 0x216, 0x025,
+ 0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6, 0x180, 0x3b3,
+ 0x24d, 0x07e, 0x018, 0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2,
+ 0x17d, 0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382,
+ 0x27c, 0x04f, 0x029, 0x21a, 0x0e5, 0x2d6, 0x2b0, 0x083,
+ 0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2, 0x3d1,
+ 0x22f, 0x01c, 0x07a, 0x249, 0x0b6, 0x285, 0x2e3, 0x0d0,
+ 0x11f, 0x32c, 0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0,
+ 0x21e, 0x02d, 0x04b, 0x278, 0x087, 0x2b4, 0x2d2, 0x0e1,
};
-#define CRC10_INITFCS 0x000 // Initial FCS value
-#define CRC10_GOODFCS 0x000 // Good final FCS value
-#define CRC10_FCS(fcs, c) ( (((fcs) << 8) & 0x3ff) ^ crc10_table[((fcs) >> 2) & 0xff] ^ (c))
+#define CRC10_INITFCS 0x000 /* Initial FCS value */
+#define CRC10_GOODFCS 0x000 /* Good final FCS value */
+#define CRC10_FCS(fcs, c) ((((fcs) << 8) & 0x3ff) ^ crc10_table[((fcs) >> 2) & 0xff] ^ (c))
-/**
+/**
* fcs_compute10 - memcpy and calculate 10 bit CRC across buffer
* @sp: pointer to buffer
* @len: number of bytes
@@ -187,13 +206,13 @@ static const __u16 crc10_table[256] = {
* Perform a memcpy and calculate fcs using ppp 10bit CRC algorithm. Return
* new 10 bit FCS.
*/
-static __u16 __inline__ fcs_compute10 (unsigned char *sp, int len, __u16 fcs)
+static __u16 __inline__ fcs_compute10(unsigned char *sp, int len, __u16 fcs)
{
- for (; len-- > 0; fcs = CRC10_FCS (fcs, *sp++));
+ for (; len-- > 0; fcs = CRC10_FCS(fcs, *sp++));
return fcs;
}
-static void safe_read_bulk_callback (struct urb *urb)
+static void safe_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
@@ -201,7 +220,7 @@ static void safe_read_bulk_callback (struct urb *urb)
int result;
int status = urb->status;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
if (status) {
dbg("%s - nonzero read bulk status received: %d",
@@ -209,76 +228,82 @@ static void safe_read_bulk_callback (struct urb *urb)
return;
}
- dbg ("safe_read_bulk_callback length: %d", port->read_urb->actual_length);
+ dbg("safe_read_bulk_callback length: %d",
+ port->read_urb->actual_length);
#ifdef ECHO_RCV
{
int i;
unsigned char *cp = port->read_urb->transfer_buffer;
for (i = 0; i < port->read_urb->actual_length; i++) {
- if ((i % 32) == 0) {
- printk ("\nru[%02x] ", i);
- }
- printk ("%02x ", *cp++);
+ if ((i % 32) == 0)
+ printk("\nru[%02x] ", i);
+ printk("%02x ", *cp++);
}
- printk ("\n");
+ printk("\n");
}
#endif
if (safe) {
__u16 fcs;
- if (!(fcs = fcs_compute10 (data, length, CRC10_INITFCS))) {
+ fcs = fcs_compute10(data, length, CRC10_INITFCS);
+ if (!fcs) {
int actual_length = data[length - 2] >> 2;
if (actual_length <= (length - 2)) {
- info ("%s - actual: %d", __func__, actual_length);
- tty_insert_flip_string(port->tty, data, actual_length);
- tty_flip_buffer_push (port->tty);
+ info("%s - actual: %d", __func__,
+ actual_length);
+ tty_insert_flip_string(port->port.tty,
+ data, actual_length);
+ tty_flip_buffer_push(port->port.tty);
} else {
- err ("%s - inconsistent lengths %d:%d", __func__,
- actual_length, length);
+ err("%s - inconsistent lengths %d:%d",
+ __func__, actual_length, length);
}
} else {
- err ("%s - bad CRC %x", __func__, fcs);
+ err("%s - bad CRC %x", __func__, fcs);
}
} else {
- tty_insert_flip_string(port->tty, data, length);
- tty_flip_buffer_push (port->tty);
+ tty_insert_flip_string(port->port.tty, data, length);
+ tty_flip_buffer_push(port->port.tty);
}
/* Continue trying to always read */
- usb_fill_bulk_urb (urb, port->serial->dev,
- usb_rcvbulkpipe (port->serial->dev, port->bulk_in_endpointAddress),
- urb->transfer_buffer, urb->transfer_buffer_length,
- safe_read_bulk_callback, port);
-
- if ((result = usb_submit_urb (urb, GFP_ATOMIC))) {
- err ("%s - failed resubmitting read urb, error %d", __func__, result);
+ usb_fill_bulk_urb(urb, port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
+ port->bulk_in_endpointAddress),
+ urb->transfer_buffer, urb->transfer_buffer_length,
+ safe_read_bulk_callback, port);
+
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result)
+ err("%s - failed resubmitting read urb, error %d",
+ __func__, result);
/* FIXME: Need a mechanism to retry later if this happens */
- }
}
-static int safe_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int safe_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
unsigned char *data;
int result;
int i;
int packet_length;
- dbg ("safe_write port: %p %d urb: %p count: %d", port, port->number, port->write_urb,
- count);
+ dbg("safe_write port: %p %d urb: %p count: %d",
+ port, port->number, port->write_urb, count);
if (!port->write_urb) {
- dbg ("%s - write urb NULL", __func__);
+ dbg("%s - write urb NULL", __func__);
return 0;
}
- dbg ("safe_write write_urb: %d transfer_buffer_length",
+ dbg("safe_write write_urb: %d transfer_buffer_length",
port->write_urb->transfer_buffer_length);
if (!port->write_urb->transfer_buffer_length) {
- dbg ("%s - write urb transfer_buffer_length zero", __func__);
+ dbg("%s - write urb transfer_buffer_length zero", __func__);
return 0;
}
if (count == 0) {
- dbg ("%s - write request of 0 bytes", __func__);
+ dbg("%s - write request of 0 bytes", __func__);
return 0;
}
spin_lock_bh(&port->lock);
@@ -290,85 +315,85 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i
port->write_urb_busy = 1;
spin_unlock_bh(&port->lock);
- packet_length = port->bulk_out_size; // get max packetsize
+ packet_length = port->bulk_out_size; /* get max packetsize */
- i = packet_length - (safe ? 2 : 0); // get bytes to send
+ i = packet_length - (safe ? 2 : 0); /* get bytes to send */
count = (count > i) ? i : count;
- // get the data into the transfer buffer
+ /* get the data into the transfer buffer */
data = port->write_urb->transfer_buffer;
- memset (data, '0', packet_length);
+ memset(data, '0', packet_length);
- memcpy (data, buf, count);
+ memcpy(data, buf, count);
if (safe) {
__u16 fcs;
- // pad if necessary
- if (!padded) {
+ /* pad if necessary */
+ if (!padded)
packet_length = count + 2;
- }
- // set count
+ /* set count */
data[packet_length - 2] = count << 2;
data[packet_length - 1] = 0;
- // compute fcs and insert into trailer
- fcs = fcs_compute10 (data, packet_length, CRC10_INITFCS);
+ /* compute fcs and insert into trailer */
+ fcs = fcs_compute10(data, packet_length, CRC10_INITFCS);
data[packet_length - 2] |= fcs >> 8;
data[packet_length - 1] |= fcs & 0xff;
- // set length to send
+ /* set length to send */
port->write_urb->transfer_buffer_length = packet_length;
} else {
port->write_urb->transfer_buffer_length = count;
}
- usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
+ usb_serial_debug_data(debug, &port->dev, __func__, count,
+ port->write_urb->transfer_buffer);
#ifdef ECHO_TX
{
int i;
unsigned char *cp = port->write_urb->transfer_buffer;
for (i = 0; i < port->write_urb->transfer_buffer_length; i++) {
- if ((i % 32) == 0) {
- printk ("\nsu[%02x] ", i);
- }
- printk ("%02x ", *cp++);
+ if ((i % 32) == 0)
+ printk("\nsu[%02x] ", i);
+ printk("%02x ", *cp++);
}
- printk ("\n");
+ printk("\n");
}
#endif
port->write_urb->dev = port->serial->dev;
- if ((result = usb_submit_urb (port->write_urb, GFP_KERNEL))) {
+ result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+ if (result) {
port->write_urb_busy = 0;
- err ("%s - failed submitting write urb, error %d", __func__, result);
+ err("%s - failed submitting write urb, error %d",
+ __func__, result);
return 0;
}
- dbg ("%s urb: %p submitted", __func__, port->write_urb);
+ dbg("%s urb: %p submitted", __func__, port->write_urb);
- return (count);
+ return count;
}
-static int safe_write_room (struct usb_serial_port *port)
+static int safe_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int room = 0; /* Default: no room */
unsigned long flags;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
spin_lock_irqsave(&port->lock, flags);
if (port->write_urb_busy)
room = port->bulk_out_size - (safe ? 2 : 0);
spin_unlock_irqrestore(&port->lock, flags);
- if (room) {
- dbg ("safe_write_room returns %d", room);
- }
-
+ if (room)
+ dbg("safe_write_room returns %d", room);
return room;
}
-static int safe_startup (struct usb_serial *serial)
+static int safe_startup(struct usb_serial *serial)
{
switch (serial->interface->cur_altsetting->desc.bInterfaceProtocol) {
case LINEO_SAFESERIAL_CRC:
@@ -396,17 +421,18 @@ static struct usb_serial_driver safe_device = {
.attach = safe_startup,
};
-static int __init safe_init (void)
+static int __init safe_init(void)
{
int i, retval;
- info (DRIVER_VERSION " " DRIVER_AUTHOR);
- info (DRIVER_DESC);
- info ("vendor: %x product: %x safe: %d padded: %d\n", vendor, product, safe, padded);
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+ info("vendor: %x product: %x safe: %d padded: %d\n",
+ vendor, product, safe, padded);
- // if we have vendor / product parameters patch them into id list
+ /* if we have vendor / product parameters patch them into id list */
if (vendor || product) {
- info ("vendor: %x product: %x\n", vendor, product);
+ info("vendor: %x product: %x\n", vendor, product);
for (i = 0; i < ARRAY_SIZE(id_table); i++) {
if (!id_table[i].idVendor && !id_table[i].idProduct) {
@@ -431,11 +457,11 @@ failed_usb_serial_register:
return retval;
}
-static void __exit safe_exit (void)
+static void __exit safe_exit(void)
{
- usb_deregister (&safe_driver);
- usb_serial_deregister (&safe_device);
+ usb_deregister(&safe_driver);
+ usb_serial_deregister(&safe_device);
}
-module_init (safe_init);
-module_exit (safe_exit);
+module_init(safe_init);
+module_exit(safe_exit);
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 29074c1ba22..2f6f1523ec5 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -250,7 +250,8 @@ struct sierra_port_private {
int ri_state;
};
-static int sierra_send_setup(struct usb_serial_port *port)
+static int sierra_send_setup(struct tty_struct *tty,
+ struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct sierra_port_private *portdata;
@@ -260,7 +261,7 @@ static int sierra_send_setup(struct usb_serial_port *port)
portdata = usb_get_serial_port_data(port);
- if (port->tty) {
+ if (tty) {
int val = 0;
if (portdata->dtr_state)
val |= 0x01;
@@ -284,32 +285,17 @@ static int sierra_send_setup(struct usb_serial_port *port)
return 0;
}
-static void sierra_rx_throttle(struct usb_serial_port *port)
+static void sierra_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
dbg("%s", __func__);
+ tty_termios_copy_hw(tty->termios, old_termios);
+ sierra_send_setup(tty, port);
}
-static void sierra_rx_unthrottle(struct usb_serial_port *port)
-{
- dbg("%s", __func__);
-}
-
-static void sierra_break_ctl(struct usb_serial_port *port, int break_state)
-{
- /* Unfortunately, I don't know how to send a break */
- dbg("%s", __func__);
-}
-
-static void sierra_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
-{
- dbg("%s", __func__);
- tty_termios_copy_hw(port->tty->termios, old_termios);
- sierra_send_setup(port);
-}
-
-static int sierra_tiocmget(struct usb_serial_port *port, struct file *file)
+static int sierra_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned int value;
struct sierra_port_private *portdata;
@@ -325,9 +311,10 @@ static int sierra_tiocmget(struct usb_serial_port *port, struct file *file)
return value;
}
-static int sierra_tiocmset(struct usb_serial_port *port, struct file *file,
+static int sierra_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct sierra_port_private *portdata;
portdata = usb_get_serial_port_data(port);
@@ -341,13 +328,7 @@ static int sierra_tiocmset(struct usb_serial_port *port, struct file *file,
portdata->rts_state = 0;
if (clear & TIOCM_DTR)
portdata->dtr_state = 0;
- return sierra_send_setup(port);
-}
-
-static int sierra_ioctl(struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return -ENOIOCTLCMD;
+ return sierra_send_setup(tty, port);
}
static void sierra_outdat_callback(struct urb *urb)
@@ -374,8 +355,8 @@ static void sierra_outdat_callback(struct urb *urb)
}
/* Write */
-static int sierra_write(struct usb_serial_port *port,
- const unsigned char *buf, int count)
+static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct sierra_port_private *portdata = usb_get_serial_port_data(port);
struct usb_serial *serial = port->serial;
@@ -463,7 +444,7 @@ static void sierra_indat_callback(struct urb *urb)
dbg("%s: nonzero status: %d on endpoint %02x.",
__func__, status, endpoint);
} else {
- tty = port->tty;
+ tty = port->port.tty;
if (urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
@@ -473,7 +454,7 @@ static void sierra_indat_callback(struct urb *urb)
}
/* Resubmit urb so we continue receiving */
- if (port->open_count && status != -ESHUTDOWN) {
+ if (port->port.count && status != -ESHUTDOWN) {
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
dev_err(&port->dev, "resubmit read urb failed."
@@ -517,9 +498,9 @@ static void sierra_instat_callback(struct urb *urb)
portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
portdata->ri_state = ((signals & 0x08) ? 1 : 0);
- if (port->tty && !C_CLOCAL(port->tty) &&
+ if (port->port.tty && !C_CLOCAL(port->port.tty) &&
old_dcd_state && !portdata->dcd_state)
- tty_hangup(port->tty);
+ tty_hangup(port->port.tty);
} else {
dbg("%s: type %x req %x", __func__,
req_pkt->bRequestType, req_pkt->bRequest);
@@ -537,8 +518,9 @@ static void sierra_instat_callback(struct urb *urb)
}
}
-static int sierra_write_room(struct usb_serial_port *port)
+static int sierra_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct sierra_port_private *portdata = usb_get_serial_port_data(port);
unsigned long flags;
@@ -557,22 +539,8 @@ static int sierra_write_room(struct usb_serial_port *port)
return 2048;
}
-static int sierra_chars_in_buffer(struct usb_serial_port *port)
-{
- dbg("%s - port %d", __func__, port->number);
-
- /*
- * We can't really account for how much data we
- * have sent out, but hasn't made it through to the
- * device as we can't see the backend here, so just
- * tell the tty layer that everything is flushed.
- *
- * FIXME: should walk the outstanding urbs info
- */
- return 0;
-}
-
-static int sierra_open(struct usb_serial_port *port, struct file *filp)
+static int sierra_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct sierra_port_private *portdata;
struct usb_serial *serial = port->serial;
@@ -612,9 +580,10 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
}
}
- port->tty->low_latency = 1;
+ if (tty)
+ tty->low_latency = 1;
- sierra_send_setup(port);
+ sierra_send_setup(tty, port);
/* start up the interrupt endpoint if we have one */
if (port->interrupt_in_urb) {
@@ -626,7 +595,8 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
return 0;
}
-static void sierra_close(struct usb_serial_port *port, struct file *filp)
+static void sierra_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
int i;
struct usb_serial *serial = port->serial;
@@ -641,7 +611,7 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp)
if (serial->dev) {
mutex_lock(&serial->disc_mutex);
if (!serial->disconnected)
- sierra_send_setup(port);
+ sierra_send_setup(tty, port);
mutex_unlock(&serial->disc_mutex);
/* Stop reading/writing urbs */
@@ -651,7 +621,7 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp)
usb_kill_urb(port->interrupt_in_urb);
- port->tty = NULL;
+ port->port.tty = NULL; /* FIXME */
}
static int sierra_startup(struct usb_serial *serial)
@@ -754,12 +724,7 @@ static struct usb_serial_driver sierra_device = {
.close = sierra_close,
.write = sierra_write,
.write_room = sierra_write_room,
- .chars_in_buffer = sierra_chars_in_buffer,
- .throttle = sierra_rx_throttle,
- .unthrottle = sierra_rx_unthrottle,
- .ioctl = sierra_ioctl,
.set_termios = sierra_set_termios,
- .break_ctl = sierra_break_ctl,
.tiocmget = sierra_tiocmget,
.tiocmset = sierra_tiocmset,
.attach = sierra_startup,
@@ -792,7 +757,7 @@ failed_device_register:
static void __exit sierra_exit(void)
{
- usb_deregister (&sierra_driver);
+ usb_deregister(&sierra_driver);
usb_serial_deregister(&sierra_device);
}
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 55b2570b8b8..283cf6b36b2 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -208,7 +208,7 @@ static inline unsigned int ringbuf_avail_data(struct ringbuf *pb)
{
if (pb == NULL)
return 0;
- return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+ return (pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size;
}
/* get the number of space in the pipo */
@@ -216,7 +216,7 @@ static inline unsigned int ringbuf_avail_space(struct ringbuf *pb)
{
if (pb == NULL)
return 0;
- return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+ return (pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size;
}
/* put count data into pipo */
@@ -448,7 +448,8 @@ static void spcp8x5_set_workMode(struct usb_device *dev, u16 value,
/* close the serial port. We should wait for data sending to device 1st and
* then kill all urb. */
-static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
+static void spcp8x5_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -464,7 +465,7 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
spin_lock_irqsave(&priv->lock, flags);
timeout = SPCP8x5_CLOSING_WAIT;
init_waitqueue_entry(&wait, current);
- add_wait_queue(&port->tty->write_wait, &wait);
+ add_wait_queue(&tty->write_wait, &wait);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
if (ringbuf_avail_data(priv->buf) == 0 ||
@@ -475,7 +476,7 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
spin_lock_irqsave(&priv->lock, flags);
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->tty->write_wait, &wait);
+ remove_wait_queue(&tty->write_wait, &wait);
/* clear out any remaining data in the buffer */
clear_ringbuf(priv->buf);
@@ -486,7 +487,7 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
* flow control for data rates of 1200 bps or more, for lower rates we
* should really know how much data is in the buffer to compute a delay
* that is not unnecessarily long) */
- bps = tty_get_baud_rate(port->tty);
+ bps = tty_get_baud_rate(tty);
if (bps > 1200)
timeout = max((HZ*2560) / bps, HZ/10);
else
@@ -495,8 +496,8 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
schedule_timeout(timeout);
/* clear control lines */
- if (port->tty) {
- c_cflag = port->tty->termios->c_cflag;
+ if (tty) {
+ c_cflag = tty->termios->c_cflag;
if (c_cflag & HUPCL) {
spin_lock_irqsave(&priv->lock, flags);
priv->line_control = 0;
@@ -518,14 +519,14 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
}
/* set the serial param for transfer. we should check if we really need to
- * transfer. then if be set flow contorl we should do this too. */
-static void spcp8x5_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+ * transfer. if we set flow control we should do this too. */
+static void spcp8x5_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- unsigned int cflag = port->tty->termios->c_cflag;
+ unsigned int cflag = tty->termios->c_cflag;
unsigned int old_cflag = old_termios->c_cflag;
unsigned short uartdata;
unsigned char buf[2] = {0, 0};
@@ -533,21 +534,19 @@ static void spcp8x5_set_termios(struct usb_serial_port *port,
int i;
u8 control;
- if ((!port->tty) || (!port->tty->termios))
- return;
-
/* for the 1st time call this function */
spin_lock_irqsave(&priv->lock, flags);
if (!priv->termios_initialized) {
- *(port->tty->termios) = tty_std_termios;
- port->tty->termios->c_cflag = B115200 | CS8 | CREAD |
- HUPCL | CLOCAL;
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios->c_ispeed = 115200;
+ tty->termios->c_ospeed = 115200;
priv->termios_initialized = 1;
}
spin_unlock_irqrestore(&priv->lock, flags);
/* check that they really want us to change something */
- if (!tty_termios_hw_change(port->tty->termios, old_termios))
+ if (!tty_termios_hw_change(tty->termios, old_termios))
return;
/* set DTR/RTS active */
@@ -567,7 +566,7 @@ static void spcp8x5_set_termios(struct usb_serial_port *port,
}
/* Set Baud Rate */
- baud = tty_get_baud_rate(port->tty);;
+ baud = tty_get_baud_rate(tty);;
switch (baud) {
case 300: buf[0] = 0x00; break;
case 600: buf[0] = 0x01; break;
@@ -643,7 +642,8 @@ static void spcp8x5_set_termios(struct usb_serial_port *port,
/* open the serial port. do some usb system call. set termios and get the line
* status of the device. then submit the read urb */
-static int spcp8x5_open(struct usb_serial_port *port, struct file *filp)
+static int spcp8x5_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
@@ -665,7 +665,7 @@ static int spcp8x5_open(struct usb_serial_port *port, struct file *filp)
return ret;
spin_lock_irqsave(&priv->lock, flags);
- if (port->tty->termios->c_cflag & CBAUD)
+ if (tty && (tty->termios->c_cflag & CBAUD))
priv->line_control = MCR_DTR | MCR_RTS;
else
priv->line_control = 0;
@@ -674,8 +674,8 @@ static int spcp8x5_open(struct usb_serial_port *port, struct file *filp)
spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
/* Setup termios */
- if (port->tty)
- spcp8x5_set_termios(port, &tmp_termios);
+ if (tty)
+ spcp8x5_set_termios(tty, port, &tmp_termios);
spcp8x5_get_msr(serial->dev, &status, priv->type);
@@ -690,7 +690,7 @@ static int spcp8x5_open(struct usb_serial_port *port, struct file *filp)
port->read_urb->dev = serial->dev;
ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (ret) {
- spcp8x5_close(port, NULL);
+ spcp8x5_close(tty, port, NULL);
return -EPROTO;
}
return 0;
@@ -717,7 +717,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb)
/* check the urb status */
if (urb->status) {
- if (!port->open_count)
+ if (!port->port.count)
return;
if (urb->status == -EPROTO) {
/* spcp8x5 mysteriously fails with -EPROTO */
@@ -755,7 +755,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb)
tty_flag = TTY_FRAME;
dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length + 1);
/* overrun is special, not associated with a char */
@@ -767,7 +767,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb)
}
/* Schedule the next read _if_ we are still open */
- if (port->open_count) {
+ if (port->port.count) {
urb->dev = port->serial->dev;
result = usb_submit_urb(urb , GFP_ATOMIC);
if (result)
@@ -866,7 +866,7 @@ static void spcp8x5_write_bulk_callback(struct urb *urb)
}
/* write data to ring buffer. and then start the write transfer */
-static int spcp8x5_write(struct usb_serial_port *port,
+static int spcp8x5_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
@@ -925,9 +925,10 @@ static int spcp8x5_wait_modem_info(struct usb_serial_port *port,
return 0;
}
-static int spcp8x5_ioctl(struct usb_serial_port *port, struct file *file,
+static int spcp8x5_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
switch (cmd) {
@@ -943,9 +944,10 @@ static int spcp8x5_ioctl(struct usb_serial_port *port, struct file *file,
return -ENOIOCTLCMD;
}
-static int spcp8x5_tiocmset(struct usb_serial_port *port, struct file *file,
+static int spcp8x5_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
u8 control;
@@ -965,8 +967,9 @@ static int spcp8x5_tiocmset(struct usb_serial_port *port, struct file *file,
return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
}
-static int spcp8x5_tiocmget(struct usb_serial_port *port, struct file *file)
+static int spcp8x5_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int mcr;
@@ -989,8 +992,9 @@ static int spcp8x5_tiocmget(struct usb_serial_port *port, struct file *file)
}
/* get the avail space room in ring buffer */
-static int spcp8x5_write_room(struct usb_serial_port *port)
+static int spcp8x5_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
int room = 0;
unsigned long flags;
@@ -1003,8 +1007,9 @@ static int spcp8x5_write_room(struct usb_serial_port *port)
}
/* get the number of avail data in write ring buffer */
-static int spcp8x5_chars_in_buffer(struct usb_serial_port *port)
+static int spcp8x5_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
int chars = 0;
unsigned long flags;
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index a26a629dfc4..e39c779e416 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -16,7 +16,7 @@
* For questions or problems with this driver, contact Texas Instruments
* technical support, or Al Borchers <alborchers@steinerpoint.com>, or
* Peter Berger <pberger@brimson.com>.
- *
+ *
* This driver needs this hotplug script in /etc/hotplug/usb/ti_usb_3410_5052
* or in /etc/hotplug.d/usb/ti_usb_3410_5052.hotplug to set the device
* configuration.
@@ -70,6 +70,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
+#include <linux/firmware.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
@@ -81,7 +82,7 @@
#include <linux/serial.h>
#include <linux/circ_buf.h>
#include <linux/mutex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include <linux/firmware.h>
@@ -149,21 +150,24 @@ struct ti_device {
static int ti_startup(struct usb_serial *serial);
static void ti_shutdown(struct usb_serial *serial);
-static int ti_open(struct usb_serial_port *port, struct file *file);
-static void ti_close(struct usb_serial_port *port, struct file *file);
-static int ti_write(struct usb_serial_port *port, const unsigned char *data,
- int count);
-static int ti_write_room(struct usb_serial_port *port);
-static int ti_chars_in_buffer(struct usb_serial_port *port);
-static void ti_throttle(struct usb_serial_port *port);
-static void ti_unthrottle(struct usb_serial_port *port);
-static int ti_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);
-static void ti_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios);
-static int ti_tiocmget(struct usb_serial_port *port, struct file *file);
-static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
- unsigned int set, unsigned int clear);
-static void ti_break(struct usb_serial_port *port, int break_state);
+static int ti_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *file);
+static void ti_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *file);
+static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *data, int count);
+static int ti_write_room(struct tty_struct *tty);
+static int ti_chars_in_buffer(struct tty_struct *tty);
+static void ti_throttle(struct tty_struct *tty);
+static void ti_unthrottle(struct tty_struct *tty);
+static int ti_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static void ti_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios);
+static int ti_tiocmget(struct tty_struct *tty, struct file *file);
+static int ti_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
+static void ti_break(struct tty_struct *tty, int break_state);
static void ti_interrupt_callback(struct urb *urb);
static void ti_bulk_in_callback(struct urb *urb);
static void ti_bulk_out_callback(struct urb *urb);
@@ -192,8 +196,7 @@ static int ti_command_in_sync(struct ti_device *tdev, __u8 command,
static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
__u8 mask, __u8 byte);
-static int ti_download_firmware(struct ti_device *tdev, char *fw_name);
-
+static int ti_download_firmware(struct ti_device *tdev, int type);
/* circular buffer */
static struct circ_buf *ti_buf_alloc(void);
@@ -325,19 +328,25 @@ module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Enable debugging, 0=no, 1=yes");
module_param(low_latency, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(low_latency, "TTY low_latency flag, 0=off, 1=on, default is off");
+MODULE_PARM_DESC(low_latency,
+ "TTY low_latency flag, 0=off, 1=on, default is off");
module_param(closing_wait, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain in close, in .01 secs, default is 4000");
+MODULE_PARM_DESC(closing_wait,
+ "Maximum wait for data to drain in close, in .01 secs, default is 4000");
module_param_array(vendor_3410, ushort, &vendor_3410_count, S_IRUGO);
-MODULE_PARM_DESC(vendor_3410, "Vendor ids for 3410 based devices, 1-5 short integers");
+MODULE_PARM_DESC(vendor_3410,
+ "Vendor ids for 3410 based devices, 1-5 short integers");
module_param_array(product_3410, ushort, &product_3410_count, S_IRUGO);
-MODULE_PARM_DESC(product_3410, "Product ids for 3410 based devices, 1-5 short integers");
+MODULE_PARM_DESC(product_3410,
+ "Product ids for 3410 based devices, 1-5 short integers");
module_param_array(vendor_5052, ushort, &vendor_5052_count, S_IRUGO);
-MODULE_PARM_DESC(vendor_5052, "Vendor ids for 5052 based devices, 1-5 short integers");
+MODULE_PARM_DESC(vendor_5052,
+ "Vendor ids for 5052 based devices, 1-5 short integers");
module_param_array(product_5052, ushort, &product_5052_count, S_IRUGO);
-MODULE_PARM_DESC(product_5052, "Product ids for 5052 based devices, 1-5 short integers");
+MODULE_PARM_DESC(product_5052,
+ "Product ids for 5052 based devices, 1-5 short integers");
MODULE_DEVICE_TABLE(usb, ti_id_table_combined);
@@ -346,18 +355,18 @@ MODULE_DEVICE_TABLE(usb, ti_id_table_combined);
static int __init ti_init(void)
{
- int i,j;
+ int i, j;
int ret;
/* insert extra vendor and product ids */
j = ARRAY_SIZE(ti_id_table_3410) - TI_EXTRA_VID_PID_COUNT - 1;
- for (i=0; i<min(vendor_3410_count,product_3410_count); i++,j++) {
+ for (i = 0; i < min(vendor_3410_count, product_3410_count); i++, j++) {
ti_id_table_3410[j].idVendor = vendor_3410[i];
ti_id_table_3410[j].idProduct = product_3410[i];
ti_id_table_3410[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
}
j = ARRAY_SIZE(ti_id_table_5052) - TI_EXTRA_VID_PID_COUNT - 1;
- for (i=0; i<min(vendor_5052_count,product_5052_count); i++,j++) {
+ for (i = 0; i < min(vendor_5052_count, product_5052_count); i++, j++) {
ti_id_table_5052[j].idVendor = vendor_5052[i];
ti_id_table_5052[j].idProduct = product_5052[i];
ti_id_table_5052[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
@@ -426,15 +435,15 @@ static int ti_startup(struct usb_serial *serial)
/* determine device type */
if (usb_match_id(serial->interface, ti_id_table_3410))
tdev->td_is_3410 = 1;
- dbg("%s - device type is %s", __func__, tdev->td_is_3410 ? "3410" : "5052");
+ dbg("%s - device type is %s", __func__,
+ tdev->td_is_3410 ? "3410" : "5052");
/* if we have only 1 configuration, download firmware */
if (dev->descriptor.bNumConfigurations == 1) {
-
if (tdev->td_is_3410)
- status = ti_download_firmware(tdev, "ti_3410.fw");
+ status = ti_download_firmware(tdev, 3410);
else
- status = ti_download_firmware(tdev, "ti_5052.fw");
+ status = ti_download_firmware(tdev, 5052);
if (status)
goto free_tdev;
@@ -446,7 +455,7 @@ static int ti_startup(struct usb_serial *serial)
status = -ENODEV;
goto free_tdev;
- }
+ }
/* the second configuration must be set (in sysfs by hotplug script) */
if (dev->actconfig->desc.bConfigurationValue == TI_BOOT_CONFIG) {
@@ -463,7 +472,8 @@ static int ti_startup(struct usb_serial *serial)
goto free_tports;
}
spin_lock_init(&tport->tp_lock);
- tport->tp_uart_base_addr = (i == 0 ? TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
+ tport->tp_uart_base_addr = (i == 0 ?
+ TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
tport->tp_flags = low_latency ? ASYNC_LOW_LATENCY : 0;
tport->tp_closing_wait = closing_wait;
init_waitqueue_head(&tport->tp_msr_wait);
@@ -480,11 +490,11 @@ static int ti_startup(struct usb_serial *serial)
usb_set_serial_port_data(serial->port[i], tport);
tport->tp_uart_mode = 0; /* default is RS232 */
}
-
+
return 0;
free_tports:
- for (--i; i>=0; --i) {
+ for (--i; i >= 0; --i) {
tport = usb_get_serial_port_data(serial->port[i]);
ti_buf_free(tport->tp_write_buf);
kfree(tport);
@@ -505,7 +515,7 @@ static void ti_shutdown(struct usb_serial *serial)
dbg("%s", __func__);
- for (i=0; i < serial->num_ports; ++i) {
+ for (i = 0; i < serial->num_ports; ++i) {
tport = usb_get_serial_port_data(serial->port[i]);
if (tport) {
ti_buf_free(tport->tp_write_buf);
@@ -519,7 +529,8 @@ static void ti_shutdown(struct usb_serial *serial)
}
-static int ti_open(struct usb_serial_port *port, struct file *file)
+static int ti_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *file)
{
struct ti_port *tport = usb_get_serial_port_data(port);
struct ti_device *tdev;
@@ -527,8 +538,8 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
struct urb *urb;
int port_number;
int status;
- __u16 open_settings = (__u8)(TI_PIPE_MODE_CONTINOUS |
- TI_PIPE_TIMEOUT_ENABLE |
+ __u16 open_settings = (__u8)(TI_PIPE_MODE_CONTINOUS |
+ TI_PIPE_TIMEOUT_ENABLE |
(TI_TRANSFER_TIMEOUT << 2));
dbg("%s - port %d", __func__, port->number);
@@ -543,9 +554,9 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
if (mutex_lock_interruptible(&tdev->td_open_close_lock))
return -ERESTARTSYS;
- if (port->tty)
- port->tty->low_latency =
- (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ if (tty)
+ tty->low_latency =
+ (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
port_number = port->number - port->serial->minor;
@@ -559,7 +570,8 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
dbg("%s - start interrupt in urb", __func__);
urb = tdev->td_serial->port[0]->interrupt_in_urb;
if (!urb) {
- dev_err(&port->dev, "%s - no interrupt urb\n", __func__);
+ dev_err(&port->dev, "%s - no interrupt urb\n",
+ __func__);
status = -EINVAL;
goto release_lock;
}
@@ -568,18 +580,22 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
urb->dev = dev;
status = usb_submit_urb(urb, GFP_KERNEL);
if (status) {
- dev_err(&port->dev, "%s - submit interrupt urb failed, %d\n", __func__, status);
+ dev_err(&port->dev,
+ "%s - submit interrupt urb failed, %d\n",
+ __func__, status);
goto release_lock;
}
}
- ti_set_termios(port, port->tty->termios);
+ if (tty)
+ ti_set_termios(tty, port, tty->termios);
dbg("%s - sending TI_OPEN_PORT", __func__);
status = ti_command_out_sync(tdev, TI_OPEN_PORT,
(__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
if (status) {
- dev_err(&port->dev, "%s - cannot send open command, %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot send open command, %d\n",
+ __func__, status);
goto unlink_int_urb;
}
@@ -587,7 +603,8 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
status = ti_command_out_sync(tdev, TI_START_PORT,
(__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
if (status) {
- dev_err(&port->dev, "%s - cannot send start command, %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot send start command, %d\n",
+ __func__, status);
goto unlink_int_urb;
}
@@ -595,13 +612,15 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
status = ti_command_out_sync(tdev, TI_PURGE_PORT,
(__u8)(TI_UART1_PORT + port_number), TI_PURGE_INPUT, NULL, 0);
if (status) {
- dev_err(&port->dev, "%s - cannot clear input buffers, %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot clear input buffers, %d\n",
+ __func__, status);
goto unlink_int_urb;
}
status = ti_command_out_sync(tdev, TI_PURGE_PORT,
(__u8)(TI_UART1_PORT + port_number), TI_PURGE_OUTPUT, NULL, 0);
if (status) {
- dev_err(&port->dev, "%s - cannot clear output buffers, %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot clear output buffers, %d\n",
+ __func__, status);
goto unlink_int_urb;
}
@@ -610,13 +629,15 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
usb_clear_halt(dev, port->write_urb->pipe);
usb_clear_halt(dev, port->read_urb->pipe);
- ti_set_termios(port, port->tty->termios);
+ if (tty)
+ ti_set_termios(tty, port, tty->termios);
dbg("%s - sending TI_OPEN_PORT (2)", __func__);
status = ti_command_out_sync(tdev, TI_OPEN_PORT,
(__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
if (status) {
- dev_err(&port->dev, "%s - cannot send open command (2), %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot send open command (2), %d\n",
+ __func__, status);
goto unlink_int_urb;
}
@@ -624,7 +645,8 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
status = ti_command_out_sync(tdev, TI_START_PORT,
(__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
if (status) {
- dev_err(&port->dev, "%s - cannot send start command (2), %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot send start command (2), %d\n",
+ __func__, status);
goto unlink_int_urb;
}
@@ -642,7 +664,8 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
urb->dev = dev;
status = usb_submit_urb(urb, GFP_KERNEL);
if (status) {
- dev_err(&port->dev, "%s - submit read urb failed, %d\n", __func__, status);
+ dev_err(&port->dev, "%s - submit read urb failed, %d\n",
+ __func__, status);
goto unlink_int_urb;
}
@@ -661,7 +684,8 @@ release_lock:
}
-static void ti_close(struct usb_serial_port *port, struct file *file)
+static void ti_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *file)
{
struct ti_device *tdev;
struct ti_port *tport;
@@ -670,7 +694,7 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
int do_unlock;
dbg("%s - port %d", __func__, port->number);
-
+
tdev = usb_get_serial_data(port->serial);
tport = usb_get_serial_port_data(port);
if (tdev == NULL || tport == NULL)
@@ -690,7 +714,9 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
status = ti_command_out_sync(tdev, TI_CLOSE_PORT,
(__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
if (status)
- dev_err(&port->dev, "%s - cannot send close port command, %d\n" , __func__, status);
+ dev_err(&port->dev,
+ "%s - cannot send close port command, %d\n"
+ , __func__, status);
/* if mutex_lock is interrupted, continue anyway */
do_unlock = !mutex_lock_interruptible(&tdev->td_open_close_lock);
@@ -707,8 +733,8 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
}
-static int ti_write(struct usb_serial_port *port, const unsigned char *data,
- int count)
+static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *data, int count)
{
struct ti_port *tport = usb_get_serial_port_data(port);
unsigned long flags;
@@ -733,8 +759,9 @@ static int ti_write(struct usb_serial_port *port, const unsigned char *data,
}
-static int ti_write_room(struct usb_serial_port *port)
+static int ti_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
int room = 0;
unsigned long flags;
@@ -743,7 +770,7 @@ static int ti_write_room(struct usb_serial_port *port)
if (tport == NULL)
return -ENODEV;
-
+
spin_lock_irqsave(&tport->tp_lock, flags);
room = ti_buf_space_avail(tport->tp_write_buf);
spin_unlock_irqrestore(&tport->tp_lock, flags);
@@ -753,8 +780,9 @@ static int ti_write_room(struct usb_serial_port *port)
}
-static int ti_chars_in_buffer(struct usb_serial_port *port)
+static int ti_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
int chars = 0;
unsigned long flags;
@@ -773,32 +801,26 @@ static int ti_chars_in_buffer(struct usb_serial_port *port)
}
-static void ti_throttle(struct usb_serial_port *port)
+static void ti_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
- struct tty_struct *tty;
dbg("%s - port %d", __func__, port->number);
if (tport == NULL)
return;
- tty = port->tty;
- if (!tty) {
- dbg("%s - no tty", __func__);
- return;
- }
-
if (I_IXOFF(tty) || C_CRTSCTS(tty))
ti_stop_read(tport, tty);
}
-static void ti_unthrottle(struct usb_serial_port *port)
+static void ti_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
- struct tty_struct *tty;
int status;
dbg("%s - port %d", __func__, port->number);
@@ -806,23 +828,19 @@ static void ti_unthrottle(struct usb_serial_port *port)
if (tport == NULL)
return;
- tty = port->tty;
- if (!tty) {
- dbg("%s - no tty", __func__);
- return;
- }
-
if (I_IXOFF(tty) || C_CRTSCTS(tty)) {
status = ti_restart_read(tport, tty);
if (status)
- dev_err(&port->dev, "%s - cannot restart read, %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot restart read, %d\n",
+ __func__, status);
}
}
-static int ti_ioctl(struct usb_serial_port *port, struct file *file,
+static int ti_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
struct async_icount cnow;
struct async_icount cprev;
@@ -833,55 +851,52 @@ static int ti_ioctl(struct usb_serial_port *port, struct file *file,
return -ENODEV;
switch (cmd) {
- case TIOCGSERIAL:
- dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
- return ti_get_serial_info(tport, (struct serial_struct __user *)arg);
- break;
-
- case TIOCSSERIAL:
- dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
- return ti_set_serial_info(tport, (struct serial_struct __user *)arg);
- break;
-
- case TIOCMIWAIT:
- dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
- cprev = tport->tp_icount;
- while (1) {
- interruptible_sleep_on(&tport->tp_msr_wait);
- if (signal_pending(current))
- return -ERESTARTSYS;
- cnow = tport->tp_icount;
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
- return 0;
- }
- cprev = cnow;
- }
- break;
-
- case TIOCGICOUNT:
- dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, port->number, tport->tp_icount.rx, tport->tp_icount.tx);
- if (copy_to_user((void __user *)arg, &tport->tp_icount, sizeof(tport->tp_icount)))
- return -EFAULT;
- return 0;
+ case TIOCGSERIAL:
+ dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
+ return ti_get_serial_info(tport,
+ (struct serial_struct __user *)arg);
+ case TIOCSSERIAL:
+ dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
+ return ti_set_serial_info(tport,
+ (struct serial_struct __user *)arg);
+ case TIOCMIWAIT:
+ dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
+ cprev = tport->tp_icount;
+ while (1) {
+ interruptible_sleep_on(&tport->tp_msr_wait);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ cnow = tport->tp_icount;
+ if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+ cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+ return -EIO; /* no change => error */
+ if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+ ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)))
+ return 0;
+ cprev = cnow;
+ }
+ break;
+ case TIOCGICOUNT:
+ dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d",
+ __func__, port->number,
+ tport->tp_icount.rx, tport->tp_icount.tx);
+ if (copy_to_user((void __user *)arg, &tport->tp_icount,
+ sizeof(tport->tp_icount)))
+ return -EFAULT;
+ return 0;
}
-
return -ENOIOCTLCMD;
}
-static void ti_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void ti_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct ti_port *tport = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
struct ti_uart_config *config;
- tcflag_t cflag,iflag;
+ tcflag_t cflag, iflag;
int baud;
int status;
int port_number = port->number - port->serial->minor;
@@ -893,7 +908,8 @@ static void ti_set_termios(struct usb_serial_port *port,
iflag = tty->termios->c_iflag;
dbg("%s - cflag %08x, iflag %08x", __func__, cflag, iflag);
- dbg("%s - old clfag %08x, old iflag %08x", __func__, old_termios->c_cflag, old_termios->c_iflag);
+ dbg("%s - old clfag %08x, old iflag %08x", __func__,
+ old_termios->c_cflag, old_termios->c_iflag);
if (tport == NULL)
return;
@@ -912,19 +928,19 @@ static void ti_set_termios(struct usb_serial_port *port,
config->bUartMode = (__u8)(tport->tp_uart_mode);
switch (cflag & CSIZE) {
- case CS5:
- config->bDataBits = TI_UART_5_DATA_BITS;
- break;
- case CS6:
- config->bDataBits = TI_UART_6_DATA_BITS;
- break;
- case CS7:
- config->bDataBits = TI_UART_7_DATA_BITS;
- break;
- default:
- case CS8:
- config->bDataBits = TI_UART_8_DATA_BITS;
- break;
+ case CS5:
+ config->bDataBits = TI_UART_5_DATA_BITS;
+ break;
+ case CS6:
+ config->bDataBits = TI_UART_6_DATA_BITS;
+ break;
+ case CS7:
+ config->bDataBits = TI_UART_7_DATA_BITS;
+ break;
+ default:
+ case CS8:
+ config->bDataBits = TI_UART_8_DATA_BITS;
+ break;
}
/* CMSPAR isn't supported by this driver */
@@ -940,7 +956,7 @@ static void ti_set_termios(struct usb_serial_port *port,
}
} else {
config->wFlags &= ~TI_UART_ENABLE_PARITY_CHECKING;
- config->bParity = TI_UART_NO_PARITY;
+ config->bParity = TI_UART_NO_PARITY;
}
if (cflag & CSTOPB)
@@ -993,7 +1009,8 @@ static void ti_set_termios(struct usb_serial_port *port,
(__u8)(TI_UART1_PORT + port_number), 0, (__u8 *)config,
sizeof(*config));
if (status)
- dev_err(&port->dev, "%s - cannot set config on port %d, %d\n", __func__, port_number, status);
+ dev_err(&port->dev, "%s - cannot set config on port %d, %d\n",
+ __func__, port_number, status);
/* SET_CONFIG asserts RTS and DTR, reset them correctly */
mcr = tport->tp_shadow_mcr;
@@ -1002,14 +1019,17 @@ static void ti_set_termios(struct usb_serial_port *port,
mcr &= ~(TI_MCR_DTR | TI_MCR_RTS);
status = ti_set_mcr(tport, mcr);
if (status)
- dev_err(&port->dev, "%s - cannot set modem control on port %d, %d\n", __func__, port_number, status);
+ dev_err(&port->dev,
+ "%s - cannot set modem control on port %d, %d\n",
+ __func__, port_number, status);
kfree(config);
}
-static int ti_tiocmget(struct usb_serial_port *port, struct file *file)
+static int ti_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
unsigned int result;
unsigned int msr;
@@ -1040,9 +1060,10 @@ static int ti_tiocmget(struct usb_serial_port *port, struct file *file)
}
-static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
+static int ti_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
unsigned int mcr;
unsigned long flags;
@@ -1074,8 +1095,9 @@ static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
}
-static void ti_break(struct usb_serial_port *port, int break_state)
+static void ti_break(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
int status;
@@ -1141,10 +1163,12 @@ static void ti_interrupt_callback(struct urb *urb)
port_number = TI_GET_PORT_FROM_CODE(data[0]);
function = TI_GET_FUNC_FROM_CODE(data[0]);
- dbg("%s - port_number %d, function %d, data 0x%02X", __func__, port_number, function, data[1]);
+ dbg("%s - port_number %d, function %d, data 0x%02X",
+ __func__, port_number, function, data[1]);
if (port_number >= serial->num_ports) {
- dev_err(dev, "%s - bad port number, %d\n", __func__, port_number);
+ dev_err(dev, "%s - bad port number, %d\n",
+ __func__, port_number);
goto exit;
}
@@ -1156,7 +1180,8 @@ static void ti_interrupt_callback(struct urb *urb)
switch (function) {
case TI_CODE_DATA_ERROR:
- dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n", __func__, port_number, data[1]);
+ dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n",
+ __func__, port_number, data[1]);
break;
case TI_CODE_MODEM_STATUS:
@@ -1166,7 +1191,8 @@ static void ti_interrupt_callback(struct urb *urb)
break;
default:
- dev_err(dev, "%s - unknown interrupt code, 0x%02X\n", __func__, data[1]);
+ dev_err(dev, "%s - unknown interrupt code, 0x%02X\n",
+ __func__, data[1]);
break;
}
@@ -1200,7 +1226,7 @@ static void ti_bulk_in_callback(struct urb *urb)
return;
default:
dev_err(dev, "%s - nonzero urb status, %d\n",
- __func__, status );
+ __func__, status);
tport->tp_tdev->td_urb_error = 1;
wake_up_interruptible(&tport->tp_write_wait);
}
@@ -1213,15 +1239,16 @@ static void ti_bulk_in_callback(struct urb *urb)
return;
}
- if (port->tty && urb->actual_length) {
+ if (port->port.tty && urb->actual_length) {
usb_serial_debug_data(debug, dev, __func__,
urb->actual_length, urb->transfer_buffer);
if (!tport->tp_is_open)
dbg("%s - port closed, dropping data", __func__);
else
- ti_recv(&urb->dev->dev, port->tty, urb->transfer_buffer,
- urb->actual_length);
+ ti_recv(&urb->dev->dev, port->port.tty,
+ urb->transfer_buffer,
+ urb->actual_length);
spin_lock(&tport->tp_lock);
tport->tp_icount.rx += urb->actual_length;
@@ -1285,8 +1312,9 @@ static void ti_recv(struct device *dev, struct tty_struct *tty,
do {
cnt = tty_buffer_request_room(tty, length);
if (cnt < length) {
- dev_err(dev, "%s - dropping data, %d bytes lost\n", __func__, length - cnt);
- if(cnt == 0)
+ dev_err(dev, "%s - dropping data, %d bytes lost\n",
+ __func__, length - cnt);
+ if (cnt == 0)
break;
}
tty_insert_flip_string(tty, data, cnt);
@@ -1302,7 +1330,7 @@ static void ti_send(struct ti_port *tport)
{
int count, result;
struct usb_serial_port *port = tport->tp_port;
- struct tty_struct *tty = port->tty;
+ struct tty_struct *tty = port->port.tty; /* FIXME */
unsigned long flags;
@@ -1328,7 +1356,8 @@ static void ti_send(struct ti_port *tport)
spin_unlock_irqrestore(&tport->tp_lock, flags);
- usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
+ usb_serial_debug_data(debug, &port->dev, __func__, count,
+ port->write_urb->transfer_buffer);
usb_fill_bulk_urb(port->write_urb, port->serial->dev,
usb_sndbulkpipe(port->serial->dev,
@@ -1338,8 +1367,9 @@ static void ti_send(struct ti_port *tport)
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev, "%s - submit write urb failed, %d\n", __func__, result);
- tport->tp_write_urb_in_use = 0;
+ dev_err(&port->dev, "%s - submit write urb failed, %d\n",
+ __func__, result);
+ tport->tp_write_urb_in_use = 0;
/* TODO: reschedule ti_send */
} else {
spin_lock_irqsave(&tport->tp_lock, flags);
@@ -1374,7 +1404,7 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr)
static int ti_get_lsr(struct ti_port *tport)
{
- int size,status;
+ int size, status;
struct ti_device *tdev = tport->tp_tdev;
struct usb_serial_port *port = tport->tp_port;
int port_number = port->number - port->serial->minor;
@@ -1392,7 +1422,9 @@ static int ti_get_lsr(struct ti_port *tport)
status = ti_command_in_sync(tdev, TI_GET_PORT_STATUS,
(__u8)(TI_UART1_PORT+port_number), 0, (__u8 *)data, size);
if (status) {
- dev_err(&port->dev, "%s - get port status command failed, %d\n", __func__, status);
+ dev_err(&port->dev,
+ "%s - get port status command failed, %d\n",
+ __func__, status);
goto free_data;
}
@@ -1442,8 +1474,9 @@ static int ti_set_serial_info(struct ti_port *tport,
return -EFAULT;
tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS;
- if (port->tty)
- port->tty->low_latency =
+ /* FIXME */
+ if (port->port.tty)
+ port->port.tty->low_latency =
(tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
tport->tp_closing_wait = new_serial.closing_wait;
@@ -1477,7 +1510,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
tport->tp_msr = msr & TI_MSR_MASK;
/* handle CTS flow control */
- tty = tport->tp_port->tty;
+ tty = tport->tp_port->port.tty;
if (tty && C_CRTSCTS(tty)) {
if (msr & TI_MSR_CTS) {
tty->hw_stopped = 0;
@@ -1627,7 +1660,8 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
struct ti_write_data_bytes *data;
struct device *dev = &tdev->td_serial->dev->dev;
- dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X", __func__, addr, mask, byte);
+ dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X",
+ __func__, addr, mask, byte);
size = sizeof(struct ti_write_data_bytes) + 2;
data = kmalloc(size, GFP_KERNEL);
@@ -1655,67 +1689,68 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
return status;
}
-
-static int ti_download_firmware(struct ti_device *tdev,
- char *fw_name)
+static int ti_do_download(struct usb_device *dev, int pipe,
+ u8 *buffer, int size)
{
- const struct firmware *fw;
- int status = 0;
- int buffer_size;
int pos;
- int len;
+ u8 cs = 0;
int done;
- __u8 cs = 0;
- __u8 *buffer;
- struct usb_device *dev = tdev->td_serial->dev;
struct ti_firmware_header *header;
- unsigned int pipe = usb_sndbulkpipe(dev,
- tdev->td_serial->port[0]->bulk_out_endpointAddress);
-
- buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header);
-
- if (request_firmware(&fw, fw_name, &dev->dev)) {
- dev_err(&dev->dev, "%s - failed to load firmware \"%s\"\n",
- __func__, fw_name);
- return -ENOENT;
- }
- if (fw->size > buffer_size) {
- dev_err(&dev->dev, "%s - firmware \"%s\" is too large\n",
- __func__, fw_name);
- release_firmware(fw);
- return -EINVAL;
- }
-
- buffer = kmalloc(buffer_size, GFP_KERNEL);
- if (!buffer) {
- dev_err(&dev->dev, "%s - out of memory\n", __func__);
- release_firmware(fw);
- return -ENOMEM;
- }
-
- memcpy(buffer, fw->data, fw->size);
- memset(buffer+fw->size, 0xff, buffer_size-fw->size);
+ int status;
+ int len;
- for(pos = sizeof(struct ti_firmware_header); pos < buffer_size; pos++)
+ for (pos = sizeof(struct ti_firmware_header); pos < size; pos++)
cs = (__u8)(cs + buffer[pos]);
header = (struct ti_firmware_header *)buffer;
- header->wLength = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_firmware_header)));
+ header->wLength = cpu_to_le16((__u16)(size
+ - sizeof(struct ti_firmware_header)));
header->bCheckSum = cs;
dbg("%s - downloading firmware", __func__);
- for (pos = 0; pos < buffer_size; pos += done) {
- len = min(buffer_size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE);
- status = usb_bulk_msg(dev, pipe, buffer+pos, len, &done, 1000);
+ for (pos = 0; pos < size; pos += done) {
+ len = min(size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE);
+ status = usb_bulk_msg(dev, pipe, buffer + pos, len,
+ &done, 1000);
if (status)
break;
}
+ return status;
+}
- kfree(buffer);
- release_firmware(fw);
+static int ti_download_firmware(struct ti_device *tdev, int type)
+{
+ int status = -ENOMEM;
+ int buffer_size;
+ __u8 *buffer;
+ struct usb_device *dev = tdev->td_serial->dev;
+ unsigned int pipe = usb_sndbulkpipe(dev,
+ tdev->td_serial->port[0]->bulk_out_endpointAddress);
+ const struct firmware *fw_p;
+ char buf[32];
+ sprintf(buf, "ti_usb-%d.bin", type);
+ if (request_firmware(&fw_p, buf, &dev->dev)) {
+ dev_err(&dev->dev, "%s - firmware not found\n", __func__);
+ return -ENOENT;
+ }
+ if (fw_p->size > TI_FIRMWARE_BUF_SIZE) {
+ dev_err(&dev->dev, "%s - firmware too large\n", __func__);
+ return -ENOENT;
+ }
+
+ buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header);
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (buffer) {
+ memcpy(buffer, fw_p->data, fw_p->size);
+ memset(buffer + fw_p->size, 0xff, buffer_size - fw_p->size);
+ ti_do_download(dev, pipe, buffer, fw_p->size);
+ kfree(buffer);
+ }
+ release_firmware(fw_p);
if (status) {
- dev_err(&dev->dev, "%s - error downloading firmware, %d\n", __func__, status);
+ dev_err(&dev->dev, "%s - error downloading firmware, %d\n",
+ __func__, status);
return status;
}
@@ -1787,7 +1822,7 @@ static void ti_buf_clear(struct circ_buf *cb)
static int ti_buf_data_avail(struct circ_buf *cb)
{
- return CIRC_CNT(cb->head,cb->tail,TI_WRITE_BUF_SIZE);
+ return CIRC_CNT(cb->head, cb->tail, TI_WRITE_BUF_SIZE);
}
@@ -1800,7 +1835,7 @@ static int ti_buf_data_avail(struct circ_buf *cb)
static int ti_buf_space_avail(struct circ_buf *cb)
{
- return CIRC_SPACE(cb->head,cb->tail,TI_WRITE_BUF_SIZE);
+ return CIRC_SPACE(cb->head, cb->tail, TI_WRITE_BUF_SIZE);
}
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 35379863190..8c2d531eede 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -12,7 +12,8 @@
* This driver was originally based on the ACM driver by Armin Fuerst (which was
* based on a driver by Brad Keryan)
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
*/
@@ -28,7 +29,7 @@
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/list.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include "pl2303.h"
@@ -59,7 +60,8 @@ static struct usb_driver usb_serial_driver = {
*/
static int debug;
-static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
+/* initially all NULL */
+static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
static DEFINE_MUTEX(table_lock);
static LIST_HEAD(usb_serial_driver_list);
@@ -76,7 +78,8 @@ struct usb_serial *usb_serial_get_by_index(unsigned index)
return serial;
}
-static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_ports, unsigned int *minor)
+static struct usb_serial *get_free_serial(struct usb_serial *serial,
+ int num_ports, unsigned int *minor)
{
unsigned int i, j;
int good_spot;
@@ -122,9 +125,8 @@ static void return_serial(struct usb_serial *serial)
if (serial == NULL)
return;
- for (i = 0; i < serial->num_ports; ++i) {
+ for (i = 0; i < serial->num_ports; ++i)
serial_table[serial->minor + i] = NULL;
- }
}
static void destroy_serial(struct kref *kref)
@@ -143,7 +145,7 @@ static void destroy_serial(struct kref *kref)
return_serial(serial);
for (i = 0; i < serial->num_ports; ++i)
- serial->port[i]->open_count = 0;
+ serial->port[i]->port.count = 0;
/* the ports are cleaned up and released in port_release() */
for (i = 0; i < serial->num_ports; ++i)
@@ -156,7 +158,8 @@ static void destroy_serial(struct kref *kref)
* not get cleaned up in port_release() as it was never registered with
* the driver core */
if (serial->num_ports < serial->num_port_pointers) {
- for (i = serial->num_ports; i < serial->num_port_pointers; ++i) {
+ for (i = serial->num_ports;
+ i < serial->num_port_pointers; ++i) {
port = serial->port[i];
if (!port)
continue;
@@ -167,7 +170,7 @@ static void destroy_serial(struct kref *kref)
usb_put_dev(serial->dev);
/* free up any memory that we allocated */
- kfree (serial);
+ kfree(serial);
}
void usb_serial_put(struct usb_serial *serial)
@@ -180,13 +183,13 @@ void usb_serial_put(struct usb_serial *serial)
/*****************************************************************************
* Driver tty interface functions
*****************************************************************************/
-static int serial_open (struct tty_struct *tty, struct file * filp)
+static int serial_open (struct tty_struct *tty, struct file *filp)
{
struct usb_serial *serial;
struct usb_serial_port *port;
unsigned int portNumber;
int retval;
-
+
dbg("%s", __func__);
/* get the serial object associated with this tty pointer */
@@ -207,15 +210,15 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
retval = -ERESTARTSYS;
goto bailout_kref_put;
}
-
- ++port->open_count;
+
+ ++port->port.count;
/* set up our port structure making the tty driver
* remember our port object, and us it */
tty->driver_data = port;
- port->tty = tty;
+ port->port.tty = tty;
- if (port->open_count == 1) {
+ if (port->port.count == 1) {
/* lock this module before we call it
* this may fail, which means we must bail out,
@@ -228,9 +231,9 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
retval = usb_autopm_get_interface(serial->interface);
if (retval)
goto bailout_module_put;
- /* only call the device specific open if this
+ /* only call the device specific open if this
* is the first time the port is opened */
- retval = serial->type->open(port, filp);
+ retval = serial->type->open(tty, port, filp);
if (retval)
goto bailout_interface_put;
}
@@ -243,16 +246,16 @@ bailout_interface_put:
bailout_module_put:
module_put(serial->type->driver.owner);
bailout_mutex_unlock:
- port->open_count = 0;
+ port->port.count = 0;
tty->driver_data = NULL;
- port->tty = NULL;
+ port->port.tty = NULL;
mutex_unlock(&port->mutex);
bailout_kref_put:
usb_serial_put(serial);
return retval;
}
-static void serial_close(struct tty_struct *tty, struct file * filp)
+static void serial_close(struct tty_struct *tty, struct file *filp)
{
struct usb_serial_port *port = tty->driver_data;
@@ -263,26 +266,26 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
mutex_lock(&port->mutex);
- if (port->open_count == 0) {
+ if (port->port.count == 0) {
mutex_unlock(&port->mutex);
return;
}
- --port->open_count;
- if (port->open_count == 0)
- /* only call the device specific close if this
+ --port->port.count;
+ if (port->port.count == 0)
+ /* only call the device specific close if this
* port is being closed by the last owner */
- port->serial->type->close(port, filp);
+ port->serial->type->close(tty, port, filp);
- if (port->open_count == (port->console? 1 : 0)) {
- if (port->tty) {
- if (port->tty->driver_data)
- port->tty->driver_data = NULL;
- port->tty = NULL;
+ if (port->port.count == (port->console? 1 : 0)) {
+ if (port->port.tty) {
+ if (port->port.tty->driver_data)
+ port->port.tty->driver_data = NULL;
+ port->port.tty = NULL;
}
}
- if (port->open_count == 0) {
+ if (port->port.count == 0) {
mutex_lock(&port->serial->disc_mutex);
if (!port->serial->disconnected)
usb_autopm_put_interface(port->serial->interface);
@@ -294,7 +297,8 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
usb_serial_put(port->serial);
}
-static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
+static int serial_write(struct tty_struct *tty, const unsigned char *buf,
+ int count)
{
struct usb_serial_port *port = tty->driver_data;
int retval = -ENODEV;
@@ -304,107 +308,112 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int
dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
- /* open_count is managed under the mutex lock for the tty so cannot
- drop to zero until after the last close completes */
- WARN_ON(!port->open_count);
+ /* count is managed under the mutex lock for the tty so cannot
+ drop to zero until after the last close completes */
+ WARN_ON(!port->port.count);
/* pass on to the driver specific version of this function */
- retval = port->serial->type->write(port, buf, count);
+ retval = port->serial->type->write(tty, port, buf, count);
exit:
return retval;
}
-static int serial_write_room (struct tty_struct *tty)
+static int serial_write_room(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
- WARN_ON(!port->open_count);
+ WARN_ON(!port->port.count);
/* pass on to the driver specific version of this function */
- return port->serial->type->write_room(port);
+ return port->serial->type->write_room(tty);
}
-static int serial_chars_in_buffer (struct tty_struct *tty)
+static int serial_chars_in_buffer(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s = port %d", __func__, port->number);
- WARN_ON(!port->open_count);
+ WARN_ON(!port->port.count);
/* pass on to the driver specific version of this function */
- return port->serial->type->chars_in_buffer(port);
+ return port->serial->type->chars_in_buffer(tty);
}
-static void serial_throttle (struct tty_struct * tty)
+static void serial_throttle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
- WARN_ON(!port->open_count);
+ WARN_ON(!port->port.count);
/* pass on to the driver specific version of this function */
if (port->serial->type->throttle)
- port->serial->type->throttle(port);
+ port->serial->type->throttle(tty);
}
-static void serial_unthrottle (struct tty_struct * tty)
+static void serial_unthrottle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
- WARN_ON(!port->open_count);
+ WARN_ON(!port->port.count);
/* pass on to the driver specific version of this function */
if (port->serial->type->unthrottle)
- port->serial->type->unthrottle(port);
+ port->serial->type->unthrottle(tty);
}
-static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
+static int serial_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
int retval = -ENODEV;
dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
- WARN_ON(!port->open_count);
+ WARN_ON(!port->port.count);
- /* pass on to the driver specific version of this function if it is available */
+ /* pass on to the driver specific version of this function
+ if it is available */
if (port->serial->type->ioctl) {
lock_kernel();
- retval = port->serial->type->ioctl(port, file, cmd, arg);
+ retval = port->serial->type->ioctl(tty, file, cmd, arg);
unlock_kernel();
- }
- else
+ } else
retval = -ENOIOCTLCMD;
return retval;
}
-static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
+static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
- WARN_ON(!port->open_count);
- /* pass on to the driver specific version of this function if it is available */
+ WARN_ON(!port->port.count);
+ /* pass on to the driver specific version of this function
+ if it is available */
if (port->serial->type->set_termios)
- port->serial->type->set_termios(port, old);
+ port->serial->type->set_termios(tty, port, old);
else
tty_termios_copy_hw(tty->termios, old);
}
-static void serial_break (struct tty_struct *tty, int break_state)
+static int serial_break(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
- WARN_ON(!port->open_count);
- /* pass on to the driver specific version of this function if it is available */
+ WARN_ON(!port->port.count);
+ /* pass on to the driver specific version of this function
+ if it is available */
if (port->serial->type->break_ctl) {
lock_kernel();
- port->serial->type->break_ctl(port, break_state);
+ port->serial->type->break_ctl(tty, break_state);
unlock_kernel();
}
+ return 0;
}
-static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
+static int serial_read_proc(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
{
struct usb_serial *serial;
int length = 0;
@@ -413,26 +422,29 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int
char tmp[40];
dbg("%s", __func__);
- length += sprintf (page, "usbserinfo:1.0 driver:2.0\n");
+ length += sprintf(page, "usbserinfo:1.0 driver:2.0\n");
for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
serial = usb_serial_get_by_index(i);
if (serial == NULL)
continue;
- length += sprintf (page+length, "%d:", i);
+ length += sprintf(page+length, "%d:", i);
if (serial->type->driver.owner)
- length += sprintf (page+length, " module:%s", module_name(serial->type->driver.owner));
- length += sprintf (page+length, " name:\"%s\"", serial->type->description);
- length += sprintf (page+length, " vendor:%04x product:%04x",
- le16_to_cpu(serial->dev->descriptor.idVendor),
- le16_to_cpu(serial->dev->descriptor.idProduct));
- length += sprintf (page+length, " num_ports:%d", serial->num_ports);
- length += sprintf (page+length, " port:%d", i - serial->minor + 1);
-
+ length += sprintf(page+length, " module:%s",
+ module_name(serial->type->driver.owner));
+ length += sprintf(page+length, " name:\"%s\"",
+ serial->type->description);
+ length += sprintf(page+length, " vendor:%04x product:%04x",
+ le16_to_cpu(serial->dev->descriptor.idVendor),
+ le16_to_cpu(serial->dev->descriptor.idProduct));
+ length += sprintf(page+length, " num_ports:%d",
+ serial->num_ports);
+ length += sprintf(page+length, " port:%d",
+ i - serial->minor + 1);
usb_make_path(serial->dev, tmp, sizeof(tmp));
- length += sprintf (page+length, " path:%s", tmp);
-
- length += sprintf (page+length, "\n");
+ length += sprintf(page+length, " path:%s", tmp);
+
+ length += sprintf(page+length, "\n");
if ((length + begin) > (off + count)) {
usb_serial_put(serial);
goto done;
@@ -448,31 +460,31 @@ done:
if (off >= (length + begin))
return 0;
*start = page + (off-begin);
- return ((count < begin+length-off) ? count : begin+length-off);
+ return (count < begin+length-off) ? count : begin+length-off;
}
-static int serial_tiocmget (struct tty_struct *tty, struct file *file)
+static int serial_tiocmget(struct tty_struct *tty, struct file *file)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
- WARN_ON(!port->open_count);
+ WARN_ON(!port->port.count);
if (port->serial->type->tiocmget)
- return port->serial->type->tiocmget(port, file);
+ return port->serial->type->tiocmget(tty, file);
return -EINVAL;
}
-static int serial_tiocmset (struct tty_struct *tty, struct file *file,
+static int serial_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
- WARN_ON(!port->open_count);
+ WARN_ON(!port->port.count);
if (port->serial->type->tiocmset)
- return port->serial->type->tiocmset(port, file, set, clear);
+ return port->serial->type->tiocmset(tty, file, set, clear);
return -EINVAL;
}
@@ -485,6 +497,7 @@ void usb_serial_port_softint(struct usb_serial_port *port)
{
schedule_work(&port->work);
}
+EXPORT_SYMBOL_GPL(usb_serial_port_softint);
static void usb_serial_port_work(struct work_struct *work)
{
@@ -493,11 +506,11 @@ static void usb_serial_port_work(struct work_struct *work)
struct tty_struct *tty;
dbg("%s - port %d", __func__, port->number);
-
+
if (!port)
return;
- tty = port->tty;
+ tty = port->port.tty;
if (!tty)
return;
@@ -546,9 +559,9 @@ static void port_free(struct usb_serial_port *port)
kfree(port);
}
-static struct usb_serial * create_serial (struct usb_device *dev,
- struct usb_interface *interface,
- struct usb_serial_driver *driver)
+static struct usb_serial *create_serial(struct usb_device *dev,
+ struct usb_interface *interface,
+ struct usb_serial_driver *driver)
{
struct usb_serial *serial;
@@ -567,7 +580,7 @@ static struct usb_serial * create_serial (struct usb_device *dev,
}
static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
- struct usb_serial_driver *drv)
+ struct usb_serial_driver *drv)
{
struct usb_dynid *dynid;
@@ -599,7 +612,8 @@ exit:
return id;
}
-static struct usb_serial_driver *search_serial_device(struct usb_interface *iface)
+static struct usb_serial_driver *search_serial_device(
+ struct usb_interface *iface)
{
const struct usb_device_id *id;
struct usb_serial_driver *drv;
@@ -617,7 +631,7 @@ static struct usb_serial_driver *search_serial_device(struct usb_interface *ifac
int usb_serial_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
- struct usb_device *dev = interface_to_usbdev (interface);
+ struct usb_device *dev = interface_to_usbdev(interface);
struct usb_serial *serial = NULL;
struct usb_serial_port *port;
struct usb_host_interface *iface_desc;
@@ -646,7 +660,7 @@ int usb_serial_probe(struct usb_interface *interface,
return -ENODEV;
}
- serial = create_serial (dev, interface, type);
+ serial = create_serial(dev, interface, type);
if (!serial) {
unlock_kernel();
dev_err(&interface->dev, "%s - out of memory\n", __func__);
@@ -659,8 +673,9 @@ int usb_serial_probe(struct usb_interface *interface,
if (!try_module_get(type->driver.owner)) {
unlock_kernel();
- dev_err(&interface->dev, "module get failed, exiting\n");
- kfree (serial);
+ dev_err(&interface->dev,
+ "module get failed, exiting\n");
+ kfree(serial);
return -EIO;
}
@@ -670,8 +685,8 @@ int usb_serial_probe(struct usb_interface *interface,
if (retval) {
unlock_kernel();
- dbg ("sub driver rejected device");
- kfree (serial);
+ dbg("sub driver rejected device");
+ kfree(serial);
return retval;
}
}
@@ -712,7 +727,7 @@ int usb_serial_probe(struct usb_interface *interface,
}
#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
- /* BEGIN HORRIBLE HACK FOR PL2303 */
+ /* BEGIN HORRIBLE HACK FOR PL2303 */
/* this is needed due to the looney way its endpoints are set up */
if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
(le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
@@ -741,7 +756,7 @@ int usb_serial_probe(struct usb_interface *interface,
if (num_bulk_in == 0 || num_bulk_out == 0) {
unlock_kernel();
dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
- kfree (serial);
+ kfree(serial);
return -ENODEV;
}
}
@@ -753,8 +768,9 @@ int usb_serial_probe(struct usb_interface *interface,
num_ports = num_bulk_out;
if (num_ports == 0) {
unlock_kernel();
- dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n");
- kfree (serial);
+ dev_err(&interface->dev,
+ "Generic device with no bulk out, not allowed.\n");
+ kfree(serial);
return -EIO;
}
}
@@ -764,11 +780,12 @@ int usb_serial_probe(struct usb_interface *interface,
if (type->calc_num_ports) {
if (!try_module_get(type->driver.owner)) {
unlock_kernel();
- dev_err(&interface->dev, "module get failed, exiting\n");
- kfree (serial);
+ dev_err(&interface->dev,
+ "module get failed, exiting\n");
+ kfree(serial);
return -EIO;
}
- num_ports = type->calc_num_ports (serial);
+ num_ports = type->calc_num_ports(serial);
module_put(type->driver.owner);
}
if (!num_ports)
@@ -786,7 +803,8 @@ int usb_serial_probe(struct usb_interface *interface,
type->description);
/* create our ports, we need as many as the max endpoints */
- /* we don't use num_ports here cauz some devices have more endpoint pairs than ports */
+ /* we don't use num_ports here because some devices have more
+ endpoint pairs than ports */
max_endpoints = max(num_bulk_in, num_bulk_out);
max_endpoints = max(max_endpoints, num_interrupt_in);
max_endpoints = max(max_endpoints, num_interrupt_out);
@@ -794,7 +812,8 @@ int usb_serial_probe(struct usb_interface *interface,
serial->num_port_pointers = max_endpoints;
unlock_kernel();
- dbg("%s - setting up %d port structures for this device", __func__, max_endpoints);
+ dbg("%s - setting up %d port structures for this device",
+ __func__, max_endpoints);
for (i = 0; i < max_endpoints; ++i) {
port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
if (!port)
@@ -810,7 +829,7 @@ int usb_serial_probe(struct usb_interface *interface,
for (i = 0; i < num_bulk_in; ++i) {
endpoint = bulk_in_endpoint[i];
port = serial->port[i];
- port->read_urb = usb_alloc_urb (0, GFP_KERNEL);
+ port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port->read_urb) {
dev_err(&interface->dev, "No free urbs available\n");
goto probe_error;
@@ -818,17 +837,17 @@ int usb_serial_probe(struct usb_interface *interface,
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
port->bulk_in_size = buffer_size;
port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
- port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+ port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!port->bulk_in_buffer) {
- dev_err(&interface->dev, "Couldn't allocate bulk_in_buffer\n");
+ dev_err(&interface->dev,
+ "Couldn't allocate bulk_in_buffer\n");
goto probe_error;
}
- usb_fill_bulk_urb (port->read_urb, dev,
- usb_rcvbulkpipe (dev,
- endpoint->bEndpointAddress),
- port->bulk_in_buffer, buffer_size,
- serial->type->read_bulk_callback,
- port);
+ usb_fill_bulk_urb(port->read_urb, dev,
+ usb_rcvbulkpipe(dev,
+ endpoint->bEndpointAddress),
+ port->bulk_in_buffer, buffer_size,
+ serial->type->read_bulk_callback, port);
}
for (i = 0; i < num_bulk_out; ++i) {
@@ -842,17 +861,17 @@ int usb_serial_probe(struct usb_interface *interface,
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
port->bulk_out_size = buffer_size;
port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
- port->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
+ port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!port->bulk_out_buffer) {
- dev_err(&interface->dev, "Couldn't allocate bulk_out_buffer\n");
+ dev_err(&interface->dev,
+ "Couldn't allocate bulk_out_buffer\n");
goto probe_error;
}
- usb_fill_bulk_urb (port->write_urb, dev,
- usb_sndbulkpipe (dev,
- endpoint->bEndpointAddress),
- port->bulk_out_buffer, buffer_size,
- serial->type->write_bulk_callback,
- port);
+ usb_fill_bulk_urb(port->write_urb, dev,
+ usb_sndbulkpipe(dev,
+ endpoint->bEndpointAddress),
+ port->bulk_out_buffer, buffer_size,
+ serial->type->write_bulk_callback, port);
}
if (serial->type->read_int_callback) {
@@ -861,73 +880,82 @@ int usb_serial_probe(struct usb_interface *interface,
port = serial->port[i];
port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port->interrupt_in_urb) {
- dev_err(&interface->dev, "No free urbs available\n");
+ dev_err(&interface->dev,
+ "No free urbs available\n");
goto probe_error;
}
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
- port->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
- port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+ port->interrupt_in_endpointAddress =
+ endpoint->bEndpointAddress;
+ port->interrupt_in_buffer = kmalloc(buffer_size,
+ GFP_KERNEL);
if (!port->interrupt_in_buffer) {
- dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n");
+ dev_err(&interface->dev,
+ "Couldn't allocate interrupt_in_buffer\n");
goto probe_error;
}
- usb_fill_int_urb (port->interrupt_in_urb, dev,
- usb_rcvintpipe (dev,
- endpoint->bEndpointAddress),
- port->interrupt_in_buffer, buffer_size,
- serial->type->read_int_callback, port,
- endpoint->bInterval);
+ usb_fill_int_urb(port->interrupt_in_urb, dev,
+ usb_rcvintpipe(dev,
+ endpoint->bEndpointAddress),
+ port->interrupt_in_buffer, buffer_size,
+ serial->type->read_int_callback, port,
+ endpoint->bInterval);
}
} else if (num_interrupt_in) {
dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
}
-
+
if (serial->type->write_int_callback) {
for (i = 0; i < num_interrupt_out; ++i) {
endpoint = interrupt_out_endpoint[i];
port = serial->port[i];
port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port->interrupt_out_urb) {
- dev_err(&interface->dev, "No free urbs available\n");
+ dev_err(&interface->dev,
+ "No free urbs available\n");
goto probe_error;
}
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
port->interrupt_out_size = buffer_size;
- port->interrupt_out_endpointAddress = endpoint->bEndpointAddress;
- port->interrupt_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
+ port->interrupt_out_endpointAddress =
+ endpoint->bEndpointAddress;
+ port->interrupt_out_buffer = kmalloc(buffer_size,
+ GFP_KERNEL);
if (!port->interrupt_out_buffer) {
- dev_err(&interface->dev, "Couldn't allocate interrupt_out_buffer\n");
+ dev_err(&interface->dev,
+ "Couldn't allocate interrupt_out_buffer\n");
goto probe_error;
}
- usb_fill_int_urb (port->interrupt_out_urb, dev,
- usb_sndintpipe (dev,
- endpoint->bEndpointAddress),
- port->interrupt_out_buffer, buffer_size,
- serial->type->write_int_callback, port,
- endpoint->bInterval);
+ usb_fill_int_urb(port->interrupt_out_urb, dev,
+ usb_sndintpipe(dev,
+ endpoint->bEndpointAddress),
+ port->interrupt_out_buffer, buffer_size,
+ serial->type->write_int_callback, port,
+ endpoint->bInterval);
}
} else if (num_interrupt_out) {
dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
}
-
+
/* if this device type has an attach function, call it */
if (type->attach) {
if (!try_module_get(type->driver.owner)) {
- dev_err(&interface->dev, "module get failed, exiting\n");
+ dev_err(&interface->dev,
+ "module get failed, exiting\n");
goto probe_error;
}
- retval = type->attach (serial);
+ retval = type->attach(serial);
module_put(type->driver.owner);
if (retval < 0)
goto probe_error;
if (retval > 0) {
- /* quietly accept this device, but don't bind to a serial port
- * as it's about to disappear */
+ /* quietly accept this device, but don't bind to a
+ serial port as it's about to disappear */
goto exit;
}
}
- if (get_free_serial (serial, num_ports, &minor) == NULL) {
+ if (get_free_serial(serial, num_ports, &minor) == NULL) {
dev_err(&interface->dev, "No more free serial devices\n");
goto probe_error;
}
@@ -949,11 +977,11 @@ int usb_serial_probe(struct usb_interface *interface,
"continuing\n");
}
- usb_serial_console_init (debug, minor);
+ usb_serial_console_init(debug, minor);
exit:
/* success */
- usb_set_intfdata (interface, serial);
+ usb_set_intfdata(interface, serial);
return 0;
probe_error:
@@ -989,29 +1017,30 @@ probe_error:
/* free up any memory that we allocated */
for (i = 0; i < serial->num_port_pointers; ++i)
kfree(serial->port[i]);
- kfree (serial);
+ kfree(serial);
return -EIO;
}
+EXPORT_SYMBOL_GPL(usb_serial_probe);
void usb_serial_disconnect(struct usb_interface *interface)
{
int i;
- struct usb_serial *serial = usb_get_intfdata (interface);
+ struct usb_serial *serial = usb_get_intfdata(interface);
struct device *dev = &interface->dev;
struct usb_serial_port *port;
usb_serial_console_disconnect(serial);
- dbg ("%s", __func__);
+ dbg("%s", __func__);
mutex_lock(&serial->disc_mutex);
- usb_set_intfdata (interface, NULL);
+ usb_set_intfdata(interface, NULL);
/* must set a flag, to signal subdrivers */
serial->disconnected = 1;
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
if (port) {
- if (port->tty)
- tty_hangup(port->tty);
+ if (port->port.tty)
+ tty_hangup(port->port.tty);
kill_traffic(port);
}
}
@@ -1021,6 +1050,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
usb_serial_put(serial);
dev_info(dev, "device disconnected\n");
}
+EXPORT_SYMBOL_GPL(usb_serial_disconnect);
int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
{
@@ -1079,9 +1109,8 @@ static int __init usb_serial_init(void)
return -ENOMEM;
/* Initialize our global data */
- for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
+ for (i = 0; i < SERIAL_TTY_MINORS; ++i)
serial_table[i] = NULL;
- }
result = bus_register(&usb_serial_bus_type);
if (result) {
@@ -1096,9 +1125,11 @@ static int __init usb_serial_init(void)
usb_serial_tty_driver->minor_start = 0;
usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
- usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV;
usb_serial_tty_driver->init_termios = tty_std_termios;
- usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
+ | HUPCL | CLOCAL;
usb_serial_tty_driver->init_termios.c_ispeed = 9600;
usb_serial_tty_driver->init_termios.c_ospeed = 9600;
tty_set_operations(usb_serial_tty_driver, &serial_ops);
@@ -1136,7 +1167,7 @@ exit_reg_driver:
bus_unregister(&usb_serial_bus_type);
exit_bus:
- err ("%s - returning with error %d", __func__, result);
+ err("%s - returning with error %d", __func__, result);
put_tty_driver(usb_serial_tty_driver);
return result;
}
@@ -1163,7 +1194,7 @@ module_exit(usb_serial_exit);
if (!type->function) { \
type->function = usb_serial_generic_##function; \
dbg("Had to override the " #function \
- " usb serial operation with the generic one.");\
+ " usb serial operation with the generic one.");\
} \
} while (0)
@@ -1180,8 +1211,9 @@ static void fixup_generic(struct usb_serial_driver *device)
set_to_generic_if_null(device, resume);
}
-int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */
+int usb_serial_register(struct usb_serial_driver *driver)
{
+ /* must be called with BKL held */
int retval;
fixup_generic(driver);
@@ -1194,37 +1226,30 @@ int usb_serial_register(struct usb_serial_driver *driver) /* must be called with
retval = usb_serial_bus_register(driver);
if (retval) {
- err("problem %d when registering driver %s", retval, driver->description);
+ err("problem %d when registering driver %s",
+ retval, driver->description);
list_del(&driver->driver_list);
- }
- else
- info("USB Serial support registered for %s", driver->description);
+ } else
+ info("USB Serial support registered for %s",
+ driver->description);
return retval;
}
+EXPORT_SYMBOL_GPL(usb_serial_register);
-void usb_serial_deregister(struct usb_serial_driver *device) /* must be called with BKL held */
+void usb_serial_deregister(struct usb_serial_driver *device)
{
+ /* must be called with BKL held */
info("USB Serial deregistering driver %s", device->description);
list_del(&device->driver_list);
usb_serial_bus_deregister(device);
}
-
-
-
-/* If the usb-serial core is built into the core, the usb-serial drivers
- need these symbols to load properly as modules. */
-EXPORT_SYMBOL_GPL(usb_serial_register);
EXPORT_SYMBOL_GPL(usb_serial_deregister);
-EXPORT_SYMBOL_GPL(usb_serial_probe);
-EXPORT_SYMBOL_GPL(usb_serial_disconnect);
-EXPORT_SYMBOL_GPL(usb_serial_port_softint);
-
/* Module information */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
index 9ca4d4db1dd..fc5d9952b03 100644
--- a/drivers/usb/serial/usb_debug.c
+++ b/drivers/usb/serial/usb_debug.c
@@ -31,10 +31,11 @@ static struct usb_driver debug_driver = {
.no_dynamic_id = 1,
};
-int usb_debug_open(struct usb_serial_port *port, struct file *filp)
+int usb_debug_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
port->bulk_out_size = USB_DEBUG_MAX_PACKET_SIZE;
- return usb_serial_generic_open(port, filp);
+ return usb_serial_generic_open(tty, port, filp);
}
static struct usb_serial_driver debug_device = {
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 5fc20122145..cf8924f9a2c 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -9,7 +9,8 @@
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
*/
@@ -23,7 +24,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include "visor.h"
@@ -35,25 +36,29 @@
#define DRIVER_DESC "USB HandSpring Visor / Palm OS driver"
/* function prototypes for a handspring visor */
-static int visor_open (struct usb_serial_port *port, struct file *filp);
-static void visor_close (struct usb_serial_port *port, struct file *filp);
-static int visor_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-static int visor_write_room (struct usb_serial_port *port);
-static int visor_chars_in_buffer (struct usb_serial_port *port);
-static void visor_throttle (struct usb_serial_port *port);
-static void visor_unthrottle (struct usb_serial_port *port);
-static int visor_probe (struct usb_serial *serial, const struct usb_device_id *id);
+static int visor_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static void visor_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static int visor_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+static int visor_write_room(struct tty_struct *tty);
+static void visor_throttle(struct tty_struct *tty);
+static void visor_unthrottle(struct tty_struct *tty);
+static int visor_probe(struct usb_serial *serial,
+ const struct usb_device_id *id);
static int visor_calc_num_ports(struct usb_serial *serial);
-static void visor_shutdown (struct usb_serial *serial);
-static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void visor_write_bulk_callback (struct urb *urb);
-static void visor_read_bulk_callback (struct urb *urb);
-static void visor_read_int_callback (struct urb *urb);
-static int clie_3_5_startup (struct usb_serial *serial);
-static int treo_attach (struct usb_serial *serial);
-static int clie_5_attach (struct usb_serial *serial);
-static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id);
-static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id);
+static void visor_shutdown(struct usb_serial *serial);
+static void visor_write_bulk_callback(struct urb *urb);
+static void visor_read_bulk_callback(struct urb *urb);
+static void visor_read_int_callback(struct urb *urb);
+static int clie_3_5_startup(struct usb_serial *serial);
+static int treo_attach(struct usb_serial *serial);
+static int clie_5_attach(struct usb_serial *serial);
+static int palm_os_3_probe(struct usb_serial *serial,
+ const struct usb_device_id *id);
+static int palm_os_4_probe(struct usb_serial *serial,
+ const struct usb_device_id *id);
/* Parameters that may be passed into the module. */
static int debug;
@@ -105,13 +110,13 @@ static struct usb_device_id id_table [] = {
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(ACER_VENDOR_ID, ACER_S10_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
- { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID),
+ { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
- { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID),
+ { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(TAPWAVE_VENDOR_ID, TAPWAVE_ZODIAC_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
- { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID),
+ { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
@@ -170,7 +175,7 @@ static struct usb_device_id id_table_combined [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver visor_driver = {
.name = "visor",
@@ -180,7 +185,8 @@ static struct usb_driver visor_driver = {
.no_dynamic_id = 1,
};
-/* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */
+/* All of the device info needed for the Handspring Visor,
+ and Palm 4.0 devices */
static struct usb_serial_driver handspring_device = {
.driver = {
.owner = THIS_MODULE,
@@ -198,10 +204,8 @@ static struct usb_serial_driver handspring_device = {
.probe = visor_probe,
.calc_num_ports = visor_calc_num_ports,
.shutdown = visor_shutdown,
- .ioctl = visor_ioctl,
.write = visor_write,
.write_room = visor_write_room,
- .chars_in_buffer = visor_chars_in_buffer,
.write_bulk_callback = visor_write_bulk_callback,
.read_bulk_callback = visor_read_bulk_callback,
.read_int_callback = visor_read_int_callback,
@@ -225,10 +229,8 @@ static struct usb_serial_driver clie_5_device = {
.probe = visor_probe,
.calc_num_ports = visor_calc_num_ports,
.shutdown = visor_shutdown,
- .ioctl = visor_ioctl,
.write = visor_write,
.write_room = visor_write_room,
- .chars_in_buffer = visor_chars_in_buffer,
.write_bulk_callback = visor_write_bulk_callback,
.read_bulk_callback = visor_read_bulk_callback,
.read_int_callback = visor_read_int_callback,
@@ -249,10 +251,8 @@ static struct usb_serial_driver clie_3_5_device = {
.throttle = visor_throttle,
.unthrottle = visor_unthrottle,
.attach = clie_3_5_startup,
- .ioctl = visor_ioctl,
.write = visor_write,
.write_room = visor_write_room,
- .chars_in_buffer = visor_chars_in_buffer,
.write_bulk_callback = visor_write_bulk_callback,
.read_bulk_callback = visor_read_bulk_callback,
};
@@ -274,7 +274,8 @@ static int stats;
/******************************************************************************
* Handspring Visor specific driver functions
******************************************************************************/
-static int visor_open (struct usb_serial_port *port, struct file *filp)
+static int visor_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
struct usb_serial *serial = port->serial;
struct visor_private *priv = usb_get_serial_port_data(port);
@@ -300,42 +301,45 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
* through, otherwise it is scheduled, and with high data rates (like
* with OHCI) data can get lost.
*/
- if (port->tty)
- port->tty->low_latency = 1;
+ if (tty)
+ tty->low_latency = 1;
/* Start reading from the device */
- usb_fill_bulk_urb (port->read_urb, serial->dev,
- usb_rcvbulkpipe (serial->dev,
+ usb_fill_bulk_urb(port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
visor_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",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, result);
goto exit;
}
-
+
if (port->interrupt_in_urb) {
dbg("%s - adding interrupt input for treo", __func__);
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result)
- dev_err(&port->dev, "%s - failed submitting interrupt urb, error %d\n",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting interrupt urb, error %d\n",
+ __func__, result);
}
-exit:
+exit:
return result;
}
-static void visor_close (struct usb_serial_port *port, struct file * filp)
+static void visor_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct visor_private *priv = usb_get_serial_port_data(port);
unsigned char *transfer_buffer;
dbg("%s - port %d", __func__, port->number);
-
+
/* shutdown our urbs */
usb_kill_urb(port->read_urb);
usb_kill_urb(port->interrupt_in_urb);
@@ -343,14 +347,14 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
mutex_lock(&port->serial->disc_mutex);
if (!port->serial->disconnected) {
/* Try to send shutdown message, unless the device is gone */
- transfer_buffer = kmalloc (0x12, GFP_KERNEL);
+ transfer_buffer = kmalloc(0x12, GFP_KERNEL);
if (transfer_buffer) {
- usb_control_msg (port->serial->dev,
+ usb_control_msg(port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0),
VISOR_CLOSE_NOTIFICATION, 0xc2,
0x0000, 0x0000,
transfer_buffer, 0x12, 300);
- kfree (transfer_buffer);
+ kfree(transfer_buffer);
}
}
mutex_unlock(&port->serial->disc_mutex);
@@ -361,7 +365,8 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
}
-static int visor_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int visor_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct visor_private *priv = usb_get_serial_port_data(port);
struct usb_serial *serial = port->serial;
@@ -381,7 +386,7 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
priv->outstanding_urbs++;
spin_unlock_irqrestore(&priv->lock, flags);
- buffer = kmalloc (count, GFP_ATOMIC);
+ buffer = kmalloc(count, GFP_ATOMIC);
if (!buffer) {
dev_err(&port->dev, "out of memory\n");
count = -ENOMEM;
@@ -395,21 +400,22 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
goto error_no_urb;
}
- memcpy (buffer, buf, count);
+ memcpy(buffer, buf, count);
usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
- usb_fill_bulk_urb (urb, serial->dev,
- usb_sndbulkpipe (serial->dev,
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_sndbulkpipe(serial->dev,
port->bulk_out_endpointAddress),
- buffer, count,
+ buffer, count,
visor_write_bulk_callback, port);
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
- dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n",
- __func__, status);
+ dev_err(&port->dev,
+ "%s - usb_submit_urb(write bulk) failed with status = %d\n",
+ __func__, status);
count = status;
goto error;
} else {
@@ -435,8 +441,9 @@ error_no_buffer:
}
-static int visor_write_room (struct usb_serial_port *port)
+static int visor_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct visor_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -460,23 +467,7 @@ static int visor_write_room (struct usb_serial_port *port)
}
-static int visor_chars_in_buffer (struct usb_serial_port *port)
-{
- dbg("%s - port %d", __func__, port->number);
-
- /*
- * We can't really account for how much data we
- * have sent out, but hasn't made it through to the
- * device, so just tell the tty layer that everything
- * is flushed.
- *
- * FIXME: Should walk outstanding_urbs
- */
- return 0;
-}
-
-
-static void visor_write_bulk_callback (struct urb *urb)
+static void visor_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct visor_private *priv = usb_get_serial_port_data(port);
@@ -484,7 +475,7 @@ static void visor_write_bulk_callback (struct urb *urb)
unsigned long flags;
/* free up the transfer buffer, as usb_free_urb() does not do this */
- kfree (urb->transfer_buffer);
+ kfree(urb->transfer_buffer);
dbg("%s - port %d", __func__, port->number);
@@ -500,7 +491,7 @@ static void visor_write_bulk_callback (struct urb *urb)
}
-static void visor_read_bulk_callback (struct urb *urb)
+static void visor_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct visor_private *priv = usb_get_serial_port_data(port);
@@ -518,11 +509,13 @@ static void visor_read_bulk_callback (struct urb *urb)
return;
}
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
- available_room = tty_buffer_request_room(tty, urb->actual_length);
+ available_room = tty_buffer_request_room(tty,
+ urb->actual_length);
if (available_room) {
tty_insert_flip_string(tty, data, available_room);
tty_flip_buffer_push(tty);
@@ -536,22 +529,23 @@ static void visor_read_bulk_callback (struct urb *urb)
/* Continue trying to always read if we should */
if (!priv->throttled) {
- usb_fill_bulk_urb (port->read_urb, port->serial->dev,
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
- port->bulk_in_endpointAddress),
+ port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
visor_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
- } else {
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
+ } else
priv->actually_throttled = 1;
- }
spin_unlock(&priv->lock);
}
-static void visor_read_int_callback (struct urb *urb)
+static void visor_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
int status = urb->status;
@@ -585,14 +579,16 @@ static void visor_read_int_callback (struct urb *urb)
urb->actual_length, urb->transfer_buffer);
exit:
- result = usb_submit_urb (urb, GFP_ATOMIC);
+ result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
- dev_err(&urb->dev->dev, "%s - Error %d submitting interrupt urb\n",
- __func__, result);
+ dev_err(&urb->dev->dev,
+ "%s - Error %d submitting interrupt urb\n",
+ __func__, result);
}
-static void visor_throttle (struct usb_serial_port *port)
+static void visor_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct visor_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -603,8 +599,9 @@ static void visor_throttle (struct usb_serial_port *port)
}
-static void visor_unthrottle (struct usb_serial_port *port)
+static void visor_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct visor_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int result;
@@ -618,10 +615,13 @@ static void visor_unthrottle (struct usb_serial_port *port)
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, result);
}
-static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id)
+static int palm_os_3_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
{
struct device *dev = &serial->dev->dev;
struct visor_connection_info *connection_info;
@@ -633,7 +633,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
dbg("%s", __func__);
- transfer_buffer = kmalloc (sizeof (*connection_info), GFP_KERNEL);
+ transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL);
if (!transfer_buffer) {
dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
sizeof(*connection_info));
@@ -641,7 +641,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
}
/* send a get connection info request */
- retval = usb_control_msg (serial->dev,
+ retval = usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
VISOR_GET_CONNECTION_INFORMATION,
0xc2, 0x0000, 0x0000, transfer_buffer,
@@ -653,29 +653,31 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
}
if (retval == sizeof(*connection_info)) {
- connection_info = (struct visor_connection_info *)transfer_buffer;
+ connection_info = (struct visor_connection_info *)
+ transfer_buffer;
num_ports = le16_to_cpu(connection_info->num_ports);
for (i = 0; i < num_ports; ++i) {
- switch (connection_info->connections[i].port_function_id) {
- case VISOR_FUNCTION_GENERIC:
- string = "Generic";
- break;
- case VISOR_FUNCTION_DEBUGGER:
- string = "Debugger";
- break;
- case VISOR_FUNCTION_HOTSYNC:
- string = "HotSync";
- break;
- case VISOR_FUNCTION_CONSOLE:
- string = "Console";
- break;
- case VISOR_FUNCTION_REMOTE_FILE_SYS:
- string = "Remote File System";
- break;
- default:
- string = "unknown";
- break;
+ switch (
+ connection_info->connections[i].port_function_id) {
+ case VISOR_FUNCTION_GENERIC:
+ string = "Generic";
+ break;
+ case VISOR_FUNCTION_DEBUGGER:
+ string = "Debugger";
+ break;
+ case VISOR_FUNCTION_HOTSYNC:
+ string = "HotSync";
+ break;
+ case VISOR_FUNCTION_CONSOLE:
+ string = "Console";
+ break;
+ case VISOR_FUNCTION_REMOTE_FILE_SYS:
+ string = "Remote File System";
+ break;
+ default:
+ string = "unknown";
+ break;
}
dev_info(dev, "%s: port %d, is for %s use\n",
serial->type->description,
@@ -686,11 +688,11 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
* Handle devices that report invalid stuff here.
*/
if (num_ports == 0 || num_ports > 2) {
- dev_warn (dev, "%s: No valid connect info available\n",
+ dev_warn(dev, "%s: No valid connect info available\n",
serial->type->description);
num_ports = 2;
}
-
+
dev_info(dev, "%s: Number of ports: %d\n", serial->type->description,
num_ports);
@@ -700,8 +702,9 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
*/
usb_set_serial_data(serial, (void *)(long)num_ports);
- /* ask for the number of bytes available, but ignore the response as it is broken */
- retval = usb_control_msg (serial->dev,
+ /* ask for the number of bytes available, but ignore the
+ response as it is broken */
+ retval = usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
VISOR_REQUEST_BYTES_AVAILABLE,
0xc2, 0x0000, 0x0005, transfer_buffer,
@@ -712,12 +715,13 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
retval = 0;
exit:
- kfree (transfer_buffer);
+ kfree(transfer_buffer);
return retval;
}
-static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id)
+static int palm_os_4_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
{
struct device *dev = &serial->dev->dev;
struct palm_ext_connection_info *connection_info;
@@ -726,18 +730,18 @@ static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_i
dbg("%s", __func__);
- transfer_buffer = kmalloc (sizeof (*connection_info), GFP_KERNEL);
+ transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL);
if (!transfer_buffer) {
dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
sizeof(*connection_info));
return -ENOMEM;
}
- retval = usb_control_msg (serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
+ retval = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
PALM_GET_EXT_CONNECTION_INFORMATION,
0xc2, 0x0000, 0x0000, transfer_buffer,
- sizeof (*connection_info), 300);
+ sizeof(*connection_info), 300);
if (retval < 0)
dev_err(dev, "%s - error %d getting connection info\n",
__func__, retval);
@@ -745,15 +749,17 @@ static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_i
usb_serial_debug_data(debug, &serial->dev->dev, __func__,
retval, transfer_buffer);
- kfree (transfer_buffer);
+ kfree(transfer_buffer);
return 0;
}
-static int visor_probe (struct usb_serial *serial, const struct usb_device_id *id)
+static int visor_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
{
int retval = 0;
- int (*startup) (struct usb_serial *serial, const struct usb_device_id *id);
+ int (*startup)(struct usb_serial *serial,
+ const struct usb_device_id *id);
dbg("%s", __func__);
@@ -771,7 +777,7 @@ static int visor_probe (struct usb_serial *serial, const struct usb_device_id *i
return retval;
}
-static int visor_calc_num_ports (struct usb_serial *serial)
+static int visor_calc_num_ports(struct usb_serial *serial)
{
int num_ports = (int)(long)(usb_get_serial_data(serial));
@@ -788,7 +794,7 @@ static int generic_startup(struct usb_serial *serial)
int i;
for (i = 0; i < serial->num_ports; ++i) {
- priv = kzalloc (sizeof(*priv), GFP_KERNEL);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
while (i-- != 0) {
priv = usb_get_serial_port_data(ports[i]);
@@ -803,7 +809,7 @@ static int generic_startup(struct usb_serial *serial)
return 0;
}
-static int clie_3_5_startup (struct usb_serial *serial)
+static int clie_3_5_startup(struct usb_serial *serial)
{
struct device *dev = &serial->dev->dev;
int result;
@@ -816,62 +822,72 @@ static int clie_3_5_startup (struct usb_serial *serial)
*/
/* get the config number */
- result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
USB_REQ_GET_CONFIGURATION, USB_DIR_IN,
0, 0, &data, 1, 3000);
if (result < 0) {
- dev_err(dev, "%s: get config number failed: %d\n", __func__, result);
+ dev_err(dev, "%s: get config number failed: %d\n",
+ __func__, result);
return result;
}
if (result != 1) {
- dev_err(dev, "%s: get config number bad return length: %d\n", __func__, result);
+ dev_err(dev, "%s: get config number bad return length: %d\n",
+ __func__, result);
return -EIO;
}
/* get the interface number */
- result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0),
- USB_REQ_GET_INTERFACE,
+ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ USB_REQ_GET_INTERFACE,
USB_DIR_IN | USB_RECIP_INTERFACE,
0, 0, &data, 1, 3000);
if (result < 0) {
- dev_err(dev, "%s: get interface number failed: %d\n", __func__, result);
+ dev_err(dev, "%s: get interface number failed: %d\n",
+ __func__, result);
return result;
}
if (result != 1) {
- dev_err(dev, "%s: get interface number bad return length: %d\n", __func__, result);
+ dev_err(dev,
+ "%s: get interface number bad return length: %d\n",
+ __func__, result);
return -EIO;
}
return generic_startup(serial);
}
-
-static int treo_attach (struct usb_serial *serial)
+
+static int treo_attach(struct usb_serial *serial)
{
struct usb_serial_port *swap_port;
/* Only do this endpoint hack for the Handspring devices with
* interrupt in endpoints, which for now are the Treo devices. */
- if (!((le16_to_cpu(serial->dev->descriptor.idVendor) == HANDSPRING_VENDOR_ID) ||
- (le16_to_cpu(serial->dev->descriptor.idVendor) == KYOCERA_VENDOR_ID)) ||
- (serial->num_interrupt_in == 0))
+ if (!((le16_to_cpu(serial->dev->descriptor.idVendor)
+ == HANDSPRING_VENDOR_ID) ||
+ (le16_to_cpu(serial->dev->descriptor.idVendor)
+ == KYOCERA_VENDOR_ID)) ||
+ (serial->num_interrupt_in == 0))
goto generic_startup;
dbg("%s", __func__);
/*
- * It appears that Treos and Kyoceras want to use the
- * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
- * so let's swap the 1st and 2nd bulk in and interrupt endpoints.
- * Note that swapping the bulk out endpoints would break lots of
+ * It appears that Treos and Kyoceras want to use the
+ * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
+ * so let's swap the 1st and 2nd bulk in and interrupt endpoints.
+ * Note that swapping the bulk out endpoints would break lots of
* apps that want to communicate on the second port.
*/
#define COPY_PORT(dest, src) \
- dest->read_urb = src->read_urb; \
- dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress; \
- dest->bulk_in_buffer = src->bulk_in_buffer; \
- dest->interrupt_in_urb = src->interrupt_in_urb; \
- dest->interrupt_in_endpointAddress = src->interrupt_in_endpointAddress; \
- dest->interrupt_in_buffer = src->interrupt_in_buffer;
+ do { \
+ dest->read_urb = src->read_urb; \
+ dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress;\
+ dest->bulk_in_buffer = src->bulk_in_buffer; \
+ dest->interrupt_in_urb = src->interrupt_in_urb; \
+ dest->interrupt_in_endpointAddress = \
+ src->interrupt_in_endpointAddress;\
+ dest->interrupt_in_buffer = src->interrupt_in_buffer; \
+ } while (0);
swap_port = kmalloc(sizeof(*swap_port), GFP_KERNEL);
if (!swap_port)
@@ -885,28 +901,30 @@ generic_startup:
return generic_startup(serial);
}
-static int clie_5_attach (struct usb_serial *serial)
+static int clie_5_attach(struct usb_serial *serial)
{
dbg("%s", __func__);
- /* TH55 registers 2 ports.
- Communication in from the UX50/TH55 uses bulk_in_endpointAddress from port 0
- Communication out to the UX50/TH55 uses bulk_out_endpointAddress from port 1
-
+ /* TH55 registers 2 ports.
+ Communication in from the UX50/TH55 uses bulk_in_endpointAddress
+ from port 0. Communication out to the UX50/TH55 uses
+ bulk_out_endpointAddress from port 1
+
Lets do a quick and dirty mapping
*/
-
+
/* some sanity check */
if (serial->num_ports < 2)
return -1;
-
+
/* port 0 now uses the modified endpoint Address */
- serial->port[0]->bulk_out_endpointAddress = serial->port[1]->bulk_out_endpointAddress;
+ serial->port[0]->bulk_out_endpointAddress =
+ serial->port[1]->bulk_out_endpointAddress;
return generic_startup(serial);
}
-static void visor_shutdown (struct usb_serial *serial)
+static void visor_shutdown(struct usb_serial *serial)
{
struct visor_private *priv;
int i;
@@ -922,37 +940,35 @@ static void visor_shutdown (struct usb_serial *serial)
}
}
-static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
-{
- dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
-
- return -ENOIOCTLCMD;
-}
-
-static int __init visor_init (void)
+static int __init visor_init(void)
{
int i, retval;
/* Only if parameters were passed to us */
- if ((vendor>0) && (product>0)) {
- struct usb_device_id usb_dev_temp[]=
- {{USB_DEVICE(vendor, product),
- .driver_info = (kernel_ulong_t)&palm_os_4_probe }};
+ if (vendor > 0 && product > 0) {
+ struct usb_device_id usb_dev_temp[] = {
+ {
+ USB_DEVICE(vendor, product),
+ .driver_info =
+ (kernel_ulong_t) &palm_os_4_probe
+ }
+ };
/* Find the last entry in id_table */
- for (i=0; ; i++) {
- if (id_table[i].idVendor==0) {
+ for (i = 0;; i++) {
+ if (id_table[i].idVendor == 0) {
id_table[i] = usb_dev_temp[0];
break;
}
}
/* Find the last entry in id_table_combined */
- for (i=0; ; i++) {
- if (id_table_combined[i].idVendor==0) {
+ for (i = 0;; i++) {
+ if (id_table_combined[i].idVendor == 0) {
id_table_combined[i] = usb_dev_temp[0];
break;
}
}
- info("Untested USB device specified at time of module insertion");
+ info(
+ "Untested USB device specified at time of module insertion");
info("Warning: This is not guaranteed to work");
info("Using a newer kernel is preferred to this method");
info("Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x",
@@ -968,7 +984,7 @@ static int __init visor_init (void)
if (retval)
goto failed_clie_5_register;
retval = usb_register(&visor_driver);
- if (retval)
+ if (retval)
goto failed_usb_register;
info(DRIVER_DESC);
@@ -986,18 +1002,18 @@ failed_handspring_register:
static void __exit visor_exit (void)
{
- usb_deregister (&visor_driver);
- usb_serial_deregister (&handspring_device);
- usb_serial_deregister (&clie_3_5_device);
- usb_serial_deregister (&clie_5_device);
+ usb_deregister(&visor_driver);
+ usb_serial_deregister(&handspring_device);
+ usb_serial_deregister(&clie_3_5_device);
+ usb_serial_deregister(&clie_5_device);
}
module_init(visor_init);
module_exit(visor_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 665aa77a917..3a9d14384a4 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -12,29 +12,31 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
* (10/09/2002) Stuart MacDonald (stuartm@connecttech.com)
* Upgrade to full working driver
*
* (05/30/2001) gkh
- * switched from using spinlock to a semaphore, which fixes lots of problems.
+ * switched from using spinlock to a semaphore, which fixes lots of
+ * problems.
*
* (04/08/2001) gb
* Identify version on module load.
- *
+ *
* 2001_Mar_19 gkh
- * Fixed MOD_INC and MOD_DEC logic, the ability to open a port more
+ * Fixed MOD_INC and MOD_DEC logic, the ability to open a port more
* than once, and the got the proper usb_device_id table entries so
* the driver works again.
*
* (11/01/2000) Adam J. Richter
* usb_device_id table support
- *
+ *
* (10/05/2000) gkh
* Fixed bug with urb->dev not being set properly, now that the usb
* core needs it.
- *
+ *
* (10/03/2000) smd
* firmware is improved to guard against crap sent to device
* firmware now replies CMD_FAILURE on bad things
@@ -52,9 +54,9 @@
* Fixed bug with port->minor that was found by Al Borchers
*
* (07/04/2000) gkh
- * Added support for port settings. Baud rate can now be changed. Line signals
- * are not transferred to and from the tty layer yet, but things seem to be
- * working well now.
+ * Added support for port settings. Baud rate can now be changed. Line
+ * signals are not transferred to and from the tty layer yet, but things
+ * seem to be working well now.
*
* (05/04/2000) gkh
* First cut at open and close commands. Data can flow through the ports at
@@ -62,7 +64,7 @@
*
* (03/26/2000) gkh
* Split driver up into device specific pieces.
- *
+ *
*/
#include <linux/kernel.h>
@@ -75,7 +77,7 @@
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/termbits.h>
#include <linux/usb.h>
#include <linux/serial_reg.h>
@@ -125,7 +127,7 @@ static struct usb_device_id id_table_combined [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver whiteheat_driver = {
.name = "whiteheat",
@@ -136,26 +138,34 @@ static struct usb_driver whiteheat_driver = {
};
/* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */
-static int whiteheat_firmware_download (struct usb_serial *serial, const struct usb_device_id *id);
-static int whiteheat_firmware_attach (struct usb_serial *serial);
+static int whiteheat_firmware_download(struct usb_serial *serial,
+ const struct usb_device_id *id);
+static int whiteheat_firmware_attach(struct usb_serial *serial);
/* function prototypes for the Connect Tech WhiteHEAT serial converter */
-static int whiteheat_attach (struct usb_serial *serial);
-static void whiteheat_shutdown (struct usb_serial *serial);
-static int whiteheat_open (struct usb_serial_port *port, struct file *filp);
-static void whiteheat_close (struct usb_serial_port *port, struct file *filp);
-static int whiteheat_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-static int whiteheat_write_room (struct usb_serial_port *port);
-static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios * old);
-static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file);
-static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
-static void whiteheat_break_ctl (struct usb_serial_port *port, int break_state);
-static int whiteheat_chars_in_buffer (struct usb_serial_port *port);
-static void whiteheat_throttle (struct usb_serial_port *port);
-static void whiteheat_unthrottle (struct usb_serial_port *port);
-static void whiteheat_read_callback (struct urb *urb);
-static void whiteheat_write_callback (struct urb *urb);
+static int whiteheat_attach(struct usb_serial *serial);
+static void whiteheat_shutdown(struct usb_serial *serial);
+static int whiteheat_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void whiteheat_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static int whiteheat_write(struct tty_struct *tty,
+ struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+static int whiteheat_write_room(struct tty_struct *tty);
+static int whiteheat_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static void whiteheat_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
+static int whiteheat_tiocmget(struct tty_struct *tty, struct file *file);
+static int whiteheat_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
+static void whiteheat_break_ctl(struct tty_struct *tty, int break_state);
+static int whiteheat_chars_in_buffer(struct tty_struct *tty);
+static void whiteheat_throttle(struct tty_struct *tty);
+static void whiteheat_unthrottle(struct tty_struct *tty);
+static void whiteheat_read_callback(struct urb *urb);
+static void whiteheat_write_callback(struct urb *urb);
static struct usb_serial_driver whiteheat_fake_device = {
.driver = {
@@ -202,7 +212,9 @@ struct whiteheat_command_private {
struct mutex mutex;
__u8 port_running;
__u8 command_finished;
- wait_queue_head_t wait_command; /* for handling sleeping while waiting for a command to finish */
+ wait_queue_head_t wait_command; /* for handling sleeping whilst
+ waiting for a command to
+ finish */
__u8 result_buffer[64];
};
@@ -239,14 +251,16 @@ static void command_port_write_callback(struct urb *urb);
static void command_port_read_callback(struct urb *urb);
static int start_port_read(struct usb_serial_port *port);
-static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, struct list_head *head);
+static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb,
+ struct list_head *head);
static struct list_head *list_first(struct list_head *head);
static void rx_data_softint(struct work_struct *work);
-static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize);
+static int firm_send_command(struct usb_serial_port *port, __u8 command,
+ __u8 *data, __u8 datasize);
static int firm_open(struct usb_serial_port *port);
static int firm_close(struct usb_serial_port *port);
-static int firm_setup_port(struct usb_serial_port *port);
+static int firm_setup_port(struct tty_struct *tty);
static int firm_set_rts(struct usb_serial_port *port, __u8 onoff);
static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff);
static int firm_set_break(struct usb_serial_port *port, __u8 onoff);
@@ -278,7 +292,8 @@ static int firm_report_tx_done(struct usb_serial_port *port);
- device renumerated itself and comes up as new device id with all
firmware download completed.
*/
-static int whiteheat_firmware_download (struct usb_serial *serial, const struct usb_device_id *id)
+static int whiteheat_firmware_download(struct usb_serial *serial,
+ const struct usb_device_id *id)
{
int response, ret = -ENOENT;
const struct firmware *loader_fw = NULL, *firmware_fw = NULL;
@@ -313,7 +328,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
record = ihex_next_binrec(record);
}
- response = ezusb_set_reset (serial, 0);
+ response = ezusb_set_reset(serial, 0);
record = (const struct ihex_binrec *)firmware_fw->data;
while (record && be32_to_cpu(record->addr) < 0x1b40)
@@ -330,8 +345,8 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
}
++record;
}
-
- response = ezusb_set_reset (serial, 1);
+
+ response = ezusb_set_reset(serial, 1);
record = (const struct ihex_binrec *)firmware_fw->data;
while (record && be32_to_cpu(record->addr) < 0x1b40) {
@@ -355,7 +370,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
}
-static int whiteheat_firmware_attach (struct usb_serial *serial)
+static int whiteheat_firmware_attach(struct usb_serial *serial)
{
/* We want this device to fail to have a driver assigned to it */
return 1;
@@ -365,7 +380,7 @@ static int whiteheat_firmware_attach (struct usb_serial *serial)
/*****************************************************************************
* Connect Tech's White Heat serial driver functions
*****************************************************************************/
-static int whiteheat_attach (struct usb_serial *serial)
+static int whiteheat_attach(struct usb_serial *serial)
{
struct usb_serial_port *command_port;
struct whiteheat_command_private *command_info;
@@ -386,43 +401,52 @@ static int whiteheat_attach (struct usb_serial *serial)
command_port = serial->port[COMMAND_PORT];
- pipe = usb_sndbulkpipe (serial->dev, command_port->bulk_out_endpointAddress);
+ pipe = usb_sndbulkpipe(serial->dev,
+ command_port->bulk_out_endpointAddress);
command = kmalloc(2, GFP_KERNEL);
if (!command)
goto no_command_buffer;
command[0] = WHITEHEAT_GET_HW_INFO;
command[1] = 0;
-
+
result = kmalloc(sizeof(*hw_info) + 1, GFP_KERNEL);
if (!result)
goto no_result_buffer;
/*
* When the module is reloaded the firmware is still there and
* the endpoints are still in the usb core unchanged. This is the
- * unlinking bug in disguise. Same for the call below.
- */
+ * unlinking bug in disguise. Same for the call below.
+ */
usb_clear_halt(serial->dev, pipe);
- ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT_MS);
+ ret = usb_bulk_msg(serial->dev, pipe, command, 2,
+ &alen, COMMAND_TIMEOUT_MS);
if (ret) {
- err("%s: Couldn't send command [%d]", serial->type->description, ret);
+ err("%s: Couldn't send command [%d]",
+ serial->type->description, ret);
goto no_firmware;
} else if (alen != 2) {
- err("%s: Send command incomplete [%d]", serial->type->description, alen);
+ err("%s: Send command incomplete [%d]",
+ serial->type->description, alen);
goto no_firmware;
}
- pipe = usb_rcvbulkpipe (serial->dev, command_port->bulk_in_endpointAddress);
+ pipe = usb_rcvbulkpipe(serial->dev,
+ command_port->bulk_in_endpointAddress);
/* See the comment on the usb_clear_halt() above */
usb_clear_halt(serial->dev, pipe);
- ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS);
+ ret = usb_bulk_msg(serial->dev, pipe, result,
+ sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS);
if (ret) {
- err("%s: Couldn't get results [%d]", serial->type->description, ret);
+ err("%s: Couldn't get results [%d]",
+ serial->type->description, ret);
goto no_firmware;
} else if (alen != sizeof(*hw_info) + 1) {
- err("%s: Get results incomplete [%d]", serial->type->description, alen);
+ err("%s: Get results incomplete [%d]",
+ serial->type->description, alen);
goto no_firmware;
} else if (result[0] != command[0]) {
- err("%s: Command failed [%d]", serial->type->description, result[0]);
+ err("%s: Command failed [%d]",
+ serial->type->description, result[0]);
goto no_firmware;
}
@@ -436,7 +460,8 @@ static int whiteheat_attach (struct usb_serial *serial)
info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
if (info == NULL) {
- err("%s: Out of memory for port structures\n", serial->type->description);
+ err("%s: Out of memory for port structures\n",
+ serial->type->description);
goto no_private;
}
@@ -506,9 +531,11 @@ static int whiteheat_attach (struct usb_serial *serial)
usb_set_serial_port_data(port, info);
}
- command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
+ command_info = kmalloc(sizeof(struct whiteheat_command_private),
+ GFP_KERNEL);
if (command_info == NULL) {
- err("%s: Out of memory for port structures\n", serial->type->description);
+ err("%s: Out of memory for port structures\n",
+ serial->type->description);
goto no_command_private;
}
@@ -525,9 +552,12 @@ static int whiteheat_attach (struct usb_serial *serial)
no_firmware:
/* Firmware likely not running */
- err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->description);
- err("%s: If the firmware is not running (status led not blinking)\n", serial->type->description);
- err("%s: please contact support@connecttech.com\n", serial->type->description);
+ err("%s: Unable to retrieve firmware version, try replugging\n",
+ serial->type->description);
+ err("%s: If the firmware is not running (status led not blinking)\n",
+ serial->type->description);
+ err("%s: please contact support@connecttech.com\n",
+ serial->type->description);
kfree(result);
return -ENODEV;
@@ -570,7 +600,7 @@ no_command_buffer:
}
-static void whiteheat_shutdown (struct usb_serial *serial)
+static void whiteheat_shutdown(struct usb_serial *serial)
{
struct usb_serial_port *command_port;
struct usb_serial_port *port;
@@ -585,7 +615,7 @@ static void whiteheat_shutdown (struct usb_serial *serial)
/* free up our private data for our command port */
command_port = serial->port[COMMAND_PORT];
- kfree (usb_get_serial_port_data(command_port));
+ kfree(usb_get_serial_port_data(command_port));
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
@@ -612,11 +642,10 @@ static void whiteheat_shutdown (struct usb_serial *serial)
return;
}
-
-static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
+static int whiteheat_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
int retval = 0;
- struct ktermios old_term;
dbg("%s - port %d", __func__, port->number);
@@ -624,7 +653,8 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
if (retval)
goto exit;
- port->tty->low_latency = 1;
+ if (tty)
+ tty->low_latency = 1;
/* send an open port command */
retval = firm_open(port);
@@ -640,9 +670,8 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
goto exit;
}
- old_term.c_cflag = ~port->tty->termios->c_cflag;
- old_term.c_iflag = ~port->tty->termios->c_iflag;
- whiteheat_set_termios(port, &old_term);
+ if (tty)
+ firm_setup_port(tty);
/* Work around HCD bugs */
usb_clear_halt(port->serial->dev, port->read_urb->pipe);
@@ -651,7 +680,8 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
/* Start reading from the device */
retval = start_port_read(port);
if (retval) {
- err("%s - failed submitting read urb, error %d", __func__, retval);
+ err("%s - failed submitting read urb, error %d",
+ __func__, retval);
firm_close(port);
stop_command_port(port->serial);
goto exit;
@@ -663,7 +693,8 @@ exit:
}
-static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
+static void whiteheat_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct whiteheat_private *info = usb_get_serial_port_data(port);
struct whiteheat_urb_wrap *wrap;
@@ -681,7 +712,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
}
mutex_unlock(&port->serial->disc_mutex);
- port->tty->closing = 1;
+ tty->closing = 1;
/*
* Not currently in use; tty_wait_until_sent() calls
@@ -689,12 +720,12 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
* acquisition. This should be fixed at some point. Greg's been
* notified.
if ((filp->f_flags & (O_NDELAY | O_NONBLOCK)) == 0) {
- tty_wait_until_sent(port->tty, CLOSING_DELAY);
+ tty_wait_until_sent(tty, CLOSING_DELAY);
}
*/
- tty_driver_flush_buffer(port->tty);
- tty_ldisc_flush(port->tty);
+ tty_driver_flush_buffer(tty);
+ tty_ldisc_flush(tty);
firm_report_tx_done(port);
@@ -728,11 +759,12 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
stop_command_port(port->serial);
- port->tty->closing = 0;
+ tty->closing = 0;
}
-static int whiteheat_write(struct usb_serial_port *port, const unsigned char *buf, int count)
+static int whiteheat_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
struct whiteheat_private *info = usb_get_serial_port_data(port);
@@ -763,16 +795,19 @@ static int whiteheat_write(struct usb_serial_port *port, const unsigned char *bu
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
urb = wrap->urb;
- bytes = (count > port->bulk_out_size) ? port->bulk_out_size : count;
- memcpy (urb->transfer_buffer, buf + sent, bytes);
+ bytes = (count > port->bulk_out_size) ?
+ port->bulk_out_size : count;
+ memcpy(urb->transfer_buffer, buf + sent, bytes);
- usb_serial_debug_data(debug, &port->dev, __func__, bytes, urb->transfer_buffer);
+ usb_serial_debug_data(debug, &port->dev,
+ __func__, bytes, urb->transfer_buffer);
urb->dev = serial->dev;
urb->transfer_buffer_length = bytes;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
- err("%s - failed submitting write urb, error %d", __func__, result);
+ err("%s - failed submitting write urb, error %d",
+ __func__, result);
sent = result;
spin_lock_irqsave(&info->lock, flags);
list_add(tmp, &info->tx_urbs_free);
@@ -790,16 +825,16 @@ static int whiteheat_write(struct usb_serial_port *port, const unsigned char *bu
return sent;
}
-
-static int whiteheat_write_room(struct usb_serial_port *port)
+static int whiteheat_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port);
struct list_head *tmp;
int room = 0;
unsigned long flags;
dbg("%s - port %d", __func__, port->number);
-
+
spin_lock_irqsave(&info->lock, flags);
list_for_each(tmp, &info->tx_urbs_free)
room++;
@@ -810,9 +845,9 @@ static int whiteheat_write_room(struct usb_serial_port *port)
return (room);
}
-
-static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file)
+static int whiteheat_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port);
unsigned int modem_signals = 0;
@@ -827,10 +862,10 @@ static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file)
return modem_signals;
}
-
-static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file,
+static int whiteheat_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port);
dbg("%s - port %d", __func__, port->number);
@@ -851,65 +886,55 @@ static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file,
}
-static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+static int whiteheat_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct serial_struct serstruct;
void __user *user_arg = (void __user *)arg;
dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
switch (cmd) {
- case TIOCGSERIAL:
- memset(&serstruct, 0, sizeof(serstruct));
- serstruct.type = PORT_16654;
- serstruct.line = port->serial->minor;
- serstruct.port = port->number;
- serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
- serstruct.xmit_fifo_size = port->bulk_out_size;
- serstruct.custom_divisor = 0;
- serstruct.baud_base = 460800;
- serstruct.close_delay = CLOSING_DELAY;
- serstruct.closing_wait = CLOSING_DELAY;
-
- if (copy_to_user(user_arg, &serstruct, sizeof(serstruct)))
- return -EFAULT;
-
- break;
-
- case TIOCSSERIAL:
- if (copy_from_user(&serstruct, user_arg, sizeof(serstruct)))
- return -EFAULT;
-
- /*
- * For now this is ignored. dip sets the ASYNC_[V]HI flags
- * but this isn't used by us at all. Maybe someone somewhere
- * will need the custom_divisor setting.
- */
-
- break;
-
- default:
- break;
+ case TIOCGSERIAL:
+ memset(&serstruct, 0, sizeof(serstruct));
+ serstruct.type = PORT_16654;
+ serstruct.line = port->serial->minor;
+ serstruct.port = port->number;
+ serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+ serstruct.xmit_fifo_size = port->bulk_out_size;
+ serstruct.custom_divisor = 0;
+ serstruct.baud_base = 460800;
+ serstruct.close_delay = CLOSING_DELAY;
+ serstruct.closing_wait = CLOSING_DELAY;
+
+ if (copy_to_user(user_arg, &serstruct, sizeof(serstruct)))
+ return -EFAULT;
+ break;
+ default:
+ break;
}
return -ENOIOCTLCMD;
}
-static void whiteheat_set_termios(struct usb_serial_port *port, struct ktermios *old_termios)
+static void whiteheat_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
- dbg("%s -port %d", __func__, port->number);
- firm_setup_port(port);
+ firm_setup_port(tty);
}
-
-static void whiteheat_break_ctl(struct usb_serial_port *port, int break_state) {
+static void whiteheat_break_ctl(struct tty_struct *tty, int break_state)
+{
+ struct usb_serial_port *port = tty->driver_data;
firm_set_break(port, break_state);
}
-static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
+static int whiteheat_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port);
struct list_head *tmp;
struct whiteheat_urb_wrap *wrap;
@@ -925,13 +950,14 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
}
spin_unlock_irqrestore(&info->lock, flags);
- dbg ("%s - returns %d", __func__, chars);
+ dbg("%s - returns %d", __func__, chars);
return chars;
}
-static void whiteheat_throttle (struct usb_serial_port *port)
+static void whiteheat_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port);
unsigned long flags;
@@ -945,8 +971,9 @@ static void whiteheat_throttle (struct usb_serial_port *port)
}
-static void whiteheat_unthrottle (struct usb_serial_port *port)
+static void whiteheat_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port);
int actually_throttled;
unsigned long flags;
@@ -993,7 +1020,7 @@ static void command_port_read_callback(struct urb *urb)
command_info = usb_get_serial_port_data(command_port);
if (!command_info) {
- dbg ("%s - command_info is NULL, exiting.", __func__);
+ dbg("%s - command_info is NULL, exiting.", __func__);
return;
}
if (status) {
@@ -1004,7 +1031,8 @@ static void command_port_read_callback(struct urb *urb)
return;
}
- usb_serial_debug_data(debug, &command_port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &command_port->dev,
+ __func__, urb->actual_length, data);
if (data[0] == WHITEHEAT_CMD_COMPLETE) {
command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
@@ -1013,21 +1041,23 @@ static void command_port_read_callback(struct urb *urb)
command_info->command_finished = WHITEHEAT_CMD_FAILURE;
wake_up(&command_info->wait_command);
} else if (data[0] == WHITEHEAT_EVENT) {
- /* These are unsolicited reports from the firmware, hence no waiting command to wakeup */
+ /* These are unsolicited reports from the firmware, hence no
+ waiting command to wakeup */
dbg("%s - event received", __func__);
} else if (data[0] == WHITEHEAT_GET_DTR_RTS) {
- memcpy(command_info->result_buffer, &data[1], urb->actual_length - 1);
+ memcpy(command_info->result_buffer, &data[1],
+ urb->actual_length - 1);
command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
wake_up(&command_info->wait_command);
- } else {
+ } else
dbg("%s - bad reply from firmware", __func__);
- }
-
+
/* Continue trying to always read */
command_port->read_urb->dev = command_port->serial->dev;
result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC);
if (result)
- dbg("%s - failed resubmitting read urb, error %d", __func__, result);
+ dbg("%s - failed resubmitting read urb, error %d",
+ __func__, result);
}
@@ -1060,7 +1090,8 @@ static void whiteheat_read_callback(struct urb *urb)
return;
}
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev,
+ __func__, urb->actual_length, data);
spin_lock(&info->lock);
list_add_tail(&wrap->list, &info->rx_urb_q);
@@ -1107,7 +1138,8 @@ static void whiteheat_write_callback(struct urb *urb)
/*****************************************************************************
* Connect Tech's White Heat firmware interface
*****************************************************************************/
-static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize)
+static int firm_send_command(struct usb_serial_port *port, __u8 command,
+ __u8 *data, __u8 datasize)
{
struct usb_serial_port *command_port;
struct whiteheat_command_private *command_info;
@@ -1122,13 +1154,13 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d
command_info = usb_get_serial_port_data(command_port);
mutex_lock(&command_info->mutex);
command_info->command_finished = false;
-
+
transfer_buffer = (__u8 *)command_port->write_urb->transfer_buffer;
transfer_buffer[0] = command;
- memcpy (&transfer_buffer[1], data, datasize);
+ memcpy(&transfer_buffer[1], data, datasize);
command_port->write_urb->transfer_buffer_length = datasize + 1;
command_port->write_urb->dev = port->serial->dev;
- retval = usb_submit_urb (command_port->write_urb, GFP_NOIO);
+ retval = usb_submit_urb(command_port->write_urb, GFP_NOIO);
if (retval) {
dbg("%s - submit urb failed", __func__);
goto exit;
@@ -1155,51 +1187,57 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d
if (command_info->command_finished == WHITEHEAT_CMD_COMPLETE) {
dbg("%s - command completed.", __func__);
switch (command) {
- case WHITEHEAT_GET_DTR_RTS:
- info = usb_get_serial_port_data(port);
- memcpy(&info->mcr, command_info->result_buffer, sizeof(struct whiteheat_dr_info));
+ case WHITEHEAT_GET_DTR_RTS:
+ info = usb_get_serial_port_data(port);
+ memcpy(&info->mcr, command_info->result_buffer,
+ sizeof(struct whiteheat_dr_info));
break;
}
}
-
exit:
mutex_unlock(&command_info->mutex);
return retval;
}
-static int firm_open(struct usb_serial_port *port) {
+static int firm_open(struct usb_serial_port *port)
+{
struct whiteheat_simple open_command;
open_command.port = port->number - port->serial->minor + 1;
- return firm_send_command(port, WHITEHEAT_OPEN, (__u8 *)&open_command, sizeof(open_command));
+ return firm_send_command(port, WHITEHEAT_OPEN,
+ (__u8 *)&open_command, sizeof(open_command));
}
-static int firm_close(struct usb_serial_port *port) {
+static int firm_close(struct usb_serial_port *port)
+{
struct whiteheat_simple close_command;
close_command.port = port->number - port->serial->minor + 1;
- return firm_send_command(port, WHITEHEAT_CLOSE, (__u8 *)&close_command, sizeof(close_command));
+ return firm_send_command(port, WHITEHEAT_CLOSE,
+ (__u8 *)&close_command, sizeof(close_command));
}
-static int firm_setup_port(struct usb_serial_port *port) {
+static int firm_setup_port(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
struct whiteheat_port_settings port_settings;
- unsigned int cflag = port->tty->termios->c_cflag;
+ unsigned int cflag = tty->termios->c_cflag;
port_settings.port = port->number + 1;
/* get the byte size */
switch (cflag & CSIZE) {
- case CS5: port_settings.bits = 5; break;
- case CS6: port_settings.bits = 6; break;
- case CS7: port_settings.bits = 7; break;
- default:
- case CS8: port_settings.bits = 8; break;
+ case CS5: port_settings.bits = 5; break;
+ case CS6: port_settings.bits = 6; break;
+ case CS7: port_settings.bits = 7; break;
+ default:
+ case CS8: port_settings.bits = 8; break;
}
dbg("%s - data bits = %d", __func__, port_settings.bits);
-
+
/* determine the parity */
if (cflag & PARENB)
if (cflag & CMSPAR)
@@ -1225,7 +1263,8 @@ static int firm_setup_port(struct usb_serial_port *port) {
/* figure out the flow control settings */
if (cflag & CRTSCTS)
- port_settings.hflow = (WHITEHEAT_HFLOW_CTS | WHITEHEAT_HFLOW_RTS);
+ port_settings.hflow = (WHITEHEAT_HFLOW_CTS |
+ WHITEHEAT_HFLOW_RTS);
else
port_settings.hflow = WHITEHEAT_HFLOW_NONE;
dbg("%s - hardware flow control = %s %s %s %s", __func__,
@@ -1233,81 +1272,95 @@ static int firm_setup_port(struct usb_serial_port *port) {
(port_settings.hflow & WHITEHEAT_HFLOW_RTS) ? "RTS" : "",
(port_settings.hflow & WHITEHEAT_HFLOW_DSR) ? "DSR" : "",
(port_settings.hflow & WHITEHEAT_HFLOW_DTR) ? "DTR" : "");
-
+
/* determine software flow control */
- if (I_IXOFF(port->tty))
+ if (I_IXOFF(tty))
port_settings.sflow = WHITEHEAT_SFLOW_RXTX;
else
port_settings.sflow = WHITEHEAT_SFLOW_NONE;
dbg("%s - software flow control = %c", __func__, port_settings.sflow);
-
- port_settings.xon = START_CHAR(port->tty);
- port_settings.xoff = STOP_CHAR(port->tty);
- dbg("%s - XON = %2x, XOFF = %2x", __func__, port_settings.xon, port_settings.xoff);
+
+ port_settings.xon = START_CHAR(tty);
+ port_settings.xoff = STOP_CHAR(tty);
+ dbg("%s - XON = %2x, XOFF = %2x",
+ __func__, port_settings.xon, port_settings.xoff);
/* get the baud rate wanted */
- port_settings.baud = tty_get_baud_rate(port->tty);
+ port_settings.baud = tty_get_baud_rate(tty);
dbg("%s - baud rate = %d", __func__, port_settings.baud);
/* fixme: should set validated settings */
- tty_encode_baud_rate(port->tty, port_settings.baud, port_settings.baud);
+ tty_encode_baud_rate(tty, port_settings.baud, port_settings.baud);
/* handle any settings that aren't specified in the tty structure */
port_settings.lloop = 0;
-
+
/* now send the message to the device */
- return firm_send_command(port, WHITEHEAT_SETUP_PORT, (__u8 *)&port_settings, sizeof(port_settings));
+ return firm_send_command(port, WHITEHEAT_SETUP_PORT,
+ (__u8 *)&port_settings, sizeof(port_settings));
}
-static int firm_set_rts(struct usb_serial_port *port, __u8 onoff) {
+static int firm_set_rts(struct usb_serial_port *port, __u8 onoff)
+{
struct whiteheat_set_rdb rts_command;
rts_command.port = port->number - port->serial->minor + 1;
rts_command.state = onoff;
- return firm_send_command(port, WHITEHEAT_SET_RTS, (__u8 *)&rts_command, sizeof(rts_command));
+ return firm_send_command(port, WHITEHEAT_SET_RTS,
+ (__u8 *)&rts_command, sizeof(rts_command));
}
-static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff) {
+static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff)
+{
struct whiteheat_set_rdb dtr_command;
dtr_command.port = port->number - port->serial->minor + 1;
dtr_command.state = onoff;
- return firm_send_command(port, WHITEHEAT_SET_RTS, (__u8 *)&dtr_command, sizeof(dtr_command));
+ return firm_send_command(port, WHITEHEAT_SET_DTR,
+ (__u8 *)&dtr_command, sizeof(dtr_command));
}
-static int firm_set_break(struct usb_serial_port *port, __u8 onoff) {
+static int firm_set_break(struct usb_serial_port *port, __u8 onoff)
+{
struct whiteheat_set_rdb break_command;
break_command.port = port->number - port->serial->minor + 1;
break_command.state = onoff;
- return firm_send_command(port, WHITEHEAT_SET_RTS, (__u8 *)&break_command, sizeof(break_command));
+ return firm_send_command(port, WHITEHEAT_SET_BREAK,
+ (__u8 *)&break_command, sizeof(break_command));
}
-static int firm_purge(struct usb_serial_port *port, __u8 rxtx) {
+static int firm_purge(struct usb_serial_port *port, __u8 rxtx)
+{
struct whiteheat_purge purge_command;
purge_command.port = port->number - port->serial->minor + 1;
purge_command.what = rxtx;
- return firm_send_command(port, WHITEHEAT_PURGE, (__u8 *)&purge_command, sizeof(purge_command));
+ return firm_send_command(port, WHITEHEAT_PURGE,
+ (__u8 *)&purge_command, sizeof(purge_command));
}
-static int firm_get_dtr_rts(struct usb_serial_port *port) {
+static int firm_get_dtr_rts(struct usb_serial_port *port)
+{
struct whiteheat_simple get_dr_command;
get_dr_command.port = port->number - port->serial->minor + 1;
- return firm_send_command(port, WHITEHEAT_GET_DTR_RTS, (__u8 *)&get_dr_command, sizeof(get_dr_command));
+ return firm_send_command(port, WHITEHEAT_GET_DTR_RTS,
+ (__u8 *)&get_dr_command, sizeof(get_dr_command));
}
-static int firm_report_tx_done(struct usb_serial_port *port) {
+static int firm_report_tx_done(struct usb_serial_port *port)
+{
struct whiteheat_simple close_command;
close_command.port = port->number - port->serial->minor + 1;
- return firm_send_command(port, WHITEHEAT_REPORT_TX_DONE, (__u8 *)&close_command, sizeof(close_command));
+ return firm_send_command(port, WHITEHEAT_REPORT_TX_DONE,
+ (__u8 *)&close_command, sizeof(close_command));
}
@@ -1319,7 +1372,7 @@ static int start_command_port(struct usb_serial *serial)
struct usb_serial_port *command_port;
struct whiteheat_command_private *command_info;
int retval = 0;
-
+
command_port = serial->port[COMMAND_PORT];
command_info = usb_get_serial_port_data(command_port);
mutex_lock(&command_info->mutex);
@@ -1330,7 +1383,8 @@ static int start_command_port(struct usb_serial *serial)
command_port->read_urb->dev = serial->dev;
retval = usb_submit_urb(command_port->read_urb, GFP_KERNEL);
if (retval) {
- err("%s - failed submitting read urb, error %d", __func__, retval);
+ err("%s - failed submitting read urb, error %d",
+ __func__, retval);
goto exit;
}
}
@@ -1400,7 +1454,8 @@ static int start_port_read(struct usb_serial_port *port)
}
-static struct whiteheat_urb_wrap *urb_to_wrap(struct urb* urb, struct list_head *head)
+static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb,
+ struct list_head *head)
{
struct whiteheat_urb_wrap *wrap;
struct list_head *tmp;
@@ -1426,7 +1481,7 @@ static void rx_data_softint(struct work_struct *work)
struct whiteheat_private *info =
container_of(work, struct whiteheat_private, rx_work);
struct usb_serial_port *port = info->port;
- struct tty_struct *tty = port->tty;
+ struct tty_struct *tty = port->port.tty;
struct whiteheat_urb_wrap *wrap;
struct urb *urb;
unsigned long flags;
@@ -1449,7 +1504,8 @@ static void rx_data_softint(struct work_struct *work)
urb = wrap->urb;
if (tty && urb->actual_length) {
- int len = tty_buffer_request_room(tty, urb->actual_length);
+ int len = tty_buffer_request_room(tty,
+ urb->actual_length);
/* This stuff can go away now I suspect */
if (unlikely(len < urb->actual_length)) {
spin_lock_irqsave(&info->lock, flags);
@@ -1466,7 +1522,8 @@ static void rx_data_softint(struct work_struct *work)
urb->dev = port->serial->dev;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
- err("%s - failed resubmitting read urb, error %d", __func__, result);
+ err("%s - failed resubmitting read urb, error %d",
+ __func__, result);
spin_lock_irqsave(&info->lock, flags);
list_add(tmp, &info->rx_urbs_free);
continue;
@@ -1485,7 +1542,7 @@ static void rx_data_softint(struct work_struct *work)
/*****************************************************************************
* Connect Tech's White Heat module functions
*****************************************************************************/
-static int __init whiteheat_init (void)
+static int __init whiteheat_init(void)
{
int retval;
retval = usb_serial_register(&whiteheat_fake_device);
@@ -1508,19 +1565,19 @@ failed_fake_register:
}
-static void __exit whiteheat_exit (void)
+static void __exit whiteheat_exit(void)
{
- usb_deregister (&whiteheat_driver);
- usb_serial_deregister (&whiteheat_fake_device);
- usb_serial_deregister (&whiteheat_device);
+ usb_deregister(&whiteheat_driver);
+ usb_serial_deregister(&whiteheat_fake_device);
+ usb_serial_deregister(&whiteheat_device);
}
module_init(whiteheat_init);
module_exit(whiteheat_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("whiteheat.fw");
diff --git a/drivers/usb/serial/whiteheat.h b/drivers/usb/serial/whiteheat.h
index f1607970566..38065df4d2d 100644
--- a/drivers/usb/serial/whiteheat.h
+++ b/drivers/usb/serial/whiteheat.h
@@ -2,7 +2,7 @@
* USB ConnectTech WhiteHEAT driver
*
* Copyright (C) 2002
- * Connect Tech Inc.
+ * Connect Tech Inc.
*
* Copyright (C) 1999, 2000
* Greg Kroah-Hartman (greg@kroah.com)
@@ -12,7 +12,8 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
*/
@@ -30,13 +31,16 @@
#define WHITEHEAT_DUMP 7 /* dump memory */
#define WHITEHEAT_STATUS 8 /* get status */
#define WHITEHEAT_PURGE 9 /* clear the UART fifos */
-#define WHITEHEAT_GET_DTR_RTS 10 /* get the state of DTR and RTS for a port */
-#define WHITEHEAT_GET_HW_INFO 11 /* get EEPROM info and hardware ID */
+#define WHITEHEAT_GET_DTR_RTS 10 /* get the state of DTR and RTS
+ for a port */
+#define WHITEHEAT_GET_HW_INFO 11 /* get EEPROM info and
+ hardware ID */
#define WHITEHEAT_REPORT_TX_DONE 12 /* get the next TX done */
#define WHITEHEAT_EVENT 13 /* unsolicited status events */
-#define WHITEHEAT_ECHO 14 /* send data to the indicated IN endpoint */
-#define WHITEHEAT_DO_TEST 15 /* perform the specified test */
-#define WHITEHEAT_CMD_COMPLETE 16 /* reply for certain commands */
+#define WHITEHEAT_ECHO 14 /* send data to the indicated
+ IN endpoint */
+#define WHITEHEAT_DO_TEST 15 /* perform specified test */
+#define WHITEHEAT_CMD_COMPLETE 16 /* reply for some commands */
#define WHITEHEAT_CMD_FAILURE 17 /* reply for failed commands */
@@ -67,20 +71,28 @@ struct whiteheat_simple {
#define WHITEHEAT_PAR_MARK '1' /* mark (force 1) parity */
#define WHITEHEAT_SFLOW_NONE 'n' /* no software flow control */
-#define WHITEHEAT_SFLOW_RX 'r' /* XOFF/ON is sent when RX fills/empties */
-#define WHITEHEAT_SFLOW_TX 't' /* when received XOFF/ON will stop/start TX */
+#define WHITEHEAT_SFLOW_RX 'r' /* XOFF/ON is sent when RX
+ fills/empties */
+#define WHITEHEAT_SFLOW_TX 't' /* when received XOFF/ON will
+ stop/start TX */
#define WHITEHEAT_SFLOW_RXTX 'b' /* both SFLOW_RX and SFLOW_TX */
#define WHITEHEAT_HFLOW_NONE 0x00 /* no hardware flow control */
-#define WHITEHEAT_HFLOW_RTS_TOGGLE 0x01 /* RTS is on during transmit, off otherwise */
-#define WHITEHEAT_HFLOW_DTR 0x02 /* DTR is off/on when RX fills/empties */
-#define WHITEHEAT_HFLOW_CTS 0x08 /* when received CTS off/on will stop/start TX */
-#define WHITEHEAT_HFLOW_DSR 0x10 /* when received DSR off/on will stop/start TX */
-#define WHITEHEAT_HFLOW_RTS 0x80 /* RTS is off/on when RX fills/empties */
+#define WHITEHEAT_HFLOW_RTS_TOGGLE 0x01 /* RTS is on during transmit,
+ off otherwise */
+#define WHITEHEAT_HFLOW_DTR 0x02 /* DTR is off/on when RX
+ fills/empties */
+#define WHITEHEAT_HFLOW_CTS 0x08 /* when received CTS off/on
+ will stop/start TX */
+#define WHITEHEAT_HFLOW_DSR 0x10 /* when received DSR off/on
+ will stop/start TX */
+#define WHITEHEAT_HFLOW_RTS 0x80 /* RTS is off/on when RX
+ fills/empties */
struct whiteheat_port_settings {
__u8 port; /* port number (1 to N) */
- __u32 baud; /* any value 7 - 460800, firmware calculates best fit; arrives little endian */
+ __u32 baud; /* any value 7 - 460800, firmware calculates
+ best fit; arrives little endian */
__u8 bits; /* 5, 6, 7, or 8 */
__u8 stop; /* 1 or 2, default 1 (2 = 1.5 if bits = 5) */
__u8 parity; /* see WHITEHEAT_PAR_* above */
@@ -167,12 +179,14 @@ struct whiteheat_echo {
*/
#define WHITEHEAT_TEST_UART_RW 0x01 /* read/write uart registers */
#define WHITEHEAT_TEST_UART_INTR 0x02 /* uart interrupt */
-#define WHITEHEAT_TEST_SETUP_CONT 0x03 /* setup for PORT_CONT/PORT_DISCONT */
+#define WHITEHEAT_TEST_SETUP_CONT 0x03 /* setup for
+ PORT_CONT/PORT_DISCONT */
#define WHITEHEAT_TEST_PORT_CONT 0x04 /* port connect */
#define WHITEHEAT_TEST_PORT_DISCONT 0x05 /* port disconnect */
#define WHITEHEAT_TEST_UART_CLK_START 0x06 /* uart clock test start */
#define WHITEHEAT_TEST_UART_CLK_STOP 0x07 /* uart clock test stop */
-#define WHITEHEAT_TEST_MODEM_FT 0x08 /* modem signals, requires a loopback cable/connector */
+#define WHITEHEAT_TEST_MODEM_FT 0x08 /* modem signals, requires a
+ loopback cable/connector */
#define WHITEHEAT_TEST_ERASE_EEPROM 0x09 /* erase eeprom */
#define WHITEHEAT_TEST_READ_EEPROM 0x0a /* read eeprom */
#define WHITEHEAT_TEST_PROGRAM_EEPROM 0x0b /* program eeprom */
@@ -198,19 +212,27 @@ struct whiteheat_test {
#define WHITEHEAT_EVENT_CONNECT 0x08 /* connect field is valid */
#define WHITEHEAT_FLOW_NONE 0x00 /* no flow control active */
-#define WHITEHEAT_FLOW_HARD_OUT 0x01 /* TX is stopped by CTS (waiting for CTS to go on) */
-#define WHITEHEAT_FLOW_HARD_IN 0x02 /* remote TX is stopped by RTS */
-#define WHITEHEAT_FLOW_SOFT_OUT 0x04 /* TX is stopped by XOFF received (waiting for XON) */
-#define WHITEHEAT_FLOW_SOFT_IN 0x08 /* remote TX is stopped by XOFF transmitted */
+#define WHITEHEAT_FLOW_HARD_OUT 0x01 /* TX is stopped by CTS
+ (waiting for CTS to go on) */
+#define WHITEHEAT_FLOW_HARD_IN 0x02 /* remote TX is stopped
+ by RTS */
+#define WHITEHEAT_FLOW_SOFT_OUT 0x04 /* TX is stopped by XOFF
+ received (waiting for XON) */
+#define WHITEHEAT_FLOW_SOFT_IN 0x08 /* remote TX is stopped by XOFF
+ transmitted */
#define WHITEHEAT_FLOW_TX_DONE 0x80 /* TX has completed */
struct whiteheat_status_info {
__u8 port; /* port number (1 to N) */
- __u8 event; /* indicates what the current event is, see WHITEHEAT_EVENT_* above */
- __u8 modem; /* modem signal status (copy of uart's MSR register) */
+ __u8 event; /* indicates what the current event is,
+ see WHITEHEAT_EVENT_* above */
+ __u8 modem; /* modem signal status (copy of uart's
+ MSR register) */
__u8 error; /* line status (copy of uart's LSR register) */
- __u8 flow; /* flow control state, see WHITEHEAT_FLOW_* above */
- __u8 connect; /* 0 means not connected, non-zero means connected */
+ __u8 flow; /* flow control state, see WHITEHEAT_FLOW_*
+ above */
+ __u8 connect; /* 0 means not connected, non-zero means
+ connected */
};
@@ -256,7 +278,8 @@ struct whiteheat_hw_info {
struct whiteheat_event_info {
__u8 port; /* port number (1 to N) */
__u8 event; /* see whiteheat_status_info.event */
- __u8 info; /* see whiteheat_status_info.modem, .error, .flow, .connect */
+ __u8 info; /* see whiteheat_status_info.modem, .error,
+ .flow, .connect */
};
@@ -269,7 +292,8 @@ struct whiteheat_event_info {
struct whiteheat_test_info {
__u8 port; /* port number (1 to N) */
- __u8 test; /* indicates which test this is a response for, see WHITEHEAT_DO_TEST above */
+ __u8 test; /* indicates which test this is a response for,
+ see WHITEHEAT_DO_TEST above */
__u8 status; /* see WHITEHEAT_TEST_* above */
__u8 results[32]; /* test-dependent results */
};
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 9b887ef64ff..70d135e0cc4 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1658,6 +1658,32 @@ config FB_PM3
similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000
and maybe other boards.
+config FB_CARMINE
+ tristate "Fujitsu carmine frame buffer support"
+ depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the Fujitsu Carmine chip.
+ The driver provides two independent frame buffer devices.
+
+choice
+ depends on FB_CARMINE
+ prompt "DRAM timing"
+ default FB_CARMINE_DRAM_EVAL
+
+config FB_CARMINE_DRAM_EVAL
+ bool "Eval board timings"
+ help
+ Use timings which work on the eval card.
+
+config CARMINE_DRAM_CUSTOM
+ bool "Custom board timings"
+ help
+ Use custom board timings.
+endchoice
+
config FB_AU1100
bool "Au1100 LCD Driver"
depends on (FB = y) && MIPS && SOC_AU1100
@@ -1840,6 +1866,16 @@ config FB_W100
If unsure, say N.
+config FB_SH_MOBILE_LCDC
+ tristate "SuperH Mobile LCDC framebuffer support"
+ depends on FB && SUPERH
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ default m
+ ---help---
+ Frame buffer driver for the on-chip SH-Mobile LCD controller.
+
config FB_S3C2410
tristate "S3C2410 LCD framebuffer support"
depends on FB && ARCH_S3C2410
@@ -1951,6 +1987,23 @@ config FB_AM200EPD
This enables support for the Metronome display controller used on
the E-Ink AM-200 EPD devkit.
+config FB_COBALT
+ tristate "Cobalt server LCD frame buffer support"
+ depends on FB && MIPS_COBALT
+
+config FB_SH7760
+ bool "SH7760/SH7763 LCDC support"
+ depends on FB && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ Support for the SH7760/SH7763 integrated (D)STN/TFT LCD Controller.
+ Supports display resolutions up to 1024x1024 pixel, grayscale and
+ color operation, with depths ranging from 1 bpp to 8 bpp monochrome
+ and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for
+ panels <= 320 pixel horizontal resolution.
+
config FB_VIRTUAL
tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
depends on FB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 04bca35403f..0ebc1bfd251 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -106,17 +106,22 @@ obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
obj-$(CONFIG_FB_MAXINE) += maxinefb.o
obj-$(CONFIG_FB_METRONOME) += metronomefb.o
obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
+obj-$(CONFIG_FB_SH7760) += sh7760fb.o
obj-$(CONFIG_FB_IMX) += imxfb.o
obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o
+obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o
obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/
obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/
obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
obj-$(CONFIG_FB_PS3) += ps3fb.o
obj-$(CONFIG_FB_SM501) += sm501fb.o
obj-$(CONFIG_FB_XILINX) += xilinxfb.o
+obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
+obj-$(CONFIG_FB_SH7343VOU) += sh7343_voufb.o
obj-$(CONFIG_FB_OMAP) += omap/
obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
+obj-$(CONFIG_FB_CARMINE) += carminefb.o
# Platform or fallback drivers go here
obj-$(CONFIG_FB_UVESA) += uvesafb.o
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index eedb8285e32..017233d0c48 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -23,6 +23,7 @@
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/slab.h>
+#include <linux/mm.h>
#include <linux/init.h>
#include <linux/fb.h>
#include <linux/platform_device.h>
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 45c154ade9c..b8e9a8682f2 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -1136,7 +1136,6 @@ static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg
* Interface to the low level console driver
*/
-int amifb_init(void);
static void amifb_deinit(void);
/*
@@ -2048,13 +2047,16 @@ static void amifb_copyarea(struct fb_info *info,
width = x2 - dx;
height = y2 - dy;
+ if (area->sx + dx < area->dx || area->sy + dy < area->dy)
+ return;
+
/* update sx,sy */
sx = area->sx + (dx - area->dx);
sy = area->sy + (dy - area->dy);
/* the source must be completely inside the virtual screen */
- if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual ||
- (sy + height) > info->var.yres_virtual)
+ if (sx + width > info->var.xres_virtual ||
+ sy + height > info->var.yres_virtual)
return;
if (dy > sy || (dy == sy && dx > sx)) {
@@ -2245,7 +2247,7 @@ static inline void chipfree(void)
* Initialisation
*/
-int __init amifb_init(void)
+static int __init amifb_init(void)
{
int tag, i, err = 0;
u_long chipptr;
@@ -3790,16 +3792,14 @@ static void ami_rebuild_copper(void)
}
}
-
-module_init(amifb_init);
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-
-void cleanup_module(void)
+static void __exit amifb_exit(void)
{
unregister_framebuffer(&fb_info);
amifb_deinit();
amifb_video_off();
}
-#endif /* MODULE */
+
+module_init(amifb_init);
+module_exit(amifb_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index fa55d356b53..77eb8b34fbf 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -2593,13 +2593,16 @@ static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
width = x2 - dx;
height = y2 - dy;
+ if (area->sx + dx < area->dx || area->sy + dy < area->dy)
+ return;
+
/* update sx,sy */
sx = area->sx + (dx - area->dx);
sy = area->sy + (dy - area->dy);
/* the source must be completely inside the virtual screen */
- if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual ||
- (sy + height) > info->var.yres_virtual)
+ if (sx + width > info->var.xres_virtual ||
+ sy + height > info->var.yres_virtual)
return;
if (dy > sy || (dy == sy && dx > sx)) {
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index b004036d408..5b3a15dffb5 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -256,6 +256,20 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
return 0;
}
+static const struct fb_videomode *atmel_lcdfb_choose_mode(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct fb_videomode varfbmode;
+ const struct fb_videomode *fbmode = NULL;
+
+ fb_var_to_videomode(&varfbmode, var);
+ fbmode = fb_find_nearest_mode(&varfbmode, &info->modelist);
+ if (fbmode)
+ fb_videomode_to_var(var, fbmode);
+ return fbmode;
+}
+
+
/**
* atmel_lcdfb_check_var - Validates a var passed in.
* @var: frame buffer variable screen structure
@@ -289,6 +303,15 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
dev_dbg(dev, "%s:\n", __func__);
+
+ if (!(var->pixclock && var->bits_per_pixel)) {
+ /* choose a suitable mode if possible */
+ if (!atmel_lcdfb_choose_mode(var, info)) {
+ dev_err(dev, "needed value not specified\n");
+ return -EINVAL;
+ }
+ }
+
dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres);
dev_dbg(dev, " pixclk: %lu KHz\n", PICOS2KHZ(var->pixclock));
dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel);
@@ -299,6 +322,13 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
return -EINVAL;
}
+ /* Do not allow to have real resoulution larger than virtual */
+ if (var->xres > var->xres_virtual)
+ var->xres_virtual = var->xres;
+
+ if (var->yres > var->yres_virtual)
+ var->yres_virtual = var->yres;
+
/* Force same alignment for each line */
var->xres = (var->xres + 3) & ~3UL;
var->xres_virtual = (var->xres_virtual + 3) & ~3UL;
@@ -379,6 +409,35 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
return 0;
}
+/*
+ * LCD reset sequence
+ */
+static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo)
+{
+ might_sleep();
+
+ /* LCD power off */
+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
+
+ /* wait for the LCDC core to become idle */
+ while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
+ msleep(10);
+
+ /* DMA disable */
+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
+
+ /* wait for DMA engine to become idle */
+ while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
+ msleep(10);
+
+ /* LCD power on */
+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
+ (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR);
+
+ /* DMA enable */
+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
+}
+
/**
* atmel_lcdfb_set_par - Alters the hardware state.
* @info: frame buffer structure that represents a single frame buffer
@@ -401,6 +460,8 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
unsigned long clk_value_khz;
unsigned long bits_per_line;
+ might_sleep();
+
dev_dbg(info->device, "%s:\n", __func__);
dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n",
info->var.xres, info->var.yres,
@@ -511,6 +572,8 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
/* Disable all interrupts */
lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
+ /* Enable FIFO & DMA errors */
+ lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
/* ...wait for DMA engine to become idle... */
while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
@@ -645,10 +708,26 @@ static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id)
u32 status;
status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
- lcdc_writel(sinfo, ATMEL_LCDC_IDR, status);
+ if (status & ATMEL_LCDC_UFLWI) {
+ dev_warn(info->device, "FIFO underflow %#x\n", status);
+ /* reset DMA and FIFO to avoid screen shifting */
+ schedule_work(&sinfo->task);
+ }
+ lcdc_writel(sinfo, ATMEL_LCDC_ICR, status);
return IRQ_HANDLED;
}
+/*
+ * LCD controller task (to reset the LCD)
+ */
+static void atmel_lcdfb_task(struct work_struct *work)
+{
+ struct atmel_lcdfb_info *sinfo =
+ container_of(work, struct atmel_lcdfb_info, task);
+
+ atmel_lcdfb_reset(sinfo);
+}
+
static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
{
struct fb_info *info = sinfo->info;
@@ -691,6 +770,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
struct fb_info *info;
struct atmel_lcdfb_info *sinfo;
struct atmel_lcdfb_info *pdata_sinfo;
+ struct fb_videomode fbmode;
struct resource *regs = NULL;
struct resource *map = NULL;
int ret;
@@ -824,6 +904,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
goto unmap_mmio;
}
+ /* Some operations on the LCDC might sleep and
+ * require a preemptible task context */
+ INIT_WORK(&sinfo->task, atmel_lcdfb_task);
+
ret = atmel_lcdfb_init_fbinfo(sinfo);
if (ret < 0) {
dev_err(dev, "init fbinfo failed: %d\n", ret);
@@ -853,6 +937,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
goto free_cmap;
}
+ /* add selected videomode to modelist */
+ fb_var_to_videomode(&fbmode, &info->var);
+ fb_add_videomode(&fbmode, &info->modelist);
+
/* Power up the LCDC screen */
if (sinfo->atmel_lcdfb_power_control)
sinfo->atmel_lcdfb_power_control(1);
@@ -866,6 +954,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
free_cmap:
fb_dealloc_cmap(&info->cmap);
unregister_irqs:
+ cancel_work_sync(&sinfo->task);
free_irq(sinfo->irq_base, info);
unmap_mmio:
exit_backlight(sinfo);
@@ -903,6 +992,7 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
if (!sinfo)
return 0;
+ cancel_work_sync(&sinfo->task);
exit_backlight(sinfo);
if (sinfo->atmel_lcdfb_power_control)
sinfo->atmel_lcdfb_power_control(0);
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 24ee96c4e9e..243ea4ab20c 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -1339,10 +1339,8 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
if (vclk * 12 < c.ppll_min)
vclk = c.ppll_min/12;
- pll->post_divider = -1;
-
/* now, find an acceptable divider */
- for (i = 0; i < sizeof(post_dividers); i++) {
+ for (i = 0; i < ARRAY_SIZE(post_dividers); i++) {
output_freq = post_dividers[i] * vclk;
if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) {
pll->post_divider = post_dividers[i];
@@ -1350,7 +1348,7 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
}
}
- if (pll->post_divider < 0)
+ if (i == ARRAY_SIZE(post_dividers))
return -EINVAL;
/* calculate feedback divider */
@@ -1872,7 +1870,7 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i
struct fb_info *info = pci_get_drvdata(pdev);
struct aty128fb_par *par = info->par;
struct fb_var_screeninfo var;
- char video_card[DEVICE_NAME_SIZE];
+ char video_card[50];
u8 chip_rev;
u32 dac;
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index bd4ac0bafec..620ba812036 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -424,7 +424,6 @@ static struct {
#endif /* CONFIG_FB_ATY_CT */
};
-/* can not fail */
static int __devinit correct_chipset(struct atyfb_par *par)
{
u8 rev;
@@ -437,6 +436,9 @@ static int __devinit correct_chipset(struct atyfb_par *par)
if (par->pci_id == aty_chips[i].pci_id)
break;
+ if (i < 0)
+ return -ENODEV;
+
name = aty_chips[i].name;
par->pll_limits.pll_max = aty_chips[i].pll;
par->pll_limits.mclk = aty_chips[i].mclk;
@@ -2229,6 +2231,7 @@ static int __devinit aty_init(struct fb_info *info)
const char *ramname = NULL, *xtal;
int gtb_memsize, has_var = 0;
struct fb_var_screeninfo var;
+ int ret;
init_waitqueue_head(&par->vblank.wait);
spin_lock_init(&par->int_lock);
@@ -2610,7 +2613,8 @@ static int __devinit aty_init(struct fb_info *info)
var.yres_virtual = var.yres;
}
- if (atyfb_check_var(&var, info)) {
+ ret = atyfb_check_var(&var, info);
+ if (ret) {
PRINTKE("can't set default video mode\n");
goto aty_init_exit;
}
@@ -2621,10 +2625,12 @@ static int __devinit aty_init(struct fb_info *info)
#endif /* CONFIG_FB_ATY_CT */
info->var = var;
- if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (ret < 0)
goto aty_init_exit;
- if (register_framebuffer(info) < 0) {
+ ret = register_framebuffer(info);
+ if (ret < 0) {
fb_dealloc_cmap(&info->cmap);
goto aty_init_exit;
}
@@ -2650,7 +2656,7 @@ aty_init_exit:
par->mtrr_aper = -1;
}
#endif
- return -1;
+ return ret;
}
static void aty_resume_chip(struct fb_info *info)
@@ -2709,8 +2715,7 @@ static int atyfb_blank(int blank, struct fb_info *info)
if (par->lock_blank || par->asleep)
return 0;
-#ifdef CONFIG_FB_ATY_BACKLIGHT
-#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
if (par->lcd_table && blank > FB_BLANK_NORMAL &&
(aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
@@ -2739,8 +2744,7 @@ static int atyfb_blank(int blank, struct fb_info *info)
}
aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
-#ifdef CONFIG_FB_ATY_BACKLIGHT
-#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
(aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
@@ -3331,7 +3335,7 @@ static int __devinit init_from_bios(struct atyfb_par *par)
PRINTKE("no BIOS frequency table found, use parameters\n");
ret = -ENXIO;
}
- iounmap((void* __iomem )bios_base);
+ iounmap((void __iomem *)bios_base);
return ret;
}
@@ -3418,14 +3422,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
struct fb_info *info;
struct resource *rp;
struct atyfb_par *par;
- int i, rc = -ENOMEM;
-
- for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--)
- if (pdev->device == aty_chips[i].pci_id)
- break;
-
- if (i < 0)
- return -ENODEV;
+ int rc = -ENOMEM;
/* Enable device in PCI config */
if (pci_enable_device(pdev)) {
@@ -3456,7 +3453,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
par = info->par;
info->fix = atyfb_fix;
info->device = &pdev->dev;
- par->pci_id = aty_chips[i].pci_id;
+ par->pci_id = pdev->device;
par->res_start = res_start;
par->res_size = res_size;
par->irq = pdev->irq;
@@ -3474,7 +3471,8 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
pci_set_drvdata(pdev, info);
/* Init chip & register framebuffer */
- if (aty_init(info))
+ rc = aty_init(info);
+ if (rc)
goto err_release_io;
#ifdef __sparc__
@@ -3655,18 +3653,62 @@ static void __devexit atyfb_pci_remove(struct pci_dev *pdev)
atyfb_remove(info);
}
-/*
- * This driver uses its own matching table. That will be more difficult
- * to fix, so for now, we just match against any ATI ID and let the
- * probe() function find out what's up. That also mean we don't have
- * a module ID table though.
- */
static struct pci_device_id atyfb_pci_tbl[] = {
- { PCI_VENDOR_ID_ATI, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
- PCI_BASE_CLASS_DISPLAY << 16, 0xff0000, 0 },
- { 0, }
+#ifdef CONFIG_FB_ATY_GX
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GX) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64CX) },
+#endif /* CONFIG_FB_ATY_GX */
+
+#ifdef CONFIG_FB_ATY_CT
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64CT) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64ET) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LT) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VT) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GT) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VU) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GU) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LG) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VV) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GV) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GW) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GY) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GZ) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GB) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GD) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GI) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GP) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GQ) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LB) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LD) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LI) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LP) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LQ) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GM) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GN) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GO) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GL) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GR) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GS) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LM) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LN) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LR) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LS) },
+#endif /* CONFIG_FB_ATY_CT */
+ { }
};
+MODULE_DEVICE_TABLE(pci, atyfb_pci_tbl);
+
static struct pci_driver atyfb_driver = {
.name = "atyfb",
.id_table = atyfb_pci_tbl,
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 400e9264e45..652273e9f5f 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -2098,15 +2098,7 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u8 *edid)
{
- if (off > EDID_LENGTH)
- return 0;
-
- if (off + count > EDID_LENGTH)
- count = EDID_LENGTH - off;
-
- memcpy(buf, edid + off, count);
-
- return count;
+ return memory_read_from_buffer(buf, count, &off, edid, EDID_LENGTH);
}
@@ -2161,6 +2153,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
struct radeonfb_info *rinfo;
int ret;
unsigned char c1, c2;
+ int err = 0;
pr_debug("radeonfb_pci_register BEGIN\n");
@@ -2340,9 +2333,14 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
/* Register some sysfs stuff (should be done better) */
if (rinfo->mon1_EDID)
- sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid1_attr);
+ err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj,
+ &edid1_attr);
if (rinfo->mon2_EDID)
- sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr);
+ err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj,
+ &edid2_attr);
+ if (err)
+ pr_warning("%s() Creating sysfs files failed, continuing\n",
+ __func__);
/* save current mode regs before we switch into the new one
* so we can restore this upon __exit
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index c347e38cd0b..ccbfffd1280 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -289,7 +289,7 @@ struct radeonfb_info {
struct radeon_regs state;
struct radeon_regs init_state;
- char name[DEVICE_NAME_SIZE];
+ char name[50];
unsigned long mmio_base_phys;
unsigned long fb_base_phys;
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 30bf7f2f163..452b770d8cc 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -36,6 +36,30 @@ config LCD_LTV350QV
The LTV350QV panel is present on all ATSTK1000 boards.
+config LCD_ILI9320
+ tristate
+ depends on LCD_CLASS_DEVICE && BACKLIGHT_LCD_SUPPORT
+ default n
+ help
+ If you have a panel based on the ILI9320 controller chip
+ then say y to include a power driver for it.
+
+config LCD_VGG2432A4
+ tristate "VGG2432A4 LCM device support"
+ depends on BACKLIGHT_LCD_SUPPORT && LCD_CLASS_DEVICE && SPI_MASTER
+ select LCD_ILI9320
+ default n
+ help
+ If you have a VGG2432A4 panel based on the ILI9320 controller chip
+ then say y to include a power driver for it.
+
+config LCD_PLATFORM
+ tristate "Platform LCD controls"
+ depends on LCD_CLASS_DEVICE
+ help
+ This driver provides a platform-device registered LCD power
+ control interface.
+
#
# Backlight
#
@@ -63,6 +87,18 @@ config BACKLIGHT_ATMEL_LCDC
If in doubt, it's safe to enable this option; it doesn't kick
in unless the board's description says it's wired that way.
+config BACKLIGHT_ATMEL_PWM
+ tristate "Atmel PWM backlight control"
+ depends on BACKLIGHT_CLASS_DEVICE && ATMEL_PWM
+ default n
+ help
+ Say Y here if you want to use the PWM peripheral in Atmel AT91 and
+ AVR32 devices. This driver will need additional platform data to know
+ which PWM instance to use and how to configure it.
+
+ To compile this driver as a module, choose M here: the module will be
+ called atmel-pwm-bl.
+
config BACKLIGHT_CORGI
tristate "Generic (aka Sharp Corgi) Backlight Driver"
depends on BACKLIGHT_CLASS_DEVICE
@@ -119,3 +155,12 @@ config BACKLIGHT_PWM
help
If you have a LCD backlight adjustable by PWM, say Y to enable
this driver.
+
+config BACKLIGHT_MBP_NVIDIA
+ tristate "MacBook Pro Nvidia Backlight Driver"
+ depends on BACKLIGHT_CLASS_DEVICE && X86
+ default n
+ help
+ If you have an Apple Macbook Pro with Nvidia graphics hardware say Y
+ to enable a driver for its backlight
+
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index b51a7cd1250..b405aace803 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -1,9 +1,13 @@
# Backlight & LCD drivers
obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
-obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
+obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
+obj-$(CONFIG_LCD_ILI9320) += ili9320.o
+obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o
+obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o
obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
+obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o
obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o
obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
@@ -11,3 +15,5 @@ obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
+obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
+
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
new file mode 100644
index 00000000000..505c0823a10
--- /dev/null
+++ b/drivers/video/backlight/atmel-pwm-bl.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2008 Atmel Corporation
+ *
+ * Backlight driver using Atmel PWM peripheral.
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/backlight.h>
+#include <linux/atmel_pwm.h>
+#include <linux/atmel-pwm-bl.h>
+
+struct atmel_pwm_bl {
+ const struct atmel_pwm_bl_platform_data *pdata;
+ struct backlight_device *bldev;
+ struct platform_device *pdev;
+ struct pwm_channel pwmc;
+ int gpio_on;
+};
+
+static int atmel_pwm_bl_set_intensity(struct backlight_device *bd)
+{
+ struct atmel_pwm_bl *pwmbl = bl_get_data(bd);
+ int intensity = bd->props.brightness;
+ int pwm_duty;
+
+ if (bd->props.power != FB_BLANK_UNBLANK)
+ intensity = 0;
+ if (bd->props.fb_blank != FB_BLANK_UNBLANK)
+ intensity = 0;
+
+ if (pwmbl->pdata->pwm_active_low)
+ pwm_duty = pwmbl->pdata->pwm_duty_min + intensity;
+ else
+ pwm_duty = pwmbl->pdata->pwm_duty_max - intensity;
+
+ if (pwm_duty > pwmbl->pdata->pwm_duty_max)
+ pwm_duty = pwmbl->pdata->pwm_duty_max;
+ if (pwm_duty < pwmbl->pdata->pwm_duty_min)
+ pwm_duty = pwmbl->pdata->pwm_duty_min;
+
+ if (!intensity) {
+ if (pwmbl->gpio_on != -1) {
+ gpio_set_value(pwmbl->gpio_on,
+ 0 ^ pwmbl->pdata->on_active_low);
+ }
+ pwm_channel_writel(&pwmbl->pwmc, PWM_CUPD, pwm_duty);
+ pwm_channel_disable(&pwmbl->pwmc);
+ } else {
+ pwm_channel_enable(&pwmbl->pwmc);
+ pwm_channel_writel(&pwmbl->pwmc, PWM_CUPD, pwm_duty);
+ if (pwmbl->gpio_on != -1) {
+ gpio_set_value(pwmbl->gpio_on,
+ 1 ^ pwmbl->pdata->on_active_low);
+ }
+ }
+
+ return 0;
+}
+
+static int atmel_pwm_bl_get_intensity(struct backlight_device *bd)
+{
+ struct atmel_pwm_bl *pwmbl = bl_get_data(bd);
+ u8 intensity;
+
+ if (pwmbl->pdata->pwm_active_low) {
+ intensity = pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY) -
+ pwmbl->pdata->pwm_duty_min;
+ } else {
+ intensity = pwmbl->pdata->pwm_duty_max -
+ pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY);
+ }
+
+ return intensity;
+}
+
+static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl)
+{
+ unsigned long pwm_rate = pwmbl->pwmc.mck;
+ unsigned long prescale = DIV_ROUND_UP(pwm_rate,
+ (pwmbl->pdata->pwm_frequency *
+ pwmbl->pdata->pwm_compare_max)) - 1;
+
+ /*
+ * Prescale must be power of two and maximum 0xf in size because of
+ * hardware limit. PWM speed will be:
+ * PWM module clock speed / (2 ^ prescale).
+ */
+ prescale = fls(prescale);
+ if (prescale > 0xf)
+ prescale = 0xf;
+
+ pwm_channel_writel(&pwmbl->pwmc, PWM_CMR, prescale);
+ pwm_channel_writel(&pwmbl->pwmc, PWM_CDTY,
+ pwmbl->pdata->pwm_duty_min +
+ pwmbl->bldev->props.brightness);
+ pwm_channel_writel(&pwmbl->pwmc, PWM_CPRD,
+ pwmbl->pdata->pwm_compare_max);
+
+ dev_info(&pwmbl->pdev->dev, "Atmel PWM backlight driver "
+ "(%lu Hz)\n", pwmbl->pwmc.mck /
+ pwmbl->pdata->pwm_compare_max /
+ (1 << prescale));
+
+ return pwm_channel_enable(&pwmbl->pwmc);
+}
+
+static struct backlight_ops atmel_pwm_bl_ops = {
+ .get_brightness = atmel_pwm_bl_get_intensity,
+ .update_status = atmel_pwm_bl_set_intensity,
+};
+
+static int atmel_pwm_bl_probe(struct platform_device *pdev)
+{
+ const struct atmel_pwm_bl_platform_data *pdata;
+ struct backlight_device *bldev;
+ struct atmel_pwm_bl *pwmbl;
+ int retval;
+
+ pwmbl = kzalloc(sizeof(struct atmel_pwm_bl), GFP_KERNEL);
+ if (!pwmbl)
+ return -ENOMEM;
+
+ pwmbl->pdev = pdev;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ retval = -ENODEV;
+ goto err_free_mem;
+ }
+
+ if (pdata->pwm_compare_max < pdata->pwm_duty_max ||
+ pdata->pwm_duty_min > pdata->pwm_duty_max ||
+ pdata->pwm_frequency == 0) {
+ retval = -EINVAL;
+ goto err_free_mem;
+ }
+
+ pwmbl->pdata = pdata;
+ pwmbl->gpio_on = pdata->gpio_on;
+
+ retval = pwm_channel_alloc(pdata->pwm_channel, &pwmbl->pwmc);
+ if (retval)
+ goto err_free_mem;
+
+ if (pwmbl->gpio_on != -1) {
+ retval = gpio_request(pwmbl->gpio_on, "gpio_atmel_pwm_bl");
+ if (retval) {
+ pwmbl->gpio_on = -1;
+ goto err_free_pwm;
+ }
+
+ /* Turn display off by defatult. */
+ retval = gpio_direction_output(pwmbl->gpio_on,
+ 0 ^ pdata->on_active_low);
+ if (retval)
+ goto err_free_gpio;
+ }
+
+ bldev = backlight_device_register("atmel-pwm-bl",
+ &pdev->dev, pwmbl, &atmel_pwm_bl_ops);
+ if (IS_ERR(bldev)) {
+ retval = PTR_ERR(bldev);
+ goto err_free_gpio;
+ }
+
+ pwmbl->bldev = bldev;
+
+ platform_set_drvdata(pdev, pwmbl);
+
+ /* Power up the backlight by default at middle intesity. */
+ bldev->props.power = FB_BLANK_UNBLANK;
+ bldev->props.max_brightness = pdata->pwm_duty_max - pdata->pwm_duty_min;
+ bldev->props.brightness = bldev->props.max_brightness / 2;
+
+ retval = atmel_pwm_bl_init_pwm(pwmbl);
+ if (retval)
+ goto err_free_bl_dev;
+
+ atmel_pwm_bl_set_intensity(bldev);
+
+ return 0;
+
+err_free_bl_dev:
+ platform_set_drvdata(pdev, NULL);
+ backlight_device_unregister(bldev);
+err_free_gpio:
+ if (pwmbl->gpio_on != -1)
+ gpio_free(pwmbl->gpio_on);
+err_free_pwm:
+ pwm_channel_free(&pwmbl->pwmc);
+err_free_mem:
+ kfree(pwmbl);
+ return retval;
+}
+
+static int __exit atmel_pwm_bl_remove(struct platform_device *pdev)
+{
+ struct atmel_pwm_bl *pwmbl = platform_get_drvdata(pdev);
+
+ if (pwmbl->gpio_on != -1) {
+ gpio_set_value(pwmbl->gpio_on, 0);
+ gpio_free(pwmbl->gpio_on);
+ }
+ pwm_channel_disable(&pwmbl->pwmc);
+ pwm_channel_free(&pwmbl->pwmc);
+ backlight_device_unregister(pwmbl->bldev);
+ platform_set_drvdata(pdev, NULL);
+ kfree(pwmbl);
+
+ return 0;
+}
+
+static struct platform_driver atmel_pwm_bl_driver = {
+ .driver = {
+ .name = "atmel-pwm-bl",
+ },
+ /* REVISIT add suspend() and resume() */
+ .remove = __exit_p(atmel_pwm_bl_remove),
+};
+
+static int __init atmel_pwm_bl_init(void)
+{
+ return platform_driver_probe(&atmel_pwm_bl_driver, atmel_pwm_bl_probe);
+}
+module_init(atmel_pwm_bl_init);
+
+static void __exit atmel_pwm_bl_exit(void)
+{
+ platform_driver_unregister(&atmel_pwm_bl_driver);
+}
+module_exit(atmel_pwm_bl_exit);
+
+MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>");
+MODULE_DESCRIPTION("Atmel PWM backlight driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 39394757679..fab0bc874b5 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -191,6 +191,7 @@ static struct device_attribute bl_device_attributes[] = {
* backlight_device class.
* @name: the name of the new object(must be the same as the name of the
* respective framebuffer device).
+ * @parent: a pointer to the parent device
* @devdata: an optional pointer to be stored for private driver use. The
* methods may retrieve it by using bl_get_data(bd).
* @ops: the backlight operations structure.
diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c
new file mode 100644
index 00000000000..ba89b41b639
--- /dev/null
+++ b/drivers/video/backlight/ili9320.c
@@ -0,0 +1,330 @@
+/* drivers/video/backlight/ili9320.c
+ *
+ * ILI9320 LCD controller driver core.
+ *
+ * Copyright 2007 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/lcd.h>
+#include <linux/module.h>
+
+#include <linux/spi/spi.h>
+
+#include <video/ili9320.h>
+
+#include "ili9320.h"
+
+
+static inline int ili9320_write_spi(struct ili9320 *ili,
+ unsigned int reg,
+ unsigned int value)
+{
+ struct ili9320_spi *spi = &ili->access.spi;
+ unsigned char *addr = spi->buffer_addr;
+ unsigned char *data = spi->buffer_data;
+
+ /* spi message consits of:
+ * first byte: ID and operation
+ */
+
+ addr[0] = spi->id | ILI9320_SPI_INDEX | ILI9320_SPI_WRITE;
+ addr[1] = reg >> 8;
+ addr[2] = reg;
+
+ /* second message is the data to transfer */
+
+ data[0] = spi->id | ILI9320_SPI_DATA | ILI9320_SPI_WRITE;
+ data[1] = value >> 8;
+ data[2] = value;
+
+ return spi_sync(spi->dev, &spi->message);
+}
+
+int ili9320_write(struct ili9320 *ili, unsigned int reg, unsigned int value)
+{
+ dev_dbg(ili->dev, "write: reg=%02x, val=%04x\n", reg, value);
+ return ili->write(ili, reg, value);
+}
+
+EXPORT_SYMBOL_GPL(ili9320_write);
+
+int ili9320_write_regs(struct ili9320 *ili,
+ struct ili9320_reg *values,
+ int nr_values)
+{
+ int index;
+ int ret;
+
+ for (index = 0; index < nr_values; index++, values++) {
+ ret = ili9320_write(ili, values->address, values->value);
+ if (ret != 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ili9320_write_regs);
+
+static void ili9320_reset(struct ili9320 *lcd)
+{
+ struct ili9320_platdata *cfg = lcd->platdata;
+
+ cfg->reset(1);
+ mdelay(50);
+
+ cfg->reset(0);
+ mdelay(50);
+
+ cfg->reset(1);
+ mdelay(100);
+}
+
+static inline int ili9320_init_chip(struct ili9320 *lcd)
+{
+ int ret;
+
+ ili9320_reset(lcd);
+
+ ret = lcd->client->init(lcd, lcd->platdata);
+ if (ret != 0) {
+ dev_err(lcd->dev, "failed to initialise display\n");
+ return ret;
+ }
+
+ lcd->initialised = 1;
+ return 0;
+}
+
+static inline int ili9320_power_on(struct ili9320 *lcd)
+{
+ if (!lcd->initialised)
+ ili9320_init_chip(lcd);
+
+ lcd->display1 |= (ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_BASEE);
+ ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1);
+
+ return 0;
+}
+
+static inline int ili9320_power_off(struct ili9320 *lcd)
+{
+ lcd->display1 &= ~(ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_BASEE);
+ ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1);
+
+ return 0;
+}
+
+#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
+
+static int ili9320_power(struct ili9320 *lcd, int power)
+{
+ int ret = 0;
+
+ dev_dbg(lcd->dev, "power %d => %d\n", lcd->power, power);
+
+ if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
+ ret = ili9320_power_on(lcd);
+ else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
+ ret = ili9320_power_off(lcd);
+
+ if (ret == 0)
+ lcd->power = power;
+ else
+ dev_warn(lcd->dev, "failed to set power mode %d\n", power);
+
+ return ret;
+}
+
+static inline struct ili9320 *to_our_lcd(struct lcd_device *lcd)
+{
+ return lcd_get_data(lcd);
+}
+
+static int ili9320_set_power(struct lcd_device *ld, int power)
+{
+ struct ili9320 *lcd = to_our_lcd(ld);
+
+ return ili9320_power(lcd, power);
+}
+
+static int ili9320_get_power(struct lcd_device *ld)
+{
+ struct ili9320 *lcd = to_our_lcd(ld);
+
+ return lcd->power;
+}
+
+static struct lcd_ops ili9320_ops = {
+ .get_power = ili9320_get_power,
+ .set_power = ili9320_set_power,
+};
+
+static void __devinit ili9320_setup_spi(struct ili9320 *ili,
+ struct spi_device *dev)
+{
+ struct ili9320_spi *spi = &ili->access.spi;
+
+ ili->write = ili9320_write_spi;
+ spi->dev = dev;
+
+ /* fill the two messages we are going to use to send the data
+ * with, the first the address followed by the data. The datasheet
+ * says they should be done as two distinct cycles of the SPI CS line.
+ */
+
+ spi->xfer[0].tx_buf = spi->buffer_addr;
+ spi->xfer[1].tx_buf = spi->buffer_data;
+ spi->xfer[0].len = 3;
+ spi->xfer[1].len = 3;
+ spi->xfer[0].bits_per_word = 8;
+ spi->xfer[1].bits_per_word = 8;
+ spi->xfer[0].cs_change = 1;
+
+ spi_message_init(&spi->message);
+ spi_message_add_tail(&spi->xfer[0], &spi->message);
+ spi_message_add_tail(&spi->xfer[1], &spi->message);
+}
+
+int __devinit ili9320_probe_spi(struct spi_device *spi,
+ struct ili9320_client *client)
+{
+ struct ili9320_platdata *cfg = spi->dev.platform_data;
+ struct device *dev = &spi->dev;
+ struct ili9320 *ili;
+ struct lcd_device *lcd;
+ int ret = 0;
+
+ /* verify we where given some information */
+
+ if (cfg == NULL) {
+ dev_err(dev, "no platform data supplied\n");
+ return -EINVAL;
+ }
+
+ if (cfg->hsize <= 0 || cfg->vsize <= 0 || cfg->reset == NULL) {
+ dev_err(dev, "invalid platform data supplied\n");
+ return -EINVAL;
+ }
+
+ /* allocate and initialse our state */
+
+ ili = kzalloc(sizeof(struct ili9320), GFP_KERNEL);
+ if (ili == NULL) {
+ dev_err(dev, "no memory for device\n");
+ return -ENOMEM;
+ }
+
+ ili->access.spi.id = ILI9320_SPI_IDCODE | ILI9320_SPI_ID(1);
+
+ ili->dev = dev;
+ ili->client = client;
+ ili->power = FB_BLANK_POWERDOWN;
+ ili->platdata = cfg;
+
+ dev_set_drvdata(&spi->dev, ili);
+
+ ili9320_setup_spi(ili, spi);
+
+ lcd = lcd_device_register("ili9320", dev, ili, &ili9320_ops);
+ if (IS_ERR(lcd)) {
+ dev_err(dev, "failed to register lcd device\n");
+ ret = PTR_ERR(lcd);
+ goto err_free;
+ }
+
+ ili->lcd = lcd;
+
+ dev_info(dev, "initialising %s\n", client->name);
+
+ ret = ili9320_power(ili, FB_BLANK_UNBLANK);
+ if (ret != 0) {
+ dev_err(dev, "failed to set lcd power state\n");
+ goto err_unregister;
+ }
+
+ return 0;
+
+ err_unregister:
+ lcd_device_unregister(lcd);
+
+ err_free:
+ kfree(ili);
+
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ili9320_probe_spi);
+
+int __devexit ili9320_remove(struct ili9320 *ili)
+{
+ ili9320_power(ili, FB_BLANK_POWERDOWN);
+
+ lcd_device_unregister(ili->lcd);
+ kfree(ili);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ili9320_remove);
+
+#ifdef CONFIG_PM
+int ili9320_suspend(struct ili9320 *lcd, pm_message_t state)
+{
+ int ret;
+
+ dev_dbg(lcd->dev, "%s: event %d\n", __func__, state.event);
+
+ if (state.event == PM_EVENT_SUSPEND) {
+ ret = ili9320_power(lcd, FB_BLANK_POWERDOWN);
+
+ if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) {
+ ili9320_write(lcd, ILI9320_POWER1, lcd->power1 |
+ ILI9320_POWER1_SLP |
+ ILI9320_POWER1_DSTB);
+ lcd->initialised = 0;
+ }
+
+ return ret;
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ili9320_suspend);
+
+int ili9320_resume(struct ili9320 *lcd)
+{
+ dev_info(lcd->dev, "resuming from power state %d\n", lcd->power);
+
+ if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) {
+ ili9320_write(lcd, ILI9320_POWER1, 0x00);
+ }
+
+ return ili9320_power(lcd, FB_BLANK_UNBLANK);
+}
+
+EXPORT_SYMBOL_GPL(ili9320_resume);
+#endif
+
+/* Power down all displays on reboot, poweroff or halt */
+void ili9320_shutdown(struct ili9320 *lcd)
+{
+ ili9320_power(lcd, FB_BLANK_POWERDOWN);
+}
+
+EXPORT_SYMBOL_GPL(ili9320_shutdown);
+
+MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
+MODULE_DESCRIPTION("ILI9320 LCD Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/backlight/ili9320.h b/drivers/video/backlight/ili9320.h
new file mode 100644
index 00000000000..e388eca7cac
--- /dev/null
+++ b/drivers/video/backlight/ili9320.h
@@ -0,0 +1,80 @@
+/* drivers/video/backlight/ili9320.h
+ *
+ * ILI9320 LCD controller driver core.
+ *
+ * Copyright 2007 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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.
+*/
+
+/* Holder for register and value pairs. */
+struct ili9320_reg {
+ unsigned short address;
+ unsigned short value;
+};
+
+struct ili9320;
+
+struct ili9320_client {
+ const char *name;
+ int (*init)(struct ili9320 *ili, struct ili9320_platdata *cfg);
+
+};
+/* Device attached via an SPI bus. */
+struct ili9320_spi {
+ struct spi_device *dev;
+ struct spi_message message;
+ struct spi_transfer xfer[2];
+
+ unsigned char id;
+ unsigned char buffer_addr[4];
+ unsigned char buffer_data[4];
+};
+
+/* ILI9320 device state. */
+struct ili9320 {
+ union {
+ struct ili9320_spi spi; /* SPI attachged device. */
+ } access; /* Register access method. */
+
+ struct device *dev;
+ struct lcd_device *lcd; /* LCD device we created. */
+ struct ili9320_client *client;
+ struct ili9320_platdata *platdata;
+
+ int power; /* current power state. */
+ int initialised;
+
+ unsigned short display1;
+ unsigned short power1;
+
+ int (*write)(struct ili9320 *ili, unsigned int reg, unsigned int val);
+};
+
+
+/* ILI9320 register access routines */
+
+extern int ili9320_write(struct ili9320 *ili,
+ unsigned int reg, unsigned int value);
+
+extern int ili9320_write_regs(struct ili9320 *ili,
+ struct ili9320_reg *values,
+ int nr_values);
+
+/* Device probe */
+
+extern int ili9320_probe_spi(struct spi_device *spi,
+ struct ili9320_client *cli);
+
+extern int ili9320_remove(struct ili9320 *lcd);
+extern void ili9320_shutdown(struct ili9320 *lcd);
+
+/* PM */
+
+extern int ili9320_suspend(struct ili9320 *lcd, pm_message_t state);
+extern int ili9320_resume(struct ili9320 *lcd);
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 299fd318dd4..b15b2b84a6f 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -33,7 +33,7 @@ static int fb_notifier_callback(struct notifier_block *self,
ld = container_of(self, struct lcd_device, fb_notif);
mutex_lock(&ld->ops_lock);
if (ld->ops)
- if (!ld->ops->check_fb || ld->ops->check_fb(evdata->info))
+ if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info))
ld->ops->set_power(ld, *(int *)evdata->data);
mutex_unlock(&ld->ops_lock);
return 0;
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
new file mode 100644
index 00000000000..385cba40ea8
--- /dev/null
+++ b/drivers/video/backlight/mbp_nvidia_bl.c
@@ -0,0 +1,116 @@
+/*
+ * Backlight Driver for Nvidia 8600 in Macbook Pro
+ *
+ * Copyright (c) Red Hat <mjg@redhat.com>
+ * Based on code from Pommed:
+ * Copyright (C) 2006 Nicolas Boichat <nicolas @boichat.ch>
+ * Copyright (C) 2006 Felipe Alfaro Solana <felipe_alfaro @linuxmail.org>
+ * Copyright (C) 2007 Julien BLACHE <jb@jblache.org>
+ *
+ * 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.
+ *
+ * This driver triggers SMIs which cause the firmware to change the
+ * backlight brightness. This is icky in many ways, but it's impractical to
+ * get at the firmware code in order to figure out what it's actually doing.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/dmi.h>
+#include <linux/io.h>
+
+static struct backlight_device *mbp_backlight_device;
+
+static struct dmi_system_id __initdata mbp_device_table[] = {
+ {
+ .ident = "3,1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
+ },
+ },
+ {
+ .ident = "3,2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,2"),
+ },
+ },
+ {
+ .ident = "4,1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4,1"),
+ },
+ },
+ { }
+};
+
+static int mbp_send_intensity(struct backlight_device *bd)
+{
+ int intensity = bd->props.brightness;
+
+ outb(0x04 | (intensity << 4), 0xb3);
+ outb(0xbf, 0xb2);
+
+ return 0;
+}
+
+static int mbp_get_intensity(struct backlight_device *bd)
+{
+ outb(0x03, 0xb3);
+ outb(0xbf, 0xb2);
+ return inb(0xb3) >> 4;
+}
+
+static struct backlight_ops mbp_ops = {
+ .get_brightness = mbp_get_intensity,
+ .update_status = mbp_send_intensity,
+};
+
+static int __init mbp_init(void)
+{
+ if (!dmi_check_system(mbp_device_table))
+ return -ENODEV;
+
+ if (!request_region(0xb2, 2, "Macbook Pro backlight"))
+ return -ENXIO;
+
+ mbp_backlight_device = backlight_device_register("mbp_backlight",
+ NULL, NULL,
+ &mbp_ops);
+ if (IS_ERR(mbp_backlight_device)) {
+ release_region(0xb2, 2);
+ return PTR_ERR(mbp_backlight_device);
+ }
+
+ mbp_backlight_device->props.max_brightness = 15;
+ mbp_backlight_device->props.brightness =
+ mbp_get_intensity(mbp_backlight_device);
+ backlight_update_status(mbp_backlight_device);
+
+ return 0;
+}
+
+static void __exit mbp_exit(void)
+{
+ backlight_device_unregister(mbp_backlight_device);
+
+ release_region(0xb2, 2);
+}
+
+module_init(mbp_init);
+module_exit(mbp_exit);
+
+MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
+MODULE_DESCRIPTION("Nvidia-based Macbook Pro Backlight Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("svnAppleInc.:pnMacBookPro3,1");
+MODULE_ALIAS("svnAppleInc.:pnMacBookPro3,2");
+MODULE_ALIAS("svnAppleInc.:pnMacBookPro4,1");
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
new file mode 100644
index 00000000000..72d44dbfce8
--- /dev/null
+++ b/drivers/video/backlight/platform_lcd.c
@@ -0,0 +1,172 @@
+/* drivers/video/backlight/platform_lcd.c
+ *
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Generic platform-device LCD power control interface.
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+
+#include <video/platform_lcd.h>
+
+struct platform_lcd {
+ struct device *us;
+ struct lcd_device *lcd;
+ struct plat_lcd_data *pdata;
+
+ unsigned int power;
+ unsigned int suspended : 1;
+};
+
+static inline struct platform_lcd *to_our_lcd(struct lcd_device *lcd)
+{
+ return lcd_get_data(lcd);
+}
+
+static int platform_lcd_get_power(struct lcd_device *lcd)
+{
+ struct platform_lcd *plcd = to_our_lcd(lcd);
+
+ return plcd->power;
+}
+
+static int platform_lcd_set_power(struct lcd_device *lcd, int power)
+{
+ struct platform_lcd *plcd = to_our_lcd(lcd);
+ int lcd_power = 1;
+
+ if (power == FB_BLANK_POWERDOWN || plcd->suspended)
+ lcd_power = 0;
+
+ plcd->pdata->set_power(plcd->pdata, lcd_power);
+ plcd->power = power;
+
+ return 0;
+}
+
+static int platform_lcd_match(struct lcd_device *lcd, struct fb_info *info)
+{
+ struct platform_lcd *plcd = to_our_lcd(lcd);
+ struct plat_lcd_data *pdata = plcd->pdata;
+
+ if (pdata->match_fb)
+ return pdata->match_fb(pdata, info);
+
+ return plcd->us->parent == info->device;
+}
+
+static struct lcd_ops platform_lcd_ops = {
+ .get_power = platform_lcd_get_power,
+ .set_power = platform_lcd_set_power,
+ .check_fb = platform_lcd_match,
+};
+
+static int __devinit platform_lcd_probe(struct platform_device *pdev)
+{
+ struct plat_lcd_data *pdata;
+ struct platform_lcd *plcd;
+ struct device *dev = &pdev->dev;
+ int err;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ dev_err(dev, "no platform data supplied\n");
+ return -EINVAL;
+ }
+
+ plcd = kzalloc(sizeof(struct platform_lcd), GFP_KERNEL);
+ if (!plcd) {
+ dev_err(dev, "no memory for state\n");
+ return -ENOMEM;
+ }
+
+ plcd->us = dev;
+ plcd->pdata = pdata;
+ plcd->lcd = lcd_device_register("platform-lcd", dev,
+ plcd, &platform_lcd_ops);
+ if (IS_ERR(plcd->lcd)) {
+ dev_err(dev, "cannot register lcd device\n");
+ err = PTR_ERR(plcd->lcd);
+ goto err_mem;
+ }
+
+ platform_set_drvdata(pdev, plcd);
+ return 0;
+
+ err_mem:
+ kfree(plcd);
+ return err;
+}
+
+static int __devexit platform_lcd_remove(struct platform_device *pdev)
+{
+ struct platform_lcd *plcd = platform_get_drvdata(pdev);
+
+ lcd_device_unregister(plcd->lcd);
+ kfree(plcd);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int platform_lcd_suspend(struct platform_device *pdev, pm_message_t st)
+{
+ struct platform_lcd *plcd = platform_get_drvdata(pdev);
+
+ plcd->suspended = 1;
+ platform_lcd_set_power(plcd->lcd, plcd->power);
+
+ return 0;
+}
+
+static int platform_lcd_resume(struct platform_device *pdev)
+{
+ struct platform_lcd *plcd = platform_get_drvdata(pdev);
+
+ plcd->suspended = 0;
+ platform_lcd_set_power(plcd->lcd, plcd->power);
+
+ return 0;
+}
+#else
+#define platform_lcd_suspend NULL
+#define platform_lcd_resume NULL
+#endif
+
+static struct platform_driver platform_lcd_driver = {
+ .driver = {
+ .name = "platform-lcd",
+ .owner = THIS_MODULE,
+ },
+ .probe = platform_lcd_probe,
+ .remove = __devexit_p(platform_lcd_remove),
+ .suspend = platform_lcd_suspend,
+ .resume = platform_lcd_resume,
+};
+
+static int __init platform_lcd_init(void)
+{
+ return platform_driver_register(&platform_lcd_driver);
+}
+
+static void __exit platform_lcd_cleanup(void)
+{
+ platform_driver_unregister(&platform_lcd_driver);
+}
+
+module_init(platform_lcd_init);
+module_exit(platform_lcd_cleanup);
+
+MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:platform-lcd");
diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c
new file mode 100644
index 00000000000..593c7687d54
--- /dev/null
+++ b/drivers/video/backlight/vgg2432a4.c
@@ -0,0 +1,284 @@
+/* drivers/video/backlight/vgg2432a4.c
+ *
+ * VGG2432A4 (ILI9320) LCD controller driver.
+ *
+ * Copyright 2007 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/lcd.h>
+#include <linux/module.h>
+
+#include <linux/spi/spi.h>
+
+#include <video/ili9320.h>
+
+#include "ili9320.h"
+
+/* Device initialisation sequences */
+
+static struct ili9320_reg vgg_init1[] = {
+ {
+ .address = ILI9320_POWER1,
+ .value = ILI9320_POWER1_AP(0) | ILI9320_POWER1_BT(0),
+ }, {
+ .address = ILI9320_POWER2,
+ .value = (ILI9320_POWER2_VC(7) |
+ ILI9320_POWER2_DC0(0) | ILI9320_POWER2_DC1(0)),
+ }, {
+ .address = ILI9320_POWER3,
+ .value = ILI9320_POWER3_VRH(0),
+ }, {
+ .address = ILI9320_POWER4,
+ .value = ILI9320_POWER4_VREOUT(0),
+ },
+};
+
+static struct ili9320_reg vgg_init2[] = {
+ {
+ .address = ILI9320_POWER1,
+ .value = (ILI9320_POWER1_AP(3) | ILI9320_POWER1_APE |
+ ILI9320_POWER1_BT(7) | ILI9320_POWER1_SAP),
+ }, {
+ .address = ILI9320_POWER2,
+ .value = ILI9320_POWER2_VC(7) | ILI9320_POWER2_DC0(3),
+ }
+};
+
+static struct ili9320_reg vgg_gamma[] = {
+ {
+ .address = ILI9320_GAMMA1,
+ .value = 0x0000,
+ }, {
+ .address = ILI9320_GAMMA2,
+ .value = 0x0505,
+ }, {
+ .address = ILI9320_GAMMA3,
+ .value = 0x0004,
+ }, {
+ .address = ILI9320_GAMMA4,
+ .value = 0x0006,
+ }, {
+ .address = ILI9320_GAMMA5,
+ .value = 0x0707,
+ }, {
+ .address = ILI9320_GAMMA6,
+ .value = 0x0105,
+ }, {
+ .address = ILI9320_GAMMA7,
+ .value = 0x0002,
+ }, {
+ .address = ILI9320_GAMMA8,
+ .value = 0x0707,
+ }, {
+ .address = ILI9320_GAMMA9,
+ .value = 0x0704,
+ }, {
+ .address = ILI9320_GAMMA10,
+ .value = 0x807,
+ }
+
+};
+
+static struct ili9320_reg vgg_init0[] = {
+ [0] = {
+ /* set direction and scan mode gate */
+ .address = ILI9320_DRIVER,
+ .value = ILI9320_DRIVER_SS,
+ }, {
+ .address = ILI9320_DRIVEWAVE,
+ .value = (ILI9320_DRIVEWAVE_MUSTSET |
+ ILI9320_DRIVEWAVE_EOR | ILI9320_DRIVEWAVE_BC),
+ }, {
+ .address = ILI9320_ENTRYMODE,
+ .value = ILI9320_ENTRYMODE_ID(3) | ILI9320_ENTRYMODE_BGR,
+ }, {
+ .address = ILI9320_RESIZING,
+ .value = 0x0,
+ },
+};
+
+
+static int vgg2432a4_lcd_init(struct ili9320 *lcd,
+ struct ili9320_platdata *cfg)
+{
+ unsigned int addr;
+ int ret;
+
+ /* Set VCore before anything else (VGG243237-6UFLWA) */
+ ret = ili9320_write(lcd, 0x00e5, 0x8000);
+ if (ret)
+ goto err_initial;
+
+ /* Start the oscillator up before we can do anything else. */
+ ret = ili9320_write(lcd, ILI9320_OSCILATION, ILI9320_OSCILATION_OSC);
+ if (ret)
+ goto err_initial;
+
+ /* must wait at-lesat 10ms after starting */
+ mdelay(15);
+
+ ret = ili9320_write_regs(lcd, vgg_init0, ARRAY_SIZE(vgg_init0));
+ if (ret != 0)
+ goto err_initial;
+
+ ili9320_write(lcd, ILI9320_DISPLAY2, cfg->display2);
+ ili9320_write(lcd, ILI9320_DISPLAY3, cfg->display3);
+ ili9320_write(lcd, ILI9320_DISPLAY4, cfg->display4);
+
+ ili9320_write(lcd, ILI9320_RGB_IF1, cfg->rgb_if1);
+ ili9320_write(lcd, ILI9320_FRAMEMAKER, 0x0);
+ ili9320_write(lcd, ILI9320_RGB_IF2, ILI9320_RGBIF2_DPL);
+
+ ret = ili9320_write_regs(lcd, vgg_init1, ARRAY_SIZE(vgg_init1));
+ if (ret != 0)
+ goto err_vgg;
+
+ mdelay(300);
+
+ ret = ili9320_write_regs(lcd, vgg_init2, ARRAY_SIZE(vgg_init2));
+ if (ret != 0)
+ goto err_vgg2;
+
+ mdelay(100);
+
+ ili9320_write(lcd, ILI9320_POWER3, 0x13c);
+
+ mdelay(100);
+
+ ili9320_write(lcd, ILI9320_POWER4, 0x1c00);
+ ili9320_write(lcd, ILI9320_POWER7, 0x000e);
+
+ mdelay(100);
+
+ ili9320_write(lcd, ILI9320_GRAM_HORIZ_ADDR, 0x00);
+ ili9320_write(lcd, ILI9320_GRAM_VERT_ADD, 0x00);
+
+ ret = ili9320_write_regs(lcd, vgg_gamma, ARRAY_SIZE(vgg_gamma));
+ if (ret != 0)
+ goto err_vgg3;
+
+ ili9320_write(lcd, ILI9320_HORIZ_START, 0x0);
+ ili9320_write(lcd, ILI9320_HORIZ_END, cfg->hsize - 1);
+ ili9320_write(lcd, ILI9320_VERT_START, 0x0);
+ ili9320_write(lcd, ILI9320_VERT_END, cfg->vsize - 1);
+
+ ili9320_write(lcd, ILI9320_DRIVER2,
+ ILI9320_DRIVER2_NL(((cfg->vsize - 240) / 8) + 0x1D));
+
+ ili9320_write(lcd, ILI9320_BASE_IMAGE, 0x1);
+ ili9320_write(lcd, ILI9320_VERT_SCROLL, 0x00);
+
+ for (addr = ILI9320_PARTIAL1_POSITION; addr <= ILI9320_PARTIAL2_END;
+ addr++) {
+ ili9320_write(lcd, addr, 0x0);
+ }
+
+ ili9320_write(lcd, ILI9320_INTERFACE1, 0x10);
+ ili9320_write(lcd, ILI9320_INTERFACE2, cfg->interface2);
+ ili9320_write(lcd, ILI9320_INTERFACE3, cfg->interface3);
+ ili9320_write(lcd, ILI9320_INTERFACE4, cfg->interface4);
+ ili9320_write(lcd, ILI9320_INTERFACE5, cfg->interface5);
+ ili9320_write(lcd, ILI9320_INTERFACE6, cfg->interface6);
+
+ lcd->display1 = (ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_DTE |
+ ILI9320_DISPLAY1_GON | ILI9320_DISPLAY1_BASEE |
+ 0x40);
+
+ ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1);
+
+ return 0;
+
+ err_vgg3:
+ err_vgg2:
+ err_vgg:
+ err_initial:
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int vgg2432a4_suspend(struct spi_device *spi, pm_message_t state)
+{
+ return ili9320_suspend(dev_get_drvdata(&spi->dev), state);
+}
+
+static int vgg2432a4_resume(struct spi_device *spi)
+{
+ return ili9320_resume(dev_get_drvdata(&spi->dev));
+}
+#else
+#define vgg2432a4_suspend NULL
+#define vgg2432a4_resume NULL
+#endif
+
+static struct ili9320_client vgg2432a4_client = {
+ .name = "VGG2432A4",
+ .init = vgg2432a4_lcd_init,
+};
+
+/* Device probe */
+
+static int __devinit vgg2432a4_probe(struct spi_device *spi)
+{
+ int ret;
+
+ ret = ili9320_probe_spi(spi, &vgg2432a4_client);
+ if (ret != 0) {
+ dev_err(&spi->dev, "failed to initialise ili9320\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __devexit vgg2432a4_remove(struct spi_device *spi)
+{
+ return ili9320_remove(dev_get_drvdata(&spi->dev));
+}
+
+static void vgg2432a4_shutdown(struct spi_device *spi)
+{
+ ili9320_shutdown(dev_get_drvdata(&spi->dev));
+}
+
+static struct spi_driver vgg2432a4_driver = {
+ .driver = {
+ .name = "VGG2432A4",
+ .owner = THIS_MODULE,
+ },
+ .probe = vgg2432a4_probe,
+ .remove = __devexit_p(vgg2432a4_remove),
+ .shutdown = vgg2432a4_shutdown,
+ .suspend = vgg2432a4_suspend,
+ .resume = vgg2432a4_resume,
+};
+
+/* Device driver initialisation */
+
+static int __init vgg2432a4_init(void)
+{
+ return spi_register_driver(&vgg2432a4_driver);
+}
+
+static void __exit vgg2432a4_exit(void)
+{
+ spi_unregister_driver(&vgg2432a4_driver);
+}
+
+module_init(vgg2432a4_init);
+module_exit(vgg2432a4_exit);
+
+MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
+MODULE_DESCRIPTION("VGG2432A4 LCD Driver");
+MODULE_LICENSE("GPL v2");
+
+
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index 49834a67a62..940467aed13 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -478,7 +478,7 @@ static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
return 0;
}
-static int bfin_lcd_check_fb(struct fb_info *fi)
+static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi)
{
if (!fi || (fi == &bfin_bf54x_fb))
return 1;
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index 135d6dd7e67..7d1b819e501 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -396,7 +396,7 @@ static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
return 0;
}
-static int bfin_lcd_check_fb(struct fb_info *fi)
+static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi)
{
if (!fi || (fi == &bfin_t350mcqb_fb))
return 1;
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c
new file mode 100644
index 00000000000..e15bb447440
--- /dev/null
+++ b/drivers/video/carminefb.c
@@ -0,0 +1,790 @@
+/*
+ * Frame buffer driver for the Carmine GPU.
+ *
+ * The driver configures the GPU as follows
+ * - FB0 is display 0 with unique memory area
+ * - FB1 is display 1 with unique memory area
+ * - both display use 32 bit colors
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
+#include "carminefb.h"
+#include "carminefb_regs.h"
+
+#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
+#error "The endianness of the target host has not been defined."
+#endif
+
+/*
+ * The initial video mode can be supplied via two different ways:
+ * - as a string that is passed to fb_find_mode() (module option fb_mode_str)
+ * - as an integer that picks the video mode from carmine_modedb[] (module
+ * option fb_mode)
+ *
+ * If nothing is used than the initial video mode will be the
+ * CARMINEFB_DEFAULT_VIDEO_MODE member of the carmine_modedb[].
+ */
+#define CARMINEFB_DEFAULT_VIDEO_MODE 1
+
+static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
+module_param(fb_mode, uint, 444);
+MODULE_PARM_DESC(fb_mode, "Initial video mode as integer.");
+
+static char *fb_mode_str;
+module_param(fb_mode_str, charp, 444);
+MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
+
+/*
+ * Carminefb displays:
+ * 0b000 None
+ * 0b001 Display 0
+ * 0b010 Display 1
+ */
+static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1;
+module_param(fb_displays, int, 444);
+MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used");
+
+struct carmine_hw {
+ void __iomem *v_regs;
+ void __iomem *screen_mem;
+ struct fb_info *fb[MAX_DISPLAY];
+};
+
+struct carmine_resolution {
+ u32 htp;
+ u32 hsp;
+ u32 hsw;
+ u32 hdp;
+ u32 vtr;
+ u32 vsp;
+ u32 vsw;
+ u32 vdp;
+ u32 disp_mode;
+};
+
+struct carmine_fb {
+ void __iomem *display_reg;
+ void __iomem *screen_base;
+ u32 smem_offset;
+ u32 cur_mode;
+ u32 new_mode;
+ struct carmine_resolution *res;
+ u32 pseudo_palette[16];
+};
+
+static struct fb_fix_screeninfo carminefb_fix __devinitdata = {
+ .id = "Carmine",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .accel = FB_ACCEL_NONE,
+};
+
+static const struct fb_videomode carmine_modedb[] = {
+ {
+ .name = "640x480",
+ .xres = 640,
+ .yres = 480,
+ }, {
+ .name = "800x600",
+ .xres = 800,
+ .yres = 600,
+ },
+};
+
+static struct carmine_resolution car_modes[] = {
+ {
+ /* 640x480 */
+ .htp = 800,
+ .hsp = 672,
+ .hsw = 96,
+ .hdp = 640,
+ .vtr = 525,
+ .vsp = 490,
+ .vsw = 2,
+ .vdp = 480,
+ .disp_mode = 0x1400,
+ },
+ {
+ /* 800x600 */
+ .htp = 1060,
+ .hsp = 864,
+ .hsw = 72,
+ .hdp = 800,
+ .vtr = 628,
+ .vsp = 601,
+ .vsw = 2,
+ .vdp = 600,
+ .disp_mode = 0x0d00,
+ }
+};
+
+static int carmine_find_mode(const struct fb_var_screeninfo *var)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(car_modes); i++)
+ if (car_modes[i].hdp == var->xres &&
+ car_modes[i].vdp == var->yres)
+ return i;
+ return -EINVAL;
+}
+
+static void c_set_disp_reg(const struct carmine_fb *par,
+ u32 offset, u32 val)
+{
+ writel(val, par->display_reg + offset);
+}
+
+static u32 c_get_disp_reg(const struct carmine_fb *par,
+ u32 offset)
+{
+ return readl(par->display_reg + offset);
+}
+
+static void c_set_hw_reg(const struct carmine_hw *hw,
+ u32 offset, u32 val)
+{
+ writel(val, hw->v_regs + offset);
+}
+
+static u32 c_get_hw_reg(const struct carmine_hw *hw,
+ u32 offset)
+{
+ return readl(hw->v_regs + offset);
+}
+
+static int carmine_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp, struct fb_info *info)
+{
+ if (regno >= 16)
+ return 1;
+
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ transp >>= 8;
+
+ ((u32 *)info->pseudo_palette)[regno] = be32_to_cpu(transp << 24 |
+ red << 0 | green << 8 | blue << 16);
+ return 0;
+}
+
+static int carmine_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ int ret;
+
+ ret = carmine_find_mode(var);
+ if (ret < 0)
+ return ret;
+
+ if (var->grayscale || var->rotate || var->nonstd)
+ return -EINVAL;
+
+ var->xres_virtual = var->xres;
+ var->yres_virtual = var->yres;
+
+ var->bits_per_pixel = 32;
+
+#ifdef __BIG_ENDIAN
+ var->transp.offset = 24;
+ var->red.offset = 0;
+ var->green.offset = 8;
+ var->blue.offset = 16;
+#else
+ var->transp.offset = 24;
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+#endif
+
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ var->transp.length = 8;
+
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
+ var->transp.msb_right = 0;
+ return 0;
+}
+
+static void carmine_init_display_param(struct carmine_fb *par)
+{
+ u32 width;
+ u32 height;
+ u32 param;
+ u32 window_size;
+ u32 soffset = par->smem_offset;
+
+ c_set_disp_reg(par, CARMINE_DISP_REG_C_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_MLMR_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_CURSOR_MODE,
+ CARMINE_CURSOR0_PRIORITY_MASK |
+ CARMINE_CURSOR1_PRIORITY_MASK |
+ CARMINE_CURSOR_CUTZ_MASK);
+
+ /* Set default cursor position */
+ c_set_disp_reg(par, CARMINE_DISP_REG_CUR1_POS, 0 << 16 | 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_CUR2_POS, 0 << 16 | 0);
+
+ /* Set default display mode */
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0_EXT_MODE, CARMINE_WINDOW_MODE |
+ CARMINE_EXT_CMODE_DIRECT24_RGBA);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L1_EXT_MODE,
+ CARMINE_EXT_CMODE_DIRECT24_RGBA);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2_EXT_MODE, CARMINE_EXTEND_MODE |
+ CARMINE_EXT_CMODE_DIRECT24_RGBA);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3_EXT_MODE, CARMINE_EXTEND_MODE |
+ CARMINE_EXT_CMODE_DIRECT24_RGBA);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4_EXT_MODE, CARMINE_EXTEND_MODE |
+ CARMINE_EXT_CMODE_DIRECT24_RGBA);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5_EXT_MODE, CARMINE_EXTEND_MODE |
+ CARMINE_EXT_CMODE_DIRECT24_RGBA);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6_EXT_MODE, CARMINE_EXTEND_MODE |
+ CARMINE_EXT_CMODE_DIRECT24_RGBA);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7_EXT_MODE, CARMINE_EXTEND_MODE |
+ CARMINE_EXT_CMODE_DIRECT24_RGBA);
+
+ /* Set default frame size to layer mode register */
+ width = par->res->hdp * 4 / CARMINE_DISP_WIDTH_UNIT;
+ width = width << CARMINE_DISP_WIDTH_SHIFT;
+
+ height = par->res->vdp - 1;
+ param = width | height;
+
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0_MODE_W_H, param);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIDTH, width);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2_MODE_W_H, param);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3_MODE_W_H, param);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4_MODE_W_H, param);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5_MODE_W_H, param);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6_MODE_W_H, param);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7_MODE_W_H, param);
+
+ /* Set default pos and size */
+ window_size = (par->res->vdp - 1) << CARMINE_DISP_WIN_H_SHIFT;
+ window_size |= par->res->hdp;
+
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_SIZE, window_size);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_SIZE, window_size);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_SIZE, window_size);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_SIZE, window_size);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_SIZE, window_size);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_SIZE, window_size);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_SIZE, window_size);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_SIZE, window_size);
+
+ /* Set default origin address */
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0_ORG_ADR, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L1_ORG_ADR, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2_ORG_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3_ORG_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4_ORG_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5_ORG_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6_ORG_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7_ORG_ADR1, soffset);
+
+ /* Set default display address */
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_ADR, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_ADR0, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_ADR0, soffset);
+
+ /* Set default display position */
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_POS, 0);
+
+ /* Set default blend mode */
+ c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L0, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L1, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L2, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L3, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L4, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L5, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L6, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L7, 0);
+
+ /* default transparency mode */
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L1_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7_TRANS, 0);
+
+ /* Set default read skip parameter */
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0RM, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2RM, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3RM, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4RM, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5RM, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6RM, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7RM, 0);
+
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0PX, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2PX, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3PX, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4PX, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5PX, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6PX, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7PX, 0);
+
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0PY, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2PY, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3PY, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4PY, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5PY, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6PY, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7PY, 0);
+}
+
+static void set_display_parameters(struct carmine_fb *par)
+{
+ u32 mode;
+ u32 hdp, vdp, htp, hsp, hsw, vtr, vsp, vsw;
+
+ /*
+ * display timing. Parameters are decreased by one because hardware
+ * spec is 0 to (n - 1)
+ * */
+ hdp = par->res->hdp - 1;
+ vdp = par->res->vdp - 1;
+ htp = par->res->htp - 1;
+ hsp = par->res->hsp - 1;
+ hsw = par->res->hsw - 1;
+ vtr = par->res->vtr - 1;
+ vsp = par->res->vsp - 1;
+ vsw = par->res->vsw - 1;
+
+ c_set_disp_reg(par, CARMINE_DISP_REG_H_TOTAL,
+ htp << CARMINE_DISP_HTP_SHIFT);
+ c_set_disp_reg(par, CARMINE_DISP_REG_H_PERIOD,
+ (hdp << CARMINE_DISP_HDB_SHIFT) | hdp);
+ c_set_disp_reg(par, CARMINE_DISP_REG_V_H_W_H_POS,
+ (vsw << CARMINE_DISP_VSW_SHIFT) |
+ (hsw << CARMINE_DISP_HSW_SHIFT) |
+ (hsp));
+ c_set_disp_reg(par, CARMINE_DISP_REG_V_TOTAL,
+ vtr << CARMINE_DISP_VTR_SHIFT);
+ c_set_disp_reg(par, CARMINE_DISP_REG_V_PERIOD_POS,
+ (vdp << CARMINE_DISP_VDP_SHIFT) | vsp);
+
+ /* clock */
+ mode = c_get_disp_reg(par, CARMINE_DISP_REG_DCM1);
+ mode = (mode & ~CARMINE_DISP_DCM_MASK) |
+ (par->res->disp_mode & CARMINE_DISP_DCM_MASK);
+ /* enable video output and layer 0 */
+ mode |= CARMINE_DEN | CARMINE_L0E;
+ c_set_disp_reg(par, CARMINE_DISP_REG_DCM1, mode);
+}
+
+static int carmine_set_par(struct fb_info *info)
+{
+ struct carmine_fb *par = info->par;
+ int ret;
+
+ ret = carmine_find_mode(&info->var);
+ if (ret < 0)
+ return ret;
+
+ par->new_mode = ret;
+ if (par->cur_mode != par->new_mode) {
+
+ par->cur_mode = par->new_mode;
+ par->res = &car_modes[par->new_mode];
+
+ carmine_init_display_param(par);
+ set_display_parameters(par);
+ }
+
+ info->fix.line_length = info->var.xres * info->var.bits_per_pixel / 8;
+ return 0;
+}
+
+static int init_hardware(struct carmine_hw *hw)
+{
+ u32 flags;
+ u32 loops;
+ u32 ret;
+
+ /* Initalize Carmine */
+ /* Sets internal clock */
+ c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE,
+ CARMINE_DFLT_IP_CLOCK_ENABLE);
+
+ /* Video signal output is turned off */
+ c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
+ c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
+
+ /* Software reset */
+ c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 1);
+ c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 0);
+
+ /* I/O mode settings */
+ flags = CARMINE_DFLT_IP_DCTL_IO_CONT1 << 16 |
+ CARMINE_DFLT_IP_DCTL_IO_CONT0;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_IOCONT1_IOCONT0,
+ flags);
+
+ /* DRAM initial sequence */
+ flags = CARMINE_DFLT_IP_DCTL_MODE << 16 | CARMINE_DFLT_IP_DCTL_ADD;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD,
+ flags);
+
+ flags = CARMINE_DFLT_IP_DCTL_SET_TIME1 << 16 |
+ CARMINE_DFLT_IP_DCTL_EMODE;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_SETTIME1_EMODE,
+ flags);
+
+ flags = CARMINE_DFLT_IP_DCTL_REFRESH << 16 |
+ CARMINE_DFLT_IP_DCTL_SET_TIME2;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_REFRESH_SETTIME2,
+ flags);
+
+ flags = CARMINE_DFLT_IP_DCTL_RESERVE2 << 16 |
+ CARMINE_DFLT_IP_DCTL_FIFO_DEPTH;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV2_RSV1, flags);
+
+ flags = CARMINE_DFLT_IP_DCTL_DDRIF2 << 16 | CARMINE_DFLT_IP_DCTL_DDRIF1;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_DDRIF2_DDRIF1,
+ flags);
+
+ flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
+ CARMINE_DFLT_IP_DCTL_STATES;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
+ flags);
+
+ /* Executes DLL reset */
+ if (CARMINE_DCTL_DLL_RESET) {
+ for (loops = 0; loops < CARMINE_DCTL_INIT_WAIT_LIMIT; loops++) {
+
+ ret = c_get_hw_reg(hw, CARMINE_DCTL_REG +
+ CARMINE_DCTL_REG_RSV0_STATES);
+ ret &= CARMINE_DCTL_REG_STATES_MASK;
+ if (!ret)
+ break;
+
+ mdelay(CARMINE_DCTL_INIT_WAIT_INTERVAL);
+ }
+
+ if (loops >= CARMINE_DCTL_INIT_WAIT_LIMIT) {
+ printk(KERN_ERR "DRAM init failed\n");
+ return -EIO;
+ }
+ }
+
+ flags = CARMINE_DFLT_IP_DCTL_MODE_AFT_RST << 16 |
+ CARMINE_DFLT_IP_DCTL_ADD;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD, flags);
+
+ flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
+ CARMINE_DFLT_IP_DCTL_STATES_AFT_RST;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
+ flags);
+
+ /* Initialize the write back register */
+ c_set_hw_reg(hw, CARMINE_WB_REG + CARMINE_WB_REG_WBM,
+ CARMINE_WB_REG_WBM_DEFAULT);
+
+ /* Initialize the Kottos registers */
+ c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRINTM, 0);
+ c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRERRM, 0);
+
+ /* Set DC offsets */
+ c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PX, 0);
+ c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PY, 0);
+ c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LX, 0);
+ c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LY, 0);
+ c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TX, 0);
+ c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TY, 0);
+ return 0;
+}
+
+static struct fb_ops carminefb_ops = {
+ .owner = THIS_MODULE,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+
+ .fb_check_var = carmine_check_var,
+ .fb_set_par = carmine_set_par,
+ .fb_setcolreg = carmine_setcolreg,
+};
+
+static int alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
+ int smem_offset, struct device *device, struct fb_info **rinfo)
+{
+ int ret;
+ struct fb_info *info;
+ struct carmine_fb *par;
+
+ info = framebuffer_alloc(sizeof *par, device);
+ if (!info)
+ return -ENOMEM;
+
+ par = info->par;
+ par->display_reg = regs;
+ par->smem_offset = smem_offset;
+
+ info->screen_base = smem_base + smem_offset;
+ info->screen_size = CARMINE_DISPLAY_MEM;
+ info->fbops = &carminefb_ops;
+
+ info->fix = carminefb_fix;
+ info->pseudo_palette = par->pseudo_palette;
+ info->flags = FBINFO_DEFAULT;
+
+ ret = fb_alloc_cmap(&info->cmap, 256, 1);
+ if (ret < 0)
+ goto err_free_fb;
+
+ if (fb_mode > ARRAY_SIZE(carmine_modedb))
+ fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
+
+ par->cur_mode = par->new_mode = ~0;
+
+ ret = fb_find_mode(&info->var, info, fb_mode_str, carmine_modedb,
+ ARRAY_SIZE(carmine_modedb),
+ &carmine_modedb[fb_mode], 32);
+ if (!ret || ret == 4) {
+ ret = -EINVAL;
+ goto err_dealloc_cmap;
+ }
+
+ fb_videomode_to_modelist(carmine_modedb, ARRAY_SIZE(carmine_modedb),
+ &info->modelist);
+
+ ret = register_framebuffer(info);
+ if (ret < 0)
+ goto err_dealloc_cmap;
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+ info->fix.id);
+
+ *rinfo = info;
+ return 0;
+
+err_dealloc_cmap:
+ fb_dealloc_cmap(&info->cmap);
+err_free_fb:
+ framebuffer_release(info);
+ return ret;
+}
+
+static void cleanup_fb_device(struct fb_info *info)
+{
+ if (info) {
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info->cmap);
+ framebuffer_release(info);
+ }
+}
+
+static int __devinit carminefb_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ struct carmine_hw *hw;
+ struct device *device = &dev->dev;
+ struct fb_info *info;
+ int ret;
+
+ ret = pci_enable_device(dev);
+ if (ret)
+ return ret;
+
+ ret = -ENOMEM;
+ hw = kzalloc(sizeof *hw, GFP_KERNEL);
+ if (!hw)
+ goto err_enable_pci;
+
+ carminefb_fix.mmio_start = pci_resource_start(dev, CARMINE_CONFIG_BAR);
+ carminefb_fix.mmio_len = pci_resource_len(dev, CARMINE_CONFIG_BAR);
+
+ if (!request_mem_region(carminefb_fix.mmio_start,
+ carminefb_fix.mmio_len,
+ "carminefb regbase")) {
+ printk(KERN_ERR "carminefb: Can't reserve regbase.\n");
+ ret = -EBUSY;
+ goto err_free_hw;
+ }
+ hw->v_regs = ioremap_nocache(carminefb_fix.mmio_start,
+ carminefb_fix.mmio_len);
+ if (!hw->v_regs) {
+ printk(KERN_ERR "carminefb: Can't remap %s register.\n",
+ carminefb_fix.id);
+ goto err_free_reg_mmio;
+ }
+
+ carminefb_fix.smem_start = pci_resource_start(dev, CARMINE_MEMORY_BAR);
+ carminefb_fix.smem_len = pci_resource_len(dev, CARMINE_MEMORY_BAR);
+
+ /* The memory area tends to be very large (256 MiB). Remap only what
+ * is required for that largest resolution to avoid remaps at run
+ * time
+ */
+ if (carminefb_fix.smem_len > CARMINE_TOTAL_DIPLAY_MEM)
+ carminefb_fix.smem_len = CARMINE_TOTAL_DIPLAY_MEM;
+
+ else if (carminefb_fix.smem_len < CARMINE_TOTAL_DIPLAY_MEM) {
+ printk(KERN_ERR "carminefb: Memory bar is only %d bytes, %d "
+ "are required.", carminefb_fix.smem_len,
+ CARMINE_TOTAL_DIPLAY_MEM);
+ goto err_free_reg_mmio;
+ }
+
+ if (!request_mem_region(carminefb_fix.smem_start,
+ carminefb_fix.smem_len, "carminefb smem")) {
+ printk(KERN_ERR "carminefb: Can't reserve smem.\n");
+ goto err_unmap_vregs;
+ }
+
+ hw->screen_mem = ioremap_nocache(carminefb_fix.smem_start,
+ carminefb_fix.smem_len);
+ if (!hw->screen_mem) {
+ printk(KERN_ERR "carmine: Can't ioremap smem area.\n");
+ release_mem_region(carminefb_fix.smem_start,
+ carminefb_fix.smem_len);
+ goto err_reg_smem;
+ }
+
+ ret = init_hardware(hw);
+ if (ret)
+ goto err_unmap_screen;
+
+ info = NULL;
+ if (fb_displays & CARMINE_USE_DISPLAY0) {
+ ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP0_REG,
+ hw->screen_mem, CARMINE_DISPLAY_MEM * 0,
+ device, &info);
+ if (ret)
+ goto err_deinit_hw;
+ }
+
+ hw->fb[0] = info;
+
+ info = NULL;
+ if (fb_displays & CARMINE_USE_DISPLAY1) {
+ ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP1_REG,
+ hw->screen_mem, CARMINE_DISPLAY_MEM * 1,
+ device, &info);
+ if (ret)
+ goto err_cleanup_fb0;
+ }
+
+ hw->fb[1] = info;
+ info = NULL;
+
+ pci_set_drvdata(dev, hw);
+ return 0;
+
+err_cleanup_fb0:
+ cleanup_fb_device(hw->fb[0]);
+err_deinit_hw:
+ /* disable clock, etc */
+ c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
+err_unmap_screen:
+ iounmap(hw->screen_mem);
+err_reg_smem:
+ release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len);
+err_unmap_vregs:
+ iounmap(hw->v_regs);
+err_free_reg_mmio:
+ release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len);
+err_free_hw:
+ kfree(hw);
+err_enable_pci:
+ pci_disable_device(dev);
+ return ret;
+}
+
+static void __devexit carminefb_remove(struct pci_dev *dev)
+{
+ struct carmine_hw *hw = pci_get_drvdata(dev);
+ struct fb_fix_screeninfo fix;
+ int i;
+
+ /* in case we use only fb1 and not fb1 */
+ if (hw->fb[0])
+ fix = hw->fb[0]->fix;
+ else
+ fix = hw->fb[1]->fix;
+
+ /* deactivate display(s) and switch clocks */
+ c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
+ c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
+ c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
+
+ for (i = 0; i < MAX_DISPLAY; i++)
+ cleanup_fb_device(hw->fb[i]);
+
+ iounmap(hw->screen_mem);
+ release_mem_region(fix.smem_start, fix.smem_len);
+ iounmap(hw->v_regs);
+ release_mem_region(fix.mmio_start, fix.mmio_len);
+
+ pci_set_drvdata(dev, NULL);
+ pci_disable_device(dev);
+ kfree(hw);
+}
+
+#define PCI_VENDOR_ID_FUJITU_LIMITED 0x10cf
+static struct pci_device_id carmine_devices[] __devinitdata = {
+{
+ PCI_DEVICE(PCI_VENDOR_ID_FUJITU_LIMITED, 0x202b)},
+ {0, 0, 0, 0, 0, 0, 0}
+};
+
+MODULE_DEVICE_TABLE(pci, carmine_devices);
+
+static struct pci_driver carmine_pci_driver = {
+ .name = "carminefb",
+ .id_table = carmine_devices,
+ .probe = carminefb_probe,
+ .remove = __devexit_p(carminefb_remove),
+};
+
+static int __init carminefb_init(void)
+{
+ if (!(fb_displays &
+ (CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1))) {
+ printk(KERN_ERR "If you disable both displays than you don't "
+ "need the driver at all\n");
+ return -EINVAL;
+ }
+ return pci_register_driver(&carmine_pci_driver);
+}
+module_init(carminefb_init);
+
+static void __exit carminefb_cleanup(void)
+{
+ pci_unregister_driver(&carmine_pci_driver);
+}
+module_exit(carminefb_cleanup);
+
+MODULE_AUTHOR("Sebastian Siewior <bigeasy@linutronix.de>");
+MODULE_DESCRIPTION("Framebuffer driver for Fujitsu Carmine based devices");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/carminefb.h b/drivers/video/carminefb.h
new file mode 100644
index 00000000000..05306de0c6b
--- /dev/null
+++ b/drivers/video/carminefb.h
@@ -0,0 +1,64 @@
+#ifndef CARMINE_CARMINE_H
+#define CARMINE_CARMINE_H
+
+#define CARMINE_MEMORY_BAR 2
+#define CARMINE_CONFIG_BAR 3
+
+#define MAX_DISPLAY 2
+#define CARMINE_DISPLAY_MEM (800 * 600 * 4)
+#define CARMINE_TOTAL_DIPLAY_MEM (CARMINE_DISPLAY_MEM * MAX_DISPLAY)
+
+#define CARMINE_USE_DISPLAY0 (1 << 0)
+#define CARMINE_USE_DISPLAY1 (1 << 1)
+
+/*
+ * This values work on the eval card. Custom boards may use different timings,
+ * here an example :)
+ */
+
+/* DRAM initialization values */
+#ifdef CONFIG_FB_CARMINE_DRAM_EVAL
+
+#define CARMINE_DFLT_IP_CLOCK_ENABLE (0x03ff)
+#define CARMINE_DFLT_IP_DCTL_ADD (0x05c3)
+#define CARMINE_DFLT_IP_DCTL_MODE (0x0121)
+#define CARMINE_DFLT_IP_DCTL_EMODE (0x8000)
+#define CARMINE_DFLT_IP_DCTL_SET_TIME1 (0x4749)
+#define CARMINE_DFLT_IP_DCTL_SET_TIME2 (0x2a22)
+#define CARMINE_DFLT_IP_DCTL_REFRESH (0x0042)
+#define CARMINE_DFLT_IP_DCTL_STATES (0x0003)
+#define CARMINE_DFLT_IP_DCTL_RESERVE0 (0x0020)
+#define CARMINE_DFLT_IP_DCTL_FIFO_DEPTH (0x000f)
+#define CARMINE_DFLT_IP_DCTL_RESERVE2 (0x0000)
+#define CARMINE_DFLT_IP_DCTL_DDRIF1 (0x6646)
+#define CARMINE_DFLT_IP_DCTL_DDRIF2 (0x0055)
+#define CARMINE_DFLT_IP_DCTL_MODE_AFT_RST (0x0021)
+#define CARMINE_DFLT_IP_DCTL_STATES_AFT_RST (0x0002)
+#define CARMINE_DFLT_IP_DCTL_IO_CONT0 (0x0555)
+#define CARMINE_DFLT_IP_DCTL_IO_CONT1 (0x0555)
+#define CARMINE_DCTL_DLL_RESET (1)
+#endif
+
+#ifdef CONFIG_CARMINE_DRAM_CUSTOM
+
+#define CARMINE_DFLT_IP_CLOCK_ENABLE (0x03ff)
+#define CARMINE_DFLT_IP_DCTL_ADD (0x03b2)
+#define CARMINE_DFLT_IP_DCTL_MODE (0x0161)
+#define CARMINE_DFLT_IP_DCTL_EMODE (0x8000)
+#define CARMINE_DFLT_IP_DCTL_SET_TIME1 (0x2628)
+#define CARMINE_DFLT_IP_DCTL_SET_TIME2 (0x1a09)
+#define CARMINE_DFLT_IP_DCTL_REFRESH (0x00fe)
+#define CARMINE_DFLT_IP_DCTL_STATES (0x0003)
+#define CARMINE_DFLT_IP_DCTL_RESERVE0 (0x0020)
+#define CARMINE_DFLT_IP_DCTL_FIFO_DEPTH (0x000f)
+#define CARMINE_DFLT_IP_DCTL_RESERVE2 (0x0000)
+#define CARMINE_DFLT_IP_DCTL_DDRIF1 (0x0646)
+#define CARMINE_DFLT_IP_DCTL_DDRIF2 (0x55aa)
+#define CARMINE_DFLT_IP_DCTL_MODE_AFT_RST (0x0061)
+#define CARMINE_DFLT_IP_DCTL_STATES_AFT_RST (0x0002)
+#define CARMINE_DFLT_IP_DCTL_IO_CONT0 (0x0555)
+#define CARMINE_DFLT_IP_DCTL_IO_CONT1 (0x0555)
+#define CARMINE_DCTL_DLL_RESET (1)
+#endif
+
+#endif
diff --git a/drivers/video/carminefb_regs.h b/drivers/video/carminefb_regs.h
new file mode 100644
index 00000000000..045215600b7
--- /dev/null
+++ b/drivers/video/carminefb_regs.h
@@ -0,0 +1,159 @@
+#ifndef _CARMINEFB_REGS_H
+#define _CARMINEFB_REGS_H
+
+#define CARMINE_OVERLAY_EXT_MODE (0x00000002)
+#define CARMINE_GRAPH_REG (0x00000000)
+#define CARMINE_DISP0_REG (0x00100000)
+#define CARMINE_DISP1_REG (0x00140000)
+#define CARMINE_WB_REG (0x00180000)
+#define CARMINE_DCTL_REG (0x00300000)
+#define CARMINE_CTL_REG (0x00400000)
+#define CARMINE_WINDOW_MODE (0x00000001)
+#define CARMINE_EXTEND_MODE (CARMINE_WINDOW_MODE | \
+ CARMINE_OVERLAY_EXT_MODE)
+#define CARMINE_L0E (1 << 16)
+#define CARMINE_L2E (1 << 18)
+#define CARMINE_DEN (1 << 31)
+
+#define CARMINE_EXT_CMODE_DIRECT24_RGBA (0xC0000000)
+#define CARMINE_DCTL_REG_MODE_ADD (0x00)
+#define CARMINE_DCTL_REG_SETTIME1_EMODE (0x04)
+#define CARMINE_DCTL_REG_REFRESH_SETTIME2 (0x08)
+#define CARMINE_DCTL_REG_RSV0_STATES (0x0C)
+#define CARMINE_DCTL_REG_RSV2_RSV1 (0x10)
+#define CARMINE_DCTL_REG_DDRIF2_DDRIF1 (0x14)
+#define CARMINE_DCTL_REG_IOCONT1_IOCONT0 (0x24)
+#define CARMINE_DCTL_REG_STATES_MASK (0x000F)
+#define CARMINE_DCTL_INIT_WAIT_INTERVAL (1)
+#define CARMINE_DCTL_INIT_WAIT_LIMIT (5000)
+#define CARMINE_WB_REG_WBM_DEFAULT (0x0001c020)
+#define CARMINE_DISP_REG_L0RM (0x1880)
+#define CARMINE_DISP_REG_L0PX (0x1884)
+#define CARMINE_DISP_REG_L0PY (0x1888)
+#define CARMINE_DISP_REG_L2RM (0x18A0)
+#define CARMINE_DISP_REG_L2PX (0x18A4)
+#define CARMINE_DISP_REG_L2PY (0x18A8)
+#define CARMINE_DISP_REG_L3RM (0x18B0)
+#define CARMINE_DISP_REG_L3PX (0x18B4)
+#define CARMINE_DISP_REG_L3PY (0x18B8)
+#define CARMINE_DISP_REG_L4RM (0x18C0)
+#define CARMINE_DISP_REG_L4PX (0x18C4)
+#define CARMINE_DISP_REG_L4PY (0x18C8)
+#define CARMINE_DISP_REG_L5RM (0x18D0)
+#define CARMINE_DISP_REG_L5PX (0x18D4)
+#define CARMINE_DISP_REG_L5PY (0x18D8)
+#define CARMINE_DISP_REG_L6RM (0x1924)
+#define CARMINE_DISP_REG_L6PX (0x1928)
+#define CARMINE_DISP_REG_L6PY (0x192C)
+#define CARMINE_DISP_REG_L7RM (0x1964)
+#define CARMINE_DISP_REG_L7PX (0x1968)
+#define CARMINE_DISP_REG_L7PY (0x196C)
+#define CARMINE_WB_REG_WBM (0x0004)
+#define CARMINE_DISP_HTP_SHIFT (16)
+#define CARMINE_DISP_HDB_SHIFT (16)
+#define CARMINE_DISP_HSW_SHIFT (16)
+#define CARMINE_DISP_VSW_SHIFT (24)
+#define CARMINE_DISP_VTR_SHIFT (16)
+#define CARMINE_DISP_VDP_SHIFT (16)
+#define CARMINE_CURSOR_CUTZ_MASK (0x00000100)
+#define CARMINE_CURSOR0_PRIORITY_MASK (0x00010000)
+#define CARMINE_CURSOR1_PRIORITY_MASK (0x00020000)
+#define CARMINE_DISP_WIDTH_SHIFT (16)
+#define CARMINE_DISP_WIN_H_SHIFT (16)
+#define CARMINE_DISP_REG_H_TOTAL (0x0004)
+#define CARMINE_DISP_REG_H_PERIOD (0x0008)
+#define CARMINE_DISP_REG_V_H_W_H_POS (0x000C)
+#define CARMINE_DISP_REG_V_TOTAL (0x0010)
+#define CARMINE_DISP_REG_V_PERIOD_POS (0x0014)
+#define CARMINE_DISP_REG_L0_MODE_W_H (0x0020)
+#define CARMINE_DISP_REG_L0_ORG_ADR (0x0024)
+#define CARMINE_DISP_REG_L0_DISP_ADR (0x0028)
+#define CARMINE_DISP_REG_L0_DISP_POS (0x002C)
+#define CARMINE_DISP_REG_L1_WIDTH (0x0030)
+#define CARMINE_DISP_REG_L1_ORG_ADR (0x0034)
+#define CARMINE_DISP_REG_L2_MODE_W_H (0x0040)
+#define CARMINE_DISP_REG_L2_ORG_ADR1 (0x0044)
+#define CARMINE_DISP_REG_L2_DISP_ADR1 (0x0048)
+#define CARMINE_DISP_REG_L2_DISP_POS (0x0054)
+#define CARMINE_DISP_REG_L3_MODE_W_H (0x0058)
+#define CARMINE_DISP_REG_L3_ORG_ADR1 (0x005C)
+#define CARMINE_DISP_REG_L3_DISP_ADR1 (0x0060)
+#define CARMINE_DISP_REG_L3_DISP_POS (0x006C)
+#define CARMINE_DISP_REG_L4_MODE_W_H (0x0070)
+#define CARMINE_DISP_REG_L4_ORG_ADR1 (0x0074)
+#define CARMINE_DISP_REG_L4_DISP_ADR1 (0x0078)
+#define CARMINE_DISP_REG_L4_DISP_POS (0x0084)
+#define CARMINE_DISP_REG_L5_MODE_W_H (0x0088)
+#define CARMINE_DISP_REG_L5_ORG_ADR1 (0x008C)
+#define CARMINE_DISP_REG_L5_DISP_ADR1 (0x0090)
+#define CARMINE_DISP_REG_L5_DISP_POS (0x009C)
+#define CARMINE_DISP_REG_CURSOR_MODE (0x00A0)
+#define CARMINE_DISP_REG_CUR1_POS (0x00A8)
+#define CARMINE_DISP_REG_CUR2_POS (0x00B0)
+#define CARMINE_DISP_REG_C_TRANS (0x00BC)
+#define CARMINE_DISP_REG_MLMR_TRANS (0x00C0)
+#define CARMINE_DISP_REG_L0_EXT_MODE (0x0110)
+#define CARMINE_DISP_REG_L0_WIN_POS (0x0114)
+#define CARMINE_DISP_REG_L0_WIN_SIZE (0x0118)
+#define CARMINE_DISP_REG_L1_EXT_MODE (0x0120)
+#define CARMINE_DISP_REG_L1_WIN_POS (0x0124)
+#define CARMINE_DISP_REG_L1_WIN_SIZE (0x0128)
+#define CARMINE_DISP_REG_L2_EXT_MODE (0x0130)
+#define CARMINE_DISP_REG_L2_WIN_POS (0x0134)
+#define CARMINE_DISP_REG_L2_WIN_SIZE (0x0138)
+#define CARMINE_DISP_REG_L3_EXT_MODE (0x0140)
+#define CARMINE_DISP_REG_L3_WIN_POS (0x0144)
+#define CARMINE_DISP_REG_L3_WIN_SIZE (0x0148)
+#define CARMINE_DISP_REG_L4_EXT_MODE (0x0150)
+#define CARMINE_DISP_REG_L4_WIN_POS (0x0154)
+#define CARMINE_DISP_REG_L4_WIN_SIZE (0x0158)
+#define CARMINE_DISP_REG_L5_EXT_MODE (0x0160)
+#define CARMINE_DISP_REG_L5_WIN_POS (0x0164)
+#define CARMINE_DISP_REG_L5_WIN_SIZE (0x0168)
+#define CARMINE_DISP_REG_L6_EXT_MODE (0x1918)
+#define CARMINE_DISP_REG_L6_WIN_POS (0x191c)
+#define CARMINE_DISP_REG_L6_WIN_SIZE (0x1920)
+#define CARMINE_DISP_REG_L7_EXT_MODE (0x1958)
+#define CARMINE_DISP_REG_L7_WIN_POS (0x195c)
+#define CARMINE_DISP_REG_L7_WIN_SIZE (0x1960)
+#define CARMINE_DISP_REG_BLEND_MODE_L0 (0x00B4)
+#define CARMINE_DISP_REG_BLEND_MODE_L1 (0x0188)
+#define CARMINE_DISP_REG_BLEND_MODE_L2 (0x018C)
+#define CARMINE_DISP_REG_BLEND_MODE_L3 (0x0190)
+#define CARMINE_DISP_REG_BLEND_MODE_L4 (0x0194)
+#define CARMINE_DISP_REG_BLEND_MODE_L5 (0x0198)
+#define CARMINE_DISP_REG_BLEND_MODE_L6 (0x1990)
+#define CARMINE_DISP_REG_BLEND_MODE_L7 (0x1994)
+#define CARMINE_DISP_REG_L0_TRANS (0x01A0)
+#define CARMINE_DISP_REG_L1_TRANS (0x01A4)
+#define CARMINE_DISP_REG_L2_TRANS (0x01A8)
+#define CARMINE_DISP_REG_L3_TRANS (0x01AC)
+#define CARMINE_DISP_REG_L4_TRANS (0x01B0)
+#define CARMINE_DISP_REG_L5_TRANS (0x01B4)
+#define CARMINE_DISP_REG_L6_TRANS (0x1998)
+#define CARMINE_DISP_REG_L7_TRANS (0x199c)
+#define CARMINE_EXTEND_MODE_MASK (0x00000003)
+#define CARMINE_DISP_DCM_MASK (0x0000FFFF)
+#define CARMINE_DISP_REG_DCM1 (0x0100)
+#define CARMINE_DISP_WIDTH_UNIT (64)
+#define CARMINE_DISP_REG_L6_MODE_W_H (0x1900)
+#define CARMINE_DISP_REG_L6_ORG_ADR1 (0x1904)
+#define CARMINE_DISP_REG_L6_DISP_ADR0 (0x1908)
+#define CARMINE_DISP_REG_L6_DISP_POS (0x1914)
+#define CARMINE_DISP_REG_L7_MODE_W_H (0x1940)
+#define CARMINE_DISP_REG_L7_ORG_ADR1 (0x1944)
+#define CARMINE_DISP_REG_L7_DISP_ADR0 (0x1948)
+#define CARMINE_DISP_REG_L7_DISP_POS (0x1954)
+#define CARMINE_CTL_REG_CLOCK_ENABLE (0x000C)
+#define CARMINE_CTL_REG_SOFTWARE_RESET (0x0010)
+#define CARMINE_CTL_REG_IST_MASK_ALL (0x07FFFFFF)
+#define CARMINE_GRAPH_REG_VRINTM (0x00028064)
+#define CARMINE_GRAPH_REG_VRERRM (0x0002806C)
+#define CARMINE_GRAPH_REG_DC_OFFSET_PX (0x0004005C)
+#define CARMINE_GRAPH_REG_DC_OFFSET_PY (0x00040060)
+#define CARMINE_GRAPH_REG_DC_OFFSET_LX (0x00040064)
+#define CARMINE_GRAPH_REG_DC_OFFSET_LY (0x00040068)
+#define CARMINE_GRAPH_REG_DC_OFFSET_TX (0x0004006C)
+#define CARMINE_GRAPH_REG_DC_OFFSET_TY (0x00040070)
+
+#endif
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c
new file mode 100644
index 00000000000..7bad24ed04e
--- /dev/null
+++ b/drivers/video/cobalt_lcdfb.c
@@ -0,0 +1,371 @@
+/*
+ * Cobalt server LCD frame buffer driver.
+ *
+ * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+
+/*
+ * Cursor position address
+ * \X 0 1 2 ... 14 15
+ * Y+----+----+----+---+----+----+
+ * 0|0x00|0x01|0x02|...|0x0e|0x0f|
+ * +----+----+----+---+----+----+
+ * 1|0x40|0x41|0x42|...|0x4e|0x4f|
+ * +----+----+----+---+----+----+
+ */
+#define LCD_DATA_REG_OFFSET 0x10
+#define LCD_XRES_MAX 16
+#define LCD_YRES_MAX 2
+#define LCD_CHARS_MAX 32
+
+#define LCD_CLEAR 0x01
+#define LCD_CURSOR_MOVE_HOME 0x02
+#define LCD_RESET 0x06
+#define LCD_OFF 0x08
+#define LCD_CURSOR_OFF 0x0c
+#define LCD_CURSOR_BLINK_OFF 0x0e
+#define LCD_CURSOR_ON 0x0f
+#define LCD_ON LCD_CURSOR_ON
+#define LCD_CURSOR_MOVE_LEFT 0x10
+#define LCD_CURSOR_MOVE_RIGHT 0x14
+#define LCD_DISPLAY_LEFT 0x18
+#define LCD_DISPLAY_RIGHT 0x1c
+#define LCD_PRERESET 0x3f /* execute 4 times continuously */
+#define LCD_BUSY 0x80
+
+#define LCD_GRAPHIC_MODE 0x40
+#define LCD_TEXT_MODE 0x80
+#define LCD_CUR_POS_MASK 0x7f
+
+#define LCD_CUR_POS(x) ((x) & LCD_CUR_POS_MASK)
+#define LCD_TEXT_POS(x) ((x) | LCD_TEXT_MODE)
+
+static inline void lcd_write_control(struct fb_info *info, u8 control)
+{
+ writel((u32)control << 24, info->screen_base);
+}
+
+static inline u8 lcd_read_control(struct fb_info *info)
+{
+ return readl(info->screen_base) >> 24;
+}
+
+static inline void lcd_write_data(struct fb_info *info, u8 data)
+{
+ writel((u32)data << 24, info->screen_base + LCD_DATA_REG_OFFSET);
+}
+
+static inline u8 lcd_read_data(struct fb_info *info)
+{
+ return readl(info->screen_base + LCD_DATA_REG_OFFSET) >> 24;
+}
+
+static int lcd_busy_wait(struct fb_info *info)
+{
+ u8 val = 0;
+ int timeout = 10, retval = 0;
+
+ do {
+ val = lcd_read_control(info);
+ val &= LCD_BUSY;
+ if (val != LCD_BUSY)
+ break;
+
+ if (msleep_interruptible(1))
+ return -EINTR;
+
+ timeout--;
+ } while (timeout);
+
+ if (val == LCD_BUSY)
+ retval = -EBUSY;
+
+ return retval;
+}
+
+static void lcd_clear(struct fb_info *info)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ udelay(150);
+
+ lcd_write_control(info, LCD_PRERESET);
+ }
+
+ udelay(150);
+
+ lcd_write_control(info, LCD_CLEAR);
+
+ udelay(150);
+
+ lcd_write_control(info, LCD_RESET);
+}
+
+static struct fb_fix_screeninfo cobalt_lcdfb_fix __initdata = {
+ .id = "cobalt-lcd",
+ .type = FB_TYPE_TEXT,
+ .type_aux = FB_AUX_TEXT_MDA,
+ .visual = FB_VISUAL_MONO01,
+ .line_length = LCD_XRES_MAX,
+ .accel = FB_ACCEL_NONE,
+};
+
+static ssize_t cobalt_lcdfb_read(struct fb_info *info, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char src[LCD_CHARS_MAX];
+ unsigned long pos;
+ int len, retval = 0;
+
+ pos = *ppos;
+ if (pos >= LCD_CHARS_MAX || count == 0)
+ return 0;
+
+ if (count > LCD_CHARS_MAX)
+ count = LCD_CHARS_MAX;
+
+ if (pos + count > LCD_CHARS_MAX)
+ count = LCD_CHARS_MAX - pos;
+
+ for (len = 0; len < count; len++) {
+ retval = lcd_busy_wait(info);
+ if (retval < 0)
+ break;
+
+ lcd_write_control(info, LCD_TEXT_POS(pos));
+
+ retval = lcd_busy_wait(info);
+ if (retval < 0)
+ break;
+
+ src[len] = lcd_read_data(info);
+ if (pos == 0x0f)
+ pos = 0x40;
+ else
+ pos++;
+ }
+
+ if (retval < 0 && signal_pending(current))
+ return -ERESTARTSYS;
+
+ if (copy_to_user(buf, src, len))
+ return -EFAULT;
+
+ *ppos += len;
+
+ return len;
+}
+
+static ssize_t cobalt_lcdfb_write(struct fb_info *info, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char dst[LCD_CHARS_MAX];
+ unsigned long pos;
+ int len, retval = 0;
+
+ pos = *ppos;
+ if (pos >= LCD_CHARS_MAX || count == 0)
+ return 0;
+
+ if (count > LCD_CHARS_MAX)
+ count = LCD_CHARS_MAX;
+
+ if (pos + count > LCD_CHARS_MAX)
+ count = LCD_CHARS_MAX - pos;
+
+ if (copy_from_user(dst, buf, count))
+ return -EFAULT;
+
+ for (len = 0; len < count; len++) {
+ retval = lcd_busy_wait(info);
+ if (retval < 0)
+ break;
+
+ lcd_write_control(info, LCD_TEXT_POS(pos));
+
+ retval = lcd_busy_wait(info);
+ if (retval < 0)
+ break;
+
+ lcd_write_data(info, dst[len]);
+ if (pos == 0x0f)
+ pos = 0x40;
+ else
+ pos++;
+ }
+
+ if (retval < 0 && signal_pending(current))
+ return -ERESTARTSYS;
+
+ *ppos += len;
+
+ return len;
+}
+
+static int cobalt_lcdfb_blank(int blank_mode, struct fb_info *info)
+{
+ int retval;
+
+ retval = lcd_busy_wait(info);
+ if (retval < 0)
+ return retval;
+
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ lcd_write_control(info, LCD_ON);
+ break;
+ default:
+ lcd_write_control(info, LCD_OFF);
+ break;
+ }
+
+ return 0;
+}
+
+static int cobalt_lcdfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ u32 x, y;
+ int retval;
+
+ switch (cursor->set) {
+ case FB_CUR_SETPOS:
+ x = cursor->image.dx;
+ y = cursor->image.dy;
+ if (x >= LCD_XRES_MAX || y >= LCD_YRES_MAX)
+ return -EINVAL;
+
+ retval = lcd_busy_wait(info);
+ if (retval < 0)
+ return retval;
+
+ lcd_write_control(info,
+ LCD_TEXT_POS(info->fix.line_length * y + x));
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ retval = lcd_busy_wait(info);
+ if (retval < 0)
+ return retval;
+
+ if (cursor->enable)
+ lcd_write_control(info, LCD_CURSOR_ON);
+ else
+ lcd_write_control(info, LCD_CURSOR_OFF);
+
+ return 0;
+}
+
+static struct fb_ops cobalt_lcd_fbops = {
+ .owner = THIS_MODULE,
+ .fb_read = cobalt_lcdfb_read,
+ .fb_write = cobalt_lcdfb_write,
+ .fb_blank = cobalt_lcdfb_blank,
+ .fb_cursor = cobalt_lcdfb_cursor,
+};
+
+static int __init cobalt_lcdfb_probe(struct platform_device *dev)
+{
+ struct fb_info *info;
+ struct resource *res;
+ int retval;
+
+ info = framebuffer_alloc(0, &dev->dev);
+ if (!info)
+ return -ENOMEM;
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!res) {
+ framebuffer_release(info);
+ return -EBUSY;
+ }
+
+ info->screen_size = res->end - res->start + 1;
+ info->screen_base = ioremap(res->start, info->screen_size);
+ info->fbops = &cobalt_lcd_fbops;
+ info->fix = cobalt_lcdfb_fix;
+ info->fix.smem_start = res->start;
+ info->fix.smem_len = info->screen_size;
+ info->pseudo_palette = NULL;
+ info->par = NULL;
+ info->flags = FBINFO_DEFAULT;
+
+ retval = register_framebuffer(info);
+ if (retval < 0) {
+ iounmap(info->screen_base);
+ framebuffer_release(info);
+ return retval;
+ }
+
+ platform_set_drvdata(dev, info);
+
+ lcd_clear(info);
+
+ printk(KERN_INFO "fb%d: Cobalt server LCD frame buffer device\n",
+ info->node);
+
+ return 0;
+}
+
+static int __devexit cobalt_lcdfb_remove(struct platform_device *dev)
+{
+ struct fb_info *info;
+
+ info = platform_get_drvdata(dev);
+ if (info) {
+ iounmap(info->screen_base);
+ unregister_framebuffer(info);
+ framebuffer_release(info);
+ }
+
+ return 0;
+}
+
+static struct platform_driver cobalt_lcdfb_driver = {
+ .probe = cobalt_lcdfb_probe,
+ .remove = __devexit_p(cobalt_lcdfb_remove),
+ .driver = {
+ .name = "cobalt-lcd",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init cobalt_lcdfb_init(void)
+{
+ return platform_driver_register(&cobalt_lcdfb_driver);
+}
+
+static void __exit cobalt_lcdfb_exit(void)
+{
+ platform_driver_unregister(&cobalt_lcdfb_driver);
+}
+
+module_init(cobalt_lcdfb_init);
+module_exit(cobalt_lcdfb_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Yoichi Yuasa");
+MODULE_DESCRIPTION("Cobalt server LCD frame buffer driver");
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 97aff8db10b..3ccfa76d9b2 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -107,9 +107,7 @@ static struct display fb_display[MAX_NR_CONSOLES];
static signed char con2fb_map[MAX_NR_CONSOLES];
static signed char con2fb_map_boot[MAX_NR_CONSOLES];
-#ifndef MODULE
-static int logo_height;
-#endif
+
static int logo_lines;
/* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
enums. */
@@ -607,6 +605,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
struct fbcon_ops *ops = info->fbcon_par;
int cnt, erase = vc->vc_video_erase_char, step;
unsigned short *save = NULL, *r, *q;
+ int logo_height;
if (info->flags & FBINFO_MODULE) {
logo_shown = FBCON_LOGO_DONTSHOW;
@@ -3586,7 +3585,8 @@ static int __init fb_console_init(void)
acquire_console_sem();
fb_register_client(&fbcon_event_notifier);
- fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), "fbcon");
+ fbcon_device = device_create_drvdata(fb_class, NULL, MKDEV(0, 0),
+ NULL, "fbcon");
if (IS_ERR(fbcon_device)) {
printk(KERN_WARNING "Unable to create device "
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 0135e039545..de1b1365279 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -92,7 +92,7 @@ struct fbcon_ops {
#define attr_fgcol(fgshift,s) \
(((s) >> (fgshift)) & 0x0f)
#define attr_bgcol(bgshift,s) \
- (((s) >> (bgshift)) & 0x0f)
+ (((s) >> (bgshift)) & 0x07)
/* Monochrome */
#define attr_bold(s) \
@@ -146,10 +146,8 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,
return is_fg ? fg : bg;
}
-#define attr_bgcol_ec(bgshift,vc,info) \
- attr_col_ec(bgshift,vc,info,0);
-#define attr_fgcol_ec(fgshift,vc,info) \
- attr_col_ec(fgshift,vc,info,1);
+#define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0)
+#define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1)
/* Font */
#define REFCOUNT(fd) (((int *)(fd))[-1])
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
index 38a296bbdfc..9901064199b 100644
--- a/drivers/video/console/mdacon.c
+++ b/drivers/video/console/mdacon.c
@@ -71,13 +71,15 @@ static char *mda_type_name;
/* console information */
-static int mda_first_vc = 1;
+static int mda_first_vc = 13;
static int mda_last_vc = 16;
static struct vc_data *mda_display_fg = NULL;
module_param(mda_first_vc, int, 0);
+MODULE_PARM_DESC(mda_first_vc, "First virtual console. Default: 13");
module_param(mda_last_vc, int, 0);
+MODULE_PARM_DESC(mda_last_vc, "Last virtual console. Default: 16");
/* MDA register values
*/
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 33ebdb198da..5d84b343109 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -35,6 +35,7 @@
#include <linux/device.h>
#include <linux/efi.h>
#include <linux/fb.h>
+#include <linux/major.h>
#include <asm/fb.h>
@@ -848,9 +849,8 @@ int
fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
{
struct fb_fix_screeninfo *fix = &info->fix;
- int xoffset = var->xoffset;
- int yoffset = var->yoffset;
- int err = 0, yres = info->var.yres;
+ unsigned int yres = info->var.yres;
+ int err = 0;
if (var->yoffset > 0) {
if (var->vmode & FB_VMODE_YWRAP) {
@@ -866,8 +866,8 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
(var->xoffset % fix->xpanstep)))
err = -EINVAL;
- if (err || !info->fbops->fb_pan_display || xoffset < 0 ||
- yoffset < 0 || var->yoffset + yres > info->var.yres_virtual ||
+ if (err || !info->fbops->fb_pan_display ||
+ var->yoffset + yres > info->var.yres_virtual ||
var->xoffset + info->var.xres > info->var.xres_virtual)
return -EINVAL;
@@ -1439,8 +1439,9 @@ register_framebuffer(struct fb_info *fb_info)
break;
fb_info->node = i;
- fb_info->dev = device_create(fb_class, fb_info->device,
- MKDEV(FB_MAJOR, i), "fb%d", i);
+ fb_info->dev = device_create_drvdata(fb_class, fb_info->device,
+ MKDEV(FB_MAJOR, i), NULL,
+ "fb%d", i);
if (IS_ERR(fb_info->dev)) {
/* Not fatal */
printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 052e1805849..6a0aa180c26 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -879,7 +879,7 @@ int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
if (edid_is_timing_block(block)) {
var->xres = var->xres_virtual = H_ACTIVE;
var->yres = var->yres_virtual = V_ACTIVE;
- var->height = var->width = -1;
+ var->height = var->width = 0;
var->right_margin = H_SYNC_OFFSET;
var->left_margin = (H_ACTIVE + H_BLANKING) -
(H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 09d7e22c6fe..9cd36c223d3 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -279,58 +279,42 @@ static struct diu_hw dr = {
static struct diu_pool pool;
-/* To allocate memory for framebuffer. First try __get_free_pages(). If it
- * fails, try rh_alloc. The reason is __get_free_pages() cannot allocate
- * very large memory (more than 4MB). We don't want to allocate all memory
- * in rheap since small memory allocation/deallocation will fragment the
- * rheap and make the furture large allocation fail.
+/**
+ * fsl_diu_alloc - allocate memory for the DIU
+ * @size: number of bytes to allocate
+ * @param: returned physical address of memory
+ *
+ * This function allocates a physically-contiguous block of memory.
*/
-
-static void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys)
+static void *fsl_diu_alloc(size_t size, phys_addr_t *phys)
{
void *virt;
- pr_debug("size=%lu\n", size);
+ pr_debug("size=%zu\n", size);
- virt = (void *)__get_free_pages(GFP_DMA | __GFP_ZERO, get_order(size));
+ virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO);
if (virt) {
*phys = virt_to_phys(virt);
- pr_debug("virt %p, phys=%llx\n", virt, (uint64_t) *phys);
- return virt;
- }
- if (!diu_ops.diu_mem) {
- printk(KERN_INFO "%s: no diu_mem."
- " To reserve more memory, put 'diufb=15M' "
- "in the command line\n", __func__);
- return NULL;
- }
-
- virt = (void *)rh_alloc(&diu_ops.diu_rh_info, size, "DIU");
- if (virt) {
- *phys = virt_to_bus(virt);
- memset(virt, 0, size);
+ pr_debug("virt=%p phys=%llx\n", virt,
+ (unsigned long long)*phys);
}
- pr_debug("rh virt=%p phys=%llx\n", virt, (unsigned long long)*phys);
-
return virt;
}
-static void fsl_diu_free(void *p, unsigned long size)
+/**
+ * fsl_diu_free - release DIU memory
+ * @virt: pointer returned by fsl_diu_alloc()
+ * @size: number of bytes allocated by fsl_diu_alloc()
+ *
+ * This function releases memory allocated by fsl_diu_alloc().
+ */
+static void fsl_diu_free(void *virt, size_t size)
{
- pr_debug("p=%p size=%lu\n", p, size);
+ pr_debug("virt=%p size=%zu\n", virt, size);
- if (!p)
- return;
-
- if ((p >= diu_ops.diu_mem) &&
- (p < (diu_ops.diu_mem + diu_ops.diu_size))) {
- pr_debug("rh\n");
- rh_free(&diu_ops.diu_rh_info, (unsigned long) p);
- } else {
- pr_debug("dma\n");
- free_pages((unsigned long)p, get_order(size));
- }
+ if (virt && size)
+ free_pages_exact(virt, size);
}
static int fsl_diu_enable_panel(struct fb_info *info)
diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h
index 3b9416f4ee2..6a51448fd3f 100644
--- a/drivers/video/geode/lxfb.h
+++ b/drivers/video/geode/lxfb.h
@@ -51,8 +51,6 @@ static inline unsigned int lx_get_pitch(unsigned int xres, int bpp)
}
void lx_set_mode(struct fb_info *);
-void lx_get_gamma(struct fb_info *, unsigned int *, int);
-void lx_set_gamma(struct fb_info *, unsigned int *, int);
unsigned int lx_framebuffer_size(void);
int lx_blank_display(struct fb_info *, int);
void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int,
diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/geode/lxfb_ops.c
index aaef9165ec9..b1cd49c9935 100644
--- a/drivers/video/geode/lxfb_ops.c
+++ b/drivers/video/geode/lxfb_ops.c
@@ -517,25 +517,25 @@ void lx_set_palette_reg(struct fb_info *info, unsigned regno,
int lx_blank_display(struct fb_info *info, int blank_mode)
{
struct lxfb_par *par = info->par;
- u32 dcfg, fp_pm;
- int blank, hsync, vsync, crt;
+ u32 dcfg, misc, fp_pm;
+ int blank, hsync, vsync;
/* CRT power saving modes. */
switch (blank_mode) {
case FB_BLANK_UNBLANK:
- blank = 0; hsync = 1; vsync = 1; crt = 1;
+ blank = 0; hsync = 1; vsync = 1;
break;
case FB_BLANK_NORMAL:
- blank = 1; hsync = 1; vsync = 1; crt = 1;
+ blank = 1; hsync = 1; vsync = 1;
break;
case FB_BLANK_VSYNC_SUSPEND:
- blank = 1; hsync = 1; vsync = 0; crt = 1;
+ blank = 1; hsync = 1; vsync = 0;
break;
case FB_BLANK_HSYNC_SUSPEND:
- blank = 1; hsync = 0; vsync = 1; crt = 1;
+ blank = 1; hsync = 0; vsync = 1;
break;
case FB_BLANK_POWERDOWN:
- blank = 1; hsync = 0; vsync = 0; crt = 0;
+ blank = 1; hsync = 0; vsync = 0;
break;
default:
return -EINVAL;
@@ -545,15 +545,23 @@ int lx_blank_display(struct fb_info *info, int blank_mode)
dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN |
VP_DCFG_CRT_EN);
if (!blank)
- dcfg |= VP_DCFG_DAC_BL_EN;
+ dcfg |= VP_DCFG_DAC_BL_EN | VP_DCFG_CRT_EN;
if (hsync)
dcfg |= VP_DCFG_HSYNC_EN;
if (vsync)
dcfg |= VP_DCFG_VSYNC_EN;
- if (crt)
- dcfg |= VP_DCFG_CRT_EN;
+
write_vp(par, VP_DCFG, dcfg);
+ misc = read_vp(par, VP_MISC);
+
+ if (vsync && hsync)
+ misc &= ~VP_MISC_DACPWRDN;
+ else
+ misc |= VP_MISC_DACPWRDN;
+
+ write_vp(par, VP_MISC, misc);
+
/* Power on/off flat panel */
if (par->output & OUTPUT_PANEL) {
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index c18880d9db1..0129c044f6d 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -551,7 +551,7 @@ static struct fb_ops hgafb_ops = {
* Initialization
*/
-static int __init hgafb_probe(struct device *device)
+static int __init hgafb_probe(struct platform_device *pdev)
{
struct fb_info *info;
@@ -565,7 +565,7 @@ static int __init hgafb_probe(struct device *device)
printk(KERN_INFO "hgafb: %s with %ldK of memory detected.\n",
hga_type_name, hga_vram_len/1024);
- info = framebuffer_alloc(0, NULL);
+ info = framebuffer_alloc(0, &pdev->dev);
if (!info) {
iounmap(hga_vram);
return -ENOMEM;
@@ -593,13 +593,13 @@ static int __init hgafb_probe(struct device *device)
printk(KERN_INFO "fb%d: %s frame buffer device\n",
info->node, info->fix.id);
- dev_set_drvdata(device, info);
+ platform_set_drvdata(pdev, info);
return 0;
}
-static int hgafb_remove(struct device *device)
+static int hgafb_remove(struct platform_device *pdev)
{
- struct fb_info *info = dev_get_drvdata(device);
+ struct fb_info *info = platform_get_drvdata(pdev);
hga_txt_mode();
hga_clear_screen();
@@ -620,16 +620,15 @@ static int hgafb_remove(struct device *device)
return 0;
}
-static struct device_driver hgafb_driver = {
- .name = "hgafb",
- .bus = &platform_bus_type,
+static struct platform_driver hgafb_driver = {
.probe = hgafb_probe,
.remove = hgafb_remove,
+ .driver = {
+ .name = "hgafb",
+ },
};
-static struct platform_device hgafb_device = {
- .name = "hgafb",
-};
+static struct platform_device *hgafb_device;
static int __init hgafb_init(void)
{
@@ -638,12 +637,15 @@ static int __init hgafb_init(void)
if (fb_get_options("hgafb", NULL))
return -ENODEV;
- ret = driver_register(&hgafb_driver);
+ ret = platform_driver_register(&hgafb_driver);
if (!ret) {
- ret = platform_device_register(&hgafb_device);
- if (ret)
- driver_unregister(&hgafb_driver);
+ hgafb_device = platform_device_register_simple("hgafb", 0, NULL, 0);
+
+ if (IS_ERR(hgafb_device)) {
+ platform_driver_unregister(&hgafb_driver);
+ ret = PTR_ERR(hgafb_device);
+ }
}
return ret;
@@ -651,8 +653,8 @@ static int __init hgafb_init(void)
static void __exit hgafb_exit(void)
{
- platform_device_unregister(&hgafb_device);
- driver_unregister(&hgafb_driver);
+ platform_device_unregister(hgafb_device);
+ platform_driver_unregister(&hgafb_driver);
}
/* -------------------------------------------------------------------------
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 94e4d3ac1a0..0c5a475c1ca 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -24,6 +24,7 @@
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
+#include <linux/mm.h>
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/init.h>
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 5246b0402d7..25172b2a2a9 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -201,7 +201,6 @@ static int neoFindMode(int xres, int yres, int depth)
*
* Determine the closest clock frequency to the one requested.
*/
-#define REF_FREQ 0xe517 /* 14.31818 in 20.12 fixed point */
#define MAX_N 127
#define MAX_D 31
#define MAX_F 1
@@ -211,27 +210,24 @@ static void neoCalcVCLK(const struct fb_info *info,
{
int n, d, f;
int n_best = 0, d_best = 0, f_best = 0;
- long f_best_diff = (0x7ffff << 12); /* 20.12 */
- long f_target = (freq << 12) / 1000; /* 20.12 */
+ long f_best_diff = 0x7ffff;
for (f = 0; f <= MAX_F; f++)
- for (n = 0; n <= MAX_N; n++)
- for (d = 0; d <= MAX_D; d++) {
- long f_out; /* 20.12 */
- long f_diff; /* 20.12 */
-
- f_out =
- ((((n + 1) << 12) / ((d +
- 1) *
- (1 << f))) >> 12)
- * REF_FREQ;
- f_diff = abs(f_out - f_target);
- if (f_diff < f_best_diff) {
+ for (d = 0; d <= MAX_D; d++)
+ for (n = 0; n <= MAX_N; n++) {
+ long f_out;
+ long f_diff;
+
+ f_out = ((14318 * (n + 1)) / (d + 1)) >> f;
+ f_diff = abs(f_out - freq);
+ if (f_diff <= f_best_diff) {
f_best_diff = f_diff;
n_best = n;
d_best = d;
f_best = f;
}
+ if (f_out > freq)
+ break;
}
if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
@@ -248,11 +244,11 @@ static void neoCalcVCLK(const struct fb_info *info,
par->VCLK3Denominator = d_best;
#ifdef NEOFB_DEBUG
- printk("neoVCLK: f:%d NumLow=%d NumHi=%d Den=%d Df=%d\n",
- f_target >> 12,
+ printk(KERN_DEBUG "neoVCLK: f:%ld NumLow=%d NumHi=%d Den=%d Df=%ld\n",
+ freq,
par->VCLK3NumeratorLow,
par->VCLK3NumeratorHigh,
- par->VCLK3Denominator, f_best_diff >> 12);
+ par->VCLK3Denominator, f_best_diff);
#endif
}
@@ -263,15 +259,20 @@ static void neoCalcVCLK(const struct fb_info *info,
*/
static int vgaHWInit(const struct fb_var_screeninfo *var,
- const struct fb_info *info,
- struct neofb_par *par, struct xtimings *timings)
+ struct neofb_par *par)
{
+ int hsync_end = var->xres + var->right_margin + var->hsync_len;
+ int htotal = (hsync_end + var->left_margin) >> 3;
+ int vsync_start = var->yres + var->lower_margin;
+ int vsync_end = vsync_start + var->vsync_len;
+ int vtotal = vsync_end + var->upper_margin;
+
par->MiscOutReg = 0x23;
- if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT))
+ if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
par->MiscOutReg |= 0x40;
- if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT))
+ if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
par->MiscOutReg |= 0x80;
/*
@@ -286,25 +287,25 @@ static int vgaHWInit(const struct fb_var_screeninfo *var,
/*
* CRTC Controller
*/
- par->CRTC[0] = (timings->HTotal >> 3) - 5;
- par->CRTC[1] = (timings->HDisplay >> 3) - 1;
- par->CRTC[2] = (timings->HDisplay >> 3) - 1;
- par->CRTC[3] = (((timings->HTotal >> 3) - 1) & 0x1F) | 0x80;
- par->CRTC[4] = (timings->HSyncStart >> 3);
- par->CRTC[5] = ((((timings->HTotal >> 3) - 1) & 0x20) << 2)
- | (((timings->HSyncEnd >> 3)) & 0x1F);
- par->CRTC[6] = (timings->VTotal - 2) & 0xFF;
- par->CRTC[7] = (((timings->VTotal - 2) & 0x100) >> 8)
- | (((timings->VDisplay - 1) & 0x100) >> 7)
- | ((timings->VSyncStart & 0x100) >> 6)
- | (((timings->VDisplay - 1) & 0x100) >> 5)
- | 0x10 | (((timings->VTotal - 2) & 0x200) >> 4)
- | (((timings->VDisplay - 1) & 0x200) >> 3)
- | ((timings->VSyncStart & 0x200) >> 2);
+ par->CRTC[0] = htotal - 5;
+ par->CRTC[1] = (var->xres >> 3) - 1;
+ par->CRTC[2] = (var->xres >> 3) - 1;
+ par->CRTC[3] = ((htotal - 1) & 0x1F) | 0x80;
+ par->CRTC[4] = ((var->xres + var->right_margin) >> 3);
+ par->CRTC[5] = (((htotal - 1) & 0x20) << 2)
+ | (((hsync_end >> 3)) & 0x1F);
+ par->CRTC[6] = (vtotal - 2) & 0xFF;
+ par->CRTC[7] = (((vtotal - 2) & 0x100) >> 8)
+ | (((var->yres - 1) & 0x100) >> 7)
+ | ((vsync_start & 0x100) >> 6)
+ | (((var->yres - 1) & 0x100) >> 5)
+ | 0x10 | (((vtotal - 2) & 0x200) >> 4)
+ | (((var->yres - 1) & 0x200) >> 3)
+ | ((vsync_start & 0x200) >> 2);
par->CRTC[8] = 0x00;
- par->CRTC[9] = (((timings->VDisplay - 1) & 0x200) >> 4) | 0x40;
+ par->CRTC[9] = (((var->yres - 1) & 0x200) >> 4) | 0x40;
- if (timings->dblscan)
+ if (var->vmode & FB_VMODE_DOUBLE)
par->CRTC[9] |= 0x80;
par->CRTC[10] = 0x00;
@@ -313,13 +314,13 @@ static int vgaHWInit(const struct fb_var_screeninfo *var,
par->CRTC[13] = 0x00;
par->CRTC[14] = 0x00;
par->CRTC[15] = 0x00;
- par->CRTC[16] = timings->VSyncStart & 0xFF;
- par->CRTC[17] = (timings->VSyncEnd & 0x0F) | 0x20;
- par->CRTC[18] = (timings->VDisplay - 1) & 0xFF;
+ par->CRTC[16] = vsync_start & 0xFF;
+ par->CRTC[17] = (vsync_end & 0x0F) | 0x20;
+ par->CRTC[18] = (var->yres - 1) & 0xFF;
par->CRTC[19] = var->xres_virtual >> 4;
par->CRTC[20] = 0x00;
- par->CRTC[21] = (timings->VDisplay - 1) & 0xFF;
- par->CRTC[22] = (timings->VTotal - 1) & 0xFF;
+ par->CRTC[21] = (var->yres - 1) & 0xFF;
+ par->CRTC[22] = (vtotal - 1) & 0xFF;
par->CRTC[23] = 0xC3;
par->CRTC[24] = 0xFF;
@@ -483,7 +484,8 @@ static inline int neo2200_sync(struct fb_info *info)
{
struct neofb_par *par = info->par;
- while (readl(&par->neo2200->bltStat) & 1);
+ while (readl(&par->neo2200->bltStat) & 1)
+ cpu_relax();
return 0;
}
@@ -591,34 +593,14 @@ static int
neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct neofb_par *par = info->par;
- unsigned int pixclock = var->pixclock;
- struct xtimings timings;
int memlen, vramlen;
int mode_ok = 0;
DBG("neofb_check_var");
- if (!pixclock)
- pixclock = 10000; /* 10ns = 100MHz */
- timings.pixclock = 1000000000 / pixclock;
- if (timings.pixclock < 1)
- timings.pixclock = 1;
-
- if (timings.pixclock > par->maxClock)
+ if (PICOS2KHZ(var->pixclock) > par->maxClock)
return -EINVAL;
- timings.dblscan = var->vmode & FB_VMODE_DOUBLE;
- timings.interlaced = var->vmode & FB_VMODE_INTERLACED;
- timings.HDisplay = var->xres;
- timings.HSyncStart = timings.HDisplay + var->right_margin;
- timings.HSyncEnd = timings.HSyncStart + var->hsync_len;
- timings.HTotal = timings.HSyncEnd + var->left_margin;
- timings.VDisplay = var->yres;
- timings.VSyncStart = timings.VDisplay + var->lower_margin;
- timings.VSyncEnd = timings.VSyncStart + var->vsync_len;
- timings.VTotal = timings.VSyncEnd + var->upper_margin;
- timings.sync = var->sync;
-
/* Is the mode larger than the LCD panel? */
if (par->internal_display &&
((var->xres > par->NeoPanelWidth) ||
@@ -759,11 +741,11 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int neofb_set_par(struct fb_info *info)
{
struct neofb_par *par = info->par;
- struct xtimings timings;
unsigned char temp;
int i, clock_hi = 0;
int lcd_stretch;
int hoffset, voffset;
+ int vsync_start, vtotal;
DBG("neofb_set_par");
@@ -771,28 +753,15 @@ static int neofb_set_par(struct fb_info *info)
vgaHWProtect(1); /* Blank the screen */
- timings.dblscan = info->var.vmode & FB_VMODE_DOUBLE;
- timings.interlaced = info->var.vmode & FB_VMODE_INTERLACED;
- timings.HDisplay = info->var.xres;
- timings.HSyncStart = timings.HDisplay + info->var.right_margin;
- timings.HSyncEnd = timings.HSyncStart + info->var.hsync_len;
- timings.HTotal = timings.HSyncEnd + info->var.left_margin;
- timings.VDisplay = info->var.yres;
- timings.VSyncStart = timings.VDisplay + info->var.lower_margin;
- timings.VSyncEnd = timings.VSyncStart + info->var.vsync_len;
- timings.VTotal = timings.VSyncEnd + info->var.upper_margin;
- timings.sync = info->var.sync;
- timings.pixclock = PICOS2KHZ(info->var.pixclock);
-
- if (timings.pixclock < 1)
- timings.pixclock = 1;
+ vsync_start = info->var.yres + info->var.lower_margin;
+ vtotal = vsync_start + info->var.vsync_len + info->var.upper_margin;
/*
* This will allocate the datastructure and initialize all of the
* generic VGA registers.
*/
- if (vgaHWInit(&info->var, info, par, &timings))
+ if (vgaHWInit(&info->var, par))
return -EINVAL;
/*
@@ -831,10 +800,10 @@ static int neofb_set_par(struct fb_info *info)
par->ExtCRTDispAddr = 0x10;
/* Vertical Extension */
- par->VerticalExt = (((timings.VTotal - 2) & 0x400) >> 10)
- | (((timings.VDisplay - 1) & 0x400) >> 9)
- | (((timings.VSyncStart) & 0x400) >> 8)
- | (((timings.VSyncStart) & 0x400) >> 7);
+ par->VerticalExt = (((vtotal - 2) & 0x400) >> 10)
+ | (((info->var.yres - 1) & 0x400) >> 9)
+ | (((vsync_start) & 0x400) >> 8)
+ | (((vsync_start) & 0x400) >> 7);
/* Fast write bursts on unless disabled. */
if (par->pci_burst)
@@ -995,7 +964,7 @@ static int neofb_set_par(struct fb_info *info)
* Calculate the VCLK that most closely matches the requested dot
* clock.
*/
- neoCalcVCLK(info, par, timings.pixclock);
+ neoCalcVCLK(info, par, PICOS2KHZ(info->var.pixclock));
/* Since we program the clocks ourselves, always use VCLK3. */
par->MiscOutReg |= 0x0C;
@@ -1927,9 +1896,6 @@ static int __devinit neo_init_hw(struct fb_info *info)
int maxClock = 65000;
int CursorMem = 1024;
int CursorOff = 0x100;
- int linearSize = 1024;
- int maxWidth = 1024;
- int maxHeight = 1024;
DBG("neo_init_hw");
@@ -1948,81 +1914,52 @@ static int __devinit neo_init_hw(struct fb_info *info)
case FB_ACCEL_NEOMAGIC_NM2070:
videoRam = 896;
maxClock = 65000;
- CursorMem = 2048;
- CursorOff = 0x100;
- linearSize = 1024;
- maxWidth = 1024;
- maxHeight = 1024;
break;
case FB_ACCEL_NEOMAGIC_NM2090:
case FB_ACCEL_NEOMAGIC_NM2093:
- videoRam = 1152;
- maxClock = 80000;
- CursorMem = 2048;
- CursorOff = 0x100;
- linearSize = 2048;
- maxWidth = 1024;
- maxHeight = 1024;
- break;
case FB_ACCEL_NEOMAGIC_NM2097:
videoRam = 1152;
maxClock = 80000;
- CursorMem = 1024;
- CursorOff = 0x100;
- linearSize = 2048;
- maxWidth = 1024;
- maxHeight = 1024;
break;
case FB_ACCEL_NEOMAGIC_NM2160:
videoRam = 2048;
maxClock = 90000;
- CursorMem = 1024;
- CursorOff = 0x100;
- linearSize = 2048;
- maxWidth = 1024;
- maxHeight = 1024;
break;
case FB_ACCEL_NEOMAGIC_NM2200:
videoRam = 2560;
maxClock = 110000;
- CursorMem = 1024;
- CursorOff = 0x1000;
- linearSize = 4096;
- maxWidth = 1280;
- maxHeight = 1024; /* ???? */
-
- par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
break;
case FB_ACCEL_NEOMAGIC_NM2230:
videoRam = 3008;
maxClock = 110000;
- CursorMem = 1024;
- CursorOff = 0x1000;
- linearSize = 4096;
- maxWidth = 1280;
- maxHeight = 1024; /* ???? */
-
- par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
break;
case FB_ACCEL_NEOMAGIC_NM2360:
videoRam = 4096;
maxClock = 110000;
- CursorMem = 1024;
- CursorOff = 0x1000;
- linearSize = 4096;
- maxWidth = 1280;
- maxHeight = 1024; /* ???? */
-
- par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
break;
case FB_ACCEL_NEOMAGIC_NM2380:
videoRam = 6144;
maxClock = 110000;
+ break;
+ }
+ switch (info->fix.accel) {
+ case FB_ACCEL_NEOMAGIC_NM2070:
+ case FB_ACCEL_NEOMAGIC_NM2090:
+ case FB_ACCEL_NEOMAGIC_NM2093:
+ CursorMem = 2048;
+ CursorOff = 0x100;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2097:
+ case FB_ACCEL_NEOMAGIC_NM2160:
+ CursorMem = 1024;
+ CursorOff = 0x100;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2200:
+ case FB_ACCEL_NEOMAGIC_NM2230:
+ case FB_ACCEL_NEOMAGIC_NM2360:
+ case FB_ACCEL_NEOMAGIC_NM2380:
CursorMem = 1024;
CursorOff = 0x1000;
- linearSize = 8192;
- maxWidth = 1280;
- maxHeight = 1024; /* ???? */
par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
break;
@@ -2036,7 +1973,7 @@ static int __devinit neo_init_hw(struct fb_info *info)
*/
par->maxClock = maxClock;
par->cursorOff = CursorOff;
- return ((videoRam * 1024));
+ return videoRam * 1024;
}
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index d7b3dcc0dc4..e1d9eeb1aea 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -47,6 +47,7 @@ enum {
cmap_M3B, /* ATI Rage Mobility M3 Head B */
cmap_radeon, /* ATI Radeon */
cmap_gxt2000, /* IBM GXT2000 */
+ cmap_avivo, /* ATI R5xx */
};
struct offb_par {
@@ -58,26 +59,36 @@ struct offb_par {
struct offb_par default_par;
- /*
- * Interface used by the world
- */
-
-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);
-
#ifdef CONFIG_PPC32
extern boot_infos_t *boot_infos;
#endif
-static struct fb_ops offb_ops = {
- .owner = THIS_MODULE,
- .fb_setcolreg = offb_setcolreg,
- .fb_blank = offb_blank,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
-};
+/* Definitions used by the Avivo palette hack */
+#define AVIVO_DC_LUT_RW_SELECT 0x6480
+#define AVIVO_DC_LUT_RW_MODE 0x6484
+#define AVIVO_DC_LUT_RW_INDEX 0x6488
+#define AVIVO_DC_LUT_SEQ_COLOR 0x648c
+#define AVIVO_DC_LUT_PWL_DATA 0x6490
+#define AVIVO_DC_LUT_30_COLOR 0x6494
+#define AVIVO_DC_LUT_READ_PIPE_SELECT 0x6498
+#define AVIVO_DC_LUT_WRITE_EN_MASK 0x649c
+#define AVIVO_DC_LUT_AUTOFILL 0x64a0
+
+#define AVIVO_DC_LUTA_CONTROL 0x64c0
+#define AVIVO_DC_LUTA_BLACK_OFFSET_BLUE 0x64c4
+#define AVIVO_DC_LUTA_BLACK_OFFSET_GREEN 0x64c8
+#define AVIVO_DC_LUTA_BLACK_OFFSET_RED 0x64cc
+#define AVIVO_DC_LUTA_WHITE_OFFSET_BLUE 0x64d0
+#define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN 0x64d4
+#define AVIVO_DC_LUTA_WHITE_OFFSET_RED 0x64d8
+
+#define AVIVO_DC_LUTB_CONTROL 0x6cc0
+#define AVIVO_DC_LUTB_BLACK_OFFSET_BLUE 0x6cc4
+#define AVIVO_DC_LUTB_BLACK_OFFSET_GREEN 0x6cc8
+#define AVIVO_DC_LUTB_BLACK_OFFSET_RED 0x6ccc
+#define AVIVO_DC_LUTB_WHITE_OFFSET_BLUE 0x6cd0
+#define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN 0x6cd4
+#define AVIVO_DC_LUTB_WHITE_OFFSET_RED 0x6cd8
/*
* Set a single color register. The values supplied are already
@@ -160,6 +171,17 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
out_le32(((unsigned __iomem *) par->cmap_adr) + regno,
(red << 16 | green << 8 | blue));
break;
+ case cmap_avivo:
+ /* Write to both LUTs for now */
+ writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+ writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+ writel(((red) << 22) | ((green) << 12) | ((blue) << 2),
+ par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+ writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+ writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+ writel(((red) << 22) | ((green) << 12) | ((blue) << 2),
+ par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+ break;
}
return 0;
@@ -216,12 +238,59 @@ static int offb_blank(int blank, struct fb_info *info)
out_le32(((unsigned __iomem *) par->cmap_adr) + i,
0);
break;
+ case cmap_avivo:
+ writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+ writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+ writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+ writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+ writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+ writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+ break;
}
} else
fb_set_cmap(&info->cmap, info);
return 0;
}
+static int offb_set_par(struct fb_info *info)
+{
+ struct offb_par *par = (struct offb_par *) info->par;
+
+ /* On avivo, initialize palette control */
+ if (par->cmap_type == cmap_avivo) {
+ writel(0, par->cmap_adr + AVIVO_DC_LUTA_CONTROL);
+ writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_BLUE);
+ writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_GREEN);
+ writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_RED);
+ writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_BLUE);
+ writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_GREEN);
+ writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_RED);
+ writel(0, par->cmap_adr + AVIVO_DC_LUTB_CONTROL);
+ writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_BLUE);
+ writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_GREEN);
+ writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_RED);
+ writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_BLUE);
+ writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_GREEN);
+ writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_RED);
+ writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+ writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE);
+ writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK);
+ writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+ writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE);
+ writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK);
+ }
+ return 0;
+}
+
+static struct fb_ops offb_ops = {
+ .owner = THIS_MODULE,
+ .fb_setcolreg = offb_setcolreg,
+ .fb_set_par = offb_set_par,
+ .fb_blank = offb_blank,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
static void __iomem *offb_map_reg(struct device_node *np, int index,
unsigned long offset, unsigned long size)
@@ -245,6 +314,59 @@ static void __iomem *offb_map_reg(struct device_node *np, int index,
return ioremap(taddr + offset, size);
}
+static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp,
+ const char *name, unsigned long address)
+{
+ struct offb_par *par = (struct offb_par *) info->par;
+
+ if (dp && !strncmp(name, "ATY,Rage128", 11)) {
+ 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))) {
+ 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)) {
+ 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)) {
+ 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 (dp && (of_device_is_compatible(dp, "pci1014,b7") ||
+ of_device_is_compatible(dp, "pci1014,21c"))) {
+ par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
+ if (par->cmap_adr)
+ par->cmap_type = cmap_gxt2000;
+ } else if (dp && !strncmp(name, "vga,Display-", 12)) {
+ /* Look for AVIVO initialized by SLOF */
+ struct device_node *pciparent = of_get_parent(dp);
+ const u32 *vid, *did;
+ vid = of_get_property(pciparent, "vendor-id", NULL);
+ did = of_get_property(pciparent, "device-id", NULL);
+ /* This will match most R5xx */
+ if (vid && did && *vid == 0x1002 &&
+ ((*did >= 0x7100 && *did < 0x7800) ||
+ (*did >= 0x9400))) {
+ par->cmap_adr = offb_map_reg(pciparent, 2, 0, 0x10000);
+ if (par->cmap_adr)
+ par->cmap_type = cmap_avivo;
+ }
+ of_node_put(pciparent);
+ }
+ info->fix.visual = (par->cmap_type != cmap_unknown) ?
+ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR;
+}
+
static void __init offb_init_fb(const char *name, const char *full_name,
int width, int height, int depth,
int pitch, unsigned long address,
@@ -283,6 +405,7 @@ static void __init offb_init_fb(const char *name, const char *full_name,
fix = &info->fix;
var = &info->var;
+ info->par = par;
strcpy(fix->id, "OFfb ");
strncat(fix->id, name, sizeof(fix->id) - sizeof("OFfb "));
@@ -298,39 +421,9 @@ static void __init offb_init_fb(const char *name, const char *full_name,
fix->type_aux = 0;
par->cmap_type = cmap_unknown;
- if (depth == 8) {
- if (dp && !strncmp(name, "ATY,Rage128", 11)) {
- 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))) {
- 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)) {
- 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)) {
- 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 (dp && (of_device_is_compatible(dp, "pci1014,b7") ||
- of_device_is_compatible(dp, "pci1014,21c"))) {
- par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
- if (par->cmap_adr)
- par->cmap_type = cmap_gxt2000;
- }
- fix->visual = (par->cmap_type != cmap_unknown) ?
- FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR;
- } else
+ if (depth == 8)
+ offb_init_palette_hacks(info, dp, name, address);
+ else
fix->visual = FB_VISUAL_TRUECOLOR;
var->xoffset = var->yoffset = 0;
@@ -395,7 +488,6 @@ static void __init offb_init_fb(const char *name, const char *full_name,
info->fbops = &offb_ops;
info->screen_base = ioremap(address, fix->smem_len);
- info->par = par;
info->pseudo_palette = (void *) (info + 1);
info->flags = FBINFO_DEFAULT | foreign_endian;
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
index ab32ceb0617..ab77c51fe9d 100644
--- a/drivers/video/omap/dispc.c
+++ b/drivers/video/omap/dispc.c
@@ -20,6 +20,7 @@
*/
#include <linux/kernel.h>
#include <linux/dma-mapping.h>
+#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/clk.h>
#include <linux/io.h>
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index 14d0f7a1114..f85af5c4fa6 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -25,6 +25,7 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/platform_device.h>
+#include <linux/mm.h>
#include <linux/uaccess.h>
#include <asm/mach-types.h>
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index dc3af1c78c5..4b5d8077190 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -1297,6 +1297,7 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
static struct ps3_system_bus_driver ps3fb_driver = {
.match_id = PS3_MATCH_ID_GRAPHICS,
+ .match_sub_id = PS3_MATCH_SUB_ID_FB,
.core.name = DEVICE_NAME,
.core.owner = THIS_MODULE,
.probe = ps3fb_probe,
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index d0746261c95..2b707a8ce5d 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -30,6 +30,7 @@
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
+#include <linux/mm.h>
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/init.h>
@@ -40,6 +41,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/completion.h>
+#include <linux/mutex.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
@@ -227,6 +229,22 @@ static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var)
case 4: ret = LCCR3_4BPP; break;
case 8: ret = LCCR3_8BPP; break;
case 16: ret = LCCR3_16BPP; break;
+ case 24:
+ switch (var->red.length + var->green.length +
+ var->blue.length + var->transp.length) {
+ case 18: ret = LCCR3_18BPP_P | LCCR3_PDFOR_3; break;
+ case 19: ret = LCCR3_19BPP_P; break;
+ }
+ break;
+ case 32:
+ switch (var->red.length + var->green.length +
+ var->blue.length + var->transp.length) {
+ case 18: ret = LCCR3_18BPP | LCCR3_PDFOR_3; break;
+ case 19: ret = LCCR3_19BPP; break;
+ case 24: ret = LCCR3_24BPP | LCCR3_PDFOR_3; break;
+ case 25: ret = LCCR3_25BPP; break;
+ }
+ break;
}
return ret;
}
@@ -345,6 +363,41 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->green.offset = 5; var->green.length = 6;
var->blue.offset = 0; var->blue.length = 5;
var->transp.offset = var->transp.length = 0;
+ } else if (var->bits_per_pixel > 16) {
+ struct pxafb_mode_info *mode;
+
+ mode = pxafb_getmode(inf, var);
+ if (!mode)
+ return -EINVAL;
+
+ switch (mode->depth) {
+ case 18: /* RGB666 */
+ var->transp.offset = var->transp.length = 0;
+ var->red.offset = 12; var->red.length = 6;
+ var->green.offset = 6; var->green.length = 6;
+ var->blue.offset = 0; var->blue.length = 6;
+ break;
+ case 19: /* RGBT666 */
+ var->transp.offset = 18; var->transp.length = 1;
+ var->red.offset = 12; var->red.length = 6;
+ var->green.offset = 6; var->green.length = 6;
+ var->blue.offset = 0; var->blue.length = 6;
+ break;
+ case 24: /* RGB888 */
+ var->transp.offset = var->transp.length = 0;
+ var->red.offset = 16; var->red.length = 8;
+ var->green.offset = 8; var->green.length = 8;
+ var->blue.offset = 0; var->blue.length = 8;
+ break;
+ case 25: /* RGBT888 */
+ var->transp.offset = 24; var->transp.length = 1;
+ var->red.offset = 16; var->red.length = 8;
+ var->green.offset = 8; var->green.length = 8;
+ var->blue.offset = 0; var->blue.length = 8;
+ break;
+ default:
+ return -EINVAL;
+ }
} else {
var->red.offset = var->green.offset = 0;
var->blue.offset = var->transp.offset = 0;
@@ -376,7 +429,7 @@ static int pxafb_set_par(struct fb_info *info)
struct pxafb_info *fbi = (struct pxafb_info *)info;
struct fb_var_screeninfo *var = &info->var;
- if (var->bits_per_pixel == 16)
+ if (var->bits_per_pixel >= 16)
fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
else if (!fbi->cmap_static)
fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
@@ -391,7 +444,7 @@ static int pxafb_set_par(struct fb_info *info)
fbi->fb.fix.line_length = var->xres_virtual *
var->bits_per_pixel / 8;
- if (var->bits_per_pixel == 16)
+ if (var->bits_per_pixel >= 16)
fbi->palette_size = 0;
else
fbi->palette_size = var->bits_per_pixel == 1 ?
@@ -404,7 +457,7 @@ static int pxafb_set_par(struct fb_info *info)
*/
pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);
- if (fbi->fb.var.bits_per_pixel == 16)
+ if (fbi->fb.var.bits_per_pixel >= 16)
fb_dealloc_cmap(&fbi->fb.cmap);
else
fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0);
@@ -831,6 +884,8 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
case 4:
case 8:
case 16:
+ case 24:
+ case 32:
break;
default:
printk(KERN_ERR "%s: invalid bit depth %d\n",
@@ -968,6 +1023,11 @@ static void pxafb_setup_gpio(struct pxafb_info *fbi)
for (gpio = 58; ldd_bits; gpio++, ldd_bits--)
pxa_gpio_mode(gpio | GPIO_ALT_FN_2_OUT);
+ /* 18 bit interface */
+ if (fbi->fb.var.bits_per_pixel > 16) {
+ pxa_gpio_mode(86 | GPIO_ALT_FN_2_OUT);
+ pxa_gpio_mode(87 | GPIO_ALT_FN_2_OUT);
+ }
pxa_gpio_mode(GPIO74_LCD_FCLK_MD);
pxa_gpio_mode(GPIO75_LCD_LCLK_MD);
pxa_gpio_mode(GPIO76_LCD_PCLK_MD);
@@ -1058,7 +1118,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
{
u_int old_state;
- down(&fbi->ctrlr_sem);
+ mutex_lock(&fbi->ctrlr_lock);
old_state = fbi->state;
@@ -1146,7 +1206,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
}
break;
}
- up(&fbi->ctrlr_sem);
+ mutex_unlock(&fbi->ctrlr_lock);
}
/*
@@ -1399,7 +1459,7 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev)
init_waitqueue_head(&fbi->ctrlr_wait);
INIT_WORK(&fbi->task, pxafb_task);
- init_MUTEX(&fbi->ctrlr_sem);
+ mutex_init(&fbi->ctrlr_lock);
init_completion(&fbi->disable_done);
#ifdef CONFIG_FB_PXA_SMARTPANEL
init_completion(&fbi->command_done);
diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h
index 8238dc82642..31541b86f13 100644
--- a/drivers/video/pxafb.h
+++ b/drivers/video/pxafb.h
@@ -106,7 +106,7 @@ struct pxafb_info {
volatile u_char state;
volatile u_char task_state;
- struct semaphore ctrlr_sem;
+ struct mutex ctrlr_lock;
wait_queue_head_t ctrlr_wait;
struct work_struct task;
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index ab2b2110478..78bcdbc3f48 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -167,6 +167,7 @@
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
+#include <linux/mm.h>
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/init.h>
@@ -174,6 +175,7 @@
#include <linux/cpufreq.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <linux/mutex.h>
#include <asm/hardware.h>
#include <asm/io.h>
@@ -1107,7 +1109,7 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
{
u_int old_state;
- down(&fbi->ctrlr_sem);
+ mutex_lock(&fbi->ctrlr_lock);
old_state = fbi->state;
@@ -1192,7 +1194,7 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
}
break;
}
- up(&fbi->ctrlr_sem);
+ mutex_unlock(&fbi->ctrlr_lock);
}
/*
@@ -1444,7 +1446,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
init_waitqueue_head(&fbi->ctrlr_wait);
INIT_WORK(&fbi->task, sa1100fb_task);
- init_MUTEX(&fbi->ctrlr_sem);
+ mutex_init(&fbi->ctrlr_lock);
return fbi;
}
diff --git a/drivers/video/sa1100fb.h b/drivers/video/sa1100fb.h
index f465b27ed86..86831db9a04 100644
--- a/drivers/video/sa1100fb.h
+++ b/drivers/video/sa1100fb.h
@@ -100,7 +100,7 @@ struct sa1100fb_info {
volatile u_char state;
volatile u_char task_state;
- struct semaphore ctrlr_sem;
+ struct mutex ctrlr_lock;
wait_queue_head_t ctrlr_wait;
struct work_struct task;
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c
new file mode 100644
index 00000000000..4d0e28c5790
--- /dev/null
+++ b/drivers/video/sh7760fb.c
@@ -0,0 +1,658 @@
+/*
+ * SH7760/SH7763 LCDC Framebuffer driver.
+ *
+ * (c) 2006-2008 MSC Vertriebsges.m.b.H.,
+ * Manuel Lauss <mano@roarinelk.homelinux.net>
+ * (c) 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.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.
+ *
+ * PLEASE HAVE A LOOK AT Documentation/fb/sh7760fb.txt!
+ *
+ * Thanks to Siegfried Schaefer <s.schaefer at schaefer-edv.de>
+ * for his original source and testing!
+ */
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/sh7760fb.h>
+
+struct sh7760fb_par {
+ void __iomem *base;
+ int irq;
+
+ struct sh7760fb_platdata *pd; /* display information */
+
+ dma_addr_t fbdma; /* physical address */
+
+ int rot; /* rotation enabled? */
+
+ u32 pseudo_palette[16];
+
+ struct platform_device *dev;
+ struct resource *ioarea;
+ struct completion vsync; /* vsync irq event */
+};
+
+static irqreturn_t sh7760fb_irq(int irq, void *data)
+{
+ struct completion *c = data;
+
+ complete(c);
+
+ return IRQ_HANDLED;
+}
+
+static void sh7760fb_wait_vsync(struct fb_info *info)
+{
+ struct sh7760fb_par *par = info->par;
+
+ if (par->pd->novsync)
+ return;
+
+ iowrite16(ioread16(par->base + LDINTR) & ~VINT_CHECK,
+ par->base + LDINTR);
+
+ if (par->irq < 0) {
+ /* poll for vert. retrace: status bit is sticky */
+ while (!(ioread16(par->base + LDINTR) & VINT_CHECK))
+ cpu_relax();
+ } else {
+ /* a "wait_for_irq_event(par->irq)" would be extremely nice */
+ init_completion(&par->vsync);
+ enable_irq(par->irq);
+ wait_for_completion(&par->vsync);
+ disable_irq_nosync(par->irq);
+ }
+}
+
+/* wait_for_lps - wait until power supply has reached a certain state. */
+static int wait_for_lps(struct sh7760fb_par *par, int val)
+{
+ int i = 100;
+ while (--i && ((ioread16(par->base + LDPMMR) & 3) != val))
+ msleep(1);
+
+ if (i <= 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+/* en/disable the LCDC */
+static int sh7760fb_blank(int blank, struct fb_info *info)
+{
+ struct sh7760fb_par *par = info->par;
+ struct sh7760fb_platdata *pd = par->pd;
+ unsigned short cntr = ioread16(par->base + LDCNTR);
+ unsigned short intr = ioread16(par->base + LDINTR);
+ int lps;
+
+ if (blank == FB_BLANK_UNBLANK) {
+ intr |= VINT_START;
+ cntr = LDCNTR_DON2 | LDCNTR_DON;
+ lps = 3;
+ } else {
+ intr &= ~VINT_START;
+ cntr = LDCNTR_DON2;
+ lps = 0;
+ }
+
+ if (pd->blank)
+ pd->blank(blank);
+
+ iowrite16(intr, par->base + LDINTR);
+ iowrite16(cntr, par->base + LDCNTR);
+
+ return wait_for_lps(par, lps);
+}
+
+/* set color registers */
+static int sh7760fb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+ struct sh7760fb_par *par = info->par;
+ u32 s = cmap->start;
+ u32 l = cmap->len;
+ u16 *r = cmap->red;
+ u16 *g = cmap->green;
+ u16 *b = cmap->blue;
+ u32 col, tmo;
+ int ret;
+
+ ret = 0;
+
+ sh7760fb_wait_vsync(info);
+
+ /* request palette access */
+ iowrite16(LDPALCR_PALEN, par->base + LDPALCR);
+
+ /* poll for access grant */
+ tmo = 100;
+ while (!(ioread16(par->base + LDPALCR) & LDPALCR_PALS) && (--tmo))
+ cpu_relax();
+
+ if (!tmo) {
+ ret = 1;
+ dev_dbg(info->dev, "no palette access!\n");
+ goto out;
+ }
+
+ while (l && (s < 256)) {
+ col = ((*r) & 0xff) << 16;
+ col |= ((*g) & 0xff) << 8;
+ col |= ((*b) & 0xff);
+ col &= SH7760FB_PALETTE_MASK;
+
+ if (s < 16)
+ ((u32 *) (info->pseudo_palette))[s] = s;
+
+ s++;
+ l--;
+ r++;
+ g++;
+ b++;
+ }
+out:
+ iowrite16(0, par->base + LDPALCR);
+ return ret;
+}
+
+static void encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info,
+ unsigned long stride)
+{
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+ strcpy(fix->id, "sh7760-lcdc");
+
+ fix->smem_start = (unsigned long)info->screen_base;
+ fix->smem_len = info->screen_size;
+
+ fix->line_length = stride;
+}
+
+static int sh7760fb_get_color_info(struct device *dev,
+ u16 lddfr, int *bpp, int *gray)
+{
+ int lbpp, lgray;
+
+ lgray = lbpp = 0;
+
+ switch (lddfr & LDDFR_COLOR_MASK) {
+ case LDDFR_1BPP_MONO:
+ lgray = 1;
+ lbpp = 1;
+ break;
+ case LDDFR_2BPP_MONO:
+ lgray = 1;
+ lbpp = 2;
+ break;
+ case LDDFR_4BPP_MONO:
+ lgray = 1;
+ case LDDFR_4BPP:
+ lbpp = 4;
+ break;
+ case LDDFR_6BPP_MONO:
+ lgray = 1;
+ case LDDFR_8BPP:
+ lbpp = 8;
+ break;
+ case LDDFR_16BPP_RGB555:
+ case LDDFR_16BPP_RGB565:
+ lbpp = 16;
+ lgray = 0;
+ break;
+ default:
+ dev_dbg(dev, "unsupported LDDFR bit depth.\n");
+ return -EINVAL;
+ }
+
+ if (bpp)
+ *bpp = lbpp;
+ if (gray)
+ *gray = lgray;
+
+ return 0;
+}
+
+static int sh7760fb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct fb_fix_screeninfo *fix = &info->fix;
+ struct sh7760fb_par *par = info->par;
+ int ret, bpp;
+
+ /* get color info from register value */
+ ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, NULL);
+ if (ret)
+ return ret;
+
+ var->bits_per_pixel = bpp;
+
+ if ((var->grayscale) && (var->bits_per_pixel == 1))
+ fix->visual = FB_VISUAL_MONO10;
+ else if (var->bits_per_pixel >= 15)
+ fix->visual = FB_VISUAL_TRUECOLOR;
+ else
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+
+ /* TODO: add some more validation here */
+ return 0;
+}
+
+/*
+ * sh7760fb_set_par - set videomode.
+ *
+ * NOTE: The rotation, grayscale and DSTN codepaths are
+ * totally untested!
+ */
+static int sh7760fb_set_par(struct fb_info *info)
+{
+ struct sh7760fb_par *par = info->par;
+ struct fb_videomode *vm = par->pd->def_mode;
+ unsigned long sbase, dstn_off, ldsarl, stride;
+ unsigned short hsynp, hsynw, htcn, hdcn;
+ unsigned short vsynp, vsynw, vtln, vdln;
+ unsigned short lddfr, ldmtr;
+ int ret, bpp, gray;
+
+ par->rot = par->pd->rotate;
+
+ /* rotate only works with xres <= 320 */
+ if (par->rot && (vm->xres > 320)) {
+ dev_dbg(info->dev, "rotation disabled due to display size\n");
+ par->rot = 0;
+ }
+
+ /* calculate LCDC reg vals from display parameters */
+ hsynp = vm->right_margin + vm->xres;
+ hsynw = vm->hsync_len;
+ htcn = vm->left_margin + hsynp + hsynw;
+ hdcn = vm->xres;
+ vsynp = vm->lower_margin + vm->yres;
+ vsynw = vm->vsync_len;
+ vtln = vm->upper_margin + vsynp + vsynw;
+ vdln = vm->yres;
+
+ /* get color info from register value */
+ ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, &gray);
+ if (ret)
+ return ret;
+
+ dev_dbg(info->dev, "%dx%d %dbpp %s (orientation %s)\n", hdcn,
+ vdln, bpp, gray ? "grayscale" : "color",
+ par->rot ? "rotated" : "normal");
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ lddfr = par->pd->lddfr | (1 << 8);
+#else
+ lddfr = par->pd->lddfr & ~(1 << 8);
+#endif
+
+ ldmtr = par->pd->ldmtr;
+
+ if (!(vm->sync & FB_SYNC_HOR_HIGH_ACT))
+ ldmtr |= LDMTR_CL1POL;
+ if (!(vm->sync & FB_SYNC_VERT_HIGH_ACT))
+ ldmtr |= LDMTR_FLMPOL;
+
+ /* shut down LCDC before changing display parameters */
+ sh7760fb_blank(FB_BLANK_POWERDOWN, info);
+
+ iowrite16(par->pd->ldickr, par->base + LDICKR); /* pixclock */
+ iowrite16(ldmtr, par->base + LDMTR); /* polarities */
+ iowrite16(lddfr, par->base + LDDFR); /* color/depth */
+ iowrite16((par->rot ? 1 << 13 : 0), par->base + LDSMR); /* rotate */
+ iowrite16(par->pd->ldpmmr, par->base + LDPMMR); /* Power Management */
+ iowrite16(par->pd->ldpspr, par->base + LDPSPR); /* Power Supply Ctrl */
+
+ /* display resolution */
+ iowrite16(((htcn >> 3) - 1) | (((hdcn >> 3) - 1) << 8),
+ par->base + LDHCNR);
+ iowrite16(vdln - 1, par->base + LDVDLNR);
+ iowrite16(vtln - 1, par->base + LDVTLNR);
+ /* h/v sync signals */
+ iowrite16((vsynp - 1) | ((vsynw - 1) << 12), par->base + LDVSYNR);
+ iowrite16(((hsynp >> 3) - 1) | (((hsynw >> 3) - 1) << 12),
+ par->base + LDHSYNR);
+ /* AC modulation sig */
+ iowrite16(par->pd->ldaclnr, par->base + LDACLNR);
+
+ stride = (par->rot) ? vtln : hdcn;
+ if (!gray)
+ stride *= (bpp + 7) >> 3;
+ else {
+ if (bpp == 1)
+ stride >>= 3;
+ else if (bpp == 2)
+ stride >>= 2;
+ else if (bpp == 4)
+ stride >>= 1;
+ /* 6 bpp == 8 bpp */
+ }
+
+ /* if rotated, stride must be power of 2 */
+ if (par->rot) {
+ unsigned long bit = 1 << 31;
+ while (bit) {
+ if (stride & bit)
+ break;
+ bit >>= 1;
+ }
+ if (stride & ~bit)
+ stride = bit << 1; /* not P-o-2, round up */
+ }
+ iowrite16(stride, par->base + LDLAOR);
+
+ /* set display mem start address */
+ sbase = (unsigned long)par->fbdma;
+ if (par->rot)
+ sbase += (hdcn - 1) * stride;
+
+ iowrite32(sbase, par->base + LDSARU);
+
+ /*
+ * for DSTN need to set address for lower half.
+ * I (mlau) don't know which address to set it to,
+ * so I guessed at (stride * yres/2).
+ */
+ if (((ldmtr & 0x003f) >= LDMTR_DSTN_MONO_8) &&
+ ((ldmtr & 0x003f) <= LDMTR_DSTN_COLOR_16)) {
+
+ dev_dbg(info->dev, " ***** DSTN untested! *****\n");
+
+ dstn_off = stride;
+ if (par->rot)
+ dstn_off *= hdcn >> 1;
+ else
+ dstn_off *= vdln >> 1;
+
+ ldsarl = sbase + dstn_off;
+ } else
+ ldsarl = 0;
+
+ iowrite32(ldsarl, par->base + LDSARL); /* mem for lower half of DSTN */
+
+ encode_fix(&info->fix, info, stride);
+ sh7760fb_check_var(&info->var, info);
+
+ sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */
+
+ dev_dbg(info->dev, "hdcn : %6d htcn : %6d\n", hdcn, htcn);
+ dev_dbg(info->dev, "hsynw : %6d hsynp : %6d\n", hsynw, hsynp);
+ dev_dbg(info->dev, "vdln : %6d vtln : %6d\n", vdln, vtln);
+ dev_dbg(info->dev, "vsynw : %6d vsynp : %6d\n", vsynw, vsynp);
+ dev_dbg(info->dev, "clksrc: %6d clkdiv: %6d\n",
+ (par->pd->ldickr >> 12) & 3, par->pd->ldickr & 0x1f);
+ dev_dbg(info->dev, "ldpmmr: 0x%04x ldpspr: 0x%04x\n", par->pd->ldpmmr,
+ par->pd->ldpspr);
+ dev_dbg(info->dev, "ldmtr : 0x%04x lddfr : 0x%04x\n", ldmtr, lddfr);
+ dev_dbg(info->dev, "ldlaor: %ld\n", stride);
+ dev_dbg(info->dev, "ldsaru: 0x%08lx ldsarl: 0x%08lx\n", sbase, ldsarl);
+
+ return 0;
+}
+
+static struct fb_ops sh7760fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_blank = sh7760fb_blank,
+ .fb_check_var = sh7760fb_check_var,
+ .fb_setcmap = sh7760fb_setcmap,
+ .fb_set_par = sh7760fb_set_par,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+static void sh7760fb_free_mem(struct fb_info *info)
+{
+ struct sh7760fb_par *par = info->par;
+
+ if (!info->screen_base)
+ return;
+
+ dma_free_coherent(info->dev, info->screen_size,
+ info->screen_base, par->fbdma);
+
+ par->fbdma = 0;
+ info->screen_base = NULL;
+ info->screen_size = 0;
+}
+
+/* allocate the framebuffer memory. This memory must be in Area3,
+ * (dictated by the DMA engine) and contiguous, at a 512 byte boundary.
+ */
+static int sh7760fb_alloc_mem(struct fb_info *info)
+{
+ struct sh7760fb_par *par = info->par;
+ void *fbmem;
+ unsigned long vram;
+ int ret, bpp;
+
+ if (info->screen_base)
+ return 0;
+
+ /* get color info from register value */
+ ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, NULL);
+ if (ret) {
+ printk(KERN_ERR "colinfo\n");
+ return ret;
+ }
+
+ /* min VRAM: xres_min = 16, yres_min = 1, bpp = 1: 2byte -> 1 page
+ max VRAM: xres_max = 1024, yres_max = 1024, bpp = 16: 2MB */
+
+ vram = info->var.xres * info->var.yres;
+ if (info->var.grayscale) {
+ if (bpp == 1)
+ vram >>= 3;
+ else if (bpp == 2)
+ vram >>= 2;
+ else if (bpp == 4)
+ vram >>= 1;
+ } else if (bpp > 8)
+ vram *= 2;
+ if ((vram < 1) || (vram > 1024 * 2048)) {
+ dev_dbg(info->dev, "too much VRAM required. Check settings\n");
+ return -ENODEV;
+ }
+
+ if (vram < PAGE_SIZE)
+ vram = PAGE_SIZE;
+
+ fbmem = dma_alloc_coherent(info->dev, vram, &par->fbdma, GFP_KERNEL);
+
+ if (!fbmem)
+ return -ENOMEM;
+
+ if ((par->fbdma & SH7760FB_DMA_MASK) != SH7760FB_DMA_MASK) {
+ sh7760fb_free_mem(info);
+ dev_err(info->dev, "kernel gave me memory at 0x%08lx, which is"
+ "unusable for the LCDC\n", (unsigned long)par->fbdma);
+ return -ENOMEM;
+ }
+
+ info->screen_base = fbmem;
+ info->screen_size = vram;
+
+ return 0;
+}
+
+static int __devinit sh7760fb_probe(struct platform_device *pdev)
+{
+ struct fb_info *info;
+ struct resource *res;
+ struct sh7760fb_par *par;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (unlikely(res == NULL)) {
+ dev_err(&pdev->dev, "invalid resource\n");
+ return -EINVAL;
+ }
+
+ info = framebuffer_alloc(sizeof(struct sh7760fb_par), &pdev->dev);
+ if (!info)
+ return -ENOMEM;
+
+ par = info->par;
+ par->dev = pdev;
+
+ par->pd = pdev->dev.platform_data;
+ if (!par->pd) {
+ dev_dbg(info->dev, "no display setup data!\n");
+ ret = -ENODEV;
+ goto out_fb;
+ }
+
+ par->ioarea = request_mem_region(res->start,
+ (res->end - res->start), pdev->name);
+ if (!par->ioarea) {
+ dev_err(&pdev->dev, "mmio area busy\n");
+ ret = -EBUSY;
+ goto out_fb;
+ }
+
+ par->base = ioremap_nocache(res->start, res->end - res->start + 1);
+ if (!par->base) {
+ dev_err(&pdev->dev, "cannot remap\n");
+ ret = -ENODEV;
+ goto out_res;
+ }
+
+ iowrite16(0, par->base + LDINTR); /* disable vsync irq */
+ par->irq = platform_get_irq(pdev, 0);
+ if (par->irq >= 0) {
+ ret = request_irq(par->irq, sh7760fb_irq, 0,
+ "sh7760-lcdc", &par->vsync);
+ if (ret) {
+ dev_err(&pdev->dev, "cannot grab IRQ\n");
+ par->irq = -ENXIO;
+ } else
+ disable_irq_nosync(par->irq);
+ }
+
+ fb_videomode_to_var(&info->var, par->pd->def_mode);
+
+ ret = sh7760fb_alloc_mem(info);
+ if (ret) {
+ dev_dbg(info->dev, "framebuffer memory allocation failed!\n");
+ goto out_unmap;
+ }
+
+ info->pseudo_palette = par->pseudo_palette;
+
+ /* fixup color register bitpositions. These are fixed by hardware */
+ info->var.red.offset = 11;
+ info->var.red.length = 5;
+ info->var.red.msb_right = 0;
+
+ info->var.green.offset = 5;
+ info->var.green.length = 6;
+ info->var.green.msb_right = 0;
+
+ info->var.blue.offset = 0;
+ info->var.blue.length = 5;
+ info->var.blue.msb_right = 0;
+
+ info->var.transp.offset = 0;
+ info->var.transp.length = 0;
+ info->var.transp.msb_right = 0;
+
+ /* set the DON2 bit now, before cmap allocation, as it will randomize
+ * palette memory.
+ */
+ iowrite16(LDCNTR_DON2, par->base + LDCNTR);
+ info->fbops = &sh7760fb_ops;
+
+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (ret) {
+ dev_dbg(info->dev, "Unable to allocate cmap memory\n");
+ goto out_mem;
+ }
+
+ ret = register_framebuffer(info);
+ if (ret < 0) {
+ dev_dbg(info->dev, "cannot register fb!\n");
+ goto out_cmap;
+ }
+ platform_set_drvdata(pdev, info);
+
+ printk(KERN_INFO "%s: memory at phys 0x%08lx-0x%08lx, size %ld KiB\n",
+ pdev->name,
+ (unsigned long)par->fbdma,
+ (unsigned long)(par->fbdma + info->screen_size - 1),
+ info->screen_size >> 10);
+
+ return 0;
+
+out_cmap:
+ sh7760fb_blank(FB_BLANK_POWERDOWN, info);
+ fb_dealloc_cmap(&info->cmap);
+out_mem:
+ sh7760fb_free_mem(info);
+out_unmap:
+ if (par->irq >= 0)
+ free_irq(par->irq, &par->vsync);
+ iounmap(par->base);
+out_res:
+ release_resource(par->ioarea);
+ kfree(par->ioarea);
+out_fb:
+ framebuffer_release(info);
+ return ret;
+}
+
+static int __devexit sh7760fb_remove(struct platform_device *dev)
+{
+ struct fb_info *info = platform_get_drvdata(dev);
+ struct sh7760fb_par *par = info->par;
+
+ sh7760fb_blank(FB_BLANK_POWERDOWN, info);
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info->cmap);
+ sh7760fb_free_mem(info);
+ if (par->irq >= 0)
+ free_irq(par->irq, par);
+ iounmap(par->base);
+ release_resource(par->ioarea);
+ kfree(par->ioarea);
+ framebuffer_release(info);
+ platform_set_drvdata(dev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver sh7760_lcdc_driver = {
+ .driver = {
+ .name = "sh7760-lcdc",
+ .owner = THIS_MODULE,
+ },
+ .probe = sh7760fb_probe,
+ .remove = __devexit_p(sh7760fb_remove),
+};
+
+static int __init sh7760fb_init(void)
+{
+ return platform_driver_register(&sh7760_lcdc_driver);
+}
+
+static void __exit sh7760fb_exit(void)
+{
+ platform_driver_unregister(&sh7760_lcdc_driver);
+}
+
+module_init(sh7760fb_init);
+module_exit(sh7760fb_exit);
+
+MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss");
+MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
new file mode 100644
index 00000000000..f6ef6cca73c
--- /dev/null
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -0,0 +1,725 @@
+/*
+ * SuperH Mobile LCDC Framebuffer
+ *
+ * Copyright (c) 2008 Magnus Damm
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <asm/sh_mobile_lcdc.h>
+
+#define PALETTE_NR 16
+
+struct sh_mobile_lcdc_priv;
+struct sh_mobile_lcdc_chan {
+ struct sh_mobile_lcdc_priv *lcdc;
+ unsigned long *reg_offs;
+ unsigned long ldmt1r_value;
+ unsigned long enabled; /* ME and SE in LDCNT2R */
+ struct sh_mobile_lcdc_chan_cfg cfg;
+ u32 pseudo_palette[PALETTE_NR];
+ struct fb_info info;
+ dma_addr_t dma_handle;
+};
+
+struct sh_mobile_lcdc_priv {
+ void __iomem *base;
+ struct clk *clk;
+ unsigned long lddckr;
+ struct sh_mobile_lcdc_chan ch[2];
+};
+
+/* shared registers */
+#define _LDDCKR 0x410
+#define _LDDCKSTPR 0x414
+#define _LDINTR 0x468
+#define _LDSR 0x46c
+#define _LDCNT1R 0x470
+#define _LDCNT2R 0x474
+#define _LDDDSR 0x47c
+#define _LDDWD0R 0x800
+#define _LDDRDR 0x840
+#define _LDDWAR 0x900
+#define _LDDRAR 0x904
+
+/* per-channel registers */
+enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
+ LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR };
+
+static unsigned long lcdc_offs_mainlcd[] = {
+ [LDDCKPAT1R] = 0x400,
+ [LDDCKPAT2R] = 0x404,
+ [LDMT1R] = 0x418,
+ [LDMT2R] = 0x41c,
+ [LDMT3R] = 0x420,
+ [LDDFR] = 0x424,
+ [LDSM1R] = 0x428,
+ [LDSA1R] = 0x430,
+ [LDMLSR] = 0x438,
+ [LDHCNR] = 0x448,
+ [LDHSYNR] = 0x44c,
+ [LDVLNR] = 0x450,
+ [LDVSYNR] = 0x454,
+ [LDPMR] = 0x460,
+};
+
+static unsigned long lcdc_offs_sublcd[] = {
+ [LDDCKPAT1R] = 0x408,
+ [LDDCKPAT2R] = 0x40c,
+ [LDMT1R] = 0x600,
+ [LDMT2R] = 0x604,
+ [LDMT3R] = 0x608,
+ [LDDFR] = 0x60c,
+ [LDSM1R] = 0x610,
+ [LDSA1R] = 0x618,
+ [LDMLSR] = 0x620,
+ [LDHCNR] = 0x624,
+ [LDHSYNR] = 0x628,
+ [LDVLNR] = 0x62c,
+ [LDVSYNR] = 0x630,
+ [LDPMR] = 0x63c,
+};
+
+#define START_LCDC 0x00000001
+#define LCDC_RESET 0x00000100
+#define DISPLAY_BEU 0x00000008
+#define LCDC_ENABLE 0x00000001
+
+static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan,
+ int reg_nr, unsigned long data)
+{
+ iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]);
+}
+
+static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan,
+ int reg_nr)
+{
+ return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]);
+}
+
+static void lcdc_write(struct sh_mobile_lcdc_priv *priv,
+ unsigned long reg_offs, unsigned long data)
+{
+ iowrite32(data, priv->base + reg_offs);
+}
+
+static unsigned long lcdc_read(struct sh_mobile_lcdc_priv *priv,
+ unsigned long reg_offs)
+{
+ return ioread32(priv->base + reg_offs);
+}
+
+static void lcdc_wait_bit(struct sh_mobile_lcdc_priv *priv,
+ unsigned long reg_offs,
+ unsigned long mask, unsigned long until)
+{
+ while ((lcdc_read(priv, reg_offs) & mask) != until)
+ cpu_relax();
+}
+
+static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan)
+{
+ return chan->cfg.chan == LCDC_CHAN_SUBLCD;
+}
+
+static void lcdc_sys_write_index(void *handle, unsigned long data)
+{
+ struct sh_mobile_lcdc_chan *ch = handle;
+
+ lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000);
+ lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
+ lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+}
+
+static void lcdc_sys_write_data(void *handle, unsigned long data)
+{
+ struct sh_mobile_lcdc_chan *ch = handle;
+
+ lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000);
+ lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
+ lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+}
+
+static unsigned long lcdc_sys_read_data(void *handle)
+{
+ struct sh_mobile_lcdc_chan *ch = handle;
+
+ lcdc_write(ch->lcdc, _LDDRDR, 0x01000000);
+ lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
+ lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+ udelay(1);
+
+ return lcdc_read(ch->lcdc, _LDDRDR) & 0xffff;
+}
+
+struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
+ lcdc_sys_write_index,
+ lcdc_sys_write_data,
+ lcdc_sys_read_data,
+};
+
+static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
+ int start)
+{
+ unsigned long tmp = lcdc_read(priv, _LDCNT2R);
+ int k;
+
+ /* start or stop the lcdc */
+ if (start)
+ lcdc_write(priv, _LDCNT2R, tmp | START_LCDC);
+ else
+ lcdc_write(priv, _LDCNT2R, tmp & ~START_LCDC);
+
+ /* wait until power is applied/stopped on all channels */
+ for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
+ if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled)
+ while (1) {
+ tmp = lcdc_read_chan(&priv->ch[k], LDPMR) & 3;
+ if (start && tmp == 3)
+ break;
+ if (!start && tmp == 0)
+ break;
+ cpu_relax();
+ }
+
+ if (!start)
+ lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */
+}
+
+static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+{
+ struct sh_mobile_lcdc_chan *ch;
+ struct fb_videomode *lcd_cfg;
+ struct sh_mobile_lcdc_board_cfg *board_cfg;
+ unsigned long tmp;
+ int k, m;
+ int ret = 0;
+
+ /* reset */
+ lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET);
+ lcdc_wait_bit(priv, _LDCNT2R, LCDC_RESET, 0);
+
+ /* enable LCDC channels */
+ tmp = lcdc_read(priv, _LDCNT2R);
+ tmp |= priv->ch[0].enabled;
+ tmp |= priv->ch[1].enabled;
+ lcdc_write(priv, _LDCNT2R, tmp);
+
+ /* read data from external memory, avoid using the BEU for now */
+ lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) & ~DISPLAY_BEU);
+
+ /* stop the lcdc first */
+ sh_mobile_lcdc_start_stop(priv, 0);
+
+ /* configure clocks */
+ tmp = priv->lddckr;
+ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+ ch = &priv->ch[k];
+
+ if (!priv->ch[k].enabled)
+ continue;
+
+ m = ch->cfg.clock_divider;
+ if (!m)
+ continue;
+
+ if (m == 1)
+ m = 1 << 6;
+ tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
+
+ lcdc_write_chan(ch, LDDCKPAT1R, 0x00000000);
+ lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
+ }
+
+ lcdc_write(priv, _LDDCKR, tmp);
+
+ /* start dotclock again */
+ lcdc_write(priv, _LDDCKSTPR, 0);
+ lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0);
+
+ /* interrupts are disabled */
+ lcdc_write(priv, _LDINTR, 0);
+
+ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+ ch = &priv->ch[k];
+ lcd_cfg = &ch->cfg.lcd_cfg;
+
+ if (!ch->enabled)
+ continue;
+
+ tmp = ch->ldmt1r_value;
+ tmp |= (lcd_cfg->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
+ tmp |= (lcd_cfg->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
+ lcdc_write_chan(ch, LDMT1R, tmp);
+
+ /* setup SYS bus */
+ lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r);
+ lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
+
+ /* horizontal configuration */
+ tmp = lcd_cfg->xres + lcd_cfg->hsync_len;
+ tmp += lcd_cfg->left_margin;
+ tmp += lcd_cfg->right_margin;
+ tmp /= 8; /* HTCN */
+ tmp |= (lcd_cfg->xres / 8) << 16; /* HDCN */
+ lcdc_write_chan(ch, LDHCNR, tmp);
+
+ tmp = lcd_cfg->xres;
+ tmp += lcd_cfg->right_margin;
+ tmp /= 8; /* HSYNP */
+ tmp |= (lcd_cfg->hsync_len / 8) << 16; /* HSYNW */
+ lcdc_write_chan(ch, LDHSYNR, tmp);
+
+ /* power supply */
+ lcdc_write_chan(ch, LDPMR, 0);
+
+ /* vertical configuration */
+ tmp = lcd_cfg->yres + lcd_cfg->vsync_len;
+ tmp += lcd_cfg->upper_margin;
+ tmp += lcd_cfg->lower_margin; /* VTLN */
+ tmp |= lcd_cfg->yres << 16; /* VDLN */
+ lcdc_write_chan(ch, LDVLNR, tmp);
+
+ tmp = lcd_cfg->yres;
+ tmp += lcd_cfg->lower_margin; /* VSYNP */
+ tmp |= lcd_cfg->vsync_len << 16; /* VSYNW */
+ lcdc_write_chan(ch, LDVSYNR, tmp);
+
+ board_cfg = &ch->cfg.board_cfg;
+ if (board_cfg->setup_sys)
+ ret = board_cfg->setup_sys(board_cfg->board_data, ch,
+ &sh_mobile_lcdc_sys_bus_ops);
+ if (ret)
+ return ret;
+ }
+
+ /* --- display_lcdc_data() --- */
+ lcdc_write(priv, _LDINTR, 0x00000f00);
+
+ /* word and long word swap */
+ lcdc_write(priv, _LDDDSR, lcdc_read(priv, _LDDDSR) | 6);
+
+ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+ ch = &priv->ch[k];
+
+ if (!priv->ch[k].enabled)
+ continue;
+
+ /* set bpp format in PKF[4:0] */
+ tmp = lcdc_read_chan(ch, LDDFR);
+ tmp &= ~(0x0001001f);
+ tmp |= (priv->ch[k].info.var.bits_per_pixel == 16) ? 3 : 0;
+ lcdc_write_chan(ch, LDDFR, tmp);
+
+ /* point out our frame buffer */
+ lcdc_write_chan(ch, LDSA1R, ch->info.fix.smem_start);
+
+ /* set line size */
+ lcdc_write_chan(ch, LDMLSR, ch->info.fix.line_length);
+
+ /* continuous read mode */
+ lcdc_write_chan(ch, LDSM1R, 0);
+ }
+
+ /* display output */
+ lcdc_write(priv, _LDCNT1R, LCDC_ENABLE);
+
+ /* start the lcdc */
+ sh_mobile_lcdc_start_stop(priv, 1);
+
+ /* tell the board code to enable the panel */
+ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+ ch = &priv->ch[k];
+ board_cfg = &ch->cfg.board_cfg;
+ if (board_cfg->display_on)
+ board_cfg->display_on(board_cfg->board_data);
+ }
+
+ return 0;
+}
+
+static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
+{
+ struct sh_mobile_lcdc_chan *ch;
+ struct sh_mobile_lcdc_board_cfg *board_cfg;
+ int k;
+
+ /* tell the board code to disable the panel */
+ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+ ch = &priv->ch[k];
+ board_cfg = &ch->cfg.board_cfg;
+ if (board_cfg->display_off)
+ board_cfg->display_off(board_cfg->board_data);
+ }
+
+ /* stop the lcdc */
+ sh_mobile_lcdc_start_stop(priv, 0);
+}
+
+static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
+{
+ int ifm, miftyp;
+
+ switch (ch->cfg.interface_type) {
+ case RGB8: ifm = 0; miftyp = 0; break;
+ case RGB9: ifm = 0; miftyp = 4; break;
+ case RGB12A: ifm = 0; miftyp = 5; break;
+ case RGB12B: ifm = 0; miftyp = 6; break;
+ case RGB16: ifm = 0; miftyp = 7; break;
+ case RGB18: ifm = 0; miftyp = 10; break;
+ case RGB24: ifm = 0; miftyp = 11; break;
+ case SYS8A: ifm = 1; miftyp = 0; break;
+ case SYS8B: ifm = 1; miftyp = 1; break;
+ case SYS8C: ifm = 1; miftyp = 2; break;
+ case SYS8D: ifm = 1; miftyp = 3; break;
+ case SYS9: ifm = 1; miftyp = 4; break;
+ case SYS12: ifm = 1; miftyp = 5; break;
+ case SYS16A: ifm = 1; miftyp = 7; break;
+ case SYS16B: ifm = 1; miftyp = 8; break;
+ case SYS16C: ifm = 1; miftyp = 9; break;
+ case SYS18: ifm = 1; miftyp = 10; break;
+ case SYS24: ifm = 1; miftyp = 11; break;
+ default: goto bad;
+ }
+
+ /* SUBLCD only supports SYS interface */
+ if (lcdc_chan_is_sublcd(ch)) {
+ if (ifm == 0)
+ goto bad;
+ else
+ ifm = 0;
+ }
+
+ ch->ldmt1r_value = (ifm << 12) | miftyp;
+ return 0;
+ bad:
+ return -EINVAL;
+}
+
+static int sh_mobile_lcdc_setup_clocks(struct device *dev, int clock_source,
+ struct sh_mobile_lcdc_priv *priv)
+{
+ char *str;
+ int icksel;
+
+ switch (clock_source) {
+ case LCDC_CLK_BUS: str = "bus_clk"; icksel = 0; break;
+ case LCDC_CLK_PERIPHERAL: str = "peripheral_clk"; icksel = 1; break;
+ case LCDC_CLK_EXTERNAL: str = NULL; icksel = 2; break;
+ default:
+ return -EINVAL;
+ }
+
+ priv->lddckr = icksel << 16;
+
+ if (str) {
+ priv->clk = clk_get(dev, str);
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "cannot get clock %s\n", str);
+ return PTR_ERR(priv->clk);
+ }
+
+ clk_enable(priv->clk);
+ }
+
+ return 0;
+}
+
+static int sh_mobile_lcdc_setcolreg(u_int regno,
+ u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
+{
+ u32 *palette = info->pseudo_palette;
+
+ if (regno >= PALETTE_NR)
+ return -EINVAL;
+
+ /* only FB_VISUAL_TRUECOLOR supported */
+
+ red >>= 16 - info->var.red.length;
+ green >>= 16 - info->var.green.length;
+ blue >>= 16 - info->var.blue.length;
+ transp >>= 16 - info->var.transp.length;
+
+ palette[regno] = (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset) |
+ (transp << info->var.transp.offset);
+
+ return 0;
+}
+
+static struct fb_fix_screeninfo sh_mobile_lcdc_fix = {
+ .id = "SH Mobile LCDC",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .accel = FB_ACCEL_NONE,
+};
+
+static struct fb_ops sh_mobile_lcdc_ops = {
+ .fb_setcolreg = sh_mobile_lcdc_setcolreg,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp)
+{
+ switch (bpp) {
+ case 16: /* PKF[4:0] = 00011 - RGB 565 */
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+
+ case 32: /* PKF[4:0] = 00000 - RGB 888
+ * sh7722 pdf says 00RRGGBB but reality is GGBB00RR
+ * this may be because LDDDSR has word swap enabled..
+ */
+ var->red.offset = 0;
+ var->red.length = 8;
+ var->green.offset = 24;
+ var->green.length = 8;
+ var->blue.offset = 16;
+ var->blue.length = 8;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ var->bits_per_pixel = bpp;
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
+ var->transp.msb_right = 0;
+ return 0;
+}
+
+static int sh_mobile_lcdc_remove(struct platform_device *pdev);
+
+static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
+{
+ struct fb_info *info;
+ struct sh_mobile_lcdc_priv *priv;
+ struct sh_mobile_lcdc_info *pdata;
+ struct sh_mobile_lcdc_chan_cfg *cfg;
+ struct resource *res;
+ int error;
+ void *buf;
+ int i, j;
+
+ if (!pdev->dev.platform_data) {
+ dev_err(&pdev->dev, "no platform data defined\n");
+ error = -EINVAL;
+ goto err0;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "cannot find IO resource\n");
+ error = -ENOENT;
+ goto err0;
+ }
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(&pdev->dev, "cannot allocate device data\n");
+ error = -ENOMEM;
+ goto err0;
+ }
+
+ platform_set_drvdata(pdev, priv);
+ pdata = pdev->dev.platform_data;
+
+ j = 0;
+ for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) {
+ priv->ch[j].lcdc = priv;
+ memcpy(&priv->ch[j].cfg, &pdata->ch[i], sizeof(pdata->ch[i]));
+
+ error = sh_mobile_lcdc_check_interface(&priv->ch[i]);
+ if (error) {
+ dev_err(&pdev->dev, "unsupported interface type\n");
+ goto err1;
+ }
+
+ switch (pdata->ch[i].chan) {
+ case LCDC_CHAN_MAINLCD:
+ priv->ch[j].enabled = 1 << 1;
+ priv->ch[j].reg_offs = lcdc_offs_mainlcd;
+ j++;
+ break;
+ case LCDC_CHAN_SUBLCD:
+ priv->ch[j].enabled = 1 << 2;
+ priv->ch[j].reg_offs = lcdc_offs_sublcd;
+ j++;
+ break;
+ }
+ }
+
+ if (!j) {
+ dev_err(&pdev->dev, "no channels defined\n");
+ error = -EINVAL;
+ goto err1;
+ }
+
+ error = sh_mobile_lcdc_setup_clocks(&pdev->dev,
+ pdata->clock_source, priv);
+ if (error) {
+ dev_err(&pdev->dev, "unable to setup clocks\n");
+ goto err1;
+ }
+
+ priv->lddckr = pdata->lddckr;
+ priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1);
+
+ for (i = 0; i < j; i++) {
+ info = &priv->ch[i].info;
+ cfg = &priv->ch[i].cfg;
+
+ info->fbops = &sh_mobile_lcdc_ops;
+ info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres;
+ info->var.yres = info->var.yres_virtual = cfg->lcd_cfg.yres;
+ info->var.activate = FB_ACTIVATE_NOW;
+ error = sh_mobile_lcdc_set_bpp(&info->var, cfg->bpp);
+ if (error)
+ break;
+
+ info->fix = sh_mobile_lcdc_fix;
+ info->fix.line_length = cfg->lcd_cfg.xres * (cfg->bpp / 8);
+ info->fix.smem_len = info->fix.line_length * cfg->lcd_cfg.yres;
+
+ buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
+ &priv->ch[i].dma_handle, GFP_KERNEL);
+ if (!buf) {
+ dev_err(&pdev->dev, "unable to allocate buffer\n");
+ error = -ENOMEM;
+ break;
+ }
+
+ info->pseudo_palette = &priv->ch[i].pseudo_palette;
+ info->flags = FBINFO_FLAG_DEFAULT;
+
+ error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
+ if (error < 0) {
+ dev_err(&pdev->dev, "unable to allocate cmap\n");
+ dma_free_coherent(&pdev->dev, info->fix.smem_len,
+ buf, priv->ch[i].dma_handle);
+ break;
+ }
+
+ memset(buf, 0, info->fix.smem_len);
+ info->fix.smem_start = priv->ch[i].dma_handle;
+ info->screen_base = buf;
+ info->device = &pdev->dev;
+ }
+
+ if (error)
+ goto err1;
+
+ error = sh_mobile_lcdc_start(priv);
+ if (error) {
+ dev_err(&pdev->dev, "unable to start hardware\n");
+ goto err1;
+ }
+
+ for (i = 0; i < j; i++) {
+ error = register_framebuffer(&priv->ch[i].info);
+ if (error < 0)
+ goto err1;
+ }
+
+ for (i = 0; i < j; i++) {
+ info = &priv->ch[i].info;
+ dev_info(info->dev,
+ "registered %s/%s as %dx%d %dbpp.\n",
+ pdev->name,
+ (priv->ch[i].cfg.chan == LCDC_CHAN_MAINLCD) ?
+ "mainlcd" : "sublcd",
+ (int) priv->ch[i].cfg.lcd_cfg.xres,
+ (int) priv->ch[i].cfg.lcd_cfg.yres,
+ priv->ch[i].cfg.bpp);
+ }
+
+ return 0;
+ err1:
+ sh_mobile_lcdc_remove(pdev);
+ err0:
+ return error;
+}
+
+static int sh_mobile_lcdc_remove(struct platform_device *pdev)
+{
+ struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
+ struct fb_info *info;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
+ if (priv->ch[i].info.dev)
+ unregister_framebuffer(&priv->ch[i].info);
+
+ sh_mobile_lcdc_stop(priv);
+
+ for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
+ info = &priv->ch[i].info;
+
+ if (!info->device)
+ continue;
+
+ dma_free_coherent(&pdev->dev, info->fix.smem_len,
+ info->screen_base, priv->ch[i].dma_handle);
+ fb_dealloc_cmap(&info->cmap);
+ }
+
+ if (priv->clk) {
+ clk_disable(priv->clk);
+ clk_put(priv->clk);
+ }
+
+ if (priv->base)
+ iounmap(priv->base);
+
+ kfree(priv);
+ return 0;
+}
+
+static struct platform_driver sh_mobile_lcdc_driver = {
+ .driver = {
+ .name = "sh_mobile_lcdc_fb",
+ .owner = THIS_MODULE,
+ },
+ .probe = sh_mobile_lcdc_probe,
+ .remove = sh_mobile_lcdc_remove,
+};
+
+static int __init sh_mobile_lcdc_init(void)
+{
+ return platform_driver_register(&sh_mobile_lcdc_driver);
+}
+
+static void __exit sh_mobile_lcdc_exit(void)
+{
+ platform_driver_unregister(&sh_mobile_lcdc_driver);
+}
+
+module_init(sh_mobile_lcdc_init);
+module_exit(sh_mobile_lcdc_exit);
+
+MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
+MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sis/init.h b/drivers/video/sis/init.h
index f40a680df86..b96005c39c6 100644
--- a/drivers/video/sis/init.h
+++ b/drivers/video/sis/init.h
@@ -73,7 +73,6 @@
#ifdef SIS_CP
#undef SIS_CP
#endif
-#include <linux/version.h>
#include <linux/types.h>
#include <asm/io.h>
#include <linux/fb.h>
diff --git a/drivers/video/sis/init301.h b/drivers/video/sis/init301.h
index 7708e1e1d99..51d99222375 100644
--- a/drivers/video/sis/init301.h
+++ b/drivers/video/sis/init301.h
@@ -67,7 +67,6 @@
#ifdef SIS_CP
#undef SIS_CP
#endif
-#include <linux/version.h>
#include <linux/types.h>
#include <asm/io.h>
#include <linux/fb.h>
diff --git a/drivers/video/sis/initextlfb.c b/drivers/video/sis/initextlfb.c
index 47a33501549..99c04a4855d 100644
--- a/drivers/video/sis/initextlfb.c
+++ b/drivers/video/sis/initextlfb.c
@@ -30,7 +30,6 @@
#include "vgatypes.h"
#include "vstruct.h"
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/fb.h>
diff --git a/drivers/video/sis/osdef.h b/drivers/video/sis/osdef.h
index c1492782cb1..6ff8f988a1a 100644
--- a/drivers/video/sis/osdef.h
+++ b/drivers/video/sis/osdef.h
@@ -87,7 +87,6 @@
/**********************************************************************/
#ifdef SIS_LINUX_KERNEL
-#include <linux/version.h>
#ifdef CONFIG_FB_SIS_300
#define SIS300
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
index a14e8221103..7c5710e3fb5 100644
--- a/drivers/video/sis/sis.h
+++ b/drivers/video/sis/sis.h
@@ -24,8 +24,6 @@
#ifndef _SIS_H_
#define _SIS_H_
-#include <linux/version.h>
-
#include "osdef.h"
#include <video/sisfb.h>
@@ -42,16 +40,6 @@
#define SIS_NEW_CONFIG_COMPAT
#endif /* CONFIG_COMPAT */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
-#define SIS_IOTYPE1 void __iomem
-#define SIS_IOTYPE2 __iomem
-#define SISINITSTATIC static
-#else
-#define SIS_IOTYPE1 unsigned char
-#define SIS_IOTYPE2
-#define SISINITSTATIC
-#endif
-
#undef SISFBDEBUG
#ifdef SISFBDEBUG
@@ -505,8 +493,8 @@ struct sis_video_info {
unsigned long UMAsize, LFBsize;
- SIS_IOTYPE1 *video_vbase;
- SIS_IOTYPE1 *mmio_vbase;
+ void __iomem *video_vbase;
+ void __iomem *mmio_vbase;
unsigned char *bios_abase;
@@ -533,8 +521,8 @@ struct sis_video_info {
int sisfb_nocrt2rate;
u32 heapstart; /* offset */
- SIS_IOTYPE1 *sisfb_heap_start; /* address */
- SIS_IOTYPE1 *sisfb_heap_end; /* address */
+ void __iomem *sisfb_heap_start; /* address */
+ void __iomem *sisfb_heap_end; /* address */
u32 sisfb_heap_size;
int havenoheap;
@@ -612,7 +600,7 @@ struct sis_video_info {
u8 detectedpdca;
u8 detectedlcda;
- SIS_IOTYPE1 *hwcursor_vbase;
+ void __iomem *hwcursor_vbase;
int chronteltype;
int tvxpos, tvypos;
diff --git a/drivers/video/sis/sis_accel.c b/drivers/video/sis/sis_accel.c
index 7addf91d2fe..ceb434c95c0 100644
--- a/drivers/video/sis/sis_accel.c
+++ b/drivers/video/sis/sis_accel.c
@@ -28,7 +28,6 @@
* for more information and updates)
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fb.h>
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index b9343844cd1..346d6458cf7 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -33,7 +33,6 @@
*
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -41,13 +40,7 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
-#include <linux/tty.h>
-#else
#include <linux/screen_info.h>
-#endif
-
#include <linux/slab.h>
#include <linux/fb.h>
#include <linux/selection.h>
@@ -1167,11 +1160,7 @@ sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
unsigned short modeno = ivideo->mode_no;
/* >=2.6.12's fbcon clears the screen anyway */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
- if(!clrscrn) modeno |= 0x80;
-#else
modeno |= 0x80;
-#endif
outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
@@ -1436,11 +1425,8 @@ sisfb_set_par(struct fb_info *info)
if((err = sisfb_do_set_var(&info->var, 1, info)))
return err;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
- sisfb_get_fix(&info->fix, info->currcon, info);
-#else
sisfb_get_fix(&info->fix, -1, info);
-#endif
+
return 0;
}
@@ -1676,14 +1662,8 @@ sisfb_blank(int blank, struct fb_info *info)
/* ----------- FBDev related routines for all series ---------- */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
-#else
-static int sisfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- struct fb_info *info)
-#endif
{
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
struct sis_memreq sismemreq;
@@ -3986,8 +3966,7 @@ sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_comm
}
#ifndef MODULE
-SISINITSTATIC int __init
-sisfb_setup(char *options)
+static int __init sisfb_setup(char *options)
{
char *this_opt;
@@ -4086,9 +4065,9 @@ sisfb_setup(char *options)
#endif
static int __devinit
-sisfb_check_rom(SIS_IOTYPE1 *rom_base, struct sis_video_info *ivideo)
+sisfb_check_rom(void __iomem *rom_base, struct sis_video_info *ivideo)
{
- SIS_IOTYPE1 *rom;
+ void __iomem *rom;
int romptr;
if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
@@ -4117,10 +4096,9 @@ static unsigned char * __devinit
sisfb_find_rom(struct pci_dev *pdev)
{
struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- SIS_IOTYPE1 *rom_base;
+ void __iomem *rom_base;
unsigned char *myrombase = NULL;
u32 temp;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
size_t romsize;
/* First, try the official pci ROM functions (except
@@ -4151,7 +4129,6 @@ sisfb_find_rom(struct pci_dev *pdev)
}
if(myrombase) return myrombase;
-#endif
/* Otherwise do it the conventional way. */
@@ -4225,7 +4202,7 @@ sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
static int __devinit
sisfb_post_300_buswidth(struct sis_video_info *ivideo)
{
- SIS_IOTYPE1 *FBAddress = ivideo->video_vbase;
+ void __iomem *FBAddress = ivideo->video_vbase;
unsigned short temp;
unsigned char reg;
int i, j;
@@ -4273,7 +4250,7 @@ sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth
int PseudoRankCapacity, int PseudoAdrPinCount,
unsigned int mapsize)
{
- SIS_IOTYPE1 *FBAddr = ivideo->video_vbase;
+ void __iomem *FBAddr = ivideo->video_vbase;
unsigned short sr14;
unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
@@ -5829,7 +5806,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ivideo->engineok = 0;
ivideo->sisfb_was_boot_device = 0;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
+
if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
if(ivideo->sisvga_enabled)
ivideo->sisfb_was_boot_device = 1;
@@ -5840,7 +5817,6 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
"as the primary VGA device\n");
}
}
-#endif
ivideo->sisfb_parm_mem = sisfb_parm_mem;
ivideo->sisfb_accel = sisfb_accel;
@@ -6010,7 +5986,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ivideo->modeprechange = reg & 0x7f;
} else if(ivideo->sisvga_enabled) {
#if defined(__i386__) || defined(__x86_64__)
- unsigned char SIS_IOTYPE2 *tt = ioremap(0x400, 0x100);
+ unsigned char __iomem *tt = ioremap(0x400, 0x100);
if(tt) {
ivideo->modeprechange = readb(tt + 0x49);
iounmap(tt);
@@ -6503,7 +6479,7 @@ static struct pci_driver sisfb_driver = {
.remove = __devexit_p(sisfb_remove)
};
-SISINITSTATIC int __init sisfb_init(void)
+static int __init sisfb_init(void)
{
#ifndef MODULE
char *options = NULL;
diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h
index 3e3b7fa05d6..9540e977270 100644
--- a/drivers/video/sis/sis_main.h
+++ b/drivers/video/sis/sis_main.h
@@ -665,11 +665,11 @@ static struct _customttable {
/* Interface used by the world */
#ifndef MODULE
-SISINITSTATIC int sisfb_setup(char *options);
+static int sisfb_setup(char *options);
#endif
/* Interface to the low level console driver */
-SISINITSTATIC int sisfb_init(void);
+static int sisfb_init(void);
/* fbdev routines */
static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
diff --git a/drivers/video/sis/vgatypes.h b/drivers/video/sis/vgatypes.h
index b532fbd2b04..81a22eaabfd 100644
--- a/drivers/video/sis/vgatypes.h
+++ b/drivers/video/sis/vgatypes.h
@@ -53,10 +53,6 @@
#ifndef _VGATYPES_H_
#define _VGATYPES_H_
-#ifdef SIS_LINUX_KERNEL
-#include <linux/version.h>
-#endif
-
#define SISIOMEMTYPE
#ifdef SIS_LINUX_KERNEL
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index 62321458f71..df5336561d1 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -675,13 +675,13 @@ static struct fb_ops xxxfb_ops = {
* Initialization
*/
-/* static int __init xxfb_probe (struct device *device) -- for platform devs */
+/* static int __init xxfb_probe (struct platform_device *pdev) -- for platform devs */
static int __devinit xxxfb_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
struct fb_info *info;
struct xxx_par *par;
- struct device* device = &dev->dev; /* for pci drivers */
+ struct device *device = &dev->dev; /* or &pdev->dev */
int cmap_len, retval;
/*
@@ -824,18 +824,18 @@ static int __devinit xxxfb_probe(struct pci_dev *dev,
return -EINVAL;
printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
info->fix.id);
- pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */
+ pci_set_drvdata(dev, info); /* or platform_set_drvdata(pdev, info) */
return 0;
}
/*
* Cleanup
*/
-/* static void __devexit xxxfb_remove(struct device *device) */
+/* static void __devexit xxxfb_remove(struct platform_device *pdev) */
static void __devexit xxxfb_remove(struct pci_dev *dev)
{
struct fb_info *info = pci_get_drvdata(dev);
- /* or dev_get_drvdata(device); */
+ /* or platform_get_drvdata(pdev); */
if (info) {
unregister_framebuffer(info);
@@ -961,18 +961,17 @@ static int xxxfb_resume(struct platform_dev *dev)
#define xxxfb_resume NULL
#endif /* CONFIG_PM */
-static struct device_driver xxxfb_driver = {
- .name = "xxxfb",
- .bus = &platform_bus_type,
+static struct platform_device_driver xxxfb_driver = {
.probe = xxxfb_probe,
.remove = xxxfb_remove,
.suspend = xxxfb_suspend, /* optional but recommended */
.resume = xxxfb_resume, /* optional but recommended */
+ .driver = {
+ .name = "xxxfb",
+ },
};
-static struct platform_device xxxfb_device = {
- .name = "xxxfb",
-};
+static struct platform_device *xxxfb_device;
#ifndef MODULE
/*
@@ -1002,12 +1001,16 @@ static int __init xxxfb_init(void)
return -ENODEV;
xxxfb_setup(option);
#endif
- ret = driver_register(&xxxfb_driver);
+ ret = platform_driver_register(&xxxfb_driver);
if (!ret) {
- ret = platform_device_register(&xxxfb_device);
- if (ret)
- driver_unregister(&xxxfb_driver);
+ xxxfb_device = platform_device_register_simple("xxxfb", 0,
+ NULL, 0);
+
+ if (IS_ERR(xxxfb_device)) {
+ platform_driver_unregister(&xxxfb_driver);
+ ret = PTR_ERR(xxxfb_device);
+ }
}
return ret;
@@ -1015,8 +1018,8 @@ static int __init xxxfb_init(void)
static void __exit xxxfb_exit(void)
{
- platform_device_unregister(&xxxfb_device);
- driver_unregister(&xxxfb_driver);
+ platform_device_unregister(xxxfb_device);
+ platform_driver_unregister(&xxxfb_driver);
}
#endif /* CONFIG_PCI */
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index 15d4a768b1f..f94ae84a58c 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -48,10 +48,15 @@ enum sm501_controller {
HEAD_PANEL = 1,
};
-/* SM501 memory address */
+/* SM501 memory address.
+ *
+ * This structure is used to track memory usage within the SM501 framebuffer
+ * allocation. The sm_addr field is stored as an offset as it is often used
+ * against both the physical and mapped addresses.
+ */
struct sm501_mem {
unsigned long size;
- unsigned long sm_addr;
+ unsigned long sm_addr; /* offset from base of sm501 fb. */
void __iomem *k_addr;
};
@@ -142,31 +147,68 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info)
static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
unsigned int why, size_t size)
{
- unsigned int ptr = 0;
+ struct sm501fb_par *par;
+ struct fb_info *fbi;
+ unsigned int ptr;
+ unsigned int end;
switch (why) {
case SM501_MEMF_CURSOR:
ptr = inf->fbmem_len - size;
- inf->fbmem_len = ptr;
+ inf->fbmem_len = ptr; /* adjust available memory. */
break;
case SM501_MEMF_PANEL:
ptr = inf->fbmem_len - size;
- if (ptr < inf->fb[0]->fix.smem_len)
+ fbi = inf->fb[HEAD_CRT];
+
+ /* round down, some programs such as directfb do not draw
+ * 0,0 correctly unless the start is aligned to a page start.
+ */
+
+ if (ptr > 0)
+ ptr &= ~(PAGE_SIZE - 1);
+
+ if (fbi && ptr < fbi->fix.smem_len)
+ return -ENOMEM;
+
+ if (ptr < 0)
return -ENOMEM;
break;
case SM501_MEMF_CRT:
ptr = 0;
+
+ /* check to see if we have panel memory allocated
+ * which would put an limit on available memory. */
+
+ fbi = inf->fb[HEAD_PANEL];
+ if (fbi) {
+ par = fbi->par;
+ end = par->screen.k_addr ? par->screen.sm_addr : inf->fbmem_len;
+ } else
+ end = inf->fbmem_len;
+
+ if ((ptr + size) > end)
+ return -ENOMEM;
+
break;
case SM501_MEMF_ACCEL:
- ptr = inf->fb[0]->fix.smem_len;
+ fbi = inf->fb[HEAD_CRT];
+ ptr = fbi ? fbi->fix.smem_len : 0;
+
+ fbi = inf->fb[HEAD_PANEL];
+ if (fbi) {
+ par = fbi->par;
+ end = par->screen.sm_addr;
+ } else
+ end = inf->fbmem_len;
- if ((ptr + size) >
- (inf->fb[1]->fix.smem_start - inf->fbmem_res->start))
+ if ((ptr + size) > end)
return -ENOMEM;
+
break;
default:
@@ -663,15 +705,25 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
sm501fb_sync_regs(fbi);
mdelay(10);
+ /* VBIASEN */
+
if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
- control |= SM501_DC_PANEL_CONTROL_BIAS; /* VBIASEN */
+ if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN)
+ control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+ else
+ control |= SM501_DC_PANEL_CONTROL_BIAS;
+
writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
- control |= SM501_DC_PANEL_CONTROL_FPEN;
+ if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN)
+ control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+ else
+ control |= SM501_DC_PANEL_CONTROL_FPEN;
+
writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
@@ -679,14 +731,22 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
} else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) {
/* disable panel power */
if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
- control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+ if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN)
+ control |= SM501_DC_PANEL_CONTROL_FPEN;
+ else
+ control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+
writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
- control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+ if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN)
+ control |= SM501_DC_PANEL_CONTROL_BIAS;
+ else
+ control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+
writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
@@ -1210,39 +1270,6 @@ static struct fb_ops sm501fb_ops_pnl = {
.fb_imageblit = cfb_imageblit,
};
-/* sm501fb_info_alloc
- *
- * creates and initialises an sm501fb_info structure
-*/
-
-static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt,
- struct fb_info *fbinfo_pnl)
-{
- struct sm501fb_info *info;
- struct sm501fb_par *par;
-
- info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
- if (info) {
- /* set the references back */
-
- par = fbinfo_crt->par;
- par->info = info;
- par->head = HEAD_CRT;
- fbinfo_crt->pseudo_palette = &par->pseudo_palette;
-
- par = fbinfo_pnl->par;
- par->info = info;
- par->head = HEAD_PANEL;
- fbinfo_pnl->pseudo_palette = &par->pseudo_palette;
-
- /* store the two fbs into our info */
- info->fb[HEAD_CRT] = fbinfo_crt;
- info->fb[HEAD_PANEL] = fbinfo_pnl;
- }
-
- return info;
-}
-
/* sm501_init_cursor
*
* initialise hw cursor parameters
@@ -1250,10 +1277,16 @@ static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt,
static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
{
- struct sm501fb_par *par = fbi->par;
- struct sm501fb_info *info = par->info;
+ struct sm501fb_par *par;
+ struct sm501fb_info *info;
int ret;
+ if (fbi == NULL)
+ return 0;
+
+ par = fbi->par;
+ info = par->info;
+
par->cursor_regs = info->regs + reg_base;
ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024);
@@ -1281,13 +1314,10 @@ static int sm501fb_start(struct sm501fb_info *info,
struct platform_device *pdev)
{
struct resource *res;
- struct device *dev;
+ struct device *dev = &pdev->dev;
int k;
int ret;
- info->dev = dev = &pdev->dev;
- platform_set_drvdata(pdev, info);
-
info->irq = ret = platform_get_irq(pdev, 0);
if (ret < 0) {
/* we currently do not use the IRQ */
@@ -1390,11 +1420,6 @@ static void sm501fb_stop(struct sm501fb_info *info)
kfree(info->regs_res);
}
-static void sm501fb_info_release(struct sm501fb_info *info)
-{
- kfree(info);
-}
-
static int sm501fb_init_fb(struct fb_info *fb,
enum sm501_controller head,
const char *fbname)
@@ -1539,36 +1564,93 @@ static struct sm501_platdata_fb sm501fb_def_pdata = {
static char driver_name_crt[] = "sm501fb-crt";
static char driver_name_pnl[] = "sm501fb-panel";
-static int __init sm501fb_probe(struct platform_device *pdev)
+static int __devinit sm501fb_probe_one(struct sm501fb_info *info,
+ enum sm501_controller head)
{
- struct sm501fb_info *info;
- struct device *dev = &pdev->dev;
- struct fb_info *fbinfo_crt;
- struct fb_info *fbinfo_pnl;
- int ret;
+ unsigned char *name = (head == HEAD_CRT) ? "crt" : "panel";
+ struct sm501_platdata_fbsub *pd;
+ struct sm501fb_par *par;
+ struct fb_info *fbi;
- /* allocate our framebuffers */
+ pd = (head == HEAD_CRT) ? info->pdata->fb_crt : info->pdata->fb_pnl;
+
+ /* Do not initialise if we've not been given any platform data */
+ if (pd == NULL) {
+ dev_info(info->dev, "no data for fb %s (disabled)\n", name);
+ return 0;
+ }
- fbinfo_crt = framebuffer_alloc(sizeof(struct sm501fb_par), dev);
- if (fbinfo_crt == NULL) {
- dev_err(dev, "cannot allocate crt framebuffer\n");
+ fbi = framebuffer_alloc(sizeof(struct sm501fb_par), info->dev);
+ if (fbi == NULL) {
+ dev_err(info->dev, "cannot allocate %s framebuffer\n", name);
return -ENOMEM;
}
- fbinfo_pnl = framebuffer_alloc(sizeof(struct sm501fb_par), dev);
- if (fbinfo_pnl == NULL) {
- dev_err(dev, "cannot allocate panel framebuffer\n");
- ret = -ENOMEM;
- goto fbinfo_crt_alloc_fail;
+ par = fbi->par;
+ par->info = info;
+ par->head = head;
+ fbi->pseudo_palette = &par->pseudo_palette;
+
+ info->fb[head] = fbi;
+
+ return 0;
+}
+
+/* Free up anything allocated by sm501fb_init_fb */
+
+static void sm501_free_init_fb(struct sm501fb_info *info,
+ enum sm501_controller head)
+{
+ struct fb_info *fbi = info->fb[head];
+
+ fb_dealloc_cmap(&fbi->cmap);
+}
+
+static int __devinit sm501fb_start_one(struct sm501fb_info *info,
+ enum sm501_controller head,
+ const char *drvname)
+{
+ struct fb_info *fbi = info->fb[head];
+ int ret;
+
+ if (!fbi)
+ return 0;
+
+ ret = sm501fb_init_fb(info->fb[head], head, drvname);
+ if (ret) {
+ dev_err(info->dev, "cannot initialise fb %s\n", drvname);
+ return ret;
+ }
+
+ ret = register_framebuffer(info->fb[head]);
+ if (ret) {
+ dev_err(info->dev, "failed to register fb %s\n", drvname);
+ sm501_free_init_fb(info, head);
+ return ret;
}
- info = sm501fb_info_alloc(fbinfo_crt, fbinfo_pnl);
- if (info == NULL) {
- dev_err(dev, "cannot allocate par\n");
- ret = -ENOMEM;
- goto sm501fb_alloc_fail;
+ dev_info(info->dev, "fb%d: %s frame buffer\n", fbi->node, fbi->fix.id);
+
+ return 0;
+}
+
+static int __devinit sm501fb_probe(struct platform_device *pdev)
+{
+ struct sm501fb_info *info;
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ /* allocate our framebuffers */
+
+ info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
+ if (!info) {
+ dev_err(dev, "failed to allocate state\n");
+ return -ENOMEM;
}
+ info->dev = dev = &pdev->dev;
+ platform_set_drvdata(pdev, info);
+
if (dev->parent->platform_data) {
struct sm501_platdata *pd = dev->parent->platform_data;
info->pdata = pd->fb;
@@ -1579,90 +1661,88 @@ static int __init sm501fb_probe(struct platform_device *pdev)
info->pdata = &sm501fb_def_pdata;
}
- /* start the framebuffers */
+ /* probe for the presence of each panel */
- ret = sm501fb_start(info, pdev);
- if (ret) {
- dev_err(dev, "cannot initialise SM501\n");
- goto sm501fb_start_fail;
+ ret = sm501fb_probe_one(info, HEAD_CRT);
+ if (ret < 0) {
+ dev_err(dev, "failed to probe CRT\n");
+ goto err_alloc;
}
- /* CRT framebuffer setup */
+ ret = sm501fb_probe_one(info, HEAD_PANEL);
+ if (ret < 0) {
+ dev_err(dev, "failed to probe PANEL\n");
+ goto err_probed_crt;
+ }
- ret = sm501fb_init_fb(fbinfo_crt, HEAD_CRT, driver_name_crt);
- if (ret) {
- dev_err(dev, "cannot initialise CRT fb\n");
- goto sm501fb_start_fail;
+ if (info->fb[HEAD_PANEL] == NULL &&
+ info->fb[HEAD_CRT] == NULL) {
+ dev_err(dev, "no framebuffers found\n");
+ goto err_alloc;
}
- /* Panel framebuffer setup */
+ /* get the resources for both of the framebuffers */
- ret = sm501fb_init_fb(fbinfo_pnl, HEAD_PANEL, driver_name_pnl);
+ ret = sm501fb_start(info, pdev);
if (ret) {
- dev_err(dev, "cannot initialise Panel fb\n");
- goto sm501fb_start_fail;
+ dev_err(dev, "cannot initialise SM501\n");
+ goto err_probed_panel;
}
- /* register framebuffers */
-
- ret = register_framebuffer(fbinfo_crt);
- if (ret < 0) {
- dev_err(dev, "failed to register CRT fb (%d)\n", ret);
- goto register_crt_fail;
+ ret = sm501fb_start_one(info, HEAD_CRT, driver_name_crt);
+ if (ret) {
+ dev_err(dev, "failed to start CRT\n");
+ goto err_started;
}
- ret = register_framebuffer(fbinfo_pnl);
- if (ret < 0) {
- dev_err(dev, "failed to register panel fb (%d)\n", ret);
- goto register_pnl_fail;
+ ret = sm501fb_start_one(info, HEAD_PANEL, driver_name_pnl);
+ if (ret) {
+ dev_err(dev, "failed to start Panel\n");
+ goto err_started_crt;
}
- dev_info(dev, "fb%d: %s frame buffer device\n",
- fbinfo_crt->node, fbinfo_crt->fix.id);
-
- dev_info(dev, "fb%d: %s frame buffer device\n",
- fbinfo_pnl->node, fbinfo_pnl->fix.id);
-
/* create device files */
ret = device_create_file(dev, &dev_attr_crt_src);
if (ret)
- goto crtsrc_fail;
+ goto err_started_panel;
ret = device_create_file(dev, &dev_attr_fbregs_pnl);
if (ret)
- goto fbregs_pnl_fail;
+ goto err_attached_crtsrc_file;
ret = device_create_file(dev, &dev_attr_fbregs_crt);
if (ret)
- goto fbregs_crt_fail;
+ goto err_attached_pnlregs_file;
/* we registered, return ok */
return 0;
- fbregs_crt_fail:
+err_attached_pnlregs_file:
device_remove_file(dev, &dev_attr_fbregs_pnl);
- fbregs_pnl_fail:
+err_attached_crtsrc_file:
device_remove_file(dev, &dev_attr_crt_src);
- crtsrc_fail:
- unregister_framebuffer(fbinfo_pnl);
+err_started_panel:
+ unregister_framebuffer(info->fb[HEAD_PANEL]);
+ sm501_free_init_fb(info, HEAD_PANEL);
- register_pnl_fail:
- unregister_framebuffer(fbinfo_crt);
+err_started_crt:
+ unregister_framebuffer(info->fb[HEAD_CRT]);
+ sm501_free_init_fb(info, HEAD_CRT);
- register_crt_fail:
+err_started:
sm501fb_stop(info);
- sm501fb_start_fail:
- sm501fb_info_release(info);
+err_probed_panel:
+ framebuffer_release(info->fb[HEAD_PANEL]);
- sm501fb_alloc_fail:
- framebuffer_release(fbinfo_pnl);
+err_probed_crt:
+ framebuffer_release(info->fb[HEAD_CRT]);
- fbinfo_crt_alloc_fail:
- framebuffer_release(fbinfo_crt);
+err_alloc:
+ kfree(info);
return ret;
}
@@ -1681,11 +1761,14 @@ static int sm501fb_remove(struct platform_device *pdev)
device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl);
device_remove_file(&pdev->dev, &dev_attr_crt_src);
+ sm501_free_init_fb(info, HEAD_CRT);
+ sm501_free_init_fb(info, HEAD_PANEL);
+
unregister_framebuffer(fbinfo_crt);
unregister_framebuffer(fbinfo_pnl);
sm501fb_stop(info);
- sm501fb_info_release(info);
+ kfree(info);
framebuffer_release(fbinfo_pnl);
framebuffer_release(fbinfo_crt);
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index ea9f19d2559..77aafcfae03 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -836,16 +836,12 @@ static int tdfxfb_pan_display(struct fb_var_screeninfo *var,
struct tdfx_par *par = info->par;
u32 addr = var->yoffset * info->fix.line_length;
- if (nopan || var->xoffset || (var->yoffset > var->yres_virtual))
- return -EINVAL;
- if ((var->yoffset + var->yres > var->yres_virtual && nowrap))
+ if (nopan || var->xoffset)
return -EINVAL;
banshee_make_room(par, 1);
tdfx_outl(par, VIDDESKSTART, addr);
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
return 0;
}
@@ -1426,6 +1422,8 @@ MODULE_LICENSE("GPL");
module_param(hwcursor, int, 0644);
MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
"(1=enable, 0=disable, default=1)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
#ifdef CONFIG_MTRR
module_param(nomtrr, bool, 0);
MODULE_PARM_DESC(nomtrr, "Disable MTRR support (default: enabled)");
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index beefab2992c..479b2e79ad6 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -1,5 +1,5 @@
/*
- * Frame buffer driver for Trident Blade and Image series
+ * Frame buffer driver for Trident TGUI, Blade and Image series
*
* Copyright 2001, 2002 - Jani Monoses <jani@iv.ro>
*
@@ -13,7 +13,6 @@
* code, suggestions
* TODO:
* timing value tweaking so it looks good on every monitor in every mode
- * TGUI acceleration
*/
#include <linux/module.h>
@@ -22,25 +21,26 @@
#include <linux/pci.h>
#include <linux/delay.h>
+#include <video/vga.h>
#include <video/trident.h>
-#define VERSION "0.7.8-NEWAPI"
-
struct tridentfb_par {
void __iomem *io_virt; /* iospace virtual memory address */
+ u32 pseudo_pal[16];
+ int chip_id;
+ int flatpanel;
+ void (*init_accel) (struct tridentfb_par *, int, int);
+ void (*wait_engine) (struct tridentfb_par *);
+ void (*fill_rect)
+ (struct tridentfb_par *par, u32, u32, u32, u32, u32, u32);
+ void (*copy_rect)
+ (struct tridentfb_par *par, u32, u32, u32, u32, u32, u32);
+ void (*image_blit)
+ (struct tridentfb_par *par, const char*,
+ u32, u32, u32, u32, u32, u32);
+ unsigned char eng_oper; /* engine operation... */
};
-static unsigned char eng_oper; /* engine operation... */
-static struct fb_ops tridentfb_ops;
-
-static struct tridentfb_par default_par;
-
-/* FIXME:kmalloc these 3 instead */
-static struct fb_info fb_info;
-static u32 pseudo_pal[16];
-
-static struct fb_var_screeninfo default_var;
-
static struct fb_fix_screeninfo tridentfb_fix = {
.id = "Trident",
.type = FB_TYPE_PACKED_PIXELS,
@@ -49,27 +49,22 @@ static struct fb_fix_screeninfo tridentfb_fix = {
.accel = FB_ACCEL_NONE,
};
-static int chip_id;
-
-static int defaultaccel;
-static int displaytype;
-
/* defaults which are normally overriden by user values */
/* video mode */
-static char *mode_option __devinitdata = "640x480";
-static int bpp = 8;
+static char *mode_option __devinitdata = "640x480-8@60";
+static int bpp __devinitdata = 8;
-static int noaccel;
+static int noaccel __devinitdata;
static int center;
static int stretch;
-static int fp;
-static int crt;
+static int fp __devinitdata;
+static int crt __devinitdata;
-static int memsize;
-static int memdiff;
+static int memsize __devinitdata;
+static int memdiff __devinitdata;
static int nativex;
module_param(mode_option, charp, 0);
@@ -84,25 +79,53 @@ module_param(memsize, int, 0);
module_param(memdiff, int, 0);
module_param(nativex, int, 0);
module_param(fp, int, 0);
+MODULE_PARM_DESC(fp, "Define if flatpanel is connected");
module_param(crt, int, 0);
+MODULE_PARM_DESC(crt, "Define if CRT is connected");
+
+static inline int is_oldclock(int id)
+{
+ return (id == TGUI9440) ||
+ (id == TGUI9660) ||
+ (id == CYBER9320);
+}
+
+static inline int is_oldprotect(int id)
+{
+ return is_oldclock(id) ||
+ (id == PROVIDIA9685) ||
+ (id == CYBER9382) ||
+ (id == CYBER9385);
+}
+
+static inline int is_blade(int id)
+{
+ return (id == BLADE3D) ||
+ (id == CYBERBLADEE4) ||
+ (id == CYBERBLADEi7) ||
+ (id == CYBERBLADEi7D) ||
+ (id == CYBERBLADEi1) ||
+ (id == CYBERBLADEi1D) ||
+ (id == CYBERBLADEAi1) ||
+ (id == CYBERBLADEAi1D);
+}
-static int chip3D;
-static int chipcyber;
+static inline int is_xp(int id)
+{
+ return (id == CYBERBLADEXPAi1) ||
+ (id == CYBERBLADEXPm8) ||
+ (id == CYBERBLADEXPm16);
+}
-static int is3Dchip(int id)
+static inline int is3Dchip(int id)
{
- return ((id == BLADE3D) || (id == CYBERBLADEE4) ||
- (id == CYBERBLADEi7) || (id == CYBERBLADEi7D) ||
+ return is_blade(id) || is_xp(id) ||
(id == CYBER9397) || (id == CYBER9397DVD) ||
(id == CYBER9520) || (id == CYBER9525DVD) ||
- (id == IMAGE975) || (id == IMAGE985) ||
- (id == CYBERBLADEi1) || (id == CYBERBLADEi1D) ||
- (id == CYBERBLADEAi1) || (id == CYBERBLADEAi1D) ||
- (id == CYBERBLADEXPm8) || (id == CYBERBLADEXPm16) ||
- (id == CYBERBLADEXPAi1));
+ (id == IMAGE975) || (id == IMAGE985);
}
-static int iscyber(int id)
+static inline int iscyber(int id)
{
switch (id) {
case CYBER9388:
@@ -122,12 +145,7 @@ static int iscyber(int id)
return 1;
case CYBER9320:
- case TGUI9660:
- case IMAGE975:
- case IMAGE985:
- case BLADE3D:
case CYBERBLADEi7: /* VIA MPV4 integrated version */
-
default:
/* case CYBERBLDAEXPm8: Strange */
/* case CYBERBLDAEXPm16: Strange */
@@ -135,147 +153,110 @@ static int iscyber(int id)
}
}
-#define CRT 0x3D0 /* CRTC registers offset for color display */
-
-#ifndef TRIDENT_MMIO
- #define TRIDENT_MMIO 1
-#endif
-
-#if TRIDENT_MMIO
- #define t_outb(val, reg) writeb(val,((struct tridentfb_par *)(fb_info.par))->io_virt + reg)
- #define t_inb(reg) readb(((struct tridentfb_par*)(fb_info.par))->io_virt + reg)
-#else
- #define t_outb(val, reg) outb(val, reg)
- #define t_inb(reg) inb(reg)
-#endif
+static inline void t_outb(struct tridentfb_par *p, u8 val, u16 reg)
+{
+ fb_writeb(val, p->io_virt + reg);
+}
+static inline u8 t_inb(struct tridentfb_par *p, u16 reg)
+{
+ return fb_readb(p->io_virt + reg);
+}
-static struct accel_switch {
- void (*init_accel) (int, int);
- void (*wait_engine) (void);
- void (*fill_rect) (u32, u32, u32, u32, u32, u32);
- void (*copy_rect) (u32, u32, u32, u32, u32, u32);
-} *acc;
+static inline void writemmr(struct tridentfb_par *par, u16 r, u32 v)
+{
+ fb_writel(v, par->io_virt + r);
+}
-#define writemmr(r, v) writel(v, ((struct tridentfb_par *)fb_info.par)->io_virt + r)
-#define readmmr(r) readl(((struct tridentfb_par *)fb_info.par)->io_virt + r)
+static inline u32 readmmr(struct tridentfb_par *par, u16 r)
+{
+ return fb_readl(par->io_virt + r);
+}
/*
* Blade specific acceleration.
*/
#define point(x, y) ((y) << 16 | (x))
-#define STA 0x2120
-#define CMD 0x2144
-#define ROP 0x2148
-#define CLR 0x2160
-#define SR1 0x2100
-#define SR2 0x2104
-#define DR1 0x2108
-#define DR2 0x210C
-
-#define ROP_S 0xCC
-
-static void blade_init_accel(int pitch, int bpp)
+
+static void blade_init_accel(struct tridentfb_par *par, int pitch, int bpp)
{
int v1 = (pitch >> 3) << 20;
- int tmp = 0, v2;
- switch (bpp) {
- case 8:
- tmp = 0;
- break;
- case 15:
- tmp = 5;
- break;
- case 16:
- tmp = 1;
- break;
- case 24:
- case 32:
- tmp = 2;
- break;
- }
- v2 = v1 | (tmp << 29);
- writemmr(0x21C0, v2);
- writemmr(0x21C4, v2);
- writemmr(0x21B8, v2);
- writemmr(0x21BC, v2);
- writemmr(0x21D0, v1);
- writemmr(0x21D4, v1);
- writemmr(0x21C8, v1);
- writemmr(0x21CC, v1);
- writemmr(0x216C, 0);
+ int tmp = bpp == 24 ? 2 : (bpp >> 4);
+ int v2 = v1 | (tmp << 29);
+
+ writemmr(par, 0x21C0, v2);
+ writemmr(par, 0x21C4, v2);
+ writemmr(par, 0x21B8, v2);
+ writemmr(par, 0x21BC, v2);
+ writemmr(par, 0x21D0, v1);
+ writemmr(par, 0x21D4, v1);
+ writemmr(par, 0x21C8, v1);
+ writemmr(par, 0x21CC, v1);
+ writemmr(par, 0x216C, 0);
}
-static void blade_wait_engine(void)
+static void blade_wait_engine(struct tridentfb_par *par)
{
- while (readmmr(STA) & 0xFA800000) ;
+ while (readmmr(par, STATUS) & 0xFA800000)
+ cpu_relax();
}
-static void blade_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
+static void blade_fill_rect(struct tridentfb_par *par,
+ u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
{
- writemmr(CLR, c);
- writemmr(ROP, rop ? 0x66 : ROP_S);
- writemmr(CMD, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
+ writemmr(par, COLOR, c);
+ writemmr(par, ROP, rop ? ROP_X : ROP_S);
+ writemmr(par, CMD, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
- writemmr(DR1, point(x, y));
- writemmr(DR2, point(x + w - 1, y + h - 1));
+ writemmr(par, DST1, point(x, y));
+ writemmr(par, DST2, point(x + w - 1, y + h - 1));
}
-static void blade_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
+static void blade_image_blit(struct tridentfb_par *par, const char *data,
+ u32 x, u32 y, u32 w, u32 h, u32 c, u32 b)
+{
+ unsigned size = ((w + 31) >> 5) * h;
+
+ writemmr(par, COLOR, c);
+ writemmr(par, BGCOLOR, b);
+ writemmr(par, CMD, 0xa0000000 | 3 << 19);
+
+ writemmr(par, DST1, point(x, y));
+ writemmr(par, DST2, point(x + w - 1, y + h - 1));
+
+ memcpy(par->io_virt + 0x10000, data, 4 * size);
+}
+
+static void blade_copy_rect(struct tridentfb_par *par,
+ u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
{
- u32 s1, s2, d1, d2;
int direction = 2;
- s1 = point(x1, y1);
- s2 = point(x1 + w - 1, y1 + h - 1);
- d1 = point(x2, y2);
- d2 = point(x2 + w - 1, y2 + h - 1);
+ u32 s1 = point(x1, y1);
+ u32 s2 = point(x1 + w - 1, y1 + h - 1);
+ u32 d1 = point(x2, y2);
+ u32 d2 = point(x2 + w - 1, y2 + h - 1);
if ((y1 > y2) || ((y1 == y2) && (x1 > x2)))
direction = 0;
- writemmr(ROP, ROP_S);
- writemmr(CMD, 0xE0000000 | 1 << 19 | 1 << 4 | 1 << 2 | direction);
+ writemmr(par, ROP, ROP_S);
+ writemmr(par, CMD, 0xE0000000 | 1 << 19 | 1 << 4 | 1 << 2 | direction);
- writemmr(SR1, direction ? s2 : s1);
- writemmr(SR2, direction ? s1 : s2);
- writemmr(DR1, direction ? d2 : d1);
- writemmr(DR2, direction ? d1 : d2);
+ writemmr(par, SRC1, direction ? s2 : s1);
+ writemmr(par, SRC2, direction ? s1 : s2);
+ writemmr(par, DST1, direction ? d2 : d1);
+ writemmr(par, DST2, direction ? d1 : d2);
}
-static struct accel_switch accel_blade = {
- blade_init_accel,
- blade_wait_engine,
- blade_fill_rect,
- blade_copy_rect,
-};
-
/*
* BladeXP specific acceleration functions
*/
-#define ROP_P 0xF0
-#define masked_point(x, y) ((y & 0xffff)<<16|(x & 0xffff))
-
-static void xp_init_accel(int pitch, int bpp)
+static void xp_init_accel(struct tridentfb_par *par, int pitch, int bpp)
{
- int tmp = 0, v1;
- unsigned char x = 0;
-
- switch (bpp) {
- case 8:
- x = 0;
- break;
- case 16:
- x = 1;
- break;
- case 24:
- x = 3;
- break;
- case 32:
- x = 2;
- break;
- }
+ unsigned char x = bpp == 24 ? 3 : (bpp >> 4);
+ int v1 = pitch << (bpp == 24 ? 20 : (18 + x));
switch (pitch << (bpp >> 3)) {
case 8192:
@@ -293,42 +274,21 @@ static void xp_init_accel(int pitch, int bpp)
break;
}
- t_outb(x, 0x2125);
-
- eng_oper = x | 0x40;
-
- switch (bpp) {
- case 8:
- tmp = 18;
- break;
- case 15:
- case 16:
- tmp = 19;
- break;
- case 24:
- case 32:
- tmp = 20;
- break;
- }
+ t_outb(par, x, 0x2125);
- v1 = pitch << tmp;
+ par->eng_oper = x | 0x40;
- writemmr(0x2154, v1);
- writemmr(0x2150, v1);
- t_outb(3, 0x2126);
+ writemmr(par, 0x2154, v1);
+ writemmr(par, 0x2150, v1);
+ t_outb(par, 3, 0x2126);
}
-static void xp_wait_engine(void)
+static void xp_wait_engine(struct tridentfb_par *par)
{
- int busy;
- int count, timeout;
-
- count = 0;
- timeout = 0;
- for (;;) {
- busy = t_inb(STA) & 0x80;
- if (busy != 0x80)
- return;
+ int count = 0;
+ int timeout = 0;
+
+ while (t_inb(par, STATUS) & 0x80) {
count++;
if (count == 10000000) {
/* Timeout */
@@ -336,30 +296,31 @@ static void xp_wait_engine(void)
timeout++;
if (timeout == 8) {
/* Reset engine */
- t_outb(0x00, 0x2120);
+ t_outb(par, 0x00, STATUS);
return;
}
}
+ cpu_relax();
}
}
-static void xp_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
+static void xp_fill_rect(struct tridentfb_par *par,
+ u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
{
- writemmr(0x2127, ROP_P);
- writemmr(0x2158, c);
- writemmr(0x2128, 0x4000);
- writemmr(0x2140, masked_point(h, w));
- writemmr(0x2138, masked_point(y, x));
- t_outb(0x01, 0x2124);
- t_outb(eng_oper, 0x2125);
+ writemmr(par, 0x2127, ROP_P);
+ writemmr(par, 0x2158, c);
+ writemmr(par, DRAWFL, 0x4000);
+ writemmr(par, OLDDIM, point(h, w));
+ writemmr(par, OLDDST, point(y, x));
+ t_outb(par, 0x01, OLDCMD);
+ t_outb(par, par->eng_oper, 0x2125);
}
-static void xp_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
+static void xp_copy_rect(struct tridentfb_par *par,
+ u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
{
- int direction;
u32 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
-
- direction = 0x0004;
+ int direction = 0x0004;
if ((x1 < x2) && (y1 == y2)) {
direction |= 0x0200;
@@ -379,103 +340,152 @@ static void xp_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
y2_tmp = y2;
}
- writemmr(0x2128, direction);
- t_outb(ROP_S, 0x2127);
- writemmr(0x213C, masked_point(y1_tmp, x1_tmp));
- writemmr(0x2138, masked_point(y2_tmp, x2_tmp));
- writemmr(0x2140, masked_point(h, w));
- t_outb(0x01, 0x2124);
+ writemmr(par, DRAWFL, direction);
+ t_outb(par, ROP_S, 0x2127);
+ writemmr(par, OLDSRC, point(y1_tmp, x1_tmp));
+ writemmr(par, OLDDST, point(y2_tmp, x2_tmp));
+ writemmr(par, OLDDIM, point(h, w));
+ t_outb(par, 0x01, OLDCMD);
}
-static struct accel_switch accel_xp = {
- xp_init_accel,
- xp_wait_engine,
- xp_fill_rect,
- xp_copy_rect,
-};
-
/*
* Image specific acceleration functions
*/
-static void image_init_accel(int pitch, int bpp)
+static void image_init_accel(struct tridentfb_par *par, int pitch, int bpp)
{
- int tmp = 0;
- switch (bpp) {
- case 8:
- tmp = 0;
- break;
- case 15:
- tmp = 5;
- break;
- case 16:
- tmp = 1;
- break;
- case 24:
- case 32:
- tmp = 2;
- break;
- }
- writemmr(0x2120, 0xF0000000);
- writemmr(0x2120, 0x40000000 | tmp);
- writemmr(0x2120, 0x80000000);
- writemmr(0x2144, 0x00000000);
- writemmr(0x2148, 0x00000000);
- writemmr(0x2150, 0x00000000);
- writemmr(0x2154, 0x00000000);
- writemmr(0x2120, 0x60000000 | (pitch << 16) | pitch);
- writemmr(0x216C, 0x00000000);
- writemmr(0x2170, 0x00000000);
- writemmr(0x217C, 0x00000000);
- writemmr(0x2120, 0x10000000);
- writemmr(0x2130, (2047 << 16) | 2047);
+ int tmp = bpp == 24 ? 2: (bpp >> 4);
+
+ writemmr(par, 0x2120, 0xF0000000);
+ writemmr(par, 0x2120, 0x40000000 | tmp);
+ writemmr(par, 0x2120, 0x80000000);
+ writemmr(par, 0x2144, 0x00000000);
+ writemmr(par, 0x2148, 0x00000000);
+ writemmr(par, 0x2150, 0x00000000);
+ writemmr(par, 0x2154, 0x00000000);
+ writemmr(par, 0x2120, 0x60000000 | (pitch << 16) | pitch);
+ writemmr(par, 0x216C, 0x00000000);
+ writemmr(par, 0x2170, 0x00000000);
+ writemmr(par, 0x217C, 0x00000000);
+ writemmr(par, 0x2120, 0x10000000);
+ writemmr(par, 0x2130, (2047 << 16) | 2047);
}
-static void image_wait_engine(void)
+static void image_wait_engine(struct tridentfb_par *par)
{
- while (readmmr(0x2164) & 0xF0000000) ;
+ while (readmmr(par, 0x2164) & 0xF0000000)
+ cpu_relax();
}
-static void image_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
+static void image_fill_rect(struct tridentfb_par *par,
+ u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
{
- writemmr(0x2120, 0x80000000);
- writemmr(0x2120, 0x90000000 | ROP_S);
+ writemmr(par, 0x2120, 0x80000000);
+ writemmr(par, 0x2120, 0x90000000 | ROP_S);
- writemmr(0x2144, c);
+ writemmr(par, 0x2144, c);
- writemmr(DR1, point(x, y));
- writemmr(DR2, point(x + w - 1, y + h - 1));
+ writemmr(par, DST1, point(x, y));
+ writemmr(par, DST2, point(x + w - 1, y + h - 1));
- writemmr(0x2124, 0x80000000 | 3 << 22 | 1 << 10 | 1 << 9);
+ writemmr(par, 0x2124, 0x80000000 | 3 << 22 | 1 << 10 | 1 << 9);
}
-static void image_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
+static void image_copy_rect(struct tridentfb_par *par,
+ u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
{
- u32 s1, s2, d1, d2;
- int direction = 2;
- s1 = point(x1, y1);
- s2 = point(x1 + w - 1, y1 + h - 1);
- d1 = point(x2, y2);
- d2 = point(x2 + w - 1, y2 + h - 1);
+ int direction = 0x4;
+ u32 s1 = point(x1, y1);
+ u32 s2 = point(x1 + w - 1, y1 + h - 1);
+ u32 d1 = point(x2, y2);
+ u32 d2 = point(x2 + w - 1, y2 + h - 1);
if ((y1 > y2) || ((y1 == y2) && (x1 > x2)))
direction = 0;
- writemmr(0x2120, 0x80000000);
- writemmr(0x2120, 0x90000000 | ROP_S);
+ writemmr(par, 0x2120, 0x80000000);
+ writemmr(par, 0x2120, 0x90000000 | ROP_S);
- writemmr(SR1, direction ? s2 : s1);
- writemmr(SR2, direction ? s1 : s2);
- writemmr(DR1, direction ? d2 : d1);
- writemmr(DR2, direction ? d1 : d2);
- writemmr(0x2124, 0x80000000 | 1 << 22 | 1 << 10 | 1 << 7 | direction);
+ writemmr(par, SRC1, direction ? s2 : s1);
+ writemmr(par, SRC2, direction ? s1 : s2);
+ writemmr(par, DST1, direction ? d2 : d1);
+ writemmr(par, DST2, direction ? d1 : d2);
+ writemmr(par, 0x2124,
+ 0x80000000 | 1 << 22 | 1 << 10 | 1 << 7 | direction);
}
-static struct accel_switch accel_image = {
- image_init_accel,
- image_wait_engine,
- image_fill_rect,
- image_copy_rect,
-};
+/*
+ * TGUI 9440/96XX acceleration
+ */
+
+static void tgui_init_accel(struct tridentfb_par *par, int pitch, int bpp)
+{
+ unsigned char x = bpp == 24 ? 3 : (bpp >> 4);
+
+ /* disable clipping */
+ writemmr(par, 0x2148, 0);
+ writemmr(par, 0x214C, point(4095, 2047));
+
+ switch ((pitch * bpp) / 8) {
+ case 8192:
+ case 512:
+ x |= 0x00;
+ break;
+ case 1024:
+ x |= 0x04;
+ break;
+ case 2048:
+ x |= 0x08;
+ break;
+ case 4096:
+ x |= 0x0C;
+ break;
+ }
+
+ fb_writew(x, par->io_virt + 0x2122);
+}
+
+static void tgui_fill_rect(struct tridentfb_par *par,
+ u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
+{
+ t_outb(par, ROP_P, 0x2127);
+ writemmr(par, OLDCLR, c);
+ writemmr(par, DRAWFL, 0x4020);
+ writemmr(par, OLDDIM, point(w - 1, h - 1));
+ writemmr(par, OLDDST, point(x, y));
+ t_outb(par, 1, OLDCMD);
+}
+
+static void tgui_copy_rect(struct tridentfb_par *par,
+ u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
+{
+ int flags = 0;
+ u16 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
+
+ if ((x1 < x2) && (y1 == y2)) {
+ flags |= 0x0200;
+ x1_tmp = x1 + w - 1;
+ x2_tmp = x2 + w - 1;
+ } else {
+ x1_tmp = x1;
+ x2_tmp = x2;
+ }
+
+ if (y1 < y2) {
+ flags |= 0x0100;
+ y1_tmp = y1 + h - 1;
+ y2_tmp = y2 + h - 1;
+ } else {
+ y1_tmp = y1;
+ y2_tmp = y2;
+ }
+
+ writemmr(par, DRAWFL, 0x4 | flags);
+ t_outb(par, ROP_S, 0x2127);
+ writemmr(par, OLDSRC, point(x1_tmp, y1_tmp));
+ writemmr(par, OLDDST, point(x2_tmp, y2_tmp));
+ writemmr(par, OLDDIM, point(w - 1, h - 1));
+ t_outb(par, 1, OLDCMD);
+}
/*
* Accel functions called by the upper layers
@@ -484,129 +494,162 @@ static struct accel_switch accel_image = {
static void tridentfb_fillrect(struct fb_info *info,
const struct fb_fillrect *fr)
{
- int bpp = info->var.bits_per_pixel;
- int col = 0;
+ struct tridentfb_par *par = info->par;
+ int col;
- switch (bpp) {
- default:
- case 8:
- col |= fr->color;
+ if (info->flags & FBINFO_HWACCEL_DISABLED) {
+ cfb_fillrect(info, fr);
+ return;
+ }
+ if (info->var.bits_per_pixel == 8) {
+ col = fr->color;
col |= col << 8;
col |= col << 16;
- break;
- case 16:
+ } else
col = ((u32 *)(info->pseudo_palette))[fr->color];
- break;
- case 32:
- col = ((u32 *)(info->pseudo_palette))[fr->color];
- break;
+
+ par->wait_engine(par);
+ par->fill_rect(par, fr->dx, fr->dy, fr->width,
+ fr->height, col, fr->rop);
+}
+
+static void tridentfb_imageblit(struct fb_info *info,
+ const struct fb_image *img)
+{
+ struct tridentfb_par *par = info->par;
+ int col, bgcol;
+
+ if ((info->flags & FBINFO_HWACCEL_DISABLED) || img->depth != 1) {
+ cfb_imageblit(info, img);
+ return;
+ }
+ if (info->var.bits_per_pixel == 8) {
+ col = img->fg_color;
+ col |= col << 8;
+ col |= col << 16;
+ bgcol = img->bg_color;
+ bgcol |= bgcol << 8;
+ bgcol |= bgcol << 16;
+ } else {
+ col = ((u32 *)(info->pseudo_palette))[img->fg_color];
+ bgcol = ((u32 *)(info->pseudo_palette))[img->bg_color];
}
- acc->fill_rect(fr->dx, fr->dy, fr->width, fr->height, col, fr->rop);
- acc->wait_engine();
+ par->wait_engine(par);
+ if (par->image_blit)
+ par->image_blit(par, img->data, img->dx, img->dy,
+ img->width, img->height, col, bgcol);
+ else
+ cfb_imageblit(info, img);
}
+
static void tridentfb_copyarea(struct fb_info *info,
const struct fb_copyarea *ca)
{
- acc->copy_rect(ca->sx, ca->sy, ca->dx, ca->dy, ca->width, ca->height);
- acc->wait_engine();
+ struct tridentfb_par *par = info->par;
+
+ if (info->flags & FBINFO_HWACCEL_DISABLED) {
+ cfb_copyarea(info, ca);
+ return;
+ }
+ par->wait_engine(par);
+ par->copy_rect(par, ca->sx, ca->sy, ca->dx, ca->dy,
+ ca->width, ca->height);
+}
+
+static int tridentfb_sync(struct fb_info *info)
+{
+ struct tridentfb_par *par = info->par;
+
+ if (!(info->flags & FBINFO_HWACCEL_DISABLED))
+ par->wait_engine(par);
+ return 0;
}
-#else /* !CONFIG_FB_TRIDENT_ACCEL */
+#else
#define tridentfb_fillrect cfb_fillrect
#define tridentfb_copyarea cfb_copyarea
+#define tridentfb_imageblit cfb_imageblit
#endif /* CONFIG_FB_TRIDENT_ACCEL */
-
/*
* Hardware access functions
*/
-static inline unsigned char read3X4(int reg)
+static inline unsigned char read3X4(struct tridentfb_par *par, int reg)
{
- struct tridentfb_par *par = (struct tridentfb_par *)fb_info.par;
- writeb(reg, par->io_virt + CRT + 4);
- return readb(par->io_virt + CRT + 5);
+ return vga_mm_rcrt(par->io_virt, reg);
}
-static inline void write3X4(int reg, unsigned char val)
+static inline void write3X4(struct tridentfb_par *par, int reg,
+ unsigned char val)
{
- struct tridentfb_par *par = (struct tridentfb_par *)fb_info.par;
- writeb(reg, par->io_virt + CRT + 4);
- writeb(val, par->io_virt + CRT + 5);
+ vga_mm_wcrt(par->io_virt, reg, val);
}
-static inline unsigned char read3C4(int reg)
+static inline unsigned char read3CE(struct tridentfb_par *par,
+ unsigned char reg)
{
- t_outb(reg, 0x3C4);
- return t_inb(0x3C5);
+ return vga_mm_rgfx(par->io_virt, reg);
}
-static inline void write3C4(int reg, unsigned char val)
+static inline void writeAttr(struct tridentfb_par *par, int reg,
+ unsigned char val)
{
- t_outb(reg, 0x3C4);
- t_outb(val, 0x3C5);
+ fb_readb(par->io_virt + VGA_IS1_RC); /* flip-flop to index */
+ vga_mm_wattr(par->io_virt, reg, val);
}
-static inline unsigned char read3CE(int reg)
+static inline void write3CE(struct tridentfb_par *par, int reg,
+ unsigned char val)
{
- t_outb(reg, 0x3CE);
- return t_inb(0x3CF);
+ vga_mm_wgfx(par->io_virt, reg, val);
}
-static inline void writeAttr(int reg, unsigned char val)
-{
- readb(((struct tridentfb_par *)fb_info.par)->io_virt + CRT + 0x0A); /* flip-flop to index */
- t_outb(reg, 0x3C0);
- t_outb(val, 0x3C0);
-}
-
-static inline void write3CE(int reg, unsigned char val)
-{
- t_outb(reg, 0x3CE);
- t_outb(val, 0x3CF);
-}
-
-static void enable_mmio(void)
+static void enable_mmio(struct tridentfb_par *par)
{
/* Goto New Mode */
- outb(0x0B, 0x3C4);
- inb(0x3C5);
+ vga_io_rseq(0x0B);
/* Unprotect registers */
- outb(NewMode1, 0x3C4);
- outb(0x80, 0x3C5);
+ vga_io_wseq(NewMode1, 0x80);
+ if (!is_oldprotect(par->chip_id))
+ vga_io_wseq(Protection, 0x92);
/* Enable MMIO */
outb(PCIReg, 0x3D4);
outb(inb(0x3D5) | 0x01, 0x3D5);
}
-static void disable_mmio(void)
+static void disable_mmio(struct tridentfb_par *par)
{
/* Goto New Mode */
- t_outb(0x0B, 0x3C4);
- t_inb(0x3C5);
+ vga_mm_rseq(par->io_virt, 0x0B);
/* Unprotect registers */
- t_outb(NewMode1, 0x3C4);
- t_outb(0x80, 0x3C5);
+ vga_mm_wseq(par->io_virt, NewMode1, 0x80);
+ if (!is_oldprotect(par->chip_id))
+ vga_mm_wseq(par->io_virt, Protection, 0x92);
/* Disable MMIO */
- t_outb(PCIReg, 0x3D4);
- t_outb(t_inb(0x3D5) & ~0x01, 0x3D5);
+ t_outb(par, PCIReg, 0x3D4);
+ t_outb(par, t_inb(par, 0x3D5) & ~0x01, 0x3D5);
}
-#define crtc_unlock() write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F)
+static inline void crtc_unlock(struct tridentfb_par *par)
+{
+ write3X4(par, VGA_CRTC_V_SYNC_END,
+ read3X4(par, VGA_CRTC_V_SYNC_END) & 0x7F);
+}
/* Return flat panel's maximum x resolution */
-static int __devinit get_nativex(void)
+static int __devinit get_nativex(struct tridentfb_par *par)
{
int x, y, tmp;
if (nativex)
return nativex;
- tmp = (read3CE(VertStretch) >> 4) & 3;
+ tmp = (read3CE(par, VertStretch) >> 4) & 3;
switch (tmp) {
case 0:
@@ -632,77 +675,92 @@ static int __devinit get_nativex(void)
}
/* Set pitch */
-static void set_lwidth(int width)
+static inline void set_lwidth(struct tridentfb_par *par, int width)
{
- write3X4(Offset, width & 0xFF);
- write3X4(AddColReg,
- (read3X4(AddColReg) & 0xCF) | ((width & 0x300) >> 4));
+ write3X4(par, VGA_CRTC_OFFSET, width & 0xFF);
+ write3X4(par, AddColReg,
+ (read3X4(par, AddColReg) & 0xCF) | ((width & 0x300) >> 4));
}
/* For resolutions smaller than FP resolution stretch */
-static void screen_stretch(void)
+static void screen_stretch(struct tridentfb_par *par)
{
- if (chip_id != CYBERBLADEXPAi1)
- write3CE(BiosReg, 0);
+ if (par->chip_id != CYBERBLADEXPAi1)
+ write3CE(par, BiosReg, 0);
else
- write3CE(BiosReg, 8);
- write3CE(VertStretch, (read3CE(VertStretch) & 0x7C) | 1);
- write3CE(HorStretch, (read3CE(HorStretch) & 0x7C) | 1);
+ write3CE(par, BiosReg, 8);
+ write3CE(par, VertStretch, (read3CE(par, VertStretch) & 0x7C) | 1);
+ write3CE(par, HorStretch, (read3CE(par, HorStretch) & 0x7C) | 1);
}
/* For resolutions smaller than FP resolution center */
-static void screen_center(void)
+static inline void screen_center(struct tridentfb_par *par)
{
- write3CE(VertStretch, (read3CE(VertStretch) & 0x7C) | 0x80);
- write3CE(HorStretch, (read3CE(HorStretch) & 0x7C) | 0x80);
+ write3CE(par, VertStretch, (read3CE(par, VertStretch) & 0x7C) | 0x80);
+ write3CE(par, HorStretch, (read3CE(par, HorStretch) & 0x7C) | 0x80);
}
/* Address of first shown pixel in display memory */
-static void set_screen_start(int base)
+static void set_screen_start(struct tridentfb_par *par, int base)
{
- write3X4(StartAddrLow, base & 0xFF);
- write3X4(StartAddrHigh, (base & 0xFF00) >> 8);
- write3X4(CRTCModuleTest,
- (read3X4(CRTCModuleTest) & 0xDF) | ((base & 0x10000) >> 11));
- write3X4(CRTHiOrd,
- (read3X4(CRTHiOrd) & 0xF8) | ((base & 0xE0000) >> 17));
+ u8 tmp;
+ write3X4(par, VGA_CRTC_START_LO, base & 0xFF);
+ write3X4(par, VGA_CRTC_START_HI, (base & 0xFF00) >> 8);
+ tmp = read3X4(par, CRTCModuleTest) & 0xDF;
+ write3X4(par, CRTCModuleTest, tmp | ((base & 0x10000) >> 11));
+ tmp = read3X4(par, CRTHiOrd) & 0xF8;
+ write3X4(par, CRTHiOrd, tmp | ((base & 0xE0000) >> 17));
}
/* Set dotclock frequency */
-static void set_vclk(unsigned long freq)
+static void set_vclk(struct tridentfb_par *par, unsigned long freq)
{
int m, n, k;
- unsigned long f, fi, d, di;
- unsigned char lo = 0, hi = 0;
+ unsigned long fi, d, di;
+ unsigned char best_m = 0, best_n = 0, best_k = 0;
+ unsigned char hi, lo;
+ unsigned char shift = !is_oldclock(par->chip_id) ? 2 : 1;
d = 20000;
- for (k = 2; k >= 0; k--)
- for (m = 0; m < 63; m++)
- for (n = 0; n < 128; n++) {
+ for (k = shift; k >= 0; k--)
+ for (m = 1; m < 32; m++) {
+ n = ((m + 2) << shift) - 8;
+ for (n = (n < 0 ? 0 : n); n < 122; n++) {
fi = ((14318l * (n + 8)) / (m + 2)) >> k;
- if ((di = abs(fi - freq)) < d) {
+ di = abs(fi - freq);
+ if (di < d || (di == d && k == best_k)) {
d = di;
- f = fi;
- lo = n;
- hi = (k << 6) | m;
+ best_n = n;
+ best_m = m;
+ best_k = k;
}
if (fi > freq)
break;
}
- if (chip3D) {
- write3C4(ClockHigh, hi);
- write3C4(ClockLow, lo);
+ }
+
+ if (is_oldclock(par->chip_id)) {
+ lo = best_n | (best_m << 7);
+ hi = (best_m >> 1) | (best_k << 4);
} else {
- outb(lo, 0x43C8);
- outb(hi, 0x43C9);
+ lo = best_n;
+ hi = best_m | (best_k << 6);
+ }
+
+ if (is3Dchip(par->chip_id)) {
+ vga_mm_wseq(par->io_virt, ClockHigh, hi);
+ vga_mm_wseq(par->io_virt, ClockLow, lo);
+ } else {
+ t_outb(par, lo, 0x43C8);
+ t_outb(par, hi, 0x43C9);
}
debug("VCLK = %X %X\n", hi, lo);
}
/* Set number of lines for flat panels*/
-static void set_number_of_lines(int lines)
+static void set_number_of_lines(struct tridentfb_par *par, int lines)
{
- int tmp = read3CE(CyberEnhance) & 0x8F;
+ int tmp = read3CE(par, CyberEnhance) & 0x8F;
if (lines > 1024)
tmp |= 0x50;
else if (lines > 768)
@@ -711,24 +769,24 @@ static void set_number_of_lines(int lines)
tmp |= 0x20;
else if (lines > 480)
tmp |= 0x10;
- write3CE(CyberEnhance, tmp);
+ write3CE(par, CyberEnhance, tmp);
}
/*
* If we see that FP is active we assume we have one.
- * Otherwise we have a CRT display.User can override.
+ * Otherwise we have a CRT display. User can override.
*/
-static unsigned int __devinit get_displaytype(void)
+static int __devinit is_flatpanel(struct tridentfb_par *par)
{
if (fp)
- return DISPLAY_FP;
- if (crt || !chipcyber)
- return DISPLAY_CRT;
- return (read3CE(FPConfig) & 0x10) ? DISPLAY_FP : DISPLAY_CRT;
+ return 1;
+ if (crt || !iscyber(par->chip_id))
+ return 0;
+ return (read3CE(par, FPConfig) & 0x10) ? 1 : 0;
}
/* Try detecting the video memory size */
-static unsigned int __devinit get_memsize(void)
+static unsigned int __devinit get_memsize(struct tridentfb_par *par)
{
unsigned char tmp, tmp2;
unsigned int k;
@@ -737,12 +795,12 @@ static unsigned int __devinit get_memsize(void)
if (memsize)
k = memsize * Kb;
else
- switch (chip_id) {
+ switch (par->chip_id) {
case CYBER9525DVD:
k = 2560 * Kb;
break;
default:
- tmp = read3X4(SPR) & 0x0F;
+ tmp = read3X4(par, SPR) & 0x0F;
switch (tmp) {
case 0x01:
@@ -774,7 +832,7 @@ static unsigned int __devinit get_memsize(void)
break;
case 0x0E: /* XP */
- tmp2 = read3C4(0xC1);
+ tmp2 = vga_mm_rseq(par->io_virt, 0xC1);
switch (tmp2) {
case 0x00:
k = 20 * Mb;
@@ -812,26 +870,67 @@ static unsigned int __devinit get_memsize(void)
static int tridentfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
+ struct tridentfb_par *par = info->par;
int bpp = var->bits_per_pixel;
+ int line_length;
+ int ramdac = 230000; /* 230MHz for most 3D chips */
debug("enter\n");
/* check color depth */
if (bpp == 24)
bpp = var->bits_per_pixel = 32;
+ if (bpp != 8 && bpp != 16 && bpp != 32)
+ return -EINVAL;
+ if (par->chip_id == TGUI9440 && bpp == 32)
+ return -EINVAL;
/* check whether resolution fits on panel and in memory */
- if (flatpanel && nativex && var->xres > nativex)
+ if (par->flatpanel && nativex && var->xres > nativex)
+ return -EINVAL;
+ /* various resolution checks */
+ var->xres = (var->xres + 7) & ~0x7;
+ if (var->xres > var->xres_virtual)
+ var->xres_virtual = var->xres;
+ if (var->yres > var->yres_virtual)
+ var->yres_virtual = var->yres;
+ if (var->xres_virtual > 4095 || var->yres > 2048)
return -EINVAL;
- if (var->xres * var->yres_virtual * bpp / 8 > info->fix.smem_len)
+ /* prevent from position overflow for acceleration */
+ if (var->yres_virtual > 0xffff)
+ return -EINVAL;
+ line_length = var->xres_virtual * bpp / 8;
+
+ if (!is3Dchip(par->chip_id) &&
+ !(info->flags & FBINFO_HWACCEL_DISABLED)) {
+ /* acceleration requires line length to be power of 2 */
+ if (line_length <= 512)
+ var->xres_virtual = 512 * 8 / bpp;
+ else if (line_length <= 1024)
+ var->xres_virtual = 1024 * 8 / bpp;
+ else if (line_length <= 2048)
+ var->xres_virtual = 2048 * 8 / bpp;
+ else if (line_length <= 4096)
+ var->xres_virtual = 4096 * 8 / bpp;
+ else if (line_length <= 8192)
+ var->xres_virtual = 8192 * 8 / bpp;
+ else
+ return -EINVAL;
+
+ line_length = var->xres_virtual * bpp / 8;
+ }
+
+ /* datasheet specifies how to set panning only up to 4 MB */
+ if (line_length * (var->yres_virtual - var->yres) > (4 << 20))
+ var->yres_virtual = ((4 << 20) / line_length) + var->yres;
+
+ if (line_length * var->yres_virtual > info->fix.smem_len)
return -EINVAL;
switch (bpp) {
case 8:
var->red.offset = 0;
- var->green.offset = 0;
- var->blue.offset = 0;
- var->red.length = 6;
- var->green.length = 6;
- var->blue.length = 6;
+ var->red.length = 8;
+ var->green = var->red;
+ var->blue = var->red;
break;
case 16:
var->red.offset = 11;
@@ -852,6 +951,33 @@ static int tridentfb_check_var(struct fb_var_screeninfo *var,
default:
return -EINVAL;
}
+
+ if (is_xp(par->chip_id))
+ ramdac = 350000;
+
+ switch (par->chip_id) {
+ case TGUI9440:
+ ramdac = (bpp >= 16) ? 45000 : 90000;
+ break;
+ case CYBER9320:
+ case TGUI9660:
+ ramdac = 135000;
+ break;
+ case PROVIDIA9685:
+ case CYBER9388:
+ case CYBER9382:
+ case CYBER9385:
+ ramdac = 170000;
+ break;
+ }
+
+ /* The clock is doubled for 32 bpp */
+ if (bpp == 32)
+ ramdac /= 2;
+
+ if (PICOS2KHZ(var->pixclock) > ramdac)
+ return -EINVAL;
+
debug("exit\n");
return 0;
@@ -862,25 +988,31 @@ static int tridentfb_check_var(struct fb_var_screeninfo *var,
static int tridentfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
+ struct tridentfb_par *par = info->par;
unsigned int offset;
debug("enter\n");
- offset = (var->xoffset + (var->yoffset * var->xres))
+ offset = (var->xoffset + (var->yoffset * var->xres_virtual))
* var->bits_per_pixel / 32;
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
- set_screen_start(offset);
+ set_screen_start(par, offset);
debug("exit\n");
return 0;
}
-#define shadowmode_on() write3CE(CyberControl, read3CE(CyberControl) | 0x81)
-#define shadowmode_off() write3CE(CyberControl, read3CE(CyberControl) & 0x7E)
+static inline void shadowmode_on(struct tridentfb_par *par)
+{
+ write3CE(par, CyberControl, read3CE(par, CyberControl) | 0x81);
+}
+
+static inline void shadowmode_off(struct tridentfb_par *par)
+{
+ write3CE(par, CyberControl, read3CE(par, CyberControl) & 0x7E);
+}
/* Set the hardware to the requested video mode */
static int tridentfb_set_par(struct fb_info *info)
{
- struct tridentfb_par *par = (struct tridentfb_par *)(info->par);
+ struct tridentfb_par *par = info->par;
u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend;
u32 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend;
struct fb_var_screeninfo *var = &info->var;
@@ -891,58 +1023,73 @@ static int tridentfb_set_par(struct fb_info *info)
debug("enter\n");
hdispend = var->xres / 8 - 1;
hsyncstart = (var->xres + var->right_margin) / 8;
- hsyncend = var->hsync_len / 8;
- htotal =
- (var->xres + var->left_margin + var->right_margin +
- var->hsync_len) / 8 - 10;
+ hsyncend = (var->xres + var->right_margin + var->hsync_len) / 8;
+ htotal = (var->xres + var->left_margin + var->right_margin +
+ var->hsync_len) / 8 - 5;
hblankstart = hdispend + 1;
- hblankend = htotal + 5;
+ hblankend = htotal + 3;
vdispend = var->yres - 1;
vsyncstart = var->yres + var->lower_margin;
- vsyncend = var->vsync_len;
- vtotal = var->upper_margin + vsyncstart + vsyncend - 2;
- vblankstart = var->yres;
- vblankend = vtotal + 2;
+ vsyncend = vsyncstart + var->vsync_len;
+ vtotal = var->upper_margin + vsyncend - 2;
+ vblankstart = vdispend + 1;
+ vblankend = vtotal;
+
+ if (info->var.vmode & FB_VMODE_INTERLACED) {
+ vtotal /= 2;
+ vdispend /= 2;
+ vsyncstart /= 2;
+ vsyncend /= 2;
+ vblankstart /= 2;
+ vblankend /= 2;
+ }
- crtc_unlock();
- write3CE(CyberControl, 8);
+ enable_mmio(par);
+ crtc_unlock(par);
+ write3CE(par, CyberControl, 8);
+ tmp = 0xEB;
+ if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+ tmp &= ~0x40;
+ if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+ tmp &= ~0x80;
- if (flatpanel && var->xres < nativex) {
+ if (par->flatpanel && var->xres < nativex) {
/*
* on flat panels with native size larger
* than requested resolution decide whether
* we stretch or center
*/
- t_outb(0xEB, 0x3C2);
+ t_outb(par, tmp | 0xC0, VGA_MIS_W);
- shadowmode_on();
+ shadowmode_on(par);
if (center)
- screen_center();
+ screen_center(par);
else if (stretch)
- screen_stretch();
+ screen_stretch(par);
} else {
- t_outb(0x2B, 0x3C2);
- write3CE(CyberControl, 8);
+ t_outb(par, tmp, VGA_MIS_W);
+ write3CE(par, CyberControl, 8);
}
/* vertical timing values */
- write3X4(CRTVTotal, vtotal & 0xFF);
- write3X4(CRTVDispEnd, vdispend & 0xFF);
- write3X4(CRTVSyncStart, vsyncstart & 0xFF);
- write3X4(CRTVSyncEnd, (vsyncend & 0x0F));
- write3X4(CRTVBlankStart, vblankstart & 0xFF);
- write3X4(CRTVBlankEnd, 0 /* p->vblankend & 0xFF */ );
+ write3X4(par, VGA_CRTC_V_TOTAL, vtotal & 0xFF);
+ write3X4(par, VGA_CRTC_V_DISP_END, vdispend & 0xFF);
+ write3X4(par, VGA_CRTC_V_SYNC_START, vsyncstart & 0xFF);
+ write3X4(par, VGA_CRTC_V_SYNC_END, (vsyncend & 0x0F));
+ write3X4(par, VGA_CRTC_V_BLANK_START, vblankstart & 0xFF);
+ write3X4(par, VGA_CRTC_V_BLANK_END, vblankend & 0xFF);
/* horizontal timing values */
- write3X4(CRTHTotal, htotal & 0xFF);
- write3X4(CRTHDispEnd, hdispend & 0xFF);
- write3X4(CRTHSyncStart, hsyncstart & 0xFF);
- write3X4(CRTHSyncEnd, (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));
- write3X4(CRTHBlankStart, hblankstart & 0xFF);
- write3X4(CRTHBlankEnd, 0 /* (p->hblankend & 0x1F) */ );
+ write3X4(par, VGA_CRTC_H_TOTAL, htotal & 0xFF);
+ write3X4(par, VGA_CRTC_H_DISP, hdispend & 0xFF);
+ write3X4(par, VGA_CRTC_H_SYNC_START, hsyncstart & 0xFF);
+ write3X4(par, VGA_CRTC_H_SYNC_END,
+ (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));
+ write3X4(par, VGA_CRTC_H_BLANK_START, hblankstart & 0xFF);
+ write3X4(par, VGA_CRTC_H_BLANK_END, hblankend & 0x1F);
/* higher bits of vertical timing values */
tmp = 0x10;
@@ -954,39 +1101,43 @@ static int tridentfb_set_par(struct fb_info *info)
if (vtotal & 0x200) tmp |= 0x20;
if (vdispend & 0x200) tmp |= 0x40;
if (vsyncstart & 0x200) tmp |= 0x80;
- write3X4(CRTOverflow, tmp);
+ write3X4(par, VGA_CRTC_OVERFLOW, tmp);
- tmp = read3X4(CRTHiOrd) | 0x08; /* line compare bit 10 */
+ tmp = read3X4(par, CRTHiOrd) & 0x07;
+ tmp |= 0x08; /* line compare bit 10 */
if (vtotal & 0x400) tmp |= 0x80;
if (vblankstart & 0x400) tmp |= 0x40;
if (vsyncstart & 0x400) tmp |= 0x20;
if (vdispend & 0x400) tmp |= 0x10;
- write3X4(CRTHiOrd, tmp);
+ write3X4(par, CRTHiOrd, tmp);
- tmp = 0;
- if (htotal & 0x800) tmp |= 0x800 >> 11;
- if (hblankstart & 0x800) tmp |= 0x800 >> 7;
- write3X4(HorizOverflow, tmp);
+ tmp = (htotal >> 8) & 0x01;
+ tmp |= (hdispend >> 7) & 0x02;
+ tmp |= (hsyncstart >> 5) & 0x08;
+ tmp |= (hblankstart >> 4) & 0x10;
+ write3X4(par, HorizOverflow, tmp);
tmp = 0x40;
if (vblankstart & 0x200) tmp |= 0x20;
//FIXME if (info->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80; /* double scan for 200 line modes */
- write3X4(CRTMaxScanLine, tmp);
+ write3X4(par, VGA_CRTC_MAX_SCAN, tmp);
- write3X4(CRTLineCompare, 0xFF);
- write3X4(CRTPRowScan, 0);
- write3X4(CRTModeControl, 0xC3);
+ write3X4(par, VGA_CRTC_LINE_COMPARE, 0xFF);
+ write3X4(par, VGA_CRTC_PRESET_ROW, 0);
+ write3X4(par, VGA_CRTC_MODE, 0xC3);
- write3X4(LinearAddReg, 0x20); /* enable linear addressing */
+ write3X4(par, LinearAddReg, 0x20); /* enable linear addressing */
tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80;
- write3X4(CRTCModuleTest, tmp); /* enable access extended memory */
-
- write3X4(GraphEngReg, 0x80); /* enable GE for text acceleration */
+ /* enable access extended memory */
+ write3X4(par, CRTCModuleTest, tmp);
+ tmp = read3CE(par, MiscIntContReg) & ~0x4;
+ if (info->var.vmode & FB_VMODE_INTERLACED)
+ tmp |= 0x4;
+ write3CE(par, MiscIntContReg, tmp);
-#ifdef CONFIG_FB_TRIDENT_ACCEL
- acc->init_accel(info->var.xres, bpp);
-#endif
+ /* enable GE for text acceleration */
+ write3X4(par, GraphEngReg, 0x80);
switch (bpp) {
case 8:
@@ -1003,57 +1154,59 @@ static int tridentfb_set_par(struct fb_info *info)
break;
}
- write3X4(PixelBusReg, tmp);
+ write3X4(par, PixelBusReg, tmp);
- tmp = 0x10;
- if (chipcyber)
+ tmp = read3X4(par, DRAMControl);
+ if (!is_oldprotect(par->chip_id))
+ tmp |= 0x10;
+ if (iscyber(par->chip_id))
tmp |= 0x20;
- write3X4(DRAMControl, tmp); /* both IO, linear enable */
-
- write3X4(InterfaceSel, read3X4(InterfaceSel) | 0x40);
- write3X4(Performance, 0x92);
- write3X4(PCIReg, 0x07); /* MMIO & PCI read and write burst enable */
+ write3X4(par, DRAMControl, tmp); /* both IO, linear enable */
+
+ write3X4(par, InterfaceSel, read3X4(par, InterfaceSel) | 0x40);
+ if (!is_xp(par->chip_id))
+ write3X4(par, Performance, read3X4(par, Performance) | 0x10);
+ /* MMIO & PCI read and write burst enable */
+ if (par->chip_id != TGUI9440 && par->chip_id != IMAGE975)
+ write3X4(par, PCIReg, read3X4(par, PCIReg) | 0x06);
+
+ vga_mm_wseq(par->io_virt, 0, 3);
+ vga_mm_wseq(par->io_virt, 1, 1); /* set char clock 8 dots wide */
+ /* enable 4 maps because needed in chain4 mode */
+ vga_mm_wseq(par->io_virt, 2, 0x0F);
+ vga_mm_wseq(par->io_virt, 3, 0);
+ vga_mm_wseq(par->io_virt, 4, 0x0E); /* memory mode enable bitmaps ?? */
/* convert from picoseconds to kHz */
vclk = PICOS2KHZ(info->var.pixclock);
- if (bpp == 32)
+
+ /* divide clock by 2 if 32bpp chain4 mode display and CPU path */
+ tmp = read3CE(par, MiscExtFunc) & 0xF0;
+ if (bpp == 32 || (par->chip_id == TGUI9440 && bpp == 16)) {
+ tmp |= 8;
vclk *= 2;
- set_vclk(vclk);
-
- write3C4(0, 3);
- write3C4(1, 1); /* set char clock 8 dots wide */
- write3C4(2, 0x0F); /* enable 4 maps because needed in chain4 mode */
- write3C4(3, 0);
- write3C4(4, 0x0E); /* memory mode enable bitmaps ?? */
-
- write3CE(MiscExtFunc, (bpp == 32) ? 0x1A : 0x12); /* divide clock by 2 if 32bpp */
- /* chain4 mode display and CPU path */
- write3CE(0x5, 0x40); /* no CGA compat, allow 256 col */
- write3CE(0x6, 0x05); /* graphics mode */
- write3CE(0x7, 0x0F); /* planes? */
-
- if (chip_id == CYBERBLADEXPAi1) {
- /* This fixes snow-effect in 32 bpp */
- write3X4(CRTHSyncStart, 0x84);
}
+ set_vclk(par, vclk);
+ write3CE(par, MiscExtFunc, tmp | 0x12);
+ write3CE(par, 0x5, 0x40); /* no CGA compat, allow 256 col */
+ write3CE(par, 0x6, 0x05); /* graphics mode */
+ write3CE(par, 0x7, 0x0F); /* planes? */
- writeAttr(0x10, 0x41); /* graphics mode and support 256 color modes */
- writeAttr(0x12, 0x0F); /* planes */
- writeAttr(0x13, 0); /* horizontal pel panning */
+ /* graphics mode and support 256 color modes */
+ writeAttr(par, 0x10, 0x41);
+ writeAttr(par, 0x12, 0x0F); /* planes */
+ writeAttr(par, 0x13, 0); /* horizontal pel panning */
/* colors */
for (tmp = 0; tmp < 0x10; tmp++)
- writeAttr(tmp, tmp);
- readb(par->io_virt + CRT + 0x0A); /* flip-flop to index */
- t_outb(0x20, 0x3C0); /* enable attr */
+ writeAttr(par, tmp, tmp);
+ fb_readb(par->io_virt + VGA_IS1_RC); /* flip-flop to index */
+ t_outb(par, 0x20, VGA_ATT_W); /* enable attr */
switch (bpp) {
case 8:
tmp = 0;
break;
- case 15:
- tmp = 0x10;
- break;
case 16:
tmp = 0x30;
break;
@@ -1063,19 +1216,23 @@ static int tridentfb_set_par(struct fb_info *info)
break;
}
- t_inb(0x3C8);
- t_inb(0x3C6);
- t_inb(0x3C6);
- t_inb(0x3C6);
- t_inb(0x3C6);
- t_outb(tmp, 0x3C6);
- t_inb(0x3C8);
-
- if (flatpanel)
- set_number_of_lines(info->var.yres);
- set_lwidth(info->var.xres * bpp / (4 * 16));
+ t_inb(par, VGA_PEL_IW);
+ t_inb(par, VGA_PEL_MSK);
+ t_inb(par, VGA_PEL_MSK);
+ t_inb(par, VGA_PEL_MSK);
+ t_inb(par, VGA_PEL_MSK);
+ t_outb(par, tmp, VGA_PEL_MSK);
+ t_inb(par, VGA_PEL_IW);
+
+ if (par->flatpanel)
+ set_number_of_lines(par, info->var.yres);
+ info->fix.line_length = info->var.xres_virtual * bpp / 8;
+ set_lwidth(par, info->fix.line_length / 8);
+
+ if (!(info->flags & FBINFO_HWACCEL_DISABLED))
+ par->init_accel(par, info->var.xres_virtual, bpp);
+
info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
- info->fix.line_length = info->var.xres * (bpp >> 3);
info->cmap.len = (bpp == 8) ? 256 : 16;
debug("exit\n");
return 0;
@@ -1087,17 +1244,18 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
struct fb_info *info)
{
int bpp = info->var.bits_per_pixel;
+ struct tridentfb_par *par = info->par;
if (regno >= info->cmap.len)
return 1;
if (bpp == 8) {
- t_outb(0xFF, 0x3C6);
- t_outb(regno, 0x3C8);
+ t_outb(par, 0xFF, VGA_PEL_MSK);
+ t_outb(par, regno, VGA_PEL_IW);
- t_outb(red >> 10, 0x3C9);
- t_outb(green >> 10, 0x3C9);
- t_outb(blue >> 10, 0x3C9);
+ t_outb(par, red >> 10, VGA_PEL_D);
+ t_outb(par, green >> 10, VGA_PEL_D);
+ t_outb(par, blue >> 10, VGA_PEL_D);
} else if (regno < 16) {
if (bpp == 16) { /* RGB 565 */
@@ -1108,28 +1266,28 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
col |= col << 16;
((u32 *)(info->pseudo_palette))[regno] = col;
} else if (bpp == 32) /* ARGB 8888 */
- ((u32*)info->pseudo_palette)[regno] =
+ ((u32 *)info->pseudo_palette)[regno] =
((transp & 0xFF00) << 16) |
((red & 0xFF00) << 8) |
((green & 0xFF00)) |
((blue & 0xFF00) >> 8);
}
-/* debug("exit\n"); */
return 0;
}
-/* Try blanking the screen.For flat panels it does nothing */
+/* Try blanking the screen. For flat panels it does nothing */
static int tridentfb_blank(int blank_mode, struct fb_info *info)
{
unsigned char PMCont, DPMSCont;
+ struct tridentfb_par *par = info->par;
debug("enter\n");
- if (flatpanel)
+ if (par->flatpanel)
return 0;
- t_outb(0x04, 0x83C8); /* Read DPMS Control */
- PMCont = t_inb(0x83C6) & 0xFC;
- DPMSCont = read3CE(PowerStatus) & 0xFC;
+ t_outb(par, 0x04, 0x83C8); /* Read DPMS Control */
+ PMCont = t_inb(par, 0x83C6) & 0xFC;
+ DPMSCont = read3CE(par, PowerStatus) & 0xFC;
switch (blank_mode) {
case FB_BLANK_UNBLANK:
/* Screen: On, HSync: On, VSync: On */
@@ -1155,9 +1313,9 @@ static int tridentfb_blank(int blank_mode, struct fb_info *info)
break;
}
- write3CE(PowerStatus, DPMSCont);
- t_outb(4, 0x83C8);
- t_outb(PMCont, 0x83C6);
+ write3CE(par, PowerStatus, DPMSCont);
+ t_outb(par, 4, 0x83C8);
+ t_outb(par, PMCont, 0x83C6);
debug("exit\n");
@@ -1174,33 +1332,46 @@ static struct fb_ops tridentfb_ops = {
.fb_set_par = tridentfb_set_par,
.fb_fillrect = tridentfb_fillrect,
.fb_copyarea = tridentfb_copyarea,
- .fb_imageblit = cfb_imageblit,
+ .fb_imageblit = tridentfb_imageblit,
+#ifdef CONFIG_FB_TRIDENT_ACCEL
+ .fb_sync = tridentfb_sync,
+#endif
};
-static int __devinit trident_pci_probe(struct pci_dev * dev,
- const struct pci_device_id * id)
+static int __devinit trident_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
{
int err;
unsigned char revision;
+ struct fb_info *info;
+ struct tridentfb_par *default_par;
+ int chip3D;
+ int chip_id;
err = pci_enable_device(dev);
if (err)
return err;
- chip_id = id->device;
+ info = framebuffer_alloc(sizeof(struct tridentfb_par), &dev->dev);
+ if (!info)
+ return -ENOMEM;
+ default_par = info->par;
- if (chip_id == CYBERBLADEi1)
- output("*** Please do use cyblafb, Cyberblade/i1 support "
- "will soon be removed from tridentfb!\n");
+ chip_id = id->device;
+#ifndef CONFIG_FB_TRIDENT_ACCEL
+ noaccel = 1;
+#endif
/* If PCI id is 0x9660 then further detect chip type */
if (chip_id == TGUI9660) {
- outb(RevisionID, 0x3C4);
- revision = inb(0x3C5);
+ revision = vga_io_rseq(RevisionID);
switch (revision) {
+ case 0x21:
+ chip_id = PROVIDIA9685;
+ break;
case 0x22:
case 0x23:
chip_id = CYBER9397;
@@ -1229,123 +1400,170 @@ static int __devinit trident_pci_probe(struct pci_dev * dev,
}
chip3D = is3Dchip(chip_id);
- chipcyber = iscyber(chip_id);
if (is_xp(chip_id)) {
- acc = &accel_xp;
+ default_par->init_accel = xp_init_accel;
+ default_par->wait_engine = xp_wait_engine;
+ default_par->fill_rect = xp_fill_rect;
+ default_par->copy_rect = xp_copy_rect;
+ tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADEXP;
} else if (is_blade(chip_id)) {
- acc = &accel_blade;
- } else {
- acc = &accel_image;
+ default_par->init_accel = blade_init_accel;
+ default_par->wait_engine = blade_wait_engine;
+ default_par->fill_rect = blade_fill_rect;
+ default_par->copy_rect = blade_copy_rect;
+ default_par->image_blit = blade_image_blit;
+ tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADE3D;
+ } else if (chip3D) { /* 3DImage family left */
+ default_par->init_accel = image_init_accel;
+ default_par->wait_engine = image_wait_engine;
+ default_par->fill_rect = image_fill_rect;
+ default_par->copy_rect = image_copy_rect;
+ tridentfb_fix.accel = FB_ACCEL_TRIDENT_3DIMAGE;
+ } else { /* TGUI 9440/96XX family */
+ default_par->init_accel = tgui_init_accel;
+ default_par->wait_engine = xp_wait_engine;
+ default_par->fill_rect = tgui_fill_rect;
+ default_par->copy_rect = tgui_copy_rect;
+ tridentfb_fix.accel = FB_ACCEL_TRIDENT_TGUI;
}
- /* acceleration is on by default for 3D chips */
- defaultaccel = chip3D && !noaccel;
-
- fb_info.par = &default_par;
+ default_par->chip_id = chip_id;
/* setup MMIO region */
tridentfb_fix.mmio_start = pci_resource_start(dev, 1);
- tridentfb_fix.mmio_len = chip3D ? 0x20000 : 0x10000;
+ tridentfb_fix.mmio_len = pci_resource_len(dev, 1);
- if (!request_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len, "tridentfb")) {
+ if (!request_mem_region(tridentfb_fix.mmio_start,
+ tridentfb_fix.mmio_len, "tridentfb")) {
debug("request_region failed!\n");
+ framebuffer_release(info);
return -1;
}
- default_par.io_virt = ioremap_nocache(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
+ default_par->io_virt = ioremap_nocache(tridentfb_fix.mmio_start,
+ tridentfb_fix.mmio_len);
- if (!default_par.io_virt) {
+ if (!default_par->io_virt) {
debug("ioremap failed\n");
err = -1;
goto out_unmap1;
}
- enable_mmio();
+ enable_mmio(default_par);
/* setup framebuffer memory */
tridentfb_fix.smem_start = pci_resource_start(dev, 0);
- tridentfb_fix.smem_len = get_memsize();
+ tridentfb_fix.smem_len = get_memsize(default_par);
- if (!request_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len, "tridentfb")) {
+ if (!request_mem_region(tridentfb_fix.smem_start,
+ tridentfb_fix.smem_len, "tridentfb")) {
debug("request_mem_region failed!\n");
- disable_mmio();
+ disable_mmio(info->par);
err = -1;
goto out_unmap1;
}
- fb_info.screen_base = ioremap_nocache(tridentfb_fix.smem_start,
- tridentfb_fix.smem_len);
+ info->screen_base = ioremap_nocache(tridentfb_fix.smem_start,
+ tridentfb_fix.smem_len);
- if (!fb_info.screen_base) {
+ if (!info->screen_base) {
debug("ioremap failed\n");
err = -1;
goto out_unmap2;
}
- output("%s board found\n", pci_name(dev));
- displaytype = get_displaytype();
+ default_par->flatpanel = is_flatpanel(default_par);
- if (flatpanel)
- nativex = get_nativex();
+ if (default_par->flatpanel)
+ nativex = get_nativex(default_par);
- fb_info.fix = tridentfb_fix;
- fb_info.fbops = &tridentfb_ops;
+ info->fix = tridentfb_fix;
+ info->fbops = &tridentfb_ops;
+ info->pseudo_palette = default_par->pseudo_pal;
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+ if (!noaccel && default_par->init_accel) {
+ info->flags &= ~FBINFO_HWACCEL_DISABLED;
+ info->flags |= FBINFO_HWACCEL_COPYAREA;
+ info->flags |= FBINFO_HWACCEL_FILLRECT;
+ } else
+ info->flags |= FBINFO_HWACCEL_DISABLED;
- fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-#ifdef CONFIG_FB_TRIDENT_ACCEL
- fb_info.flags |= FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
-#endif
- fb_info.pseudo_palette = pseudo_pal;
+ info->pixmap.addr = kmalloc(4096, GFP_KERNEL);
+ if (!info->pixmap.addr) {
+ err = -ENOMEM;
+ goto out_unmap2;
+ }
+
+ info->pixmap.size = 4096;
+ info->pixmap.buf_align = 4;
+ info->pixmap.scan_align = 1;
+ info->pixmap.access_align = 32;
+ info->pixmap.flags = FB_PIXMAP_SYSTEM;
- if (!fb_find_mode(&default_var, &fb_info,
+ if (default_par->image_blit) {
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT;
+ info->pixmap.scan_align = 4;
+ }
+
+ if (noaccel) {
+ printk(KERN_DEBUG "disabling acceleration\n");
+ info->flags |= FBINFO_HWACCEL_DISABLED;
+ info->pixmap.scan_align = 1;
+ }
+
+ if (!fb_find_mode(&info->var, info,
mode_option, NULL, 0, NULL, bpp)) {
err = -EINVAL;
goto out_unmap2;
}
- err = fb_alloc_cmap(&fb_info.cmap, 256, 0);
+ err = fb_alloc_cmap(&info->cmap, 256, 0);
if (err < 0)
goto out_unmap2;
- if (defaultaccel && acc)
- default_var.accel_flags |= FB_ACCELF_TEXT;
- else
- default_var.accel_flags &= ~FB_ACCELF_TEXT;
- default_var.activate |= FB_ACTIVATE_NOW;
- fb_info.var = default_var;
- fb_info.device = &dev->dev;
- if (register_framebuffer(&fb_info) < 0) {
- printk(KERN_ERR "tridentfb: could not register Trident framebuffer\n");
- fb_dealloc_cmap(&fb_info.cmap);
+ info->var.activate |= FB_ACTIVATE_NOW;
+ info->device = &dev->dev;
+ if (register_framebuffer(info) < 0) {
+ printk(KERN_ERR "tridentfb: could not register framebuffer\n");
+ fb_dealloc_cmap(&info->cmap);
err = -EINVAL;
goto out_unmap2;
}
output("fb%d: %s frame buffer device %dx%d-%dbpp\n",
- fb_info.node, fb_info.fix.id, default_var.xres,
- default_var.yres, default_var.bits_per_pixel);
+ info->node, info->fix.id, info->var.xres,
+ info->var.yres, info->var.bits_per_pixel);
+
+ pci_set_drvdata(dev, info);
return 0;
out_unmap2:
- if (fb_info.screen_base)
- iounmap(fb_info.screen_base);
+ kfree(info->pixmap.addr);
+ if (info->screen_base)
+ iounmap(info->screen_base);
release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
- disable_mmio();
+ disable_mmio(info->par);
out_unmap1:
- if (default_par.io_virt)
- iounmap(default_par.io_virt);
+ if (default_par->io_virt)
+ iounmap(default_par->io_virt);
release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
+ framebuffer_release(info);
return err;
}
static void __devexit trident_pci_remove(struct pci_dev *dev)
{
- struct tridentfb_par *par = (struct tridentfb_par*)fb_info.par;
- unregister_framebuffer(&fb_info);
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct tridentfb_par *par = info->par;
+
+ unregister_framebuffer(info);
iounmap(par->io_virt);
- iounmap(fb_info.screen_base);
+ iounmap(info->screen_base);
release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
+ pci_set_drvdata(dev, NULL);
+ kfree(info->pixmap.addr);
+ framebuffer_release(info);
}
/* List of boards that we are trying to support */
@@ -1358,6 +1576,7 @@ static struct pci_device_id trident_devices[] = {
{PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_TRIDENT, CYBERBLADEE4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, TGUI9440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_TRIDENT, TGUI9660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_TRIDENT, IMAGE975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_TRIDENT, IMAGE985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -1399,9 +1618,9 @@ static int __init tridentfb_setup(char *options)
if (!strncmp(opt, "noaccel", 7))
noaccel = 1;
else if (!strncmp(opt, "fp", 2))
- displaytype = DISPLAY_FP;
+ fp = 1;
else if (!strncmp(opt, "crt", 3))
- displaytype = DISPLAY_CRT;
+ fp = 0;
else if (!strncmp(opt, "bpp=", 4))
bpp = simple_strtoul(opt + 4, NULL, 0);
else if (!strncmp(opt, "center", 6))
@@ -1430,7 +1649,6 @@ static int __init tridentfb_init(void)
return -ENODEV;
tridentfb_setup(option);
#endif
- output("Trident framebuffer %s initializing\n", VERSION);
return pci_register_driver(&tridentfb_pci_driver);
}
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index cdbb56edb6c..50744229c7a 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -2054,8 +2054,8 @@ MODULE_PARM_DESC(maxhf,
module_param(maxvf, ushort, 0);
MODULE_PARM_DESC(maxvf,
"Maximum vertical frequency [Hz], overrides EDID data");
-module_param_named(mode, mode_option, charp, 0);
-MODULE_PARM_DESC(mode,
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option,
"Specify initial video mode as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");
module_param(vbemode, ushort, 0);
MODULE_PARM_DESC(vbemode,
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 072638a9528..93fe08d6c78 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -443,19 +443,29 @@ static int vfb_mmap(struct fb_info *info,
}
#ifndef MODULE
+/*
+ * The virtual framebuffer driver is only enabled if explicitly
+ * requested by passing 'video=vfb:' (or any actual options).
+ */
static int __init vfb_setup(char *options)
{
char *this_opt;
+ vfb_enable = 0;
+
+ if (!options)
+ return 1;
+
vfb_enable = 1;
- if (!options || !*options)
+ if (!*options)
return 1;
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt)
continue;
- if (!strncmp(this_opt, "disable", 7))
+ /* Test disable for backwards compatibility */
+ if (!strcmp(this_opt, "disable"))
vfb_enable = 0;
}
return 1;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 9b3c5923365..e31bca8a0cb 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -26,18 +26,6 @@
#include <asm/io.h>
#include <video/vga.h>
-#define GRAPHICS_ADDR_REG VGA_GFX_I /* Graphics address register. */
-#define GRAPHICS_DATA_REG VGA_GFX_D /* Graphics data register. */
-
-#define SET_RESET_INDEX VGA_GFX_SR_VALUE /* Set/Reset Register index. */
-#define ENABLE_SET_RESET_INDEX VGA_GFX_SR_ENABLE /* Enable Set/Reset Register index. */
-#define DATA_ROTATE_INDEX VGA_GFX_DATA_ROTATE /* Data Rotate Register index. */
-#define GRAPHICS_MODE_INDEX VGA_GFX_MODE /* Graphics Mode Register index. */
-#define BIT_MASK_INDEX VGA_GFX_BIT_MASK /* Bit Mask Register index. */
-
-#define dac_reg (VGA_PEL_IW)
-#define dac_val (VGA_PEL_D)
-
#define VGA_FB_PHYS 0xA0000
#define VGA_FB_PHYS_LEN 65536
@@ -108,7 +96,7 @@ static struct fb_fix_screeninfo vga16fb_fix __initdata = {
.visual = FB_VISUAL_PSEUDOCOLOR,
.xpanstep = 8,
.ypanstep = 1,
- .line_length = 640/8,
+ .line_length = 640 / 8,
.accel = FB_ACCEL_NONE
};
@@ -135,23 +123,22 @@ static inline int setmode(int mode)
{
int oldmode;
- vga_io_w(GRAPHICS_ADDR_REG, GRAPHICS_MODE_INDEX);
- oldmode = vga_io_r(GRAPHICS_DATA_REG);
- vga_io_w(GRAPHICS_DATA_REG, mode);
+ oldmode = vga_io_rgfx(VGA_GFX_MODE);
+ vga_io_w(VGA_GFX_D, mode);
return oldmode;
}
/* Select the Bit Mask Register and return its value. */
static inline int selectmask(void)
{
- return vga_io_rgfx(BIT_MASK_INDEX);
+ return vga_io_rgfx(VGA_GFX_BIT_MASK);
}
/* Set the value of the Bit Mask Register. It must already have been
selected with selectmask(). */
static inline void setmask(int mask)
{
- vga_io_w(GRAPHICS_DATA_REG, mask);
+ vga_io_w(VGA_GFX_D, mask);
}
/* Set the Data Rotate Register and return its old value.
@@ -161,9 +148,8 @@ static inline int setop(int op)
{
int oldop;
- vga_io_w(GRAPHICS_ADDR_REG, DATA_ROTATE_INDEX);
- oldop = vga_io_r(GRAPHICS_DATA_REG);
- vga_io_w(GRAPHICS_DATA_REG, op);
+ oldop = vga_io_rgfx(VGA_GFX_DATA_ROTATE);
+ vga_io_w(VGA_GFX_D, op);
return oldop;
}
@@ -173,9 +159,8 @@ static inline int setsr(int sr)
{
int oldsr;
- vga_io_w(GRAPHICS_ADDR_REG, ENABLE_SET_RESET_INDEX);
- oldsr = vga_io_r(GRAPHICS_DATA_REG);
- vga_io_w(GRAPHICS_DATA_REG, sr);
+ oldsr = vga_io_rgfx(VGA_GFX_SR_ENABLE);
+ vga_io_w(VGA_GFX_D, sr);
return oldsr;
}
@@ -184,22 +169,21 @@ static inline int setcolor(int color)
{
int oldcolor;
- vga_io_w(GRAPHICS_ADDR_REG, SET_RESET_INDEX);
- oldcolor = vga_io_r(GRAPHICS_DATA_REG);
- vga_io_w(GRAPHICS_DATA_REG, color);
+ oldcolor = vga_io_rgfx(VGA_GFX_SR_VALUE);
+ vga_io_w(VGA_GFX_D, color);
return oldcolor;
}
/* Return the value in the Graphics Address Register. */
static inline int getindex(void)
{
- return vga_io_r(GRAPHICS_ADDR_REG);
+ return vga_io_r(VGA_GFX_I);
}
/* Set the value in the Graphics Address Register. */
static inline void setindex(int index)
{
- vga_io_w(GRAPHICS_ADDR_REG, index);
+ vga_io_w(VGA_GFX_I, index);
}
static void vga16fb_pan_var(struct fb_info *info,
@@ -672,10 +656,10 @@ static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned b
static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
{
- outb(regno, dac_reg);
- outb(red >> 10, dac_val);
- outb(green >> 10, dac_val);
- outb(blue >> 10, dac_val);
+ outb(regno, VGA_PEL_IW);
+ outb(red >> 10, VGA_PEL_D);
+ outb(green >> 10, VGA_PEL_D);
+ outb(blue >> 10, VGA_PEL_D);
}
static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -719,28 +703,15 @@ static int vga16fb_pan_display(struct fb_var_screeninfo *var,
blanking code was originally by Huang shi chao, and modified by
Christoph Rimek (chrimek@toppoint.de) and todd j. derr
(tjd@barefoot.org) for Linux. */
-#define attrib_port VGA_ATC_IW
-#define seq_port_reg VGA_SEQ_I
-#define seq_port_val VGA_SEQ_D
-#define gr_port_reg VGA_GFX_I
-#define gr_port_val VGA_GFX_D
-#define video_misc_rd VGA_MIS_R
-#define video_misc_wr VGA_MIS_W
-#define vga_video_port_reg VGA_CRT_IC
-#define vga_video_port_val VGA_CRT_DC
static void vga_vesa_blank(struct vga16fb_par *par, int mode)
{
- unsigned char SeqCtrlIndex;
- unsigned char CrtCtrlIndex;
+ unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
+ unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
- //cli();
- SeqCtrlIndex = vga_io_r(seq_port_reg);
- CrtCtrlIndex = vga_io_r(vga_video_port_reg);
-
/* save original values of VGA controller registers */
if(!par->vesa_blanked) {
- par->vga_state.CrtMiscIO = vga_io_r(video_misc_rd);
+ par->vga_state.CrtMiscIO = vga_io_r(VGA_MIS_R);
//sti();
par->vga_state.HorizontalTotal = vga_io_rcrt(0x00); /* HorizontalTotal */
@@ -756,12 +727,11 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
/* assure that video is enabled */
/* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
- //cli();
vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20);
/* test for vertical retrace in process.... */
if ((par->vga_state.CrtMiscIO & 0x80) == 0x80)
- vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO & 0xef);
+ vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO & 0xef);
/*
* Set <End of vertical retrace> to minimum (0) and
@@ -769,12 +739,10 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
* Result: turn off vertical sync (VSync) pulse.
*/
if (mode & FB_BLANK_VSYNC_SUSPEND) {
- outb_p(0x10,vga_video_port_reg); /* StartVertRetrace */
- outb_p(0xff,vga_video_port_val); /* maximum value */
- outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */
- outb_p(0x40,vga_video_port_val); /* minimum (bits 0..3) */
- outb_p(0x07,vga_video_port_reg); /* Overflow */
- outb_p(par->vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */
+ vga_io_wcrt(VGA_CRTC_V_SYNC_START, 0xff);
+ vga_io_wcrt(VGA_CRTC_V_SYNC_END, 0x40);
+ /* bits 9,10 of vert. retrace */
+ vga_io_wcrt(VGA_CRTC_OVERFLOW, par->vga_state.Overflow | 0x84);
}
if (mode & FB_BLANK_HSYNC_SUSPEND) {
@@ -783,29 +751,22 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
* <Start of horizontal Retrace> to maximum
* Result: turn off horizontal sync (HSync) pulse.
*/
- outb_p(0x04,vga_video_port_reg); /* StartHorizRetrace */
- outb_p(0xff,vga_video_port_val); /* maximum */
- outb_p(0x05,vga_video_port_reg); /* EndHorizRetrace */
- outb_p(0x00,vga_video_port_val); /* minimum (0) */
+ vga_io_wcrt(VGA_CRTC_H_SYNC_START, 0xff);
+ vga_io_wcrt(VGA_CRTC_H_SYNC_END, 0x00);
}
/* restore both index registers */
- outb_p(SeqCtrlIndex,seq_port_reg);
- outb_p(CrtCtrlIndex,vga_video_port_reg);
- //sti();
+ outb_p(SeqCtrlIndex, VGA_SEQ_I);
+ outb_p(CrtCtrlIndex, VGA_CRT_IC);
}
static void vga_vesa_unblank(struct vga16fb_par *par)
{
- unsigned char SeqCtrlIndex;
- unsigned char CrtCtrlIndex;
+ unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
+ unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
- //cli();
- SeqCtrlIndex = vga_io_r(seq_port_reg);
- CrtCtrlIndex = vga_io_r(vga_video_port_reg);
-
/* restore original values of VGA controller registers */
- vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO);
+ vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO);
/* HorizontalTotal */
vga_io_wcrt(0x00, par->vga_state.HorizontalTotal);
@@ -827,9 +788,8 @@ static void vga_vesa_unblank(struct vga16fb_par *par)
vga_io_wseq(0x01, par->vga_state.ClockingMode);
/* restore index/control registers */
- vga_io_w(seq_port_reg, SeqCtrlIndex);
- vga_io_w(vga_video_port_reg, CrtCtrlIndex);
- //sti();
+ vga_io_w(VGA_SEQ_I, SeqCtrlIndex);
+ vga_io_w(VGA_CRT_IC, CrtCtrlIndex);
}
static void vga_pal_blank(void)
@@ -837,10 +797,10 @@ static void vga_pal_blank(void)
int i;
for (i=0; i<16; i++) {
- outb_p (i, dac_reg) ;
- outb_p (0, dac_val) ;
- outb_p (0, dac_val) ;
- outb_p (0, dac_val) ;
+ outb_p(i, VGA_PEL_IW);
+ outb_p(0, VGA_PEL_D);
+ outb_p(0, VGA_PEL_D);
+ outb_p(0, VGA_PEL_D);
}
}
@@ -1087,12 +1047,15 @@ static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *are
width = x2 - dx;
height = y2 - dy;
+ if (sx + dx < old_dx || sy + dy < old_dy)
+ return;
+
/* update sx1,sy1 */
sx += (dx - old_dx);
sy += (dy - old_dy);
/* the source must be completely inside the virtual screen */
- if (sx < 0 || sy < 0 || (sx + width) > vxres || (sy + height) > vyres)
+ if (sx + width > vxres || sy + height > vyres)
return;
switch (info->fix.type) {
@@ -1482,6 +1445,7 @@ static void __exit vga16fb_exit(void)
platform_driver_unregister(&vga16fb_driver);
}
+MODULE_DESCRIPTION("Legacy VGA framebuffer device driver");
MODULE_LICENSE("GPL");
module_init(vga16fb_init);
module_exit(vga16fb_exit);
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index 7084e7e146c..5b78fd0aff0 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -71,13 +71,6 @@ static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env)
dev->id.device, dev->id.vendor);
}
-static struct bus_type virtio_bus = {
- .name = "virtio",
- .match = virtio_dev_match,
- .dev_attrs = virtio_dev_attrs,
- .uevent = virtio_uevent,
-};
-
static void add_status(struct virtio_device *dev, unsigned status)
{
dev->config->set_status(dev, dev->config->get_status(dev) | status);
@@ -120,12 +113,16 @@ static int virtio_dev_probe(struct device *_d)
set_bit(f, dev->features);
}
+ /* Transport features always preserved to pass to finalize_features. */
+ for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++)
+ if (device_features & (1 << i))
+ set_bit(i, dev->features);
+
err = drv->probe(dev);
if (err)
add_status(dev, VIRTIO_CONFIG_S_FAILED);
else {
- /* They should never have set feature bits beyond 32 */
- dev->config->set_features(dev, dev->features[0]);
+ dev->config->finalize_features(dev);
add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
}
return err;
@@ -147,13 +144,20 @@ static int virtio_dev_remove(struct device *_d)
return 0;
}
+static struct bus_type virtio_bus = {
+ .name = "virtio",
+ .match = virtio_dev_match,
+ .dev_attrs = virtio_dev_attrs,
+ .uevent = virtio_uevent,
+ .probe = virtio_dev_probe,
+ .remove = virtio_dev_remove,
+};
+
int register_virtio_driver(struct virtio_driver *driver)
{
/* Catch this early. */
BUG_ON(driver->feature_table_size && !driver->feature_table);
driver->driver.bus = &virtio_bus;
- driver->driver.probe = virtio_dev_probe;
- driver->driver.remove = virtio_dev_remove;
return driver_register(&driver->driver);
}
EXPORT_SYMBOL_GPL(register_virtio_driver);
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index eae7236310e..c7dc37c7cce 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -94,12 +94,17 @@ static u32 vp_get_features(struct virtio_device *vdev)
return ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES);
}
-/* virtio config->set_features() implementation */
-static void vp_set_features(struct virtio_device *vdev, u32 features)
+/* virtio config->finalize_features() implementation */
+static void vp_finalize_features(struct virtio_device *vdev)
{
struct virtio_pci_device *vp_dev = to_vp_device(vdev);
- iowrite32(features, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES);
+ /* Give virtio_ring a chance to accept features. */
+ vring_transport_features(vdev);
+
+ /* We only support 32 feature bits. */
+ BUILD_BUG_ON(ARRAY_SIZE(vdev->features) != 1);
+ iowrite32(vdev->features[0], vp_dev->ioaddr+VIRTIO_PCI_GUEST_FEATURES);
}
/* virtio config->get() implementation */
@@ -297,7 +302,7 @@ static struct virtio_config_ops virtio_pci_config_ops = {
.find_vq = vp_find_vq,
.del_vq = vp_del_vq,
.get_features = vp_get_features,
- .set_features = vp_set_features,
+ .finalize_features = vp_finalize_features,
};
/* the PCI probing function */
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 72bf8bc0901..6eb5303fed1 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -18,6 +18,7 @@
*/
#include <linux/virtio.h>
#include <linux/virtio_ring.h>
+#include <linux/virtio_config.h>
#include <linux/device.h>
#ifdef DEBUG
@@ -87,8 +88,11 @@ static int vring_add_buf(struct virtqueue *_vq,
if (vq->num_free < out + in) {
pr_debug("Can't add buf len %i - avail = %i\n",
out + in, vq->num_free);
- /* We notify *even if* VRING_USED_F_NO_NOTIFY is set here. */
- vq->notify(&vq->vq);
+ /* FIXME: for historical reasons, we force a notify here if
+ * there are outgoing parts to the buffer. Presumably the
+ * host should service the ring ASAP. */
+ if (out)
+ vq->notify(&vq->vq);
END_USE(vq);
return -ENOSPC;
}
@@ -320,4 +324,19 @@ void vring_del_virtqueue(struct virtqueue *vq)
}
EXPORT_SYMBOL_GPL(vring_del_virtqueue);
+/* Manipulates transport-specific feature bits. */
+void vring_transport_features(struct virtio_device *vdev)
+{
+ unsigned int i;
+
+ for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++) {
+ switch (i) {
+ default:
+ /* We don't understand this bit. */
+ clear_bit(i, vdev->features);
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(vring_transport_features);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index ccb78f66c2b..48399e134c0 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -788,8 +788,6 @@ config WATCHDOG_RIO
machines. The watchdog timeout period is normally one minute but
can be changed with a boot-time parameter.
-# V850 Architecture
-
# XTENSA Architecture
#
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 25b352b664d..edd305a64e6 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -119,8 +119,6 @@ obj-$(CONFIG_SH_WDT) += shwdt.o
# SPARC64 Architecture
-# V850 Architecture
-
# XTENSA Architecture
# Architecture Independant
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index 591bc29b55f..d4427cb8697 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -610,6 +610,7 @@ static ssize_t show_target_kb(struct sys_device *dev, char *buf)
}
static ssize_t store_target_kb(struct sys_device *dev,
+ struct sysdev_attribute *attr,
const char *buf,
size_t count)
{
diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c
index 3da712cc770..5290552d2ef 100644
--- a/drivers/zorro/zorro-sysfs.c
+++ b/drivers/zorro/zorro-sysfs.c
@@ -15,7 +15,6 @@
#include <linux/zorro.h>
#include <linux/stat.h>
#include <linux/string.h>
-#include <linux/fs.h>
#include "zorro.h"
diff --git a/fs/Kconfig b/fs/Kconfig
index 37db79a2ff9..97e3bdedb1e 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -902,65 +902,7 @@ endif # BLOCK
menu "Pseudo filesystems"
-config PROC_FS
- bool "/proc file system support" if EMBEDDED
- default y
- help
- This is a virtual file system providing information about the status
- of the system. "Virtual" means that it doesn't take up any space on
- your hard disk: the files are created on the fly by the kernel when
- you try to access them. Also, you cannot read the files with older
- version of the program less: you need to use more or cat.
-
- It's totally cool; for example, "cat /proc/interrupts" gives
- information about what the different IRQs are used for at the moment
- (there is a small number of Interrupt ReQuest lines in your computer
- that are used by the attached devices to gain the CPU's attention --
- often a source of trouble if two devices are mistakenly configured
- to use the same IRQ). The program procinfo to display some
- information about your system gathered from the /proc file system.
-
- Before you can use the /proc file system, it has to be mounted,
- meaning it has to be given a location in the directory hierarchy.
- That location should be /proc. A command such as "mount -t proc proc
- /proc" or the equivalent line in /etc/fstab does the job.
-
- The /proc file system is explained in the file
- <file:Documentation/filesystems/proc.txt> and on the proc(5) manpage
- ("man 5 proc").
-
- This option will enlarge your kernel by about 67 KB. Several
- programs depend on this, so everyone should say Y here.
-
-config PROC_KCORE
- bool "/proc/kcore support" if !ARM
- depends on PROC_FS && MMU
-
-config PROC_VMCORE
- bool "/proc/vmcore support (EXPERIMENTAL)"
- depends on PROC_FS && CRASH_DUMP
- default y
- help
- Exports the dump image of crashed kernel in ELF format.
-
-config PROC_SYSCTL
- bool "Sysctl support (/proc/sys)" if EMBEDDED
- depends on PROC_FS
- select SYSCTL
- default y
- ---help---
- The sysctl interface provides a means of dynamically changing
- certain kernel parameters and variables on the fly without requiring
- a recompile of the kernel or reboot of the system. The primary
- interface is through /proc/sys. If you say Y here a tree of
- modifiable sysctl entries will be generated beneath the
- /proc/sys directory. They are explained in the files
- in <file:Documentation/sysctl/>. Note that enabling this
- option will enlarge the kernel by at least 8 KB.
-
- As it is generally a good thing, you should say Y here unless
- building a kernel for install/rescue disks or your system is very
- limited in memory.
+source "fs/proc/Kconfig"
config SYSFS
bool "sysfs file system support" if EMBEDDED
@@ -2093,20 +2035,6 @@ config CODA_FS
To compile the coda client support as a module, choose M here: the
module will be called coda.
-config CODA_FS_OLD_API
- bool "Use 96-bit Coda file identifiers"
- depends on CODA_FS
- help
- A new kernel-userspace API had to be introduced for Coda v6.0
- to support larger 128-bit file identifiers as needed by the
- new realms implementation.
-
- However this new API is not backward compatible with older
- clients. If you really need to run the old Coda userspace
- cache manager then say Y.
-
- For most cases you probably want to say N.
-
config AFS_FS
tristate "Andrew File System support (AFS) (EXPERIMENTAL)"
depends on INET && EXPERIMENTAL
diff --git a/fs/aio.c b/fs/aio.c
index 0fb3117ddd9..0051fd94b44 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -586,7 +586,6 @@ static void use_mm(struct mm_struct *mm)
struct task_struct *tsk = current;
task_lock(tsk);
- tsk->flags |= PF_BORROWED_MM;
active_mm = tsk->active_mm;
atomic_inc(&mm->mm_count);
tsk->mm = mm;
@@ -610,7 +609,6 @@ static void unuse_mm(struct mm_struct *mm)
struct task_struct *tsk = current;
task_lock(tsk);
- tsk->flags &= ~PF_BORROWED_MM;
tsk->mm = NULL;
/* active_mm is still 'mm' */
enter_lazy_tlb(mm, tsk);
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 977ef208c05..3662dd44896 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -58,8 +58,9 @@ static struct dentry_operations anon_inodefs_dentry_operations = {
* of the file
*
* @name: [in] name of the "class" of the new file
- * @fops [in] file operations for the new file
- * @priv [in] private data for the new file (will be file's private_data)
+ * @fops: [in] file operations for the new file
+ * @priv: [in] private data for the new file (will be file's private_data)
+ * @flags: [in] flags
*
* Creates a new file by hooking it on a single inode. This is useful for files
* that do not need to have a full-fledged inode in order to operate correctly.
@@ -68,7 +69,7 @@ static struct dentry_operations anon_inodefs_dentry_operations = {
* setup. Returns new descriptor or -error.
*/
int anon_inode_getfd(const char *name, const struct file_operations *fops,
- void *priv)
+ void *priv, int flags)
{
struct qstr this;
struct dentry *dentry;
@@ -78,7 +79,7 @@ int anon_inode_getfd(const char *name, const struct file_operations *fops,
if (IS_ERR(anon_inode_inode))
return -ENODEV;
- error = get_unused_fd();
+ error = get_unused_fd_flags(flags);
if (error < 0)
return error;
fd = error;
@@ -115,7 +116,7 @@ int anon_inode_getfd(const char *name, const struct file_operations *fops,
file->f_mapping = anon_inode_inode->i_mapping;
file->f_pos = 0;
- file->f_flags = O_RDWR;
+ file->f_flags = O_RDWR | (flags & O_NONBLOCK);
file->f_version = 0;
file->private_data = priv;
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index c3d352d7fa9..69a2f5c9231 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -52,7 +52,10 @@ struct autofs_info {
int flags;
- struct list_head rehash;
+ struct completion expire_complete;
+
+ struct list_head active;
+ struct list_head expiring;
struct autofs_sb_info *sbi;
unsigned long last_used;
@@ -68,15 +71,14 @@ struct autofs_info {
};
#define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */
+#define AUTOFS_INF_MOUNTPOINT (1<<1) /* mountpoint status for direct expire */
struct autofs_wait_queue {
wait_queue_head_t queue;
struct autofs_wait_queue *next;
autofs_wqt_t wait_queue_token;
/* We use the following to see what we are waiting for */
- unsigned int hash;
- unsigned int len;
- char *name;
+ struct qstr name;
u32 dev;
u64 ino;
uid_t uid;
@@ -85,7 +87,7 @@ struct autofs_wait_queue {
pid_t tgid;
/* This is for status reporting upon return */
int status;
- atomic_t wait_ctr;
+ unsigned int wait_ctr;
};
#define AUTOFS_SBI_MAGIC 0x6d4a556d
@@ -112,8 +114,9 @@ struct autofs_sb_info {
struct mutex wq_mutex;
spinlock_t fs_lock;
struct autofs_wait_queue *queues; /* Wait queue pointer */
- spinlock_t rehash_lock;
- struct list_head rehash_list;
+ spinlock_t lookup_lock;
+ struct list_head active_list;
+ struct list_head expiring_list;
};
static inline struct autofs_sb_info *autofs4_sbi(struct super_block *sb)
@@ -138,18 +141,14 @@ static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) {
static inline int autofs4_ispending(struct dentry *dentry)
{
struct autofs_info *inf = autofs4_dentry_ino(dentry);
- int pending = 0;
if (dentry->d_flags & DCACHE_AUTOFS_PENDING)
return 1;
- if (inf) {
- spin_lock(&inf->sbi->fs_lock);
- pending = inf->flags & AUTOFS_INF_EXPIRING;
- spin_unlock(&inf->sbi->fs_lock);
- }
+ if (inf->flags & AUTOFS_INF_EXPIRING)
+ return 1;
- return pending;
+ return 0;
}
static inline void autofs4_copy_atime(struct file *src, struct file *dst)
@@ -164,6 +163,7 @@ void autofs4_free_ino(struct autofs_info *);
/* Expiration */
int is_autofs4_dentry(struct dentry *);
+int autofs4_expire_wait(struct dentry *dentry);
int autofs4_expire_run(struct super_block *, struct vfsmount *,
struct autofs_sb_info *,
struct autofs_packet_expire __user *);
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 894fee54d4d..cdabb796ff0 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -259,13 +259,15 @@ static struct dentry *autofs4_expire_direct(struct super_block *sb,
now = jiffies;
timeout = sbi->exp_timeout;
- /* Lock the tree as we must expire as a whole */
spin_lock(&sbi->fs_lock);
if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
struct autofs_info *ino = autofs4_dentry_ino(root);
-
- /* Set this flag early to catch sys_chdir and the like */
+ if (d_mountpoint(root)) {
+ ino->flags |= AUTOFS_INF_MOUNTPOINT;
+ root->d_mounted--;
+ }
ino->flags |= AUTOFS_INF_EXPIRING;
+ init_completion(&ino->expire_complete);
spin_unlock(&sbi->fs_lock);
return root;
}
@@ -292,6 +294,8 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb,
struct list_head *next;
int do_now = how & AUTOFS_EXP_IMMEDIATE;
int exp_leaves = how & AUTOFS_EXP_LEAVES;
+ struct autofs_info *ino;
+ unsigned int ino_count;
if (!root)
return NULL;
@@ -316,6 +320,9 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb,
dentry = dget(dentry);
spin_unlock(&dcache_lock);
+ spin_lock(&sbi->fs_lock);
+ ino = autofs4_dentry_ino(dentry);
+
/*
* Case 1: (i) indirect mount or top level pseudo direct mount
* (autofs-4.1).
@@ -326,6 +333,11 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb,
DPRINTK("checking mountpoint %p %.*s",
dentry, (int)dentry->d_name.len, dentry->d_name.name);
+ /* Path walk currently on this dentry? */
+ ino_count = atomic_read(&ino->count) + 2;
+ if (atomic_read(&dentry->d_count) > ino_count)
+ goto next;
+
/* Can we umount this guy */
if (autofs4_mount_busy(mnt, dentry))
goto next;
@@ -343,23 +355,25 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb,
/* Case 2: tree mount, expire iff entire tree is not busy */
if (!exp_leaves) {
- /* Lock the tree as we must expire as a whole */
- spin_lock(&sbi->fs_lock);
- if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
- struct autofs_info *inf = autofs4_dentry_ino(dentry);
+ /* Path walk currently on this dentry? */
+ ino_count = atomic_read(&ino->count) + 1;
+ if (atomic_read(&dentry->d_count) > ino_count)
+ goto next;
- /* Set this flag early to catch sys_chdir and the like */
- inf->flags |= AUTOFS_INF_EXPIRING;
- spin_unlock(&sbi->fs_lock);
+ if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
expired = dentry;
goto found;
}
- spin_unlock(&sbi->fs_lock);
/*
* Case 3: pseudo direct mount, expire individual leaves
* (autofs-4.1).
*/
} else {
+ /* Path walk currently on this dentry? */
+ ino_count = atomic_read(&ino->count) + 1;
+ if (atomic_read(&dentry->d_count) > ino_count)
+ goto next;
+
expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
if (expired) {
dput(dentry);
@@ -367,6 +381,7 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb,
}
}
next:
+ spin_unlock(&sbi->fs_lock);
dput(dentry);
spin_lock(&dcache_lock);
next = next->next;
@@ -377,12 +392,45 @@ next:
found:
DPRINTK("returning %p %.*s",
expired, (int)expired->d_name.len, expired->d_name.name);
+ ino = autofs4_dentry_ino(expired);
+ ino->flags |= AUTOFS_INF_EXPIRING;
+ init_completion(&ino->expire_complete);
+ spin_unlock(&sbi->fs_lock);
spin_lock(&dcache_lock);
list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
spin_unlock(&dcache_lock);
return expired;
}
+int autofs4_expire_wait(struct dentry *dentry)
+{
+ struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ struct autofs_info *ino = autofs4_dentry_ino(dentry);
+ int status;
+
+ /* Block on any pending expire */
+ spin_lock(&sbi->fs_lock);
+ if (ino->flags & AUTOFS_INF_EXPIRING) {
+ spin_unlock(&sbi->fs_lock);
+
+ DPRINTK("waiting for expire %p name=%.*s",
+ dentry, dentry->d_name.len, dentry->d_name.name);
+
+ status = autofs4_wait(sbi, dentry, NFY_NONE);
+ wait_for_completion(&ino->expire_complete);
+
+ DPRINTK("expire done status=%d", status);
+
+ if (d_unhashed(dentry))
+ return -EAGAIN;
+
+ return status;
+ }
+ spin_unlock(&sbi->fs_lock);
+
+ return 0;
+}
+
/* Perform an expiry operation */
int autofs4_expire_run(struct super_block *sb,
struct vfsmount *mnt,
@@ -390,7 +438,9 @@ int autofs4_expire_run(struct super_block *sb,
struct autofs_packet_expire __user *pkt_p)
{
struct autofs_packet_expire pkt;
+ struct autofs_info *ino;
struct dentry *dentry;
+ int ret = 0;
memset(&pkt,0,sizeof pkt);
@@ -406,9 +456,15 @@ int autofs4_expire_run(struct super_block *sb,
dput(dentry);
if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) )
- return -EFAULT;
+ ret = -EFAULT;
- return 0;
+ spin_lock(&sbi->fs_lock);
+ ino = autofs4_dentry_ino(dentry);
+ ino->flags &= ~AUTOFS_INF_EXPIRING;
+ complete_all(&ino->expire_complete);
+ spin_unlock(&sbi->fs_lock);
+
+ return ret;
}
/* Call repeatedly until it returns -EAGAIN, meaning there's nothing
@@ -433,9 +489,16 @@ int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
/* This is synchronous because it makes the daemon a
little easier */
- ino->flags |= AUTOFS_INF_EXPIRING;
ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);
+
+ spin_lock(&sbi->fs_lock);
+ if (ino->flags & AUTOFS_INF_MOUNTPOINT) {
+ sb->s_root->d_mounted++;
+ ino->flags &= ~AUTOFS_INF_MOUNTPOINT;
+ }
ino->flags &= ~AUTOFS_INF_EXPIRING;
+ complete_all(&ino->expire_complete);
+ spin_unlock(&sbi->fs_lock);
dput(dentry);
}
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 2fdcf5e1d23..7bb3e5ba053 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -24,8 +24,10 @@
static void ino_lnkfree(struct autofs_info *ino)
{
- kfree(ino->u.symlink);
- ino->u.symlink = NULL;
+ if (ino->u.symlink) {
+ kfree(ino->u.symlink);
+ ino->u.symlink = NULL;
+ }
}
struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
@@ -41,16 +43,18 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
if (ino == NULL)
return NULL;
- ino->flags = 0;
- ino->mode = mode;
- ino->inode = NULL;
- ino->dentry = NULL;
- ino->size = 0;
-
- INIT_LIST_HEAD(&ino->rehash);
+ if (!reinit) {
+ ino->flags = 0;
+ ino->inode = NULL;
+ ino->dentry = NULL;
+ ino->size = 0;
+ INIT_LIST_HEAD(&ino->active);
+ INIT_LIST_HEAD(&ino->expiring);
+ atomic_set(&ino->count, 0);
+ }
+ ino->mode = mode;
ino->last_used = jiffies;
- atomic_set(&ino->count, 0);
ino->sbi = sbi;
@@ -159,8 +163,8 @@ void autofs4_kill_sb(struct super_block *sb)
if (!sbi)
goto out_kill_sb;
- if (!sbi->catatonic)
- autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */
+ /* Free wait queues, close pipe */
+ autofs4_catatonic_mode(sbi);
/* Clean up and release dangling references */
autofs4_force_release(sbi);
@@ -338,8 +342,9 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
mutex_init(&sbi->wq_mutex);
spin_lock_init(&sbi->fs_lock);
sbi->queues = NULL;
- spin_lock_init(&sbi->rehash_lock);
- INIT_LIST_HEAD(&sbi->rehash_list);
+ spin_lock_init(&sbi->lookup_lock);
+ INIT_LIST_HEAD(&sbi->active_list);
+ INIT_LIST_HEAD(&sbi->expiring_list);
s->s_blocksize = 1024;
s->s_blocksize_bits = 10;
s->s_magic = AUTOFS_SUPER_MAGIC;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index edf5b6bddb5..bcfb2dc0a61 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -25,25 +25,25 @@ static int autofs4_dir_rmdir(struct inode *,struct dentry *);
static int autofs4_dir_mkdir(struct inode *,struct dentry *,int);
static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
static int autofs4_dir_open(struct inode *inode, struct file *file);
-static int autofs4_dir_close(struct inode *inode, struct file *file);
-static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir);
-static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir);
static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
static void *autofs4_follow_link(struct dentry *, struct nameidata *);
+#define TRIGGER_FLAGS (LOOKUP_CONTINUE | LOOKUP_DIRECTORY)
+#define TRIGGER_INTENTS (LOOKUP_OPEN | LOOKUP_CREATE)
+
const struct file_operations autofs4_root_operations = {
.open = dcache_dir_open,
.release = dcache_dir_close,
.read = generic_read_dir,
- .readdir = autofs4_root_readdir,
+ .readdir = dcache_readdir,
.ioctl = autofs4_root_ioctl,
};
const struct file_operations autofs4_dir_operations = {
.open = autofs4_dir_open,
- .release = autofs4_dir_close,
+ .release = dcache_dir_close,
.read = generic_read_dir,
- .readdir = autofs4_dir_readdir,
+ .readdir = dcache_readdir,
};
const struct inode_operations autofs4_indirect_root_inode_operations = {
@@ -70,42 +70,10 @@ const struct inode_operations autofs4_dir_inode_operations = {
.rmdir = autofs4_dir_rmdir,
};
-static int autofs4_root_readdir(struct file *file, void *dirent,
- filldir_t filldir)
-{
- struct autofs_sb_info *sbi = autofs4_sbi(file->f_path.dentry->d_sb);
- int oz_mode = autofs4_oz_mode(sbi);
-
- DPRINTK("called, filp->f_pos = %lld", file->f_pos);
-
- /*
- * Don't set reghost flag if:
- * 1) f_pos is larger than zero -- we've already been here.
- * 2) we haven't even enabled reghosting in the 1st place.
- * 3) this is the daemon doing a readdir
- */
- if (oz_mode && file->f_pos == 0 && sbi->reghost_enabled)
- sbi->needs_reghost = 1;
-
- DPRINTK("needs_reghost = %d", sbi->needs_reghost);
-
- return dcache_readdir(file, dirent, filldir);
-}
-
static int autofs4_dir_open(struct inode *inode, struct file *file)
{
struct dentry *dentry = file->f_path.dentry;
- struct vfsmount *mnt = file->f_path.mnt;
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
- struct dentry *cursor;
- int status;
-
- status = dcache_dir_open(inode, file);
- if (status)
- goto out;
-
- cursor = file->private_data;
- cursor->d_fsdata = NULL;
DPRINTK("file=%p dentry=%p %.*s",
file, dentry, dentry->d_name.len, dentry->d_name.name);
@@ -113,159 +81,32 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
if (autofs4_oz_mode(sbi))
goto out;
- if (autofs4_ispending(dentry)) {
- DPRINTK("dentry busy");
- dcache_dir_close(inode, file);
- status = -EBUSY;
- goto out;
- }
-
- status = -ENOENT;
- if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) {
- struct nameidata nd;
- int empty, ret;
-
- /* In case there are stale directory dentrys from a failed mount */
- spin_lock(&dcache_lock);
- empty = list_empty(&dentry->d_subdirs);
+ /*
+ * An empty directory in an autofs file system is always a
+ * mount point. The daemon must have failed to mount this
+ * during lookup so it doesn't exist. This can happen, for
+ * example, if user space returns an incorrect status for a
+ * mount request. Otherwise we're doing a readdir on the
+ * autofs file system so just let the libfs routines handle
+ * it.
+ */
+ spin_lock(&dcache_lock);
+ if (!d_mountpoint(dentry) && __simple_empty(dentry)) {
spin_unlock(&dcache_lock);
-
- if (!empty)
- d_invalidate(dentry);
-
- nd.flags = LOOKUP_DIRECTORY;
- ret = (dentry->d_op->d_revalidate)(dentry, &nd);
-
- if (ret <= 0) {
- if (ret < 0)
- status = ret;
- dcache_dir_close(inode, file);
- goto out;
- }
+ return -ENOENT;
}
+ spin_unlock(&dcache_lock);
- if (d_mountpoint(dentry)) {
- struct file *fp = NULL;
- struct path fp_path = { .dentry = dentry, .mnt = mnt };
-
- path_get(&fp_path);
-
- if (!autofs4_follow_mount(&fp_path.mnt, &fp_path.dentry)) {
- path_put(&fp_path);
- dcache_dir_close(inode, file);
- goto out;
- }
-
- fp = dentry_open(fp_path.dentry, fp_path.mnt, file->f_flags);
- status = PTR_ERR(fp);
- if (IS_ERR(fp)) {
- dcache_dir_close(inode, file);
- goto out;
- }
- cursor->d_fsdata = fp;
- }
- return 0;
-out:
- return status;
-}
-
-static int autofs4_dir_close(struct inode *inode, struct file *file)
-{
- struct dentry *dentry = file->f_path.dentry;
- struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
- struct dentry *cursor = file->private_data;
- int status = 0;
-
- DPRINTK("file=%p dentry=%p %.*s",
- file, dentry, dentry->d_name.len, dentry->d_name.name);
-
- if (autofs4_oz_mode(sbi))
- goto out;
-
- if (autofs4_ispending(dentry)) {
- DPRINTK("dentry busy");
- status = -EBUSY;
- goto out;
- }
-
- if (d_mountpoint(dentry)) {
- struct file *fp = cursor->d_fsdata;
- if (!fp) {
- status = -ENOENT;
- goto out;
- }
- filp_close(fp, current->files);
- }
-out:
- dcache_dir_close(inode, file);
- return status;
-}
-
-static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir)
-{
- struct dentry *dentry = file->f_path.dentry;
- struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
- struct dentry *cursor = file->private_data;
- int status;
-
- DPRINTK("file=%p dentry=%p %.*s",
- file, dentry, dentry->d_name.len, dentry->d_name.name);
-
- if (autofs4_oz_mode(sbi))
- goto out;
-
- if (autofs4_ispending(dentry)) {
- DPRINTK("dentry busy");
- return -EBUSY;
- }
-
- if (d_mountpoint(dentry)) {
- struct file *fp = cursor->d_fsdata;
-
- if (!fp)
- return -ENOENT;
-
- if (!fp->f_op || !fp->f_op->readdir)
- goto out;
-
- status = vfs_readdir(fp, filldir, dirent);
- file->f_pos = fp->f_pos;
- if (status)
- autofs4_copy_atime(file, fp);
- return status;
- }
out:
- return dcache_readdir(file, dirent, filldir);
+ return dcache_dir_open(inode, file);
}
static int try_to_fill_dentry(struct dentry *dentry, int flags)
{
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
- struct dentry *new;
int status;
- /* Block on any pending expiry here; invalidate the dentry
- when expiration is done to trigger mount request with a new
- dentry */
- if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) {
- DPRINTK("waiting for expire %p name=%.*s",
- dentry, dentry->d_name.len, dentry->d_name.name);
-
- status = autofs4_wait(sbi, dentry, NFY_NONE);
-
- DPRINTK("expire done status=%d", status);
-
- /*
- * If the directory still exists the mount request must
- * continue otherwise it can't be followed at the right
- * time during the walk.
- */
- status = d_invalidate(dentry);
- if (status != -EBUSY)
- return -EAGAIN;
- }
-
DPRINTK("dentry=%p %.*s ino=%p",
dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
@@ -292,7 +133,8 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)
return status;
}
/* Trigger mount for path component or follow link */
- } else if (flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) ||
+ } else if (dentry->d_flags & DCACHE_AUTOFS_PENDING ||
+ flags & (TRIGGER_FLAGS | TRIGGER_INTENTS) ||
current->link_count) {
DPRINTK("waiting for mount name=%.*s",
dentry->d_name.len, dentry->d_name.name);
@@ -320,26 +162,6 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags)
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
spin_unlock(&dentry->d_lock);
- /*
- * The dentry that is passed in from lookup may not be the one
- * we end up using, as mkdir can create a new one. If this
- * happens, and another process tries the lookup at the same time,
- * it will set the PENDING flag on this new dentry, but add itself
- * to our waitq. Then, if after the lookup succeeds, the first
- * process that requested the mount performs another lookup of the
- * same directory, it will show up as still pending! So, we need
- * to redo the lookup here and clear pending on that dentry.
- */
- if (d_unhashed(dentry)) {
- new = d_lookup(dentry->d_parent, &dentry->d_name);
- if (new) {
- spin_lock(&new->d_lock);
- new->d_flags &= ~DCACHE_AUTOFS_PENDING;
- spin_unlock(&new->d_lock);
- dput(new);
- }
- }
-
return 0;
}
@@ -355,51 +177,63 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
DPRINTK("dentry=%p %.*s oz_mode=%d nd->flags=%d",
dentry, dentry->d_name.len, dentry->d_name.name, oz_mode,
nd->flags);
-
- /* If it's our master or we shouldn't trigger a mount we're done */
- lookup_type = nd->flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY);
- if (oz_mode || !lookup_type)
+ /*
+ * For an expire of a covered direct or offset mount we need
+ * to beeak out of follow_down() at the autofs mount trigger
+ * (d_mounted--), so we can see the expiring flag, and manage
+ * the blocking and following here until the expire is completed.
+ */
+ if (oz_mode) {
+ spin_lock(&sbi->fs_lock);
+ if (ino->flags & AUTOFS_INF_EXPIRING) {
+ spin_unlock(&sbi->fs_lock);
+ /* Follow down to our covering mount. */
+ if (!follow_down(&nd->path.mnt, &nd->path.dentry))
+ goto done;
+ goto follow;
+ }
+ spin_unlock(&sbi->fs_lock);
goto done;
+ }
- /* If an expire request is pending wait for it. */
- if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) {
- DPRINTK("waiting for active request %p name=%.*s",
- dentry, dentry->d_name.len, dentry->d_name.name);
-
- status = autofs4_wait(sbi, dentry, NFY_NONE);
+ /* If an expire request is pending everyone must wait. */
+ autofs4_expire_wait(dentry);
- DPRINTK("request done status=%d", status);
- }
+ /* We trigger a mount for almost all flags */
+ lookup_type = nd->flags & (TRIGGER_FLAGS | TRIGGER_INTENTS);
+ if (!(lookup_type || dentry->d_flags & DCACHE_AUTOFS_PENDING))
+ goto follow;
/*
- * If the dentry contains directories then it is an
- * autofs multi-mount with no root mount offset. So
- * don't try to mount it again.
+ * If the dentry contains directories then it is an autofs
+ * multi-mount with no root mount offset. So don't try to
+ * mount it again.
*/
spin_lock(&dcache_lock);
- if (!d_mountpoint(dentry) && __simple_empty(dentry)) {
+ if (dentry->d_flags & DCACHE_AUTOFS_PENDING ||
+ (!d_mountpoint(dentry) && __simple_empty(dentry))) {
spin_unlock(&dcache_lock);
status = try_to_fill_dentry(dentry, 0);
if (status)
goto out_error;
- /*
- * The mount succeeded but if there is no root mount
- * it must be an autofs multi-mount with no root offset
- * so we don't need to follow the mount.
- */
- if (d_mountpoint(dentry)) {
- if (!autofs4_follow_mount(&nd->path.mnt,
- &nd->path.dentry)) {
- status = -ENOENT;
- goto out_error;
- }
- }
-
- goto done;
+ goto follow;
}
spin_unlock(&dcache_lock);
+follow:
+ /*
+ * If there is no root mount it must be an autofs
+ * multi-mount with no root offset so we don't need
+ * to follow it.
+ */
+ if (d_mountpoint(dentry)) {
+ if (!autofs4_follow_mount(&nd->path.mnt,
+ &nd->path.dentry)) {
+ status = -ENOENT;
+ goto out_error;
+ }
+ }
done:
return NULL;
@@ -424,12 +258,23 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
int status = 1;
/* Pending dentry */
+ spin_lock(&sbi->fs_lock);
if (autofs4_ispending(dentry)) {
/* The daemon never causes a mount to trigger */
+ spin_unlock(&sbi->fs_lock);
+
if (oz_mode)
return 1;
/*
+ * If the directory has gone away due to an expire
+ * we have been called as ->d_revalidate() and so
+ * we need to return false and proceed to ->lookup().
+ */
+ if (autofs4_expire_wait(dentry) == -EAGAIN)
+ return 0;
+
+ /*
* A zero status is success otherwise we have a
* negative error code.
*/
@@ -437,17 +282,9 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
if (status == 0)
return 1;
- /*
- * A status of EAGAIN here means that the dentry has gone
- * away while waiting for an expire to complete. If we are
- * racing with expire lookup will wait for it so this must
- * be a revalidate and we need to send it to lookup.
- */
- if (status == -EAGAIN)
- return 0;
-
return status;
}
+ spin_unlock(&sbi->fs_lock);
/* Negative dentry.. invalidate if "old" */
if (dentry->d_inode == NULL)
@@ -461,6 +298,7 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
DPRINTK("dentry=%p %.*s, emptydir",
dentry, dentry->d_name.len, dentry->d_name.name);
spin_unlock(&dcache_lock);
+
/* The daemon never causes a mount to trigger */
if (oz_mode)
return 1;
@@ -493,10 +331,12 @@ void autofs4_dentry_release(struct dentry *de)
struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb);
if (sbi) {
- spin_lock(&sbi->rehash_lock);
- if (!list_empty(&inf->rehash))
- list_del(&inf->rehash);
- spin_unlock(&sbi->rehash_lock);
+ spin_lock(&sbi->lookup_lock);
+ if (!list_empty(&inf->active))
+ list_del(&inf->active);
+ if (!list_empty(&inf->expiring))
+ list_del(&inf->expiring);
+ spin_unlock(&sbi->lookup_lock);
}
inf->dentry = NULL;
@@ -518,7 +358,7 @@ static struct dentry_operations autofs4_dentry_operations = {
.d_release = autofs4_dentry_release,
};
-static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name)
+static struct dentry *autofs4_lookup_active(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name)
{
unsigned int len = name->len;
unsigned int hash = name->hash;
@@ -526,14 +366,66 @@ static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct
struct list_head *p, *head;
spin_lock(&dcache_lock);
- spin_lock(&sbi->rehash_lock);
- head = &sbi->rehash_list;
+ spin_lock(&sbi->lookup_lock);
+ head = &sbi->active_list;
list_for_each(p, head) {
struct autofs_info *ino;
struct dentry *dentry;
struct qstr *qstr;
- ino = list_entry(p, struct autofs_info, rehash);
+ ino = list_entry(p, struct autofs_info, active);
+ dentry = ino->dentry;
+
+ spin_lock(&dentry->d_lock);
+
+ /* Already gone? */
+ if (atomic_read(&dentry->d_count) == 0)
+ goto next;
+
+ qstr = &dentry->d_name;
+
+ if (dentry->d_name.hash != hash)
+ goto next;
+ if (dentry->d_parent != parent)
+ goto next;
+
+ if (qstr->len != len)
+ goto next;
+ if (memcmp(qstr->name, str, len))
+ goto next;
+
+ if (d_unhashed(dentry)) {
+ dget(dentry);
+ spin_unlock(&dentry->d_lock);
+ spin_unlock(&sbi->lookup_lock);
+ spin_unlock(&dcache_lock);
+ return dentry;
+ }
+next:
+ spin_unlock(&dentry->d_lock);
+ }
+ spin_unlock(&sbi->lookup_lock);
+ spin_unlock(&dcache_lock);
+
+ return NULL;
+}
+
+static struct dentry *autofs4_lookup_expiring(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name)
+{
+ unsigned int len = name->len;
+ unsigned int hash = name->hash;
+ const unsigned char *str = name->name;
+ struct list_head *p, *head;
+
+ spin_lock(&dcache_lock);
+ spin_lock(&sbi->lookup_lock);
+ head = &sbi->expiring_list;
+ list_for_each(p, head) {
+ struct autofs_info *ino;
+ struct dentry *dentry;
+ struct qstr *qstr;
+
+ ino = list_entry(p, struct autofs_info, expiring);
dentry = ino->dentry;
spin_lock(&dentry->d_lock);
@@ -555,33 +447,16 @@ static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct
goto next;
if (d_unhashed(dentry)) {
- struct inode *inode = dentry->d_inode;
-
- ino = autofs4_dentry_ino(dentry);
- list_del_init(&ino->rehash);
dget(dentry);
- /*
- * Make the rehashed dentry negative so the VFS
- * behaves as it should.
- */
- if (inode) {
- dentry->d_inode = NULL;
- list_del_init(&dentry->d_alias);
- spin_unlock(&dentry->d_lock);
- spin_unlock(&sbi->rehash_lock);
- spin_unlock(&dcache_lock);
- iput(inode);
- return dentry;
- }
spin_unlock(&dentry->d_lock);
- spin_unlock(&sbi->rehash_lock);
+ spin_unlock(&sbi->lookup_lock);
spin_unlock(&dcache_lock);
return dentry;
}
next:
spin_unlock(&dentry->d_lock);
}
- spin_unlock(&sbi->rehash_lock);
+ spin_unlock(&sbi->lookup_lock);
spin_unlock(&dcache_lock);
return NULL;
@@ -591,7 +466,8 @@ next:
static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct autofs_sb_info *sbi;
- struct dentry *unhashed;
+ struct autofs_info *ino;
+ struct dentry *expiring, *unhashed;
int oz_mode;
DPRINTK("name = %.*s",
@@ -607,8 +483,26 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d",
current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode);
- unhashed = autofs4_lookup_unhashed(sbi, dentry->d_parent, &dentry->d_name);
- if (!unhashed) {
+ expiring = autofs4_lookup_expiring(sbi, dentry->d_parent, &dentry->d_name);
+ if (expiring) {
+ /*
+ * If we are racing with expire the request might not
+ * be quite complete but the directory has been removed
+ * so it must have been successful, so just wait for it.
+ */
+ ino = autofs4_dentry_ino(expiring);
+ autofs4_expire_wait(expiring);
+ spin_lock(&sbi->lookup_lock);
+ if (!list_empty(&ino->expiring))
+ list_del_init(&ino->expiring);
+ spin_unlock(&sbi->lookup_lock);
+ dput(expiring);
+ }
+
+ unhashed = autofs4_lookup_active(sbi, dentry->d_parent, &dentry->d_name);
+ if (unhashed)
+ dentry = unhashed;
+ else {
/*
* Mark the dentry incomplete but don't hash it. We do this
* to serialize our inode creation operations (symlink and
@@ -622,39 +516,34 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
*/
dentry->d_op = &autofs4_root_dentry_operations;
- dentry->d_fsdata = NULL;
- d_instantiate(dentry, NULL);
- } else {
- struct autofs_info *ino = autofs4_dentry_ino(unhashed);
- DPRINTK("rehash %p with %p", dentry, unhashed);
/*
- * If we are racing with expire the request might not
- * be quite complete but the directory has been removed
- * so it must have been successful, so just wait for it.
- * We need to ensure the AUTOFS_INF_EXPIRING flag is clear
- * before continuing as revalidate may fail when calling
- * try_to_fill_dentry (returning EAGAIN) if we don't.
+ * And we need to ensure that the same dentry is used for
+ * all following lookup calls until it is hashed so that
+ * the dentry flags are persistent throughout the request.
*/
- while (ino && (ino->flags & AUTOFS_INF_EXPIRING)) {
- DPRINTK("wait for incomplete expire %p name=%.*s",
- unhashed, unhashed->d_name.len,
- unhashed->d_name.name);
- autofs4_wait(sbi, unhashed, NFY_NONE);
- DPRINTK("request completed");
- }
- dentry = unhashed;
+ ino = autofs4_init_ino(NULL, sbi, 0555);
+ if (!ino)
+ return ERR_PTR(-ENOMEM);
+
+ dentry->d_fsdata = ino;
+ ino->dentry = dentry;
+
+ spin_lock(&sbi->lookup_lock);
+ list_add(&ino->active, &sbi->active_list);
+ spin_unlock(&sbi->lookup_lock);
+
+ d_instantiate(dentry, NULL);
}
if (!oz_mode) {
spin_lock(&dentry->d_lock);
dentry->d_flags |= DCACHE_AUTOFS_PENDING;
spin_unlock(&dentry->d_lock);
- }
-
- if (dentry->d_op && dentry->d_op->d_revalidate) {
- mutex_unlock(&dir->i_mutex);
- (dentry->d_op->d_revalidate)(dentry, nd);
- mutex_lock(&dir->i_mutex);
+ if (dentry->d_op && dentry->d_op->d_revalidate) {
+ mutex_unlock(&dir->i_mutex);
+ (dentry->d_op->d_revalidate)(dentry, nd);
+ mutex_lock(&dir->i_mutex);
+ }
}
/*
@@ -673,9 +562,11 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
return ERR_PTR(-ERESTARTNOINTR);
}
}
- spin_lock(&dentry->d_lock);
- dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
- spin_unlock(&dentry->d_lock);
+ if (!oz_mode) {
+ spin_lock(&dentry->d_lock);
+ dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
+ spin_unlock(&dentry->d_lock);
+ }
}
/*
@@ -706,7 +597,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
}
if (unhashed)
- return dentry;
+ return unhashed;
return NULL;
}
@@ -728,20 +619,31 @@ static int autofs4_dir_symlink(struct inode *dir,
return -EACCES;
ino = autofs4_init_ino(ino, sbi, S_IFLNK | 0555);
- if (ino == NULL)
- return -ENOSPC;
+ if (!ino)
+ return -ENOMEM;
- ino->size = strlen(symname);
- ino->u.symlink = cp = kmalloc(ino->size + 1, GFP_KERNEL);
+ spin_lock(&sbi->lookup_lock);
+ if (!list_empty(&ino->active))
+ list_del_init(&ino->active);
+ spin_unlock(&sbi->lookup_lock);
- if (cp == NULL) {
- kfree(ino);
- return -ENOSPC;
+ ino->size = strlen(symname);
+ cp = kmalloc(ino->size + 1, GFP_KERNEL);
+ if (!cp) {
+ if (!dentry->d_fsdata)
+ kfree(ino);
+ return -ENOMEM;
}
strcpy(cp, symname);
inode = autofs4_get_inode(dir->i_sb, ino);
+ if (!inode) {
+ kfree(cp);
+ if (!dentry->d_fsdata)
+ kfree(ino);
+ return -ENOMEM;
+ }
d_add(dentry, inode);
if (dir == dir->i_sb->s_root->d_inode)
@@ -757,6 +659,7 @@ static int autofs4_dir_symlink(struct inode *dir,
atomic_inc(&p_ino->count);
ino->inode = inode;
+ ino->u.symlink = cp;
dir->i_mtime = CURRENT_TIME;
return 0;
@@ -769,9 +672,8 @@ static int autofs4_dir_symlink(struct inode *dir,
* that the file no longer exists. However, doing that means that the
* VFS layer can turn the dentry into a negative dentry. We don't want
* this, because the unlink is probably the result of an expire.
- * We simply d_drop it and add it to a rehash candidates list in the
- * super block, which allows the dentry lookup to reuse it retaining
- * the flags, such as expire in progress, in case we're racing with expire.
+ * We simply d_drop it and add it to a expiring list in the super block,
+ * which allows the dentry lookup to check for an incomplete expire.
*
* If a process is blocked on the dentry waiting for the expire to finish,
* it will invalidate the dentry and try to mount with a new one.
@@ -801,9 +703,10 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
dir->i_mtime = CURRENT_TIME;
spin_lock(&dcache_lock);
- spin_lock(&sbi->rehash_lock);
- list_add(&ino->rehash, &sbi->rehash_list);
- spin_unlock(&sbi->rehash_lock);
+ spin_lock(&sbi->lookup_lock);
+ if (list_empty(&ino->expiring))
+ list_add(&ino->expiring, &sbi->expiring_list);
+ spin_unlock(&sbi->lookup_lock);
spin_lock(&dentry->d_lock);
__d_drop(dentry);
spin_unlock(&dentry->d_lock);
@@ -829,9 +732,10 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
spin_unlock(&dcache_lock);
return -ENOTEMPTY;
}
- spin_lock(&sbi->rehash_lock);
- list_add(&ino->rehash, &sbi->rehash_list);
- spin_unlock(&sbi->rehash_lock);
+ spin_lock(&sbi->lookup_lock);
+ if (list_empty(&ino->expiring))
+ list_add(&ino->expiring, &sbi->expiring_list);
+ spin_unlock(&sbi->lookup_lock);
spin_lock(&dentry->d_lock);
__d_drop(dentry);
spin_unlock(&dentry->d_lock);
@@ -866,10 +770,20 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
dentry, dentry->d_name.len, dentry->d_name.name);
ino = autofs4_init_ino(ino, sbi, S_IFDIR | 0555);
- if (ino == NULL)
- return -ENOSPC;
+ if (!ino)
+ return -ENOMEM;
+
+ spin_lock(&sbi->lookup_lock);
+ if (!list_empty(&ino->active))
+ list_del_init(&ino->active);
+ spin_unlock(&sbi->lookup_lock);
inode = autofs4_get_inode(dir->i_sb, ino);
+ if (!inode) {
+ if (!dentry->d_fsdata)
+ kfree(ino);
+ return -ENOMEM;
+ }
d_add(dentry, inode);
if (dir == dir->i_sb->s_root->d_inode)
@@ -922,44 +836,6 @@ static inline int autofs4_get_protosubver(struct autofs_sb_info *sbi, int __user
}
/*
- * Tells the daemon whether we need to reghost or not. Also, clears
- * the reghost_needed flag.
- */
-static inline int autofs4_ask_reghost(struct autofs_sb_info *sbi, int __user *p)
-{
- int status;
-
- DPRINTK("returning %d", sbi->needs_reghost);
-
- status = put_user(sbi->needs_reghost, p);
- if (status)
- return status;
-
- sbi->needs_reghost = 0;
- return 0;
-}
-
-/*
- * Enable / Disable reghosting ioctl() operation
- */
-static inline int autofs4_toggle_reghost(struct autofs_sb_info *sbi, int __user *p)
-{
- int status;
- int val;
-
- status = get_user(val, p);
-
- DPRINTK("reghost = %d", val);
-
- if (status)
- return status;
-
- /* turn on/off reghosting, with the val */
- sbi->reghost_enabled = val;
- return 0;
-}
-
-/*
* Tells the daemon whether it can umount the autofs mount.
*/
static inline int autofs4_ask_umount(struct vfsmount *mnt, int __user *p)
@@ -1023,11 +899,6 @@ static int autofs4_root_ioctl(struct inode *inode, struct file *filp,
case AUTOFS_IOC_SETTIMEOUT:
return autofs4_get_set_timeout(sbi, p);
- case AUTOFS_IOC_TOGGLEREGHOST:
- return autofs4_toggle_reghost(sbi, p);
- case AUTOFS_IOC_ASKREGHOST:
- return autofs4_ask_reghost(sbi, p);
-
case AUTOFS_IOC_ASKUMOUNT:
return autofs4_ask_umount(filp->f_path.mnt, p);
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 75e5955c3f6..35216d18d8b 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -28,6 +28,12 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
{
struct autofs_wait_queue *wq, *nwq;
+ mutex_lock(&sbi->wq_mutex);
+ if (sbi->catatonic) {
+ mutex_unlock(&sbi->wq_mutex);
+ return;
+ }
+
DPRINTK("entering catatonic mode");
sbi->catatonic = 1;
@@ -36,13 +42,18 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
while (wq) {
nwq = wq->next;
wq->status = -ENOENT; /* Magic is gone - report failure */
- kfree(wq->name);
- wq->name = NULL;
+ if (wq->name.name) {
+ kfree(wq->name.name);
+ wq->name.name = NULL;
+ }
+ wq->wait_ctr--;
wake_up_interruptible(&wq->queue);
wq = nwq;
}
fput(sbi->pipe); /* Close the pipe */
sbi->pipe = NULL;
+ sbi->pipefd = -1;
+ mutex_unlock(&sbi->wq_mutex);
}
static int autofs4_write(struct file *file, const void *addr, int bytes)
@@ -89,10 +100,11 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
union autofs_packet_union v4_pkt;
union autofs_v5_packet_union v5_pkt;
} pkt;
+ struct file *pipe = NULL;
size_t pktsz;
DPRINTK("wait id = 0x%08lx, name = %.*s, type=%d",
- wq->wait_queue_token, wq->len, wq->name, type);
+ wq->wait_queue_token, wq->name.len, wq->name.name, type);
memset(&pkt,0,sizeof pkt); /* For security reasons */
@@ -107,9 +119,9 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
pktsz = sizeof(*mp);
mp->wait_queue_token = wq->wait_queue_token;
- mp->len = wq->len;
- memcpy(mp->name, wq->name, wq->len);
- mp->name[wq->len] = '\0';
+ mp->len = wq->name.len;
+ memcpy(mp->name, wq->name.name, wq->name.len);
+ mp->name[wq->name.len] = '\0';
break;
}
case autofs_ptype_expire_multi:
@@ -119,9 +131,9 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
pktsz = sizeof(*ep);
ep->wait_queue_token = wq->wait_queue_token;
- ep->len = wq->len;
- memcpy(ep->name, wq->name, wq->len);
- ep->name[wq->len] = '\0';
+ ep->len = wq->name.len;
+ memcpy(ep->name, wq->name.name, wq->name.len);
+ ep->name[wq->name.len] = '\0';
break;
}
/*
@@ -138,9 +150,9 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
pktsz = sizeof(*packet);
packet->wait_queue_token = wq->wait_queue_token;
- packet->len = wq->len;
- memcpy(packet->name, wq->name, wq->len);
- packet->name[wq->len] = '\0';
+ packet->len = wq->name.len;
+ memcpy(packet->name, wq->name.name, wq->name.len);
+ packet->name[wq->name.len] = '\0';
packet->dev = wq->dev;
packet->ino = wq->ino;
packet->uid = wq->uid;
@@ -154,8 +166,19 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
return;
}
- if (autofs4_write(sbi->pipe, &pkt, pktsz))
- autofs4_catatonic_mode(sbi);
+ /* Check if we have become catatonic */
+ mutex_lock(&sbi->wq_mutex);
+ if (!sbi->catatonic) {
+ pipe = sbi->pipe;
+ get_file(pipe);
+ }
+ mutex_unlock(&sbi->wq_mutex);
+
+ if (pipe) {
+ if (autofs4_write(pipe, &pkt, pktsz))
+ autofs4_catatonic_mode(sbi);
+ fput(pipe);
+ }
}
static int autofs4_getpath(struct autofs_sb_info *sbi,
@@ -191,58 +214,55 @@ static int autofs4_getpath(struct autofs_sb_info *sbi,
}
static struct autofs_wait_queue *
-autofs4_find_wait(struct autofs_sb_info *sbi,
- char *name, unsigned int hash, unsigned int len)
+autofs4_find_wait(struct autofs_sb_info *sbi, struct qstr *qstr)
{
struct autofs_wait_queue *wq;
for (wq = sbi->queues; wq; wq = wq->next) {
- if (wq->hash == hash &&
- wq->len == len &&
- wq->name && !memcmp(wq->name, name, len))
+ if (wq->name.hash == qstr->hash &&
+ wq->name.len == qstr->len &&
+ wq->name.name &&
+ !memcmp(wq->name.name, qstr->name, qstr->len))
break;
}
return wq;
}
-int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
- enum autofs_notify notify)
+/*
+ * Check if we have a valid request.
+ * Returns
+ * 1 if the request should continue.
+ * In this case we can return an autofs_wait_queue entry if one is
+ * found or NULL to idicate a new wait needs to be created.
+ * 0 or a negative errno if the request shouldn't continue.
+ */
+static int validate_request(struct autofs_wait_queue **wait,
+ struct autofs_sb_info *sbi,
+ struct qstr *qstr,
+ struct dentry*dentry, enum autofs_notify notify)
{
- struct autofs_info *ino;
struct autofs_wait_queue *wq;
- char *name;
- unsigned int len = 0;
- unsigned int hash = 0;
- int status, type;
-
- /* In catatonic mode, we don't wait for nobody */
- if (sbi->catatonic)
- return -ENOENT;
-
- name = kmalloc(NAME_MAX + 1, GFP_KERNEL);
- if (!name)
- return -ENOMEM;
+ struct autofs_info *ino;
- /* If this is a direct mount request create a dummy name */
- if (IS_ROOT(dentry) && (sbi->type & AUTOFS_TYPE_DIRECT))
- len = sprintf(name, "%p", dentry);
- else {
- len = autofs4_getpath(sbi, dentry, &name);
- if (!len) {
- kfree(name);
- return -ENOENT;
- }
+ /* Wait in progress, continue; */
+ wq = autofs4_find_wait(sbi, qstr);
+ if (wq) {
+ *wait = wq;
+ return 1;
}
- hash = full_name_hash(name, len);
- if (mutex_lock_interruptible(&sbi->wq_mutex)) {
- kfree(name);
- return -EINTR;
- }
+ *wait = NULL;
- wq = autofs4_find_wait(sbi, name, hash, len);
+ /* If we don't yet have any info this is a new request */
ino = autofs4_dentry_ino(dentry);
- if (!wq && ino && notify == NFY_NONE) {
+ if (!ino)
+ return 1;
+
+ /*
+ * If we've been asked to wait on an existing expire (NFY_NONE)
+ * but there is no wait in the queue ...
+ */
+ if (notify == NFY_NONE) {
/*
* Either we've betean the pending expire to post it's
* wait or it finished while we waited on the mutex.
@@ -253,13 +273,14 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
while (ino->flags & AUTOFS_INF_EXPIRING) {
mutex_unlock(&sbi->wq_mutex);
schedule_timeout_interruptible(HZ/10);
- if (mutex_lock_interruptible(&sbi->wq_mutex)) {
- kfree(name);
+ if (mutex_lock_interruptible(&sbi->wq_mutex))
return -EINTR;
+
+ wq = autofs4_find_wait(sbi, qstr);
+ if (wq) {
+ *wait = wq;
+ return 1;
}
- wq = autofs4_find_wait(sbi, name, hash, len);
- if (wq)
- break;
}
/*
@@ -267,18 +288,96 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
* cases where we wait on NFY_NONE neither depend on the
* return status of the wait.
*/
- if (!wq) {
+ return 0;
+ }
+
+ /*
+ * If we've been asked to trigger a mount and the request
+ * completed while we waited on the mutex ...
+ */
+ if (notify == NFY_MOUNT) {
+ /*
+ * If the dentry isn't hashed just go ahead and try the
+ * mount again with a new wait (not much else we can do).
+ */
+ if (!d_unhashed(dentry)) {
+ /*
+ * But if the dentry is hashed, that means that we
+ * got here through the revalidate path. Thus, we
+ * need to check if the dentry has been mounted
+ * while we waited on the wq_mutex. If it has,
+ * simply return success.
+ */
+ if (d_mountpoint(dentry))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
+ enum autofs_notify notify)
+{
+ struct autofs_wait_queue *wq;
+ struct qstr qstr;
+ char *name;
+ int status, ret, type;
+
+ /* In catatonic mode, we don't wait for nobody */
+ if (sbi->catatonic)
+ return -ENOENT;
+
+ if (!dentry->d_inode) {
+ /*
+ * A wait for a negative dentry is invalid for certain
+ * cases. A direct or offset mount "always" has its mount
+ * point directory created and so the request dentry must
+ * be positive or the map key doesn't exist. The situation
+ * is very similar for indirect mounts except only dentrys
+ * in the root of the autofs file system may be negative.
+ */
+ if (sbi->type & (AUTOFS_TYPE_DIRECT|AUTOFS_TYPE_OFFSET))
+ return -ENOENT;
+ else if (!IS_ROOT(dentry->d_parent))
+ return -ENOENT;
+ }
+
+ name = kmalloc(NAME_MAX + 1, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+
+ /* If this is a direct mount request create a dummy name */
+ if (IS_ROOT(dentry) && (sbi->type & AUTOFS_TYPE_DIRECT))
+ qstr.len = sprintf(name, "%p", dentry);
+ else {
+ qstr.len = autofs4_getpath(sbi, dentry, &name);
+ if (!qstr.len) {
kfree(name);
- mutex_unlock(&sbi->wq_mutex);
- return 0;
+ return -ENOENT;
}
}
+ qstr.name = name;
+ qstr.hash = full_name_hash(name, qstr.len);
+
+ if (mutex_lock_interruptible(&sbi->wq_mutex)) {
+ kfree(qstr.name);
+ return -EINTR;
+ }
+
+ ret = validate_request(&wq, sbi, &qstr, dentry, notify);
+ if (ret <= 0) {
+ if (ret == 0)
+ mutex_unlock(&sbi->wq_mutex);
+ kfree(qstr.name);
+ return ret;
+ }
if (!wq) {
/* Create a new wait queue */
wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
if (!wq) {
- kfree(name);
+ kfree(qstr.name);
mutex_unlock(&sbi->wq_mutex);
return -ENOMEM;
}
@@ -289,9 +388,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
wq->next = sbi->queues;
sbi->queues = wq;
init_waitqueue_head(&wq->queue);
- wq->hash = hash;
- wq->name = name;
- wq->len = len;
+ memcpy(&wq->name, &qstr, sizeof(struct qstr));
wq->dev = autofs4_get_dev(sbi);
wq->ino = autofs4_get_ino(sbi);
wq->uid = current->uid;
@@ -299,7 +396,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
wq->pid = current->pid;
wq->tgid = current->tgid;
wq->status = -EINTR; /* Status return if interrupted */
- atomic_set(&wq->wait_ctr, 2);
+ wq->wait_ctr = 2;
mutex_unlock(&sbi->wq_mutex);
if (sbi->version < 5) {
@@ -319,28 +416,25 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
}
DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n",
- (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
+ (unsigned long) wq->wait_queue_token, wq->name.len,
+ wq->name.name, notify);
/* autofs4_notify_daemon() may block */
autofs4_notify_daemon(sbi, wq, type);
} else {
- atomic_inc(&wq->wait_ctr);
+ wq->wait_ctr++;
mutex_unlock(&sbi->wq_mutex);
- kfree(name);
+ kfree(qstr.name);
DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
- (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
- }
-
- /* wq->name is NULL if and only if the lock is already released */
-
- if (sbi->catatonic) {
- /* We might have slept, so check again for catatonic mode */
- wq->status = -ENOENT;
- kfree(wq->name);
- wq->name = NULL;
+ (unsigned long) wq->wait_queue_token, wq->name.len,
+ wq->name.name, notify);
}
- if (wq->name) {
+ /*
+ * wq->name.name is NULL iff the lock is already released
+ * or the mount has been made catatonic.
+ */
+ if (wq->name.name) {
/* Block all but "shutdown" signals while waiting */
sigset_t oldset;
unsigned long irqflags;
@@ -351,7 +445,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
recalc_sigpending();
spin_unlock_irqrestore(&current->sighand->siglock, irqflags);
- wait_event_interruptible(wq->queue, wq->name == NULL);
+ wait_event_interruptible(wq->queue, wq->name.name == NULL);
spin_lock_irqsave(&current->sighand->siglock, irqflags);
current->blocked = oldset;
@@ -364,8 +458,10 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
status = wq->status;
/* Are we the last process to need status? */
- if (atomic_dec_and_test(&wq->wait_ctr))
+ mutex_lock(&sbi->wq_mutex);
+ if (!--wq->wait_ctr)
kfree(wq);
+ mutex_unlock(&sbi->wq_mutex);
return status;
}
@@ -387,16 +483,13 @@ int autofs4_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_tok
}
*wql = wq->next; /* Unlink from chain */
- mutex_unlock(&sbi->wq_mutex);
- kfree(wq->name);
- wq->name = NULL; /* Do not wait on this queue */
-
+ kfree(wq->name.name);
+ wq->name.name = NULL; /* Do not wait on this queue */
wq->status = status;
-
- if (atomic_dec_and_test(&wq->wait_ctr)) /* Is anyone still waiting for this guy? */
+ wake_up_interruptible(&wq->queue);
+ if (!--wq->wait_ctr)
kfree(wq);
- else
- wake_up_interruptible(&wq->queue);
+ mutex_unlock(&sbi->wq_mutex);
return 0;
}
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index d48ff5f370f..3b6ff854d98 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -131,6 +131,15 @@ static int padzero(unsigned long elf_bss)
#define STACK_ALLOC(sp, len) ({ sp -= len ; sp; })
#endif
+#ifndef ELF_BASE_PLATFORM
+/*
+ * AT_BASE_PLATFORM indicates the "real" hardware/microarchitecture.
+ * If the arch defines ELF_BASE_PLATFORM (in asm/elf.h), the value
+ * will be copied to the user stack in the same manner as AT_PLATFORM.
+ */
+#define ELF_BASE_PLATFORM NULL
+#endif
+
static int
create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
unsigned long load_addr, unsigned long interp_load_addr)
@@ -142,7 +151,9 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
elf_addr_t __user *envp;
elf_addr_t __user *sp;
elf_addr_t __user *u_platform;
+ elf_addr_t __user *u_base_platform;
const char *k_platform = ELF_PLATFORM;
+ const char *k_base_platform = ELF_BASE_PLATFORM;
int items;
elf_addr_t *elf_info;
int ei_index = 0;
@@ -172,6 +183,19 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
return -EFAULT;
}
+ /*
+ * If this architecture has a "base" platform capability
+ * string, copy it to userspace.
+ */
+ u_base_platform = NULL;
+ if (k_base_platform) {
+ size_t len = strlen(k_base_platform) + 1;
+
+ u_base_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
+ if (__copy_to_user(u_base_platform, k_base_platform, len))
+ return -EFAULT;
+ }
+
/* Create the ELF interpreter info */
elf_info = (elf_addr_t *)current->mm->saved_auxv;
/* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */
@@ -204,10 +228,15 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
NEW_AUX_ENT(AT_GID, tsk->gid);
NEW_AUX_ENT(AT_EGID, tsk->egid);
NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm));
+ NEW_AUX_ENT(AT_EXECFN, bprm->exec);
if (k_platform) {
NEW_AUX_ENT(AT_PLATFORM,
(elf_addr_t)(unsigned long)u_platform);
}
+ if (k_base_platform) {
+ NEW_AUX_ENT(AT_BASE_PLATFORM,
+ (elf_addr_t)(unsigned long)u_base_platform);
+ }
if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) {
NEW_AUX_ENT(AT_EXECFD, bprm->interp_data);
}
@@ -1477,7 +1506,7 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
const struct user_regset_view *view = task_user_regset_view(dump_task);
struct elf_thread_core_info *t;
struct elf_prpsinfo *psinfo;
- struct task_struct *g, *p;
+ struct core_thread *ct;
unsigned int i;
info->size = 0;
@@ -1516,31 +1545,26 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
/*
* Allocate a structure for each thread.
*/
- rcu_read_lock();
- do_each_thread(g, p)
- if (p->mm == dump_task->mm) {
- t = kzalloc(offsetof(struct elf_thread_core_info,
- notes[info->thread_notes]),
- GFP_ATOMIC);
- if (unlikely(!t)) {
- rcu_read_unlock();
- return 0;
- }
- t->task = p;
- if (p == dump_task || !info->thread) {
- t->next = info->thread;
- info->thread = t;
- } else {
- /*
- * Make sure to keep the original task at
- * the head of the list.
- */
- t->next = info->thread->next;
- info->thread->next = t;
- }
+ for (ct = &dump_task->mm->core_state->dumper; ct; ct = ct->next) {
+ t = kzalloc(offsetof(struct elf_thread_core_info,
+ notes[info->thread_notes]),
+ GFP_KERNEL);
+ if (unlikely(!t))
+ return 0;
+
+ t->task = ct->task;
+ if (ct->task == dump_task || !info->thread) {
+ t->next = info->thread;
+ info->thread = t;
+ } else {
+ /*
+ * Make sure to keep the original task at
+ * the head of the list.
+ */
+ t->next = info->thread->next;
+ info->thread->next = t;
}
- while_each_thread(g, p);
- rcu_read_unlock();
+ }
/*
* Now fill in each thread's information.
@@ -1687,7 +1711,6 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
{
#define NUM_NOTES 6
struct list_head *t;
- struct task_struct *g, *p;
info->notes = NULL;
info->prstatus = NULL;
@@ -1719,20 +1742,19 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
info->thread_status_size = 0;
if (signr) {
+ struct core_thread *ct;
struct elf_thread_status *ets;
- rcu_read_lock();
- do_each_thread(g, p)
- if (current->mm == p->mm && current != p) {
- ets = kzalloc(sizeof(*ets), GFP_ATOMIC);
- if (!ets) {
- rcu_read_unlock();
- return 0;
- }
- ets->thread = p;
- list_add(&ets->list, &info->thread_list);
- }
- while_each_thread(g, p);
- rcu_read_unlock();
+
+ for (ct = current->mm->core_state->dumper.next;
+ ct; ct = ct->next) {
+ ets = kzalloc(sizeof(*ets), GFP_KERNEL);
+ if (!ets)
+ return 0;
+
+ ets->thread = ct->task;
+ list_add(&ets->list, &info->thread_list);
+ }
+
list_for_each(t, &info->thread_list) {
int sz;
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index d051a32e627..1b59b1edf26 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -1573,7 +1573,6 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
struct memelfnote *notes = NULL;
struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */
struct elf_prpsinfo *psinfo = NULL; /* NT_PRPSINFO */
- struct task_struct *g, *p;
LIST_HEAD(thread_list);
struct list_head *t;
elf_fpregset_t *fpu = NULL;
@@ -1622,20 +1621,19 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
#endif
if (signr) {
+ struct core_thread *ct;
struct elf_thread_status *tmp;
- rcu_read_lock();
- do_each_thread(g,p)
- if (current->mm == p->mm && current != p) {
- tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);
- if (!tmp) {
- rcu_read_unlock();
- goto cleanup;
- }
- tmp->thread = p;
- list_add(&tmp->list, &thread_list);
- }
- while_each_thread(g,p);
- rcu_read_unlock();
+
+ for (ct = current->mm->core_state->dumper.next;
+ ct; ct = ct->next) {
+ tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+ if (!tmp)
+ goto cleanup;
+
+ tmp->thread = ct->task;
+ list_add(&tmp->list, &thread_list);
+ }
+
list_for_each(t, &thread_list) {
struct elf_thread_status *tmp;
int sz;
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 7191306367c..756205314c2 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -27,6 +27,7 @@
#include <linux/namei.h>
#include <linux/mount.h>
#include <linux/syscalls.h>
+#include <linux/fs.h>
#include <asm/uaccess.h>
@@ -535,31 +536,16 @@ static ssize_t
bm_entry_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
{
Node *e = file->f_path.dentry->d_inode->i_private;
- loff_t pos = *ppos;
ssize_t res;
char *page;
- int len;
if (!(page = (char*) __get_free_page(GFP_KERNEL)))
return -ENOMEM;
entry_status(e, page);
- len = strlen(page);
- res = -EINVAL;
- if (pos < 0)
- goto out;
- res = 0;
- if (pos >= len)
- goto out;
- if (len < pos + nbytes)
- nbytes = len - pos;
- res = -EFAULT;
- if (copy_to_user(buf, page + pos, nbytes))
- goto out;
- *ppos = pos + nbytes;
- res = nbytes;
-out:
+ res = simple_read_from_buffer(buf, nbytes, ppos, page, strlen(page));
+
free_page((unsigned long) page);
return res;
}
diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
index e1c854890f9..bf4a3fd3c8e 100644
--- a/fs/coda/coda_linux.c
+++ b/fs/coda/coda_linux.c
@@ -28,11 +28,9 @@ int coda_fake_statfs;
char * coda_f2s(struct CodaFid *f)
{
static char s[60];
-#ifdef CONFIG_CODA_FS_OLD_API
- sprintf(s, "(%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2]);
-#else
+
sprintf(s, "(%08x.%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2], f->opaque[3]);
-#endif
+
return s;
}
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index e3eb3556622..0d9b80ec689 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -362,8 +362,9 @@ static int init_coda_psdev(void)
goto out_chrdev;
}
for (i = 0; i < MAX_CODADEVS; i++)
- device_create(coda_psdev_class, NULL,
- MKDEV(CODA_PSDEV_MAJOR,i), "cfs%d", i);
+ device_create_drvdata(coda_psdev_class, NULL,
+ MKDEV(CODA_PSDEV_MAJOR, i),
+ NULL, "cfs%d", i);
coda_sysctl_init();
goto out;
@@ -377,11 +378,7 @@ MODULE_AUTHOR("Jan Harkes, Peter J. Braam");
MODULE_DESCRIPTION("Coda Distributed File System VFS interface");
MODULE_ALIAS_CHARDEV_MAJOR(CODA_PSDEV_MAJOR);
MODULE_LICENSE("GPL");
-#ifdef CONFIG_CODA_FS_OLD_API
-MODULE_VERSION("5.3.21");
-#else
MODULE_VERSION("6.6");
-#endif
static int __init init_coda(void)
{
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index 359e531094d..ce432bca95d 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -52,12 +52,8 @@ static void *alloc_upcall(int opcode, int size)
inp->ih.opcode = opcode;
inp->ih.pid = current->pid;
inp->ih.pgid = task_pgrp_nr(current);
-#ifdef CONFIG_CODA_FS_OLD_API
- memset(&inp->ih.cred, 0, sizeof(struct coda_cred));
- inp->ih.cred.cr_fsuid = current->fsuid;
-#else
inp->ih.uid = current->fsuid;
-#endif
+
return (void*)inp;
}
@@ -166,20 +162,11 @@ int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
union inputArgs *inp;
union outputArgs *outp;
int insize, outsize, error;
-#ifdef CONFIG_CODA_FS_OLD_API
- struct coda_cred cred = { 0, };
- cred.cr_fsuid = uid;
-#endif
insize = SIZE(release);
UPARG(CODA_CLOSE);
-#ifdef CONFIG_CODA_FS_OLD_API
- memcpy(&(inp->ih.cred), &cred, sizeof(cred));
-#else
inp->ih.uid = uid;
-#endif
-
inp->coda_close.VFid = *fid;
inp->coda_close.flags = flags;
diff --git a/fs/compat.c b/fs/compat.c
index ed43e17a5dc..106eba28ec5 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -197,8 +197,8 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *
{
if (sizeof ubuf->f_blocks == 4) {
- if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail) &
- 0xffffffff00000000ULL)
+ if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail |
+ kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
return -EOVERFLOW;
/* f_files and f_ffree may be -1; it's okay
* to stuff that into 32 bits */
@@ -271,8 +271,8 @@ out:
static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf)
{
if (sizeof ubuf->f_blocks == 4) {
- if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail) &
- 0xffffffff00000000ULL)
+ if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail |
+ kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
return -EOVERFLOW;
/* f_files and f_ffree may be -1; it's okay
* to stuff that into 32 bits */
@@ -2131,9 +2131,9 @@ asmlinkage long compat_sys_epoll_pwait(int epfd,
#ifdef CONFIG_SIGNALFD
-asmlinkage long compat_sys_signalfd(int ufd,
- const compat_sigset_t __user *sigmask,
- compat_size_t sigsetsize)
+asmlinkage long compat_sys_signalfd4(int ufd,
+ const compat_sigset_t __user *sigmask,
+ compat_size_t sigsetsize, int flags)
{
compat_sigset_t ss32;
sigset_t tmp;
@@ -2148,9 +2148,15 @@ asmlinkage long compat_sys_signalfd(int ufd,
if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t)))
return -EFAULT;
- return sys_signalfd(ufd, ksigmask, sizeof(sigset_t));
+ return sys_signalfd4(ufd, ksigmask, sizeof(sigset_t), flags);
}
+asmlinkage long compat_sys_signalfd(int ufd,
+ const compat_sigset_t __user *sigmask,
+ compat_size_t sigsetsize)
+{
+ return compat_sys_signalfd4(ufd, sigmask, sigsetsize, 0);
+}
#endif /* CONFIG_SIGNALFD */
#ifdef CONFIG_TIMERFD
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 7b3a03c7c6a..5235c67e759 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -25,7 +25,6 @@
#include <linux/slab.h>
#include <linux/raid/md.h>
#include <linux/kd.h>
-#include <linux/dirent.h>
#include <linux/route.h>
#include <linux/in6.h>
#include <linux/ipv6_route.h>
@@ -2297,8 +2296,6 @@ COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER)
COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE)
COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI)
COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOSUBVER)
-COMPATIBLE_IOCTL(AUTOFS_IOC_ASKREGHOST)
-COMPATIBLE_IOCTL(AUTOFS_IOC_TOGGLEREGHOST)
COMPATIBLE_IOCTL(AUTOFS_IOC_ASKUMOUNT)
/* Raw devices */
COMPATIBLE_IOCTL(RAW_SETBIND)
diff --git a/fs/dcache.c b/fs/dcache.c
index 6068c25b393..3818d6ab76c 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -61,7 +61,6 @@ static struct kmem_cache *dentry_cache __read_mostly;
static unsigned int d_hash_mask __read_mostly;
static unsigned int d_hash_shift __read_mostly;
static struct hlist_head *dentry_hashtable __read_mostly;
-static LIST_HEAD(dentry_unused);
/* Statistics gathering. */
struct dentry_stat_t dentry_stat = {
@@ -96,14 +95,6 @@ static void d_free(struct dentry *dentry)
call_rcu(&dentry->d_u.d_rcu, d_callback);
}
-static void dentry_lru_remove(struct dentry *dentry)
-{
- if (!list_empty(&dentry->d_lru)) {
- list_del_init(&dentry->d_lru);
- dentry_stat.nr_unused--;
- }
-}
-
/*
* Release the dentry's inode, using the filesystem
* d_iput() operation if defined.
@@ -130,6 +121,41 @@ static void dentry_iput(struct dentry * dentry)
}
}
+/*
+ * dentry_lru_(add|add_tail|del|del_init) must be called with dcache_lock held.
+ */
+static void dentry_lru_add(struct dentry *dentry)
+{
+ list_add(&dentry->d_lru, &dentry->d_sb->s_dentry_lru);
+ dentry->d_sb->s_nr_dentry_unused++;
+ dentry_stat.nr_unused++;
+}
+
+static void dentry_lru_add_tail(struct dentry *dentry)
+{
+ list_add_tail(&dentry->d_lru, &dentry->d_sb->s_dentry_lru);
+ dentry->d_sb->s_nr_dentry_unused++;
+ dentry_stat.nr_unused++;
+}
+
+static void dentry_lru_del(struct dentry *dentry)
+{
+ if (!list_empty(&dentry->d_lru)) {
+ list_del(&dentry->d_lru);
+ dentry->d_sb->s_nr_dentry_unused--;
+ dentry_stat.nr_unused--;
+ }
+}
+
+static void dentry_lru_del_init(struct dentry *dentry)
+{
+ if (likely(!list_empty(&dentry->d_lru))) {
+ list_del_init(&dentry->d_lru);
+ dentry->d_sb->s_nr_dentry_unused--;
+ dentry_stat.nr_unused--;
+ }
+}
+
/**
* d_kill - kill dentry and return parent
* @dentry: dentry to kill
@@ -212,8 +238,7 @@ repeat:
goto kill_it;
if (list_empty(&dentry->d_lru)) {
dentry->d_flags |= DCACHE_REFERENCED;
- list_add(&dentry->d_lru, &dentry_unused);
- dentry_stat.nr_unused++;
+ dentry_lru_add(dentry);
}
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
@@ -222,7 +247,8 @@ repeat:
unhash_it:
__d_drop(dentry);
kill_it:
- dentry_lru_remove(dentry);
+ /* if dentry was on the d_lru list delete it from there */
+ dentry_lru_del(dentry);
dentry = d_kill(dentry);
if (dentry)
goto repeat;
@@ -290,7 +316,7 @@ int d_invalidate(struct dentry * dentry)
static inline struct dentry * __dget_locked(struct dentry *dentry)
{
atomic_inc(&dentry->d_count);
- dentry_lru_remove(dentry);
+ dentry_lru_del_init(dentry);
return dentry;
}
@@ -406,133 +432,167 @@ static void prune_one_dentry(struct dentry * dentry)
if (dentry->d_op && dentry->d_op->d_delete)
dentry->d_op->d_delete(dentry);
- dentry_lru_remove(dentry);
+ dentry_lru_del_init(dentry);
__d_drop(dentry);
dentry = d_kill(dentry);
spin_lock(&dcache_lock);
}
}
-/**
- * prune_dcache - shrink the dcache
- * @count: number of entries to try and free
- * @sb: if given, ignore dentries for other superblocks
- * which are being unmounted.
- *
- * Shrink the dcache. This is done when we need
- * more memory, or simply when we need to unmount
- * something (at which point we need to unuse
- * all dentries).
- *
- * This function may fail to free any resources if
- * all the dentries are in use.
+/*
+ * Shrink the dentry LRU on a given superblock.
+ * @sb : superblock to shrink dentry LRU.
+ * @count: If count is NULL, we prune all dentries on superblock.
+ * @flags: If flags is non-zero, we need to do special processing based on
+ * which flags are set. This means we don't need to maintain multiple
+ * similar copies of this loop.
*/
-
-static void prune_dcache(int count, struct super_block *sb)
+static void __shrink_dcache_sb(struct super_block *sb, int *count, int flags)
{
- spin_lock(&dcache_lock);
- for (; count ; count--) {
- struct dentry *dentry;
- struct list_head *tmp;
- struct rw_semaphore *s_umount;
-
- cond_resched_lock(&dcache_lock);
+ LIST_HEAD(referenced);
+ LIST_HEAD(tmp);
+ struct dentry *dentry;
+ int cnt = 0;
- tmp = dentry_unused.prev;
- if (sb) {
- /* Try to find a dentry for this sb, but don't try
- * too hard, if they aren't near the tail they will
- * be moved down again soon
+ BUG_ON(!sb);
+ BUG_ON((flags & DCACHE_REFERENCED) && count == NULL);
+ spin_lock(&dcache_lock);
+ if (count != NULL)
+ /* called from prune_dcache() and shrink_dcache_parent() */
+ cnt = *count;
+restart:
+ if (count == NULL)
+ list_splice_init(&sb->s_dentry_lru, &tmp);
+ else {
+ while (!list_empty(&sb->s_dentry_lru)) {
+ dentry = list_entry(sb->s_dentry_lru.prev,
+ struct dentry, d_lru);
+ BUG_ON(dentry->d_sb != sb);
+
+ spin_lock(&dentry->d_lock);
+ /*
+ * If we are honouring the DCACHE_REFERENCED flag and
+ * the dentry has this flag set, don't free it. Clear
+ * the flag and put it back on the LRU.
*/
- int skip = count;
- while (skip && tmp != &dentry_unused &&
- list_entry(tmp, struct dentry, d_lru)->d_sb != sb) {
- skip--;
- tmp = tmp->prev;
+ if ((flags & DCACHE_REFERENCED)
+ && (dentry->d_flags & DCACHE_REFERENCED)) {
+ dentry->d_flags &= ~DCACHE_REFERENCED;
+ list_move_tail(&dentry->d_lru, &referenced);
+ spin_unlock(&dentry->d_lock);
+ } else {
+ list_move_tail(&dentry->d_lru, &tmp);
+ spin_unlock(&dentry->d_lock);
+ cnt--;
+ if (!cnt)
+ break;
}
}
- if (tmp == &dentry_unused)
- break;
- list_del_init(tmp);
- prefetch(dentry_unused.prev);
- dentry_stat.nr_unused--;
- dentry = list_entry(tmp, struct dentry, d_lru);
-
- spin_lock(&dentry->d_lock);
+ }
+ while (!list_empty(&tmp)) {
+ dentry = list_entry(tmp.prev, struct dentry, d_lru);
+ dentry_lru_del_init(dentry);
+ spin_lock(&dentry->d_lock);
/*
* We found an inuse dentry which was not removed from
- * dentry_unused because of laziness during lookup. Do not free
- * it - just keep it off the dentry_unused list.
+ * the LRU because of laziness during lookup. Do not free
+ * it - just keep it off the LRU list.
*/
- if (atomic_read(&dentry->d_count)) {
- spin_unlock(&dentry->d_lock);
+ if (atomic_read(&dentry->d_count)) {
+ spin_unlock(&dentry->d_lock);
continue;
}
- /* If the dentry was recently referenced, don't free it. */
- if (dentry->d_flags & DCACHE_REFERENCED) {
- dentry->d_flags &= ~DCACHE_REFERENCED;
- list_add(&dentry->d_lru, &dentry_unused);
- dentry_stat.nr_unused++;
- spin_unlock(&dentry->d_lock);
+ prune_one_dentry(dentry);
+ /* dentry->d_lock was dropped in prune_one_dentry() */
+ cond_resched_lock(&dcache_lock);
+ }
+ if (count == NULL && !list_empty(&sb->s_dentry_lru))
+ goto restart;
+ if (count != NULL)
+ *count = cnt;
+ if (!list_empty(&referenced))
+ list_splice(&referenced, &sb->s_dentry_lru);
+ spin_unlock(&dcache_lock);
+}
+
+/**
+ * prune_dcache - shrink the dcache
+ * @count: number of entries to try to free
+ *
+ * Shrink the dcache. This is done when we need more memory, or simply when we
+ * need to unmount something (at which point we need to unuse all dentries).
+ *
+ * This function may fail to free any resources if all the dentries are in use.
+ */
+static void prune_dcache(int count)
+{
+ struct super_block *sb;
+ int w_count;
+ int unused = dentry_stat.nr_unused;
+ int prune_ratio;
+ int pruned;
+
+ if (unused == 0 || count == 0)
+ return;
+ spin_lock(&dcache_lock);
+restart:
+ if (count >= unused)
+ prune_ratio = 1;
+ else
+ prune_ratio = unused / count;
+ spin_lock(&sb_lock);
+ list_for_each_entry(sb, &super_blocks, s_list) {
+ if (sb->s_nr_dentry_unused == 0)
continue;
- }
- /*
- * If the dentry is not DCACHED_REFERENCED, it is time
- * to remove it from the dcache, provided the super block is
- * NULL (which means we are trying to reclaim memory)
- * or this dentry belongs to the same super block that
- * we want to shrink.
- */
- /*
- * If this dentry is for "my" filesystem, then I can prune it
- * without taking the s_umount lock (I already hold it).
+ sb->s_count++;
+ /* Now, we reclaim unused dentrins with fairness.
+ * We reclaim them same percentage from each superblock.
+ * We calculate number of dentries to scan on this sb
+ * as follows, but the implementation is arranged to avoid
+ * overflows:
+ * number of dentries to scan on this sb =
+ * count * (number of dentries on this sb /
+ * number of dentries in the machine)
*/
- if (sb && dentry->d_sb == sb) {
- prune_one_dentry(dentry);
- continue;
- }
+ spin_unlock(&sb_lock);
+ if (prune_ratio != 1)
+ w_count = (sb->s_nr_dentry_unused / prune_ratio) + 1;
+ else
+ w_count = sb->s_nr_dentry_unused;
+ pruned = w_count;
/*
- * ...otherwise we need to be sure this filesystem isn't being
- * unmounted, otherwise we could race with
- * generic_shutdown_super(), and end up holding a reference to
- * an inode while the filesystem is unmounted.
- * So we try to get s_umount, and make sure s_root isn't NULL.
- * (Take a local copy of s_umount to avoid a use-after-free of
- * `dentry').
+ * We need to be sure this filesystem isn't being unmounted,
+ * otherwise we could race with generic_shutdown_super(), and
+ * end up holding a reference to an inode while the filesystem
+ * is unmounted. So we try to get s_umount, and make sure
+ * s_root isn't NULL.
*/
- s_umount = &dentry->d_sb->s_umount;
- if (down_read_trylock(s_umount)) {
- if (dentry->d_sb->s_root != NULL) {
- prune_one_dentry(dentry);
- up_read(s_umount);
- continue;
+ if (down_read_trylock(&sb->s_umount)) {
+ if ((sb->s_root != NULL) &&
+ (!list_empty(&sb->s_dentry_lru))) {
+ spin_unlock(&dcache_lock);
+ __shrink_dcache_sb(sb, &w_count,
+ DCACHE_REFERENCED);
+ pruned -= w_count;
+ spin_lock(&dcache_lock);
}
- up_read(s_umount);
+ up_read(&sb->s_umount);
}
- spin_unlock(&dentry->d_lock);
+ spin_lock(&sb_lock);
+ count -= pruned;
/*
- * Insert dentry at the head of the list as inserting at the
- * tail leads to a cycle.
+ * restart only when sb is no longer on the list and
+ * we have more work to do.
*/
- list_add(&dentry->d_lru, &dentry_unused);
- dentry_stat.nr_unused++;
+ if (__put_super_and_need_restart(sb) && count > 0) {
+ spin_unlock(&sb_lock);
+ goto restart;
+ }
}
+ spin_unlock(&sb_lock);
spin_unlock(&dcache_lock);
}
-/*
- * Shrink the dcache for the specified super block.
- * This allows us to unmount a device without disturbing
- * the dcache for the other devices.
- *
- * This implementation makes just two traversals of the
- * unused list. On the first pass we move the selected
- * dentries to the most recent end, and on the second
- * pass we free them. The second pass must restart after
- * each dput(), but since the target dentries are all at
- * the end, it's really just a single traversal.
- */
-
/**
* shrink_dcache_sb - shrink dcache for a superblock
* @sb: superblock
@@ -541,44 +601,9 @@ static void prune_dcache(int count, struct super_block *sb)
* is used to free the dcache before unmounting a file
* system
*/
-
void shrink_dcache_sb(struct super_block * sb)
{
- struct list_head *tmp, *next;
- struct dentry *dentry;
-
- /*
- * Pass one ... move the dentries for the specified
- * superblock to the most recent end of the unused list.
- */
- spin_lock(&dcache_lock);
- list_for_each_prev_safe(tmp, next, &dentry_unused) {
- dentry = list_entry(tmp, struct dentry, d_lru);
- if (dentry->d_sb != sb)
- continue;
- list_move_tail(tmp, &dentry_unused);
- }
-
- /*
- * Pass two ... free the dentries for this superblock.
- */
-repeat:
- list_for_each_prev_safe(tmp, next, &dentry_unused) {
- dentry = list_entry(tmp, struct dentry, d_lru);
- if (dentry->d_sb != sb)
- continue;
- dentry_stat.nr_unused--;
- list_del_init(tmp);
- spin_lock(&dentry->d_lock);
- if (atomic_read(&dentry->d_count)) {
- spin_unlock(&dentry->d_lock);
- continue;
- }
- prune_one_dentry(dentry);
- cond_resched_lock(&dcache_lock);
- goto repeat;
- }
- spin_unlock(&dcache_lock);
+ __shrink_dcache_sb(sb, NULL, 0);
}
/*
@@ -595,7 +620,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
/* detach this root from the system */
spin_lock(&dcache_lock);
- dentry_lru_remove(dentry);
+ dentry_lru_del_init(dentry);
__d_drop(dentry);
spin_unlock(&dcache_lock);
@@ -609,7 +634,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
spin_lock(&dcache_lock);
list_for_each_entry(loop, &dentry->d_subdirs,
d_u.d_child) {
- dentry_lru_remove(loop);
+ dentry_lru_del_init(loop);
__d_drop(loop);
cond_resched_lock(&dcache_lock);
}
@@ -791,14 +816,13 @@ resume:
struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
next = tmp->next;
- dentry_lru_remove(dentry);
+ dentry_lru_del_init(dentry);
/*
* move only zero ref count dentries to the end
* of the unused list for prune_dcache
*/
if (!atomic_read(&dentry->d_count)) {
- list_add_tail(&dentry->d_lru, &dentry_unused);
- dentry_stat.nr_unused++;
+ dentry_lru_add_tail(dentry);
found++;
}
@@ -840,10 +864,11 @@ out:
void shrink_dcache_parent(struct dentry * parent)
{
+ struct super_block *sb = parent->d_sb;
int found;
while ((found = select_parent(parent)) != 0)
- prune_dcache(found, parent->d_sb);
+ __shrink_dcache_sb(sb, &found, 0);
}
/*
@@ -863,7 +888,7 @@ static int shrink_dcache_memory(int nr, gfp_t gfp_mask)
if (nr) {
if (!(gfp_mask & __GFP_FS))
return -1;
- prune_dcache(nr, NULL);
+ prune_dcache(nr);
}
return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
}
@@ -1215,7 +1240,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
* rcu_read_lock() and rcu_read_unlock() are used to disable preemption while
* lookup is going on.
*
- * dentry_unused list is not updated even if lookup finds the required dentry
+ * The dentry unused LRU is not updated even if lookup finds the required dentry
* in there. It is updated in places such as prune_dcache, shrink_dcache_sb,
* select_parent and __dget_locked. This laziness saves lookup from dcache_lock
* acquisition.
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index e9602d85c11..08e28c9bb41 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -309,6 +309,31 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
}
EXPORT_SYMBOL_GPL(debugfs_create_symlink);
+static void __debugfs_remove(struct dentry *dentry, struct dentry *parent)
+{
+ int ret = 0;
+
+ if (debugfs_positive(dentry)) {
+ if (dentry->d_inode) {
+ dget(dentry);
+ switch (dentry->d_inode->i_mode & S_IFMT) {
+ case S_IFDIR:
+ ret = simple_rmdir(parent->d_inode, dentry);
+ break;
+ case S_IFLNK:
+ kfree(dentry->d_inode->i_private);
+ /* fall through */
+ default:
+ simple_unlink(parent->d_inode, dentry);
+ break;
+ }
+ if (!ret)
+ d_delete(dentry);
+ dput(dentry);
+ }
+ }
+}
+
/**
* debugfs_remove - removes a file or directory from the debugfs filesystem
* @dentry: a pointer to a the dentry of the file or directory to be
@@ -325,7 +350,6 @@ EXPORT_SYMBOL_GPL(debugfs_create_symlink);
void debugfs_remove(struct dentry *dentry)
{
struct dentry *parent;
- int ret = 0;
if (!dentry)
return;
@@ -335,29 +359,83 @@ void debugfs_remove(struct dentry *dentry)
return;
mutex_lock(&parent->d_inode->i_mutex);
- if (debugfs_positive(dentry)) {
- if (dentry->d_inode) {
- dget(dentry);
- switch (dentry->d_inode->i_mode & S_IFMT) {
- case S_IFDIR:
- ret = simple_rmdir(parent->d_inode, dentry);
- break;
- case S_IFLNK:
- kfree(dentry->d_inode->i_private);
- /* fall through */
- default:
- simple_unlink(parent->d_inode, dentry);
+ __debugfs_remove(dentry, parent);
+ mutex_unlock(&parent->d_inode->i_mutex);
+ simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+}
+EXPORT_SYMBOL_GPL(debugfs_remove);
+
+/**
+ * debugfs_remove_recursive - recursively removes a directory
+ * @dentry: a pointer to a the dentry of the directory to be removed.
+ *
+ * This function recursively removes a directory tree in debugfs that
+ * was previously created with a call to another debugfs function
+ * (like debugfs_create_file() or variants thereof.)
+ *
+ * This function is required to be called in order for the file to be
+ * removed, no automatic cleanup of files will happen when a module is
+ * removed, you are responsible here.
+ */
+void debugfs_remove_recursive(struct dentry *dentry)
+{
+ struct dentry *child;
+ struct dentry *parent;
+
+ if (!dentry)
+ return;
+
+ parent = dentry->d_parent;
+ if (!parent || !parent->d_inode)
+ return;
+
+ parent = dentry;
+ mutex_lock(&parent->d_inode->i_mutex);
+
+ while (1) {
+ /*
+ * When all dentries under "parent" has been removed,
+ * walk up the tree until we reach our starting point.
+ */
+ if (list_empty(&parent->d_subdirs)) {
+ mutex_unlock(&parent->d_inode->i_mutex);
+ if (parent == dentry)
break;
- }
- if (!ret)
- d_delete(dentry);
- dput(dentry);
+ parent = parent->d_parent;
+ mutex_lock(&parent->d_inode->i_mutex);
+ }
+ child = list_entry(parent->d_subdirs.next, struct dentry,
+ d_u.d_child);
+
+ /*
+ * If "child" isn't empty, walk down the tree and
+ * remove all its descendants first.
+ */
+ if (!list_empty(&child->d_subdirs)) {
+ mutex_unlock(&parent->d_inode->i_mutex);
+ parent = child;
+ mutex_lock(&parent->d_inode->i_mutex);
+ continue;
}
+ __debugfs_remove(child, parent);
+ if (parent->d_subdirs.next == &child->d_u.d_child) {
+ /*
+ * Avoid infinite loop if we fail to remove
+ * one dentry.
+ */
+ mutex_unlock(&parent->d_inode->i_mutex);
+ break;
+ }
+ simple_release_fs(&debugfs_mount, &debugfs_mount_count);
}
+
+ parent = dentry->d_parent;
+ mutex_lock(&parent->d_inode->i_mutex);
+ __debugfs_remove(dentry, parent);
mutex_unlock(&parent->d_inode->i_mutex);
simple_release_fs(&debugfs_mount, &debugfs_mount_count);
}
-EXPORT_SYMBOL_GPL(debugfs_remove);
+EXPORT_SYMBOL_GPL(debugfs_remove_recursive);
/**
* debugfs_rename - rename a file/directory in the debugfs filesystem
diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c
index 78878c5781c..eba87ff3177 100644
--- a/fs/dlm/plock.c
+++ b/fs/dlm/plock.c
@@ -116,7 +116,7 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
if (xop->callback == NULL)
wait_event(recv_wq, (op->done != 0));
else {
- rv = -EINPROGRESS;
+ rv = FILE_LOCK_DEFERRED;
goto out;
}
diff --git a/fs/dquot.c b/fs/dquot.c
index 5ac77da1995..1346eebe74c 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -562,6 +562,8 @@ static struct shrinker dqcache_shrinker = {
*/
static void dqput(struct dquot *dquot)
{
+ int ret;
+
if (!dquot)
return;
#ifdef __DQUOT_PARANOIA
@@ -594,7 +596,19 @@ we_slept:
if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && dquot_dirty(dquot)) {
spin_unlock(&dq_list_lock);
/* Commit dquot before releasing */
- dquot->dq_sb->dq_op->write_dquot(dquot);
+ ret = dquot->dq_sb->dq_op->write_dquot(dquot);
+ if (ret < 0) {
+ printk(KERN_ERR "VFS: cannot write quota structure on "
+ "device %s (error %d). Quota may get out of "
+ "sync!\n", dquot->dq_sb->s_id, ret);
+ /*
+ * We clear dirty bit anyway, so that we avoid
+ * infinite loop here
+ */
+ spin_lock(&dq_list_lock);
+ clear_dquot_dirty(dquot);
+ spin_unlock(&dq_list_lock);
+ }
goto we_slept;
}
/* Clear flag in case dquot was inactive (something bad happened) */
@@ -875,7 +889,10 @@ static void print_warning(struct dquot *dquot, const int warntype)
char *msg = NULL;
struct tty_struct *tty;
- if (!need_print_warning(dquot))
+ if (warntype == QUOTA_NL_IHARDBELOW ||
+ warntype == QUOTA_NL_ISOFTBELOW ||
+ warntype == QUOTA_NL_BHARDBELOW ||
+ warntype == QUOTA_NL_BSOFTBELOW || !need_print_warning(dquot))
return;
mutex_lock(&tty_mutex);
@@ -1083,6 +1100,35 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
return QUOTA_OK;
}
+static int info_idq_free(struct dquot *dquot, ulong inodes)
+{
+ if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
+ dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit)
+ return QUOTA_NL_NOWARN;
+
+ if (dquot->dq_dqb.dqb_curinodes - inodes <= dquot->dq_dqb.dqb_isoftlimit)
+ return QUOTA_NL_ISOFTBELOW;
+ if (dquot->dq_dqb.dqb_curinodes >= dquot->dq_dqb.dqb_ihardlimit &&
+ dquot->dq_dqb.dqb_curinodes - inodes < dquot->dq_dqb.dqb_ihardlimit)
+ return QUOTA_NL_IHARDBELOW;
+ return QUOTA_NL_NOWARN;
+}
+
+static int info_bdq_free(struct dquot *dquot, qsize_t space)
+{
+ if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
+ toqb(dquot->dq_dqb.dqb_curspace) <= dquot->dq_dqb.dqb_bsoftlimit)
+ return QUOTA_NL_NOWARN;
+
+ if (toqb(dquot->dq_dqb.dqb_curspace - space) <=
+ dquot->dq_dqb.dqb_bsoftlimit)
+ return QUOTA_NL_BSOFTBELOW;
+ if (toqb(dquot->dq_dqb.dqb_curspace) >= dquot->dq_dqb.dqb_bhardlimit &&
+ toqb(dquot->dq_dqb.dqb_curspace - space) <
+ dquot->dq_dqb.dqb_bhardlimit)
+ return QUOTA_NL_BHARDBELOW;
+ return QUOTA_NL_NOWARN;
+}
/*
* Initialize quota pointers in inode
* Transaction must be started at entry
@@ -1139,6 +1185,28 @@ int dquot_drop(struct inode *inode)
return 0;
}
+/* Wrapper to remove references to quota structures from inode */
+void vfs_dq_drop(struct inode *inode)
+{
+ /* Here we can get arbitrary inode from clear_inode() so we have
+ * to be careful. OTOH we don't need locking as quota operations
+ * are allowed to change only at mount time */
+ if (!IS_NOQUOTA(inode) && inode->i_sb && inode->i_sb->dq_op
+ && inode->i_sb->dq_op->drop) {
+ int cnt;
+ /* Test before calling to rule out calls from proc and such
+ * where we are not allowed to block. Note that this is
+ * actually reliable test even without the lock - the caller
+ * must assure that nobody can come after the DQUOT_DROP and
+ * add quota pointers back anyway */
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+ if (inode->i_dquot[cnt] != NODQUOT)
+ break;
+ if (cnt < MAXQUOTAS)
+ inode->i_sb->dq_op->drop(inode);
+ }
+}
+
/*
* Following four functions update i_blocks+i_bytes fields and
* quota information (together with appropriate checks)
@@ -1248,6 +1316,7 @@ warn_put_all:
int dquot_free_space(struct inode *inode, qsize_t number)
{
unsigned int cnt;
+ char warntype[MAXQUOTAS];
/* First test before acquiring mutex - solves deadlocks when we
* re-enter the quota code and are already holding the mutex */
@@ -1256,6 +1325,7 @@ out_sub:
inode_sub_bytes(inode, number);
return QUOTA_OK;
}
+
down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
/* Now recheck reliably when holding dqptr_sem */
if (IS_NOQUOTA(inode)) {
@@ -1266,6 +1336,7 @@ out_sub:
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (inode->i_dquot[cnt] == NODQUOT)
continue;
+ warntype[cnt] = info_bdq_free(inode->i_dquot[cnt], number);
dquot_decr_space(inode->i_dquot[cnt], number);
}
inode_sub_bytes(inode, number);
@@ -1274,6 +1345,7 @@ out_sub:
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
if (inode->i_dquot[cnt])
mark_dquot_dirty(inode->i_dquot[cnt]);
+ flush_warnings(inode->i_dquot, warntype);
up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
return QUOTA_OK;
}
@@ -1284,11 +1356,13 @@ out_sub:
int dquot_free_inode(const struct inode *inode, unsigned long number)
{
unsigned int cnt;
+ char warntype[MAXQUOTAS];
/* First test before acquiring mutex - solves deadlocks when we
* re-enter the quota code and are already holding the mutex */
if (IS_NOQUOTA(inode))
return QUOTA_OK;
+
down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
/* Now recheck reliably when holding dqptr_sem */
if (IS_NOQUOTA(inode)) {
@@ -1299,6 +1373,7 @@ int dquot_free_inode(const struct inode *inode, unsigned long number)
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (inode->i_dquot[cnt] == NODQUOT)
continue;
+ warntype[cnt] = info_idq_free(inode->i_dquot[cnt], number);
dquot_decr_inodes(inode->i_dquot[cnt], number);
}
spin_unlock(&dq_data_lock);
@@ -1306,6 +1381,7 @@ int dquot_free_inode(const struct inode *inode, unsigned long number)
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
if (inode->i_dquot[cnt])
mark_dquot_dirty(inode->i_dquot[cnt]);
+ flush_warnings(inode->i_dquot, warntype);
up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
return QUOTA_OK;
}
@@ -1323,7 +1399,8 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
struct dquot *transfer_to[MAXQUOTAS];
int cnt, ret = NO_QUOTA, chuid = (iattr->ia_valid & ATTR_UID) && inode->i_uid != iattr->ia_uid,
chgid = (iattr->ia_valid & ATTR_GID) && inode->i_gid != iattr->ia_gid;
- char warntype[MAXQUOTAS];
+ char warntype_to[MAXQUOTAS];
+ char warntype_from_inodes[MAXQUOTAS], warntype_from_space[MAXQUOTAS];
/* First test before acquiring mutex - solves deadlocks when we
* re-enter the quota code and are already holding the mutex */
@@ -1332,7 +1409,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
/* Clear the arrays */
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
transfer_to[cnt] = transfer_from[cnt] = NODQUOT;
- warntype[cnt] = QUOTA_NL_NOWARN;
+ warntype_to[cnt] = QUOTA_NL_NOWARN;
}
down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
/* Now recheck reliably when holding dqptr_sem */
@@ -1364,8 +1441,9 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
if (transfer_to[cnt] == NODQUOT)
continue;
transfer_from[cnt] = inode->i_dquot[cnt];
- if (check_idq(transfer_to[cnt], 1, warntype+cnt) == NO_QUOTA ||
- check_bdq(transfer_to[cnt], space, 0, warntype+cnt) == NO_QUOTA)
+ if (check_idq(transfer_to[cnt], 1, warntype_to + cnt) ==
+ NO_QUOTA || check_bdq(transfer_to[cnt], space, 0,
+ warntype_to + cnt) == NO_QUOTA)
goto warn_put_all;
}
@@ -1381,6 +1459,10 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
/* Due to IO error we might not have transfer_from[] structure */
if (transfer_from[cnt]) {
+ warntype_from_inodes[cnt] =
+ info_idq_free(transfer_from[cnt], 1);
+ warntype_from_space[cnt] =
+ info_bdq_free(transfer_from[cnt], space);
dquot_decr_inodes(transfer_from[cnt], 1);
dquot_decr_space(transfer_from[cnt], space);
}
@@ -1400,7 +1482,9 @@ warn_put_all:
if (transfer_to[cnt])
mark_dquot_dirty(transfer_to[cnt]);
}
- flush_warnings(transfer_to, warntype);
+ flush_warnings(transfer_to, warntype_to);
+ flush_warnings(transfer_from, warntype_from_inodes);
+ flush_warnings(transfer_from, warntype_from_space);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (ret == QUOTA_OK && transfer_from[cnt] != NODQUOT)
@@ -1412,6 +1496,18 @@ warn_put_all:
return ret;
}
+/* Wrapper for transferring ownership of an inode */
+int vfs_dq_transfer(struct inode *inode, struct iattr *iattr)
+{
+ if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode)) {
+ vfs_dq_init(inode);
+ if (inode->i_sb->dq_op->transfer(inode, iattr) == NO_QUOTA)
+ return 1;
+ }
+ return 0;
+}
+
+
/*
* Write info of quota file to disk
*/
@@ -1752,6 +1848,22 @@ out:
return error;
}
+/* Wrapper to turn on quotas when remounting rw */
+int vfs_dq_quota_on_remount(struct super_block *sb)
+{
+ int cnt;
+ int ret = 0, err;
+
+ if (!sb->s_qcop || !sb->s_qcop->quota_on)
+ return -ENOSYS;
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+ err = sb->s_qcop->quota_on(sb, cnt, 0, NULL, 1);
+ if (err < 0 && !ret)
+ ret = err;
+ }
+ return ret;
+}
+
/* Generic routine for getting common part of quota structure */
static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di)
{
@@ -2087,8 +2199,11 @@ EXPORT_SYMBOL(dquot_release);
EXPORT_SYMBOL(dquot_mark_dquot_dirty);
EXPORT_SYMBOL(dquot_initialize);
EXPORT_SYMBOL(dquot_drop);
+EXPORT_SYMBOL(vfs_dq_drop);
EXPORT_SYMBOL(dquot_alloc_space);
EXPORT_SYMBOL(dquot_alloc_inode);
EXPORT_SYMBOL(dquot_free_space);
EXPORT_SYMBOL(dquot_free_inode);
EXPORT_SYMBOL(dquot_transfer);
+EXPORT_SYMBOL(vfs_dq_transfer);
+EXPORT_SYMBOL(vfs_dq_quota_on_remount);
diff --git a/fs/ecryptfs/Makefile b/fs/ecryptfs/Makefile
index 1e34a7fd488..b4755a85996 100644
--- a/fs/ecryptfs/Makefile
+++ b/fs/ecryptfs/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
-ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o netlink.o miscdev.o debug.o
+ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o netlink.o miscdev.o kthread.o debug.o
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index e2832bc7869..7b99917ffad 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -33,6 +33,7 @@
#include <linux/crypto.h>
#include <linux/file.h>
#include <linux/scatterlist.h>
+#include <asm/unaligned.h>
#include "ecryptfs_kernel.h"
static int
@@ -1032,10 +1033,8 @@ static int contains_ecryptfs_marker(char *data)
{
u32 m_1, m_2;
- memcpy(&m_1, data, 4);
- m_1 = be32_to_cpu(m_1);
- memcpy(&m_2, (data + 4), 4);
- m_2 = be32_to_cpu(m_2);
+ m_1 = get_unaligned_be32(data);
+ m_2 = get_unaligned_be32(data + 4);
if ((m_1 ^ MAGIC_ECRYPTFS_MARKER) == m_2)
return 1;
ecryptfs_printk(KERN_DEBUG, "m_1 = [0x%.8x]; m_2 = [0x%.8x]; "
@@ -1073,8 +1072,7 @@ static int ecryptfs_process_flags(struct ecryptfs_crypt_stat *crypt_stat,
int i;
u32 flags;
- memcpy(&flags, page_virt, 4);
- flags = be32_to_cpu(flags);
+ flags = get_unaligned_be32(page_virt);
for (i = 0; i < ((sizeof(ecryptfs_flag_map)
/ sizeof(struct ecryptfs_flag_map_elem))); i++)
if (flags & ecryptfs_flag_map[i].file_flag) {
@@ -1100,11 +1098,9 @@ static void write_ecryptfs_marker(char *page_virt, size_t *written)
get_random_bytes(&m_1, (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2));
m_2 = (m_1 ^ MAGIC_ECRYPTFS_MARKER);
- m_1 = cpu_to_be32(m_1);
- memcpy(page_virt, &m_1, (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2));
- m_2 = cpu_to_be32(m_2);
- memcpy(page_virt + (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2), &m_2,
- (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2));
+ put_unaligned_be32(m_1, page_virt);
+ page_virt += (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2);
+ put_unaligned_be32(m_2, page_virt);
(*written) = MAGIC_ECRYPTFS_MARKER_SIZE_BYTES;
}
@@ -1121,8 +1117,7 @@ write_ecryptfs_flags(char *page_virt, struct ecryptfs_crypt_stat *crypt_stat,
flags |= ecryptfs_flag_map[i].file_flag;
/* Version is in top 8 bits of the 32-bit flag vector */
flags |= ((((u8)crypt_stat->file_version) << 24) & 0xFF000000);
- flags = cpu_to_be32(flags);
- memcpy(page_virt, &flags, 4);
+ put_unaligned_be32(flags, page_virt);
(*written) = 4;
}
@@ -1238,11 +1233,9 @@ ecryptfs_write_header_metadata(char *virt,
num_header_extents_at_front =
(u16)(crypt_stat->num_header_bytes_at_front
/ crypt_stat->extent_size);
- header_extent_size = cpu_to_be32(header_extent_size);
- memcpy(virt, &header_extent_size, 4);
+ put_unaligned_be32(header_extent_size, virt);
virt += 4;
- num_header_extents_at_front = cpu_to_be16(num_header_extents_at_front);
- memcpy(virt, &num_header_extents_at_front, 2);
+ put_unaligned_be16(num_header_extents_at_front, virt);
(*written) = 6;
}
@@ -1410,15 +1403,13 @@ static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat,
u32 header_extent_size;
u16 num_header_extents_at_front;
- memcpy(&header_extent_size, virt, sizeof(u32));
- header_extent_size = be32_to_cpu(header_extent_size);
- virt += sizeof(u32);
- memcpy(&num_header_extents_at_front, virt, sizeof(u16));
- num_header_extents_at_front = be16_to_cpu(num_header_extents_at_front);
+ header_extent_size = get_unaligned_be32(virt);
+ virt += sizeof(__be32);
+ num_header_extents_at_front = get_unaligned_be16(virt);
crypt_stat->num_header_bytes_at_front =
(((size_t)num_header_extents_at_front
* (size_t)header_extent_size));
- (*bytes_read) = (sizeof(u32) + sizeof(u16));
+ (*bytes_read) = (sizeof(__be32) + sizeof(__be16));
if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE)
&& (crypt_stat->num_header_bytes_at_front
< ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) {
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index c15c25745e0..b73fb752c5f 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -559,10 +559,25 @@ extern struct kmem_cache *ecryptfs_key_record_cache;
extern struct kmem_cache *ecryptfs_key_sig_cache;
extern struct kmem_cache *ecryptfs_global_auth_tok_cache;
extern struct kmem_cache *ecryptfs_key_tfm_cache;
+extern struct kmem_cache *ecryptfs_open_req_cache;
+struct ecryptfs_open_req {
+#define ECRYPTFS_REQ_PROCESSED 0x00000001
+#define ECRYPTFS_REQ_DROPPED 0x00000002
+#define ECRYPTFS_REQ_ZOMBIE 0x00000004
+ u32 flags;
+ struct file **lower_file;
+ struct dentry *lower_dentry;
+ struct vfsmount *lower_mnt;
+ wait_queue_head_t wait;
+ struct mutex mux;
+ struct list_head kthread_ctl_list;
+};
+
+#define ECRYPTFS_INTERPOSE_FLAG_D_ADD 0x00000001
int ecryptfs_interpose(struct dentry *hidden_dentry,
struct dentry *this_dentry, struct super_block *sb,
- int flag);
+ u32 flags);
int ecryptfs_fill_zeros(struct file *file, loff_t new_length);
int ecryptfs_decode_filename(struct ecryptfs_crypt_stat *crypt_stat,
const char *name, int length,
@@ -690,5 +705,11 @@ void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx);
int
ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid,
struct user_namespace *user_ns, struct pid *pid);
+int ecryptfs_init_kthread(void);
+void ecryptfs_destroy_kthread(void);
+int ecryptfs_privileged_open(struct file **lower_file,
+ struct dentry *lower_dentry,
+ struct vfsmount *lower_mnt);
+int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry);
#endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 24749bf0668..9244d653743 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -192,6 +192,23 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
| ECRYPTFS_ENCRYPTED);
}
mutex_unlock(&crypt_stat->cs_mutex);
+ if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_RDONLY)
+ && !(file->f_flags & O_RDONLY)) {
+ rc = -EPERM;
+ printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs "
+ "file must hence be opened RO\n", __func__);
+ goto out;
+ }
+ if (!ecryptfs_inode_to_private(inode)->lower_file) {
+ rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to initialize "
+ "the persistent file for the dentry with name "
+ "[%s]; rc = [%d]\n", __func__,
+ ecryptfs_dentry->d_name.name, rc);
+ goto out;
+ }
+ }
ecryptfs_set_file_lower(
file, ecryptfs_inode_to_private(inode)->lower_file);
if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index c92cc1c00aa..d755455e3bf 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -31,6 +31,7 @@
#include <linux/mount.h>
#include <linux/crypto.h>
#include <linux/fs_stack.h>
+#include <asm/unaligned.h>
#include "ecryptfs_kernel.h"
static struct dentry *lock_parent(struct dentry *dentry)
@@ -188,6 +189,16 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
"context; rc = [%d]\n", rc);
goto out;
}
+ if (!ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->lower_file) {
+ rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to initialize "
+ "the persistent file for the dentry with name "
+ "[%s]; rc = [%d]\n", __func__,
+ ecryptfs_dentry->d_name.name, rc);
+ goto out;
+ }
+ }
rc = ecryptfs_write_metadata(ecryptfs_dentry);
if (rc) {
printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc);
@@ -307,10 +318,11 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
d_add(dentry, NULL);
goto out;
}
- rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 1);
+ rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb,
+ ECRYPTFS_INTERPOSE_FLAG_D_ADD);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error interposing\n");
- goto out_dput;
+ goto out;
}
if (S_ISDIR(lower_inode->i_mode)) {
ecryptfs_printk(KERN_DEBUG, "Is a directory; returning\n");
@@ -336,11 +348,21 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
rc = -ENOMEM;
ecryptfs_printk(KERN_ERR,
"Cannot ecryptfs_kmalloc a page\n");
- goto out_dput;
+ goto out;
}
crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED))
ecryptfs_set_default_sizes(crypt_stat);
+ if (!ecryptfs_inode_to_private(dentry->d_inode)->lower_file) {
+ rc = ecryptfs_init_persistent_file(dentry);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to initialize "
+ "the persistent file for the dentry with name "
+ "[%s]; rc = [%d]\n", __func__,
+ dentry->d_name.name, rc);
+ goto out;
+ }
+ }
rc = ecryptfs_read_and_validate_header_region(page_virt,
dentry->d_inode);
if (rc) {
@@ -364,8 +386,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry,
else
file_size = i_size_read(lower_dentry->d_inode);
} else {
- memcpy(&file_size, page_virt, sizeof(file_size));
- file_size = be64_to_cpu(file_size);
+ file_size = get_unaligned_be64(page_virt);
}
i_size_write(dentry->d_inode, (loff_t)file_size);
kmem_cache_free(ecryptfs_header_cache_2, page_virt);
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index e82b457180b..f5b76a331b9 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -44,15 +44,15 @@ static int process_request_key_err(long err_code)
int rc = 0;
switch (err_code) {
- case ENOKEY:
+ case -ENOKEY:
ecryptfs_printk(KERN_WARNING, "No key\n");
rc = -ENOENT;
break;
- case EKEYEXPIRED:
+ case -EKEYEXPIRED:
ecryptfs_printk(KERN_WARNING, "Key expired\n");
rc = -ETIME;
break;
- case EKEYREVOKED:
+ case -EKEYREVOKED:
ecryptfs_printk(KERN_WARNING, "Key revoked\n");
rc = -EINVAL;
break;
@@ -963,8 +963,7 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
if (!(*auth_tok_key) || IS_ERR(*auth_tok_key)) {
printk(KERN_ERR "Could not find key with description: [%s]\n",
sig);
- process_request_key_err(PTR_ERR(*auth_tok_key));
- rc = -EINVAL;
+ rc = process_request_key_err(PTR_ERR(*auth_tok_key));
goto out;
}
(*auth_tok) = ecryptfs_get_key_payload_data(*auth_tok_key);
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c
new file mode 100644
index 00000000000..c440c6b58b2
--- /dev/null
+++ b/fs/ecryptfs/kthread.c
@@ -0,0 +1,203 @@
+/**
+ * eCryptfs: Linux filesystem encryption layer
+ *
+ * Copyright (C) 2008 International Business Machines Corp.
+ * Author(s): Michael A. Halcrow <mahalcro@us.ibm.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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/wait.h>
+#include <linux/mount.h>
+#include "ecryptfs_kernel.h"
+
+struct kmem_cache *ecryptfs_open_req_cache;
+
+static struct ecryptfs_kthread_ctl {
+#define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001
+ u32 flags;
+ struct mutex mux;
+ struct list_head req_list;
+ wait_queue_head_t wait;
+} ecryptfs_kthread_ctl;
+
+static struct task_struct *ecryptfs_kthread;
+
+/**
+ * ecryptfs_threadfn
+ * @ignored: ignored
+ *
+ * The eCryptfs kernel thread that has the responsibility of getting
+ * the lower persistent file with RW permissions.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+static int ecryptfs_threadfn(void *ignored)
+{
+ set_freezable();
+ while (1) {
+ struct ecryptfs_open_req *req;
+
+ wait_event_freezable(
+ ecryptfs_kthread_ctl.wait,
+ (!list_empty(&ecryptfs_kthread_ctl.req_list)
+ || kthread_should_stop()));
+ mutex_lock(&ecryptfs_kthread_ctl.mux);
+ if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {
+ mutex_unlock(&ecryptfs_kthread_ctl.mux);
+ goto out;
+ }
+ while (!list_empty(&ecryptfs_kthread_ctl.req_list)) {
+ req = list_first_entry(&ecryptfs_kthread_ctl.req_list,
+ struct ecryptfs_open_req,
+ kthread_ctl_list);
+ mutex_lock(&req->mux);
+ list_del(&req->kthread_ctl_list);
+ if (!(req->flags & ECRYPTFS_REQ_ZOMBIE)) {
+ dget(req->lower_dentry);
+ mntget(req->lower_mnt);
+ (*req->lower_file) = dentry_open(
+ req->lower_dentry, req->lower_mnt,
+ (O_RDWR | O_LARGEFILE));
+ req->flags |= ECRYPTFS_REQ_PROCESSED;
+ }
+ wake_up(&req->wait);
+ mutex_unlock(&req->mux);
+ }
+ mutex_unlock(&ecryptfs_kthread_ctl.mux);
+ }
+out:
+ return 0;
+}
+
+int ecryptfs_init_kthread(void)
+{
+ int rc = 0;
+
+ mutex_init(&ecryptfs_kthread_ctl.mux);
+ init_waitqueue_head(&ecryptfs_kthread_ctl.wait);
+ INIT_LIST_HEAD(&ecryptfs_kthread_ctl.req_list);
+ ecryptfs_kthread = kthread_run(&ecryptfs_threadfn, NULL,
+ "ecryptfs-kthread");
+ if (IS_ERR(ecryptfs_kthread)) {
+ rc = PTR_ERR(ecryptfs_kthread);
+ printk(KERN_ERR "%s: Failed to create kernel thread; rc = [%d]"
+ "\n", __func__, rc);
+ }
+ return rc;
+}
+
+void ecryptfs_destroy_kthread(void)
+{
+ struct ecryptfs_open_req *req;
+
+ mutex_lock(&ecryptfs_kthread_ctl.mux);
+ ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE;
+ list_for_each_entry(req, &ecryptfs_kthread_ctl.req_list,
+ kthread_ctl_list) {
+ mutex_lock(&req->mux);
+ req->flags |= ECRYPTFS_REQ_ZOMBIE;
+ wake_up(&req->wait);
+ mutex_unlock(&req->mux);
+ }
+ mutex_unlock(&ecryptfs_kthread_ctl.mux);
+ kthread_stop(ecryptfs_kthread);
+ wake_up(&ecryptfs_kthread_ctl.wait);
+}
+
+/**
+ * ecryptfs_privileged_open
+ * @lower_file: Result of dentry_open by root on lower dentry
+ * @lower_dentry: Lower dentry for file to open
+ * @lower_mnt: Lower vfsmount for file to open
+ *
+ * This function gets a r/w file opened againt the lower dentry.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+int ecryptfs_privileged_open(struct file **lower_file,
+ struct dentry *lower_dentry,
+ struct vfsmount *lower_mnt)
+{
+ struct ecryptfs_open_req *req;
+ int rc = 0;
+
+ /* Corresponding dput() and mntput() are done when the
+ * persistent file is fput() when the eCryptfs inode is
+ * destroyed. */
+ dget(lower_dentry);
+ mntget(lower_mnt);
+ (*lower_file) = dentry_open(lower_dentry, lower_mnt,
+ (O_RDWR | O_LARGEFILE));
+ if (!IS_ERR(*lower_file))
+ goto out;
+ req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL);
+ if (!req) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ mutex_init(&req->mux);
+ req->lower_file = lower_file;
+ req->lower_dentry = lower_dentry;
+ req->lower_mnt = lower_mnt;
+ init_waitqueue_head(&req->wait);
+ req->flags = 0;
+ mutex_lock(&ecryptfs_kthread_ctl.mux);
+ if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {
+ rc = -EIO;
+ mutex_unlock(&ecryptfs_kthread_ctl.mux);
+ printk(KERN_ERR "%s: We are in the middle of shutting down; "
+ "aborting privileged request to open lower file\n",
+ __func__);
+ goto out_free;
+ }
+ list_add_tail(&req->kthread_ctl_list, &ecryptfs_kthread_ctl.req_list);
+ mutex_unlock(&ecryptfs_kthread_ctl.mux);
+ wake_up(&ecryptfs_kthread_ctl.wait);
+ wait_event(req->wait, (req->flags != 0));
+ mutex_lock(&req->mux);
+ BUG_ON(req->flags == 0);
+ if (req->flags & ECRYPTFS_REQ_DROPPED
+ || req->flags & ECRYPTFS_REQ_ZOMBIE) {
+ rc = -EIO;
+ printk(KERN_WARNING "%s: Privileged open request dropped\n",
+ __func__);
+ goto out_unlock;
+ }
+ if (IS_ERR(*req->lower_file)) {
+ rc = PTR_ERR(*req->lower_file);
+ dget(lower_dentry);
+ mntget(lower_mnt);
+ (*lower_file) = dentry_open(lower_dentry, lower_mnt,
+ (O_RDONLY | O_LARGEFILE));
+ if (IS_ERR(*lower_file)) {
+ rc = PTR_ERR(*req->lower_file);
+ (*lower_file) = NULL;
+ printk(KERN_WARNING "%s: Error attempting privileged "
+ "open of lower file with either RW or RO "
+ "perms; rc = [%d]. Giving up.\n",
+ __func__, rc);
+ }
+ }
+out_unlock:
+ mutex_unlock(&req->mux);
+out_free:
+ kmem_cache_free(ecryptfs_open_req_cache, req);
+out:
+ return rc;
+}
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index d603631601e..6f403cfba14 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -117,7 +117,7 @@ void __ecryptfs_printk(const char *fmt, ...)
*
* Returns zero on success; non-zero otherwise
*/
-static int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
+int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
{
struct ecryptfs_inode_info *inode_info =
ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
@@ -130,26 +130,12 @@ static int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
- /* Corresponding dput() and mntput() are done when the
- * persistent file is fput() when the eCryptfs inode
- * is destroyed. */
- dget(lower_dentry);
- mntget(lower_mnt);
- inode_info->lower_file = dentry_open(lower_dentry,
- lower_mnt,
- (O_RDWR | O_LARGEFILE));
- if (IS_ERR(inode_info->lower_file)) {
- dget(lower_dentry);
- mntget(lower_mnt);
- inode_info->lower_file = dentry_open(lower_dentry,
- lower_mnt,
- (O_RDONLY
- | O_LARGEFILE));
- }
- if (IS_ERR(inode_info->lower_file)) {
+ rc = ecryptfs_privileged_open(&inode_info->lower_file,
+ lower_dentry, lower_mnt);
+ if (rc || IS_ERR(inode_info->lower_file)) {
printk(KERN_ERR "Error opening lower persistent file "
- "for lower_dentry [0x%p] and lower_mnt [0x%p]\n",
- lower_dentry, lower_mnt);
+ "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
+ "rc = [%d]\n", lower_dentry, lower_mnt, rc);
rc = PTR_ERR(inode_info->lower_file);
inode_info->lower_file = NULL;
}
@@ -163,14 +149,14 @@ static int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
* @lower_dentry: Existing dentry in the lower filesystem
* @dentry: ecryptfs' dentry
* @sb: ecryptfs's super_block
- * @flag: If set to true, then d_add is called, else d_instantiate is called
+ * @flags: flags to govern behavior of interpose procedure
*
* Interposes upper and lower dentries.
*
* Returns zero on success; non-zero otherwise
*/
int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
- struct super_block *sb, int flag)
+ struct super_block *sb, u32 flags)
{
struct inode *lower_inode;
struct inode *inode;
@@ -207,7 +193,7 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
init_special_inode(inode, lower_inode->i_mode,
lower_inode->i_rdev);
dentry->d_op = &ecryptfs_dops;
- if (flag)
+ if (flags & ECRYPTFS_INTERPOSE_FLAG_D_ADD)
d_add(dentry, inode);
else
d_instantiate(dentry, inode);
@@ -215,13 +201,6 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
/* This size will be overwritten for real files w/ headers and
* other metadata */
fsstack_copy_inode_size(inode, lower_inode);
- rc = ecryptfs_init_persistent_file(dentry);
- if (rc) {
- printk(KERN_ERR "%s: Error attempting to initialize the "
- "persistent file for the dentry with name [%s]; "
- "rc = [%d]\n", __func__, dentry->d_name.name, rc);
- goto out;
- }
out:
return rc;
}
@@ -262,10 +241,11 @@ static int ecryptfs_init_global_auth_toks(
"session keyring for sig specified in mount "
"option: [%s]\n", global_auth_tok->sig);
global_auth_tok->flags |= ECRYPTFS_AUTH_TOK_INVALID;
- rc = 0;
+ goto out;
} else
global_auth_tok->flags &= ~ECRYPTFS_AUTH_TOK_INVALID;
}
+out:
return rc;
}
@@ -314,7 +294,6 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
char *cipher_name_dst;
char *cipher_name_src;
char *cipher_key_bytes_src;
- int cipher_name_len;
if (!options) {
rc = -EINVAL;
@@ -395,17 +374,12 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
goto out;
}
if (!cipher_name_set) {
- cipher_name_len = strlen(ECRYPTFS_DEFAULT_CIPHER);
- if (unlikely(cipher_name_len
- >= ECRYPTFS_MAX_CIPHER_NAME_SIZE)) {
- rc = -EINVAL;
- BUG();
- goto out;
- }
- memcpy(mount_crypt_stat->global_default_cipher_name,
- ECRYPTFS_DEFAULT_CIPHER, cipher_name_len);
- mount_crypt_stat->global_default_cipher_name[cipher_name_len]
- = '\0';
+ int cipher_name_len = strlen(ECRYPTFS_DEFAULT_CIPHER);
+
+ BUG_ON(cipher_name_len >= ECRYPTFS_MAX_CIPHER_NAME_SIZE);
+
+ strcpy(mount_crypt_stat->global_default_cipher_name,
+ ECRYPTFS_DEFAULT_CIPHER);
}
if (!cipher_key_bytes_set) {
mount_crypt_stat->global_default_cipher_key_size = 0;
@@ -430,7 +404,6 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
printk(KERN_WARNING "One or more global auth toks could not "
"properly register; rc = [%d]\n", rc);
}
- rc = 0;
out:
return rc;
}
@@ -679,6 +652,11 @@ static struct ecryptfs_cache_info {
.name = "ecryptfs_key_tfm_cache",
.size = sizeof(struct ecryptfs_key_tfm),
},
+ {
+ .cache = &ecryptfs_open_req_cache,
+ .name = "ecryptfs_open_req_cache",
+ .size = sizeof(struct ecryptfs_open_req),
+ },
};
static void ecryptfs_free_kmem_caches(void)
@@ -795,11 +773,17 @@ static int __init ecryptfs_init(void)
printk(KERN_ERR "sysfs registration failed\n");
goto out_unregister_filesystem;
}
+ rc = ecryptfs_init_kthread();
+ if (rc) {
+ printk(KERN_ERR "%s: kthread initialization failed; "
+ "rc = [%d]\n", __func__, rc);
+ goto out_do_sysfs_unregistration;
+ }
rc = ecryptfs_init_messaging(ecryptfs_transport);
if (rc) {
- ecryptfs_printk(KERN_ERR, "Failure occured while attempting to "
+ printk(KERN_ERR "Failure occured while attempting to "
"initialize the eCryptfs netlink socket\n");
- goto out_do_sysfs_unregistration;
+ goto out_destroy_kthread;
}
rc = ecryptfs_init_crypto();
if (rc) {
@@ -814,6 +798,8 @@ static int __init ecryptfs_init(void)
goto out;
out_release_messaging:
ecryptfs_release_messaging(ecryptfs_transport);
+out_destroy_kthread:
+ ecryptfs_destroy_kthread();
out_do_sysfs_unregistration:
do_sysfs_unregistration();
out_unregister_filesystem:
@@ -833,6 +819,7 @@ static void __exit ecryptfs_exit(void)
printk(KERN_ERR "Failure whilst attempting to destroy crypto; "
"rc = [%d]\n", rc);
ecryptfs_release_messaging(ecryptfs_transport);
+ ecryptfs_destroy_kthread();
do_sysfs_unregistration();
unregister_filesystem(&ecryptfs_fs_type);
ecryptfs_free_kmem_caches();
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
index 09a4522f65e..b484792a099 100644
--- a/fs/ecryptfs/miscdev.c
+++ b/fs/ecryptfs/miscdev.c
@@ -358,46 +358,6 @@ out_unlock_daemon:
}
/**
- * ecryptfs_miscdev_helo
- * @euid: effective user id of miscdevess sending helo packet
- * @user_ns: The namespace in which @euid applies
- * @pid: miscdevess id of miscdevess sending helo packet
- *
- * Returns zero on success; non-zero otherwise
- */
-static int ecryptfs_miscdev_helo(uid_t euid, struct user_namespace *user_ns,
- struct pid *pid)
-{
- int rc;
-
- rc = ecryptfs_process_helo(ECRYPTFS_TRANSPORT_MISCDEV, euid, user_ns,
- pid);
- if (rc)
- printk(KERN_WARNING "Error processing HELO; rc = [%d]\n", rc);
- return rc;
-}
-
-/**
- * ecryptfs_miscdev_quit
- * @euid: effective user id of miscdevess sending quit packet
- * @user_ns: The namespace in which @euid applies
- * @pid: miscdevess id of miscdevess sending quit packet
- *
- * Returns zero on success; non-zero otherwise
- */
-static int ecryptfs_miscdev_quit(uid_t euid, struct user_namespace *user_ns,
- struct pid *pid)
-{
- int rc;
-
- rc = ecryptfs_process_quit(euid, user_ns, pid);
- if (rc)
- printk(KERN_WARNING
- "Error processing QUIT message; rc = [%d]\n", rc);
- return rc;
-}
-
-/**
* ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon
* @data: Bytes comprising struct ecryptfs_message
* @data_size: sizeof(struct ecryptfs_message) + data len
@@ -512,26 +472,7 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
__func__, rc);
break;
case ECRYPTFS_MSG_HELO:
- rc = ecryptfs_miscdev_helo(current->euid,
- current->nsproxy->user_ns,
- task_pid(current));
- if (rc) {
- printk(KERN_ERR "%s: Error attempting to process "
- "helo from pid [0x%p]; rc = [%d]\n", __func__,
- task_pid(current), rc);
- goto out_free;
- }
- break;
case ECRYPTFS_MSG_QUIT:
- rc = ecryptfs_miscdev_quit(current->euid,
- current->nsproxy->user_ns,
- task_pid(current));
- if (rc) {
- printk(KERN_ERR "%s: Error attempting to process "
- "quit from pid [0x%p]; rc = [%d]\n", __func__,
- task_pid(current), rc);
- goto out_free;
- }
break;
default:
ecryptfs_printk(KERN_WARNING, "Dropping miscdev "
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 2b6fe1e6e8b..245c2dc02d5 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -32,6 +32,7 @@
#include <linux/file.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
+#include <asm/unaligned.h>
#include "ecryptfs_kernel.h"
/**
@@ -372,7 +373,6 @@ out:
*/
static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode)
{
- u64 file_size;
char *file_size_virt;
int rc;
@@ -381,9 +381,7 @@ static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode)
rc = -ENOMEM;
goto out;
}
- file_size = (u64)i_size_read(ecryptfs_inode);
- file_size = cpu_to_be64(file_size);
- memcpy(file_size_virt, &file_size, sizeof(u64));
+ put_unaligned_be64(i_size_read(ecryptfs_inode), file_size_virt);
rc = ecryptfs_write_lower(ecryptfs_inode, file_size_virt, 0,
sizeof(u64));
kfree(file_size_virt);
@@ -403,7 +401,6 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
struct dentry *lower_dentry =
ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_dentry;
struct inode *lower_inode = lower_dentry->d_inode;
- u64 file_size;
int rc;
if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) {
@@ -424,9 +421,7 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
xattr_virt, PAGE_CACHE_SIZE);
if (size < 0)
size = 8;
- file_size = (u64)i_size_read(ecryptfs_inode);
- file_size = cpu_to_be64(file_size);
- memcpy(xattr_virt, &file_size, sizeof(u64));
+ put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
rc = lower_inode->i_op->setxattr(lower_dentry, ECRYPTFS_XATTR_NAME,
xattr_virt, size, 0);
mutex_unlock(&lower_inode->i_mutex);
diff --git a/fs/eventfd.c b/fs/eventfd.c
index 343942deeec..08bf558d040 100644
--- a/fs/eventfd.c
+++ b/fs/eventfd.c
@@ -198,11 +198,18 @@ struct file *eventfd_fget(int fd)
return file;
}
-asmlinkage long sys_eventfd(unsigned int count)
+asmlinkage long sys_eventfd2(unsigned int count, int flags)
{
int fd;
struct eventfd_ctx *ctx;
+ /* Check the EFD_* constants for consistency. */
+ BUILD_BUG_ON(EFD_CLOEXEC != O_CLOEXEC);
+ BUILD_BUG_ON(EFD_NONBLOCK != O_NONBLOCK);
+
+ if (flags & ~(EFD_CLOEXEC | EFD_NONBLOCK))
+ return -EINVAL;
+
ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
@@ -214,9 +221,15 @@ asmlinkage long sys_eventfd(unsigned int count)
* When we call this, the initialization must be complete, since
* anon_inode_getfd() will install the fd.
*/
- fd = anon_inode_getfd("[eventfd]", &eventfd_fops, ctx);
+ fd = anon_inode_getfd("[eventfd]", &eventfd_fops, ctx,
+ flags & (O_CLOEXEC | O_NONBLOCK));
if (fd < 0)
kfree(ctx);
return fd;
}
+asmlinkage long sys_eventfd(unsigned int count)
+{
+ return sys_eventfd2(count, 0);
+}
+
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 990c01d2d66..0c87474f791 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -1046,20 +1046,25 @@ retry:
* RB tree. With the current implementation, the "size" parameter is ignored
* (besides sanity checks).
*/
-asmlinkage long sys_epoll_create(int size)
+asmlinkage long sys_epoll_create1(int flags)
{
int error, fd = -1;
struct eventpoll *ep;
+ /* Check the EPOLL_* constant for consistency. */
+ BUILD_BUG_ON(EPOLL_CLOEXEC != O_CLOEXEC);
+
+ if (flags & ~EPOLL_CLOEXEC)
+ return -EINVAL;
+
DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n",
- current, size));
+ current, flags));
/*
- * Sanity check on the size parameter, and create the internal data
- * structure ( "struct eventpoll" ).
+ * Create the internal data structure ( "struct eventpoll" ).
*/
- error = -EINVAL;
- if (size <= 0 || (error = ep_alloc(&ep)) < 0) {
+ error = ep_alloc(&ep);
+ if (error < 0) {
fd = error;
goto error_return;
}
@@ -1068,17 +1073,26 @@ asmlinkage long sys_epoll_create(int size)
* Creates all the items needed to setup an eventpoll file. That is,
* a file structure and a free file descriptor.
*/
- fd = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep);
+ fd = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep,
+ flags & O_CLOEXEC);
if (fd < 0)
ep_free(ep);
error_return:
DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
- current, size, fd));
+ current, flags, fd));
return fd;
}
+asmlinkage long sys_epoll_create(int size)
+{
+ if (size < 0)
+ return -EINVAL;
+
+ return sys_epoll_create1(0);
+}
+
/*
* The following function implements the controller interface for
* the eventpoll file that enables the insertion/removal/change of
diff --git a/fs/exec.c b/fs/exec.c
index fd9234379e8..5e559013e30 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -25,19 +25,18 @@
#include <linux/slab.h>
#include <linux/file.h>
#include <linux/fdtable.h>
-#include <linux/mman.h>
+#include <linux/mm.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/smp_lock.h>
+#include <linux/swap.h>
#include <linux/string.h>
#include <linux/init.h>
-#include <linux/pagemap.h>
#include <linux/highmem.h>
#include <linux/spinlock.h>
#include <linux/key.h>
#include <linux/personality.h>
#include <linux/binfmts.h>
-#include <linux/swap.h>
#include <linux/utsname.h>
#include <linux/pid_namespace.h>
#include <linux/module.h>
@@ -47,7 +46,6 @@
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/syscalls.h>
-#include <linux/rmap.h>
#include <linux/tsacct_kern.h>
#include <linux/cn_proc.h>
#include <linux/audit.h>
@@ -541,7 +539,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
/*
* when the old and new regions overlap clear from new_end.
*/
- free_pgd_range(&tlb, new_end, old_end, new_end,
+ free_pgd_range(tlb, new_end, old_end, new_end,
vma->vm_next ? vma->vm_next->vm_start : 0);
} else {
/*
@@ -550,7 +548,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
* have constraints on va-space that make this illegal (IA64) -
* for the others its just a little faster.
*/
- free_pgd_range(&tlb, old_start, old_end, new_end,
+ free_pgd_range(tlb, old_start, old_end, new_end,
vma->vm_next ? vma->vm_next->vm_start : 0);
}
tlb_finish_mmu(tlb, new_end, old_end);
@@ -724,12 +722,10 @@ static int exec_mmap(struct mm_struct *mm)
* Make sure that if there is a core dump in progress
* for the old mm, we get out and die instead of going
* through with the exec. We must hold mmap_sem around
- * checking core_waiters and changing tsk->mm. The
- * core-inducing thread will increment core_waiters for
- * each thread whose ->mm == old_mm.
+ * checking core_state and changing tsk->mm.
*/
down_read(&old_mm->mmap_sem);
- if (unlikely(old_mm->core_waiters)) {
+ if (unlikely(old_mm->core_state)) {
up_read(&old_mm->mmap_sem);
return -EINTR;
}
@@ -1328,6 +1324,7 @@ int do_execve(char * filename,
if (retval < 0)
goto out;
+ current->flags &= ~PF_KTHREAD;
retval = search_binary_handler(bprm,regs);
if (retval >= 0) {
/* execve success */
@@ -1382,17 +1379,14 @@ EXPORT_SYMBOL(set_binfmt);
* name into corename, which must have space for at least
* CORENAME_MAX_SIZE bytes plus one byte for the zero terminator.
*/
-static int format_corename(char *corename, const char *pattern, long signr)
+static int format_corename(char *corename, int nr_threads, long signr)
{
- const char *pat_ptr = pattern;
+ const char *pat_ptr = core_pattern;
+ int ispipe = (*pat_ptr == '|');
char *out_ptr = corename;
char *const out_end = corename + CORENAME_MAX_SIZE;
int rc;
int pid_in_pattern = 0;
- int ispipe = 0;
-
- if (*pattern == '|')
- ispipe = 1;
/* Repeat as long as we have more pattern to process and more output
space */
@@ -1493,7 +1487,7 @@ static int format_corename(char *corename, const char *pattern, long signr)
* and core_uses_pid is set, then .%pid will be appended to
* the filename. Do not do this for piped commands. */
if (!ispipe && !pid_in_pattern
- && (core_uses_pid || atomic_read(&current->mm->mm_users) != 1)) {
+ && (core_uses_pid || nr_threads)) {
rc = snprintf(out_ptr, out_end - out_ptr,
".%d", task_tgid_vnr(current));
if (rc > out_end - out_ptr)
@@ -1505,9 +1499,10 @@ out:
return ispipe;
}
-static void zap_process(struct task_struct *start)
+static int zap_process(struct task_struct *start)
{
struct task_struct *t;
+ int nr = 0;
start->signal->flags = SIGNAL_GROUP_EXIT;
start->signal->group_stop_count = 0;
@@ -1515,72 +1510,99 @@ static void zap_process(struct task_struct *start)
t = start;
do {
if (t != current && t->mm) {
- t->mm->core_waiters++;
sigaddset(&t->pending.signal, SIGKILL);
signal_wake_up(t, 1);
+ nr++;
}
- } while ((t = next_thread(t)) != start);
+ } while_each_thread(start, t);
+
+ return nr;
}
static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
- int exit_code)
+ struct core_state *core_state, int exit_code)
{
struct task_struct *g, *p;
unsigned long flags;
- int err = -EAGAIN;
+ int nr = -EAGAIN;
spin_lock_irq(&tsk->sighand->siglock);
if (!signal_group_exit(tsk->signal)) {
+ mm->core_state = core_state;
tsk->signal->group_exit_code = exit_code;
- zap_process(tsk);
- err = 0;
+ nr = zap_process(tsk);
}
spin_unlock_irq(&tsk->sighand->siglock);
- if (err)
- return err;
+ if (unlikely(nr < 0))
+ return nr;
- if (atomic_read(&mm->mm_users) == mm->core_waiters + 1)
+ if (atomic_read(&mm->mm_users) == nr + 1)
goto done;
-
+ /*
+ * We should find and kill all tasks which use this mm, and we should
+ * count them correctly into ->nr_threads. We don't take tasklist
+ * lock, but this is safe wrt:
+ *
+ * fork:
+ * None of sub-threads can fork after zap_process(leader). All
+ * processes which were created before this point should be
+ * visible to zap_threads() because copy_process() adds the new
+ * process to the tail of init_task.tasks list, and lock/unlock
+ * of ->siglock provides a memory barrier.
+ *
+ * do_exit:
+ * The caller holds mm->mmap_sem. This means that the task which
+ * uses this mm can't pass exit_mm(), so it can't exit or clear
+ * its ->mm.
+ *
+ * de_thread:
+ * It does list_replace_rcu(&leader->tasks, &current->tasks),
+ * we must see either old or new leader, this does not matter.
+ * However, it can change p->sighand, so lock_task_sighand(p)
+ * must be used. Since p->mm != NULL and we hold ->mmap_sem
+ * it can't fail.
+ *
+ * Note also that "g" can be the old leader with ->mm == NULL
+ * and already unhashed and thus removed from ->thread_group.
+ * This is OK, __unhash_process()->list_del_rcu() does not
+ * clear the ->next pointer, we will find the new leader via
+ * next_thread().
+ */
rcu_read_lock();
for_each_process(g) {
if (g == tsk->group_leader)
continue;
-
+ if (g->flags & PF_KTHREAD)
+ continue;
p = g;
do {
if (p->mm) {
- if (p->mm == mm) {
- /*
- * p->sighand can't disappear, but
- * may be changed by de_thread()
- */
+ if (unlikely(p->mm == mm)) {
lock_task_sighand(p, &flags);
- zap_process(p);
+ nr += zap_process(p);
unlock_task_sighand(p, &flags);
}
break;
}
- } while ((p = next_thread(p)) != g);
+ } while_each_thread(g, p);
}
rcu_read_unlock();
done:
- return mm->core_waiters;
+ atomic_set(&core_state->nr_threads, nr);
+ return nr;
}
-static int coredump_wait(int exit_code)
+static int coredump_wait(int exit_code, struct core_state *core_state)
{
struct task_struct *tsk = current;
struct mm_struct *mm = tsk->mm;
- struct completion startup_done;
struct completion *vfork_done;
int core_waiters;
- init_completion(&mm->core_done);
- init_completion(&startup_done);
- mm->core_startup_done = &startup_done;
-
- core_waiters = zap_threads(tsk, mm, exit_code);
+ init_completion(&core_state->startup);
+ core_state->dumper.task = tsk;
+ core_state->dumper.next = NULL;
+ core_waiters = zap_threads(tsk, mm, core_state, exit_code);
up_write(&mm->mmap_sem);
if (unlikely(core_waiters < 0))
@@ -1597,12 +1619,32 @@ static int coredump_wait(int exit_code)
}
if (core_waiters)
- wait_for_completion(&startup_done);
+ wait_for_completion(&core_state->startup);
fail:
- BUG_ON(mm->core_waiters);
return core_waiters;
}
+static void coredump_finish(struct mm_struct *mm)
+{
+ struct core_thread *curr, *next;
+ struct task_struct *task;
+
+ next = mm->core_state->dumper.next;
+ while ((curr = next) != NULL) {
+ next = curr->next;
+ task = curr->task;
+ /*
+ * see exit_mm(), curr->task must not see
+ * ->task == NULL before we read ->next.
+ */
+ smp_mb();
+ curr->task = NULL;
+ wake_up_process(task);
+ }
+
+ mm->core_state = NULL;
+}
+
/*
* set_dumpable converts traditional three-value dumpable to two flags and
* stores them into mm->flags. It modifies lower two bits of mm->flags, but
@@ -1654,6 +1696,7 @@ int get_dumpable(struct mm_struct *mm)
int do_coredump(long signr, int exit_code, struct pt_regs * regs)
{
+ struct core_state core_state;
char corename[CORENAME_MAX_SIZE + 1];
struct mm_struct *mm = current->mm;
struct linux_binfmt * binfmt;
@@ -1677,7 +1720,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
/*
* If another thread got here first, or we are not dumpable, bail out.
*/
- if (mm->core_waiters || !get_dumpable(mm)) {
+ if (mm->core_state || !get_dumpable(mm)) {
up_write(&mm->mmap_sem);
goto fail;
}
@@ -1692,7 +1735,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
current->fsuid = 0; /* Dump root private */
}
- retval = coredump_wait(exit_code);
+ retval = coredump_wait(exit_code, &core_state);
if (retval < 0)
goto fail;
@@ -1707,7 +1750,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
* uses lock_kernel()
*/
lock_kernel();
- ispipe = format_corename(corename, core_pattern, signr);
+ ispipe = format_corename(corename, retval, signr);
unlock_kernel();
/*
* Don't bother to check the RLIMIT_CORE value if core_pattern points
@@ -1786,7 +1829,7 @@ fail_unlock:
argv_free(helper_argv);
current->fsuid = fsuid;
- complete_all(&mm->core_done);
+ coredump_finish(mm);
fail:
return retval;
}
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index ef50cbc792d..31308a3b0b8 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -31,6 +31,7 @@
#include <linux/seq_file.h>
#include <linux/mount.h>
#include <linux/log2.h>
+#include <linux/quotaops.h>
#include <asm/uaccess.h>
#include "ext2.h"
#include "xattr.h"
diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c
index eaa23d2d521..70c0dbdcdcb 100644
--- a/fs/ext2/xattr_security.c
+++ b/fs/ext2/xattr_security.c
@@ -14,7 +14,7 @@ static size_t
ext2_xattr_security_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
{
- const int prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
+ const int prefix_len = XATTR_SECURITY_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
if (list && total_len <= list_size) {
diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c
index 83ee149f353..e8219f8eae9 100644
--- a/fs/ext2/xattr_trusted.c
+++ b/fs/ext2/xattr_trusted.c
@@ -12,13 +12,11 @@
#include <linux/ext2_fs.h>
#include "xattr.h"
-#define XATTR_TRUSTED_PREFIX "trusted."
-
static size_t
ext2_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
{
- const int prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1;
+ const int prefix_len = XATTR_TRUSTED_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
if (!capable(CAP_SYS_ADMIN))
diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c
index f383e7c3a7b..92495d28c62 100644
--- a/fs/ext2/xattr_user.c
+++ b/fs/ext2/xattr_user.c
@@ -11,13 +11,11 @@
#include "ext2.h"
#include "xattr.h"
-#define XATTR_USER_PREFIX "user."
-
static size_t
ext2_xattr_user_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
{
- const size_t prefix_len = sizeof(XATTR_USER_PREFIX)-1;
+ const size_t prefix_len = XATTR_USER_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
if (!test_opt(inode->i_sb, XATTR_USER))
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
index 8ca3bfd7242..2eea96ec78e 100644
--- a/fs/ext3/dir.c
+++ b/fs/ext3/dir.c
@@ -272,7 +272,7 @@ static void free_rb_tree_fname(struct rb_root *root)
while (n) {
/* Do the node's children first */
- if ((n)->rb_left) {
+ if (n->rb_left) {
n = n->rb_left;
continue;
}
@@ -301,24 +301,18 @@ static void free_rb_tree_fname(struct rb_root *root)
parent->rb_right = NULL;
n = parent;
}
- root->rb_node = NULL;
}
-static struct dir_private_info *create_dir_info(loff_t pos)
+static struct dir_private_info *ext3_htree_create_dir_info(loff_t pos)
{
struct dir_private_info *p;
- p = kmalloc(sizeof(struct dir_private_info), GFP_KERNEL);
+ p = kzalloc(sizeof(struct dir_private_info), GFP_KERNEL);
if (!p)
return NULL;
- p->root.rb_node = NULL;
- p->curr_node = NULL;
- p->extra_fname = NULL;
- p->last_pos = 0;
p->curr_hash = pos2maj_hash(pos);
p->curr_minor_hash = pos2min_hash(pos);
- p->next_hash = 0;
return p;
}
@@ -433,7 +427,7 @@ static int ext3_dx_readdir(struct file * filp,
int ret;
if (!info) {
- info = create_dir_info(filp->f_pos);
+ info = ext3_htree_create_dir_info(filp->f_pos);
if (!info)
return -ENOMEM;
filp->private_data = info;
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index 77126821b2e..47b678d73e7 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -669,6 +669,14 @@ struct inode *ext3_orphan_get(struct super_block *sb, unsigned long ino)
if (IS_ERR(inode))
goto iget_failed;
+ /*
+ * If the orphans has i_nlinks > 0 then it should be able to be
+ * truncated, otherwise it won't be removed from the orphan list
+ * during processing and an infinite loop will result.
+ */
+ if (inode->i_nlink && !ext3_can_truncate(inode))
+ goto bad_orphan;
+
if (NEXT_ORPHAN(inode) > max_ino)
goto bad_orphan;
brelse(bitmap_bh);
@@ -690,6 +698,7 @@ bad_orphan:
printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n",
NEXT_ORPHAN(inode));
printk(KERN_NOTICE "max_ino=%lu\n", max_ino);
+ printk(KERN_NOTICE "i_nlink=%u\n", inode->i_nlink);
/* Avoid freeing blocks if we got a bad deleted inode */
if (inode->i_nlink == 0)
inode->i_blocks = 0;
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 6ae4ecf3ce4..3bf07d70b91 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -2127,7 +2127,21 @@ static void ext3_free_data(handle_t *handle, struct inode *inode,
if (this_bh) {
BUFFER_TRACE(this_bh, "call ext3_journal_dirty_metadata");
- ext3_journal_dirty_metadata(handle, this_bh);
+
+ /*
+ * The buffer head should have an attached journal head at this
+ * point. However, if the data is corrupted and an indirect
+ * block pointed to itself, it would have been detached when
+ * the block was cleared. Check for this instead of OOPSing.
+ */
+ if (bh2jh(this_bh))
+ ext3_journal_dirty_metadata(handle, this_bh);
+ else
+ ext3_error(inode->i_sb, "ext3_free_data",
+ "circular indirect block detected, "
+ "inode=%lu, block=%llu",
+ inode->i_ino,
+ (unsigned long long)this_bh->b_blocknr);
}
}
@@ -2253,6 +2267,19 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
}
}
+int ext3_can_truncate(struct inode *inode)
+{
+ if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+ return 0;
+ if (S_ISREG(inode->i_mode))
+ return 1;
+ if (S_ISDIR(inode->i_mode))
+ return 1;
+ if (S_ISLNK(inode->i_mode))
+ return !ext3_inode_is_fast_symlink(inode);
+ return 0;
+}
+
/*
* ext3_truncate()
*
@@ -2297,12 +2324,7 @@ void ext3_truncate(struct inode *inode)
unsigned blocksize = inode->i_sb->s_blocksize;
struct page *page;
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
- if (ext3_inode_is_fast_symlink(inode))
- return;
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+ if (!ext3_can_truncate(inode))
return;
/*
@@ -2513,6 +2535,16 @@ static int __ext3_get_inode_loc(struct inode *inode,
}
if (!buffer_uptodate(bh)) {
lock_buffer(bh);
+
+ /*
+ * If the buffer has the write error flag, we have failed
+ * to write out another inode in the same block. In this
+ * case, we don't have to read the block because we may
+ * read the old inode data successfully.
+ */
+ if (buffer_write_io_error(bh) && !buffer_uptodate(bh))
+ set_buffer_uptodate(bh);
+
if (buffer_uptodate(bh)) {
/* someone brought it uptodate while we waited */
unlock_buffer(bh);
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 0b8cf80154f..de13e919cd8 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -240,13 +240,13 @@ static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize)
{
unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(1) -
EXT3_DIR_REC_LEN(2) - infosize;
- return 0? 20: entry_space / sizeof(struct dx_entry);
+ return entry_space / sizeof(struct dx_entry);
}
static inline unsigned dx_node_limit (struct inode *dir)
{
unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(0);
- return 0? 22: entry_space / sizeof(struct dx_entry);
+ return entry_space / sizeof(struct dx_entry);
}
/*
@@ -991,19 +991,21 @@ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
de = (struct ext3_dir_entry_2 *) bh->b_data;
top = (struct ext3_dir_entry_2 *) ((char *) de + sb->s_blocksize -
EXT3_DIR_REC_LEN(0));
- for (; de < top; de = ext3_next_entry(de))
- if (ext3_match (namelen, name, de)) {
- if (!ext3_check_dir_entry("ext3_find_entry",
- dir, de, bh,
- (block<<EXT3_BLOCK_SIZE_BITS(sb))
- +((char *)de - bh->b_data))) {
- brelse (bh);
+ for (; de < top; de = ext3_next_entry(de)) {
+ int off = (block << EXT3_BLOCK_SIZE_BITS(sb))
+ + ((char *) de - bh->b_data);
+
+ if (!ext3_check_dir_entry(__func__, dir, de, bh, off)) {
+ brelse(bh);
*err = ERR_BAD_DX_DIR;
goto errout;
}
- *res_dir = de;
- dx_release (frames);
- return bh;
+
+ if (ext3_match(namelen, name, de)) {
+ *res_dir = de;
+ dx_release(frames);
+ return bh;
+ }
}
brelse (bh);
/* Check to see if we should continue to search */
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 2845425077e..615788c6843 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -842,7 +842,7 @@ static int parse_options (char *options, struct super_block *sb,
int data_opt = 0;
int option;
#ifdef CONFIG_QUOTA
- int qtype;
+ int qtype, qfmt;
char *qname;
#endif
@@ -1018,9 +1018,11 @@ static int parse_options (char *options, struct super_block *sb,
case Opt_grpjquota:
qtype = GRPQUOTA;
set_qf_name:
- if (sb_any_quota_enabled(sb)) {
+ if ((sb_any_quota_enabled(sb) ||
+ sb_any_quota_suspended(sb)) &&
+ !sbi->s_qf_names[qtype]) {
printk(KERN_ERR
- "EXT3-fs: Cannot change journalled "
+ "EXT3-fs: Cannot change journaled "
"quota options when quota turned on.\n");
return 0;
}
@@ -1056,9 +1058,11 @@ set_qf_name:
case Opt_offgrpjquota:
qtype = GRPQUOTA;
clear_qf_name:
- if (sb_any_quota_enabled(sb)) {
+ if ((sb_any_quota_enabled(sb) ||
+ sb_any_quota_suspended(sb)) &&
+ sbi->s_qf_names[qtype]) {
printk(KERN_ERR "EXT3-fs: Cannot change "
- "journalled quota options when "
+ "journaled quota options when "
"quota turned on.\n");
return 0;
}
@@ -1069,10 +1073,20 @@ clear_qf_name:
sbi->s_qf_names[qtype] = NULL;
break;
case Opt_jqfmt_vfsold:
- sbi->s_jquota_fmt = QFMT_VFS_OLD;
- break;
+ qfmt = QFMT_VFS_OLD;
+ goto set_qf_format;
case Opt_jqfmt_vfsv0:
- sbi->s_jquota_fmt = QFMT_VFS_V0;
+ qfmt = QFMT_VFS_V0;
+set_qf_format:
+ if ((sb_any_quota_enabled(sb) ||
+ sb_any_quota_suspended(sb)) &&
+ sbi->s_jquota_fmt != qfmt) {
+ printk(KERN_ERR "EXT3-fs: Cannot change "
+ "journaled quota options when "
+ "quota turned on.\n");
+ return 0;
+ }
+ sbi->s_jquota_fmt = qfmt;
break;
case Opt_quota:
case Opt_usrquota:
@@ -1084,7 +1098,8 @@ clear_qf_name:
set_opt(sbi->s_mount_opt, GRPQUOTA);
break;
case Opt_noquota:
- if (sb_any_quota_enabled(sb)) {
+ if (sb_any_quota_enabled(sb) ||
+ sb_any_quota_suspended(sb)) {
printk(KERN_ERR "EXT3-fs: Cannot change quota "
"options when quota turned on.\n");
return 0;
@@ -1169,14 +1184,14 @@ clear_qf_name:
}
if (!sbi->s_jquota_fmt) {
- printk(KERN_ERR "EXT3-fs: journalled quota format "
+ printk(KERN_ERR "EXT3-fs: journaled quota format "
"not specified.\n");
return 0;
}
} else {
if (sbi->s_jquota_fmt) {
- printk(KERN_ERR "EXT3-fs: journalled quota format "
- "specified with no journalling "
+ printk(KERN_ERR "EXT3-fs: journaled quota format "
+ "specified with no journaling "
"enabled.\n");
return 0;
}
@@ -1370,7 +1385,7 @@ static void ext3_orphan_cleanup (struct super_block * sb,
int ret = ext3_quota_on_mount(sb, i);
if (ret < 0)
printk(KERN_ERR
- "EXT3-fs: Cannot turn on journalled "
+ "EXT3-fs: Cannot turn on journaled "
"quota: error %d\n", ret);
}
}
@@ -2712,7 +2727,7 @@ static int ext3_release_dquot(struct dquot *dquot)
static int ext3_mark_dquot_dirty(struct dquot *dquot)
{
- /* Are we journalling quotas? */
+ /* Are we journaling quotas? */
if (EXT3_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] ||
EXT3_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) {
dquot_mark_dquot_dirty(dquot);
@@ -2759,23 +2774,42 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
if (!test_opt(sb, QUOTA))
return -EINVAL;
- /* Not journalling quota or remount? */
- if ((!EXT3_SB(sb)->s_qf_names[USRQUOTA] &&
- !EXT3_SB(sb)->s_qf_names[GRPQUOTA]) || remount)
+ /* When remounting, no checks are needed and in fact, path is NULL */
+ if (remount)
return vfs_quota_on(sb, type, format_id, path, remount);
+
err = path_lookup(path, LOOKUP_FOLLOW, &nd);
if (err)
return err;
+
/* Quotafile not on the same filesystem? */
if (nd.path.mnt->mnt_sb != sb) {
path_put(&nd.path);
return -EXDEV;
}
- /* Quotafile not in fs root? */
- if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
- printk(KERN_WARNING
- "EXT3-fs: Quota file not on filesystem root. "
- "Journalled quota will not work.\n");
+ /* Journaling quota? */
+ if (EXT3_SB(sb)->s_qf_names[type]) {
+ /* Quotafile not of fs root? */
+ if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
+ printk(KERN_WARNING
+ "EXT3-fs: Quota file not on filesystem root. "
+ "Journaled quota will not work.\n");
+ }
+
+ /*
+ * When we journal data on quota file, we have to flush journal to see
+ * all updates to the file when we bypass pagecache...
+ */
+ if (ext3_should_journal_data(nd.path.dentry->d_inode)) {
+ /*
+ * We don't need to lock updates but journal_flush() could
+ * otherwise be livelocked...
+ */
+ journal_lock_updates(EXT3_SB(sb)->s_journal);
+ journal_flush(EXT3_SB(sb)->s_journal);
+ journal_unlock_updates(EXT3_SB(sb)->s_journal);
+ }
+
path_put(&nd.path);
return vfs_quota_on(sb, type, format_id, path, remount);
}
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c
index 821efaf2b94..37b81097bdf 100644
--- a/fs/ext3/xattr_security.c
+++ b/fs/ext3/xattr_security.c
@@ -15,7 +15,7 @@ static size_t
ext3_xattr_security_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
{
- const size_t prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
+ const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
diff --git a/fs/ext3/xattr_trusted.c b/fs/ext3/xattr_trusted.c
index 0327497a55c..c7c41a410c4 100644
--- a/fs/ext3/xattr_trusted.c
+++ b/fs/ext3/xattr_trusted.c
@@ -13,13 +13,11 @@
#include <linux/ext3_fs.h>
#include "xattr.h"
-#define XATTR_TRUSTED_PREFIX "trusted."
-
static size_t
ext3_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
{
- const size_t prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1;
+ const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
if (!capable(CAP_SYS_ADMIN))
diff --git a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
index 1abd8f92c44..430fe63b31b 100644
--- a/fs/ext3/xattr_user.c
+++ b/fs/ext3/xattr_user.c
@@ -12,13 +12,11 @@
#include <linux/ext3_fs.h>
#include "xattr.h"
-#define XATTR_USER_PREFIX "user."
-
static size_t
ext3_xattr_user_list(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
{
- const size_t prefix_len = sizeof(XATTR_USER_PREFIX)-1;
+ const size_t prefix_len = XATTR_USER_PREFIX_LEN;
const size_t total_len = prefix_len + name_len + 1;
if (!test_opt(inode->i_sb, XATTR_USER))
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 34541d06e62..cd4a0162e10 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -17,7 +17,6 @@
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/msdos_fs.h>
-#include <linux/dirent.h>
#include <linux/smp_lock.h>
#include <linux/buffer_head.h>
#include <linux/compat.h>
@@ -124,10 +123,11 @@ static inline int fat_get_entry(struct inode *dir, loff_t *pos,
* but ignore that right now.
* Ahem... Stack smashing in ring 0 isn't fun. Fixed.
*/
-static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int len,
+static int uni16_to_x8(unsigned char *ascii, const wchar_t *uni, int len,
int uni_xlate, struct nls_table *nls)
{
- wchar_t *ip, ec;
+ const wchar_t *ip;
+ wchar_t ec;
unsigned char *op, nc;
int charlen;
int k;
@@ -167,6 +167,16 @@ static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int len,
return (op - ascii);
}
+static inline int fat_uni_to_x8(struct msdos_sb_info *sbi, const wchar_t *uni,
+ unsigned char *buf, int size)
+{
+ if (sbi->options.utf8)
+ return utf8_wcstombs(buf, uni, size);
+ else
+ return uni16_to_x8(buf, uni, size, sbi->options.unicode_xlate,
+ sbi->nls_io);
+}
+
static inline int
fat_short2uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni)
{
@@ -227,6 +237,19 @@ fat_shortname2uni(struct nls_table *nls, unsigned char *buf, int buf_size,
return len;
}
+static inline int fat_name_match(struct msdos_sb_info *sbi,
+ const unsigned char *a, int a_len,
+ const unsigned char *b, int b_len)
+{
+ if (a_len != b_len)
+ return 0;
+
+ if (sbi->options.name_check != 's')
+ return !nls_strnicmp(sbi->nls_io, a, b, a_len);
+ else
+ return !memcmp(a, b, a_len);
+}
+
enum { PARSE_INVALID = 1, PARSE_NOT_LONGNAME, PARSE_EOF, };
/**
@@ -302,6 +325,19 @@ parse_long:
}
/*
+ * Maximum buffer size of short name.
+ * [(MSDOS_NAME + '.') * max one char + nul]
+ * For msdos style, ['.' (hidden) + MSDOS_NAME + '.' + nul]
+ */
+#define FAT_MAX_SHORT_SIZE ((MSDOS_NAME + 1) * NLS_MAX_CHARSET_SIZE + 1)
+/*
+ * Maximum buffer size of unicode chars from slots.
+ * [(max longname slots * 13 (size in a slot) + nul) * sizeof(wchar_t)]
+ */
+#define FAT_MAX_UNI_CHARS ((MSDOS_SLOTS - 1) * 13 + 1)
+#define FAT_MAX_UNI_SIZE (FAT_MAX_UNI_CHARS * sizeof(wchar_t))
+
+/*
* Return values: negative -> error, 0 -> not found, positive -> found,
* value is the total amount of slots, including the shortname entry.
*/
@@ -312,29 +348,20 @@ int fat_search_long(struct inode *inode, const unsigned char *name,
struct msdos_sb_info *sbi = MSDOS_SB(sb);
struct buffer_head *bh = NULL;
struct msdos_dir_entry *de;
- struct nls_table *nls_io = sbi->nls_io;
struct nls_table *nls_disk = sbi->nls_disk;
- wchar_t bufuname[14];
unsigned char nr_slots;
- int xlate_len;
+ wchar_t bufuname[14];
wchar_t *unicode = NULL;
unsigned char work[MSDOS_NAME];
- unsigned char *bufname = NULL;
- int uni_xlate = sbi->options.unicode_xlate;
- int utf8 = sbi->options.utf8;
- int anycase = (sbi->options.name_check != 's');
+ unsigned char bufname[FAT_MAX_SHORT_SIZE];
unsigned short opt_shortname = sbi->options.shortname;
loff_t cpos = 0;
- int chl, i, j, last_u, err;
-
- bufname = __getname();
- if (!bufname)
- return -ENOMEM;
+ int chl, i, j, last_u, err, len;
err = -ENOENT;
- while(1) {
+ while (1) {
if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
- goto EODir;
+ goto end_of_dir;
parse_record:
nr_slots = 0;
if (de->name[0] == DELETED_FLAG)
@@ -353,7 +380,7 @@ parse_record:
else if (status == PARSE_NOT_LONGNAME)
goto parse_record;
else if (status == PARSE_EOF)
- goto EODir;
+ goto end_of_dir;
}
memcpy(work, de->name, sizeof(de->name));
@@ -394,30 +421,24 @@ parse_record:
if (!last_u)
continue;
+ /* Compare shortname */
bufuname[last_u] = 0x0000;
- xlate_len = utf8
- ?utf8_wcstombs(bufname, bufuname, PATH_MAX)
- :uni16_to_x8(bufname, bufuname, PATH_MAX, uni_xlate, nls_io);
- if (xlate_len == name_len)
- if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
- (anycase && !nls_strnicmp(nls_io, name, bufname,
- xlate_len)))
- goto Found;
+ len = fat_uni_to_x8(sbi, bufuname, bufname, sizeof(bufname));
+ if (fat_name_match(sbi, name, name_len, bufname, len))
+ goto found;
if (nr_slots) {
- xlate_len = utf8
- ?utf8_wcstombs(bufname, unicode, PATH_MAX)
- :uni16_to_x8(bufname, unicode, PATH_MAX, uni_xlate, nls_io);
- if (xlate_len != name_len)
- continue;
- if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
- (anycase && !nls_strnicmp(nls_io, name, bufname,
- xlate_len)))
- goto Found;
+ void *longname = unicode + FAT_MAX_UNI_CHARS;
+ int size = PATH_MAX - FAT_MAX_UNI_SIZE;
+
+ /* Compare longname */
+ len = fat_uni_to_x8(sbi, unicode, longname, size);
+ if (fat_name_match(sbi, name, name_len, longname, len))
+ goto found;
}
}
-Found:
+found:
nr_slots++; /* include the de */
sinfo->slot_off = cpos - nr_slots * sizeof(*de);
sinfo->nr_slots = nr_slots;
@@ -425,9 +446,7 @@ Found:
sinfo->bh = bh;
sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de);
err = 0;
-EODir:
- if (bufname)
- __putname(bufname);
+end_of_dir:
if (unicode)
__putname(unicode);
@@ -453,23 +472,20 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
struct msdos_sb_info *sbi = MSDOS_SB(sb);
struct buffer_head *bh;
struct msdos_dir_entry *de;
- struct nls_table *nls_io = sbi->nls_io;
struct nls_table *nls_disk = sbi->nls_disk;
- unsigned char long_slots;
- const char *fill_name;
- int fill_len;
+ unsigned char nr_slots;
wchar_t bufuname[14];
wchar_t *unicode = NULL;
- unsigned char c, work[MSDOS_NAME], bufname[56], *ptname = bufname;
- unsigned long lpos, dummy, *furrfu = &lpos;
- int uni_xlate = sbi->options.unicode_xlate;
+ unsigned char c, work[MSDOS_NAME];
+ unsigned char bufname[FAT_MAX_SHORT_SIZE], *ptname = bufname;
+ unsigned short opt_shortname = sbi->options.shortname;
int isvfat = sbi->options.isvfat;
- int utf8 = sbi->options.utf8;
int nocase = sbi->options.nocase;
- unsigned short opt_shortname = sbi->options.shortname;
+ const char *fill_name = NULL;
unsigned long inum;
- int chi, chl, i, i2, j, last, last_u, dotoffset = 0;
+ unsigned long lpos, dummy, *furrfu = &lpos;
loff_t cpos;
+ int chi, chl, i, i2, j, last, last_u, dotoffset = 0, fill_len = 0;
int ret = 0;
lock_super(sb);
@@ -489,43 +505,58 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
cpos = 0;
}
}
- if (cpos & (sizeof(struct msdos_dir_entry)-1)) {
+ if (cpos & (sizeof(struct msdos_dir_entry) - 1)) {
ret = -ENOENT;
goto out;
}
bh = NULL;
-GetNew:
+get_new:
if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
- goto EODir;
+ goto end_of_dir;
parse_record:
- long_slots = 0;
- /* Check for long filename entry */
- if (isvfat) {
+ nr_slots = 0;
+ /*
+ * Check for long filename entry, but if short_only, we don't
+ * need to parse long filename.
+ */
+ if (isvfat && !short_only) {
if (de->name[0] == DELETED_FLAG)
- goto RecEnd;
+ goto record_end;
if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME))
- goto RecEnd;
+ goto record_end;
if (de->attr != ATTR_EXT && IS_FREE(de->name))
- goto RecEnd;
+ goto record_end;
} else {
if ((de->attr & ATTR_VOLUME) || IS_FREE(de->name))
- goto RecEnd;
+ goto record_end;
}
if (isvfat && de->attr == ATTR_EXT) {
int status = fat_parse_long(inode, &cpos, &bh, &de,
- &unicode, &long_slots);
+ &unicode, &nr_slots);
if (status < 0) {
filp->f_pos = cpos;
ret = status;
goto out;
} else if (status == PARSE_INVALID)
- goto RecEnd;
+ goto record_end;
else if (status == PARSE_NOT_LONGNAME)
goto parse_record;
else if (status == PARSE_EOF)
- goto EODir;
+ goto end_of_dir;
+
+ if (nr_slots) {
+ void *longname = unicode + FAT_MAX_UNI_CHARS;
+ int size = PATH_MAX - FAT_MAX_UNI_SIZE;
+ int len = fat_uni_to_x8(sbi, unicode, longname, size);
+
+ fill_name = longname;
+ fill_len = len;
+ /* !both && !short_only, so we don't need shortname. */
+ if (!both)
+ goto start_filldir;
+ }
}
if (sbi->options.dotsOK) {
@@ -587,12 +618,32 @@ parse_record:
}
}
if (!last)
- goto RecEnd;
+ goto record_end;
i = last + dotoffset;
j = last_u;
- lpos = cpos - (long_slots+1)*sizeof(struct msdos_dir_entry);
+ if (isvfat) {
+ bufuname[j] = 0x0000;
+ i = fat_uni_to_x8(sbi, bufuname, bufname, sizeof(bufname));
+ }
+ if (nr_slots) {
+ /* hack for fat_ioctl_filldir() */
+ struct fat_ioctl_filldir_callback *p = dirent;
+
+ p->longname = fill_name;
+ p->long_len = fill_len;
+ p->shortname = bufname;
+ p->short_len = i;
+ fill_name = NULL;
+ fill_len = 0;
+ } else {
+ fill_name = bufname;
+ fill_len = i;
+ }
+
+start_filldir:
+ lpos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry);
if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME))
inum = inode->i_ino;
else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
@@ -607,49 +658,17 @@ parse_record:
inum = iunique(sb, MSDOS_ROOT_INO);
}
- if (isvfat) {
- bufuname[j] = 0x0000;
- i = utf8 ? utf8_wcstombs(bufname, bufuname, sizeof(bufname))
- : uni16_to_x8(bufname, bufuname, sizeof(bufname), uni_xlate, nls_io);
- }
-
- fill_name = bufname;
- fill_len = i;
- if (!short_only && long_slots) {
- /* convert the unicode long name. 261 is maximum size
- * of unicode buffer. (13 * slots + nul) */
- void *longname = unicode + 261;
- int buf_size = PATH_MAX - (261 * sizeof(unicode[0]));
- int long_len = utf8
- ? utf8_wcstombs(longname, unicode, buf_size)
- : uni16_to_x8(longname, unicode, buf_size, uni_xlate, nls_io);
-
- if (!both) {
- fill_name = longname;
- fill_len = long_len;
- } else {
- /* hack for fat_ioctl_filldir() */
- struct fat_ioctl_filldir_callback *p = dirent;
-
- p->longname = longname;
- p->long_len = long_len;
- p->shortname = bufname;
- p->short_len = i;
- fill_name = NULL;
- fill_len = 0;
- }
- }
if (filldir(dirent, fill_name, fill_len, *furrfu, inum,
(de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0)
- goto FillFailed;
+ goto fill_failed;
-RecEnd:
+record_end:
furrfu = &lpos;
filp->f_pos = cpos;
- goto GetNew;
-EODir:
+ goto get_new;
+end_of_dir:
filp->f_pos = cpos;
-FillFailed:
+fill_failed:
brelse(bh);
if (unicode)
__putname(unicode);
@@ -715,7 +734,7 @@ efault: \
return -EFAULT; \
}
-FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, dirent)
+FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, __fat_dirent)
static int fat_ioctl_readdir(struct inode *inode, struct file *filp,
void __user *dirent, filldir_t filldir,
@@ -741,7 +760,7 @@ static int fat_ioctl_readdir(struct inode *inode, struct file *filp,
static int fat_dir_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- struct dirent __user *d1 = (struct dirent __user *)arg;
+ struct __fat_dirent __user *d1 = (struct __fat_dirent __user *)arg;
int short_only, both;
switch (cmd) {
@@ -757,7 +776,7 @@ static int fat_dir_ioctl(struct inode *inode, struct file *filp,
return fat_generic_ioctl(inode, filp, cmd, arg);
}
- if (!access_ok(VERIFY_WRITE, d1, sizeof(struct dirent[2])))
+ if (!access_ok(VERIFY_WRITE, d1, sizeof(struct __fat_dirent[2])))
return -EFAULT;
/*
* Yes, we don't need this put_user() absolutely. However old
@@ -1082,7 +1101,7 @@ int fat_alloc_new_dir(struct inode *dir, struct timespec *ts)
goto error_free;
}
- fat_date_unix2dos(ts->tv_sec, &time, &date);
+ fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc);
de = (struct msdos_dir_entry *)bhs[0]->b_data;
/* filling the new directory slots ("." and ".." entries) */
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 46a4508ffd2..23676f9d79c 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -382,17 +382,20 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
& ~((loff_t)sbi->cluster_size - 1)) >> 9;
inode->i_mtime.tv_sec =
- date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date));
+ date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date),
+ sbi->options.tz_utc);
inode->i_mtime.tv_nsec = 0;
if (sbi->options.isvfat) {
int secs = de->ctime_cs / 100;
int csecs = de->ctime_cs % 100;
inode->i_ctime.tv_sec =
date_dos2unix(le16_to_cpu(de->ctime),
- le16_to_cpu(de->cdate)) + secs;
+ le16_to_cpu(de->cdate),
+ sbi->options.tz_utc) + secs;
inode->i_ctime.tv_nsec = csecs * 10000000;
inode->i_atime.tv_sec =
- date_dos2unix(0, le16_to_cpu(de->adate));
+ date_dos2unix(0, le16_to_cpu(de->adate),
+ sbi->options.tz_utc);
inode->i_atime.tv_nsec = 0;
} else
inode->i_ctime = inode->i_atime = inode->i_mtime;
@@ -591,11 +594,14 @@ retry:
raw_entry->attr = fat_attr(inode);
raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart);
raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16);
- fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date);
+ fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time,
+ &raw_entry->date, sbi->options.tz_utc);
if (sbi->options.isvfat) {
__le16 atime;
- fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate);
- fat_date_unix2dos(inode->i_atime.tv_sec,&atime,&raw_entry->adate);
+ fat_date_unix2dos(inode->i_ctime.tv_sec, &raw_entry->ctime,
+ &raw_entry->cdate, sbi->options.tz_utc);
+ fat_date_unix2dos(inode->i_atime.tv_sec, &atime,
+ &raw_entry->adate, sbi->options.tz_utc);
raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 +
inode->i_ctime.tv_nsec / 10000000;
}
@@ -836,6 +842,8 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
}
if (sbi->options.flush)
seq_puts(m, ",flush");
+ if (opts->tz_utc)
+ seq_puts(m, ",tz=UTC");
return 0;
}
@@ -848,7 +856,7 @@ enum {
Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
- Opt_obsolate, Opt_flush, Opt_err,
+ Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_err,
};
static match_table_t fat_tokens = {
@@ -883,6 +891,7 @@ static match_table_t fat_tokens = {
{Opt_obsolate, "cvf_options=%100s"},
{Opt_obsolate, "posix"},
{Opt_flush, "flush"},
+ {Opt_tz_utc, "tz=UTC"},
{Opt_err, NULL},
};
static match_table_t msdos_tokens = {
@@ -947,10 +956,11 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
opts->utf8 = opts->unicode_xlate = 0;
opts->numtail = 1;
opts->usefree = opts->nocase = 0;
+ opts->tz_utc = 0;
*debug = 0;
if (!options)
- return 0;
+ goto out;
while ((p = strsep(&options, ",")) != NULL) {
int token;
@@ -1036,6 +1046,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
case Opt_flush:
opts->flush = 1;
break;
+ case Opt_tz_utc:
+ opts->tz_utc = 1;
+ break;
/* msdos specific */
case Opt_dots:
@@ -1104,10 +1117,13 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
return -EINVAL;
}
}
+
+out:
/* UTF-8 doesn't provide FAT semantics */
if (!strcmp(opts->iocharset, "utf8")) {
printk(KERN_ERR "FAT: utf8 is not a recommended IO charset"
- " for FAT filesystems, filesystem will be case sensitive!\n");
+ " for FAT filesystems, filesystem will be "
+ "case sensitive!\n");
}
/* If user doesn't specify allow_utime, it's initialized from dmask. */
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 61f23511eac..79fb98ad36d 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -142,7 +142,7 @@ static int day_n[] = {
};
/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
-int date_dos2unix(unsigned short time, unsigned short date)
+int date_dos2unix(unsigned short time, unsigned short date, int tz_utc)
{
int month, year, secs;
@@ -156,16 +156,18 @@ int date_dos2unix(unsigned short time, unsigned short date)
((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
month < 2 ? 1 : 0)+3653);
/* days since 1.1.70 plus 80's leap day */
- secs += sys_tz.tz_minuteswest*60;
+ if (!tz_utc)
+ secs += sys_tz.tz_minuteswest*60;
return secs;
}
/* Convert linear UNIX date to a MS-DOS time/date pair. */
-void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
+void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date, int tz_utc)
{
int day, year, nl_day, month;
- unix_date -= sys_tz.tz_minuteswest*60;
+ if (!tz_utc)
+ unix_date -= sys_tz.tz_minuteswest*60;
/* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
if (unix_date < 315532800)
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 330a7d78259..9679fcbdeaa 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -125,13 +125,16 @@ static int dupfd(struct file *file, unsigned int start, int cloexec)
return fd;
}
-asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
+asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags)
{
int err = -EBADF;
struct file * file, *tofree;
struct files_struct * files = current->files;
struct fdtable *fdt;
+ if ((flags & ~O_CLOEXEC) != 0)
+ return -EINVAL;
+
spin_lock(&files->file_lock);
if (!(file = fcheck(oldfd)))
goto out_unlock;
@@ -163,7 +166,10 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
rcu_assign_pointer(fdt->fd[newfd], file);
FD_SET(newfd, fdt->open_fds);
- FD_CLR(newfd, fdt->close_on_exec);
+ if (flags & O_CLOEXEC)
+ FD_SET(newfd, fdt->close_on_exec);
+ else
+ FD_CLR(newfd, fdt->close_on_exec);
spin_unlock(&files->file_lock);
if (tofree)
@@ -181,6 +187,11 @@ out_fput:
goto out;
}
+asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
+{
+ return sys_dup3(oldfd, newfd, 0);
+}
+
asmlinkage long sys_dup(unsigned int fildes)
{
int ret = -EBADF;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 2060bf06b90..51d0035ff07 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -97,7 +97,7 @@ void fuse_invalidate_attr(struct inode *inode)
* timeout is unknown (unlink, rmdir, rename and in some cases
* lookup)
*/
-static void fuse_invalidate_entry_cache(struct dentry *entry)
+void fuse_invalidate_entry_cache(struct dentry *entry)
{
fuse_dentry_settime(entry, 0);
}
@@ -112,18 +112,16 @@ static void fuse_invalidate_entry(struct dentry *entry)
fuse_invalidate_entry_cache(entry);
}
-static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
- struct dentry *entry,
+static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req,
+ u64 nodeid, struct qstr *name,
struct fuse_entry_out *outarg)
{
- struct fuse_conn *fc = get_fuse_conn(dir);
-
memset(outarg, 0, sizeof(struct fuse_entry_out));
req->in.h.opcode = FUSE_LOOKUP;
- req->in.h.nodeid = get_node_id(dir);
+ req->in.h.nodeid = nodeid;
req->in.numargs = 1;
- req->in.args[0].size = entry->d_name.len + 1;
- req->in.args[0].value = entry->d_name.name;
+ req->in.args[0].size = name->len + 1;
+ req->in.args[0].value = name->name;
req->out.numargs = 1;
if (fc->minor < 9)
req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
@@ -189,7 +187,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
attr_version = fuse_get_attr_version(fc);
parent = dget_parent(entry);
- fuse_lookup_init(req, parent->d_inode, entry, &outarg);
+ fuse_lookup_init(fc, req, get_node_id(parent->d_inode),
+ &entry->d_name, &outarg);
request_send(fc, req);
dput(parent);
err = req->out.h.error;
@@ -225,7 +224,7 @@ static int invalid_nodeid(u64 nodeid)
return !nodeid || nodeid == FUSE_ROOT_ID;
}
-static struct dentry_operations fuse_dentry_operations = {
+struct dentry_operations fuse_dentry_operations = {
.d_revalidate = fuse_dentry_revalidate,
};
@@ -239,85 +238,127 @@ int fuse_valid_type(int m)
* Add a directory inode to a dentry, ensuring that no other dentry
* refers to this inode. Called with fc->inst_mutex.
*/
-static int fuse_d_add_directory(struct dentry *entry, struct inode *inode)
+static struct dentry *fuse_d_add_directory(struct dentry *entry,
+ struct inode *inode)
{
struct dentry *alias = d_find_alias(inode);
- if (alias) {
+ if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
/* This tries to shrink the subtree below alias */
fuse_invalidate_entry(alias);
dput(alias);
if (!list_empty(&inode->i_dentry))
- return -EBUSY;
+ return ERR_PTR(-EBUSY);
+ } else {
+ dput(alias);
}
- d_add(entry, inode);
- return 0;
+ return d_splice_alias(inode, entry);
}
-static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
- struct nameidata *nd)
+int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
+ struct fuse_entry_out *outarg, struct inode **inode)
{
- int err;
- struct fuse_entry_out outarg;
- struct inode *inode = NULL;
- struct fuse_conn *fc = get_fuse_conn(dir);
+ struct fuse_conn *fc = get_fuse_conn_super(sb);
struct fuse_req *req;
struct fuse_req *forget_req;
u64 attr_version;
+ int err;
- if (entry->d_name.len > FUSE_NAME_MAX)
- return ERR_PTR(-ENAMETOOLONG);
+ *inode = NULL;
+ err = -ENAMETOOLONG;
+ if (name->len > FUSE_NAME_MAX)
+ goto out;
req = fuse_get_req(fc);
+ err = PTR_ERR(req);
if (IS_ERR(req))
- return ERR_CAST(req);
+ goto out;
forget_req = fuse_get_req(fc);
+ err = PTR_ERR(forget_req);
if (IS_ERR(forget_req)) {
fuse_put_request(fc, req);
- return ERR_CAST(forget_req);
+ goto out;
}
attr_version = fuse_get_attr_version(fc);
- fuse_lookup_init(req, dir, entry, &outarg);
+ fuse_lookup_init(fc, req, nodeid, name, outarg);
request_send(fc, req);
err = req->out.h.error;
fuse_put_request(fc, req);
/* Zero nodeid is same as -ENOENT, but with valid timeout */
- if (!err && outarg.nodeid &&
- (invalid_nodeid(outarg.nodeid) ||
- !fuse_valid_type(outarg.attr.mode)))
- err = -EIO;
- if (!err && outarg.nodeid) {
- inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
- &outarg.attr, entry_attr_timeout(&outarg),
- attr_version);
- if (!inode) {
- fuse_send_forget(fc, forget_req, outarg.nodeid, 1);
- return ERR_PTR(-ENOMEM);
- }
+ if (err || !outarg->nodeid)
+ goto out_put_forget;
+
+ err = -EIO;
+ if (!outarg->nodeid)
+ goto out_put_forget;
+ if (!fuse_valid_type(outarg->attr.mode))
+ goto out_put_forget;
+
+ *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
+ &outarg->attr, entry_attr_timeout(outarg),
+ attr_version);
+ err = -ENOMEM;
+ if (!*inode) {
+ fuse_send_forget(fc, forget_req, outarg->nodeid, 1);
+ goto out;
}
+ err = 0;
+
+ out_put_forget:
fuse_put_request(fc, forget_req);
- if (err && err != -ENOENT)
- return ERR_PTR(err);
+ out:
+ return err;
+}
+
+static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
+ struct nameidata *nd)
+{
+ int err;
+ struct fuse_entry_out outarg;
+ struct inode *inode;
+ struct dentry *newent;
+ struct fuse_conn *fc = get_fuse_conn(dir);
+ bool outarg_valid = true;
+
+ err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
+ &outarg, &inode);
+ if (err == -ENOENT) {
+ outarg_valid = false;
+ err = 0;
+ }
+ if (err)
+ goto out_err;
+
+ err = -EIO;
+ if (inode && get_node_id(inode) == FUSE_ROOT_ID)
+ goto out_iput;
if (inode && S_ISDIR(inode->i_mode)) {
mutex_lock(&fc->inst_mutex);
- err = fuse_d_add_directory(entry, inode);
+ newent = fuse_d_add_directory(entry, inode);
mutex_unlock(&fc->inst_mutex);
- if (err) {
- iput(inode);
- return ERR_PTR(err);
- }
- } else
- d_add(entry, inode);
+ err = PTR_ERR(newent);
+ if (IS_ERR(newent))
+ goto out_iput;
+ } else {
+ newent = d_splice_alias(inode, entry);
+ }
+ entry = newent ? newent : entry;
entry->d_op = &fuse_dentry_operations;
- if (!err)
+ if (outarg_valid)
fuse_change_entry_timeout(entry, &outarg);
else
fuse_invalidate_entry_cache(entry);
- return NULL;
+
+ return newent;
+
+ out_iput:
+ iput(inode);
+ out_err:
+ return ERR_PTR(err);
}
/*
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 8092f0d9fd1..67ff2c6a8f6 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1341,6 +1341,11 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0;
int err;
+ if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
+ /* NLM needs asynchronous locks, which we don't support yet */
+ return -ENOLCK;
+ }
+
/* Unlock on close is handled by the flush method */
if (fl->fl_flags & FL_CLOSE)
return 0;
@@ -1365,7 +1370,9 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
struct fuse_conn *fc = get_fuse_conn(inode);
int err;
- if (cmd == F_GETLK) {
+ if (cmd == F_CANCELLK) {
+ err = 0;
+ } else if (cmd == F_GETLK) {
if (fc->no_lock) {
posix_test_lock(file, fl);
err = 0;
@@ -1373,7 +1380,7 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
err = fuse_getlk(file, fl);
} else {
if (fc->no_lock)
- err = posix_lock_file_wait(file, fl);
+ err = posix_lock_file(file, fl, NULL);
else
err = fuse_setlk(file, fl, 0);
}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index bae948657c4..3a876076bdd 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -363,6 +363,9 @@ struct fuse_conn {
/** Do not send separate SETATTR request before open(O_TRUNC) */
unsigned atomic_o_trunc : 1;
+ /** Filesystem supports NFS exporting. Only set in INIT */
+ unsigned export_support : 1;
+
/*
* The following bitfields are only for optimization purposes
* and hence races in setting them will not cause malfunction
@@ -464,6 +467,8 @@ static inline u64 get_node_id(struct inode *inode)
/** Device operations */
extern const struct file_operations fuse_dev_operations;
+extern struct dentry_operations fuse_dentry_operations;
+
/**
* Get a filled in inode
*/
@@ -471,6 +476,9 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
int generation, struct fuse_attr *attr,
u64 attr_valid, u64 attr_version);
+int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
+ struct fuse_entry_out *outarg, struct inode **inode);
+
/**
* Send FORGET command
*/
@@ -604,6 +612,8 @@ void fuse_abort_conn(struct fuse_conn *fc);
*/
void fuse_invalidate_attr(struct inode *inode);
+void fuse_invalidate_entry_cache(struct dentry *entry);
+
/**
* Acquire reference to fuse_conn
*/
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 3141690558c..7d2f7d6e22e 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -18,6 +18,7 @@
#include <linux/statfs.h>
#include <linux/random.h>
#include <linux/sched.h>
+#include <linux/exportfs.h>
MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
MODULE_DESCRIPTION("Filesystem in Userspace");
@@ -552,6 +553,174 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
return fuse_iget(sb, 1, 0, &attr, 0, 0);
}
+struct fuse_inode_handle
+{
+ u64 nodeid;
+ u32 generation;
+};
+
+static struct dentry *fuse_get_dentry(struct super_block *sb,
+ struct fuse_inode_handle *handle)
+{
+ struct fuse_conn *fc = get_fuse_conn_super(sb);
+ struct inode *inode;
+ struct dentry *entry;
+ int err = -ESTALE;
+
+ if (handle->nodeid == 0)
+ goto out_err;
+
+ inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &handle->nodeid);
+ if (!inode) {
+ struct fuse_entry_out outarg;
+ struct qstr name;
+
+ if (!fc->export_support)
+ goto out_err;
+
+ name.len = 1;
+ name.name = ".";
+ err = fuse_lookup_name(sb, handle->nodeid, &name, &outarg,
+ &inode);
+ if (err && err != -ENOENT)
+ goto out_err;
+ if (err || !inode) {
+ err = -ESTALE;
+ goto out_err;
+ }
+ err = -EIO;
+ if (get_node_id(inode) != handle->nodeid)
+ goto out_iput;
+ }
+ err = -ESTALE;
+ if (inode->i_generation != handle->generation)
+ goto out_iput;
+
+ entry = d_alloc_anon(inode);
+ err = -ENOMEM;
+ if (!entry)
+ goto out_iput;
+
+ if (get_node_id(inode) != FUSE_ROOT_ID) {
+ entry->d_op = &fuse_dentry_operations;
+ fuse_invalidate_entry_cache(entry);
+ }
+
+ return entry;
+
+ out_iput:
+ iput(inode);
+ out_err:
+ return ERR_PTR(err);
+}
+
+static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
+ int connectable)
+{
+ struct inode *inode = dentry->d_inode;
+ bool encode_parent = connectable && !S_ISDIR(inode->i_mode);
+ int len = encode_parent ? 6 : 3;
+ u64 nodeid;
+ u32 generation;
+
+ if (*max_len < len)
+ return 255;
+
+ nodeid = get_fuse_inode(inode)->nodeid;
+ generation = inode->i_generation;
+
+ fh[0] = (u32)(nodeid >> 32);
+ fh[1] = (u32)(nodeid & 0xffffffff);
+ fh[2] = generation;
+
+ if (encode_parent) {
+ struct inode *parent;
+
+ spin_lock(&dentry->d_lock);
+ parent = dentry->d_parent->d_inode;
+ nodeid = get_fuse_inode(parent)->nodeid;
+ generation = parent->i_generation;
+ spin_unlock(&dentry->d_lock);
+
+ fh[3] = (u32)(nodeid >> 32);
+ fh[4] = (u32)(nodeid & 0xffffffff);
+ fh[5] = generation;
+ }
+
+ *max_len = len;
+ return encode_parent ? 0x82 : 0x81;
+}
+
+static struct dentry *fuse_fh_to_dentry(struct super_block *sb,
+ struct fid *fid, int fh_len, int fh_type)
+{
+ struct fuse_inode_handle handle;
+
+ if ((fh_type != 0x81 && fh_type != 0x82) || fh_len < 3)
+ return NULL;
+
+ handle.nodeid = (u64) fid->raw[0] << 32;
+ handle.nodeid |= (u64) fid->raw[1];
+ handle.generation = fid->raw[2];
+ return fuse_get_dentry(sb, &handle);
+}
+
+static struct dentry *fuse_fh_to_parent(struct super_block *sb,
+ struct fid *fid, int fh_len, int fh_type)
+{
+ struct fuse_inode_handle parent;
+
+ if (fh_type != 0x82 || fh_len < 6)
+ return NULL;
+
+ parent.nodeid = (u64) fid->raw[3] << 32;
+ parent.nodeid |= (u64) fid->raw[4];
+ parent.generation = fid->raw[5];
+ return fuse_get_dentry(sb, &parent);
+}
+
+static struct dentry *fuse_get_parent(struct dentry *child)
+{
+ struct inode *child_inode = child->d_inode;
+ struct fuse_conn *fc = get_fuse_conn(child_inode);
+ struct inode *inode;
+ struct dentry *parent;
+ struct fuse_entry_out outarg;
+ struct qstr name;
+ int err;
+
+ if (!fc->export_support)
+ return ERR_PTR(-ESTALE);
+
+ name.len = 2;
+ name.name = "..";
+ err = fuse_lookup_name(child_inode->i_sb, get_node_id(child_inode),
+ &name, &outarg, &inode);
+ if (err && err != -ENOENT)
+ return ERR_PTR(err);
+ if (err || !inode)
+ return ERR_PTR(-ESTALE);
+
+ parent = d_alloc_anon(inode);
+ if (!parent) {
+ iput(inode);
+ return ERR_PTR(-ENOMEM);
+ }
+ if (get_node_id(inode) != FUSE_ROOT_ID) {
+ parent->d_op = &fuse_dentry_operations;
+ fuse_invalidate_entry_cache(parent);
+ }
+
+ return parent;
+}
+
+static const struct export_operations fuse_export_operations = {
+ .fh_to_dentry = fuse_fh_to_dentry,
+ .fh_to_parent = fuse_fh_to_parent,
+ .encode_fh = fuse_encode_fh,
+ .get_parent = fuse_get_parent,
+};
+
static const struct super_operations fuse_super_operations = {
.alloc_inode = fuse_alloc_inode,
.destroy_inode = fuse_destroy_inode,
@@ -581,6 +750,11 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
fc->no_lock = 1;
if (arg->flags & FUSE_ATOMIC_O_TRUNC)
fc->atomic_o_trunc = 1;
+ if (arg->minor >= 9) {
+ /* LOOKUP has dependency on proto version */
+ if (arg->flags & FUSE_EXPORT_SUPPORT)
+ fc->export_support = 1;
+ }
if (arg->flags & FUSE_BIG_WRITES)
fc->big_writes = 1;
} else {
@@ -607,7 +781,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
arg->minor = FUSE_KERNEL_MINOR_VERSION;
arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |
- FUSE_BIG_WRITES;
+ FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES;
req->in.h.opcode = FUSE_INIT;
req->in.numargs = 1;
req->in.args[0].size = sizeof(*arg);
@@ -652,6 +826,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
sb->s_magic = FUSE_SUPER_MAGIC;
sb->s_op = &fuse_super_operations;
sb->s_maxbytes = MAX_LFS_FILESIZE;
+ sb->s_export_op = &fuse_export_operations;
file = fget(d.fd);
if (!file)
diff --git a/fs/hfs/bitmap.c b/fs/hfs/bitmap.c
index 24e75798ddf..c6e97366e8a 100644
--- a/fs/hfs/bitmap.c
+++ b/fs/hfs/bitmap.c
@@ -145,7 +145,7 @@ u32 hfs_vbm_search_free(struct super_block *sb, u32 goal, u32 *num_bits)
if (!*num_bits)
return 0;
- down(&HFS_SB(sb)->bitmap_lock);
+ mutex_lock(&HFS_SB(sb)->bitmap_lock);
bitmap = HFS_SB(sb)->bitmap;
pos = hfs_find_set_zero_bits(bitmap, HFS_SB(sb)->fs_ablocks, goal, num_bits);
@@ -162,7 +162,7 @@ u32 hfs_vbm_search_free(struct super_block *sb, u32 goal, u32 *num_bits)
HFS_SB(sb)->free_ablocks -= *num_bits;
hfs_bitmap_dirty(sb);
out:
- up(&HFS_SB(sb)->bitmap_lock);
+ mutex_unlock(&HFS_SB(sb)->bitmap_lock);
return pos;
}
@@ -205,7 +205,7 @@ int hfs_clear_vbm_bits(struct super_block *sb, u16 start, u16 count)
if ((start + count) > HFS_SB(sb)->fs_ablocks)
return -2;
- down(&HFS_SB(sb)->bitmap_lock);
+ mutex_lock(&HFS_SB(sb)->bitmap_lock);
/* bitmap is always on a 32-bit boundary */
curr = HFS_SB(sb)->bitmap + (start / 32);
len = count;
@@ -236,7 +236,7 @@ int hfs_clear_vbm_bits(struct super_block *sb, u16 start, u16 count)
}
out:
HFS_SB(sb)->free_ablocks += len;
- up(&HFS_SB(sb)->bitmap_lock);
+ mutex_unlock(&HFS_SB(sb)->bitmap_lock);
hfs_bitmap_dirty(sb);
return 0;
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
index f6621a78520..9b9d6395bad 100644
--- a/fs/hfs/btree.c
+++ b/fs/hfs/btree.c
@@ -40,7 +40,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
{
struct hfs_mdb *mdb = HFS_SB(sb)->mdb;
HFS_I(tree->inode)->flags = 0;
- init_MUTEX(&HFS_I(tree->inode)->extents_lock);
+ mutex_init(&HFS_I(tree->inode)->extents_lock);
switch (id) {
case HFS_EXT_CNID:
hfs_inode_read_fork(tree->inode, mdb->drXTExtRec, mdb->drXTFlSize,
diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c
index c176f67ba0a..2c16316d291 100644
--- a/fs/hfs/extent.c
+++ b/fs/hfs/extent.c
@@ -343,16 +343,16 @@ int hfs_get_block(struct inode *inode, sector_t block,
goto done;
}
- down(&HFS_I(inode)->extents_lock);
+ mutex_lock(&HFS_I(inode)->extents_lock);
res = hfs_ext_read_extent(inode, ablock);
if (!res)
dblock = hfs_ext_find_block(HFS_I(inode)->cached_extents,
ablock - HFS_I(inode)->cached_start);
else {
- up(&HFS_I(inode)->extents_lock);
+ mutex_unlock(&HFS_I(inode)->extents_lock);
return -EIO;
}
- up(&HFS_I(inode)->extents_lock);
+ mutex_unlock(&HFS_I(inode)->extents_lock);
done:
map_bh(bh_result, sb, HFS_SB(sb)->fs_start +
@@ -375,7 +375,7 @@ int hfs_extend_file(struct inode *inode)
u32 start, len, goal;
int res;
- down(&HFS_I(inode)->extents_lock);
+ mutex_lock(&HFS_I(inode)->extents_lock);
if (HFS_I(inode)->alloc_blocks == HFS_I(inode)->first_blocks)
goal = hfs_ext_lastblock(HFS_I(inode)->first_extents);
else {
@@ -425,7 +425,7 @@ int hfs_extend_file(struct inode *inode)
goto insert_extent;
}
out:
- up(&HFS_I(inode)->extents_lock);
+ mutex_unlock(&HFS_I(inode)->extents_lock);
if (!res) {
HFS_I(inode)->alloc_blocks += len;
mark_inode_dirty(inode);
@@ -487,7 +487,7 @@ void hfs_file_truncate(struct inode *inode)
if (blk_cnt == alloc_cnt)
goto out;
- down(&HFS_I(inode)->extents_lock);
+ mutex_lock(&HFS_I(inode)->extents_lock);
hfs_find_init(HFS_SB(sb)->ext_tree, &fd);
while (1) {
if (alloc_cnt == HFS_I(inode)->first_blocks) {
@@ -514,7 +514,7 @@ void hfs_file_truncate(struct inode *inode)
hfs_brec_remove(&fd);
}
hfs_find_exit(&fd);
- up(&HFS_I(inode)->extents_lock);
+ mutex_unlock(&HFS_I(inode)->extents_lock);
HFS_I(inode)->alloc_blocks = blk_cnt;
out:
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 147374b6f67..9955232fdf8 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -11,6 +11,7 @@
#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/mutex.h>
#include <linux/buffer_head.h>
#include <linux/fs.h>
@@ -53,7 +54,7 @@ struct hfs_inode_info {
struct list_head open_dir_list;
struct inode *rsrc_inode;
- struct semaphore extents_lock;
+ struct mutex extents_lock;
u16 alloc_blocks, clump_blocks;
sector_t fs_blocks;
@@ -139,7 +140,7 @@ struct hfs_sb_info {
struct nls_table *nls_io, *nls_disk;
- struct semaphore bitmap_lock;
+ struct mutex bitmap_lock;
unsigned long flags;
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 97f8446c4ff..dc4ec640e87 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -150,7 +150,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
if (!inode)
return NULL;
- init_MUTEX(&HFS_I(inode)->extents_lock);
+ mutex_init(&HFS_I(inode)->extents_lock);
INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
hfs_cat_build_key(sb, (btree_key *)&HFS_I(inode)->cat_key, dir->i_ino, name);
inode->i_ino = HFS_SB(sb)->next_id++;
@@ -281,7 +281,7 @@ static int hfs_read_inode(struct inode *inode, void *data)
HFS_I(inode)->flags = 0;
HFS_I(inode)->rsrc_inode = NULL;
- init_MUTEX(&HFS_I(inode)->extents_lock);
+ mutex_init(&HFS_I(inode)->extents_lock);
INIT_LIST_HEAD(&HFS_I(inode)->open_dir_list);
/* Initialize the inode */
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 8cf67974adf..ac2ec5ef66e 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -372,7 +372,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_op = &hfs_super_operations;
sb->s_flags |= MS_NODIRATIME;
- init_MUTEX(&sbi->bitmap_lock);
+ mutex_init(&sbi->bitmap_lock);
res = hfs_mdb_get(sb);
if (res) {
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index 12e899cd788..fec8f61227f 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -199,16 +199,16 @@ int hfsplus_get_block(struct inode *inode, sector_t iblock,
goto done;
}
- down(&HFSPLUS_I(inode).extents_lock);
+ mutex_lock(&HFSPLUS_I(inode).extents_lock);
res = hfsplus_ext_read_extent(inode, ablock);
if (!res) {
dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).cached_extents, ablock -
HFSPLUS_I(inode).cached_start);
} else {
- up(&HFSPLUS_I(inode).extents_lock);
+ mutex_unlock(&HFSPLUS_I(inode).extents_lock);
return -EIO;
}
- up(&HFSPLUS_I(inode).extents_lock);
+ mutex_unlock(&HFSPLUS_I(inode).extents_lock);
done:
dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock);
@@ -355,7 +355,7 @@ int hfsplus_file_extend(struct inode *inode)
return -ENOSPC;
}
- down(&HFSPLUS_I(inode).extents_lock);
+ mutex_lock(&HFSPLUS_I(inode).extents_lock);
if (HFSPLUS_I(inode).alloc_blocks == HFSPLUS_I(inode).first_blocks)
goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).first_extents);
else {
@@ -408,7 +408,7 @@ int hfsplus_file_extend(struct inode *inode)
goto insert_extent;
}
out:
- up(&HFSPLUS_I(inode).extents_lock);
+ mutex_unlock(&HFSPLUS_I(inode).extents_lock);
if (!res) {
HFSPLUS_I(inode).alloc_blocks += len;
mark_inode_dirty(inode);
@@ -465,7 +465,7 @@ void hfsplus_file_truncate(struct inode *inode)
if (blk_cnt == alloc_cnt)
goto out;
- down(&HFSPLUS_I(inode).extents_lock);
+ mutex_lock(&HFSPLUS_I(inode).extents_lock);
hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd);
while (1) {
if (alloc_cnt == HFSPLUS_I(inode).first_blocks) {
@@ -492,7 +492,7 @@ void hfsplus_file_truncate(struct inode *inode)
hfs_brec_remove(&fd);
}
hfs_find_exit(&fd);
- up(&HFSPLUS_I(inode).extents_lock);
+ mutex_unlock(&HFSPLUS_I(inode).extents_lock);
HFSPLUS_I(inode).alloc_blocks = blk_cnt;
out:
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 9e59537b43d..f027a905225 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -11,6 +11,7 @@
#define _LINUX_HFSPLUS_FS_H
#include <linux/fs.h>
+#include <linux/mutex.h>
#include <linux/buffer_head.h>
#include "hfsplus_raw.h"
@@ -154,7 +155,7 @@ struct hfsplus_sb_info {
struct hfsplus_inode_info {
- struct semaphore extents_lock;
+ struct mutex extents_lock;
u32 clump_blocks, alloc_blocks;
sector_t fs_blocks;
/* Allocation extents from catalog record or volume header */
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 67e1c8b467c..cc3b5e24339 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -163,7 +163,7 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent
inode->i_ino = dir->i_ino;
INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
- init_MUTEX(&HFSPLUS_I(inode).extents_lock);
+ mutex_init(&HFSPLUS_I(inode).extents_lock);
HFSPLUS_I(inode).flags = HFSPLUS_FLG_RSRC;
hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
@@ -316,7 +316,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
inode->i_nlink = 1;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
- init_MUTEX(&HFSPLUS_I(inode).extents_lock);
+ mutex_init(&HFSPLUS_I(inode).extents_lock);
atomic_set(&HFSPLUS_I(inode).opencnt, 0);
HFSPLUS_I(inode).flags = 0;
memset(HFSPLUS_I(inode).first_extents, 0, sizeof(hfsplus_extent_rec));
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index ce97a54518d..3859118531c 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -34,7 +34,7 @@ struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino)
return inode;
INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
- init_MUTEX(&HFSPLUS_I(inode).extents_lock);
+ mutex_init(&HFSPLUS_I(inode).extents_lock);
HFSPLUS_I(inode).flags = 0;
HFSPLUS_I(inode).rsrc_inode = NULL;
atomic_set(&HFSPLUS_I(inode).opencnt, 0);
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index aeabf80f81a..dbd01d262ca 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -53,6 +53,7 @@ int sysctl_hugetlb_shm_group;
enum {
Opt_size, Opt_nr_inodes,
Opt_mode, Opt_uid, Opt_gid,
+ Opt_pagesize,
Opt_err,
};
@@ -62,6 +63,7 @@ static match_table_t tokens = {
{Opt_mode, "mode=%o"},
{Opt_uid, "uid=%u"},
{Opt_gid, "gid=%u"},
+ {Opt_pagesize, "pagesize=%s"},
{Opt_err, NULL},
};
@@ -80,6 +82,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
struct inode *inode = file->f_path.dentry->d_inode;
loff_t len, vma_len;
int ret;
+ struct hstate *h = hstate_file(file);
/*
* vma address alignment (but not the pgoff alignment) has
@@ -92,7 +95,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
vma->vm_flags |= VM_HUGETLB | VM_RESERVED;
vma->vm_ops = &hugetlb_vm_ops;
- if (vma->vm_pgoff & ~(HPAGE_MASK >> PAGE_SHIFT))
+ if (vma->vm_pgoff & ~(huge_page_mask(h) >> PAGE_SHIFT))
return -EINVAL;
vma_len = (loff_t)(vma->vm_end - vma->vm_start);
@@ -103,9 +106,9 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
ret = -ENOMEM;
len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
- if (vma->vm_flags & VM_MAYSHARE &&
- hugetlb_reserve_pages(inode, vma->vm_pgoff >> (HPAGE_SHIFT-PAGE_SHIFT),
- len >> HPAGE_SHIFT))
+ if (hugetlb_reserve_pages(inode,
+ vma->vm_pgoff >> huge_page_order(h),
+ len >> huge_page_shift(h), vma))
goto out;
ret = 0;
@@ -130,20 +133,21 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
unsigned long start_addr;
+ struct hstate *h = hstate_file(file);
- if (len & ~HPAGE_MASK)
+ if (len & ~huge_page_mask(h))
return -EINVAL;
if (len > TASK_SIZE)
return -ENOMEM;
if (flags & MAP_FIXED) {
- if (prepare_hugepage_range(addr, len))
+ if (prepare_hugepage_range(file, addr, len))
return -EINVAL;
return addr;
}
if (addr) {
- addr = ALIGN(addr, HPAGE_SIZE);
+ addr = ALIGN(addr, huge_page_size(h));
vma = find_vma(mm, addr);
if (TASK_SIZE - len >= addr &&
(!vma || addr + len <= vma->vm_start))
@@ -156,7 +160,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
start_addr = TASK_UNMAPPED_BASE;
full_search:
- addr = ALIGN(start_addr, HPAGE_SIZE);
+ addr = ALIGN(start_addr, huge_page_size(h));
for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
/* At this point: (!vma || addr < vma->vm_end). */
@@ -174,7 +178,7 @@ full_search:
if (!vma || addr + len <= vma->vm_start)
return addr;
- addr = ALIGN(vma->vm_end, HPAGE_SIZE);
+ addr = ALIGN(vma->vm_end, huge_page_size(h));
}
}
#endif
@@ -225,10 +229,11 @@ hugetlbfs_read_actor(struct page *page, unsigned long offset,
static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
size_t len, loff_t *ppos)
{
+ struct hstate *h = hstate_file(filp);
struct address_space *mapping = filp->f_mapping;
struct inode *inode = mapping->host;
- unsigned long index = *ppos >> HPAGE_SHIFT;
- unsigned long offset = *ppos & ~HPAGE_MASK;
+ unsigned long index = *ppos >> huge_page_shift(h);
+ unsigned long offset = *ppos & ~huge_page_mask(h);
unsigned long end_index;
loff_t isize;
ssize_t retval = 0;
@@ -243,17 +248,17 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
if (!isize)
goto out;
- end_index = (isize - 1) >> HPAGE_SHIFT;
+ end_index = (isize - 1) >> huge_page_shift(h);
for (;;) {
struct page *page;
- int nr, ret;
+ unsigned long nr, ret;
/* nr is the maximum number of bytes to copy from this page */
- nr = HPAGE_SIZE;
+ nr = huge_page_size(h);
if (index >= end_index) {
if (index > end_index)
goto out;
- nr = ((isize - 1) & ~HPAGE_MASK) + 1;
+ nr = ((isize - 1) & ~huge_page_mask(h)) + 1;
if (nr <= offset) {
goto out;
}
@@ -287,8 +292,8 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
offset += ret;
retval += ret;
len -= ret;
- index += offset >> HPAGE_SHIFT;
- offset &= ~HPAGE_MASK;
+ index += offset >> huge_page_shift(h);
+ offset &= ~huge_page_mask(h);
if (page)
page_cache_release(page);
@@ -298,7 +303,7 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
break;
}
out:
- *ppos = ((loff_t)index << HPAGE_SHIFT) + offset;
+ *ppos = ((loff_t)index << huge_page_shift(h)) + offset;
mutex_unlock(&inode->i_mutex);
return retval;
}
@@ -339,8 +344,9 @@ static void truncate_huge_page(struct page *page)
static void truncate_hugepages(struct inode *inode, loff_t lstart)
{
+ struct hstate *h = hstate_inode(inode);
struct address_space *mapping = &inode->i_data;
- const pgoff_t start = lstart >> HPAGE_SHIFT;
+ const pgoff_t start = lstart >> huge_page_shift(h);
struct pagevec pvec;
pgoff_t next;
int i, freed = 0;
@@ -441,7 +447,7 @@ hugetlb_vmtruncate_list(struct prio_tree_root *root, pgoff_t pgoff)
v_offset = 0;
__unmap_hugepage_range(vma,
- vma->vm_start + v_offset, vma->vm_end);
+ vma->vm_start + v_offset, vma->vm_end, NULL);
}
}
@@ -449,8 +455,9 @@ static int hugetlb_vmtruncate(struct inode *inode, loff_t offset)
{
pgoff_t pgoff;
struct address_space *mapping = inode->i_mapping;
+ struct hstate *h = hstate_inode(inode);
- BUG_ON(offset & ~HPAGE_MASK);
+ BUG_ON(offset & ~huge_page_mask(h));
pgoff = offset >> PAGE_SHIFT;
i_size_write(inode, offset);
@@ -465,6 +472,7 @@ static int hugetlb_vmtruncate(struct inode *inode, loff_t offset)
static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
+ struct hstate *h = hstate_inode(inode);
int error;
unsigned int ia_valid = attr->ia_valid;
@@ -476,7 +484,7 @@ static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
if (ia_valid & ATTR_SIZE) {
error = -EINVAL;
- if (!(attr->ia_size & ~HPAGE_MASK))
+ if (!(attr->ia_size & ~huge_page_mask(h)))
error = hugetlb_vmtruncate(inode, attr->ia_size);
if (error)
goto out;
@@ -610,9 +618,10 @@ static int hugetlbfs_set_page_dirty(struct page *page)
static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb);
+ struct hstate *h = hstate_inode(dentry->d_inode);
buf->f_type = HUGETLBFS_MAGIC;
- buf->f_bsize = HPAGE_SIZE;
+ buf->f_bsize = huge_page_size(h);
if (sbinfo) {
spin_lock(&sbinfo->stat_lock);
/* If no limits set, just report 0 for max/free/used
@@ -743,6 +752,8 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
char *p, *rest;
substring_t args[MAX_OPT_ARGS];
int option;
+ unsigned long long size = 0;
+ enum { NO_SIZE, SIZE_STD, SIZE_PERCENT } setsize = NO_SIZE;
if (!options)
return 0;
@@ -773,17 +784,13 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
break;
case Opt_size: {
- unsigned long long size;
/* memparse() will accept a K/M/G without a digit */
if (!isdigit(*args[0].from))
goto bad_val;
size = memparse(args[0].from, &rest);
- if (*rest == '%') {
- size <<= HPAGE_SHIFT;
- size *= max_huge_pages;
- do_div(size, 100);
- }
- pconfig->nr_blocks = (size >> HPAGE_SHIFT);
+ setsize = SIZE_STD;
+ if (*rest == '%')
+ setsize = SIZE_PERCENT;
break;
}
@@ -794,6 +801,19 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
pconfig->nr_inodes = memparse(args[0].from, &rest);
break;
+ case Opt_pagesize: {
+ unsigned long ps;
+ ps = memparse(args[0].from, &rest);
+ pconfig->hstate = size_to_hstate(ps);
+ if (!pconfig->hstate) {
+ printk(KERN_ERR
+ "hugetlbfs: Unsupported page size %lu MB\n",
+ ps >> 20);
+ return -EINVAL;
+ }
+ break;
+ }
+
default:
printk(KERN_ERR "hugetlbfs: Bad mount option: \"%s\"\n",
p);
@@ -801,6 +821,18 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
break;
}
}
+
+ /* Do size after hstate is set up */
+ if (setsize > NO_SIZE) {
+ struct hstate *h = pconfig->hstate;
+ if (setsize == SIZE_PERCENT) {
+ size <<= huge_page_shift(h);
+ size *= h->max_huge_pages;
+ do_div(size, 100);
+ }
+ pconfig->nr_blocks = (size >> huge_page_shift(h));
+ }
+
return 0;
bad_val:
@@ -825,6 +857,7 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
config.uid = current->fsuid;
config.gid = current->fsgid;
config.mode = 0755;
+ config.hstate = &default_hstate;
ret = hugetlbfs_parse_options(data, &config);
if (ret)
return ret;
@@ -833,14 +866,15 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
if (!sbinfo)
return -ENOMEM;
sb->s_fs_info = sbinfo;
+ sbinfo->hstate = config.hstate;
spin_lock_init(&sbinfo->stat_lock);
sbinfo->max_blocks = config.nr_blocks;
sbinfo->free_blocks = config.nr_blocks;
sbinfo->max_inodes = config.nr_inodes;
sbinfo->free_inodes = config.nr_inodes;
sb->s_maxbytes = MAX_LFS_FILESIZE;
- sb->s_blocksize = HPAGE_SIZE;
- sb->s_blocksize_bits = HPAGE_SHIFT;
+ sb->s_blocksize = huge_page_size(config.hstate);
+ sb->s_blocksize_bits = huge_page_shift(config.hstate);
sb->s_magic = HUGETLBFS_MAGIC;
sb->s_op = &hugetlbfs_ops;
sb->s_time_gran = 1;
@@ -942,7 +976,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size)
goto out_dentry;
error = -ENOMEM;
- if (hugetlb_reserve_pages(inode, 0, size >> HPAGE_SHIFT))
+ if (hugetlb_reserve_pages(inode, 0,
+ size >> huge_page_shift(hstate_inode(inode)), NULL))
goto out_inode;
d_instantiate(dentry, inode);
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
index 6676c06bb7c..fe79c25d95d 100644
--- a/fs/inotify_user.c
+++ b/fs/inotify_user.c
@@ -566,7 +566,7 @@ static const struct inotify_operations inotify_user_ops = {
.destroy_watch = free_inotify_user_watch,
};
-asmlinkage long sys_inotify_init(void)
+asmlinkage long sys_inotify_init1(int flags)
{
struct inotify_device *dev;
struct inotify_handle *ih;
@@ -574,7 +574,14 @@ asmlinkage long sys_inotify_init(void)
struct file *filp;
int fd, ret;
- fd = get_unused_fd();
+ /* Check the IN_* constants for consistency. */
+ BUILD_BUG_ON(IN_CLOEXEC != O_CLOEXEC);
+ BUILD_BUG_ON(IN_NONBLOCK != O_NONBLOCK);
+
+ if (flags & ~(IN_CLOEXEC | IN_NONBLOCK))
+ return -EINVAL;
+
+ fd = get_unused_fd_flags(flags & O_CLOEXEC);
if (fd < 0)
return fd;
@@ -610,7 +617,7 @@ asmlinkage long sys_inotify_init(void)
filp->f_path.dentry = dget(inotify_mnt->mnt_root);
filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping;
filp->f_mode = FMODE_READ;
- filp->f_flags = O_RDONLY;
+ filp->f_flags = O_RDONLY | (flags & O_NONBLOCK);
filp->private_data = dev;
INIT_LIST_HEAD(&dev->events);
@@ -638,6 +645,11 @@ out_put_fd:
return ret;
}
+asmlinkage long sys_inotify_init(void)
+{
+ return sys_inotify_init1(0);
+}
+
asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
{
struct inode *inode;
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 6bd48f0a704..c2fb2dd0131 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -209,6 +209,11 @@ repeat:
while (rs.len > 2) { /* There may be one byte for padding somewhere */
rr = (struct rock_ridge *)rs.chr;
+ /*
+ * Ignore rock ridge info if rr->len is out of range, but
+ * don't return -EIO because that would make the file
+ * invisible.
+ */
if (rr->len < 3)
goto out; /* Something got screwed up here */
sig = isonum_721(rs.chr);
@@ -216,8 +221,12 @@ repeat:
goto eio;
rs.chr += rr->len;
rs.len -= rr->len;
+ /*
+ * As above, just ignore the rock ridge info if rr->len
+ * is bogus.
+ */
if (rs.len < 0)
- goto eio; /* corrupted isofs */
+ goto out; /* Something got screwed up here */
switch (sig) {
case SIG('R', 'R'):
@@ -307,6 +316,11 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de,
repeat:
while (rs.len > 2) { /* There may be one byte for padding somewhere */
rr = (struct rock_ridge *)rs.chr;
+ /*
+ * Ignore rock ridge info if rr->len is out of range, but
+ * don't return -EIO because that would make the file
+ * invisible.
+ */
if (rr->len < 3)
goto out; /* Something got screwed up here */
sig = isonum_721(rs.chr);
@@ -314,8 +328,12 @@ repeat:
goto eio;
rs.chr += rr->len;
rs.len -= rr->len;
+ /*
+ * As above, just ignore the rock ridge info if rr->len
+ * is bogus.
+ */
if (rs.len < 0)
- goto eio; /* corrupted isofs */
+ goto out; /* Something got screwed up here */
switch (sig) {
#ifndef CONFIG_ZISOFS /* No flag for SF or ZF */
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 5a8ca61498c..2eccbfaa1d4 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -36,7 +36,7 @@ static void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
/*
* When an ext3-ordered file is truncated, it is possible that many pages are
- * not sucessfully freed, because they are attached to a committing transaction.
+ * not successfully freed, because they are attached to a committing transaction.
* After the transaction commits, these pages are left on the LRU, with no
* ->mapping, and with attached buffers. These pages are trivially reclaimable
* by the VM, but their apparent absence upsets the VM accounting, and it makes
@@ -45,8 +45,8 @@ static void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
* So here, we have a buffer which has just come off the forget list. Look to
* see if we can strip all buffers from the backing page.
*
- * Called under lock_journal(), and possibly under journal_datalist_lock. The
- * caller provided us with a ref against the buffer, and we drop that here.
+ * Called under journal->j_list_lock. The caller provided us with a ref
+ * against the buffer, and we drop that here.
*/
static void release_buffer_page(struct buffer_head *bh)
{
@@ -78,6 +78,19 @@ nope:
}
/*
+ * Decrement reference counter for data buffer. If it has been marked
+ * 'BH_Freed', release it and the page to which it belongs if possible.
+ */
+static void release_data_buffer(struct buffer_head *bh)
+{
+ if (buffer_freed(bh)) {
+ clear_buffer_freed(bh);
+ release_buffer_page(bh);
+ } else
+ put_bh(bh);
+}
+
+/*
* Try to acquire jbd_lock_bh_state() against the buffer, when j_list_lock is
* held. For ranking reasons we must trylock. If we lose, schedule away and
* return 0. j_list_lock is dropped in this case.
@@ -172,7 +185,7 @@ static void journal_do_submit_data(struct buffer_head **wbuf, int bufs)
/*
* Submit all the data buffers to disk
*/
-static void journal_submit_data_buffers(journal_t *journal,
+static int journal_submit_data_buffers(journal_t *journal,
transaction_t *commit_transaction)
{
struct journal_head *jh;
@@ -180,6 +193,7 @@ static void journal_submit_data_buffers(journal_t *journal,
int locked;
int bufs = 0;
struct buffer_head **wbuf = journal->j_wbuf;
+ int err = 0;
/*
* Whenever we unlock the journal and sleep, things can get added
@@ -231,7 +245,7 @@ write_out_data:
if (locked)
unlock_buffer(bh);
BUFFER_TRACE(bh, "already cleaned up");
- put_bh(bh);
+ release_data_buffer(bh);
continue;
}
if (locked && test_clear_buffer_dirty(bh)) {
@@ -253,15 +267,17 @@ write_out_data:
put_bh(bh);
} else {
BUFFER_TRACE(bh, "writeout complete: unfile");
+ if (unlikely(!buffer_uptodate(bh)))
+ err = -EIO;
__journal_unfile_buffer(jh);
jbd_unlock_bh_state(bh);
if (locked)
unlock_buffer(bh);
journal_remove_journal_head(bh);
- /* Once for our safety reference, once for
+ /* One for our safety reference, other for
* journal_remove_journal_head() */
put_bh(bh);
- put_bh(bh);
+ release_data_buffer(bh);
}
if (need_resched() || spin_needbreak(&journal->j_list_lock)) {
@@ -271,6 +287,8 @@ write_out_data:
}
spin_unlock(&journal->j_list_lock);
journal_do_submit_data(wbuf, bufs);
+
+ return err;
}
/*
@@ -410,8 +428,7 @@ void journal_commit_transaction(journal_t *journal)
* Now start flushing things to disk, in the order they appear
* on the transaction lists. Data blocks go first.
*/
- err = 0;
- journal_submit_data_buffers(journal, commit_transaction);
+ err = journal_submit_data_buffers(journal, commit_transaction);
/*
* Wait for all previously submitted IO to complete.
@@ -426,10 +443,21 @@ void journal_commit_transaction(journal_t *journal)
if (buffer_locked(bh)) {
spin_unlock(&journal->j_list_lock);
wait_on_buffer(bh);
- if (unlikely(!buffer_uptodate(bh)))
- err = -EIO;
spin_lock(&journal->j_list_lock);
}
+ if (unlikely(!buffer_uptodate(bh))) {
+ if (TestSetPageLocked(bh->b_page)) {
+ spin_unlock(&journal->j_list_lock);
+ lock_page(bh->b_page);
+ spin_lock(&journal->j_list_lock);
+ }
+ if (bh->b_page->mapping)
+ set_bit(AS_EIO, &bh->b_page->mapping->flags);
+
+ unlock_page(bh->b_page);
+ SetPageError(bh->b_page);
+ err = -EIO;
+ }
if (!inverted_lock(journal, bh)) {
put_bh(bh);
spin_lock(&journal->j_list_lock);
@@ -443,17 +471,21 @@ void journal_commit_transaction(journal_t *journal)
} else {
jbd_unlock_bh_state(bh);
}
- put_bh(bh);
+ release_data_buffer(bh);
cond_resched_lock(&journal->j_list_lock);
}
spin_unlock(&journal->j_list_lock);
- if (err)
- journal_abort(journal, err);
+ if (err) {
+ char b[BDEVNAME_SIZE];
- journal_write_revoke_records(journal, commit_transaction);
+ printk(KERN_WARNING
+ "JBD: Detected IO errors while flushing file data "
+ "on %s\n", bdevname(journal->j_fs_dev, b));
+ err = 0;
+ }
- jbd_debug(3, "JBD: commit phase 2\n");
+ journal_write_revoke_records(journal, commit_transaction);
/*
* If we found any dirty or locked buffers, then we should have
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index b99c3b3654c..aa7143a8349 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -68,7 +68,6 @@ EXPORT_SYMBOL(journal_set_features);
EXPORT_SYMBOL(journal_create);
EXPORT_SYMBOL(journal_load);
EXPORT_SYMBOL(journal_destroy);
-EXPORT_SYMBOL(journal_update_superblock);
EXPORT_SYMBOL(journal_abort);
EXPORT_SYMBOL(journal_errno);
EXPORT_SYMBOL(journal_ack_err);
@@ -1636,9 +1635,10 @@ static int journal_init_journal_head_cache(void)
static void journal_destroy_journal_head_cache(void)
{
- J_ASSERT(journal_head_cache != NULL);
- kmem_cache_destroy(journal_head_cache);
- journal_head_cache = NULL;
+ if (journal_head_cache) {
+ kmem_cache_destroy(journal_head_cache);
+ journal_head_cache = NULL;
+ }
}
/*
diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c
index 1bb43e987f4..c7bd649bbbd 100644
--- a/fs/jbd/revoke.c
+++ b/fs/jbd/revoke.c
@@ -166,138 +166,123 @@ static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
return NULL;
}
+void journal_destroy_revoke_caches(void)
+{
+ if (revoke_record_cache) {
+ kmem_cache_destroy(revoke_record_cache);
+ revoke_record_cache = NULL;
+ }
+ if (revoke_table_cache) {
+ kmem_cache_destroy(revoke_table_cache);
+ revoke_table_cache = NULL;
+ }
+}
+
int __init journal_init_revoke_caches(void)
{
+ J_ASSERT(!revoke_record_cache);
+ J_ASSERT(!revoke_table_cache);
+
revoke_record_cache = kmem_cache_create("revoke_record",
sizeof(struct jbd_revoke_record_s),
0,
SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY,
NULL);
if (!revoke_record_cache)
- return -ENOMEM;
+ goto record_cache_failure;
revoke_table_cache = kmem_cache_create("revoke_table",
sizeof(struct jbd_revoke_table_s),
0, SLAB_TEMPORARY, NULL);
- if (!revoke_table_cache) {
- kmem_cache_destroy(revoke_record_cache);
- revoke_record_cache = NULL;
- return -ENOMEM;
- }
+ if (!revoke_table_cache)
+ goto table_cache_failure;
+
return 0;
-}
-void journal_destroy_revoke_caches(void)
-{
- kmem_cache_destroy(revoke_record_cache);
- revoke_record_cache = NULL;
- kmem_cache_destroy(revoke_table_cache);
- revoke_table_cache = NULL;
+table_cache_failure:
+ journal_destroy_revoke_caches();
+record_cache_failure:
+ return -ENOMEM;
}
-/* Initialise the revoke table for a given journal to a given size. */
-
-int journal_init_revoke(journal_t *journal, int hash_size)
+static struct jbd_revoke_table_s *journal_init_revoke_table(int hash_size)
{
- int shift, tmp;
+ int shift = 0;
+ int tmp = hash_size;
+ struct jbd_revoke_table_s *table;
- J_ASSERT (journal->j_revoke_table[0] == NULL);
+ table = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
+ if (!table)
+ goto out;
- shift = 0;
- tmp = hash_size;
while((tmp >>= 1UL) != 0UL)
shift++;
- journal->j_revoke_table[0] = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
- if (!journal->j_revoke_table[0])
- return -ENOMEM;
- journal->j_revoke = journal->j_revoke_table[0];
-
- /* Check that the hash_size is a power of two */
- J_ASSERT(is_power_of_2(hash_size));
-
- journal->j_revoke->hash_size = hash_size;
-
- journal->j_revoke->hash_shift = shift;
-
- journal->j_revoke->hash_table =
+ table->hash_size = hash_size;
+ table->hash_shift = shift;
+ table->hash_table =
kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
- if (!journal->j_revoke->hash_table) {
- kmem_cache_free(revoke_table_cache, journal->j_revoke_table[0]);
- journal->j_revoke = NULL;
- return -ENOMEM;
+ if (!table->hash_table) {
+ kmem_cache_free(revoke_table_cache, table);
+ table = NULL;
+ goto out;
}
for (tmp = 0; tmp < hash_size; tmp++)
- INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
+ INIT_LIST_HEAD(&table->hash_table[tmp]);
- journal->j_revoke_table[1] = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
- if (!journal->j_revoke_table[1]) {
- kfree(journal->j_revoke_table[0]->hash_table);
- kmem_cache_free(revoke_table_cache, journal->j_revoke_table[0]);
- return -ENOMEM;
+out:
+ return table;
+}
+
+static void journal_destroy_revoke_table(struct jbd_revoke_table_s *table)
+{
+ int i;
+ struct list_head *hash_list;
+
+ for (i = 0; i < table->hash_size; i++) {
+ hash_list = &table->hash_table[i];
+ J_ASSERT(list_empty(hash_list));
}
- journal->j_revoke = journal->j_revoke_table[1];
+ kfree(table->hash_table);
+ kmem_cache_free(revoke_table_cache, table);
+}
- /* Check that the hash_size is a power of two */
+/* Initialise the revoke table for a given journal to a given size. */
+int journal_init_revoke(journal_t *journal, int hash_size)
+{
+ J_ASSERT(journal->j_revoke_table[0] == NULL);
J_ASSERT(is_power_of_2(hash_size));
- journal->j_revoke->hash_size = hash_size;
+ journal->j_revoke_table[0] = journal_init_revoke_table(hash_size);
+ if (!journal->j_revoke_table[0])
+ goto fail0;
- journal->j_revoke->hash_shift = shift;
+ journal->j_revoke_table[1] = journal_init_revoke_table(hash_size);
+ if (!journal->j_revoke_table[1])
+ goto fail1;
- journal->j_revoke->hash_table =
- kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
- if (!journal->j_revoke->hash_table) {
- kfree(journal->j_revoke_table[0]->hash_table);
- kmem_cache_free(revoke_table_cache, journal->j_revoke_table[0]);
- kmem_cache_free(revoke_table_cache, journal->j_revoke_table[1]);
- journal->j_revoke = NULL;
- return -ENOMEM;
- }
-
- for (tmp = 0; tmp < hash_size; tmp++)
- INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
+ journal->j_revoke = journal->j_revoke_table[1];
spin_lock_init(&journal->j_revoke_lock);
return 0;
-}
-/* Destoy a journal's revoke table. The table must already be empty! */
+fail1:
+ journal_destroy_revoke_table(journal->j_revoke_table[0]);
+fail0:
+ return -ENOMEM;
+}
+/* Destroy a journal's revoke table. The table must already be empty! */
void journal_destroy_revoke(journal_t *journal)
{
- struct jbd_revoke_table_s *table;
- struct list_head *hash_list;
- int i;
-
- table = journal->j_revoke_table[0];
- if (!table)
- return;
-
- for (i=0; i<table->hash_size; i++) {
- hash_list = &table->hash_table[i];
- J_ASSERT (list_empty(hash_list));
- }
-
- kfree(table->hash_table);
- kmem_cache_free(revoke_table_cache, table);
- journal->j_revoke = NULL;
-
- table = journal->j_revoke_table[1];
- if (!table)
- return;
-
- for (i=0; i<table->hash_size; i++) {
- hash_list = &table->hash_table[i];
- J_ASSERT (list_empty(hash_list));
- }
-
- kfree(table->hash_table);
- kmem_cache_free(revoke_table_cache, table);
journal->j_revoke = NULL;
+ if (journal->j_revoke_table[0])
+ journal_destroy_revoke_table(journal->j_revoke_table[0]);
+ if (journal->j_revoke_table[1])
+ journal_destroy_revoke_table(journal->j_revoke_table[1]);
}
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 67ff2024c23..8dee3200750 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -1648,12 +1648,42 @@ out:
return;
}
+/*
+ * journal_try_to_free_buffers() could race with journal_commit_transaction()
+ * The latter might still hold the a count on buffers when inspecting
+ * them on t_syncdata_list or t_locked_list.
+ *
+ * journal_try_to_free_buffers() will call this function to
+ * wait for the current transaction to finish syncing data buffers, before
+ * tryinf to free that buffer.
+ *
+ * Called with journal->j_state_lock held.
+ */
+static void journal_wait_for_transaction_sync_data(journal_t *journal)
+{
+ transaction_t *transaction = NULL;
+ tid_t tid;
+
+ spin_lock(&journal->j_state_lock);
+ transaction = journal->j_committing_transaction;
+
+ if (!transaction) {
+ spin_unlock(&journal->j_state_lock);
+ return;
+ }
+
+ tid = transaction->t_tid;
+ spin_unlock(&journal->j_state_lock);
+ log_wait_commit(journal, tid);
+}
/**
* int journal_try_to_free_buffers() - try to free page buffers.
* @journal: journal for operation
* @page: to try and free
- * @unused_gfp_mask: unused
+ * @gfp_mask: we use the mask to detect how hard should we try to release
+ * buffers. If __GFP_WAIT and __GFP_FS is set, we wait for commit code to
+ * release the buffers.
*
*
* For all the buffers on this page,
@@ -1682,9 +1712,11 @@ out:
* journal_try_to_free_buffer() is changing its state. But that
* cannot happen because we never reallocate freed data as metadata
* while the data is part of a transaction. Yes?
+ *
+ * Return 0 on failure, 1 on success
*/
int journal_try_to_free_buffers(journal_t *journal,
- struct page *page, gfp_t unused_gfp_mask)
+ struct page *page, gfp_t gfp_mask)
{
struct buffer_head *head;
struct buffer_head *bh;
@@ -1713,7 +1745,28 @@ int journal_try_to_free_buffers(journal_t *journal,
if (buffer_jbd(bh))
goto busy;
} while ((bh = bh->b_this_page) != head);
+
ret = try_to_free_buffers(page);
+
+ /*
+ * There are a number of places where journal_try_to_free_buffers()
+ * could race with journal_commit_transaction(), the later still
+ * holds the reference to the buffers to free while processing them.
+ * try_to_free_buffers() failed to free those buffers. Some of the
+ * caller of releasepage() request page buffers to be dropped, otherwise
+ * treat the fail-to-free as errors (such as generic_file_direct_IO())
+ *
+ * So, if the caller of try_to_release_page() wants the synchronous
+ * behaviour(i.e make sure buffers are dropped upon return),
+ * let's wait for the current transaction to finish flush of
+ * dirty data buffers, then try to free those buffers again,
+ * with the journal locked.
+ */
+ if (ret == 0 && (gfp_mask & __GFP_WAIT) && (gfp_mask & __GFP_FS)) {
+ journal_wait_for_transaction_sync_data(journal);
+ ret = try_to_free_buffers(page);
+ }
+
busy:
return ret;
}
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 0288e6d7936..359c091d896 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -22,6 +22,7 @@
#include <linux/parser.h>
#include <linux/completion.h>
#include <linux/vfs.h>
+#include <linux/quotaops.h>
#include <linux/mount.h>
#include <linux/moduleparam.h>
#include <linux/kthread.h>
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 1f6dc518505..31668b690e0 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -582,7 +582,15 @@ again:
}
if (status < 0)
goto out_unlock;
- status = nlm_stat_to_errno(resp->status);
+ /*
+ * EAGAIN doesn't make sense for sleeping locks, and in some
+ * cases NLM_LCK_DENIED is returned for a permanent error. So
+ * turn it into an ENOLCK.
+ */
+ if (resp->status == nlm_lck_denied && (fl_flags & FL_SLEEP))
+ status = -ENOLCK;
+ else
+ status = nlm_stat_to_errno(resp->status);
out_unblock:
nlmclnt_finish_block(block);
out:
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 821b9acdfb6..cf0d5c2c318 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -418,8 +418,8 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
goto out;
case -EAGAIN:
ret = nlm_lck_denied;
- break;
- case -EINPROGRESS:
+ goto out;
+ case FILE_LOCK_DEFERRED:
if (wait)
break;
/* Filesystem lock operation is in progress
@@ -434,10 +434,6 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
goto out;
}
- ret = nlm_lck_denied;
- if (!wait)
- goto out;
-
ret = nlm_lck_blocked;
/* Append to list of blocked */
@@ -507,7 +503,7 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
}
error = vfs_test_lock(file->f_file, &lock->fl);
- if (error == -EINPROGRESS) {
+ if (error == FILE_LOCK_DEFERRED) {
ret = nlmsvc_defer_lock_rqst(rqstp, block);
goto out;
}
@@ -731,8 +727,7 @@ nlmsvc_grant_blocked(struct nlm_block *block)
switch (error) {
case 0:
break;
- case -EAGAIN:
- case -EINPROGRESS:
+ case FILE_LOCK_DEFERRED:
dprintk("lockd: lock still blocked error %d\n", error);
nlmsvc_insert_block(block, NLM_NEVER);
nlmsvc_release_block(block);
diff --git a/fs/locks.c b/fs/locks.c
index dce8c747371..01490300f7c 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -779,8 +779,10 @@ find_conflict:
if (!flock_locks_conflict(request, fl))
continue;
error = -EAGAIN;
- if (request->fl_flags & FL_SLEEP)
- locks_insert_block(fl, request);
+ if (!(request->fl_flags & FL_SLEEP))
+ goto out;
+ error = FILE_LOCK_DEFERRED;
+ locks_insert_block(fl, request);
goto out;
}
if (request->fl_flags & FL_ACCESS)
@@ -836,7 +838,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
error = -EDEADLK;
if (posix_locks_deadlock(request, fl))
goto out;
- error = -EAGAIN;
+ error = FILE_LOCK_DEFERRED;
locks_insert_block(fl, request);
goto out;
}
@@ -1035,7 +1037,7 @@ int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
might_sleep ();
for (;;) {
error = posix_lock_file(filp, fl, NULL);
- if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
+ if (error != FILE_LOCK_DEFERRED)
break;
error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
if (!error)
@@ -1107,9 +1109,7 @@ int locks_mandatory_area(int read_write, struct inode *inode,
for (;;) {
error = __posix_lock_file(inode, &fl, NULL);
- if (error != -EAGAIN)
- break;
- if (!(fl.fl_flags & FL_SLEEP))
+ if (error != FILE_LOCK_DEFERRED)
break;
error = wait_event_interruptible(fl.fl_wait, !fl.fl_next);
if (!error) {
@@ -1531,7 +1531,7 @@ int flock_lock_file_wait(struct file *filp, struct file_lock *fl)
might_sleep();
for (;;) {
error = flock_lock_file(filp, fl);
- if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
+ if (error != FILE_LOCK_DEFERRED)
break;
error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
if (!error)
@@ -1716,17 +1716,17 @@ out:
* fl_grant is set. Callers expecting ->lock() to return asynchronously
* will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if)
* the request is for a blocking lock. When ->lock() does return asynchronously,
- * it must return -EINPROGRESS, and call ->fl_grant() when the lock
+ * it must return FILE_LOCK_DEFERRED, and call ->fl_grant() when the lock
* request completes.
* If the request is for non-blocking lock the file system should return
- * -EINPROGRESS then try to get the lock and call the callback routine with
- * the result. If the request timed out the callback routine will return a
+ * FILE_LOCK_DEFERRED then try to get the lock and call the callback routine
+ * with the result. If the request timed out the callback routine will return a
* nonzero return code and the file system should release the lock. The file
* system is also responsible to keep a corresponding posix lock when it
* grants a lock so the VFS can find out which locks are locally held and do
* the correct lock cleanup when required.
* The underlying filesystem must not drop the kernel lock or call
- * ->fl_grant() before returning to the caller with a -EINPROGRESS
+ * ->fl_grant() before returning to the caller with a FILE_LOCK_DEFERRED
* return code.
*/
int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
@@ -1738,6 +1738,30 @@ int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, str
}
EXPORT_SYMBOL_GPL(vfs_lock_file);
+static int do_lock_file_wait(struct file *filp, unsigned int cmd,
+ struct file_lock *fl)
+{
+ int error;
+
+ error = security_file_lock(filp, fl->fl_type);
+ if (error)
+ return error;
+
+ for (;;) {
+ error = vfs_lock_file(filp, cmd, fl, NULL);
+ if (error != FILE_LOCK_DEFERRED)
+ break;
+ error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
+ if (!error)
+ continue;
+
+ locks_delete_block(fl);
+ break;
+ }
+
+ return error;
+}
+
/* Apply the lock described by l to an open file descriptor.
* This implements both the F_SETLK and F_SETLKW commands of fcntl().
*/
@@ -1795,26 +1819,7 @@ again:
goto out;
}
- error = security_file_lock(filp, file_lock->fl_type);
- if (error)
- goto out;
-
- if (filp->f_op && filp->f_op->lock != NULL)
- error = filp->f_op->lock(filp, cmd, file_lock);
- else {
- for (;;) {
- error = posix_lock_file(filp, file_lock, NULL);
- if (error != -EAGAIN || cmd == F_SETLK)
- break;
- error = wait_event_interruptible(file_lock->fl_wait,
- !file_lock->fl_next);
- if (!error)
- continue;
-
- locks_delete_block(file_lock);
- break;
- }
- }
+ error = do_lock_file_wait(filp, cmd, file_lock);
/*
* Attempt to detect a close/fcntl race and recover by
@@ -1932,26 +1937,7 @@ again:
goto out;
}
- error = security_file_lock(filp, file_lock->fl_type);
- if (error)
- goto out;
-
- if (filp->f_op && filp->f_op->lock != NULL)
- error = filp->f_op->lock(filp, cmd, file_lock);
- else {
- for (;;) {
- error = posix_lock_file(filp, file_lock, NULL);
- if (error != -EAGAIN || cmd == F_SETLK64)
- break;
- error = wait_event_interruptible(file_lock->fl_wait,
- !file_lock->fl_next);
- if (!error)
- continue;
-
- locks_delete_block(file_lock);
- break;
- }
- }
+ error = do_lock_file_wait(filp, cmd, file_lock);
/*
* Attempt to detect a close/fcntl race and recover by
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 84f6242ba6f..523d7371341 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -256,9 +256,6 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
if (!s->s_root)
goto out_iput;
- if (!NO_TRUNCATE)
- s->s_root->d_op = &minix_dentry_operations;
-
if (!(s->s_flags & MS_RDONLY)) {
if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */
ms->s_state &= ~MINIX_VALID_FS;
diff --git a/fs/minix/minix.h b/fs/minix/minix.h
index 326edfe9610..e6a0b193bea 100644
--- a/fs/minix/minix.h
+++ b/fs/minix/minix.h
@@ -2,11 +2,6 @@
#include <linux/pagemap.h>
#include <linux/minix_fs.h>
-/*
- * change the define below to 0 if you want names > info->s_namelen chars to be
- * truncated. Else they will be disallowed (ENAMETOOLONG).
- */
-#define NO_TRUNCATE 1
#define INODE_VERSION(inode) minix_sb(inode->i_sb)->s_version
#define MINIX_V1 0x0001 /* original minix fs */
#define MINIX_V2 0x0002 /* minix V2 fs */
@@ -83,7 +78,6 @@ extern const struct inode_operations minix_file_inode_operations;
extern const struct inode_operations minix_dir_inode_operations;
extern const struct file_operations minix_file_operations;
extern const struct file_operations minix_dir_operations;
-extern struct dentry_operations minix_dentry_operations;
static inline struct minix_sb_info *minix_sb(struct super_block *sb)
{
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index 102241bc9c7..32b131cd612 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -18,30 +18,6 @@ static int add_nondir(struct dentry *dentry, struct inode *inode)
return err;
}
-static int minix_hash(struct dentry *dentry, struct qstr *qstr)
-{
- unsigned long hash;
- int i;
- const unsigned char *name;
-
- i = minix_sb(dentry->d_inode->i_sb)->s_namelen;
- if (i >= qstr->len)
- return 0;
- /* Truncate the name in place, avoids having to define a compare
- function. */
- qstr->len = i;
- name = qstr->name;
- hash = init_name_hash();
- while (i--)
- hash = partial_name_hash(*name++, hash);
- qstr->hash = end_name_hash(hash);
- return 0;
-}
-
-struct dentry_operations minix_dentry_operations = {
- .d_hash = minix_hash,
-};
-
static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
struct inode * inode = NULL;
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index 1f7f2956412..e844b9809d2 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -14,12 +14,7 @@
/* Characters that are undesirable in an MS-DOS file name */
static unsigned char bad_chars[] = "*?<>|\"";
-static unsigned char bad_if_strict_pc[] = "+=,; ";
-/* GEMDOS is less restrictive */
-static unsigned char bad_if_strict_atari[] = " ";
-
-#define bad_if_strict(opts) \
- ((opts)->atari ? bad_if_strict_atari : bad_if_strict_pc)
+static unsigned char bad_if_strict[] = "+=,; ";
/***** Formats an MS-DOS file name. Rejects invalid names. */
static int msdos_format_name(const unsigned char *name, int len,
@@ -40,21 +35,20 @@ static int msdos_format_name(const unsigned char *name, int len,
/* Get rid of dot - test for it elsewhere */
name++;
len--;
- } else if (!opts->atari)
+ } else
return -EINVAL;
}
/*
- * disallow names that _really_ start with a dot for MS-DOS,
- * GEMDOS does not care
+ * disallow names that _really_ start with a dot
*/
- space = !opts->atari;
+ space = 1;
c = 0;
for (walk = res; len && walk - res < 8; walk++) {
c = *name++;
len--;
if (opts->name_check != 'r' && strchr(bad_chars, c))
return -EINVAL;
- if (opts->name_check == 's' && strchr(bad_if_strict(opts), c))
+ if (opts->name_check == 's' && strchr(bad_if_strict, c))
return -EINVAL;
if (c >= 'A' && c <= 'Z' && opts->name_check == 's')
return -EINVAL;
@@ -94,7 +88,7 @@ static int msdos_format_name(const unsigned char *name, int len,
if (opts->name_check != 'r' && strchr(bad_chars, c))
return -EINVAL;
if (opts->name_check == 's' &&
- strchr(bad_if_strict(opts), c))
+ strchr(bad_if_strict, c))
return -EINVAL;
if (c < ' ' || c == ':' || c == '\\')
return -EINVAL;
@@ -243,6 +237,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name,
int is_dir, int is_hid, int cluster,
struct timespec *ts, struct fat_slot_info *sinfo)
{
+ struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb);
struct msdos_dir_entry de;
__le16 time, date;
int err;
@@ -252,7 +247,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name,
if (is_hid)
de.attr |= ATTR_HIDDEN;
de.lcase = 0;
- fat_date_unix2dos(ts->tv_sec, &time, &date);
+ fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc);
de.cdate = de.adate = 0;
de.ctime = 0;
de.ctime_cs = 0;
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index 46763d1cd39..8478fc25dae 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -127,7 +127,7 @@ enum {
Opt_err
};
-static match_table_t __initdata tokens = {
+static match_table_t __initconst tokens = {
{Opt_port, "port=%u"},
{Opt_rsize, "rsize=%u"},
{Opt_wsize, "wsize=%u"},
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 6b6225ac492..15c6faeec77 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -19,6 +19,13 @@
#define NFSDDBG_FACILITY NFSDDBG_LOCKD
+#ifdef CONFIG_LOCKD_V4
+#define nlm_stale_fh nlm4_stale_fh
+#define nlm_failed nlm4_failed
+#else
+#define nlm_stale_fh nlm_lck_denied_nolocks
+#define nlm_failed nlm_lck_denied_nolocks
+#endif
/*
* Note: we hold the dentry use count while the file is open.
*/
@@ -47,12 +54,10 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
return 0;
case nfserr_dropit:
return nlm_drop_reply;
-#ifdef CONFIG_LOCKD_V4
case nfserr_stale:
- return nlm4_stale_fh;
-#endif
+ return nlm_stale_fh;
default:
- return nlm_lck_denied;
+ return nlm_failed;
}
}
diff --git a/fs/open.c b/fs/open.c
index a99ad09c319..bb98d2fe809 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -64,7 +64,8 @@ static int vfs_statfs_native(struct dentry *dentry, struct statfs *buf)
memcpy(buf, &st, sizeof(st));
else {
if (sizeof buf->f_blocks == 4) {
- if ((st.f_blocks | st.f_bfree | st.f_bavail) &
+ if ((st.f_blocks | st.f_bfree | st.f_bavail |
+ st.f_bsize | st.f_frsize) &
0xffffffff00000000ULL)
return -EOVERFLOW;
/*
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 6149e4b58c8..7d6b34e201d 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -344,18 +344,18 @@ static ssize_t whole_disk_show(struct device *dev,
static DEVICE_ATTR(whole_disk, S_IRUSR | S_IRGRP | S_IROTH,
whole_disk_show, NULL);
-void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags)
+int add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags)
{
struct hd_struct *p;
int err;
p = kzalloc(sizeof(*p), GFP_KERNEL);
if (!p)
- return;
+ return -ENOMEM;
if (!init_part_stats(p)) {
- kfree(p);
- return;
+ err = -ENOMEM;
+ goto out0;
}
p->start_sect = start;
p->nr_sects = len;
@@ -378,15 +378,31 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len,
/* delay uevent until 'holders' subdir is created */
p->dev.uevent_suppress = 1;
- device_add(&p->dev);
+ err = device_add(&p->dev);
+ if (err)
+ goto out1;
partition_sysfs_add_subdir(p);
p->dev.uevent_suppress = 0;
- if (flags & ADDPART_FLAG_WHOLEDISK)
+ if (flags & ADDPART_FLAG_WHOLEDISK) {
err = device_create_file(&p->dev, &dev_attr_whole_disk);
+ if (err)
+ goto out2;
+ }
/* suppress uevent if the disk supresses it */
if (!disk->dev.uevent_suppress)
kobject_uevent(&p->dev.kobj, KOBJ_ADD);
+
+ return 0;
+
+out2:
+ device_del(&p->dev);
+out1:
+ put_device(&p->dev);
+ free_part_stats(p);
+out0:
+ kfree(p);
+ return err;
}
/* Not exported, helper to add_disk(). */
@@ -401,7 +417,7 @@ void register_disk(struct gendisk *disk)
disk->dev.parent = disk->driverfs_dev;
disk->dev.devt = MKDEV(disk->major, disk->first_minor);
- strlcpy(disk->dev.bus_id, disk->disk_name, KOBJ_NAME_LEN);
+ strlcpy(disk->dev.bus_id, disk->disk_name, BUS_ID_SIZE);
/* ewww... some of these buggers have / in the name... */
s = strchr(disk->dev.bus_id, '/');
if (s)
@@ -483,10 +499,16 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
if (!size)
continue;
if (from + size > get_capacity(disk)) {
- printk(" %s: p%d exceeds device capacity\n",
+ printk(KERN_ERR " %s: p%d exceeds device capacity\n",
disk->disk_name, p);
+ continue;
+ }
+ res = add_partition(disk, p, from, size, state->parts[p].flags);
+ if (res) {
+ printk(KERN_ERR " %s: p%d could not be added: %d\n",
+ disk->disk_name, p, -res);
+ continue;
}
- add_partition(disk, p, from, size, state->parts[p].flags);
#ifdef CONFIG_BLK_DEV_MD
if (state->parts[p].flags & ADDPART_FLAG_RAID)
md_autodetect_dev(bdev->bd_dev+p);
diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c
index e7b07006bc4..038a6022152 100644
--- a/fs/partitions/efi.c
+++ b/fs/partitions/efi.c
@@ -95,13 +95,6 @@
#include "check.h"
#include "efi.h"
-#undef EFI_DEBUG
-#ifdef EFI_DEBUG
-#define Dprintk(x...) printk(KERN_DEBUG x)
-#else
-#define Dprintk(x...)
-#endif
-
/* This allows a kernel command line option 'gpt' to override
* the test for invalid PMBR. Not __initdata because reloading
* the partition tables happens after init too.
@@ -305,10 +298,10 @@ is_gpt_valid(struct block_device *bdev, u64 lba,
/* Check the GUID Partition Table signature */
if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
- Dprintk("GUID Partition Table Header signature is wrong:"
- "%lld != %lld\n",
- (unsigned long long)le64_to_cpu((*gpt)->signature),
- (unsigned long long)GPT_HEADER_SIGNATURE);
+ pr_debug("GUID Partition Table Header signature is wrong:"
+ "%lld != %lld\n",
+ (unsigned long long)le64_to_cpu((*gpt)->signature),
+ (unsigned long long)GPT_HEADER_SIGNATURE);
goto fail;
}
@@ -318,9 +311,8 @@ is_gpt_valid(struct block_device *bdev, u64 lba,
crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size));
if (crc != origcrc) {
- Dprintk
- ("GUID Partition Table Header CRC is wrong: %x != %x\n",
- crc, origcrc);
+ pr_debug("GUID Partition Table Header CRC is wrong: %x != %x\n",
+ crc, origcrc);
goto fail;
}
(*gpt)->header_crc32 = cpu_to_le32(origcrc);
@@ -328,9 +320,9 @@ is_gpt_valid(struct block_device *bdev, u64 lba,
/* Check that the my_lba entry points to the LBA that contains
* the GUID Partition Table */
if (le64_to_cpu((*gpt)->my_lba) != lba) {
- Dprintk("GPT my_lba incorrect: %lld != %lld\n",
- (unsigned long long)le64_to_cpu((*gpt)->my_lba),
- (unsigned long long)lba);
+ pr_debug("GPT my_lba incorrect: %lld != %lld\n",
+ (unsigned long long)le64_to_cpu((*gpt)->my_lba),
+ (unsigned long long)lba);
goto fail;
}
@@ -339,15 +331,15 @@ is_gpt_valid(struct block_device *bdev, u64 lba,
*/
lastlba = last_lba(bdev);
if (le64_to_cpu((*gpt)->first_usable_lba) > lastlba) {
- Dprintk("GPT: first_usable_lba incorrect: %lld > %lld\n",
- (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba),
- (unsigned long long)lastlba);
+ pr_debug("GPT: first_usable_lba incorrect: %lld > %lld\n",
+ (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba),
+ (unsigned long long)lastlba);
goto fail;
}
if (le64_to_cpu((*gpt)->last_usable_lba) > lastlba) {
- Dprintk("GPT: last_usable_lba incorrect: %lld > %lld\n",
- (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba),
- (unsigned long long)lastlba);
+ pr_debug("GPT: last_usable_lba incorrect: %lld > %lld\n",
+ (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba),
+ (unsigned long long)lastlba);
goto fail;
}
@@ -360,7 +352,7 @@ is_gpt_valid(struct block_device *bdev, u64 lba,
le32_to_cpu((*gpt)->sizeof_partition_entry));
if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
- Dprintk("GUID Partitition Entry Array CRC check failed.\n");
+ pr_debug("GUID Partitition Entry Array CRC check failed.\n");
goto fail_ptes;
}
@@ -616,7 +608,7 @@ efi_partition(struct parsed_partitions *state, struct block_device *bdev)
return 0;
}
- Dprintk("GUID Partition Table is valid! Yea!\n");
+ pr_debug("GUID Partition Table is valid! Yea!\n");
for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) {
if (!is_pte_valid(&ptes[i], last_lba(bdev)))
diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c
index 0fdda2e8a4c..8652fb99e96 100644
--- a/fs/partitions/ldm.c
+++ b/fs/partitions/ldm.c
@@ -133,17 +133,17 @@ static bool ldm_parse_privhead(const u8 *data, struct privhead *ph)
bool is_vista = false;
BUG_ON(!data || !ph);
- if (MAGIC_PRIVHEAD != BE64(data)) {
+ if (MAGIC_PRIVHEAD != get_unaligned_be64(data)) {
ldm_error("Cannot find PRIVHEAD structure. LDM database is"
" corrupt. Aborting.");
return false;
}
- ph->ver_major = BE16(data + 0x000C);
- ph->ver_minor = BE16(data + 0x000E);
- ph->logical_disk_start = BE64(data + 0x011B);
- ph->logical_disk_size = BE64(data + 0x0123);
- ph->config_start = BE64(data + 0x012B);
- ph->config_size = BE64(data + 0x0133);
+ ph->ver_major = get_unaligned_be16(data + 0x000C);
+ ph->ver_minor = get_unaligned_be16(data + 0x000E);
+ ph->logical_disk_start = get_unaligned_be64(data + 0x011B);
+ ph->logical_disk_size = get_unaligned_be64(data + 0x0123);
+ ph->config_start = get_unaligned_be64(data + 0x012B);
+ ph->config_size = get_unaligned_be64(data + 0x0133);
/* Version 2.11 is Win2k/XP and version 2.12 is Vista. */
if (ph->ver_major == 2 && ph->ver_minor == 12)
is_vista = true;
@@ -191,14 +191,14 @@ static bool ldm_parse_tocblock (const u8 *data, struct tocblock *toc)
{
BUG_ON (!data || !toc);
- if (MAGIC_TOCBLOCK != BE64 (data)) {
+ if (MAGIC_TOCBLOCK != get_unaligned_be64(data)) {
ldm_crit ("Cannot find TOCBLOCK, database may be corrupt.");
return false;
}
strncpy (toc->bitmap1_name, data + 0x24, sizeof (toc->bitmap1_name));
toc->bitmap1_name[sizeof (toc->bitmap1_name) - 1] = 0;
- toc->bitmap1_start = BE64 (data + 0x2E);
- toc->bitmap1_size = BE64 (data + 0x36);
+ toc->bitmap1_start = get_unaligned_be64(data + 0x2E);
+ toc->bitmap1_size = get_unaligned_be64(data + 0x36);
if (strncmp (toc->bitmap1_name, TOC_BITMAP1,
sizeof (toc->bitmap1_name)) != 0) {
@@ -208,8 +208,8 @@ static bool ldm_parse_tocblock (const u8 *data, struct tocblock *toc)
}
strncpy (toc->bitmap2_name, data + 0x46, sizeof (toc->bitmap2_name));
toc->bitmap2_name[sizeof (toc->bitmap2_name) - 1] = 0;
- toc->bitmap2_start = BE64 (data + 0x50);
- toc->bitmap2_size = BE64 (data + 0x58);
+ toc->bitmap2_start = get_unaligned_be64(data + 0x50);
+ toc->bitmap2_size = get_unaligned_be64(data + 0x58);
if (strncmp (toc->bitmap2_name, TOC_BITMAP2,
sizeof (toc->bitmap2_name)) != 0) {
ldm_crit ("TOCBLOCK's second bitmap is '%s', should be '%s'.",
@@ -237,22 +237,22 @@ static bool ldm_parse_vmdb (const u8 *data, struct vmdb *vm)
{
BUG_ON (!data || !vm);
- if (MAGIC_VMDB != BE32 (data)) {
+ if (MAGIC_VMDB != get_unaligned_be32(data)) {
ldm_crit ("Cannot find the VMDB, database may be corrupt.");
return false;
}
- vm->ver_major = BE16 (data + 0x12);
- vm->ver_minor = BE16 (data + 0x14);
+ vm->ver_major = get_unaligned_be16(data + 0x12);
+ vm->ver_minor = get_unaligned_be16(data + 0x14);
if ((vm->ver_major != 4) || (vm->ver_minor != 10)) {
ldm_error ("Expected VMDB version %d.%d, got %d.%d. "
"Aborting.", 4, 10, vm->ver_major, vm->ver_minor);
return false;
}
- vm->vblk_size = BE32 (data + 0x08);
- vm->vblk_offset = BE32 (data + 0x0C);
- vm->last_vblk_seq = BE32 (data + 0x04);
+ vm->vblk_size = get_unaligned_be32(data + 0x08);
+ vm->vblk_offset = get_unaligned_be32(data + 0x0C);
+ vm->last_vblk_seq = get_unaligned_be32(data + 0x04);
ldm_debug ("Parsed VMDB successfully.");
return true;
@@ -507,7 +507,7 @@ static bool ldm_validate_vmdb (struct block_device *bdev, unsigned long base,
goto out; /* Already logged */
/* Are there uncommitted transactions? */
- if (BE16(data + 0x10) != 0x01) {
+ if (get_unaligned_be16(data + 0x10) != 0x01) {
ldm_crit ("Database is not in a consistent state. Aborting.");
goto out;
}
@@ -802,7 +802,7 @@ static bool ldm_parse_cmp3 (const u8 *buffer, int buflen, struct vblk *vb)
return false;
len += VBLK_SIZE_CMP3;
- if (len != BE32 (buffer + 0x14))
+ if (len != get_unaligned_be32(buffer + 0x14))
return false;
comp = &vb->vblk.comp;
@@ -851,7 +851,7 @@ static int ldm_parse_dgr3 (const u8 *buffer, int buflen, struct vblk *vb)
return false;
len += VBLK_SIZE_DGR3;
- if (len != BE32 (buffer + 0x14))
+ if (len != get_unaligned_be32(buffer + 0x14))
return false;
dgrp = &vb->vblk.dgrp;
@@ -895,7 +895,7 @@ static bool ldm_parse_dgr4 (const u8 *buffer, int buflen, struct vblk *vb)
return false;
len += VBLK_SIZE_DGR4;
- if (len != BE32 (buffer + 0x14))
+ if (len != get_unaligned_be32(buffer + 0x14))
return false;
dgrp = &vb->vblk.dgrp;
@@ -931,7 +931,7 @@ static bool ldm_parse_dsk3 (const u8 *buffer, int buflen, struct vblk *vb)
return false;
len += VBLK_SIZE_DSK3;
- if (len != BE32 (buffer + 0x14))
+ if (len != get_unaligned_be32(buffer + 0x14))
return false;
disk = &vb->vblk.disk;
@@ -968,7 +968,7 @@ static bool ldm_parse_dsk4 (const u8 *buffer, int buflen, struct vblk *vb)
return false;
len += VBLK_SIZE_DSK4;
- if (len != BE32 (buffer + 0x14))
+ if (len != get_unaligned_be32(buffer + 0x14))
return false;
disk = &vb->vblk.disk;
@@ -1034,14 +1034,14 @@ static bool ldm_parse_prt3(const u8 *buffer, int buflen, struct vblk *vb)
return false;
}
len += VBLK_SIZE_PRT3;
- if (len > BE32(buffer + 0x14)) {
+ if (len > get_unaligned_be32(buffer + 0x14)) {
ldm_error("len %d > BE32(buffer + 0x14) %d", len,
- BE32(buffer + 0x14));
+ get_unaligned_be32(buffer + 0x14));
return false;
}
part = &vb->vblk.part;
- part->start = BE64(buffer + 0x24 + r_name);
- part->volume_offset = BE64(buffer + 0x2C + r_name);
+ part->start = get_unaligned_be64(buffer + 0x24 + r_name);
+ part->volume_offset = get_unaligned_be64(buffer + 0x2C + r_name);
part->size = ldm_get_vnum(buffer + 0x34 + r_name);
part->parent_id = ldm_get_vnum(buffer + 0x34 + r_size);
part->disk_id = ldm_get_vnum(buffer + 0x34 + r_parent);
@@ -1139,9 +1139,9 @@ static bool ldm_parse_vol5(const u8 *buffer, int buflen, struct vblk *vb)
return false;
}
len += VBLK_SIZE_VOL5;
- if (len > BE32(buffer + 0x14)) {
+ if (len > get_unaligned_be32(buffer + 0x14)) {
ldm_error("len %d > BE32(buffer + 0x14) %d", len,
- BE32(buffer + 0x14));
+ get_unaligned_be32(buffer + 0x14));
return false;
}
volu = &vb->vblk.volu;
@@ -1294,9 +1294,9 @@ static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags)
BUG_ON (!data || !frags);
- group = BE32 (data + 0x08);
- rec = BE16 (data + 0x0C);
- num = BE16 (data + 0x0E);
+ group = get_unaligned_be32(data + 0x08);
+ rec = get_unaligned_be16(data + 0x0C);
+ num = get_unaligned_be16(data + 0x0E);
if ((num < 1) || (num > 4)) {
ldm_error ("A VBLK claims to have %d parts.", num);
return false;
@@ -1425,12 +1425,12 @@ static bool ldm_get_vblks (struct block_device *bdev, unsigned long base,
}
for (v = 0; v < perbuf; v++, data+=size) { /* For each vblk */
- if (MAGIC_VBLK != BE32 (data)) {
+ if (MAGIC_VBLK != get_unaligned_be32(data)) {
ldm_error ("Expected to find a VBLK.");
goto out;
}
- recs = BE16 (data + 0x0E); /* Number of records */
+ recs = get_unaligned_be16(data + 0x0E); /* Number of records */
if (recs == 1) {
if (!ldm_ldmdb_add (data, size, ldb))
goto out; /* Already logged */
diff --git a/fs/partitions/ldm.h b/fs/partitions/ldm.h
index 80f63b5fdd9..30e08e809c1 100644
--- a/fs/partitions/ldm.h
+++ b/fs/partitions/ldm.h
@@ -98,11 +98,6 @@ struct parsed_partitions;
#define TOC_BITMAP1 "config" /* Names of the two defined */
#define TOC_BITMAP2 "log" /* bitmaps in the TOCBLOCK. */
-/* Most numbers we deal with are big-endian and won't be aligned. */
-#define BE16(x) ((u16)be16_to_cpu(get_unaligned((__be16*)(x))))
-#define BE32(x) ((u32)be32_to_cpu(get_unaligned((__be32*)(x))))
-#define BE64(x) ((u64)be64_to_cpu(get_unaligned((__be64*)(x))))
-
/* Borrowed from msdos.c */
#define SYS_IND(p) (get_unaligned(&(p)->sys_ind))
diff --git a/fs/pipe.c b/fs/pipe.c
index 700f4e0d957..10c4e9aa5c4 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -950,7 +950,7 @@ fail_inode:
return NULL;
}
-struct file *create_write_pipe(void)
+struct file *create_write_pipe(int flags)
{
int err;
struct inode *inode;
@@ -983,7 +983,7 @@ struct file *create_write_pipe(void)
goto err_dentry;
f->f_mapping = inode->i_mapping;
- f->f_flags = O_WRONLY;
+ f->f_flags = O_WRONLY | (flags & O_NONBLOCK);
f->f_version = 0;
return f;
@@ -1007,7 +1007,7 @@ void free_write_pipe(struct file *f)
put_filp(f);
}
-struct file *create_read_pipe(struct file *wrf)
+struct file *create_read_pipe(struct file *wrf, int flags)
{
struct file *f = get_empty_filp();
if (!f)
@@ -1019,7 +1019,7 @@ struct file *create_read_pipe(struct file *wrf)
f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping;
f->f_pos = 0;
- f->f_flags = O_RDONLY;
+ f->f_flags = O_RDONLY | (flags & O_NONBLOCK);
f->f_op = &read_pipe_fops;
f->f_mode = FMODE_READ;
f->f_version = 0;
@@ -1027,26 +1027,29 @@ struct file *create_read_pipe(struct file *wrf)
return f;
}
-int do_pipe(int *fd)
+int do_pipe_flags(int *fd, int flags)
{
struct file *fw, *fr;
int error;
int fdw, fdr;
- fw = create_write_pipe();
+ if (flags & ~(O_CLOEXEC | O_NONBLOCK))
+ return -EINVAL;
+
+ fw = create_write_pipe(flags);
if (IS_ERR(fw))
return PTR_ERR(fw);
- fr = create_read_pipe(fw);
+ fr = create_read_pipe(fw, flags);
error = PTR_ERR(fr);
if (IS_ERR(fr))
goto err_write_pipe;
- error = get_unused_fd();
+ error = get_unused_fd_flags(flags);
if (error < 0)
goto err_read_pipe;
fdr = error;
- error = get_unused_fd();
+ error = get_unused_fd_flags(flags);
if (error < 0)
goto err_fdr;
fdw = error;
@@ -1074,16 +1077,21 @@ int do_pipe(int *fd)
return error;
}
+int do_pipe(int *fd)
+{
+ return do_pipe_flags(fd, 0);
+}
+
/*
* sys_pipe() is the normal C calling standard for creating
* a pipe. It's not the way Unix traditionally does this, though.
*/
-asmlinkage long __weak sys_pipe(int __user *fildes)
+asmlinkage long __weak sys_pipe2(int __user *fildes, int flags)
{
int fd[2];
int error;
- error = do_pipe(fd);
+ error = do_pipe_flags(fd, flags);
if (!error) {
if (copy_to_user(fildes, fd, sizeof(fd))) {
sys_close(fd[0]);
@@ -1094,6 +1102,11 @@ asmlinkage long __weak sys_pipe(int __user *fildes)
return error;
}
+asmlinkage long __weak sys_pipe(int __user *fildes)
+{
+ return sys_pipe2(fildes, 0);
+}
+
/*
* pipefs should _never_ be mounted by userland - too much of security hassle,
* no real gain from having the whole whorehouse mounted. So we don't need
diff --git a/fs/proc/Kconfig b/fs/proc/Kconfig
new file mode 100644
index 00000000000..73cd7a418f0
--- /dev/null
+++ b/fs/proc/Kconfig
@@ -0,0 +1,59 @@
+config PROC_FS
+ bool "/proc file system support" if EMBEDDED
+ default y
+ help
+ This is a virtual file system providing information about the status
+ of the system. "Virtual" means that it doesn't take up any space on
+ your hard disk: the files are created on the fly by the kernel when
+ you try to access them. Also, you cannot read the files with older
+ version of the program less: you need to use more or cat.
+
+ It's totally cool; for example, "cat /proc/interrupts" gives
+ information about what the different IRQs are used for at the moment
+ (there is a small number of Interrupt ReQuest lines in your computer
+ that are used by the attached devices to gain the CPU's attention --
+ often a source of trouble if two devices are mistakenly configured
+ to use the same IRQ). The program procinfo to display some
+ information about your system gathered from the /proc file system.
+
+ Before you can use the /proc file system, it has to be mounted,
+ meaning it has to be given a location in the directory hierarchy.
+ That location should be /proc. A command such as "mount -t proc proc
+ /proc" or the equivalent line in /etc/fstab does the job.
+
+ The /proc file system is explained in the file
+ <file:Documentation/filesystems/proc.txt> and on the proc(5) manpage
+ ("man 5 proc").
+
+ This option will enlarge your kernel by about 67 KB. Several
+ programs depend on this, so everyone should say Y here.
+
+config PROC_KCORE
+ bool "/proc/kcore support" if !ARM
+ depends on PROC_FS && MMU
+
+config PROC_VMCORE
+ bool "/proc/vmcore support (EXPERIMENTAL)"
+ depends on PROC_FS && CRASH_DUMP
+ default y
+ help
+ Exports the dump image of crashed kernel in ELF format.
+
+config PROC_SYSCTL
+ bool "Sysctl support (/proc/sys)" if EMBEDDED
+ depends on PROC_FS
+ select SYSCTL
+ default y
+ ---help---
+ The sysctl interface provides a means of dynamically changing
+ certain kernel parameters and variables on the fly without requiring
+ a recompile of the kernel or reboot of the system. The primary
+ interface is through /proc/sys. If you say Y here a tree of
+ modifiable sysctl entries will be generated beneath the
+ /proc/sys directory. They are explained in the files
+ in <file:Documentation/sysctl/>. Note that enabling this
+ option will enlarge the kernel by at least 8 KB.
+
+ As it is generally a good thing, you should say Y here unless
+ building a kernel for install/rescue disks or your system is very
+ limited in memory.
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 58c3e6a8e15..a891fe4cb43 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2376,29 +2376,82 @@ static int proc_base_fill_cache(struct file *filp, void *dirent,
}
#ifdef CONFIG_TASK_IO_ACCOUNTING
-static int proc_pid_io_accounting(struct task_struct *task, char *buffer)
-{
+static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
+{
+ u64 rchar, wchar, syscr, syscw;
+ struct task_io_accounting ioac;
+
+ if (!whole) {
+ rchar = task->rchar;
+ wchar = task->wchar;
+ syscr = task->syscr;
+ syscw = task->syscw;
+ memcpy(&ioac, &task->ioac, sizeof(ioac));
+ } else {
+ unsigned long flags;
+ struct task_struct *t = task;
+ rchar = wchar = syscr = syscw = 0;
+ memset(&ioac, 0, sizeof(ioac));
+
+ rcu_read_lock();
+ do {
+ rchar += t->rchar;
+ wchar += t->wchar;
+ syscr += t->syscr;
+ syscw += t->syscw;
+
+ ioac.read_bytes += t->ioac.read_bytes;
+ ioac.write_bytes += t->ioac.write_bytes;
+ ioac.cancelled_write_bytes +=
+ t->ioac.cancelled_write_bytes;
+ t = next_thread(t);
+ } while (t != task);
+ rcu_read_unlock();
+
+ if (lock_task_sighand(task, &flags)) {
+ struct signal_struct *sig = task->signal;
+
+ rchar += sig->rchar;
+ wchar += sig->wchar;
+ syscr += sig->syscr;
+ syscw += sig->syscw;
+
+ ioac.read_bytes += sig->ioac.read_bytes;
+ ioac.write_bytes += sig->ioac.write_bytes;
+ ioac.cancelled_write_bytes +=
+ sig->ioac.cancelled_write_bytes;
+
+ unlock_task_sighand(task, &flags);
+ }
+ }
+
return sprintf(buffer,
-#ifdef CONFIG_TASK_XACCT
"rchar: %llu\n"
"wchar: %llu\n"
"syscr: %llu\n"
"syscw: %llu\n"
-#endif
"read_bytes: %llu\n"
"write_bytes: %llu\n"
"cancelled_write_bytes: %llu\n",
-#ifdef CONFIG_TASK_XACCT
- (unsigned long long)task->rchar,
- (unsigned long long)task->wchar,
- (unsigned long long)task->syscr,
- (unsigned long long)task->syscw,
-#endif
- (unsigned long long)task->ioac.read_bytes,
- (unsigned long long)task->ioac.write_bytes,
- (unsigned long long)task->ioac.cancelled_write_bytes);
+ (unsigned long long)rchar,
+ (unsigned long long)wchar,
+ (unsigned long long)syscr,
+ (unsigned long long)syscw,
+ (unsigned long long)ioac.read_bytes,
+ (unsigned long long)ioac.write_bytes,
+ (unsigned long long)ioac.cancelled_write_bytes);
+}
+
+static int proc_tid_io_accounting(struct task_struct *task, char *buffer)
+{
+ return do_io_accounting(task, buffer, 0);
}
-#endif
+
+static int proc_tgid_io_accounting(struct task_struct *task, char *buffer)
+{
+ return do_io_accounting(task, buffer, 1);
+}
+#endif /* CONFIG_TASK_IO_ACCOUNTING */
/*
* Thread groups
@@ -2470,7 +2523,7 @@ static const struct pid_entry tgid_base_stuff[] = {
REG("coredump_filter", S_IRUGO|S_IWUSR, coredump_filter),
#endif
#ifdef CONFIG_TASK_IO_ACCOUNTING
- INF("io", S_IRUGO, pid_io_accounting),
+ INF("io", S_IRUGO, tgid_io_accounting),
#endif
};
@@ -2797,6 +2850,9 @@ static const struct pid_entry tid_base_stuff[] = {
#ifdef CONFIG_FAULT_INJECTION
REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
#endif
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+ INF("io", S_IRUGO, tid_io_accounting),
+#endif
};
static int proc_tid_base_readdir(struct file * filp,
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 43e54e86cef..bc0a0dd2d84 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -597,6 +597,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
ent->pde_users = 0;
spin_lock_init(&ent->pde_unload_lock);
ent->pde_unload_completion = NULL;
+ INIT_LIST_HEAD(&ent->pde_openers);
out:
return ent;
}
@@ -789,6 +790,19 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
spin_unlock(&de->pde_unload_lock);
continue_removing:
+ spin_lock(&de->pde_unload_lock);
+ while (!list_empty(&de->pde_openers)) {
+ struct pde_opener *pdeo;
+
+ pdeo = list_first_entry(&de->pde_openers, struct pde_opener, lh);
+ list_del(&pdeo->lh);
+ spin_unlock(&de->pde_unload_lock);
+ pdeo->release(pdeo->inode, pdeo->file);
+ kfree(pdeo);
+ spin_lock(&de->pde_unload_lock);
+ }
+ spin_unlock(&de->pde_unload_lock);
+
if (S_ISDIR(de->mode))
parent->nlink--;
de->nlink = 0;
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index b08d1001791..02eca2ed9dd 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -111,27 +111,25 @@ int __init proc_init_inodecache(void)
return 0;
}
-static int proc_remount(struct super_block *sb, int *flags, char *data)
-{
- *flags |= MS_NODIRATIME;
- return 0;
-}
-
static const struct super_operations proc_sops = {
.alloc_inode = proc_alloc_inode,
.destroy_inode = proc_destroy_inode,
.drop_inode = generic_delete_inode,
.delete_inode = proc_delete_inode,
.statfs = simple_statfs,
- .remount_fs = proc_remount,
};
-static void pde_users_dec(struct proc_dir_entry *pde)
+static void __pde_users_dec(struct proc_dir_entry *pde)
{
- spin_lock(&pde->pde_unload_lock);
pde->pde_users--;
if (pde->pde_unload_completion && pde->pde_users == 0)
complete(pde->pde_unload_completion);
+}
+
+static void pde_users_dec(struct proc_dir_entry *pde)
+{
+ spin_lock(&pde->pde_unload_lock);
+ __pde_users_dec(pde);
spin_unlock(&pde->pde_unload_lock);
}
@@ -318,36 +316,97 @@ static int proc_reg_open(struct inode *inode, struct file *file)
struct proc_dir_entry *pde = PDE(inode);
int rv = 0;
int (*open)(struct inode *, struct file *);
+ int (*release)(struct inode *, struct file *);
+ struct pde_opener *pdeo;
+
+ /*
+ * What for, you ask? Well, we can have open, rmmod, remove_proc_entry
+ * sequence. ->release won't be called because ->proc_fops will be
+ * cleared. Depending on complexity of ->release, consequences vary.
+ *
+ * We can't wait for mercy when close will be done for real, it's
+ * deadlockable: rmmod foo </proc/foo . So, we're going to do ->release
+ * by hand in remove_proc_entry(). For this, save opener's credentials
+ * for later.
+ */
+ pdeo = kmalloc(sizeof(struct pde_opener), GFP_KERNEL);
+ if (!pdeo)
+ return -ENOMEM;
spin_lock(&pde->pde_unload_lock);
if (!pde->proc_fops) {
spin_unlock(&pde->pde_unload_lock);
+ kfree(pdeo);
return rv;
}
pde->pde_users++;
open = pde->proc_fops->open;
+ release = pde->proc_fops->release;
spin_unlock(&pde->pde_unload_lock);
if (open)
rv = open(inode, file);
- pde_users_dec(pde);
+ spin_lock(&pde->pde_unload_lock);
+ if (rv == 0 && release) {
+ /* To know what to release. */
+ pdeo->inode = inode;
+ pdeo->file = file;
+ /* Strictly for "too late" ->release in proc_reg_release(). */
+ pdeo->release = release;
+ list_add(&pdeo->lh, &pde->pde_openers);
+ } else
+ kfree(pdeo);
+ __pde_users_dec(pde);
+ spin_unlock(&pde->pde_unload_lock);
return rv;
}
+static struct pde_opener *find_pde_opener(struct proc_dir_entry *pde,
+ struct inode *inode, struct file *file)
+{
+ struct pde_opener *pdeo;
+
+ list_for_each_entry(pdeo, &pde->pde_openers, lh) {
+ if (pdeo->inode == inode && pdeo->file == file)
+ return pdeo;
+ }
+ return NULL;
+}
+
static int proc_reg_release(struct inode *inode, struct file *file)
{
struct proc_dir_entry *pde = PDE(inode);
int rv = 0;
int (*release)(struct inode *, struct file *);
+ struct pde_opener *pdeo;
spin_lock(&pde->pde_unload_lock);
+ pdeo = find_pde_opener(pde, inode, file);
if (!pde->proc_fops) {
- spin_unlock(&pde->pde_unload_lock);
+ /*
+ * Can't simply exit, __fput() will think that everything is OK,
+ * and move on to freeing struct file. remove_proc_entry() will
+ * find slacker in opener's list and will try to do non-trivial
+ * things with struct file. Therefore, remove opener from list.
+ *
+ * But if opener is removed from list, who will ->release it?
+ */
+ if (pdeo) {
+ list_del(&pdeo->lh);
+ spin_unlock(&pde->pde_unload_lock);
+ rv = pdeo->release(inode, file);
+ kfree(pdeo);
+ } else
+ spin_unlock(&pde->pde_unload_lock);
return rv;
}
pde->pde_users++;
release = pde->proc_fops->release;
+ if (pdeo) {
+ list_del(&pdeo->lh);
+ kfree(pdeo);
+ }
spin_unlock(&pde->pde_unload_lock);
if (release)
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 28cbca80590..442202314d5 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -63,6 +63,7 @@ extern const struct file_operations proc_smaps_operations;
extern const struct file_operations proc_clear_refs_operations;
extern const struct file_operations proc_pagemap_operations;
extern const struct file_operations proc_net_operations;
+extern const struct file_operations proc_kmsg_operations;
extern const struct inode_operations proc_net_inode_operations;
void free_proc_entry(struct proc_dir_entry *de);
@@ -88,3 +89,10 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *ino,
struct dentry *dentry);
int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent,
filldir_t filldir);
+
+struct pde_opener {
+ struct inode *inode;
+ struct file *file;
+ int (*release)(struct inode *, struct file *);
+ struct list_head lh;
+};
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index e78c81fcf54..c2370c76fb7 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -23,6 +23,10 @@
#define CORE_STR "CORE"
+#ifndef ELF_CORE_EFLAGS
+#define ELF_CORE_EFLAGS 0
+#endif
+
static int open_kcore(struct inode * inode, struct file * filp)
{
return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
@@ -164,11 +168,7 @@ static void elf_kcore_store_hdr(char *bufp, int nphdr, int dataoff)
elf->e_entry = 0;
elf->e_phoff = sizeof(struct elfhdr);
elf->e_shoff = 0;
-#if defined(CONFIG_H8300)
- elf->e_flags = ELF_FLAGS;
-#else
- elf->e_flags = 0;
-#endif
+ elf->e_flags = ELF_CORE_EFLAGS;
elf->e_ehsize = sizeof(struct elfhdr);
elf->e_phentsize= sizeof(struct elf_phdr);
elf->e_phnum = nphdr;
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
index ff3b90b56e9..9fd5df3f40c 100644
--- a/fs/proc/kmsg.c
+++ b/fs/proc/kmsg.c
@@ -15,6 +15,8 @@
#include <asm/uaccess.h>
#include <asm/io.h>
+#include "internal.h"
+
extern wait_queue_head_t log_wait;
extern int do_syslog(int type, char __user *bug, int count);
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index c652d469dc0..ded96986296 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -232,7 +232,6 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
#undef K
}
-extern const struct seq_operations fragmentation_op;
static int fragmentation_open(struct inode *inode, struct file *file)
{
(void)inode;
@@ -246,7 +245,6 @@ static const struct file_operations fragmentation_file_operations = {
.release = seq_release,
};
-extern const struct seq_operations pagetypeinfo_op;
static int pagetypeinfo_open(struct inode *inode, struct file *file)
{
return seq_open(file, &pagetypeinfo_op);
@@ -259,7 +257,6 @@ static const struct file_operations pagetypeinfo_file_ops = {
.release = seq_release,
};
-extern const struct seq_operations zoneinfo_op;
static int zoneinfo_open(struct inode *inode, struct file *file)
{
return seq_open(file, &zoneinfo_op);
@@ -356,7 +353,6 @@ static const struct file_operations proc_devinfo_operations = {
.release = seq_release,
};
-extern const struct seq_operations vmstat_op;
static int vmstat_open(struct inode *inode, struct file *file)
{
return seq_open(file, &vmstat_op);
@@ -468,14 +464,25 @@ static const struct file_operations proc_slabstats_operations = {
#ifdef CONFIG_MMU
static int vmalloc_open(struct inode *inode, struct file *file)
{
- return seq_open(file, &vmalloc_op);
+ unsigned int *ptr = NULL;
+ int ret;
+
+ if (NUMA_BUILD)
+ ptr = kmalloc(nr_node_ids * sizeof(unsigned int), GFP_KERNEL);
+ ret = seq_open(file, &vmalloc_op);
+ if (!ret) {
+ struct seq_file *m = file->private_data;
+ m->private = ptr;
+ } else
+ kfree(ptr);
+ return ret;
}
static const struct file_operations proc_vmalloc_operations = {
.open = vmalloc_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = seq_release_private,
};
#endif
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index b224a28e0c1..7bc296f424a 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -27,6 +27,11 @@
#include "internal.h"
+static struct net *get_proc_net(const struct inode *inode)
+{
+ return maybe_get_net(PDE_NET(PDE(inode)));
+}
+
int seq_open_net(struct inode *ino, struct file *f,
const struct seq_operations *ops, int size)
{
@@ -185,12 +190,6 @@ void proc_net_remove(struct net *net, const char *name)
}
EXPORT_SYMBOL_GPL(proc_net_remove);
-struct net *get_proc_net(const struct inode *inode)
-{
- return maybe_get_net(PDE_NET(PDE(inode)));
-}
-EXPORT_SYMBOL_GPL(get_proc_net);
-
static __net_init int proc_net_ns_init(struct net *net)
{
struct proc_dir_entry *netd, *net_statd;
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 164bd9f9ede..7546a918f79 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -636,7 +636,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
struct pagemapread pm;
int pagecount;
int ret = -ESRCH;
- struct mm_walk pagemap_walk;
+ struct mm_walk pagemap_walk = {};
unsigned long src;
unsigned long svpfn;
unsigned long start_vaddr;
diff --git a/fs/quota.c b/fs/quota.c
index db1cc9f3c7a..7f4386ebc23 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -186,7 +186,7 @@ static void quota_sync_sb(struct super_block *sb, int type)
void sync_dquots(struct super_block *sb, int type)
{
- int cnt, dirty;
+ int cnt;
if (sb) {
if (sb->s_qcop->quota_sync)
@@ -198,11 +198,17 @@ void sync_dquots(struct super_block *sb, int type)
restart:
list_for_each_entry(sb, &super_blocks, s_list) {
/* This test just improves performance so it needn't be reliable... */
- for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++)
- if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt)
- && info_any_dirty(&sb_dqopt(sb)->info[cnt]))
- dirty = 1;
- if (!dirty)
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+ if (type != -1 && type != cnt)
+ continue;
+ if (!sb_has_quota_enabled(sb, cnt))
+ continue;
+ if (!info_dirty(&sb_dqopt(sb)->info[cnt]) &&
+ list_empty(&sb_dqopt(sb)->info[cnt].dqi_dirty_list))
+ continue;
+ break;
+ }
+ if (cnt == MAXQUOTAS)
continue;
sb->s_count++;
spin_unlock(&sb_lock);
diff --git a/fs/quota_v1.c b/fs/quota_v1.c
index a6cf9269105..5ae15b13eeb 100644
--- a/fs/quota_v1.c
+++ b/fs/quota_v1.c
@@ -1,6 +1,7 @@
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/quota.h>
+#include <linux/quotaops.h>
#include <linux/dqblk_v1.h>
#include <linux/quotaio_v1.h>
#include <linux/kernel.h>
diff --git a/fs/quota_v2.c b/fs/quota_v2.c
index 234ada90363..b53827dc02d 100644
--- a/fs/quota_v2.c
+++ b/fs/quota_v2.c
@@ -11,6 +11,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/quotaops.h>
#include <asm/byteorder.h>
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index e396b2fa474..c8f60ee183b 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -34,15 +34,10 @@
** from within kupdate, it will ignore the immediate flag
*/
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
#include <linux/time.h>
#include <linux/semaphore.h>
-
#include <linux/vmalloc.h>
#include <linux/reiserfs_fs.h>
-
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
@@ -54,6 +49,9 @@
#include <linux/writeback.h>
#include <linux/blkdev.h>
#include <linux/backing-dev.h>
+#include <linux/uaccess.h>
+
+#include <asm/system.h>
/* gets a struct reiserfs_journal_list * from a list head */
#define JOURNAL_LIST_ENTRY(h) (list_entry((h), struct reiserfs_journal_list, \
@@ -558,13 +556,13 @@ static inline void insert_journal_hash(struct reiserfs_journal_cnode **table,
static inline void lock_journal(struct super_block *p_s_sb)
{
PROC_INFO_INC(p_s_sb, journal.lock_journal);
- down(&SB_JOURNAL(p_s_sb)->j_lock);
+ mutex_lock(&SB_JOURNAL(p_s_sb)->j_mutex);
}
/* unlock the current transaction */
static inline void unlock_journal(struct super_block *p_s_sb)
{
- up(&SB_JOURNAL(p_s_sb)->j_lock);
+ mutex_unlock(&SB_JOURNAL(p_s_sb)->j_mutex);
}
static inline void get_journal_list(struct reiserfs_journal_list *jl)
@@ -1045,9 +1043,9 @@ static int flush_commit_list(struct super_block *s,
}
/* make sure nobody is trying to flush this one at the same time */
- down(&jl->j_commit_lock);
+ mutex_lock(&jl->j_commit_mutex);
if (!journal_list_still_alive(s, trans_id)) {
- up(&jl->j_commit_lock);
+ mutex_unlock(&jl->j_commit_mutex);
goto put_jl;
}
BUG_ON(jl->j_trans_id == 0);
@@ -1057,7 +1055,7 @@ static int flush_commit_list(struct super_block *s,
if (flushall) {
atomic_set(&(jl->j_older_commits_done), 1);
}
- up(&jl->j_commit_lock);
+ mutex_unlock(&jl->j_commit_mutex);
goto put_jl;
}
@@ -1181,7 +1179,7 @@ static int flush_commit_list(struct super_block *s,
if (flushall) {
atomic_set(&(jl->j_older_commits_done), 1);
}
- up(&jl->j_commit_lock);
+ mutex_unlock(&jl->j_commit_mutex);
put_jl:
put_journal_list(s, jl);
@@ -1411,8 +1409,8 @@ static int flush_journal_list(struct super_block *s,
/* if flushall == 0, the lock is already held */
if (flushall) {
- down(&journal->j_flush_sem);
- } else if (!down_trylock(&journal->j_flush_sem)) {
+ mutex_lock(&journal->j_flush_mutex);
+ } else if (mutex_trylock(&journal->j_flush_mutex)) {
BUG();
}
@@ -1642,7 +1640,7 @@ static int flush_journal_list(struct super_block *s,
jl->j_state = 0;
put_journal_list(s, jl);
if (flushall)
- up(&journal->j_flush_sem);
+ mutex_unlock(&journal->j_flush_mutex);
put_fs_excl();
return err;
}
@@ -1772,12 +1770,12 @@ static int kupdate_transactions(struct super_block *s,
struct reiserfs_journal *journal = SB_JOURNAL(s);
chunk.nr = 0;
- down(&journal->j_flush_sem);
+ mutex_lock(&journal->j_flush_mutex);
if (!journal_list_still_alive(s, orig_trans_id)) {
goto done;
}
- /* we've got j_flush_sem held, nobody is going to delete any
+ /* we've got j_flush_mutex held, nobody is going to delete any
* of these lists out from underneath us
*/
while ((num_trans && transactions_flushed < num_trans) ||
@@ -1812,7 +1810,7 @@ static int kupdate_transactions(struct super_block *s,
}
done:
- up(&journal->j_flush_sem);
+ mutex_unlock(&journal->j_flush_mutex);
return ret;
}
@@ -2556,7 +2554,7 @@ static struct reiserfs_journal_list *alloc_journal_list(struct super_block *s)
INIT_LIST_HEAD(&jl->j_working_list);
INIT_LIST_HEAD(&jl->j_tail_bh_list);
INIT_LIST_HEAD(&jl->j_bh_list);
- sema_init(&jl->j_commit_lock, 1);
+ mutex_init(&jl->j_commit_mutex);
SB_JOURNAL(s)->j_num_lists++;
get_journal_list(jl);
return jl;
@@ -2837,8 +2835,8 @@ int journal_init(struct super_block *p_s_sb, const char *j_dev_name,
journal->j_last = NULL;
journal->j_first = NULL;
init_waitqueue_head(&(journal->j_join_wait));
- sema_init(&journal->j_lock, 1);
- sema_init(&journal->j_flush_sem, 1);
+ mutex_init(&journal->j_mutex);
+ mutex_init(&journal->j_flush_mutex);
journal->j_trans_id = 10;
journal->j_mount_id = 10;
@@ -4030,7 +4028,7 @@ static int do_journal_end(struct reiserfs_transaction_handle *th,
* the new transaction is fully setup, and we've already flushed the
* ordered bh list
*/
- down(&jl->j_commit_lock);
+ mutex_lock(&jl->j_commit_mutex);
/* save the transaction id in case we need to commit it later */
commit_trans_id = jl->j_trans_id;
@@ -4196,7 +4194,7 @@ static int do_journal_end(struct reiserfs_transaction_handle *th,
lock_kernel();
}
BUG_ON(!list_empty(&jl->j_tail_bh_list));
- up(&jl->j_commit_lock);
+ mutex_unlock(&jl->j_commit_mutex);
/* honor the flush wishes from the caller, simple commits can
** be done outside the journal lock, they are done below
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 1d40f2bd197..2ec748ba0bd 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -22,6 +22,7 @@
#include <linux/blkdev.h>
#include <linux/buffer_head.h>
#include <linux/exportfs.h>
+#include <linux/quotaops.h>
#include <linux/vfs.h>
#include <linux/mnt_namespace.h>
#include <linux/mount.h>
@@ -182,7 +183,7 @@ static int finish_unfinished(struct super_block *s)
int ret = reiserfs_quota_on_mount(s, i);
if (ret < 0)
reiserfs_warning(s,
- "reiserfs: cannot turn on journalled quota: error %d",
+ "reiserfs: cannot turn on journaled quota: error %d",
ret);
}
}
@@ -876,7 +877,9 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin
mount options were selected. */
unsigned long *blocks, /* strtol-ed from NNN of resize=NNN */
char **jdev_name,
- unsigned int *commit_max_age)
+ unsigned int *commit_max_age,
+ char **qf_names,
+ unsigned int *qfmt)
{
int c;
char *arg = NULL;
@@ -992,9 +995,11 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin
if (c == 'u' || c == 'g') {
int qtype = c == 'u' ? USRQUOTA : GRPQUOTA;
- if (sb_any_quota_enabled(s)) {
+ if ((sb_any_quota_enabled(s) ||
+ sb_any_quota_suspended(s)) &&
+ (!*arg != !REISERFS_SB(s)->s_qf_names[qtype])) {
reiserfs_warning(s,
- "reiserfs_parse_options: cannot change journalled quota options when quota turned on.");
+ "reiserfs_parse_options: cannot change journaled quota options when quota turned on.");
return 0;
}
if (*arg) { /* Some filename specified? */
@@ -1011,46 +1016,54 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin
"reiserfs_parse_options: quotafile must be on filesystem root.");
return 0;
}
- REISERFS_SB(s)->s_qf_names[qtype] =
+ qf_names[qtype] =
kmalloc(strlen(arg) + 1, GFP_KERNEL);
- if (!REISERFS_SB(s)->s_qf_names[qtype]) {
+ if (!qf_names[qtype]) {
reiserfs_warning(s,
"reiserfs_parse_options: not enough memory for storing quotafile name.");
return 0;
}
- strcpy(REISERFS_SB(s)->s_qf_names[qtype], arg);
+ strcpy(qf_names[qtype], arg);
*mount_options |= 1 << REISERFS_QUOTA;
} else {
- kfree(REISERFS_SB(s)->s_qf_names[qtype]);
- REISERFS_SB(s)->s_qf_names[qtype] = NULL;
+ if (qf_names[qtype] !=
+ REISERFS_SB(s)->s_qf_names[qtype])
+ kfree(qf_names[qtype]);
+ qf_names[qtype] = NULL;
}
}
if (c == 'f') {
if (!strcmp(arg, "vfsold"))
- REISERFS_SB(s)->s_jquota_fmt = QFMT_VFS_OLD;
+ *qfmt = QFMT_VFS_OLD;
else if (!strcmp(arg, "vfsv0"))
- REISERFS_SB(s)->s_jquota_fmt = QFMT_VFS_V0;
+ *qfmt = QFMT_VFS_V0;
else {
reiserfs_warning(s,
"reiserfs_parse_options: unknown quota format specified.");
return 0;
}
+ if ((sb_any_quota_enabled(s) ||
+ sb_any_quota_suspended(s)) &&
+ *qfmt != REISERFS_SB(s)->s_jquota_fmt) {
+ reiserfs_warning(s,
+ "reiserfs_parse_options: cannot change journaled quota options when quota turned on.");
+ return 0;
+ }
}
#else
if (c == 'u' || c == 'g' || c == 'f') {
reiserfs_warning(s,
- "reiserfs_parse_options: journalled quota options not supported.");
+ "reiserfs_parse_options: journaled quota options not supported.");
return 0;
}
#endif
}
#ifdef CONFIG_QUOTA
- if (!REISERFS_SB(s)->s_jquota_fmt
- && (REISERFS_SB(s)->s_qf_names[USRQUOTA]
- || REISERFS_SB(s)->s_qf_names[GRPQUOTA])) {
+ if (!REISERFS_SB(s)->s_jquota_fmt && !*qfmt
+ && (qf_names[USRQUOTA] || qf_names[GRPQUOTA])) {
reiserfs_warning(s,
- "reiserfs_parse_options: journalled quota format not specified.");
+ "reiserfs_parse_options: journaled quota format not specified.");
return 0;
}
/* This checking is not precise wrt the quota type but for our purposes it is sufficient */
@@ -1130,6 +1143,21 @@ static void handle_attrs(struct super_block *s)
}
}
+#ifdef CONFIG_QUOTA
+static void handle_quota_files(struct super_block *s, char **qf_names,
+ unsigned int *qfmt)
+{
+ int i;
+
+ for (i = 0; i < MAXQUOTAS; i++) {
+ if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i])
+ kfree(REISERFS_SB(s)->s_qf_names[i]);
+ REISERFS_SB(s)->s_qf_names[i] = qf_names[i];
+ }
+ REISERFS_SB(s)->s_jquota_fmt = *qfmt;
+}
+#endif
+
static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
{
struct reiserfs_super_block *rs;
@@ -1141,23 +1169,30 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
struct reiserfs_journal *journal = SB_JOURNAL(s);
char *new_opts = kstrdup(arg, GFP_KERNEL);
int err;
+ char *qf_names[MAXQUOTAS];
+ unsigned int qfmt = 0;
#ifdef CONFIG_QUOTA
int i;
+
+ memcpy(qf_names, REISERFS_SB(s)->s_qf_names, sizeof(qf_names));
#endif
rs = SB_DISK_SUPER_BLOCK(s);
if (!reiserfs_parse_options
- (s, arg, &mount_options, &blocks, NULL, &commit_max_age)) {
+ (s, arg, &mount_options, &blocks, NULL, &commit_max_age,
+ qf_names, &qfmt)) {
#ifdef CONFIG_QUOTA
- for (i = 0; i < MAXQUOTAS; i++) {
- kfree(REISERFS_SB(s)->s_qf_names[i]);
- REISERFS_SB(s)->s_qf_names[i] = NULL;
- }
+ for (i = 0; i < MAXQUOTAS; i++)
+ if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i])
+ kfree(qf_names[i]);
#endif
err = -EINVAL;
goto out_err;
}
+#ifdef CONFIG_QUOTA
+ handle_quota_files(s, qf_names, &qfmt);
+#endif
handle_attrs(s);
@@ -1570,6 +1605,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
char *jdev_name;
struct reiserfs_sb_info *sbi;
int errval = -EINVAL;
+ char *qf_names[MAXQUOTAS] = {};
+ unsigned int qfmt = 0;
save_mount_options(s, data);
@@ -1597,9 +1634,12 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
jdev_name = NULL;
if (reiserfs_parse_options
(s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name,
- &commit_max_age) == 0) {
+ &commit_max_age, qf_names, &qfmt) == 0) {
goto error;
}
+#ifdef CONFIG_QUOTA
+ handle_quota_files(s, qf_names, &qfmt);
+#endif
if (blocks) {
SWARN(silent, s, "jmacd-7: reiserfs_fill_super: resize option "
@@ -1819,7 +1859,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
return (0);
- error:
+error:
if (jinit_done) { /* kill the commit thread, free journal ram */
journal_release_error(NULL, s);
}
@@ -1830,10 +1870,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
#ifdef CONFIG_QUOTA
{
int j;
- for (j = 0; j < MAXQUOTAS; j++) {
- kfree(sbi->s_qf_names[j]);
- sbi->s_qf_names[j] = NULL;
- }
+ for (j = 0; j < MAXQUOTAS; j++)
+ kfree(qf_names[j]);
}
#endif
kfree(sbi);
@@ -1980,7 +2018,7 @@ static int reiserfs_release_dquot(struct dquot *dquot)
static int reiserfs_mark_dquot_dirty(struct dquot *dquot)
{
- /* Are we journalling quotas? */
+ /* Are we journaling quotas? */
if (REISERFS_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] ||
REISERFS_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) {
dquot_mark_dquot_dirty(dquot);
@@ -2026,6 +2064,7 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
int err;
struct nameidata nd;
struct inode *inode;
+ struct reiserfs_transaction_handle th;
if (!(REISERFS_SB(sb)->s_mount_opt & (1 << REISERFS_QUOTA)))
return -EINVAL;
@@ -2053,17 +2092,28 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
}
mark_inode_dirty(inode);
}
- /* Not journalling quota? No more tests needed... */
- if (!REISERFS_SB(sb)->s_qf_names[USRQUOTA] &&
- !REISERFS_SB(sb)->s_qf_names[GRPQUOTA]) {
- path_put(&nd.path);
- return vfs_quota_on(sb, type, format_id, path, 0);
- }
- /* Quotafile not of fs root? */
- if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
- reiserfs_warning(sb,
+ /* Journaling quota? */
+ if (REISERFS_SB(sb)->s_qf_names[type]) {
+ /* Quotafile not of fs root? */
+ if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
+ reiserfs_warning(sb,
"reiserfs: Quota file not on filesystem root. "
"Journalled quota will not work.");
+ }
+
+ /*
+ * When we journal data on quota file, we have to flush journal to see
+ * all updates to the file when we bypass pagecache...
+ */
+ if (reiserfs_file_data_log(inode)) {
+ /* Just start temporary transaction and finish it */
+ err = journal_begin(&th, sb, 1);
+ if (err)
+ return err;
+ err = journal_end_sync(&th, sb, 1);
+ if (err)
+ return err;
+ }
path_put(&nd.path);
return vfs_quota_on(sb, type, format_id, path, 0);
}
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index 5e90a95ad60..056008db137 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -6,8 +6,6 @@
#include <linux/reiserfs_xattr.h>
#include <asm/uaccess.h>
-#define XATTR_SECURITY_PREFIX "security."
-
static int
security_get(struct inode *inode, const char *name, void *buffer, size_t size)
{
diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c
index 024a938ca60..60abe2bb1f9 100644
--- a/fs/reiserfs/xattr_trusted.c
+++ b/fs/reiserfs/xattr_trusted.c
@@ -7,8 +7,6 @@
#include <linux/reiserfs_xattr.h>
#include <asm/uaccess.h>
-#define XATTR_TRUSTED_PREFIX "trusted."
-
static int
trusted_get(struct inode *inode, const char *name, void *buffer, size_t size)
{
diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c
index 073f39364b1..1384efcb938 100644
--- a/fs/reiserfs/xattr_user.c
+++ b/fs/reiserfs/xattr_user.c
@@ -10,8 +10,6 @@
# include <linux/reiserfs_acl.h>
#endif
-#define XATTR_USER_PREFIX "user."
-
static int
user_get(struct inode *inode, const char *name, void *buffer, size_t size)
{
diff --git a/fs/signalfd.c b/fs/signalfd.c
index 619725644c7..9c39bc7f843 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -205,11 +205,19 @@ static const struct file_operations signalfd_fops = {
.read = signalfd_read,
};
-asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask)
+asmlinkage long sys_signalfd4(int ufd, sigset_t __user *user_mask,
+ size_t sizemask, int flags)
{
sigset_t sigmask;
struct signalfd_ctx *ctx;
+ /* Check the SFD_* constants for consistency. */
+ BUILD_BUG_ON(SFD_CLOEXEC != O_CLOEXEC);
+ BUILD_BUG_ON(SFD_NONBLOCK != O_NONBLOCK);
+
+ if (flags & ~(SFD_CLOEXEC | SFD_NONBLOCK))
+ return -EINVAL;
+
if (sizemask != sizeof(sigset_t) ||
copy_from_user(&sigmask, user_mask, sizeof(sigmask)))
return -EINVAL;
@@ -227,7 +235,8 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas
* When we call this, the initialization must be complete, since
* anon_inode_getfd() will install the fd.
*/
- ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx);
+ ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx,
+ flags & (O_CLOEXEC | O_NONBLOCK));
if (ufd < 0)
kfree(ctx);
} else {
@@ -249,3 +258,9 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas
return ufd;
}
+
+asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask,
+ size_t sizemask)
+{
+ return sys_signalfd4(ufd, user_mask, sizemask, 0);
+}
diff --git a/fs/smbfs/cache.c b/fs/smbfs/cache.c
index 8182f0542a2..8c177eb7e34 100644
--- a/fs/smbfs/cache.c
+++ b/fs/smbfs/cache.c
@@ -13,7 +13,6 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/mm.h>
-#include <linux/dirent.h>
#include <linux/smb_fs.h>
#include <linux/pagemap.h>
#include <linux/net.h>
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index d517a27b7f4..ee536e8a649 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -16,7 +16,6 @@
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/dcache.h>
-#include <linux/dirent.h>
#include <linux/nls.h>
#include <linux/smp_lock.h>
#include <linux/net.h>
diff --git a/fs/super.c b/fs/super.c
index 453877c5697..e931ae9511f 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -70,6 +70,7 @@ static struct super_block *alloc_super(struct file_system_type *type)
INIT_LIST_HEAD(&s->s_instances);
INIT_HLIST_HEAD(&s->s_anon);
INIT_LIST_HEAD(&s->s_inodes);
+ INIT_LIST_HEAD(&s->s_dentry_lru);
init_rwsem(&s->s_umount);
mutex_init(&s->s_lock);
lockdep_set_class(&s->s_umount, &type->s_umount_key);
diff --git a/fs/sync.c b/fs/sync.c
index 228e17b5e9e..2967562d416 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -139,7 +139,8 @@ asmlinkage long sys_fdatasync(unsigned int fd)
* before performing the write.
*
* SYNC_FILE_RANGE_WRITE: initiate writeout of all those dirty pages in the
- * range which are not presently under writeback.
+ * range which are not presently under writeback. Note that this may block for
+ * significant periods due to exhaustion of disk request structures.
*
* SYNC_FILE_RANGE_WAIT_AFTER: wait upon writeout of all pages in the range
* after performing the write.
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 8c0e4b92574..c1a7efb310b 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -398,7 +398,7 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
}
/**
- * sysfs_add_one - add sysfs_dirent to parent
+ * __sysfs_add_one - add sysfs_dirent to parent without warning
* @acxt: addrm context to use
* @sd: sysfs_dirent to be added
*
@@ -417,7 +417,7 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
* 0 on success, -EEXIST if entry with the given name already
* exists.
*/
-int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
+int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
{
if (sysfs_find_dirent(acxt->parent_sd, sd->s_name))
return -EEXIST;
@@ -435,6 +435,39 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
}
/**
+ * sysfs_add_one - add sysfs_dirent to parent
+ * @acxt: addrm context to use
+ * @sd: sysfs_dirent to be added
+ *
+ * Get @acxt->parent_sd and set sd->s_parent to it and increment
+ * nlink of parent inode if @sd is a directory and link into the
+ * children list of the parent.
+ *
+ * This function should be called between calls to
+ * sysfs_addrm_start() and sysfs_addrm_finish() and should be
+ * passed the same @acxt as passed to sysfs_addrm_start().
+ *
+ * LOCKING:
+ * Determined by sysfs_addrm_start().
+ *
+ * RETURNS:
+ * 0 on success, -EEXIST if entry with the given name already
+ * exists.
+ */
+int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
+{
+ int ret;
+
+ ret = __sysfs_add_one(acxt, sd);
+ if (ret == -EEXIST) {
+ printk(KERN_WARNING "sysfs: duplicate filename '%s' "
+ "can not be created\n", sd->s_name);
+ WARN_ON(1);
+ }
+ return ret;
+}
+
+/**
* sysfs_remove_one - remove sysfs_dirent from parent
* @acxt: addrm context to use
* @sd: sysfs_dirent to be removed
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index e7735f643cd..3f07893ff89 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -14,6 +14,7 @@
#include <linux/kobject.h>
#include <linux/kallsyms.h>
#include <linux/slab.h>
+#include <linux/fsnotify.h>
#include <linux/namei.h>
#include <linux/poll.h>
#include <linux/list.h>
@@ -585,9 +586,11 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
- rc = notify_change(victim, &newattrs);
+ newattrs.ia_ctime = current_fs_time(inode->i_sb);
+ rc = sysfs_setattr(victim, &newattrs);
if (rc == 0) {
+ fsnotify_change(victim, newattrs.ia_valid);
mutex_lock(&sysfs_mutex);
victim_sd->s_mode = newattrs.ia_mode;
mutex_unlock(&sysfs_mutex);
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 817f5966edc..a3ba217fbe7 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -19,13 +19,8 @@
#include "sysfs.h"
-/**
- * sysfs_create_link - create symlink between two objects.
- * @kobj: object whose directory we're creating the link in.
- * @target: object we're pointing to.
- * @name: name of the symlink.
- */
-int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
+static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target,
+ const char *name, int warn)
{
struct sysfs_dirent *parent_sd = NULL;
struct sysfs_dirent *target_sd = NULL;
@@ -65,7 +60,10 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
target_sd = NULL; /* reference is now owned by the symlink */
sysfs_addrm_start(&acxt, parent_sd);
- error = sysfs_add_one(&acxt, sd);
+ if (warn)
+ error = sysfs_add_one(&acxt, sd);
+ else
+ error = __sysfs_add_one(&acxt, sd);
sysfs_addrm_finish(&acxt);
if (error)
@@ -80,6 +78,33 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
}
/**
+ * sysfs_create_link - create symlink between two objects.
+ * @kobj: object whose directory we're creating the link in.
+ * @target: object we're pointing to.
+ * @name: name of the symlink.
+ */
+int sysfs_create_link(struct kobject *kobj, struct kobject *target,
+ const char *name)
+{
+ return sysfs_do_create_link(kobj, target, name, 1);
+}
+
+/**
+ * sysfs_create_link_nowarn - create symlink between two objects.
+ * @kobj: object whose directory we're creating the link in.
+ * @target: object we're pointing to.
+ * @name: name of the symlink.
+ *
+ * This function does the same as sysf_create_link(), but it
+ * doesn't warn if the link already exists.
+ */
+int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target,
+ const char *name)
+{
+ return sysfs_do_create_link(kobj, target, name, 0);
+}
+
+/**
* sysfs_remove_link - remove symlink in object's directory.
* @kobj: object we're acting for.
* @name: name of the symlink to remove.
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index ce4e15f8aae..a5db496f71c 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -107,6 +107,7 @@ struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd);
void sysfs_put_active_two(struct sysfs_dirent *sd);
void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
struct sysfs_dirent *parent_sd);
+int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
diff --git a/fs/timerfd.c b/fs/timerfd.c
index d87d354ec42..c502c60e4f5 100644
--- a/fs/timerfd.c
+++ b/fs/timerfd.c
@@ -184,7 +184,11 @@ asmlinkage long sys_timerfd_create(int clockid, int flags)
int ufd;
struct timerfd_ctx *ctx;
- if (flags)
+ /* Check the TFD_* constants for consistency. */
+ BUILD_BUG_ON(TFD_CLOEXEC != O_CLOEXEC);
+ BUILD_BUG_ON(TFD_NONBLOCK != O_NONBLOCK);
+
+ if (flags & ~(TFD_CLOEXEC | TFD_NONBLOCK))
return -EINVAL;
if (clockid != CLOCK_MONOTONIC &&
clockid != CLOCK_REALTIME)
@@ -198,7 +202,8 @@ asmlinkage long sys_timerfd_create(int clockid, int flags)
ctx->clockid = clockid;
hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS);
- ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx);
+ ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx,
+ flags & (O_CLOEXEC | O_NONBLOCK));
if (ufd < 0)
kfree(ctx);
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 85b22b5977f..227c9d70004 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -76,6 +76,7 @@
#include <linux/errno.h>
#include <linux/fs.h>
+#include <linux/quotaops.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/stat.h>
@@ -1232,7 +1233,7 @@ static int ufs_show_options(struct seq_file *seq, struct vfsmount *vfs)
{
struct ufs_sb_info *sbi = UFS_SB(vfs->mnt_sb);
unsigned mval = sbi->s_mount_opt & UFS_MOUNT_UFSTYPE;
- struct match_token *tp = tokens;
+ const struct match_token *tp = tokens;
while (tp->token != Opt_onerror_panic && tp->token != mval)
++tp;
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index b546ba69be8..155c10b4adb 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -621,7 +621,7 @@ shortname:
memcpy(de->name, msdos_name, MSDOS_NAME);
de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
de->lcase = lcase;
- fat_date_unix2dos(ts->tv_sec, &time, &date);
+ fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc);
de->time = de->ctime = time;
de->date = de->cdate = de->adate = date;
de->ctime_cs = 0;
diff --git a/include/asm-alpha/ide.h b/include/asm-alpha/ide.h
deleted file mode 100644
index f44129abc02..00000000000
--- a/include/asm-alpha/ide.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * linux/include/asm-alpha/ide.h
- *
- * Copyright (C) 1994-1996 Linus Torvalds & authors
- */
-
-/*
- * This file contains the alpha architecture specific IDE code.
- */
-
-#ifndef __ASMalpha_IDE_H
-#define __ASMalpha_IDE_H
-
-#ifdef __KERNEL__
-
-static inline int ide_default_irq(unsigned long base)
-{
- switch (base) {
- case 0x1f0: return 14;
- case 0x170: return 15;
- case 0x1e8: return 11;
- case 0x168: return 10;
- default:
- return 0;
- }
-}
-
-static inline unsigned long ide_default_io_base(int index)
-{
- switch (index) {
- case 0: return 0x1f0;
- case 1: return 0x170;
- case 2: return 0x1e8;
- case 3: return 0x168;
- default:
- return 0;
- }
-}
-
-#include <asm-generic/ide_iops.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASMalpha_IDE_H */
diff --git a/include/asm-alpha/kvm.h b/include/asm-alpha/kvm.h
deleted file mode 100644
index b9daec42968..00000000000
--- a/include/asm-alpha/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_ALPHA_H
-#define __LINUX_KVM_ALPHA_H
-
-/* alpha does not support KVM */
-
-#endif
diff --git a/include/asm-alpha/page.h b/include/asm-alpha/page.h
index 22ff9762d17..0995f9d1341 100644
--- a/include/asm-alpha/page.h
+++ b/include/asm-alpha/page.h
@@ -80,9 +80,6 @@ typedef struct page *pgtable_t;
#endif /* !__ASSEMBLY__ */
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
#ifndef CONFIG_DISCONTIGMEM
diff --git a/include/asm-alpha/semaphore.h b/include/asm-alpha/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-alpha/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-alpha/socket.h b/include/asm-alpha/socket.h
index 08c97931992..a1057c2d95e 100644
--- a/include/asm-alpha/socket.h
+++ b/include/asm-alpha/socket.h
@@ -62,4 +62,9 @@
#define SO_MARK 36
+/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
+ * have to define SOCK_NONBLOCK to a different value here.
+ */
+#define SOCK_NONBLOCK 0x40000000
+
#endif /* _ASM_SOCKET_H */
diff --git a/include/asm-alpha/thread_info.h b/include/asm-alpha/thread_info.h
index fb318519629..15fda434442 100644
--- a/include/asm-alpha/thread_info.h
+++ b/include/asm-alpha/thread_info.h
@@ -50,10 +50,8 @@ register struct thread_info *__current_thread_info __asm__("$8");
#define current_thread_info() __current_thread_info
/* Thread information allocation. */
+#define THREAD_SIZE_ORDER 1
#define THREAD_SIZE (2*PAGE_SIZE)
-#define alloc_thread_info(tsk) \
- ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-arm/arch-iop13xx/adma.h b/include/asm-arm/arch-iop13xx/adma.h
index 90d14ee564f..ef4f5da2029 100644
--- a/include/asm-arm/arch-iop13xx/adma.h
+++ b/include/asm-arm/arch-iop13xx/adma.h
@@ -198,17 +198,13 @@ iop_chan_memset_slot_count(size_t len, int *slots_per_op)
static inline int
iop_chan_xor_slot_count(size_t len, int src_cnt, int *slots_per_op)
{
- int num_slots;
- /* slots_to_find = 1 for basic descriptor + 1 per 4 sources above 1
- * (1 source => 8 bytes) (1 slot => 32 bytes)
- */
- num_slots = 1 + (((src_cnt - 1) << 3) >> 5);
- if (((src_cnt - 1) << 3) & 0x1f)
- num_slots++;
-
- *slots_per_op = num_slots;
-
- return num_slots;
+ static const char slot_count_table[] = { 1, 2, 2, 2,
+ 2, 3, 3, 3,
+ 3, 4, 4, 4,
+ 4, 5, 5, 5,
+ };
+ *slots_per_op = slot_count_table[src_cnt - 1];
+ return *slots_per_op;
}
#define ADMA_MAX_BYTE_COUNT (16 * 1024 * 1024)
diff --git a/include/asm-arm/arch-pxa/cm-x270.h b/include/asm-arm/arch-pxa/cm-x270.h
deleted file mode 100644
index f8fac9e1800..00000000000
--- a/include/asm-arm/arch-pxa/cm-x270.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * linux/include/asm/arch-pxa/cm-x270.h
- *
- * Copyright Compulab Ltd., 2003, 2007
- * Mike Rapoport <mike@compulab.co.il>
- *
- * 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.
- */
-
-
-/* CM-x270 device physical addresses */
-#define CMX270_CS1_PHYS (PXA_CS1_PHYS)
-#define MARATHON_PHYS (PXA_CS2_PHYS)
-#define CMX270_IDE104_PHYS (PXA_CS3_PHYS)
-#define CMX270_IT8152_PHYS (PXA_CS4_PHYS)
-
-/* Statically mapped regions */
-#define CMX270_VIRT_BASE (0xe8000000)
-#define CMX270_IT8152_VIRT (CMX270_VIRT_BASE)
-#define CMX270_IDE104_VIRT (CMX270_IT8152_VIRT + SZ_64M)
-
-/* GPIO related definitions */
-#define GPIO_IT8152_IRQ (22)
-
-#define IRQ_GPIO_IT8152_IRQ IRQ_GPIO(GPIO_IT8152_IRQ)
-#define PME_IRQ IRQ_GPIO(0)
-#define CMX270_IDE_IRQ IRQ_GPIO(100)
-#define CMX270_GPIRQ1 IRQ_GPIO(101)
-#define CMX270_TOUCHIRQ IRQ_GPIO(96)
-#define CMX270_ETHIRQ IRQ_GPIO(10)
-#define CMX270_GFXIRQ IRQ_GPIO(95)
-#define CMX270_NANDIRQ IRQ_GPIO(89)
-#define CMX270_MMC_IRQ IRQ_GPIO(83)
-
-/* PCMCIA related definitions */
-#define PCC_DETECT(x) (GPLR(84 - (x)) & GPIO_bit(84 - (x)))
-#define PCC_READY(x) (GPLR(82 - (x)) & GPIO_bit(82 - (x)))
-
-#define PCMCIA_S0_CD_VALID IRQ_GPIO(84)
-#define PCMCIA_S0_CD_VALID_EDGE GPIO_BOTH_EDGES
-
-#define PCMCIA_S1_CD_VALID IRQ_GPIO(83)
-#define PCMCIA_S1_CD_VALID_EDGE GPIO_BOTH_EDGES
-
-#define PCMCIA_S0_RDYINT IRQ_GPIO(82)
-#define PCMCIA_S1_RDYINT IRQ_GPIO(81)
-
-#define PCMCIA_RESET_GPIO 53
diff --git a/include/asm-arm/arch-pxa/eseries-gpio.h b/include/asm-arm/arch-pxa/eseries-gpio.h
new file mode 100644
index 00000000000..4c90b131027
--- /dev/null
+++ b/include/asm-arm/arch-pxa/eseries-gpio.h
@@ -0,0 +1,50 @@
+/*
+ * eseries-gpio.h
+ *
+ * Copyright (C) Ian Molton <spyro@f2s.com>
+ *
+ * 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.
+ *
+ */
+
+/* e-series power button */
+#define GPIO_ESERIES_POWERBTN 0
+
+/* UDC GPIO definitions */
+#define GPIO_E7XX_USB_DISC 13
+#define GPIO_E7XX_USB_PULLUP 3
+
+#define GPIO_E800_USB_DISC 4
+#define GPIO_E800_USB_PULLUP 84
+
+/* e740 PCMCIA GPIO definitions */
+/* Note: PWR1 seems to be inverted */
+#define GPIO_E740_PCMCIA_CD0 8
+#define GPIO_E740_PCMCIA_CD1 44
+#define GPIO_E740_PCMCIA_RDY0 11
+#define GPIO_E740_PCMCIA_RDY1 6
+#define GPIO_E740_PCMCIA_RST0 27
+#define GPIO_E740_PCMCIA_RST1 24
+#define GPIO_E740_PCMCIA_PWR0 20
+#define GPIO_E740_PCMCIA_PWR1 23
+
+/* e750 PCMCIA GPIO definitions */
+#define GPIO_E750_PCMCIA_CD0 8
+#define GPIO_E750_PCMCIA_RDY0 12
+#define GPIO_E750_PCMCIA_RST0 27
+#define GPIO_E750_PCMCIA_PWR0 20
+
+/* e800 PCMCIA GPIO definitions */
+#define GPIO_E800_PCMCIA_RST0 69
+#define GPIO_E800_PCMCIA_RST1 72
+#define GPIO_E800_PCMCIA_PWR0 20
+#define GPIO_E800_PCMCIA_PWR1 73
+
+/* e7xx IrDA power control */
+#define GPIO_E7XX_IR_ON 38
+
+/* ASIC related GPIOs */
+#define GPIO_ESERIES_TMIO_IRQ 5
+#define GPIO_E800_ANGELX_IRQ 8
diff --git a/include/asm-arm/arch-pxa/eseries-irq.h b/include/asm-arm/arch-pxa/eseries-irq.h
new file mode 100644
index 00000000000..f2a93d5e31d
--- /dev/null
+++ b/include/asm-arm/arch-pxa/eseries-irq.h
@@ -0,0 +1,27 @@
+/*
+ * eseries-irq.h
+ *
+ * Copyright (C) Ian Molton <spyro@f2s.com>
+ *
+ * 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.
+ *
+ */
+
+#define ANGELX_IRQ_BASE (IRQ_BOARD_START+8)
+#define IRQ_ANGELX(n) (ANGELX_IRQ_BASE + (n))
+
+#define ANGELX_RDY0_IRQ IRQ_ANGELX(0)
+#define ANGELX_ST0_IRQ IRQ_ANGELX(1)
+#define ANGELX_CD0_IRQ IRQ_ANGELX(2)
+#define ANGELX_RDY1_IRQ IRQ_ANGELX(3)
+#define ANGELX_ST1_IRQ IRQ_ANGELX(4)
+#define ANGELX_CD1_IRQ IRQ_ANGELX(5)
+
+#define TMIO_IRQ_BASE (IRQ_BOARD_START+0)
+#define IRQ_TMIO(n) (TMIO_IRQ_BASE + (n))
+
+#define TMIO_SD_IRQ IRQ_TMIO(1)
+#define TMIO_USB_IRQ IRQ_TMIO(2)
+
diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h
index d9af6dabc89..979a45695d7 100644
--- a/include/asm-arm/arch-pxa/hardware.h
+++ b/include/asm-arm/arch-pxa/hardware.h
@@ -69,6 +69,12 @@
_id == 0x212; \
})
+#define __cpu_is_pxa255(id) \
+ ({ \
+ unsigned int _id = (id) >> 4 & 0xfff; \
+ _id == 0x2d0; \
+ })
+
#define __cpu_is_pxa25x(id) \
({ \
unsigned int _id = (id) >> 4 & 0xfff; \
@@ -76,6 +82,7 @@
})
#else
#define __cpu_is_pxa21x(id) (0)
+#define __cpu_is_pxa255(id) (0)
#define __cpu_is_pxa25x(id) (0)
#endif
@@ -119,11 +126,26 @@
#define __cpu_is_pxa320(id) (0)
#endif
+#ifdef CONFIG_CPU_PXA930
+#define __cpu_is_pxa930(id) \
+ ({ \
+ unsigned int _id = (id) >> 4 & 0xfff; \
+ _id == 0x683; \
+ })
+#else
+#define __cpu_is_pxa930(id) (0)
+#endif
+
#define cpu_is_pxa21x() \
({ \
__cpu_is_pxa21x(read_cpuid_id()); \
})
+#define cpu_is_pxa255() \
+ ({ \
+ __cpu_is_pxa255(read_cpuid_id()); \
+ })
+
#define cpu_is_pxa25x() \
({ \
__cpu_is_pxa25x(read_cpuid_id()); \
@@ -149,6 +171,12 @@
__cpu_is_pxa320(read_cpuid_id()); \
})
+#define cpu_is_pxa930() \
+ ({ \
+ unsigned int id = read_cpuid(CPUID_ID); \
+ __cpu_is_pxa930(id); \
+ })
+
/*
* CPUID Core Generation Bit
* <= 0x2 for pxa21x/pxa25x/pxa26x/pxa27x
@@ -196,6 +224,11 @@ extern void pxa_gpio_set_value(unsigned gpio, int value);
*/
extern unsigned int get_memclk_frequency_10khz(void);
+/*
+ * register GPIO as reset generator
+ */
+extern int init_gpio_reset(int gpio);
+
#endif
#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h
index b6c8fe37768..9413121b0ed 100644
--- a/include/asm-arm/arch-pxa/irqs.h
+++ b/include/asm-arm/arch-pxa/irqs.h
@@ -180,10 +180,13 @@
#define NR_IRQS (IRQ_LOCOMO_SPI_TEND + 1)
#elif defined(CONFIG_ARCH_LUBBOCK) || \
defined(CONFIG_MACH_LOGICPD_PXA270) || \
+ defined(CONFIG_MACH_TOSA) || \
defined(CONFIG_MACH_MAINSTONE) || \
defined(CONFIG_MACH_PCM027) || \
defined(CONFIG_MACH_MAGICIAN)
#define NR_IRQS (IRQ_BOARD_END)
+#elif defined(CONFIG_MACH_ZYLONITE)
+#define NR_IRQS (IRQ_BOARD_START + 32)
#else
#define NR_IRQS (IRQ_BOARD_START)
#endif
diff --git a/include/asm-arm/arch-pxa/mfp-pxa2xx.h b/include/asm-arm/arch-pxa/mfp-pxa2xx.h
index db8d890d237..8de1c0dae62 100644
--- a/include/asm-arm/arch-pxa/mfp-pxa2xx.h
+++ b/include/asm-arm/arch-pxa/mfp-pxa2xx.h
@@ -128,5 +128,6 @@
#define GPIO84_GPIO MFP_CFG_IN(GPIO84, AF0)
extern void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num);
+extern void pxa2xx_mfp_set_lpm(int mfp, unsigned long lpm);
extern int gpio_set_wake(unsigned int gpio, unsigned int on);
#endif /* __ASM_ARCH_MFP_PXA2XX_H */
diff --git a/include/asm-arm/arch-pxa/mfp-pxa930.h b/include/asm-arm/arch-pxa/mfp-pxa930.h
new file mode 100644
index 00000000000..c4e945ab192
--- /dev/null
+++ b/include/asm-arm/arch-pxa/mfp-pxa930.h
@@ -0,0 +1,491 @@
+/*
+ * linux/include/asm-arm/arch-pxa/mfp-pxa930.h
+ *
+ * PXA930 specific MFP configuration definitions
+ *
+ * Copyright (C) 2007-2008 Marvell International Ltd.
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_MFP_PXA9xx_H
+#define __ASM_ARCH_MFP_PXA9xx_H
+
+#include <asm/arch/mfp.h>
+#include <asm/arch/mfp-pxa3xx.h>
+
+/* GPIO */
+#define GPIO46_GPIO MFP_CFG(GPIO46, AF0)
+#define GPIO49_GPIO MFP_CFG(GPIO49, AF0)
+#define GPIO50_GPIO MFP_CFG(GPIO50, AF0)
+#define GPIO51_GPIO MFP_CFG(GPIO51, AF0)
+#define GPIO52_GPIO MFP_CFG(GPIO52, AF0)
+#define GPIO56_GPIO MFP_CFG(GPIO56, AF0)
+#define GPIO58_GPIO MFP_CFG(GPIO58, AF0)
+#define GPIO59_GPIO MFP_CFG(GPIO59, AF0)
+#define GPIO60_GPIO MFP_CFG(GPIO60, AF0)
+#define GPIO61_GPIO MFP_CFG(GPIO61, AF0)
+#define GPIO62_GPIO MFP_CFG(GPIO62, AF0)
+
+#define GSIM_UCLK_GPIO_79 MFP_CFG(GSIM_UCLK, AF0)
+#define GSIM_UIO_GPIO_80 MFP_CFG(GSIM_UIO, AF0)
+#define GSIM_nURST_GPIO_81 MFP_CFG(GSIM_nURST, AF0)
+#define GSIM_UDET_GPIO_82 MFP_CFG(GSIM_UDET, AF0)
+
+#define DF_IO15_GPIO_28 MFP_CFG(DF_IO15, AF0)
+#define DF_IO14_GPIO_29 MFP_CFG(DF_IO14, AF0)
+#define DF_IO13_GPIO_30 MFP_CFG(DF_IO13, AF0)
+#define DF_IO12_GPIO_31 MFP_CFG(DF_IO12, AF0)
+#define DF_IO11_GPIO_32 MFP_CFG(DF_IO11, AF0)
+#define DF_IO10_GPIO_33 MFP_CFG(DF_IO10, AF0)
+#define DF_IO9_GPIO_34 MFP_CFG(DF_IO9, AF0)
+#define DF_IO8_GPIO_35 MFP_CFG(DF_IO8, AF0)
+#define DF_IO7_GPIO_36 MFP_CFG(DF_IO7, AF0)
+#define DF_IO6_GPIO_37 MFP_CFG(DF_IO6, AF0)
+#define DF_IO5_GPIO_38 MFP_CFG(DF_IO5, AF0)
+#define DF_IO4_GPIO_39 MFP_CFG(DF_IO4, AF0)
+#define DF_IO3_GPIO_40 MFP_CFG(DF_IO3, AF0)
+#define DF_IO2_GPIO_41 MFP_CFG(DF_IO2, AF0)
+#define DF_IO1_GPIO_42 MFP_CFG(DF_IO1, AF0)
+#define DF_IO0_GPIO_43 MFP_CFG(DF_IO0, AF0)
+#define DF_nCS0_GPIO_44 MFP_CFG(DF_nCS0, AF0)
+#define DF_nCS1_GPIO_45 MFP_CFG(DF_nCS1, AF0)
+#define DF_nWE_GPIO_46 MFP_CFG(DF_nWE, AF0)
+#define DF_nRE_nOE_GPIO_47 MFP_CFG(DF_nRE_nOE, AF0)
+#define DF_CLE_nOE_GPIO_48 MFP_CFG(DF_CLE_nOE, AF0)
+#define DF_nADV1_ALE_GPIO_49 MFP_CFG(DF_nADV1_ALE, AF0)
+#define DF_nADV2_ALE_GPIO_50 MFP_CFG(DF_nADV2_ALE, AF0)
+#define DF_INT_RnB_GPIO_51 MFP_CFG(DF_INT_RnB, AF0)
+#define DF_SCLK_E_GPIO_52 MFP_CFG(DF_SCLK_E, AF0)
+
+#define DF_ADDR0_GPIO_53 MFP_CFG(DF_ADDR0, AF0)
+#define DF_ADDR1_GPIO_54 MFP_CFG(DF_ADDR1, AF0)
+#define DF_ADDR2_GPIO_55 MFP_CFG(DF_ADDR2, AF0)
+#define DF_ADDR3_GPIO_56 MFP_CFG(DF_ADDR3, AF0)
+#define nXCVREN_GPIO_57 MFP_CFG(nXCVREN, AF0)
+#define nLUA_GPIO_58 MFP_CFG(nLUA, AF0)
+#define nLLA_GPIO_59 MFP_CFG(nLLA, AF0)
+#define nBE0_GPIO_60 MFP_CFG(nBE0, AF0)
+#define nBE1_GPIO_61 MFP_CFG(nBE1, AF0)
+#define RDY_GPIO_62 MFP_CFG(RDY, AF0)
+
+/* Chip Select */
+#define DF_nCS0_nCS2 MFP_CFG_LPM(DF_nCS0, AF3, PULL_HIGH)
+#define DF_nCS1_nCS3 MFP_CFG_LPM(DF_nCS1, AF3, PULL_HIGH)
+
+/* AC97 */
+#define GPIO83_BAC97_SYSCLK MFP_CFG(GPIO83, AF3)
+#define GPIO84_BAC97_SDATA_IN0 MFP_CFG(GPIO84, AF3)
+#define GPIO85_BAC97_BITCLK MFP_CFG(GPIO85, AF3)
+#define GPIO86_BAC97_nRESET MFP_CFG(GPIO86, AF3)
+#define GPIO87_BAC97_SYNC MFP_CFG(GPIO87, AF3)
+#define GPIO88_BAC97_SDATA_OUT MFP_CFG(GPIO88, AF3)
+
+/* I2C */
+#define GPIO39_CI2C_SCL MFP_CFG_LPM(GPIO39, AF3, PULL_HIGH)
+#define GPIO40_CI2C_SDA MFP_CFG_LPM(GPIO40, AF3, PULL_HIGH)
+
+#define GPIO51_CI2C_SCL MFP_CFG_LPM(GPIO51, AF3, PULL_HIGH)
+#define GPIO52_CI2C_SDA MFP_CFG_LPM(GPIO52, AF3, PULL_HIGH)
+
+#define GPIO63_CI2C_SCL MFP_CFG_LPM(GPIO63, AF4, PULL_HIGH)
+#define GPIO64_CI2C_SDA MFP_CFG_LPM(GPIO64, AF4, PULL_HIGH)
+
+#define GPIO77_CI2C_SCL MFP_CFG_LPM(GPIO77, AF2, PULL_HIGH)
+#define GPIO78_CI2C_SDA MFP_CFG_LPM(GPIO78, AF2, PULL_HIGH)
+
+#define GPIO89_CI2C_SCL MFP_CFG_LPM(GPIO89, AF1, PULL_HIGH)
+#define GPIO90_CI2C_SDA MFP_CFG_LPM(GPIO90, AF1, PULL_HIGH)
+
+#define GPIO95_CI2C_SCL MFP_CFG_LPM(GPIO95, AF1, PULL_HIGH)
+#define GPIO96_CI2C_SDA MFP_CFG_LPM(GPIO96, AF1, PULL_HIGH)
+
+#define GPIO97_CI2C_SCL MFP_CFG_LPM(GPIO97, AF3, PULL_HIGH)
+#define GPIO98_CI2C_SDA MFP_CFG_LPM(GPIO98, AF3, PULL_HIGH)
+
+/* QCI */
+#define GPIO63_CI_DD_9 MFP_CFG_LPM(GPIO63, AF1, PULL_LOW)
+#define GPIO64_CI_DD_8 MFP_CFG_LPM(GPIO64, AF1, PULL_LOW)
+#define GPIO65_CI_DD_7 MFP_CFG_LPM(GPIO65, AF1, PULL_LOW)
+#define GPIO66_CI_DD_6 MFP_CFG_LPM(GPIO66, AF1, PULL_LOW)
+#define GPIO67_CI_DD_5 MFP_CFG_LPM(GPIO67, AF1, PULL_LOW)
+#define GPIO68_CI_DD_4 MFP_CFG_LPM(GPIO68, AF1, PULL_LOW)
+#define GPIO69_CI_DD_3 MFP_CFG_LPM(GPIO69, AF1, PULL_LOW)
+#define GPIO70_CI_DD_2 MFP_CFG_LPM(GPIO70, AF1, PULL_LOW)
+#define GPIO71_CI_DD_1 MFP_CFG_LPM(GPIO71, AF1, PULL_LOW)
+#define GPIO72_CI_DD_0 MFP_CFG_LPM(GPIO72, AF1, PULL_LOW)
+#define GPIO73_CI_HSYNC MFP_CFG_LPM(GPIO73, AF1, PULL_LOW)
+#define GPIO74_CI_VSYNC MFP_CFG_LPM(GPIO74, AF1, PULL_LOW)
+#define GPIO75_CI_MCLK MFP_CFG_LPM(GPIO75, AF1, PULL_LOW)
+#define GPIO76_CI_PCLK MFP_CFG_LPM(GPIO76, AF1, PULL_LOW)
+
+/* KEYPAD */
+#define GPIO4_KP_DKIN_4 MFP_CFG_LPM(GPIO4, AF3, FLOAT)
+#define GPIO5_KP_DKIN_5 MFP_CFG_LPM(GPIO5, AF3, FLOAT)
+#define GPIO6_KP_DKIN_6 MFP_CFG_LPM(GPIO6, AF3, FLOAT)
+#define GPIO7_KP_DKIN_7 MFP_CFG_LPM(GPIO7, AF3, FLOAT)
+#define GPIO8_KP_DKIN_4 MFP_CFG_LPM(GPIO8, AF3, FLOAT)
+#define GPIO9_KP_DKIN_5 MFP_CFG_LPM(GPIO9, AF3, FLOAT)
+#define GPIO10_KP_DKIN_6 MFP_CFG_LPM(GPIO10, AF3, FLOAT)
+#define GPIO11_KP_DKIN_7 MFP_CFG_LPM(GPIO11, AF3, FLOAT)
+
+#define GPIO12_KP_DKIN_0 MFP_CFG_LPM(GPIO12, AF2, FLOAT)
+#define GPIO13_KP_DKIN_1 MFP_CFG_LPM(GPIO13, AF2, FLOAT)
+#define GPIO14_KP_DKIN_2 MFP_CFG_LPM(GPIO14, AF2, FLOAT)
+#define GPIO15_KP_DKIN_3 MFP_CFG_LPM(GPIO15, AF2, FLOAT)
+
+#define GPIO41_KP_DKIN_0 MFP_CFG_LPM(GPIO41, AF2, FLOAT)
+#define GPIO42_KP_DKIN_1 MFP_CFG_LPM(GPIO42, AF2, FLOAT)
+#define GPIO43_KP_DKIN_2 MFP_CFG_LPM(GPIO43, AF2, FLOAT)
+#define GPIO44_KP_DKIN_3 MFP_CFG_LPM(GPIO44, AF2, FLOAT)
+#define GPIO41_KP_DKIN_4 MFP_CFG_LPM(GPIO41, AF4, FLOAT)
+#define GPIO42_KP_DKIN_5 MFP_CFG_LPM(GPIO42, AF4, FLOAT)
+
+#define GPIO0_KP_MKIN_0 MFP_CFG_LPM(GPIO0, AF1, FLOAT)
+#define GPIO2_KP_MKIN_1 MFP_CFG_LPM(GPIO2, AF1, FLOAT)
+#define GPIO4_KP_MKIN_2 MFP_CFG_LPM(GPIO4, AF1, FLOAT)
+#define GPIO6_KP_MKIN_3 MFP_CFG_LPM(GPIO6, AF1, FLOAT)
+#define GPIO8_KP_MKIN_4 MFP_CFG_LPM(GPIO8, AF1, FLOAT)
+#define GPIO10_KP_MKIN_5 MFP_CFG_LPM(GPIO10, AF1, FLOAT)
+#define GPIO12_KP_MKIN_6 MFP_CFG_LPM(GPIO12, AF1, FLOAT)
+#define GPIO14_KP_MKIN_7 MFP_CFG(GPIO14, AF1)
+#define GPIO35_KP_MKIN_5 MFP_CFG(GPIO35, AF4)
+
+#define GPIO1_KP_MKOUT_0 MFP_CFG_LPM(GPIO1, AF1, DRIVE_HIGH)
+#define GPIO3_KP_MKOUT_1 MFP_CFG_LPM(GPIO3, AF1, DRIVE_HIGH)
+#define GPIO5_KP_MKOUT_2 MFP_CFG_LPM(GPIO5, AF1, DRIVE_HIGH)
+#define GPIO7_KP_MKOUT_3 MFP_CFG_LPM(GPIO7, AF1, DRIVE_HIGH)
+#define GPIO9_KP_MKOUT_4 MFP_CFG_LPM(GPIO9, AF1, DRIVE_HIGH)
+#define GPIO11_KP_MKOUT_5 MFP_CFG_LPM(GPIO11, AF1, DRIVE_HIGH)
+#define GPIO13_KP_MKOUT_6 MFP_CFG_LPM(GPIO13, AF1, DRIVE_HIGH)
+#define GPIO15_KP_MKOUT_7 MFP_CFG_LPM(GPIO15, AF1, DRIVE_HIGH)
+#define GPIO36_KP_MKOUT_5 MFP_CFG_LPM(GPIO36, AF4, DRIVE_HIGH)
+
+/* LCD */
+#define GPIO17_LCD_FCLK_RD MFP_CFG(GPIO17, AF1)
+#define GPIO18_LCD_LCLK_A0 MFP_CFG(GPIO18, AF1)
+#define GPIO19_LCD_PCLK_WR MFP_CFG(GPIO19, AF1)
+#define GPIO20_LCD_BIAS MFP_CFG(GPIO20, AF1)
+#define GPIO21_LCD_CS MFP_CFG(GPIO21, AF1)
+#define GPIO22_LCD_CS2 MFP_CFG(GPIO22, AF2)
+#define GPIO22_LCD_VSYNC MFP_CFG(GPIO22, AF1)
+#define GPIO23_LCD_DD0 MFP_CFG(GPIO23, AF1)
+#define GPIO24_LCD_DD1 MFP_CFG(GPIO24, AF1)
+#define GPIO25_LCD_DD2 MFP_CFG(GPIO25, AF1)
+#define GPIO26_LCD_DD3 MFP_CFG(GPIO26, AF1)
+#define GPIO27_LCD_DD4 MFP_CFG(GPIO27, AF1)
+#define GPIO28_LCD_DD5 MFP_CFG(GPIO28, AF1)
+#define GPIO29_LCD_DD6 MFP_CFG(GPIO29, AF1)
+#define GPIO30_LCD_DD7 MFP_CFG(GPIO30, AF1)
+#define GPIO31_LCD_DD8 MFP_CFG(GPIO31, AF1)
+#define GPIO32_LCD_DD9 MFP_CFG(GPIO32, AF1)
+#define GPIO33_LCD_DD10 MFP_CFG(GPIO33, AF1)
+#define GPIO34_LCD_DD11 MFP_CFG(GPIO34, AF1)
+#define GPIO35_LCD_DD12 MFP_CFG(GPIO35, AF1)
+#define GPIO36_LCD_DD13 MFP_CFG(GPIO36, AF1)
+#define GPIO37_LCD_DD14 MFP_CFG(GPIO37, AF1)
+#define GPIO38_LCD_DD15 MFP_CFG(GPIO38, AF1)
+#define GPIO39_LCD_DD16 MFP_CFG(GPIO39, AF1)
+#define GPIO40_LCD_DD17 MFP_CFG(GPIO40, AF1)
+#define GPIO41_LCD_CS2 MFP_CFG(GPIO41, AF3)
+#define GPIO42_LCD_VSYNC2 MFP_CFG(GPIO42, AF3)
+#define GPIO44_LCD_DD7 MFP_CFG(GPIO44, AF1)
+
+/* Mini-LCD */
+#define GPIO17_MLCD_FCLK MFP_CFG(GPIO17, AF3)
+#define GPIO18_MLCD_LCLK MFP_CFG(GPIO18, AF3)
+#define GPIO19_MLCD_PCLK MFP_CFG(GPIO19, AF3)
+#define GPIO20_MLCD_BIAS MFP_CFG(GPIO20, AF3)
+#define GPIO23_MLCD_DD0 MFP_CFG(GPIO23, AF3)
+#define GPIO24_MLCD_DD1 MFP_CFG(GPIO24, AF3)
+#define GPIO25_MLCD_DD2 MFP_CFG(GPIO25, AF3)
+#define GPIO26_MLCD_DD3 MFP_CFG(GPIO26, AF3)
+#define GPIO27_MLCD_DD4 MFP_CFG(GPIO27, AF3)
+#define GPIO28_MLCD_DD5 MFP_CFG(GPIO28, AF3)
+#define GPIO29_MLCD_DD6 MFP_CFG(GPIO29, AF3)
+#define GPIO30_MLCD_DD7 MFP_CFG(GPIO30, AF3)
+#define GPIO31_MLCD_DD8 MFP_CFG(GPIO31, AF3)
+#define GPIO32_MLCD_DD9 MFP_CFG(GPIO32, AF3)
+#define GPIO33_MLCD_DD10 MFP_CFG(GPIO33, AF3)
+#define GPIO34_MLCD_DD11 MFP_CFG(GPIO34, AF3)
+#define GPIO35_MLCD_DD12 MFP_CFG(GPIO35, AF3)
+#define GPIO36_MLCD_DD13 MFP_CFG(GPIO36, AF3)
+#define GPIO37_MLCD_DD14 MFP_CFG(GPIO37, AF3)
+#define GPIO38_MLCD_DD15 MFP_CFG(GPIO38, AF3)
+#define GPIO44_MLCD_DD7 MFP_CFG(GPIO44, AF5)
+
+/* MMC1 */
+#define GPIO10_MMC1_DAT3 MFP_CFG(GPIO10, AF4)
+#define GPIO11_MMC1_DAT2 MFP_CFG(GPIO11, AF4)
+#define GPIO12_MMC1_DAT1 MFP_CFG(GPIO12, AF4)
+#define GPIO13_MMC1_DAT0 MFP_CFG(GPIO13, AF4)
+#define GPIO14_MMC1_CMD MFP_CFG(GPIO14, AF4)
+#define GPIO15_MMC1_CLK MFP_CFG(GPIO15, AF4)
+#define GPIO55_MMC1_CMD MFP_CFG(GPIO55, AF3)
+#define GPIO56_MMC1_CLK MFP_CFG(GPIO56, AF3)
+#define GPIO57_MMC1_DAT0 MFP_CFG(GPIO57, AF3)
+#define GPIO58_MMC1_DAT1 MFP_CFG(GPIO58, AF3)
+#define GPIO59_MMC1_DAT2 MFP_CFG(GPIO59, AF3)
+#define GPIO60_MMC1_DAT3 MFP_CFG(GPIO60, AF3)
+
+#define DF_ADDR0_MMC1_CLK MFP_CFG(DF_ADDR0, AF2)
+#define DF_ADDR1_MMC1_CMD MFP_CFG(DF_ADDR1, AF2)
+#define DF_ADDR2_MMC1_DAT0 MFP_CFG(DF_ADDR2, AF2)
+#define DF_ADDR3_MMC1_DAT1 MFP_CFG(DF_ADDR3, AF3)
+#define nXCVREN_MMC1_DAT2 MFP_CFG(nXCVREN, AF2)
+
+/* MMC2 */
+#define GPIO31_MMC2_CMD MFP_CFG(GPIO31, AF7)
+#define GPIO32_MMC2_CLK MFP_CFG(GPIO32, AF7)
+#define GPIO33_MMC2_DAT0 MFP_CFG(GPIO33, AF7)
+#define GPIO34_MMC2_DAT1 MFP_CFG(GPIO34, AF7)
+#define GPIO35_MMC2_DAT2 MFP_CFG(GPIO35, AF7)
+#define GPIO36_MMC2_DAT3 MFP_CFG(GPIO36, AF7)
+
+#define GPIO101_MMC2_DAT3 MFP_CFG(GPIO101, AF1)
+#define GPIO102_MMC2_DAT2 MFP_CFG(GPIO102, AF1)
+#define GPIO103_MMC2_DAT1 MFP_CFG(GPIO103, AF1)
+#define GPIO104_MMC2_DAT0 MFP_CFG(GPIO104, AF1)
+#define GPIO105_MMC2_CMD MFP_CFG(GPIO105, AF1)
+#define GPIO106_MMC2_CLK MFP_CFG(GPIO106, AF1)
+
+#define DF_IO10_MMC2_DAT3 MFP_CFG(DF_IO10, AF3)
+#define DF_IO11_MMC2_DAT2 MFP_CFG(DF_IO11, AF3)
+#define DF_IO12_MMC2_DAT1 MFP_CFG(DF_IO12, AF3)
+#define DF_IO13_MMC2_DAT0 MFP_CFG(DF_IO13, AF3)
+#define DF_IO14_MMC2_CLK MFP_CFG(DF_IO14, AF3)
+#define DF_IO15_MMC2_CMD MFP_CFG(DF_IO15, AF3)
+
+/* BSSP1 */
+#define GPIO12_BSSP1_CLK MFP_CFG(GPIO12, AF3)
+#define GPIO13_BSSP1_FRM MFP_CFG(GPIO13, AF3)
+#define GPIO14_BSSP1_RXD MFP_CFG(GPIO14, AF3)
+#define GPIO15_BSSP1_TXD MFP_CFG(GPIO15, AF3)
+#define GPIO97_BSSP1_CLK MFP_CFG(GPIO97, AF5)
+#define GPIO98_BSSP1_FRM MFP_CFG(GPIO98, AF5)
+
+/* BSSP2 */
+#define GPIO84_BSSP2_SDATA_IN MFP_CFG(GPIO84, AF1)
+#define GPIO85_BSSP2_BITCLK MFP_CFG(GPIO85, AF1)
+#define GPIO86_BSSP2_SYSCLK MFP_CFG(GPIO86, AF1)
+#define GPIO87_BSSP2_SYNC MFP_CFG(GPIO87, AF1)
+#define GPIO88_BSSP2_DATA_OUT MFP_CFG(GPIO88, AF1)
+#define GPIO86_BSSP2_SDATA_IN MFP_CFG(GPIO86, AF4)
+
+/* BSSP3 */
+#define GPIO79_BSSP3_CLK MFP_CFG(GPIO79, AF1)
+#define GPIO80_BSSP3_FRM MFP_CFG(GPIO80, AF1)
+#define GPIO81_BSSP3_TXD MFP_CFG(GPIO81, AF1)
+#define GPIO82_BSSP3_RXD MFP_CFG(GPIO82, AF1)
+#define GPIO83_BSSP3_SYSCLK MFP_CFG(GPIO83, AF1)
+
+/* BSSP4 */
+#define GPIO43_BSSP4_CLK MFP_CFG(GPIO43, AF4)
+#define GPIO44_BSSP4_FRM MFP_CFG(GPIO44, AF4)
+#define GPIO45_BSSP4_TXD MFP_CFG(GPIO45, AF4)
+#define GPIO46_BSSP4_RXD MFP_CFG(GPIO46, AF4)
+
+#define GPIO51_BSSP4_CLK MFP_CFG(GPIO51, AF4)
+#define GPIO52_BSSP4_FRM MFP_CFG(GPIO52, AF4)
+#define GPIO53_BSSP4_TXD MFP_CFG(GPIO53, AF4)
+#define GPIO54_BSSP4_RXD MFP_CFG(GPIO54, AF4)
+
+/* GSSP1 */
+#define GPIO79_GSSP1_CLK MFP_CFG(GPIO79, AF2)
+#define GPIO80_GSSP1_FRM MFP_CFG(GPIO80, AF2)
+#define GPIO81_GSSP1_TXD MFP_CFG(GPIO81, AF2)
+#define GPIO82_GSSP1_RXD MFP_CFG(GPIO82, AF2)
+#define GPIO83_GSSP1_SYSCLK MFP_CFG(GPIO83, AF2)
+
+#define GPIO93_GSSP1_CLK MFP_CFG(GPIO93, AF4)
+#define GPIO94_GSSP1_FRM MFP_CFG(GPIO94, AF4)
+#define GPIO95_GSSP1_TXD MFP_CFG(GPIO95, AF4)
+#define GPIO96_GSSP1_RXD MFP_CFG(GPIO96, AF4)
+
+/* GSSP2 */
+#define GPIO47_GSSP2_CLK MFP_CFG(GPIO47, AF4)
+#define GPIO48_GSSP2_FRM MFP_CFG(GPIO48, AF4)
+#define GPIO49_GSSP2_RXD MFP_CFG(GPIO49, AF4)
+#define GPIO50_GSSP2_TXD MFP_CFG(GPIO50, AF4)
+
+#define GPIO69_GSSP2_CLK MFP_CFG(GPIO69, AF4)
+#define GPIO70_GSSP2_FRM MFP_CFG(GPIO70, AF4)
+#define GPIO71_GSSP2_RXD MFP_CFG(GPIO71, AF4)
+#define GPIO72_GSSP2_TXD MFP_CFG(GPIO72, AF4)
+
+#define GPIO84_GSSP2_RXD MFP_CFG(GPIO84, AF2)
+#define GPIO85_GSSP2_CLK MFP_CFG(GPIO85, AF2)
+#define GPIO86_GSSP2_SYSCLK MFP_CFG(GPIO86, AF2)
+#define GPIO87_GSSP2_FRM MFP_CFG(GPIO87, AF2)
+#define GPIO88_GSSP2_TXD MFP_CFG(GPIO88, AF2)
+#define GPIO86_GSSP2_RXD MFP_CFG(GPIO86, AF5)
+
+#define GPIO103_GSSP2_CLK MFP_CFG(GPIO103, AF2)
+#define GPIO104_GSSP2_FRM MFP_CFG(GPIO104, AF2)
+#define GPIO105_GSSP2_RXD MFP_CFG(GPIO105, AF2)
+#define GPIO106_GSSP2_TXD MFP_CFG(GPIO106, AF2)
+
+/* UART1 - FFUART */
+#define GPIO47_UART1_DSR_N MFP_CFG(GPIO47, AF1)
+#define GPIO48_UART1_DTR_N MFP_CFG(GPIO48, AF1)
+#define GPIO49_UART1_RI MFP_CFG(GPIO49, AF1)
+#define GPIO50_UART1_DCD MFP_CFG(GPIO50, AF1)
+#define GPIO51_UART1_CTS MFP_CFG(GPIO51, AF1)
+#define GPIO52_UART1_RTS MFP_CFG(GPIO52, AF1)
+#define GPIO53_UART1_RXD MFP_CFG(GPIO53, AF1)
+#define GPIO54_UART1_TXD MFP_CFG(GPIO54, AF1)
+
+#define GPIO63_UART1_TXD MFP_CFG(GPIO63, AF2)
+#define GPIO64_UART1_RXD MFP_CFG(GPIO64, AF2)
+#define GPIO65_UART1_DSR MFP_CFG(GPIO65, AF2)
+#define GPIO66_UART1_DTR MFP_CFG(GPIO66, AF2)
+#define GPIO67_UART1_RI MFP_CFG(GPIO67, AF2)
+#define GPIO68_UART1_DCD MFP_CFG(GPIO68, AF2)
+#define GPIO69_UART1_CTS MFP_CFG(GPIO69, AF2)
+#define GPIO70_UART1_RTS MFP_CFG(GPIO70, AF2)
+
+/* UART2 - BTUART */
+#define GPIO91_UART2_RXD MFP_CFG(GPIO91, AF1)
+#define GPIO92_UART2_TXD MFP_CFG(GPIO92, AF1)
+#define GPIO93_UART2_CTS MFP_CFG(GPIO93, AF1)
+#define GPIO94_UART2_RTS MFP_CFG(GPIO94, AF1)
+
+/* UART3 - STUART */
+#define GPIO43_UART3_RTS MFP_CFG(GPIO43, AF3)
+#define GPIO44_UART3_CTS MFP_CFG(GPIO44, AF3)
+#define GPIO45_UART3_RXD MFP_CFG(GPIO45, AF3)
+#define GPIO46_UART3_TXD MFP_CFG(GPIO46, AF3)
+
+#define GPIO75_UART3_RTS MFP_CFG(GPIO75, AF5)
+#define GPIO76_UART3_CTS MFP_CFG(GPIO76, AF5)
+#define GPIO77_UART3_TXD MFP_CFG(GPIO77, AF5)
+#define GPIO78_UART3_RXD MFP_CFG(GPIO78, AF5)
+
+/* DFI */
+#define DF_IO0_DF_IO0 MFP_CFG(DF_IO0, AF2)
+#define DF_IO1_DF_IO1 MFP_CFG(DF_IO1, AF2)
+#define DF_IO2_DF_IO2 MFP_CFG(DF_IO2, AF2)
+#define DF_IO3_DF_IO3 MFP_CFG(DF_IO3, AF2)
+#define DF_IO4_DF_IO4 MFP_CFG(DF_IO4, AF2)
+#define DF_IO5_DF_IO5 MFP_CFG(DF_IO5, AF2)
+#define DF_IO6_DF_IO6 MFP_CFG(DF_IO6, AF2)
+#define DF_IO7_DF_IO7 MFP_CFG(DF_IO7, AF2)
+#define DF_IO8_DF_IO8 MFP_CFG(DF_IO8, AF2)
+#define DF_IO9_DF_IO9 MFP_CFG(DF_IO9, AF2)
+#define DF_IO10_DF_IO10 MFP_CFG(DF_IO10, AF2)
+#define DF_IO11_DF_IO11 MFP_CFG(DF_IO11, AF2)
+#define DF_IO12_DF_IO12 MFP_CFG(DF_IO12, AF2)
+#define DF_IO13_DF_IO13 MFP_CFG(DF_IO13, AF2)
+#define DF_IO14_DF_IO14 MFP_CFG(DF_IO14, AF2)
+#define DF_IO15_DF_IO15 MFP_CFG(DF_IO15, AF2)
+#define DF_nADV1_ALE_DF_nADV1 MFP_CFG(DF_nADV1_ALE, AF2)
+#define DF_nADV2_ALE_DF_nADV2 MFP_CFG(DF_nADV2_ALE, AF2)
+#define DF_nCS0_DF_nCS0 MFP_CFG(DF_nCS0, AF2)
+#define DF_nCS1_DF_nCS1 MFP_CFG(DF_nCS1, AF2)
+#define DF_nRE_nOE_DF_nOE MFP_CFG(DF_nRE_nOE, AF2)
+#define DF_nWE_DF_nWE MFP_CFG(DF_nWE, AF2)
+
+/* DFI - NAND */
+#define DF_CLE_nOE_ND_CLE MFP_CFG_LPM(DF_CLE_nOE, AF1, PULL_HIGH)
+#define DF_INT_RnB_ND_INT_RnB MFP_CFG_LPM(DF_INT_RnB, AF1, PULL_LOW)
+#define DF_IO0_ND_IO0 MFP_CFG_LPM(DF_IO0, AF1, PULL_LOW)
+#define DF_IO1_ND_IO1 MFP_CFG_LPM(DF_IO1, AF1, PULL_LOW)
+#define DF_IO2_ND_IO2 MFP_CFG_LPM(DF_IO2, AF1, PULL_LOW)
+#define DF_IO3_ND_IO3 MFP_CFG_LPM(DF_IO3, AF1, PULL_LOW)
+#define DF_IO4_ND_IO4 MFP_CFG_LPM(DF_IO4, AF1, PULL_LOW)
+#define DF_IO5_ND_IO5 MFP_CFG_LPM(DF_IO5, AF1, PULL_LOW)
+#define DF_IO6_ND_IO6 MFP_CFG_LPM(DF_IO6, AF1, PULL_LOW)
+#define DF_IO7_ND_IO7 MFP_CFG_LPM(DF_IO7, AF1, PULL_LOW)
+#define DF_IO8_ND_IO8 MFP_CFG_LPM(DF_IO8, AF1, PULL_LOW)
+#define DF_IO9_ND_IO9 MFP_CFG_LPM(DF_IO9, AF1, PULL_LOW)
+#define DF_IO10_ND_IO10 MFP_CFG_LPM(DF_IO10, AF1, PULL_LOW)
+#define DF_IO11_ND_IO11 MFP_CFG_LPM(DF_IO11, AF1, PULL_LOW)
+#define DF_IO12_ND_IO12 MFP_CFG_LPM(DF_IO12, AF1, PULL_LOW)
+#define DF_IO13_ND_IO13 MFP_CFG_LPM(DF_IO13, AF1, PULL_LOW)
+#define DF_IO14_ND_IO14 MFP_CFG_LPM(DF_IO14, AF1, PULL_LOW)
+#define DF_IO15_ND_IO15 MFP_CFG_LPM(DF_IO15, AF1, PULL_LOW)
+#define DF_nADV1_ALE_ND_ALE MFP_CFG_LPM(DF_nADV1_ALE, AF1, PULL_HIGH)
+#define DF_nADV2_ALE_ND_ALE MFP_CFG_LPM(DF_nADV2_ALE, AF1, PULL_HIGH)
+#define DF_nADV2_ALE_nCS3 MFP_CFG_LPM(DF_nADV2_ALE, AF3, PULL_HIGH)
+#define DF_nCS0_ND_nCS0 MFP_CFG_LPM(DF_nCS0, AF1, PULL_HIGH)
+#define DF_nCS1_ND_nCS1 MFP_CFG_LPM(DF_nCS1, AF1, PULL_HIGH)
+#define DF_nRE_nOE_ND_nRE MFP_CFG_LPM(DF_nRE_nOE, AF1, PULL_HIGH)
+#define DF_nWE_ND_nWE MFP_CFG_LPM(DF_nWE, AF1, PULL_HIGH)
+
+/* PWM */
+#define GPIO41_PWM0 MFP_CFG_LPM(GPIO41, AF1, PULL_LOW)
+#define GPIO42_PWM1 MFP_CFG_LPM(GPIO42, AF1, PULL_LOW)
+#define GPIO43_PWM3 MFP_CFG_LPM(GPIO43, AF1, PULL_LOW)
+#define GPIO20_PWM0 MFP_CFG_LPM(GPIO20, AF2, PULL_LOW)
+#define GPIO21_PWM2 MFP_CFG_LPM(GPIO21, AF3, PULL_LOW)
+#define GPIO22_PWM3 MFP_CFG_LPM(GPIO22, AF3, PULL_LOW)
+
+/* CIR */
+#define GPIO46_CIR_OUT MFP_CFG(GPIO46, AF1)
+#define GPIO77_CIR_OUT MFP_CFG(GPIO77, AF3)
+
+/* USB P2 */
+#define GPIO0_USB_P2_7 MFP_CFG(GPIO0, AF3)
+#define GPIO15_USB_P2_7 MFP_CFG(GPIO15, AF5)
+#define GPIO16_USB_P2_7 MFP_CFG(GPIO16, AF2)
+#define GPIO48_USB_P2_7 MFP_CFG(GPIO48, AF7)
+#define GPIO49_USB_P2_7 MFP_CFG(GPIO49, AF6)
+#define DF_IO9_USB_P2_7 MFP_CFG(DF_IO9, AF3)
+
+#define GPIO48_USB_P2_8 MFP_CFG(GPIO48, AF2)
+#define GPIO50_USB_P2_7 MFP_CFG_X(GPIO50, AF2, DS02X, FLOAT)
+#define GPIO51_USB_P2_5 MFP_CFG(GPIO51, AF2)
+#define GPIO47_USB_P2_4 MFP_CFG(GPIO47, AF2)
+#define GPIO53_USB_P2_3 MFP_CFG(GPIO53, AF2)
+#define GPIO54_USB_P2_6 MFP_CFG(GPIO54, AF2)
+#define GPIO49_USB_P2_2 MFP_CFG(GPIO49, AF2)
+#define GPIO52_USB_P2_1 MFP_CFG(GPIO52, AF2)
+
+#define GPIO63_USB_P2_8 MFP_CFG(GPIO63, AF3)
+#define GPIO64_USB_P2_7 MFP_CFG(GPIO64, AF3)
+#define GPIO65_USB_P2_6 MFP_CFG(GPIO65, AF3)
+#define GPIO66_USG_P2_5 MFP_CFG(GPIO66, AF3)
+#define GPIO67_USB_P2_4 MFP_CFG(GPIO67, AF3)
+#define GPIO68_USB_P2_3 MFP_CFG(GPIO68, AF3)
+#define GPIO69_USB_P2_2 MFP_CFG(GPIO69, AF3)
+#define GPIO70_USB_P2_1 MFP_CFG(GPIO70, AF3)
+
+/* ULPI */
+#define GPIO31_USB_ULPI_D0 MFP_CFG(GPIO31, AF4)
+#define GPIO30_USB_ULPI_D1 MFP_CFG(GPIO30, AF7)
+#define GPIO33_USB_ULPI_D2 MFP_CFG(GPIO33, AF5)
+#define GPIO34_USB_ULPI_D3 MFP_CFG(GPIO34, AF5)
+#define GPIO35_USB_ULPI_D4 MFP_CFG(GPIO35, AF5)
+#define GPIO36_USB_ULPI_D5 MFP_CFG(GPIO36, AF5)
+#define GPIO41_USB_ULPI_D6 MFP_CFG(GPIO41, AF5)
+#define GPIO42_USB_ULPI_D7 MFP_CFG(GPIO42, AF5)
+#define GPIO37_USB_ULPI_DIR MFP_CFG(GPIO37, AF4)
+#define GPIO38_USB_ULPI_CLK MFP_CFG(GPIO38, AF4)
+#define GPIO39_USB_ULPI_STP MFP_CFG(GPIO39, AF4)
+#define GPIO40_USB_ULPI_NXT MFP_CFG(GPIO40, AF4)
+
+#define GPIO3_CLK26MOUTDMD MFP_CFG(GPIO3, AF3)
+#define GPIO40_CLK26MOUTDMD MFP_CFG(GPIO40, AF7)
+#define GPIO94_CLK26MOUTDMD MFP_CFG(GPIO94, AF5)
+#define GPIO104_CLK26MOUTDMD MFP_CFG(GPIO104, AF4)
+#define DF_ADDR1_CLK26MOUTDMD MFP_CFG(DF_ADDR2, AF3)
+#define DF_ADDR3_CLK26MOUTDMD MFP_CFG(DF_ADDR3, AF3)
+
+#define GPIO14_CLK26MOUT MFP_CFG(GPIO14, AF5)
+#define GPIO38_CLK26MOUT MFP_CFG(GPIO38, AF7)
+#define GPIO92_CLK26MOUT MFP_CFG(GPIO92, AF5)
+#define GPIO105_CLK26MOUT MFP_CFG(GPIO105, AF4)
+
+#define GPIO2_CLK13MOUTDMD MFP_CFG(GPIO2, AF3)
+#define GPIO39_CLK13MOUTDMD MFP_CFG(GPIO39, AF7)
+#define GPIO50_CLK13MOUTDMD MFP_CFG(GPIO50, AF3)
+#define GPIO93_CLK13MOUTDMD MFP_CFG(GPIO93, AF5)
+#define GPIO103_CLK13MOUTDMD MFP_CFG(GPIO103, AF4)
+#define DF_ADDR2_CLK13MOUTDMD MFP_CFG(DF_ADDR2, AF3)
+
+/* 1 wire */
+#define GPIO95_OW_DQ_IN MFP_CFG(GPIO95, AF5)
+
+#endif /* __ASM_ARCH_MFP_PXA9xx_H */
diff --git a/include/asm-arm/arch-pxa/mfp.h b/include/asm-arm/arch-pxa/mfp.h
index 02f6157396d..e7d58798da6 100644
--- a/include/asm-arm/arch-pxa/mfp.h
+++ b/include/asm-arm/arch-pxa/mfp.h
@@ -210,6 +210,14 @@ enum {
MFP_PIN_DF_IO14,
MFP_PIN_DF_IO15,
+ /* additional pins on PXA930 */
+ MFP_PIN_GSIM_UIO,
+ MFP_PIN_GSIM_UCLK,
+ MFP_PIN_GSIM_UDET,
+ MFP_PIN_GSIM_nURST,
+ MFP_PIN_PMIC_INT,
+ MFP_PIN_RDY,
+
MFP_PIN_MAX,
};
diff --git a/include/asm-arm/arch-pxa/palmtx.h b/include/asm-arm/arch-pxa/palmtx.h
new file mode 100644
index 00000000000..1e8bccbda51
--- /dev/null
+++ b/include/asm-arm/arch-pxa/palmtx.h
@@ -0,0 +1,106 @@
+/*
+ * GPIOs and interrupts for Palm T|X Handheld Computer
+ *
+ * Based on palmld-gpio.h by Alex Osborne
+ *
+ * Authors: Marek Vasut <marek.vasut@gmail.com>
+ * Cristiano P. <cristianop@users.sourceforge.net>
+ * Jan Herman <2hp@seznam.cz>
+ *
+ * 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.
+ *
+ */
+
+#ifndef _INCLUDE_PALMTX_H_
+#define _INCLUDE_PALMTX_H_
+
+/** HERE ARE GPIOs **/
+
+/* GPIOs */
+#define GPIO_NR_PALMTX_GPIO_RESET 1
+
+#define GPIO_NR_PALMTX_POWER_DETECT 12 /* 90 */
+#define GPIO_NR_PALMTX_HOTSYNC_BUTTON_N 10
+#define GPIO_NR_PALMTX_EARPHONE_DETECT 107
+
+/* SD/MMC */
+#define GPIO_NR_PALMTX_SD_DETECT_N 14
+#define GPIO_NR_PALMTX_SD_POWER 114 /* probably */
+#define GPIO_NR_PALMTX_SD_READONLY 115 /* probably */
+
+/* TOUCHSCREEN */
+#define GPIO_NR_PALMTX_WM9712_IRQ 27
+
+/* IRDA - disable GPIO connected to SD pin of tranceiver (TFBS4710?) ? */
+#define GPIO_NR_PALMTX_IR_DISABLE 40
+
+/* USB */
+#define GPIO_NR_PALMTX_USB_DETECT_N 13
+#define GPIO_NR_PALMTX_USB_POWER 95
+#define GPIO_NR_PALMTX_USB_PULLUP 93
+
+/* LCD/BACKLIGHT */
+#define GPIO_NR_PALMTX_BL_POWER 84
+#define GPIO_NR_PALMTX_LCD_POWER 96
+
+/* LCD BORDER */
+#define GPIO_NR_PALMTX_BORDER_SWITCH 98
+#define GPIO_NR_PALMTX_BORDER_SELECT 22
+
+/* BLUETOOTH */
+#define GPIO_NR_PALMTX_BT_POWER 17
+#define GPIO_NR_PALMTX_BT_RESET 83
+
+/* PCMCIA (WiFi) */
+#define GPIO_NR_PALMTX_PCMCIA_POWER1 94
+#define GPIO_NR_PALMTX_PCMCIA_POWER2 108
+#define GPIO_NR_PALMTX_PCMCIA_RESET 79
+#define GPIO_NR_PALMTX_PCMCIA_READY 116
+
+/* NAND Flash ... this GPIO may be incorrect! */
+#define GPIO_NR_PALMTX_NAND_BUFFER_DIR 79
+
+/* INTERRUPTS */
+#define IRQ_GPIO_PALMTX_SD_DETECT_N IRQ_GPIO(GPIO_NR_PALMTX_SD_DETECT_N)
+#define IRQ_GPIO_PALMTX_WM9712_IRQ IRQ_GPIO(GPIO_NR_PALMTX_WM9712_IRQ)
+#define IRQ_GPIO_PALMTX_USB_DETECT IRQ_GPIO(GPIO_NR_PALMTX_USB_DETECT)
+#define IRQ_GPIO_PALMTX_GPIO_RESET IRQ_GPIO(GPIO_NR_PALMTX_GPIO_RESET)
+
+/** HERE ARE INIT VALUES **/
+
+/* Various addresses */
+#define PALMTX_PCMCIA_PHYS 0x28000000
+#define PALMTX_PCMCIA_VIRT 0xf0000000
+#define PALMTX_PCMCIA_SIZE 0x100000
+
+#define PALMTX_PHYS_RAM_START 0xa0000000
+#define PALMTX_PHYS_IO_START 0x40000000
+
+#define PALMTX_PHYS_FLASH_START PXA_CS0_PHYS /* ChipSelect 0 */
+#define PALMTX_PHYS_NAND_START PXA_CS1_PHYS /* ChipSelect 1 */
+
+/* TOUCHSCREEN */
+#define AC97_LINK_FRAME 21
+
+
+/* BATTERY */
+#define PALMTX_BAT_MAX_VOLTAGE 4000 /* 4.00v current voltage */
+#define PALMTX_BAT_MIN_VOLTAGE 3550 /* 3.55v critical voltage */
+#define PALMTX_BAT_MAX_CURRENT 0 /* unknokn */
+#define PALMTX_BAT_MIN_CURRENT 0 /* unknown */
+#define PALMTX_BAT_MAX_CHARGE 1 /* unknown */
+#define PALMTX_BAT_MIN_CHARGE 1 /* unknown */
+#define PALMTX_MAX_LIFE_MINS 360 /* on-life in minutes */
+
+#define PALMTX_BAT_MEASURE_DELAY (HZ * 1)
+
+/* BACKLIGHT */
+#define PALMTX_MAX_INTENSITY 0xFE
+#define PALMTX_DEFAULT_INTENSITY 0x7E
+#define PALMTX_LIMIT_MASK 0x7F
+#define PALMTX_PRESCALER 0x3F
+#define PALMTX_PERIOD_NS 3500
+
+#endif
diff --git a/include/asm-arm/arch-pxa/pxa27x-udc.h b/include/asm-arm/arch-pxa/pxa27x-udc.h
index bc1cf7d0773..ab1443f8bd8 100644
--- a/include/asm-arm/arch-pxa/pxa27x-udc.h
+++ b/include/asm-arm/arch-pxa/pxa27x-udc.h
@@ -97,7 +97,7 @@
#define UP2OCR_IDON (1 << 10) /* OTG ID Read Enable */
#define UP2OCR_HXS (1 << 16) /* Host Port 2 Transceiver Output Select */
#define UP2OCR_HXOE (1 << 17) /* Host Port 2 Transceiver Output Enable */
-#define UP2OCR_SEOS (1 << 24) /* Single-Ended Output Select */
+#define UP2OCR_SEOS(x) ((x & 7) << 24) /* Single-Ended Output Select */
#define UDCCSN(x) __REG2(0x40600100, (x) << 2)
#define UDCCSR0 __REG(0x40600100) /* UDC Control/Status register - Endpoint 0 */
diff --git a/include/asm-arm/arch-pxa/pxa2xx_spi.h b/include/asm-arm/arch-pxa/pxa2xx_spi.h
index 3459fb26ce9..2206cb61a9f 100644
--- a/include/asm-arm/arch-pxa/pxa2xx_spi.h
+++ b/include/asm-arm/arch-pxa/pxa2xx_spi.h
@@ -41,4 +41,6 @@ struct pxa2xx_spi_chip {
void (*cs_control)(u32 command);
};
+extern void pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info);
+
#endif /*PXA2XX_SPI_H_*/
diff --git a/include/asm-arm/arch-pxa/pxa3xx_nand.h b/include/asm-arm/arch-pxa/pxa3xx_nand.h
index 81a8937486c..eb4b190b665 100644
--- a/include/asm-arm/arch-pxa/pxa3xx_nand.h
+++ b/include/asm-arm/arch-pxa/pxa3xx_nand.h
@@ -15,4 +15,6 @@ struct pxa3xx_nand_platform_data {
struct mtd_partition *parts;
unsigned int nr_parts;
};
+
+extern void pxa3xx_set_nand_info(struct pxa3xx_nand_platform_data *info);
#endif /* __ASM_ARCH_PXA3XX_NAND_H */
diff --git a/include/asm-arm/arch-pxa/pxafb.h b/include/asm-arm/arch-pxa/pxafb.h
index bbd22396841..daf018d0c60 100644
--- a/include/asm-arm/arch-pxa/pxafb.h
+++ b/include/asm-arm/arch-pxa/pxafb.h
@@ -71,7 +71,8 @@ struct pxafb_mode_info {
u_char bpp;
u_int cmap_greyscale:1,
- unused:31;
+ depth:8,
+ unused:23;
/* Parallel Mode Timing */
u_char hsync_len;
diff --git a/include/asm-arm/arch-pxa/regs-lcd.h b/include/asm-arm/arch-pxa/regs-lcd.h
index 3ba464c913a..820a189684a 100644
--- a/include/asm-arm/arch-pxa/regs-lcd.h
+++ b/include/asm-arm/arch-pxa/regs-lcd.h
@@ -27,6 +27,12 @@
#define LCCR3_4BPP (2 << 24)
#define LCCR3_8BPP (3 << 24)
#define LCCR3_16BPP (4 << 24)
+#define LCCR3_18BPP (5 << 24)
+#define LCCR3_18BPP_P (6 << 24)
+#define LCCR3_19BPP (7 << 24)
+#define LCCR3_19BPP_P (1 << 29)
+#define LCCR3_24BPP ((1 << 29) | (1 << 24))
+#define LCCR3_25BPP ((1 << 29) | (2 << 24))
#define LCCR3_PDFOR_0 (0 << 30)
#define LCCR3_PDFOR_1 (1 << 30)
diff --git a/include/asm-arm/arch-pxa/regs-ssp.h b/include/asm-arm/arch-pxa/regs-ssp.h
index 0255328c3c1..3c04cde2cf1 100644
--- a/include/asm-arm/arch-pxa/regs-ssp.h
+++ b/include/asm-arm/arch-pxa/regs-ssp.h
@@ -20,6 +20,10 @@
#define SSTSS (0x38) /* SSP Timeslot Status */
#define SSACD (0x3C) /* SSP Audio Clock Divider */
+#if defined(CONFIG_PXA3xx)
+#define SSACDD (0x40) /* SSP Audio Clock Dither Divider */
+#endif
+
/* Common PXA2xx bits first */
#define SSCR0_DSS (0x0000000f) /* Data Size Select (mask) */
#define SSCR0_DataSize(x) ((x) - 1) /* Data Size Select [4..16] */
@@ -29,10 +33,12 @@
#define SSCR0_National (0x2 << 4) /* National Microwire */
#define SSCR0_ECS (1 << 6) /* External clock select */
#define SSCR0_SSE (1 << 7) /* Synchronous Serial Port Enable */
+
#if defined(CONFIG_PXA25x)
#define SSCR0_SCR (0x0000ff00) /* Serial Clock Rate (mask) */
#define SSCR0_SerClkDiv(x) ((((x) - 2)/2) << 8) /* Divisor [2..512] */
-#elif defined(CONFIG_PXA27x)
+
+#elif defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
#define SSCR0_SCR (0x000fff00) /* Serial Clock Rate (mask) */
#define SSCR0_SerClkDiv(x) (((x) - 1) << 8) /* Divisor [1..4096] */
#define SSCR0_EDSS (1 << 20) /* Extended data size select */
@@ -45,6 +51,10 @@
#define SSCR0_MOD (1 << 31) /* Mode (normal or network) */
#endif
+#if defined(CONFIG_PXA3xx)
+#define SSCR0_FPCKE (1 << 29) /* FIFO packing enable */
+#endif
+
#define SSCR1_RIE (1 << 0) /* Receive FIFO Interrupt Enable */
#define SSCR1_TIE (1 << 1) /* Transmit FIFO Interrupt Enable */
#define SSCR1_LBM (1 << 2) /* Loop-Back Mode */
@@ -109,5 +119,9 @@
#define SSACD_SCDB (1 << 3) /* SSPSYSCLK Divider Bypass */
#define SSACD_ACPS(x) ((x) << 4) /* Audio clock PLL select */
#define SSACD_ACDS(x) ((x) << 0) /* Audio clock divider select */
+#if defined(CONFIG_PXA3xx)
+#define SSACD_SCDX8 (1 << 7) /* SYSCLK division ratio select */
+#endif
+
#endif /* __ASM_ARCH_REGS_SSP_H */
diff --git a/include/asm-arm/arch-pxa/system.h b/include/asm-arm/arch-pxa/system.h
index ba7e132de1b..6956fc5235f 100644
--- a/include/asm-arm/arch-pxa/system.h
+++ b/include/asm-arm/arch-pxa/system.h
@@ -21,19 +21,4 @@ static inline void arch_idle(void)
}
-static inline void arch_reset(char mode)
-{
- if (cpu_is_pxa2xx())
- RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
-
- if (mode == 's') {
- /* Jump into ROM at address 0 */
- cpu_reset(0);
- } else {
- /* Initialize the watchdog and let it fire */
- OWER = OWER_WME;
- OSSR = OSSR_M3;
- OSMR3 = OSCR + 368640; /* ... in 100 ms */
- }
-}
-
+void arch_reset(char mode);
diff --git a/include/asm-arm/arch-pxa/tosa.h b/include/asm-arm/arch-pxa/tosa.h
index c5b6fde6907..a72803f0461 100644
--- a/include/asm-arm/arch-pxa/tosa.h
+++ b/include/asm-arm/arch-pxa/tosa.h
@@ -25,21 +25,18 @@
*/
#define TOSA_SCOOP_GPIO_BASE NR_BUILTIN_GPIO
#define TOSA_SCOOP_PXA_VCORE1 SCOOP_GPCR_PA11
-#define TOSA_SCOOP_TC6393_REST_IN SCOOP_GPCR_PA12
+#define TOSA_GPIO_TC6393XB_REST_IN (TOSA_SCOOP_GPIO_BASE + 1)
#define TOSA_GPIO_IR_POWERDWN (TOSA_SCOOP_GPIO_BASE + 2)
#define TOSA_GPIO_SD_WP (TOSA_SCOOP_GPIO_BASE + 3)
#define TOSA_GPIO_PWR_ON (TOSA_SCOOP_GPIO_BASE + 4)
#define TOSA_SCOOP_AUD_PWR_ON SCOOP_GPCR_PA16
-#define TOSA_SCOOP_BT_RESET SCOOP_GPCR_PA17
-#define TOSA_SCOOP_BT_PWR_EN SCOOP_GPCR_PA18
+#define TOSA_GPIO_BT_RESET (TOSA_SCOOP_GPIO_BASE + 6)
+#define TOSA_GPIO_BT_PWR_EN (TOSA_SCOOP_GPIO_BASE + 7)
#define TOSA_SCOOP_AC_IN_OL SCOOP_GPCR_PA19
/* GPIO Direction 1 : output mode / 0:input mode */
-#define TOSA_SCOOP_IO_DIR ( TOSA_SCOOP_PXA_VCORE1 | TOSA_SCOOP_TC6393_REST_IN | \
- TOSA_SCOOP_AUD_PWR_ON |\
- TOSA_SCOOP_BT_RESET | TOSA_SCOOP_BT_PWR_EN )
-/* GPIO out put level when init 1: Hi */
-#define TOSA_SCOOP_IO_OUT ( TOSA_SCOOP_TC6393_REST_IN )
+#define TOSA_SCOOP_IO_DIR (TOSA_SCOOP_PXA_VCORE1 | \
+ TOSA_SCOOP_AUD_PWR_ON)
/*
* SCOOP2 jacket GPIOs
@@ -49,16 +46,34 @@
#define TOSA_GPIO_NOTE_LED (TOSA_SCOOP_JC_GPIO_BASE + 1)
#define TOSA_GPIO_CHRG_ERR_LED (TOSA_SCOOP_JC_GPIO_BASE + 2)
#define TOSA_GPIO_USB_PULLUP (TOSA_SCOOP_JC_GPIO_BASE + 3)
-#define TOSA_SCOOP_JC_TC6393_SUSPEND SCOOP_GPCR_PA15
-#define TOSA_SCOOP_JC_TC3693_L3V_ON SCOOP_GPCR_PA16
+#define TOSA_GPIO_TC6393XB_SUSPEND (TOSA_SCOOP_JC_GPIO_BASE + 4)
+#define TOSA_GPIO_TC6393XB_L3V_ON (TOSA_SCOOP_JC_GPIO_BASE + 5)
#define TOSA_SCOOP_JC_WLAN_DETECT SCOOP_GPCR_PA17
#define TOSA_GPIO_WLAN_LED (TOSA_SCOOP_JC_GPIO_BASE + 7)
#define TOSA_SCOOP_JC_CARD_LIMIT_SEL SCOOP_GPCR_PA19
/* GPIO Direction 1 : output mode / 0:input mode */
-#define TOSA_SCOOP_JC_IO_DIR ( \
- TOSA_SCOOP_JC_TC6393_SUSPEND | TOSA_SCOOP_JC_TC3693_L3V_ON | \
- TOSA_SCOOP_JC_CARD_LIMIT_SEL )
+#define TOSA_SCOOP_JC_IO_DIR (TOSA_SCOOP_JC_CARD_LIMIT_SEL)
+
+/*
+ * TC6393XB GPIOs
+ */
+#define TOSA_TC6393XB_GPIO_BASE (NR_BUILTIN_GPIO + 2 * 12)
+#define TOSA_TC6393XB_GPIO(i) (TOSA_TC6393XB_GPIO_BASE + (i))
+#define TOSA_TC6393XB_GPIO_BIT(gpio) (1 << (gpio - TOSA_TC6393XB_GPIO_BASE))
+
+#define TOSA_GPIO_TG_ON (TOSA_TC6393XB_GPIO_BASE + 0)
+#define TOSA_GPIO_L_MUTE (TOSA_TC6393XB_GPIO_BASE + 1)
+#define TOSA_GPIO_BL_C20MA (TOSA_TC6393XB_GPIO_BASE + 3)
+#define TOSA_GPIO_CARD_VCC_ON (TOSA_TC6393XB_GPIO_BASE + 4)
+#define TOSA_GPIO_CHARGE_OFF (TOSA_TC6393XB_GPIO_BASE + 6)
+#define TOSA_GPIO_CHARGE_OFF_JC (TOSA_TC6393XB_GPIO_BASE + 7)
+#define TOSA_GPIO_BAT0_V_ON (TOSA_TC6393XB_GPIO_BASE + 9)
+#define TOSA_GPIO_BAT1_V_ON (TOSA_TC6393XB_GPIO_BASE + 10)
+#define TOSA_GPIO_BU_CHRG_ON (TOSA_TC6393XB_GPIO_BASE + 11)
+#define TOSA_GPIO_BAT_SW_ON (TOSA_TC6393XB_GPIO_BASE + 12)
+#define TOSA_GPIO_BAT0_TH_ON (TOSA_TC6393XB_GPIO_BASE + 14)
+#define TOSA_GPIO_BAT1_TH_ON (TOSA_TC6393XB_GPIO_BASE + 15)
/*
* Timing Generator
@@ -84,13 +99,13 @@
#define TOSA_GPIO_JACKET_DETECT (7)
#define TOSA_GPIO_nSD_DETECT (9)
#define TOSA_GPIO_nSD_INT (10)
-#define TOSA_GPIO_TC6393_CLK (11)
+#define TOSA_GPIO_TC6393XB_CLK (11)
#define TOSA_GPIO_BAT1_CRG (12)
#define TOSA_GPIO_CF_CD (13)
#define TOSA_GPIO_BAT0_CRG (14)
-#define TOSA_GPIO_TC6393_INT (15)
+#define TOSA_GPIO_TC6393XB_INT (15)
#define TOSA_GPIO_BAT0_LOW (17)
-#define TOSA_GPIO_TC6393_RDY (18)
+#define TOSA_GPIO_TC6393XB_RDY (18)
#define TOSA_GPIO_ON_RESET (19)
#define TOSA_GPIO_EAR_IN (20)
#define TOSA_GPIO_CF_IRQ (21) /* CF slot0 Ready */
@@ -99,6 +114,7 @@
#define TOSA_GPIO_TP_INT (32) /* Touch Panel pen down interrupt */
#define TOSA_GPIO_JC_CF_IRQ (36) /* CF slot1 Ready */
#define TOSA_GPIO_BAT_LOCKED (38) /* Battery locked */
+#define TOSA_GPIO_IRDA_TX (47)
#define TOSA_GPIO_TG_SPI_SCLK (81)
#define TOSA_GPIO_TG_SPI_CS (82)
#define TOSA_GPIO_TG_SPI_MOSI (83)
@@ -137,7 +153,7 @@
#define TOSA_IRQ_GPIO_BAT1_CRG IRQ_GPIO(TOSA_GPIO_BAT1_CRG)
#define TOSA_IRQ_GPIO_CF_CD IRQ_GPIO(TOSA_GPIO_CF_CD)
#define TOSA_IRQ_GPIO_BAT0_CRG IRQ_GPIO(TOSA_GPIO_BAT0_CRG)
-#define TOSA_IRQ_GPIO_TC6393_INT IRQ_GPIO(TOSA_GPIO_TC6393_INT)
+#define TOSA_IRQ_GPIO_TC6393XB_INT IRQ_GPIO(TOSA_GPIO_TC6393XB_INT)
#define TOSA_IRQ_GPIO_BAT0_LOW IRQ_GPIO(TOSA_GPIO_BAT0_LOW)
#define TOSA_IRQ_GPIO_EAR_IN IRQ_GPIO(TOSA_GPIO_EAR_IN)
#define TOSA_IRQ_GPIO_CF_IRQ IRQ_GPIO(TOSA_GPIO_CF_IRQ)
diff --git a/include/asm-arm/arch-pxa/tosa_bt.h b/include/asm-arm/arch-pxa/tosa_bt.h
new file mode 100644
index 00000000000..efc3c3d3b75
--- /dev/null
+++ b/include/asm-arm/arch-pxa/tosa_bt.h
@@ -0,0 +1,22 @@
+/*
+ * Tosa bluetooth built-in chip control.
+ *
+ * Later it may be shared with some other platforms.
+ *
+ * Copyright (c) 2008 Dmitry Baryshkov
+ *
+ * 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.
+ *
+ */
+#ifndef TOSA_BT_H
+#define TOSA_BT_H
+
+struct tosa_bt_data {
+ int gpio_pwr;
+ int gpio_reset;
+};
+
+#endif
+
diff --git a/include/asm-arm/arch-pxa/uncompress.h b/include/asm-arm/arch-pxa/uncompress.h
index dadf4c20b62..f4551269aaf 100644
--- a/include/asm-arm/arch-pxa/uncompress.h
+++ b/include/asm-arm/arch-pxa/uncompress.h
@@ -11,11 +11,11 @@
#include <linux/serial_reg.h>
#include <asm/arch/pxa-regs.h>
+#include <asm/mach-types.h>
-#define __REG(x) ((volatile unsigned long *)x)
-
-#define UART FFUART
+#define __REG(x) ((volatile unsigned long *)x)
+static volatile unsigned long *UART = FFUART;
static inline void putc(char c)
{
@@ -33,8 +33,13 @@ static inline void flush(void)
{
}
+static inline void arch_decomp_setup(void)
+{
+ if (machine_is_littleton())
+ UART = STUART;
+}
+
/*
* nothing to do
*/
-#define arch_decomp_setup()
#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-pxa/zylonite.h b/include/asm-arm/arch-pxa/zylonite.h
index de577de8d18..0d35ca04731 100644
--- a/include/asm-arm/arch-pxa/zylonite.h
+++ b/include/asm-arm/arch-pxa/zylonite.h
@@ -16,6 +16,8 @@ struct platform_mmc_slot {
extern struct platform_mmc_slot zylonite_mmc_slot[];
extern int gpio_eth_irq;
+extern int gpio_debug_led1;
+extern int gpio_debug_led2;
extern int wm9713_irq;
diff --git a/include/asm-arm/arch-sa1100/h3600.h b/include/asm-arm/arch-sa1100/h3600.h
index 1b635597157..3ca0ecf095e 100644
--- a/include/asm-arm/arch-sa1100/h3600.h
+++ b/include/asm-arm/arch-sa1100/h3600.h
@@ -23,6 +23,11 @@
#ifndef _INCLUDE_H3600_H_
#define _INCLUDE_H3600_H_
+typedef int __bitwise pm_request_t;
+
+#define PM_SUSPEND ((__force pm_request_t) 1) /* enter D1-D3 */
+#define PM_RESUME ((__force pm_request_t) 2) /* enter D0 */
+
/* generalized support for H3xxx series Compaq Pocket PC's */
#define machine_is_h3xxx() (machine_is_h3100() || machine_is_h3600() || machine_is_h3800())
diff --git a/include/asm-arm/hardware/iop3xx-adma.h b/include/asm-arm/hardware/iop3xx-adma.h
index a32b86ac62a..af64676650a 100644
--- a/include/asm-arm/hardware/iop3xx-adma.h
+++ b/include/asm-arm/hardware/iop3xx-adma.h
@@ -260,7 +260,7 @@ static inline int iop_chan_memset_slot_count(size_t len, int *slots_per_op)
static inline int iop3xx_aau_xor_slot_count(size_t len, int src_cnt,
int *slots_per_op)
{
- static const int slot_count_table[] = { 0,
+ static const char slot_count_table[] = {
1, 1, 1, 1, /* 01 - 04 */
2, 2, 2, 2, /* 05 - 08 */
4, 4, 4, 4, /* 09 - 12 */
@@ -270,7 +270,7 @@ static inline int iop3xx_aau_xor_slot_count(size_t len, int src_cnt,
8, 8, 8, 8, /* 25 - 28 */
8, 8, 8, 8, /* 29 - 32 */
};
- *slots_per_op = slot_count_table[src_cnt];
+ *slots_per_op = slot_count_table[src_cnt - 1];
return *slots_per_op;
}
diff --git a/include/asm-arm/ide.h b/include/asm-arm/ide.h
index 88f4d231ce4..a48019f99d0 100644
--- a/include/asm-arm/ide.h
+++ b/include/asm-arm/ide.h
@@ -13,10 +13,6 @@
#ifdef __KERNEL__
-#ifndef MAX_HWIFS
-#define MAX_HWIFS 4
-#endif
-
#define __ide_mm_insw(port,addr,len) readsw(port,addr,len)
#define __ide_mm_insl(port,addr,len) readsl(port,addr,len)
#define __ide_mm_outsw(port,addr,len) writesw(port,addr,len)
diff --git a/include/asm-arm/kgdb.h b/include/asm-arm/kgdb.h
new file mode 100644
index 00000000000..67af4b84198
--- /dev/null
+++ b/include/asm-arm/kgdb.h
@@ -0,0 +1,104 @@
+/*
+ * ARM KGDB support
+ *
+ * Author: Deepak Saxena <dsaxena@mvista.com>
+ *
+ * Copyright (C) 2002 MontaVista Software Inc.
+ *
+ */
+
+#ifndef __ARM_KGDB_H__
+#define __ARM_KGDB_H__
+
+#include <linux/ptrace.h>
+
+/*
+ * GDB assumes that we're a user process being debugged, so
+ * it will send us an SWI command to write into memory as the
+ * debug trap. When an SWI occurs, the next instruction addr is
+ * placed into R14_svc before jumping to the vector trap.
+ * This doesn't work for kernel debugging as we are already in SVC
+ * we would loose the kernel's LR, which is a bad thing. This
+ * is bad thing.
+ *
+ * By doing this as an undefined instruction trap, we force a mode
+ * switch from SVC to UND mode, allowing us to save full kernel state.
+ *
+ * We also define a KGDB_COMPILED_BREAK which can be used to compile
+ * in breakpoints. This is important for things like sysrq-G and for
+ * the initial breakpoint from trap_init().
+ *
+ * Note to ARM HW designers: Add real trap support like SH && PPC to
+ * make our lives much much simpler. :)
+ */
+#define BREAK_INSTR_SIZE 4
+#define GDB_BREAKINST 0xef9f0001
+#define KGDB_BREAKINST 0xe7ffdefe
+#define KGDB_COMPILED_BREAK 0xe7ffdeff
+#define CACHE_FLUSH_IS_SAFE 1
+
+#ifndef __ASSEMBLY__
+
+static inline void arch_kgdb_breakpoint(void)
+{
+ asm(".word 0xe7ffdeff");
+}
+
+extern void kgdb_handle_bus_error(void);
+extern int kgdb_fault_expected;
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * From Kevin Hilman:
+ *
+ * gdb is expecting the following registers layout.
+ *
+ * r0-r15: 1 long word each
+ * f0-f7: unused, 3 long words each !!
+ * fps: unused, 1 long word
+ * cpsr: 1 long word
+ *
+ * Even though f0-f7 and fps are not used, they need to be
+ * present in the registers sent for correct processing in
+ * the host-side gdb.
+ *
+ * In particular, it is crucial that CPSR is in the right place,
+ * otherwise gdb will not be able to correctly interpret stepping over
+ * conditional branches.
+ */
+#define _GP_REGS 16
+#define _FP_REGS 8
+#define _EXTRA_REGS 2
+#define GDB_MAX_REGS (_GP_REGS + (_FP_REGS * 3) + _EXTRA_REGS)
+
+#define KGDB_MAX_NO_CPUS 1
+#define BUFMAX 400
+#define NUMREGBYTES (GDB_MAX_REGS << 2)
+#define NUMCRITREGBYTES (32 << 2)
+
+#define _R0 0
+#define _R1 1
+#define _R2 2
+#define _R3 3
+#define _R4 4
+#define _R5 5
+#define _R6 6
+#define _R7 7
+#define _R8 8
+#define _R9 9
+#define _R10 10
+#define _FP 11
+#define _IP 12
+#define _SPT 13
+#define _LR 14
+#define _PC 15
+#define _CPSR (GDB_MAX_REGS - 1)
+
+/*
+ * So that we can denote the end of a frame for tracing,
+ * in the simple case:
+ */
+#define CFI_END_FRAME(func) __CFI_END_FRAME(_PC, _SPT, func)
+
+#endif /* __ASM_KGDB_H__ */
diff --git a/include/asm-arm/kvm.h b/include/asm-arm/kvm.h
deleted file mode 100644
index cb3c08cbcb9..00000000000
--- a/include/asm-arm/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_ARM_H
-#define __LINUX_KVM_ARM_H
-
-/* arm does not support KVM */
-
-#endif
diff --git a/include/asm-arm/mach/udc_pxa2xx.h b/include/asm-arm/mach/udc_pxa2xx.h
index f9f3606986c..9e5ed7c0f27 100644
--- a/include/asm-arm/mach/udc_pxa2xx.h
+++ b/include/asm-arm/mach/udc_pxa2xx.h
@@ -23,6 +23,7 @@ struct pxa2xx_udc_mach_info {
*/
bool gpio_vbus_inverted;
u16 gpio_vbus; /* high == vbus present */
+ bool gpio_pullup_inverted;
u16 gpio_pullup; /* high == pullup activated */
};
diff --git a/include/asm-arm/page-nommu.h b/include/asm-arm/page-nommu.h
index a1bcad06048..ea1cde84f50 100644
--- a/include/asm-arm/page-nommu.h
+++ b/include/asm-arm/page-nommu.h
@@ -7,6 +7,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+
#ifndef _ASMARM_PAGE_NOMMU_H
#define _ASMARM_PAGE_NOMMU_H
@@ -42,9 +43,6 @@ typedef unsigned long pgprot_t;
#define __pmd(x) (x)
#define __pgprot(x) (x)
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
extern unsigned long memory_start;
extern unsigned long memory_end;
diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h
index 8e05bdb5f12..7c5fc5582e5 100644
--- a/include/asm-arm/page.h
+++ b/include/asm-arm/page.h
@@ -15,9 +15,6 @@
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
#ifndef __ASSEMBLY__
#ifndef CONFIG_MMU
diff --git a/include/asm-arm/plat-orion/mv_xor.h b/include/asm-arm/plat-orion/mv_xor.h
new file mode 100644
index 00000000000..c349e8ff5cc
--- /dev/null
+++ b/include/asm-arm/plat-orion/mv_xor.h
@@ -0,0 +1,28 @@
+/*
+ * Marvell XOR platform device data definition file.
+ */
+
+#ifndef __ASM_PLAT_ORION_MV_XOR_H
+#define __ASM_PLAT_ORION_MV_XOR_H
+
+#include <linux/dmaengine.h>
+#include <linux/mbus.h>
+
+#define MV_XOR_SHARED_NAME "mv_xor_shared"
+#define MV_XOR_NAME "mv_xor"
+
+struct mbus_dram_target_info;
+
+struct mv_xor_platform_shared_data {
+ struct mbus_dram_target_info *dram;
+};
+
+struct mv_xor_platform_data {
+ struct platform_device *shared;
+ int hw_id;
+ dma_cap_mask_t cap_mask;
+ size_t pool_size;
+};
+
+
+#endif
diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h
index 7aaa206cb54..8382b7510f9 100644
--- a/include/asm-arm/ptrace.h
+++ b/include/asm-arm/ptrace.h
@@ -139,8 +139,6 @@ static inline int valid_user_regs(struct pt_regs *regs)
return 0;
}
-#endif /* __KERNEL__ */
-
#define pc_pointer(v) \
((v) & ~PCMASK)
@@ -153,10 +151,10 @@ extern unsigned long profile_pc(struct pt_regs *regs);
#define profile_pc(regs) instruction_pointer(regs)
#endif
-#ifdef __KERNEL__
#define predicate(x) ((x) & 0xf0000000)
#define PREDICATE_ALWAYS 0xe0000000
-#endif
+
+#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-arm/semaphore.h b/include/asm-arm/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-arm/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h
index f5a66478631..d4be2d64616 100644
--- a/include/asm-arm/thread_info.h
+++ b/include/asm-arm/thread_info.h
@@ -97,19 +97,6 @@ static inline struct thread_info *current_thread_info(void)
return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
}
-/* thread information allocation */
-#ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk) \
- ((struct thread_info *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, \
- THREAD_SIZE_ORDER))
-#else
-#define alloc_thread_info(tsk) \
- ((struct thread_info *)__get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER))
-#endif
-
-#define free_thread_info(info) \
- free_pages((unsigned long)info, THREAD_SIZE_ORDER);
-
#define thread_saved_pc(tsk) \
((unsigned long)(pc_pointer(task_thread_info(tsk)->cpu_context.pc)))
#define thread_saved_fp(tsk) \
diff --git a/include/asm-arm/traps.h b/include/asm-arm/traps.h
index f1541afcf85..aa399aec568 100644
--- a/include/asm-arm/traps.h
+++ b/include/asm-arm/traps.h
@@ -24,4 +24,6 @@ static inline int in_exception_text(unsigned long ptr)
ptr < (unsigned long)&__exception_text_end;
}
+extern void __init early_trap_init(void);
+
#endif
diff --git a/include/asm-avr32/arch-at32ap/at32ap700x.h b/include/asm-avr32/arch-at32ap/at32ap700x.h
index 31e48b0e732..d18a3053be0 100644
--- a/include/asm-avr32/arch-at32ap/at32ap700x.h
+++ b/include/asm-avr32/arch-at32ap/at32ap700x.h
@@ -30,4 +30,20 @@
#define GPIO_PIN_PD(N) (GPIO_PIOD_BASE + (N))
#define GPIO_PIN_PE(N) (GPIO_PIOE_BASE + (N))
+
+/*
+ * DMAC peripheral hardware handshaking interfaces, used with dw_dmac
+ */
+#define DMAC_MCI_RX 0
+#define DMAC_MCI_TX 1
+#define DMAC_DAC_TX 2
+#define DMAC_AC97_A_RX 3
+#define DMAC_AC97_A_TX 4
+#define DMAC_AC97_B_RX 5
+#define DMAC_AC97_B_TX 6
+#define DMAC_DMAREQ_0 7
+#define DMAC_DMAREQ_1 8
+#define DMAC_DMAREQ_2 9
+#define DMAC_DMAREQ_3 10
+
#endif /* __ASM_ARCH_AT32AP700X_H__ */
diff --git a/include/asm-avr32/kvm.h b/include/asm-avr32/kvm.h
deleted file mode 100644
index 8c5777020e2..00000000000
--- a/include/asm-avr32/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_AVR32_H
-#define __LINUX_KVM_AVR32_H
-
-/* avr32 does not support KVM */
-
-#endif
diff --git a/include/asm-avr32/page.h b/include/asm-avr32/page.h
index cbbc5ca9728..f805d1cb11b 100644
--- a/include/asm-avr32/page.h
+++ b/include/asm-avr32/page.h
@@ -57,9 +57,6 @@ static inline int get_order(unsigned long size)
#endif /* !__ASSEMBLY__ */
-/* Align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-
/*
* The hardware maps the virtual addresses 0x80000000 -> 0x9fffffff
* permanently to the physical addresses 0x00000000 -> 0x1fffffff when
diff --git a/include/asm-avr32/semaphore.h b/include/asm-avr32/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-avr32/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-avr32/thread_info.h b/include/asm-avr32/thread_info.h
index df68631b7b2..294b25f9323 100644
--- a/include/asm-avr32/thread_info.h
+++ b/include/asm-avr32/thread_info.h
@@ -61,10 +61,6 @@ static inline struct thread_info *current_thread_info(void)
return (struct thread_info *)addr;
}
-/* thread information allocation */
-#define alloc_thread_info(ti) \
- ((struct thread_info *) __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER))
-#define free_thread_info(ti) free_pages((unsigned long)(ti), 1)
#define get_thread_info(ti) get_task_struct((ti)->task)
#define put_thread_info(ti) put_task_struct((ti)->task)
diff --git a/include/asm-blackfin/ide.h b/include/asm-blackfin/ide.h
deleted file mode 100644
index 5b88de115bf..00000000000
--- a/include/asm-blackfin/ide.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/****************************************************************************/
-
-/*
- * linux/include/asm-blackfin/ide.h
- *
- * Copyright (C) 1994-1996 Linus Torvalds & authors
- * Copyright (C) 2001 Lineo Inc., davidm@snapgear.com
- * Copyright (C) 2002 Greg Ungerer (gerg@snapgear.com)
- * Copyright (C) 2002 Yoshinori Sato (ysato@users.sourceforge.jp)
- * Copyright (C) 2005 Hennerich Michael (hennerich@blackfin.uclinux.org)
- */
-
-/****************************************************************************/
-#ifndef _BLACKFIN_IDE_H
-#define _BLACKFIN_IDE_H
-/****************************************************************************/
-#ifdef __KERNEL__
-/****************************************************************************/
-
-#define MAX_HWIFS 1
-
-#include <asm-generic/ide_iops.h>
-
-/****************************************************************************/
-#endif /* __KERNEL__ */
-#endif /* _BLACKFIN_IDE_H */
-/****************************************************************************/
diff --git a/include/asm-blackfin/kvm.h b/include/asm-blackfin/kvm.h
deleted file mode 100644
index e3477d77c01..00000000000
--- a/include/asm-blackfin/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_BLACKFIN_H
-#define __LINUX_KVM_BLACKFIN_H
-
-/* blackfin does not support KVM */
-
-#endif
diff --git a/include/asm-blackfin/page.h b/include/asm-blackfin/page.h
index c7db0220fbd..344f6a8c1f2 100644
--- a/include/asm-blackfin/page.h
+++ b/include/asm-blackfin/page.h
@@ -51,9 +51,6 @@ typedef struct page *pgtable_t;
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
extern unsigned long memory_start;
extern unsigned long memory_end;
diff --git a/include/asm-blackfin/ptrace.h b/include/asm-blackfin/ptrace.h
index b8346cd3a6f..a45a80e54ad 100644
--- a/include/asm-blackfin/ptrace.h
+++ b/include/asm-blackfin/ptrace.h
@@ -83,14 +83,14 @@ struct pt_regs {
#define PTRACE_GETREGS 12
#define PTRACE_SETREGS 13 /* ptrace signal */
-#ifdef CONFIG_BINFMT_ELF_FDPIC
#define PTRACE_GETFDPIC 31
#define PTRACE_GETFDPIC_EXEC 0
#define PTRACE_GETFDPIC_INTERP 1
-#endif
#define PS_S (0x0002)
+#ifdef __KERNEL__
+
/* user_mode returns true if only one bit is set in IPEND, other than the
master interrupt enable. */
#define user_mode(regs) (!(((regs)->ipend & ~0x10) & (((regs)->ipend & ~0x10) - 1)))
@@ -98,6 +98,8 @@ struct pt_regs {
#define profile_pc(regs) instruction_pointer(regs)
extern void show_regs(struct pt_regs *);
+#endif /* __KERNEL__ */
+
#endif /* __ASSEMBLY__ */
/*
diff --git a/include/asm-blackfin/semaphore.h b/include/asm-blackfin/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-blackfin/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-blackfin/thread_info.h b/include/asm-blackfin/thread_info.h
index bc2fe5accf2..642769329d1 100644
--- a/include/asm-blackfin/thread_info.h
+++ b/include/asm-blackfin/thread_info.h
@@ -42,6 +42,7 @@
/*
* Size of kernel stack for each process. This must be a power of 2...
*/
+#define THREAD_SIZE_ORDER 1
#define THREAD_SIZE 8192 /* 2 pages */
#ifndef __ASSEMBLY__
@@ -94,10 +95,6 @@ static inline struct thread_info *current_thread_info(void)
return (struct thread_info *)((long)ti & ~((long)THREAD_SIZE-1));
}
-/* thread information allocation */
-#define alloc_thread_info(tsk) ((struct thread_info *) \
- __get_free_pages(GFP_KERNEL, 1))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
#endif /* __ASSEMBLY__ */
/*
diff --git a/include/asm-cris/arch-v10/Kbuild b/include/asm-cris/arch-v10/Kbuild
index 60e7e1b73ce..7a192e1290b 100644
--- a/include/asm-cris/arch-v10/Kbuild
+++ b/include/asm-cris/arch-v10/Kbuild
@@ -1,4 +1,3 @@
-header-y += ptrace.h
header-y += user.h
header-y += svinto.h
header-y += sv_addr_ag.h
diff --git a/include/asm-cris/arch-v10/ide.h b/include/asm-cris/arch-v10/ide.h
deleted file mode 100644
index 5366e623932..00000000000
--- a/include/asm-cris/arch-v10/ide.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * linux/include/asm-cris/ide.h
- *
- * Copyright (C) 2000, 2001, 2002 Axis Communications AB
- *
- * Authors: Bjorn Wesen
- *
- */
-
-/*
- * This file contains the ETRAX 100LX specific IDE code.
- */
-
-#ifndef __ASMCRIS_IDE_H
-#define __ASMCRIS_IDE_H
-
-#ifdef __KERNEL__
-
-#include <asm/arch/svinto.h>
-#include <asm/io.h>
-#include <asm-generic/ide_iops.h>
-
-
-/* ETRAX 100 can support 4 IDE busses on the same pins (serialized) */
-
-#define MAX_HWIFS 4
-
-static inline int ide_default_irq(unsigned long base)
-{
- /* all IDE busses share the same IRQ, number 4.
- * this has the side-effect that ide-probe.c will cluster our 4 interfaces
- * together in a hwgroup, and will serialize accesses. this is good, because
- * we can't access more than one interface at the same time on ETRAX100.
- */
- return 4;
-}
-
-static inline unsigned long ide_default_io_base(int index)
-{
- /* we have no real I/O base address per interface, since all go through the
- * same register. but in a bitfield in that register, we have the i/f number.
- * so we can use the io_base to remember that bitfield.
- */
- static const unsigned long io_bases[MAX_HWIFS] = {
- IO_FIELD(R_ATA_CTRL_DATA, sel, 0),
- IO_FIELD(R_ATA_CTRL_DATA, sel, 1),
- IO_FIELD(R_ATA_CTRL_DATA, sel, 2),
- IO_FIELD(R_ATA_CTRL_DATA, sel, 3)
- };
- return io_bases[index];
-}
-
-/* this is called once for each interface, to setup the port addresses. data_port is the result
- * of the ide_default_io_base call above. ctrl_port will be 0, but that is don't care for us.
- */
-
-static inline void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, unsigned long ctrl_port, int *irq)
-{
- int i;
-
- /* fill in ports for ATA addresses 0 to 7 */
- for (i = 0; i <= 7; i++) {
- hw->io_ports_array[i] = data_port |
- IO_FIELD(R_ATA_CTRL_DATA, addr, i) |
- IO_STATE(R_ATA_CTRL_DATA, cs0, active);
- }
-
- /* the IDE control register is at ATA address 6, with CS1 active instead of CS0 */
- hw->io_ports.ctl_addr = data_port |
- IO_FIELD(R_ATA_CTRL_DATA, addr, 6) |
- IO_STATE(R_ATA_CTRL_DATA, cs1, active);
-
- /* whats this for ? */
- hw->io_ports.irq_addr = 0;
-}
-
-static inline void ide_init_default_hwifs(void)
-{
- hw_regs_t hw;
- int index;
-
- for(index = 0; index < MAX_HWIFS; index++) {
- ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
- hw.irq = ide_default_irq(ide_default_io_base(index));
- ide_register_hw(&hw, NULL);
- }
-}
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASMCRIS_IDE_H */
diff --git a/include/asm-cris/arch-v10/ptrace.h b/include/asm-cris/arch-v10/ptrace.h
index fb14c5ee37f..2f464eab3a5 100644
--- a/include/asm-cris/arch-v10/ptrace.h
+++ b/include/asm-cris/arch-v10/ptrace.h
@@ -106,10 +106,14 @@ struct switch_stack {
unsigned long return_ip; /* ip that _resume will return to */
};
+#ifdef __KERNEL__
+
/* bit 8 is user-mode flag */
#define user_mode(regs) (((regs)->dccr & 0x100) != 0)
#define instruction_pointer(regs) ((regs)->irp)
#define profile_pc(regs) instruction_pointer(regs)
extern void show_regs(struct pt_regs *);
+#endif /* __KERNEL__ */
+
#endif
diff --git a/include/asm-cris/arch-v32/Kbuild b/include/asm-cris/arch-v32/Kbuild
index a0ec545e242..35f2fc4f993 100644
--- a/include/asm-cris/arch-v32/Kbuild
+++ b/include/asm-cris/arch-v32/Kbuild
@@ -1,3 +1,2 @@
-header-y += ptrace.h
header-y += user.h
header-y += cryptocop.h
diff --git a/include/asm-cris/arch-v32/ide.h b/include/asm-cris/arch-v32/ide.h
deleted file mode 100644
index fb9c3627a5b..00000000000
--- a/include/asm-cris/arch-v32/ide.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * linux/include/asm-cris/ide.h
- *
- * Copyright (C) 2000-2004 Axis Communications AB
- *
- * Authors: Bjorn Wesen, Mikael Starvik
- *
- */
-
-/*
- * This file contains the ETRAX FS specific IDE code.
- */
-
-#ifndef __ASMCRIS_IDE_H
-#define __ASMCRIS_IDE_H
-
-#ifdef __KERNEL__
-
-#include <asm/arch/hwregs/intr_vect.h>
-#include <asm/arch/hwregs/ata_defs.h>
-#include <asm/io.h>
-#include <asm-generic/ide_iops.h>
-
-
-/* ETRAX FS can support 4 IDE busses on the same pins (serialized) */
-
-#define MAX_HWIFS 4
-
-static inline int ide_default_irq(unsigned long base)
-{
- /* all IDE busses share the same IRQ,
- * this has the side-effect that ide-probe.c will cluster our 4 interfaces
- * together in a hwgroup, and will serialize accesses. this is good, because
- * we can't access more than one interface at the same time on ETRAX100.
- */
- return ATA_INTR_VECT;
-}
-
-static inline unsigned long ide_default_io_base(int index)
-{
- reg_ata_rw_ctrl2 ctrl2 = {.sel = index};
- /* we have no real I/O base address per interface, since all go through the
- * same register. but in a bitfield in that register, we have the i/f number.
- * so we can use the io_base to remember that bitfield.
- */
- ctrl2.sel = index;
-
- return REG_TYPE_CONV(unsigned long, reg_ata_rw_ctrl2, ctrl2);
-}
-
-#define IDE_ARCH_ACK_INTR
-#define ide_ack_intr(hwif) ((hwif)->ack_intr(hwif))
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASMCRIS_IDE_H */
diff --git a/include/asm-cris/arch-v32/ptrace.h b/include/asm-cris/arch-v32/ptrace.h
index 516cc7062d9..41f4e8662bc 100644
--- a/include/asm-cris/arch-v32/ptrace.h
+++ b/include/asm-cris/arch-v32/ptrace.h
@@ -106,9 +106,13 @@ struct switch_stack {
unsigned long return_ip; /* ip that _resume will return to */
};
+#ifdef __KERNEL__
+
#define user_mode(regs) (((regs)->ccs & (1 << (U_CCS_BITNR + CCS_SHIFT))) != 0)
#define instruction_pointer(regs) ((regs)->erp)
extern void show_regs(struct pt_regs *);
#define profile_pc(regs) instruction_pointer(regs)
+#endif /* __KERNEL__ */
+
#endif
diff --git a/include/asm-cris/cacheflush.h b/include/asm-cris/cacheflush.h
index 01af2de27c5..cf60e3f69f8 100644
--- a/include/asm-cris/cacheflush.h
+++ b/include/asm-cris/cacheflush.h
@@ -26,7 +26,6 @@
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
memcpy(dst, src, len)
-void global_flush_tlb(void);
int change_page_attr(struct page *page, int numpages, pgprot_t prot);
#endif /* _CRIS_CACHEFLUSH_H */
diff --git a/include/asm-cris/ide.h b/include/asm-cris/ide.h
deleted file mode 100644
index a894f66665f..00000000000
--- a/include/asm-cris/ide.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm/arch/ide.h>
diff --git a/include/asm-cris/kvm.h b/include/asm-cris/kvm.h
deleted file mode 100644
index c860f51149f..00000000000
--- a/include/asm-cris/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_CRIS_H
-#define __LINUX_KVM_CRIS_H
-
-/* cris does not support KVM */
-
-#endif
diff --git a/include/asm-cris/page.h b/include/asm-cris/page.h
index c45bb1ef397..d19272ba6b6 100644
--- a/include/asm-cris/page.h
+++ b/include/asm-cris/page.h
@@ -60,9 +60,6 @@ typedef struct page *pgtable_t;
#define page_to_phys(page) __pa((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
#ifndef __ASSEMBLY__
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-cris/ptrace.h b/include/asm-cris/ptrace.h
index 1ec69a7ea83..d910925e317 100644
--- a/include/asm-cris/ptrace.h
+++ b/include/asm-cris/ptrace.h
@@ -4,11 +4,13 @@
#include <asm/arch/ptrace.h>
#ifdef __KERNEL__
+
/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
#define PTRACE_GETREGS 12
#define PTRACE_SETREGS 13
-#endif
#define profile_pc(regs) instruction_pointer(regs)
+#endif /* __KERNEL__ */
+
#endif /* _CRIS_PTRACE_H */
diff --git a/include/asm-cris/semaphore.h b/include/asm-cris/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-cris/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-cris/thread_info.h b/include/asm-cris/thread_info.h
index 784668ab0fa..7efe1000f99 100644
--- a/include/asm-cris/thread_info.h
+++ b/include/asm-cris/thread_info.h
@@ -11,6 +11,8 @@
#ifdef __KERNEL__
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
#ifndef __ASSEMBLY__
#include <asm/types.h>
#include <asm/processor.h>
diff --git a/include/asm-frv/Kbuild b/include/asm-frv/Kbuild
index bc3f12c5b7e..0f8956def73 100644
--- a/include/asm-frv/Kbuild
+++ b/include/asm-frv/Kbuild
@@ -3,4 +3,3 @@ include include/asm-generic/Kbuild.asm
header-y += registers.h
unifdef-y += termios.h
-unifdef-y += ptrace.h
diff --git a/include/asm-frv/ide.h b/include/asm-frv/ide.h
index 8c9a540d434..7ebcc56a222 100644
--- a/include/asm-frv/ide.h
+++ b/include/asm-frv/ide.h
@@ -18,10 +18,6 @@
#include <asm/io.h>
#include <asm/irq.h>
-#ifndef MAX_HWIFS
-#define MAX_HWIFS 8
-#endif
-
/****************************************************************************/
/*
* some bits needed for parts of the IDE subsystem to compile
diff --git a/include/asm-frv/kvm.h b/include/asm-frv/kvm.h
deleted file mode 100644
index 9c8a4f08d0a..00000000000
--- a/include/asm-frv/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_FRV_H
-#define __LINUX_KVM_FRV_H
-
-/* frv does not support KVM */
-
-#endif
diff --git a/include/asm-frv/page.h b/include/asm-frv/page.h
index c2c1e89e747..bd9c220094c 100644
--- a/include/asm-frv/page.h
+++ b/include/asm-frv/page.h
@@ -40,9 +40,6 @@ typedef struct page *pgtable_t;
#define __pgprot(x) ((pgprot_t) { (x) } )
#define PTE_MASK PAGE_MASK
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-
#define devmem_is_allowed(pfn) 1
#define __pa(vaddr) virt_to_phys((void *) (unsigned long) (vaddr))
diff --git a/include/asm-frv/semaphore.h b/include/asm-frv/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-frv/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-frv/thread_info.h b/include/asm-frv/thread_info.h
index 348b8f1df17..b7ac6bf2844 100644
--- a/include/asm-frv/thread_info.h
+++ b/include/asm-frv/thread_info.h
@@ -82,6 +82,8 @@ register struct thread_info *__current_thread_info asm("gr15");
#define current_thread_info() ({ __current_thread_info; })
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
/* thread information allocation */
#ifdef CONFIG_DEBUG_STACK_USAGE
#define alloc_thread_info(tsk) \
diff --git a/include/asm-generic/Kbuild.asm b/include/asm-generic/Kbuild.asm
index 7cd25b8e7c9..1170dc60e63 100644
--- a/include/asm-generic/Kbuild.asm
+++ b/include/asm-generic/Kbuild.asm
@@ -1,4 +1,6 @@
+ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/kvm.h),)
header-y += kvm.h
+endif
ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/a.out.h),)
unifdef-y += a.out.h
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index 2632328d864..a3f738cffdb 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -34,9 +34,14 @@ struct bug_entry {
#ifndef __WARN
#ifndef __ASSEMBLY__
extern void warn_on_slowpath(const char *file, const int line);
+extern void warn_slowpath(const char *file, const int line,
+ const char *fmt, ...) __attribute__((format(printf, 3, 4)));
#define WANT_WARN_ON_SLOWPATH
#endif
#define __WARN() warn_on_slowpath(__FILE__, __LINE__)
+#define __WARN_printf(arg...) warn_slowpath(__FILE__, __LINE__, arg)
+#else
+#define __WARN_printf(arg...) __WARN()
#endif
#ifndef WARN_ON
@@ -48,6 +53,15 @@ extern void warn_on_slowpath(const char *file, const int line);
})
#endif
+#ifndef WARN
+#define WARN(condition, format...) ({ \
+ int __ret_warn_on = !!(condition); \
+ if (unlikely(__ret_warn_on)) \
+ __WARN_printf(format); \
+ unlikely(__ret_warn_on); \
+})
+#endif
+
#else /* !CONFIG_BUG */
#ifndef HAVE_ARCH_BUG
#define BUG()
@@ -63,6 +77,14 @@ extern void warn_on_slowpath(const char *file, const int line);
unlikely(__ret_warn_on); \
})
#endif
+
+#ifndef WARN
+#define WARN(condition, format...) ({ \
+ int __ret_warn_on = !!(condition); \
+ unlikely(__ret_warn_on); \
+})
+#endif
+
#endif
#define WARN_ON_ONCE(condition) ({ \
@@ -75,6 +97,9 @@ extern void warn_on_slowpath(const char *file, const int line);
unlikely(__ret_warn_once); \
})
+#define WARN_ON_RATELIMIT(condition, state) \
+ WARN_ON((condition) && __ratelimit(state))
+
#ifdef CONFIG_SMP
# define WARN_ON_SMP(x) WARN_ON(x)
#else
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 6be061d09da..a3034d20ebd 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -3,7 +3,7 @@
#include <linux/types.h>
-#ifdef CONFIG_HAVE_GPIO_LIB
+#ifdef CONFIG_GPIOLIB
#include <linux/compiler.h>
@@ -32,6 +32,8 @@ struct module;
/**
* struct gpio_chip - abstract a GPIO controller
* @label: for diagnostics
+ * @dev: optional device providing the GPIOs
+ * @owner: helps prevent removal of modules exporting active GPIOs
* @direction_input: configures signal "offset" as input, or returns error
* @get: returns value for signal "offset"; for output signals this
* returns either the value actually sensed, or zero
@@ -59,6 +61,7 @@ struct module;
*/
struct gpio_chip {
char *label;
+ struct device *dev;
struct module *owner;
int (*direction_input)(struct gpio_chip *chip,
@@ -74,6 +77,7 @@ struct gpio_chip {
int base;
u16 ngpio;
unsigned can_sleep:1;
+ unsigned exported:1;
};
extern const char *gpiochip_is_requested(struct gpio_chip *chip,
@@ -108,7 +112,18 @@ extern void __gpio_set_value(unsigned gpio, int value);
extern int __gpio_cansleep(unsigned gpio);
-#else
+#ifdef CONFIG_GPIO_SYSFS
+
+/*
+ * A sysfs interface can be exported by individual drivers if they want,
+ * but more typically is configured entirely from userspace.
+ */
+extern int gpio_export(unsigned gpio, bool direction_may_change);
+extern void gpio_unexport(unsigned gpio);
+
+#endif /* CONFIG_GPIO_SYSFS */
+
+#else /* !CONFIG_HAVE_GPIO_LIB */
static inline int gpio_is_valid(int number)
{
@@ -137,6 +152,20 @@ static inline void gpio_set_value_cansleep(unsigned gpio, int value)
gpio_set_value(gpio, value);
}
-#endif
+#endif /* !CONFIG_HAVE_GPIO_LIB */
+
+#ifndef CONFIG_GPIO_SYSFS
+
+/* sysfs support is only available with gpiolib, where it's optional */
+
+static inline int gpio_export(unsigned gpio, bool direction_may_change)
+{
+ return -ENOSYS;
+}
+
+static inline void gpio_unexport(unsigned gpio)
+{
+}
+#endif /* CONFIG_GPIO_SYSFS */
#endif /* _ASM_GENERIC_GPIO_H */
diff --git a/include/asm-generic/int-ll64.h b/include/asm-generic/int-ll64.h
index 260948905e4..f9bc9ac29b3 100644
--- a/include/asm-generic/int-ll64.h
+++ b/include/asm-generic/int-ll64.h
@@ -26,7 +26,7 @@ typedef unsigned int __u32;
#ifdef __GNUC__
__extension__ typedef __signed__ long long __s64;
__extension__ typedef unsigned long long __u64;
-#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#else
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
#endif
diff --git a/include/asm-h8300/elf.h b/include/asm-h8300/elf.h
index 26bfc7e641d..a8b57d1f412 100644
--- a/include/asm-h8300/elf.h
+++ b/include/asm-h8300/elf.h
@@ -26,10 +26,10 @@ typedef unsigned long elf_fpregset_t;
#define ELF_DATA ELFDATA2MSB
#define ELF_ARCH EM_H8_300
#if defined(__H8300H__)
-#define ELF_FLAGS 0x810000
+#define ELF_CORE_EFLAGS 0x810000
#endif
#if defined(__H8300S__)
-#define ELF_FLAGS 0x820000
+#define ELF_CORE_EFLAGS 0x820000
#endif
#define ELF_PLAT_INIT(_r) _r->er1 = 0
diff --git a/include/asm-h8300/ide.h b/include/asm-h8300/ide.h
deleted file mode 100644
index f8535ce7476..00000000000
--- a/include/asm-h8300/ide.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/****************************************************************************/
-
-/*
- * linux/include/asm-h8300/ide.h
- *
- * Copyright (C) 1994-1996 Linus Torvalds & authors
- * Copyright (C) 2001 Lineo Inc., davidm@snapgear.com
- * Copyright (C) 2002 Greg Ungerer (gerg@snapgear.com)
- * Copyright (C) 2002 Yoshinori Sato (ysato@users.sourceforge.jp)
- */
-
-/****************************************************************************/
-#ifndef _H8300_IDE_H
-#define _H8300_IDE_H
-/****************************************************************************/
-#ifdef __KERNEL__
-/****************************************************************************/
-
-#define MAX_HWIFS 1
-
-#include <asm-generic/ide_iops.h>
-
-/****************************************************************************/
-#endif /* __KERNEL__ */
-#endif /* _H8300_IDE_H */
-/****************************************************************************/
diff --git a/include/asm-h8300/keyboard.h b/include/asm-h8300/keyboard.h
deleted file mode 100644
index 90efbd65539..00000000000
--- a/include/asm-h8300/keyboard.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * linux/include/asm-h8300/keyboard.h
- * Created 04 Dec 2001 by Khaled Hassounah <khassounah@mediumware.net>
- * This file contains the Dragonball architecture specific keyboard definitions
- */
-
-#ifndef _H8300_KEYBOARD_H
-#define _H8300_KEYBOARD_H
-
-
-/* dummy i.e. no real keyboard */
-#define kbd_setkeycode(x...) (-ENOSYS)
-#define kbd_getkeycode(x...) (-ENOSYS)
-#define kbd_translate(x...) (0)
-#define kbd_unexpected_up(x...) (1)
-#define kbd_leds(x...) do {;} while (0)
-#define kbd_init_hw(x...) do {;} while (0)
-#define kbd_enable_irq(x...) do {;} while (0)
-#define kbd_disable_irq(x...) do {;} while (0)
-
-#endif /* _H8300_KEYBOARD_H */
-
-
-
diff --git a/include/asm-h8300/kvm.h b/include/asm-h8300/kvm.h
deleted file mode 100644
index bdbed7b987e..00000000000
--- a/include/asm-h8300/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_H8300_H
-#define __LINUX_KVM_H8300_H
-
-/* h8300 does not support KVM */
-
-#endif
diff --git a/include/asm-h8300/page.h b/include/asm-h8300/page.h
index d6a3eaf3b27..0b6acf0b03a 100644
--- a/include/asm-h8300/page.h
+++ b/include/asm-h8300/page.h
@@ -43,9 +43,6 @@ typedef struct page *pgtable_t;
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
extern unsigned long memory_start;
extern unsigned long memory_end;
diff --git a/include/asm-h8300/semaphore.h b/include/asm-h8300/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-h8300/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-h8300/thread_info.h b/include/asm-h8300/thread_info.h
index 27bb95e2944..aafd4d322ec 100644
--- a/include/asm-h8300/thread_info.h
+++ b/include/asm-h8300/thread_info.h
@@ -49,6 +49,7 @@ struct thread_info {
/*
* Size of kernel stack for each process. This must be a power of 2...
*/
+#define THREAD_SIZE_ORDER 1
#define THREAD_SIZE 8192 /* 2 pages */
@@ -65,10 +66,6 @@ static inline struct thread_info *current_thread_info(void)
return ti;
}
-/* thread information allocation */
-#define alloc_thread_info(tsk) ((struct thread_info *) \
- __get_free_pages(GFP_KERNEL, 1))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
#endif /* __ASSEMBLY__ */
/*
diff --git a/include/asm-ia64/hugetlb.h b/include/asm-ia64/hugetlb.h
index f28a9701f1c..da55c63728e 100644
--- a/include/asm-ia64/hugetlb.h
+++ b/include/asm-ia64/hugetlb.h
@@ -4,11 +4,12 @@
#include <asm/page.h>
-void hugetlb_free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
+void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
unsigned long end, unsigned long floor,
unsigned long ceiling);
-int prepare_hugepage_range(unsigned long addr, unsigned long len);
+int prepare_hugepage_range(struct file *file,
+ unsigned long addr, unsigned long len);
static inline int is_hugepage_only_range(struct mm_struct *mm,
unsigned long addr,
diff --git a/include/asm-ia64/ide.h b/include/asm-ia64/ide.h
deleted file mode 100644
index 8fa3f8cd067..00000000000
--- a/include/asm-ia64/ide.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * linux/include/asm-ia64/ide.h
- *
- * Copyright (C) 1994-1996 Linus Torvalds & authors
- */
-
-/*
- * This file contains the ia64 architecture specific IDE code.
- */
-
-#ifndef __ASM_IA64_IDE_H
-#define __ASM_IA64_IDE_H
-
-#ifdef __KERNEL__
-
-
-#include <linux/irq.h>
-
-static inline int ide_default_irq(unsigned long base)
-{
- switch (base) {
- case 0x1f0: return isa_irq_to_vector(14);
- case 0x170: return isa_irq_to_vector(15);
- case 0x1e8: return isa_irq_to_vector(11);
- case 0x168: return isa_irq_to_vector(10);
- case 0x1e0: return isa_irq_to_vector(8);
- case 0x160: return isa_irq_to_vector(12);
- default:
- return 0;
- }
-}
-
-static inline unsigned long ide_default_io_base(int index)
-{
- switch (index) {
- case 0: return 0x1f0;
- case 1: return 0x170;
- case 2: return 0x1e8;
- case 3: return 0x168;
- case 4: return 0x1e0;
- case 5: return 0x160;
- default:
- return 0;
- }
-}
-
-#include <asm-generic/ide_iops.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASM_IA64_IDE_H */
diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h
index 36f39321b76..5f271bc712e 100644
--- a/include/asm-ia64/page.h
+++ b/include/asm-ia64/page.h
@@ -40,7 +40,6 @@
#define PAGE_SIZE (__IA64_UL_CONST(1) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE - 1))
-#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
#define PERCPU_PAGE_SHIFT 16 /* log2() of max. size of per-CPU area */
#define PERCPU_PAGE_SIZE (__IA64_UL_CONST(1) << PERCPU_PAGE_SHIFT)
diff --git a/include/asm-ia64/semaphore.h b/include/asm-ia64/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-ia64/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index 2422ac61658..7c60fcdd2ef 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -54,6 +54,8 @@ struct thread_info {
}, \
}
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
#ifndef ASM_OFFSETS_C
/* how to get the thread information struct from C */
#define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE))
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
index e6031471612..d535833aab5 100644
--- a/include/asm-ia64/unistd.h
+++ b/include/asm-ia64/unistd.h
@@ -302,11 +302,17 @@
#define __NR_timerfd_create 1310
#define __NR_timerfd_settime 1311
#define __NR_timerfd_gettime 1312
+#define __NR_signalfd4 1313
+#define __NR_eventfd2 1314
+#define __NR_epoll_create1 1315
+#define __NR_dup3 1316
+#define __NR_pipe2 1317
+#define __NR_inotify_init1 1318
#ifdef __KERNEL__
-#define NR_syscalls 289 /* length of syscall table */
+#define NR_syscalls 295 /* length of syscall table */
/*
* The following defines stop scripts/checksyscalls.sh from complaining about
diff --git a/include/asm-m32r/ide.h b/include/asm-m32r/ide.h
deleted file mode 100644
index 1e7f6474d13..00000000000
--- a/include/asm-m32r/ide.h
+++ /dev/null
@@ -1,70 +0,0 @@
-#ifndef _ASM_M32R_IDE_H
-#define _ASM_M32R_IDE_H
-
-/*
- * linux/include/asm-m32r/ide.h
- *
- * Copyright (C) 1994-1996 Linus Torvalds & authors
- */
-
-/*
- * This file contains the i386 architecture specific IDE code.
- */
-
-#ifdef __KERNEL__
-
-#include <asm/m32r.h>
-
-#ifndef MAX_HWIFS
-# ifdef CONFIG_BLK_DEV_IDEPCI
-#define MAX_HWIFS 10
-# else
-#define MAX_HWIFS 2
-# endif
-#endif
-
-static __inline__ int ide_default_irq(unsigned long base)
-{
- switch (base) {
-#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) \
- || defined(CONFIG_PLAT_OPSPUT)
- case 0x1f0: return PLD_IRQ_CFIREQ;
- default:
- return 0;
-#elif defined(CONFIG_PLAT_MAPPI3)
- case 0x1f0: return PLD_IRQ_CFIREQ;
- case 0x170: return PLD_IRQ_IDEIREQ;
- default:
- return 0;
-#else
- case 0x1f0: return 14;
- case 0x170: return 15;
- case 0x1e8: return 11;
- case 0x168: return 10;
- case 0x1e0: return 8;
- case 0x160: return 12;
- default:
- return 0;
-#endif
- }
-}
-
-static __inline__ unsigned long ide_default_io_base(int index)
-{
- switch (index) {
- case 0: return 0x1f0;
- case 1: return 0x170;
- case 2: return 0x1e8;
- case 3: return 0x168;
- case 4: return 0x1e0;
- case 5: return 0x160;
- default:
- return 0;
- }
-}
-
-#include <asm-generic/ide_iops.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_M32R_IDE_H */
diff --git a/include/asm-m32r/kvm.h b/include/asm-m32r/kvm.h
deleted file mode 100644
index 99a40515b77..00000000000
--- a/include/asm-m32r/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_M32R_H
-#define __LINUX_KVM_M32R_H
-
-/* m32r does not support KVM */
-
-#endif
diff --git a/include/asm-m32r/page.h b/include/asm-m32r/page.h
index 8a677f3fca6..c9333089fe1 100644
--- a/include/asm-m32r/page.h
+++ b/include/asm-m32r/page.h
@@ -41,9 +41,6 @@ typedef struct page *pgtable_t;
#endif /* !__ASSEMBLY__ */
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-
/*
* This handles the memory map.. We could make this a config
* option, but too many people screw it up, and too few need
diff --git a/include/asm-m32r/semaphore.h b/include/asm-m32r/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-m32r/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-m32r/thread_info.h b/include/asm-m32r/thread_info.h
index 1effcd0f5e6..8589d462df2 100644
--- a/include/asm-m32r/thread_info.h
+++ b/include/asm-m32r/thread_info.h
@@ -94,6 +94,8 @@ static inline struct thread_info *current_thread_info(void)
return ti;
}
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
/* thread information allocation */
#ifdef CONFIG_DEBUG_STACK_USAGE
#define alloc_thread_info(tsk) \
diff --git a/include/asm-m68k/dvma.h b/include/asm-m68k/dvma.h
index 4fff408d015..890bbf7e775 100644
--- a/include/asm-m68k/dvma.h
+++ b/include/asm-m68k/dvma.h
@@ -13,7 +13,7 @@
#define DVMA_PAGE_SHIFT 13
#define DVMA_PAGE_SIZE (1UL << DVMA_PAGE_SHIFT)
#define DVMA_PAGE_MASK (~(DVMA_PAGE_SIZE-1))
-#define DVMA_PAGE_ALIGN(addr) (((addr)+DVMA_PAGE_SIZE-1)&DVMA_PAGE_MASK)
+#define DVMA_PAGE_ALIGN(addr) ALIGN(addr, DVMA_PAGE_SIZE)
extern void dvma_init(void);
extern int dvma_map_iommu(unsigned long kaddr, unsigned long baddr,
diff --git a/include/asm-m68k/ide.h b/include/asm-m68k/ide.h
index 909c6dfd385..1daf6cbdd9f 100644
--- a/include/asm-m68k/ide.h
+++ b/include/asm-m68k/ide.h
@@ -45,10 +45,6 @@
#include <asm/macints.h>
#endif
-#ifndef MAX_HWIFS
-#define MAX_HWIFS 4 /* same as the other archs */
-#endif
-
/*
* Get rid of defs from io.h - ide has its private and conflicting versions
* Since so far no single m68k platform uses ISA/PCI I/O space for IDE, we
diff --git a/include/asm-m68k/kvm.h b/include/asm-m68k/kvm.h
deleted file mode 100644
index 7ed27fce524..00000000000
--- a/include/asm-m68k/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_M68K_H
-#define __LINUX_KVM_M68K_H
-
-/* m68k does not support KVM */
-
-#endif
diff --git a/include/asm-m68k/page.h b/include/asm-m68k/page.h
index 880c2cbff8a..a34b8bad784 100644
--- a/include/asm-m68k/page.h
+++ b/include/asm-m68k/page.h
@@ -103,9 +103,6 @@ typedef struct page *pgtable_t;
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
#endif /* !__ASSEMBLY__ */
#include <asm/page_offset.h>
diff --git a/include/asm-m68k/semaphore.h b/include/asm-m68k/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-m68k/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-m68k/thread_info.h b/include/asm-m68k/thread_info.h
index d635a375248..abc002798a2 100644
--- a/include/asm-m68k/thread_info.h
+++ b/include/asm-m68k/thread_info.h
@@ -25,13 +25,7 @@ struct thread_info {
}
/* THREAD_SIZE should be 8k, so handle differently for 4k and 8k machines */
-#if PAGE_SHIFT == 13 /* 8k machines */
-#define alloc_thread_info(tsk) ((struct thread_info *)__get_free_pages(GFP_KERNEL,0))
-#define free_thread_info(ti) free_pages((unsigned long)(ti),0)
-#else /* otherwise assume 4k pages */
-#define alloc_thread_info(tsk) ((struct thread_info *)__get_free_pages(GFP_KERNEL,1))
-#define free_thread_info(ti) free_pages((unsigned long)(ti),1)
-#endif /* PAGE_SHIFT == 13 */
+#define THREAD_SIZE_ORDER (13 - PAGE_SHIFT)
#define init_thread_info (init_task.thread.info)
#define init_stack (init_thread_union.stack)
diff --git a/include/asm-m68knommu/bitops.h b/include/asm-m68knommu/bitops.h
index c142fbf2f37..6f3685eab44 100644
--- a/include/asm-m68knommu/bitops.h
+++ b/include/asm-m68knommu/bitops.h
@@ -14,8 +14,38 @@
#error only <linux/bitops.h> can be included directly
#endif
+#if defined (__mcfisaaplus__) || defined (__mcfisac__)
+static inline int ffs(unsigned int val)
+{
+ if (!val)
+ return 0;
+
+ asm volatile(
+ "bitrev %0\n\t"
+ "ff1 %0\n\t"
+ : "=d" (val)
+ : "0" (val)
+ );
+ val++;
+ return val;
+}
+
+static inline int __ffs(unsigned int val)
+{
+ asm volatile(
+ "bitrev %0\n\t"
+ "ff1 %0\n\t"
+ : "=d" (val)
+ : "0" (val)
+ );
+ return val;
+}
+
+#else
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/__ffs.h>
+#endif
+
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/ffz.h>
diff --git a/include/asm-m68knommu/byteorder.h b/include/asm-m68knommu/byteorder.h
index 8fcde907b0f..20bb4426b61 100644
--- a/include/asm-m68knommu/byteorder.h
+++ b/include/asm-m68knommu/byteorder.h
@@ -1,13 +1,27 @@
#ifndef _M68KNOMMU_BYTEORDER_H
#define _M68KNOMMU_BYTEORDER_H
-#include <asm/types.h>
+#include <linux/types.h>
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
# define __BYTEORDER_HAS_U64__
# define __SWAB_64_THRU_32__
#endif
+#if defined (__mcfisaaplus__) || defined (__mcfisac__)
+static inline __attribute_const__ __u32 ___arch__swab32(__u32 val)
+{
+ asm(
+ "byterev %0"
+ : "=d" (val)
+ : "0" (val)
+ );
+ return val;
+}
+
+#define __arch__swab32(x) ___arch__swab32(x)
+#endif
+
#include <linux/byteorder/big_endian.h>
#endif /* _M68KNOMMU_BYTEORDER_H */
diff --git a/include/asm-m68knommu/commproc.h b/include/asm-m68knommu/commproc.h
index 36e870b468e..edf5eb6c08d 100644
--- a/include/asm-m68knommu/commproc.h
+++ b/include/asm-m68knommu/commproc.h
@@ -519,25 +519,6 @@ typedef struct scc_enet {
#define SICR_ENET_CLKRT ((uint)0x00002c00)
#endif
-#ifdef CONFIG_RPXCLASSIC
-/* Bits in parallel I/O port registers that have to be set/cleared
- * to configure the pins for SCC1 use.
- */
-#define PA_ENET_RXD ((ushort)0x0001)
-#define PA_ENET_TXD ((ushort)0x0002)
-#define PA_ENET_TCLK ((ushort)0x0200)
-#define PA_ENET_RCLK ((ushort)0x0800)
-#define PB_ENET_TENA ((uint)0x00001000)
-#define PC_ENET_CLSN ((ushort)0x0010)
-#define PC_ENET_RENA ((ushort)0x0020)
-
-/* Control bits in the SICR to route TCLK (CLK2) and RCLK (CLK4) to
- * SCC1. Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero.
- */
-#define SICR_ENET_MASK ((uint)0x000000ff)
-#define SICR_ENET_CLKRT ((uint)0x0000003d)
-#endif
-
/* SCC Event register as used by Ethernet.
*/
#define SCCE_ENET_GRA ((ushort)0x0080) /* Graceful stop complete */
diff --git a/include/asm-m68knommu/kvm.h b/include/asm-m68knommu/kvm.h
deleted file mode 100644
index b49d4258dab..00000000000
--- a/include/asm-m68knommu/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_M68KNOMMU_H
-#define __LINUX_KVM_M68KNOMMU_H
-
-/* m68knommu does not support KVM */
-
-#endif
diff --git a/include/asm-m68knommu/page.h b/include/asm-m68knommu/page.h
index 1e82ebb7d64..3a1ede4544c 100644
--- a/include/asm-m68knommu/page.h
+++ b/include/asm-m68knommu/page.h
@@ -43,9 +43,6 @@ typedef struct page *pgtable_t;
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
extern unsigned long memory_start;
extern unsigned long memory_end;
diff --git a/include/asm-m68knommu/ptrace.h b/include/asm-m68knommu/ptrace.h
index 47258e86e8c..8c9194b9854 100644
--- a/include/asm-m68knommu/ptrace.h
+++ b/include/asm-m68knommu/ptrace.h
@@ -68,10 +68,8 @@ struct switch_stack {
/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
#define PTRACE_GETREGS 12
#define PTRACE_SETREGS 13
-#ifdef CONFIG_FPU
#define PTRACE_GETFPREGS 14
#define PTRACE_SETFPREGS 15
-#endif
#ifdef __KERNEL__
diff --git a/include/asm-m68knommu/semaphore.h b/include/asm-m68knommu/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-m68knommu/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-m68knommu/system.h b/include/asm-m68knommu/system.h
index 64c64432bbb..40f49de6982 100644
--- a/include/asm-m68knommu/system.h
+++ b/include/asm-m68knommu/system.h
@@ -118,6 +118,8 @@ asmlinkage void resume(void);
#define smp_read_barrier_depends() do { } while(0)
#endif
+#define read_barrier_depends() ((void)0)
+
#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
struct __xchg_dummy { unsigned long a[100]; };
@@ -310,4 +312,13 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
#endif
#define arch_align_stack(x) (x)
+
+static inline int irqs_disabled_flags(unsigned long flags)
+{
+ if (flags & 0x0700)
+ return 0;
+ else
+ return 1;
+}
+
#endif /* _M68KNOMMU_SYSTEM_H */
diff --git a/include/asm-m68knommu/thread_info.h b/include/asm-m68knommu/thread_info.h
index 95996d978be..0c9bc095f3f 100644
--- a/include/asm-m68knommu/thread_info.h
+++ b/include/asm-m68knommu/thread_info.h
@@ -71,10 +71,6 @@ static inline struct thread_info *current_thread_info(void)
return ti;
}
-/* thread information allocation */
-#define alloc_thread_info(tsk) ((struct thread_info *) \
- __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_SIZE_ORDER)
#endif /* __ASSEMBLY__ */
#define PREEMPT_ACTIVE 0x4000000
diff --git a/include/asm-mips/kvm.h b/include/asm-mips/kvm.h
deleted file mode 100644
index 093a5b7f796..00000000000
--- a/include/asm-mips/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_MIPS_H
-#define __LINUX_KVM_MIPS_H
-
-/* mips does not support KVM */
-
-#endif
diff --git a/include/asm-mips/mach-au1x00/au1550_spi.h b/include/asm-mips/mach-au1x00/au1550_spi.h
index 40e6c489833..08e1958e941 100644
--- a/include/asm-mips/mach-au1x00/au1550_spi.h
+++ b/include/asm-mips/mach-au1x00/au1550_spi.h
@@ -6,7 +6,6 @@
#define _AU1550_SPI_H_
struct au1550_spi_info {
- s16 bus_num; /* defines which PSC and IRQ to use */
u32 mainclk_hz; /* main input clock frequency of PSC */
u16 num_chipselect; /* number of chipselects supported */
void (*activate_cs)(struct au1550_spi_info *spi, int cs, int polarity);
diff --git a/include/asm-mips/mach-generic/gpio.h b/include/asm-mips/mach-generic/gpio.h
index e6b376bd9d0..b4e70208da6 100644
--- a/include/asm-mips/mach-generic/gpio.h
+++ b/include/asm-mips/mach-generic/gpio.h
@@ -1,7 +1,7 @@
#ifndef __ASM_MACH_GENERIC_GPIO_H
#define __ASM_MACH_GENERIC_GPIO_H
-#ifdef CONFIG_HAVE_GPIO_LIB
+#ifdef CONFIG_GPIOLIB
#define gpio_get_value __gpio_get_value
#define gpio_set_value __gpio_set_value
#define gpio_cansleep __gpio_cansleep
diff --git a/include/asm-mips/mach-generic/ide.h b/include/asm-mips/mach-generic/ide.h
index 0f6c251f5fe..73008f7bdc9 100644
--- a/include/asm-mips/mach-generic/ide.h
+++ b/include/asm-mips/mach-generic/ide.h
@@ -19,14 +19,6 @@
#include <linux/stddef.h>
#include <asm/processor.h>
-#ifndef MAX_HWIFS
-# ifdef CONFIG_BLK_DEV_IDEPCI
-#define MAX_HWIFS 10
-# else
-#define MAX_HWIFS 6
-# endif
-#endif
-
static __inline__ int ide_probe_legacy(void)
{
#ifdef CONFIG_PCI
@@ -56,46 +48,6 @@ found:
#endif
}
-static __inline__ int ide_default_irq(unsigned long base)
-{
- switch (base) {
- case 0x1f0: return 14;
- case 0x170: return 15;
- case 0x1e8: return 11;
- case 0x168: return 10;
- case 0x1e0: return 8;
- case 0x160: return 12;
- default:
- return 0;
- }
-}
-
-static __inline__ unsigned long ide_default_io_base(int index)
-{
- if (!ide_probe_legacy())
- return 0;
- /*
- * If PCI is present then it is not safe to poke around
- * the other legacy IDE ports. Only 0x1f0 and 0x170 are
- * defined compatibility mode ports for PCI. A user can
- * override this using ide= but we must default safe.
- */
- if (no_pci_devices()) {
- switch (index) {
- case 2: return 0x1e8;
- case 3: return 0x168;
- case 4: return 0x1e0;
- case 5: return 0x160;
- }
- }
- switch (index) {
- case 0: return 0x1f0;
- case 1: return 0x170;
- default:
- return 0;
- }
-}
-
/* MIPS port and memory-mapped I/O string operations. */
static inline void __ide_flush_prologue(void)
{
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 494f00ba954..fe7a88ea066 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -137,9 +137,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#endif /* !__ASSEMBLY__ */
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-
/*
* __pa()/__va() should be used only during mem init.
*/
diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
index 58cbac5a64e..a1e4453469f 100644
--- a/include/asm-mips/processor.h
+++ b/include/asm-mips/processor.h
@@ -45,7 +45,7 @@ extern unsigned int vced_count, vcei_count;
* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
*/
-#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
+#define TASK_UNMAPPED_BASE ((TASK_SIZE / 3) & ~(PAGE_SIZE))
#endif
#ifdef CONFIG_64BIT
diff --git a/include/asm-mips/semaphore.h b/include/asm-mips/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-mips/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-mips/socket.h b/include/asm-mips/socket.h
index 63f60254d30..facc2d7a87c 100644
--- a/include/asm-mips/socket.h
+++ b/include/asm-mips/socket.h
@@ -102,6 +102,13 @@ enum sock_type {
};
#define SOCK_MAX (SOCK_PACKET + 1)
+/* Mask which covers at least up to SOCK_MASK-1. The
+ * * remaining bits are used as flags. */
+#define SOCK_TYPE_MASK 0xf
+
+/* Flags for socket, socketpair, paccept */
+#define SOCK_CLOEXEC O_CLOEXEC
+#define SOCK_NONBLOCK O_NONBLOCK
#define ARCH_HAS_SOCKET_TYPES 1
diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h
index b2772df1a1b..bb3060699df 100644
--- a/include/asm-mips/thread_info.h
+++ b/include/asm-mips/thread_info.h
@@ -82,6 +82,8 @@ register struct thread_info *__current_thread_info __asm__("$28");
#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
#define THREAD_MASK (THREAD_SIZE - 1UL)
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
#ifdef CONFIG_DEBUG_STACK_USAGE
#define alloc_thread_info(tsk) \
({ \
diff --git a/include/asm-mn10300/ide.h b/include/asm-mn10300/ide.h
index dc235121ec4..6adcdd92e83 100644
--- a/include/asm-mn10300/ide.h
+++ b/include/asm-mn10300/ide.h
@@ -23,10 +23,6 @@
#undef SUPPORT_VLB_SYNC
#define SUPPORT_VLB_SYNC 0
-#ifndef MAX_HWIFS
-#define MAX_HWIFS 8
-#endif
-
/*
* some bits needed for parts of the IDE subsystem to compile
*/
diff --git a/include/asm-mn10300/kvm.h b/include/asm-mn10300/kvm.h
deleted file mode 100644
index f6b609ff4a5..00000000000
--- a/include/asm-mn10300/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_MN10300_H
-#define __LINUX_KVM_MN10300_H
-
-/* mn10300 does not support KVM */
-
-#endif
diff --git a/include/asm-mn10300/page.h b/include/asm-mn10300/page.h
index 124971b9fb9..8288e124165 100644
--- a/include/asm-mn10300/page.h
+++ b/include/asm-mn10300/page.h
@@ -61,9 +61,6 @@ typedef struct page *pgtable_t;
#endif /* !__ASSEMBLY__ */
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-
/*
* This handles the memory map.. We could make this a config
* option, but too many people screw it up, and too few need
diff --git a/include/asm-mn10300/pci.h b/include/asm-mn10300/pci.h
index 205192c52bb..cd9cc5c89ce 100644
--- a/include/asm-mn10300/pci.h
+++ b/include/asm-mn10300/pci.h
@@ -74,15 +74,6 @@ struct pci_dev;
/* This is always fine. */
#define pci_dac_dma_supported(pci_dev, mask) (0)
-/*
- * These macros should be used after a pci_map_sg call has been done
- * to get bus addresses of each of the SG entries and their lengths.
- * You should only work with the number of sg entries pci_map_sg
- * returns.
- */
-#define sg_dma_address(sg) ((sg)->dma_address)
-#define sg_dma_len(sg) ((sg)->length)
-
/* Return the index of the PCI controller for device. */
static inline int pci_controller_num(struct pci_dev *dev)
{
diff --git a/include/asm-mn10300/ptrace.h b/include/asm-mn10300/ptrace.h
index b3684689fcc..7b06cc623d8 100644
--- a/include/asm-mn10300/ptrace.h
+++ b/include/asm-mn10300/ptrace.h
@@ -88,12 +88,16 @@ extern struct pt_regs *__frame; /* current frame pointer */
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
-#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#if defined(__KERNEL__)
+
+#if !defined(__ASSEMBLY__)
#define user_mode(regs) (((regs)->epsw & EPSW_nSL) == EPSW_nSL)
#define instruction_pointer(regs) ((regs)->pc)
extern void show_regs(struct pt_regs *);
-#endif
+#endif /* !__ASSEMBLY */
#define profile_pc(regs) ((regs)->pc)
+#endif /* __KERNEL__ */
+
#endif /* _ASM_PTRACE_H */
diff --git a/include/asm-mn10300/scatterlist.h b/include/asm-mn10300/scatterlist.h
index e29d91dbcf2..67535901b9f 100644
--- a/include/asm-mn10300/scatterlist.h
+++ b/include/asm-mn10300/scatterlist.h
@@ -43,4 +43,13 @@ struct scatterlist {
#define ISA_DMA_THRESHOLD (0x00ffffff)
+/*
+ * These macros should be used after a pci_map_sg call has been done
+ * to get bus addresses of each of the SG entries and their lengths.
+ * You should only work with the number of sg entries pci_map_sg
+ * returns.
+ */
+#define sg_dma_address(sg) ((sg)->dma_address)
+#define sg_dma_len(sg) ((sg)->length)
+
#endif /* _ASM_SCATTERLIST_H */
diff --git a/include/asm-mn10300/semaphore.h b/include/asm-mn10300/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-mn10300/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-mn10300/thread_info.h b/include/asm-mn10300/thread_info.h
index e397e719278..78a3881f3c1 100644
--- a/include/asm-mn10300/thread_info.h
+++ b/include/asm-mn10300/thread_info.h
@@ -112,6 +112,8 @@ static inline unsigned long current_stack_pointer(void)
return sp;
}
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
/* thread information allocation */
#ifdef CONFIG_DEBUG_STACK_USAGE
#define alloc_thread_info(tsk) kzalloc(THREAD_SIZE, GFP_KERNEL)
diff --git a/include/asm-parisc/ide.h b/include/asm-parisc/ide.h
index db0c9441009..c246ef75017 100644
--- a/include/asm-parisc/ide.h
+++ b/include/asm-parisc/ide.h
@@ -13,10 +13,6 @@
#ifdef __KERNEL__
-#ifndef MAX_HWIFS
-#define MAX_HWIFS 2
-#endif
-
#define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id))
#define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id))
#define ide_request_region(from,extent,name) request_region((from), (extent), (name))
diff --git a/include/asm-parisc/kvm.h b/include/asm-parisc/kvm.h
deleted file mode 100644
index 00cc4581254..00000000000
--- a/include/asm-parisc/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_PARISC_H
-#define __LINUX_KVM_PARISC_H
-
-/* parisc does not support KVM */
-
-#endif
diff --git a/include/asm-parisc/page.h b/include/asm-parisc/page.h
index 27d50b85954..c3941f09a87 100644
--- a/include/asm-parisc/page.h
+++ b/include/asm-parisc/page.h
@@ -119,10 +119,6 @@ extern int npmem_ranges;
#define PMD_ENTRY_SIZE (1UL << BITS_PER_PMD_ENTRY)
#define PTE_ENTRY_SIZE (1UL << BITS_PER_PTE_ENTRY)
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
-
#define LINUX_GATEWAY_SPACE 0
/* This governs the relationship between virtual and physical addresses.
diff --git a/include/asm-parisc/ptrace.h b/include/asm-parisc/ptrace.h
index 93f990e418f..3e94c5d85ff 100644
--- a/include/asm-parisc/ptrace.h
+++ b/include/asm-parisc/ptrace.h
@@ -33,7 +33,6 @@ struct pt_regs {
unsigned long ipsw; /* CR22 */
};
-#define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS))
/*
* The numbers chosen here are somewhat arbitrary but absolutely MUST
* not overlap with any of the number assigned in <linux/ptrace.h>.
@@ -43,8 +42,11 @@ struct pt_regs {
* since we have taken branch traps too)
*/
#define PTRACE_SINGLEBLOCK 12 /* resume execution until next branch */
+
#ifdef __KERNEL__
+#define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS))
+
/* XXX should we use iaoq[1] or iaoq[0] ? */
#define user_mode(regs) (((regs)->iaoq[0] & 3) ? 1 : 0)
#define user_space(regs) (((regs)->iasq[1] != 0) ? 1 : 0)
diff --git a/include/asm-parisc/semaphore.h b/include/asm-parisc/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-parisc/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-parisc/socket.h b/include/asm-parisc/socket.h
index 69a7a0d30b0..fba402c95ac 100644
--- a/include/asm-parisc/socket.h
+++ b/include/asm-parisc/socket.h
@@ -54,4 +54,9 @@
#define SO_MARK 0x401f
+/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
+ * have to define SOCK_NONBLOCK to a different value here.
+ */
+#define SOCK_NONBLOCK 0x40000000
+
#endif /* _ASM_SOCKET_H */
diff --git a/include/asm-parisc/thread_info.h b/include/asm-parisc/thread_info.h
index 2d9c7500867..9f812741c35 100644
--- a/include/asm-parisc/thread_info.h
+++ b/include/asm-parisc/thread_info.h
@@ -34,15 +34,11 @@ struct thread_info {
/* thread information allocation */
-#define THREAD_ORDER 2
+#define THREAD_SIZE_ORDER 2
/* Be sure to hunt all references to this down when you change the size of
* the kernel stack */
-#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
-#define THREAD_SHIFT (PAGE_SHIFT + THREAD_ORDER)
-
-#define alloc_thread_info(tsk) ((struct thread_info *) \
- __get_free_pages(GFP_KERNEL, THREAD_ORDER))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_ORDER)
+#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
+#define THREAD_SHIFT (PAGE_SHIFT + THREAD_SIZE_ORDER)
/* how to get the thread information struct from C */
#define current_thread_info() ((struct thread_info *)mfctl(30))
diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild
index 04ce8f8a2ee..5ab7d7fe198 100644
--- a/include/asm-powerpc/Kbuild
+++ b/include/asm-powerpc/Kbuild
@@ -29,7 +29,6 @@ unifdef-y += elf.h
unifdef-y += nvram.h
unifdef-y += param.h
unifdef-y += posix_types.h
-unifdef-y += ptrace.h
unifdef-y += seccomp.h
unifdef-y += signal.h
unifdef-y += spu_info.h
diff --git a/include/asm-powerpc/asm-compat.h b/include/asm-powerpc/asm-compat.h
index 8ec2e1da68b..8f0fe797194 100644
--- a/include/asm-powerpc/asm-compat.h
+++ b/include/asm-powerpc/asm-compat.h
@@ -22,6 +22,7 @@
#define PPC_STL stringify_in_c(std)
#define PPC_LCMPI stringify_in_c(cmpdi)
#define PPC_LONG stringify_in_c(.llong)
+#define PPC_LONG_ALIGN stringify_in_c(.balign 8)
#define PPC_TLNEI stringify_in_c(tdnei)
#define PPC_LLARX stringify_in_c(ldarx)
#define PPC_STLCX stringify_in_c(stdcx.)
@@ -43,6 +44,7 @@
#define PPC_STL stringify_in_c(stw)
#define PPC_LCMPI stringify_in_c(cmpwi)
#define PPC_LONG stringify_in_c(.long)
+#define PPC_LONG_ALIGN stringify_in_c(.balign 4)
#define PPC_TLNEI stringify_in_c(twnei)
#define PPC_LLARX stringify_in_c(lwarx)
#define PPC_STLCX stringify_in_c(stwcx.)
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index 2a3e9075a5a..ef8a248dfd5 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -127,6 +127,8 @@ extern struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr);
extern void do_feature_fixups(unsigned long value, void *fixup_start,
void *fixup_end);
+extern const char *powerpc_base_platform;
+
#endif /* __ASSEMBLY__ */
/* CPU kernel features */
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h
index 89664675b46..80d1f399ee5 100644
--- a/include/asm-powerpc/elf.h
+++ b/include/asm-powerpc/elf.h
@@ -217,6 +217,14 @@ typedef elf_vrregset_t elf_fpxregset_t;
#define ELF_PLATFORM (cur_cpu_spec->platform)
+/* While ELF_PLATFORM indicates the ISA supported by the platform, it
+ * may not accurately reflect the underlying behavior of the hardware
+ * (as in the case of running in Power5+ compatibility mode on a
+ * Power6 machine). ELF_BASE_PLATFORM allows ld.so to load libraries
+ * that are tuned for the real hardware.
+ */
+#define ELF_BASE_PLATFORM (powerpc_base_platform)
+
#ifdef __powerpc64__
# define ELF_PLAT_INIT(_r, load_addr) do { \
_r->gpr[2] = load_addr; \
diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h
index ef328995ba9..3a179827528 100644
--- a/include/asm-powerpc/firmware.h
+++ b/include/asm-powerpc/firmware.h
@@ -46,6 +46,7 @@
#define FW_FEATURE_PS3_LV1 ASM_CONST(0x0000000000800000)
#define FW_FEATURE_BEAT ASM_CONST(0x0000000001000000)
#define FW_FEATURE_BULK_REMOVE ASM_CONST(0x0000000002000000)
+#define FW_FEATURE_CMO ASM_CONST(0x0000000004000000)
#ifndef __ASSEMBLY__
@@ -58,7 +59,7 @@ enum {
FW_FEATURE_MIGRATE | FW_FEATURE_PERFMON | FW_FEATURE_CRQ |
FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN |
FW_FEATURE_BULK | FW_FEATURE_XDABR | FW_FEATURE_MULTITCE |
- FW_FEATURE_SPLPAR | FW_FEATURE_LPAR,
+ FW_FEATURE_SPLPAR | FW_FEATURE_LPAR | FW_FEATURE_CMO,
FW_FEATURE_PSERIES_ALWAYS = 0,
FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
diff --git a/include/asm-powerpc/gpio.h b/include/asm-powerpc/gpio.h
index 77ad3a890f3..ea04632399d 100644
--- a/include/asm-powerpc/gpio.h
+++ b/include/asm-powerpc/gpio.h
@@ -17,7 +17,7 @@
#include <linux/errno.h>
#include <asm-generic/gpio.h>
-#ifdef CONFIG_HAVE_GPIO_LIB
+#ifdef CONFIG_GPIOLIB
/*
* We don't (yet) implement inlined/rapid versions for on-chip gpios.
@@ -51,6 +51,6 @@ static inline int irq_to_gpio(unsigned int irq)
return -EINVAL;
}
-#endif /* CONFIG_HAVE_GPIO_LIB */
+#endif /* CONFIG_GPIOLIB */
#endif /* __ASM_POWERPC_GPIO_H */
diff --git a/include/asm-powerpc/hugetlb.h b/include/asm-powerpc/hugetlb.h
index be32ff02f4a..26f0d0ab27a 100644
--- a/include/asm-powerpc/hugetlb.h
+++ b/include/asm-powerpc/hugetlb.h
@@ -7,7 +7,7 @@
int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
unsigned long len);
-void hugetlb_free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
+void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
unsigned long end, unsigned long floor,
unsigned long ceiling);
@@ -21,11 +21,13 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
* If the arch doesn't supply something else, assume that hugepage
* size aligned regions are ok without further preparation.
*/
-static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+static inline int prepare_hugepage_range(struct file *file,
+ unsigned long addr, unsigned long len)
{
- if (len & ~HPAGE_MASK)
+ struct hstate *h = hstate_file(file);
+ if (len & ~huge_page_mask(h))
return -EINVAL;
- if (addr & ~HPAGE_MASK)
+ if (addr & ~huge_page_mask(h))
return -EINVAL;
return 0;
}
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h
index bf6cd7cb996..fbe2932fa9e 100644
--- a/include/asm-powerpc/hvcall.h
+++ b/include/asm-powerpc/hvcall.h
@@ -92,6 +92,11 @@
#define H_EXACT (1UL<<(63-24)) /* Use exact PTE or return H_PTEG_FULL */
#define H_R_XLATE (1UL<<(63-25)) /* include a valid logical page num in the pte if the valid bit is set */
#define H_READ_4 (1UL<<(63-26)) /* Return 4 PTEs */
+#define H_PAGE_STATE_CHANGE (1UL<<(63-28))
+#define H_PAGE_UNUSED ((1UL<<(63-29)) | (1UL<<(63-30)))
+#define H_PAGE_SET_UNUSED (H_PAGE_STATE_CHANGE | H_PAGE_UNUSED)
+#define H_PAGE_SET_LOANED (H_PAGE_SET_UNUSED | (1UL<<(63-31)))
+#define H_PAGE_SET_ACTIVE H_PAGE_STATE_CHANGE
#define H_AVPN (1UL<<(63-32)) /* An avpn is provided as a sanity test */
#define H_ANDCOND (1UL<<(63-33))
#define H_ICACHE_INVALIDATE (1UL<<(63-40)) /* icbi, etc. (ignored for IO pages) */
@@ -210,7 +215,9 @@
#define H_JOIN 0x298
#define H_VASI_STATE 0x2A4
#define H_ENABLE_CRQ 0x2B0
-#define MAX_HCALL_OPCODE H_ENABLE_CRQ
+#define H_SET_MPP 0x2D0
+#define H_GET_MPP 0x2D4
+#define MAX_HCALL_OPCODE H_GET_MPP
#ifndef __ASSEMBLY__
@@ -270,6 +277,20 @@ struct hcall_stats {
};
#define HCALL_STAT_ARRAY_SIZE ((MAX_HCALL_OPCODE >> 2) + 1)
+struct hvcall_mpp_data {
+ unsigned long entitled_mem;
+ unsigned long mapped_mem;
+ unsigned short group_num;
+ unsigned short pool_num;
+ unsigned char mem_weight;
+ unsigned char unallocated_mem_weight;
+ unsigned long unallocated_entitlement; /* value in bytes */
+ unsigned long pool_size;
+ signed long loan_request;
+ unsigned long backing_mem;
+};
+
+int h_get_mpp(struct hvcall_mpp_data *);
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_HVCALL_H */
diff --git a/include/asm-powerpc/ide.h b/include/asm-powerpc/ide.h
index 3d90bf7d3d7..1aaf27be874 100644
--- a/include/asm-powerpc/ide.h
+++ b/include/asm-powerpc/ide.h
@@ -14,14 +14,6 @@
#endif
#include <asm/io.h>
-#ifndef MAX_HWIFS
-#ifdef __powerpc64__
-#define MAX_HWIFS 10
-#else
-#define MAX_HWIFS 8
-#endif
-#endif
-
#define __ide_mm_insw(p, a, c) readsw((void __iomem *)(p), (a), (c))
#define __ide_mm_insl(p, a, c) readsl((void __iomem *)(p), (a), (c))
#define __ide_mm_outsw(p, a, c) writesw((void __iomem *)(p), (a), (c))
@@ -40,16 +32,6 @@ static __inline__ int ide_default_irq(unsigned long base)
case 0x170: return 15;
}
#endif
-#ifdef CONFIG_PPC_PREP
- switch (base) {
- case 0x1f0: return 13;
- case 0x170: return 13;
- case 0x1e8: return 11;
- case 0x168: return 10;
- case 0xfff0: return 14; /* MCP(N)750 ide0 */
- case 0xffe0: return 15; /* MCP(N)750 ide1 */
- }
-#endif
return 0;
}
@@ -62,14 +44,6 @@ static __inline__ unsigned long ide_default_io_base(int index)
case 1: return 0x170;
}
#endif
-#ifdef CONFIG_PPC_PREP
- switch (index) {
- case 0: return 0x1f0;
- case 1: return 0x170;
- case 2: return 0x1e8;
- case 3: return 0x168;
- }
-#endif
return 0;
}
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index 8b627823f5f..77c7fa025e6 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -617,7 +617,8 @@ static inline void iosync(void)
* and can be hooked by the platform via ppc_md
*
* * ioremap_flags allows to specify the page flags as an argument and can
- * also be hooked by the platform via ppc_md
+ * also be hooked by the platform via ppc_md. ioremap_prot is the exact
+ * same thing as ioremap_flags.
*
* * ioremap_nocache is identical to ioremap
*
@@ -639,6 +640,8 @@ extern void __iomem *ioremap(phys_addr_t address, unsigned long size);
extern void __iomem *ioremap_flags(phys_addr_t address, unsigned long size,
unsigned long flags);
#define ioremap_nocache(addr, size) ioremap((addr), (size))
+#define ioremap_prot(addr, size, prot) ioremap_flags((addr), (size), (prot))
+
extern void iounmap(volatile void __iomem *addr);
extern void __iomem *__ioremap(phys_addr_t, unsigned long size,
diff --git a/include/asm-powerpc/kgdb.h b/include/asm-powerpc/kgdb.h
index b617dac8296..1399caf719a 100644
--- a/include/asm-powerpc/kgdb.h
+++ b/include/asm-powerpc/kgdb.h
@@ -1,57 +1,65 @@
/*
- * kgdb.h: Defines and declarations for serial line source level
- * remote debugging of the Linux kernel using gdb.
+ * include/asm-powerpc/kgdb.h
*
+ * The PowerPC (32/64) specific defines / externs for KGDB. Based on
+ * the previous 32bit and 64bit specific files, which had the following
+ * copyrights:
+ *
+ * PPC64 Mods (C) 2005 Frank Rowand (frowand@mvista.com)
+ * PPC Mods (C) 2004 Tom Rini (trini@mvista.com)
+ * PPC Mods (C) 2003 John Whitney (john.whitney@timesys.com)
* PPC Mods (C) 1998 Michael Tesch (tesch@cs.wisc.edu)
*
+ *
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Author: Tom Rini <trini@kernel.crashing.org>
+ *
+ * 2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
*/
#ifdef __KERNEL__
-#ifndef _PPC_KGDB_H
-#define _PPC_KGDB_H
+#ifndef __POWERPC_KGDB_H__
+#define __POWERPC_KGDB_H__
#ifndef __ASSEMBLY__
-/* Things specific to the gen550 backend. */
-struct uart_port;
-
-extern void gen550_progress(char *, unsigned short);
-extern void gen550_kgdb_map_scc(void);
-extern void gen550_init(int, struct uart_port *);
-
-/* Things specific to the pmac backend. */
-extern void zs_kgdb_hook(int tty_num);
-
-/* To init the kgdb engine. (called by serial hook)*/
-extern void set_debug_traps(void);
-
-/* To enter the debugger explicitly. */
-extern void breakpoint(void);
-
-/* For taking exceptions
- * these are defined in traps.c
- */
-extern int (*debugger)(struct pt_regs *regs);
-extern int (*debugger_bpt)(struct pt_regs *regs);
-extern int (*debugger_sstep)(struct pt_regs *regs);
-extern int (*debugger_iabr_match)(struct pt_regs *regs);
-extern int (*debugger_dabr_match)(struct pt_regs *regs);
-extern void (*debugger_fault_handler)(struct pt_regs *regs);
-
-/* What we bring to the party */
-int kgdb_bpt(struct pt_regs *regs);
-int kgdb_sstep(struct pt_regs *regs);
-void kgdb(struct pt_regs *regs);
-int kgdb_iabr_match(struct pt_regs *regs);
-int kgdb_dabr_match(struct pt_regs *regs);
+#define BREAK_INSTR_SIZE 4
+#define BUFMAX ((NUMREGBYTES * 2) + 512)
+#define OUTBUFMAX ((NUMREGBYTES * 2) + 512)
+static inline void arch_kgdb_breakpoint(void)
+{
+ asm(".long 0x7d821008"); /* twge r2, r2 */
+}
+#define CACHE_FLUSH_IS_SAFE 1
+/* The number bytes of registers we have to save depends on a few
+ * things. For 64bit we default to not including vector registers and
+ * vector state registers. */
+#ifdef CONFIG_PPC64
/*
- * external low-level support routines (ie macserial.c)
+ * 64 bit (8 byte) registers:
+ * 32 gpr, 32 fpr, nip, msr, link, ctr
+ * 32 bit (4 byte) registers:
+ * ccr, xer, fpscr
*/
-extern void kgdb_interruptible(int); /* control interrupts from serial */
-extern void putDebugChar(char); /* write a single character */
-extern char getDebugChar(void); /* read and return a single char */
-
+#define NUMREGBYTES ((68 * 8) + (3 * 4))
+#define NUMCRITREGBYTES 184
+#else /* CONFIG_PPC32 */
+/* On non-E500 family PPC32 we determine the size by picking the last
+ * register we need, but on E500 we skip sections so we list what we
+ * need to store, and add it up. */
+#ifndef CONFIG_E500
+#define MAXREG (PT_FPSCR+1)
+#else
+/* 32 GPRs (8 bytes), nip, msr, ccr, link, ctr, xer, acc (8 bytes), spefscr*/
+#define MAXREG ((32*2)+6+2+1)
+#endif
+#define NUMREGBYTES (MAXREG * sizeof(int))
+/* CR/LR, R1, R2, R13-R31 inclusive. */
+#define NUMCRITREGBYTES (23 * sizeof(int))
+#endif /* 32/64 */
#endif /* !(__ASSEMBLY__) */
-#endif /* !(_PPC_KGDB_H) */
+#endif /* !__POWERPC_KGDB_H__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/lppaca.h b/include/asm-powerpc/lppaca.h
index 567ed92cd91..2fe268b1033 100644
--- a/include/asm-powerpc/lppaca.h
+++ b/include/asm-powerpc/lppaca.h
@@ -125,7 +125,10 @@ struct lppaca {
// NOTE: This value will ALWAYS be zero for dedicated processors and
// will NEVER be zero for shared processors (ie, initialized to a 1).
volatile u32 yield_count; // PLIC increments each dispatchx00-x03
- u8 reserved6[124]; // Reserved x04-x7F
+ u32 reserved6;
+ volatile u64 cmo_faults; // CMO page fault count x08-x0F
+ volatile u64 cmo_fault_time; // CMO page fault time x10-x17
+ u8 reserved7[104]; // Reserved x18-x7F
//=============================================================================
// CACHE_LINE_4-5 0x0180 - 0x027F Contains PMC interrupt data
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 989922621e3..893aafd87fd 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -76,11 +76,12 @@ struct machdep_calls {
* destroyed as well */
void (*hpte_clear_all)(void);
- void (*tce_build)(struct iommu_table * tbl,
+ int (*tce_build)(struct iommu_table *tbl,
long index,
long npages,
unsigned long uaddr,
- enum dma_data_direction direction);
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs);
void (*tce_free)(struct iommu_table *tbl,
long index,
long npages);
diff --git a/include/asm-powerpc/mmu-hash64.h b/include/asm-powerpc/mmu-hash64.h
index d1dc16afb11..19c7a940349 100644
--- a/include/asm-powerpc/mmu-hash64.h
+++ b/include/asm-powerpc/mmu-hash64.h
@@ -194,9 +194,9 @@ extern int mmu_ci_restrictions;
#ifdef CONFIG_HUGETLB_PAGE
/*
- * The page size index of the huge pages for use by hugetlbfs
+ * The page size indexes of the huge pages for use by hugetlbfs
*/
-extern int mmu_huge_psize;
+extern unsigned int mmu_huge_psizes[MMU_PAGE_COUNT];
#endif /* CONFIG_HUGETLB_PAGE */
@@ -281,6 +281,8 @@ extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
unsigned long pstart, unsigned long mode,
int psize, int ssize);
extern void set_huge_psize(int psize);
+extern void add_gpage(unsigned long addr, unsigned long page_size,
+ unsigned long number_of_pages);
extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr);
extern void htab_initialize(void);
diff --git a/include/asm-powerpc/mpc52xx_psc.h b/include/asm-powerpc/mpc52xx_psc.h
index 710c5d36efa..8917ed63056 100644
--- a/include/asm-powerpc/mpc52xx_psc.h
+++ b/include/asm-powerpc/mpc52xx_psc.h
@@ -60,10 +60,12 @@
#define MPC52xx_PSC_RXTX_FIFO_ALARM 0x0002
#define MPC52xx_PSC_RXTX_FIFO_EMPTY 0x0001
-/* PSC interrupt mask bits */
+/* PSC interrupt status/mask bits */
#define MPC52xx_PSC_IMR_TXRDY 0x0100
#define MPC52xx_PSC_IMR_RXRDY 0x0200
#define MPC52xx_PSC_IMR_DB 0x0400
+#define MPC52xx_PSC_IMR_TXEMP 0x0800
+#define MPC52xx_PSC_IMR_ORERR 0x1000
#define MPC52xx_PSC_IMR_IPC 0x8000
/* PSC input port change bit */
@@ -92,6 +94,34 @@
#define MPC52xx_PSC_RFNUM_MASK 0x01ff
+#define MPC52xx_PSC_SICR_DTS1 (1 << 29)
+#define MPC52xx_PSC_SICR_SHDR (1 << 28)
+#define MPC52xx_PSC_SICR_SIM_MASK (0xf << 24)
+#define MPC52xx_PSC_SICR_SIM_UART (0x0 << 24)
+#define MPC52xx_PSC_SICR_SIM_UART_DCD (0x8 << 24)
+#define MPC52xx_PSC_SICR_SIM_CODEC_8 (0x1 << 24)
+#define MPC52xx_PSC_SICR_SIM_CODEC_16 (0x2 << 24)
+#define MPC52xx_PSC_SICR_SIM_AC97 (0x3 << 24)
+#define MPC52xx_PSC_SICR_SIM_SIR (0x8 << 24)
+#define MPC52xx_PSC_SICR_SIM_SIR_DCD (0xc << 24)
+#define MPC52xx_PSC_SICR_SIM_MIR (0x5 << 24)
+#define MPC52xx_PSC_SICR_SIM_FIR (0x6 << 24)
+#define MPC52xx_PSC_SICR_SIM_CODEC_24 (0x7 << 24)
+#define MPC52xx_PSC_SICR_SIM_CODEC_32 (0xf << 24)
+#define MPC52xx_PSC_SICR_GENCLK (1 << 23)
+#define MPC52xx_PSC_SICR_I2S (1 << 22)
+#define MPC52xx_PSC_SICR_CLKPOL (1 << 21)
+#define MPC52xx_PSC_SICR_SYNCPOL (1 << 20)
+#define MPC52xx_PSC_SICR_CELLSLAVE (1 << 19)
+#define MPC52xx_PSC_SICR_CELL2XCLK (1 << 18)
+#define MPC52xx_PSC_SICR_ESAI (1 << 17)
+#define MPC52xx_PSC_SICR_ENAC97 (1 << 16)
+#define MPC52xx_PSC_SICR_SPI (1 << 15)
+#define MPC52xx_PSC_SICR_MSTR (1 << 14)
+#define MPC52xx_PSC_SICR_CPOL (1 << 13)
+#define MPC52xx_PSC_SICR_CPHA (1 << 12)
+#define MPC52xx_PSC_SICR_USEEOF (1 << 11)
+#define MPC52xx_PSC_SICR_DISABLEEOF (1 << 10)
/* Structure of the hardware registers */
struct mpc52xx_psc {
@@ -132,8 +162,12 @@ struct mpc52xx_psc {
u8 reserved5[3];
u8 ctlr; /* PSC + 0x1c */
u8 reserved6[3];
- u16 ccr; /* PSC + 0x20 */
- u8 reserved7[14];
+ /* BitClkDiv field of CCR is byte swapped in
+ * the hardware for mpc5200/b compatibility */
+ u32 ccr; /* PSC + 0x20 */
+ u32 ac97_slots; /* PSC + 0x24 */
+ u32 ac97_cmd; /* PSC + 0x28 */
+ u32 ac97_data; /* PSC + 0x2c */
u8 ivr; /* PSC + 0x30 */
u8 reserved8[3];
u8 ip; /* PSC + 0x34 */
diff --git a/include/asm-powerpc/page.h b/include/asm-powerpc/page.h
index cffdf0eb0df..e088545cb3f 100644
--- a/include/asm-powerpc/page.h
+++ b/include/asm-powerpc/page.h
@@ -119,9 +119,6 @@ extern phys_addr_t kernstart_addr;
/* align addr on a size boundary - adjust address up if needed */
#define _ALIGN(addr,size) _ALIGN_UP(addr,size)
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE)
-
/*
* Don't compare things with KERNELBASE or PAGE_OFFSET to test for
* "kernelness", use is_kernel_addr() - it should do what you want.
diff --git a/include/asm-powerpc/page_64.h b/include/asm-powerpc/page_64.h
index 02fd80710e9..043bfdfe4f7 100644
--- a/include/asm-powerpc/page_64.h
+++ b/include/asm-powerpc/page_64.h
@@ -90,6 +90,7 @@ extern unsigned int HPAGE_SHIFT;
#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+#define HUGE_MAX_HSTATE 3
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-powerpc/pgalloc-64.h b/include/asm-powerpc/pgalloc-64.h
index 68980990f62..812a1d8f35c 100644
--- a/include/asm-powerpc/pgalloc-64.h
+++ b/include/asm-powerpc/pgalloc-64.h
@@ -22,7 +22,7 @@ extern struct kmem_cache *pgtable_cache[];
#define PUD_CACHE_NUM 1
#define PMD_CACHE_NUM 1
#define HUGEPTE_CACHE_NUM 2
-#define PTE_NONCACHE_NUM 3 /* from GFP rather than kmem_cache */
+#define PTE_NONCACHE_NUM 7 /* from GFP rather than kmem_cache */
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
@@ -119,7 +119,7 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
__free_page(ptepage);
}
-#define PGF_CACHENUM_MASK 0x3
+#define PGF_CACHENUM_MASK 0x7
typedef struct pgtable_free {
unsigned long val;
diff --git a/include/asm-powerpc/pgtable-4k.h b/include/asm-powerpc/pgtable-4k.h
index fd2090dc1dc..c9601dfb4a1 100644
--- a/include/asm-powerpc/pgtable-4k.h
+++ b/include/asm-powerpc/pgtable-4k.h
@@ -51,6 +51,9 @@
#define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | \
_PAGE_SECONDARY | _PAGE_GROUP_IX)
+/* There is no 4K PFN hack on 4K pages */
+#define _PAGE_4K_PFN 0
+
/* PAGE_MASK gives the right answer below, but only by accident */
/* It should be preserving the high 48 bits and then specifically */
/* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */
diff --git a/include/asm-powerpc/pgtable-64k.h b/include/asm-powerpc/pgtable-64k.h
index c5007712473..7e54adb3559 100644
--- a/include/asm-powerpc/pgtable-64k.h
+++ b/include/asm-powerpc/pgtable-64k.h
@@ -138,7 +138,7 @@ static inline struct subpage_prot_table *pgd_subpage_prot(pgd_t *pgd)
unsigned __split = (psize == MMU_PAGE_4K || \
psize == MMU_PAGE_64K_AP); \
shift = mmu_psize_defs[psize].shift; \
- for (index = 0; va < __end; index++, va += (1 << shift)) { \
+ for (index = 0; va < __end; index++, va += (1L << shift)) { \
if (!__split || __rpte_sub_valid(rpte, index)) do { \
#define pte_iterate_hashed_end() } while(0); } } while(0)
diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h
index 73015f0139d..bdbab72f3eb 100644
--- a/include/asm-powerpc/pgtable-ppc32.h
+++ b/include/asm-powerpc/pgtable-ppc32.h
@@ -295,10 +295,10 @@ extern int icache_44x_need_flush;
#define _PAGE_PRESENT 0x00001 /* S: PTE contains a translation */
#define _PAGE_USER 0x00002 /* S: User page (maps to UR) */
#define _PAGE_FILE 0x00002 /* S: when !present: nonlinear file mapping */
-#define _PAGE_ACCESSED 0x00004 /* S: Page referenced */
-#define _PAGE_HWWRITE 0x00008 /* H: Dirty & RW, set in exception */
-#define _PAGE_RW 0x00010 /* S: Write permission */
-#define _PAGE_HWEXEC 0x00020 /* H: UX permission */
+#define _PAGE_RW 0x00004 /* S: Write permission (SW) */
+#define _PAGE_DIRTY 0x00008 /* S: Page dirty */
+#define _PAGE_HWEXEC 0x00010 /* H: SX permission */
+#define _PAGE_ACCESSED 0x00020 /* S: Page referenced */
#define _PAGE_ENDIAN 0x00040 /* H: E bit */
#define _PAGE_GUARDED 0x00080 /* H: G bit */
@@ -307,21 +307,14 @@ extern int icache_44x_need_flush;
#define _PAGE_WRITETHRU 0x00400 /* H: W bit */
#ifdef CONFIG_PTE_64BIT
-#define _PAGE_DIRTY 0x08000 /* S: Page dirty */
-
/* ERPN in a PTE never gets cleared, ignore it */
#define _PTE_NONE_MASK 0xffffffffffff0000ULL
-#else
-#define _PAGE_DIRTY 0x00800 /* S: Page dirty */
#endif
#define _PMD_PRESENT 0
#define _PMD_PRESENT_MASK (PAGE_MASK)
#define _PMD_BAD (~PAGE_MASK)
-/* Until my rework is finished, FSL BookE still needs atomic PTE updates */
-#define PTE_ATOMIC_UPDATES 1
-
#elif defined(CONFIG_8xx)
/* Definitions for 8xx embedded chips. */
#define _PAGE_PRESENT 0x0001 /* Page is valid */
@@ -402,6 +395,12 @@ extern int icache_44x_need_flush;
#ifndef _PAGE_EXEC
#define _PAGE_EXEC 0
#endif
+#ifndef _PAGE_ENDIAN
+#define _PAGE_ENDIAN 0
+#endif
+#ifndef _PAGE_COHERENT
+#define _PAGE_COHERENT 0
+#endif
#ifndef _PMD_PRESENT_MASK
#define _PMD_PRESENT_MASK _PMD_PRESENT
#endif
@@ -412,6 +411,12 @@ extern int icache_44x_need_flush;
#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+
+#define PAGE_PROT_BITS __pgprot(_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \
+ _PAGE_WRITETHRU | _PAGE_ENDIAN | \
+ _PAGE_USER | _PAGE_ACCESSED | \
+ _PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | \
+ _PAGE_EXEC | _PAGE_HWEXEC)
/*
* Note: the _PAGE_COHERENT bit automatically gets set in the hardware
* PTE if CONFIG_SMP is defined (hash_page does this); there is no need
@@ -545,6 +550,10 @@ static inline pte_t pte_mkyoung(pte_t pte) {
pte_val(pte) |= _PAGE_ACCESSED; return pte; }
static inline pte_t pte_mkspecial(pte_t pte) {
return pte; }
+static inline unsigned long pte_pgprot(pte_t pte)
+{
+ return __pgprot(pte_val(pte)) & PAGE_PROT_BITS;
+}
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
diff --git a/include/asm-powerpc/pgtable-ppc64.h b/include/asm-powerpc/pgtable-ppc64.h
index ab98a9c80b2..ba8000352b9 100644
--- a/include/asm-powerpc/pgtable-ppc64.h
+++ b/include/asm-powerpc/pgtable-ppc64.h
@@ -117,6 +117,10 @@
#define PAGE_AGP __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_NO_CACHE)
#define HAVE_PAGE_AGP
+#define PAGE_PROT_BITS __pgprot(_PAGE_GUARDED | _PAGE_COHERENT | \
+ _PAGE_NO_CACHE | _PAGE_WRITETHRU | \
+ _PAGE_4K_PFN | _PAGE_RW | _PAGE_USER | \
+ _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_EXEC)
/* PTEIDX nibble */
#define _PTEIDX_SECONDARY 0x8
#define _PTEIDX_GROUP_IX 0x7
@@ -262,6 +266,10 @@ static inline pte_t pte_mkhuge(pte_t pte) {
return pte; }
static inline pte_t pte_mkspecial(pte_t pte) {
return pte; }
+static inline unsigned long pte_pgprot(pte_t pte)
+{
+ return __pgprot(pte_val(pte)) & PAGE_PROT_BITS;
+}
/* Atomic PTE updates */
static inline unsigned long pte_update(struct mm_struct *mm,
diff --git a/include/asm-powerpc/pgtable.h b/include/asm-powerpc/pgtable.h
index d18ffe7bc7c..dbb8ca172e4 100644
--- a/include/asm-powerpc/pgtable.h
+++ b/include/asm-powerpc/pgtable.h
@@ -38,6 +38,19 @@ extern void paging_init(void);
remap_pfn_range(vma, vaddr, pfn, size, prot)
#include <asm-generic/pgtable.h>
+
+
+/*
+ * This gets called at the end of handling a page fault, when
+ * the kernel has put a new PTE into the page table for the process.
+ * We use it to ensure coherency between the i-cache and d-cache
+ * for the page which has just been mapped in.
+ * On machines which use an MMU hash table, we use this to put a
+ * corresponding HPTE into the hash table ahead of time, instead of
+ * waiting for the inevitable extra hash-table miss exception.
+ */
+extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
+
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/pmi.h b/include/asm-powerpc/pmi.h
index e1dc090748d..b4e91fbf508 100644
--- a/include/asm-powerpc/pmi.h
+++ b/include/asm-powerpc/pmi.h
@@ -30,6 +30,7 @@
#ifdef __KERNEL__
#define PMI_TYPE_FREQ_CHANGE 0x01
+#define PMI_TYPE_POWER_BUTTON 0x02
#define PMI_READ_TYPE 0
#define PMI_READ_DATA0 1
#define PMI_READ_DATA1 2
diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h
index 81ffe3b3c1c..f9e34c493cb 100644
--- a/include/asm-powerpc/ps3.h
+++ b/include/asm-powerpc/ps3.h
@@ -337,12 +337,18 @@ enum ps3_system_bus_device_type {
PS3_DEVICE_TYPE_LPM,
};
+enum ps3_match_sub_id {
+ /* for PS3_MATCH_ID_GRAPHICS */
+ PS3_MATCH_SUB_ID_FB = 1,
+};
+
/**
* struct ps3_system_bus_device - a device on the system bus
*/
struct ps3_system_bus_device {
enum ps3_match_id match_id;
+ enum ps3_match_sub_id match_sub_id;
enum ps3_system_bus_device_type dev_type;
u64 bus_id; /* SB */
@@ -371,6 +377,7 @@ int ps3_close_hv_device(struct ps3_system_bus_device *dev);
struct ps3_system_bus_driver {
enum ps3_match_id match_id;
+ enum ps3_match_sub_id match_sub_id;
struct device_driver core;
int (*probe)(struct ps3_system_bus_device *);
int (*remove)(struct ps3_system_bus_device *);
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index bbccadfee0d..c6d1ab65077 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -155,10 +155,12 @@
#define CTRL_RUNLATCH 0x1
#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
#define DABR_TRANSLATION (1UL << 2)
+#define SPRN_DABR2 0x13D /* e300 */
#define SPRN_DABRX 0x3F7 /* Data Address Breakpoint Register Extension */
#define DABRX_USER (1UL << 0)
#define DABRX_KERNEL (1UL << 1)
#define SPRN_DAR 0x013 /* Data Address Register */
+#define SPRN_DBCR 0x136 /* e300 Data Breakpoint Control Reg */
#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
#define DSISR_NOHPTE 0x40000000 /* no translation found */
#define DSISR_PROTFAULT 0x08000000 /* protection fault */
@@ -264,6 +266,8 @@
#define HID1_PS (1<<16) /* 750FX PLL selection */
#define SPRN_HID2 0x3F8 /* Hardware Implementation Register 2 */
#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */
+#define SPRN_IABR2 0x3FA /* 83xx */
+#define SPRN_IBCR 0x135 /* 83xx Insn Breakpoint Control Reg */
#define SPRN_HID4 0x3F4 /* 970 HID4 */
#define SPRN_HID5 0x3F6 /* 970 HID5 */
#define SPRN_HID6 0x3F9 /* BE HID 6 */
diff --git a/include/asm-powerpc/semaphore.h b/include/asm-powerpc/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-powerpc/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-powerpc/syscalls.h b/include/asm-powerpc/syscalls.h
index 2b8a458f990..eb8eb400c66 100644
--- a/include/asm-powerpc/syscalls.h
+++ b/include/asm-powerpc/syscalls.h
@@ -31,6 +31,7 @@ asmlinkage int sys_vfork(unsigned long p1, unsigned long p2,
unsigned long p3, unsigned long p4, unsigned long p5,
unsigned long p6, struct pt_regs *regs);
asmlinkage long sys_pipe(int __user *fildes);
+asmlinkage long sys_pipe2(int __user *fildes, int flags);
asmlinkage long sys_rt_sigaction(int sig,
const struct sigaction __user *act,
struct sigaction __user *oact, size_t sigsetsize);
diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h
index ae7085c6569..e084272ed1c 100644
--- a/include/asm-powerpc/systbl.h
+++ b/include/asm-powerpc/systbl.h
@@ -316,3 +316,9 @@ COMPAT_SYS(fallocate)
SYSCALL(subpage_prot)
COMPAT_SYS_SPU(timerfd_settime)
COMPAT_SYS_SPU(timerfd_gettime)
+COMPAT_SYS_SPU(signalfd4)
+SYSCALL_SPU(eventfd2)
+SYSCALL_SPU(epoll_create1)
+SYSCALL_SPU(dup3)
+SYSCALL_SPU(pipe2)
+SYSCALL(inotify_init1)
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h
index e6e25e2364e..d6648c14332 100644
--- a/include/asm-powerpc/system.h
+++ b/include/asm-powerpc/system.h
@@ -110,6 +110,8 @@ static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
#endif
extern int set_dabr(unsigned long dabr);
+extern void do_dabr(struct pt_regs *regs, unsigned long address,
+ unsigned long error_code);
extern void print_backtrace(unsigned long *);
extern void show_regs(struct pt_regs * regs);
extern void flush_instruction_cache(void);
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index b705c2a7651..a9db562df69 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -66,20 +66,12 @@ struct thread_info {
#if THREAD_SHIFT >= PAGE_SHIFT
-#define THREAD_ORDER (THREAD_SHIFT - PAGE_SHIFT)
-
-#ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk) \
- ((struct thread_info *)__get_free_pages(GFP_KERNEL | \
- __GFP_ZERO, THREAD_ORDER))
-#else
-#define alloc_thread_info(tsk) \
- ((struct thread_info *)__get_free_pages(GFP_KERNEL, THREAD_ORDER))
-#endif
-#define free_thread_info(ti) free_pages((unsigned long)ti, THREAD_ORDER)
+#define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT)
#else /* THREAD_SHIFT < PAGE_SHIFT */
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
extern void free_thread_info(struct thread_info *ti);
diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h
index 5c910814764..361cd5c7a32 100644
--- a/include/asm-powerpc/tlbflush.h
+++ b/include/asm-powerpc/tlbflush.h
@@ -162,16 +162,5 @@ extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
#endif
-/*
- * This gets called at the end of handling a page fault, when
- * the kernel has put a new PTE into the page table for the process.
- * We use it to ensure coherency between the i-cache and d-cache
- * for the page which has just been mapped in.
- * On machines which use an MMU hash table, we use this to put a
- * corresponding HPTE into the hash table ahead of time, instead of
- * waiting for the inevitable extra hash-table miss exception.
- */
-extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
-
#endif /*__KERNEL__ */
#endif /* _ASM_POWERPC_TLBFLUSH_H */
diff --git a/include/asm-powerpc/uaccess.h b/include/asm-powerpc/uaccess.h
index 1a0736f8803..bd0fb849515 100644
--- a/include/asm-powerpc/uaccess.h
+++ b/include/asm-powerpc/uaccess.h
@@ -6,6 +6,7 @@
#include <linux/sched.h>
#include <linux/errno.h>
+#include <asm/asm-compat.h>
#include <asm/processor.h>
#include <asm/page.h>
@@ -141,12 +142,11 @@ extern long __put_user_bad(void);
" b 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
- " .balign %5\n" \
+ PPC_LONG_ALIGN "\n" \
PPC_LONG "1b,3b\n" \
".previous" \
: "=r" (err) \
- : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err),\
- "i"(sizeof(unsigned long)))
+ : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err))
#ifdef __powerpc64__
#define __put_user_asm2(x, ptr, retval) \
@@ -162,13 +162,12 @@ extern long __put_user_bad(void);
" b 3b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
- " .balign %5\n" \
+ PPC_LONG_ALIGN "\n" \
PPC_LONG "1b,4b\n" \
PPC_LONG "2b,4b\n" \
".previous" \
: "=r" (err) \
- : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err),\
- "i"(sizeof(unsigned long)))
+ : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err))
#endif /* __powerpc64__ */
#define __put_user_size(x, ptr, size, retval) \
@@ -226,12 +225,11 @@ extern long __get_user_bad(void);
" b 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
- " .balign %5\n" \
+ PPC_LONG_ALIGN "\n" \
PPC_LONG "1b,3b\n" \
".previous" \
: "=r" (err), "=r" (x) \
- : "b" (addr), "i" (-EFAULT), "0" (err), \
- "i"(sizeof(unsigned long)))
+ : "b" (addr), "i" (-EFAULT), "0" (err))
#ifdef __powerpc64__
#define __get_user_asm2(x, addr, err) \
@@ -249,13 +247,12 @@ extern long __get_user_bad(void);
" b 3b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
- " .balign %5\n" \
+ PPC_LONG_ALIGN "\n" \
PPC_LONG "1b,4b\n" \
PPC_LONG "2b,4b\n" \
".previous" \
: "=r" (err), "=&r" (x) \
- : "b" (addr), "i" (-EFAULT), "0" (err), \
- "i"(sizeof(unsigned long)))
+ : "b" (addr), "i" (-EFAULT), "0" (err))
#endif /* __powerpc64__ */
#define __get_user_size(x, ptr, size, retval) \
diff --git a/include/asm-powerpc/ucc_fast.h b/include/asm-powerpc/ucc_fast.h
index f529f70b1d8..fce16abe7ee 100644
--- a/include/asm-powerpc/ucc_fast.h
+++ b/include/asm-powerpc/ucc_fast.h
@@ -156,11 +156,11 @@ struct ucc_fast_info {
struct ucc_fast_private {
struct ucc_fast_info *uf_info;
- struct ucc_fast *uf_regs; /* a pointer to memory map of UCC regs. */
- u32 *p_ucce; /* a pointer to the event register in memory. */
- u32 *p_uccm; /* a pointer to the mask register in memory. */
+ struct ucc_fast __iomem *uf_regs; /* a pointer to the UCC regs. */
+ u32 __iomem *p_ucce; /* a pointer to the event register in memory. */
+ u32 __iomem *p_uccm; /* a pointer to the mask register in memory. */
#ifdef CONFIG_UGETH_TX_ON_DEMAND
- u16 *p_utodr; /* pointer to the transmit on demand register */
+ u16 __iomem *p_utodr; /* pointer to the transmit on demand register */
#endif
int enabled_tx; /* Whether channel is enabled for Tx (ENT) */
int enabled_rx; /* Whether channel is enabled for Rx (ENR) */
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
index ce91bb66206..e07d0c76ed7 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -335,10 +335,16 @@
#define __NR_subpage_prot 310
#define __NR_timerfd_settime 311
#define __NR_timerfd_gettime 312
+#define __NR_signalfd4 313
+#define __NR_eventfd2 314
+#define __NR_epoll_create1 315
+#define __NR_dup3 316
+#define __NR_pipe2 317
+#define __NR_inotify_init1 318
#ifdef __KERNEL__
-#define __NR_syscalls 313
+#define __NR_syscalls 319
#define __NR__exit __NR_exit
#define NR_syscalls __NR_syscalls
diff --git a/include/asm-powerpc/vio.h b/include/asm-powerpc/vio.h
index 56512a968da..0a290a19594 100644
--- a/include/asm-powerpc/vio.h
+++ b/include/asm-powerpc/vio.h
@@ -39,16 +39,32 @@
#define VIO_IRQ_DISABLE 0UL
#define VIO_IRQ_ENABLE 1UL
+/*
+ * VIO CMO minimum entitlement for all devices and spare entitlement
+ */
+#define VIO_CMO_MIN_ENT 1562624
+
struct iommu_table;
-/*
- * The vio_dev structure is used to describe virtual I/O devices.
+/**
+ * vio_dev - This structure is used to describe virtual I/O devices.
+ *
+ * @desired: set from return of driver's get_desired_dma() function
+ * @entitled: bytes of IO data that has been reserved for this device.
+ * @allocated: bytes of IO data currently in use by the device.
+ * @allocs_failed: number of DMA failures due to insufficient entitlement.
*/
struct vio_dev {
const char *name;
const char *type;
uint32_t unit_address;
unsigned int irq;
+ struct {
+ size_t desired;
+ size_t entitled;
+ size_t allocated;
+ atomic_t allocs_failed;
+ } cmo;
struct device dev;
};
@@ -56,12 +72,19 @@ struct vio_driver {
const struct vio_device_id *id_table;
int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
int (*remove)(struct vio_dev *dev);
+ /* A driver must have a get_desired_dma() function to
+ * be loaded in a CMO environment if it uses DMA.
+ */
+ unsigned long (*get_desired_dma)(struct vio_dev *dev);
struct device_driver driver;
};
extern int vio_register_driver(struct vio_driver *drv);
extern void vio_unregister_driver(struct vio_driver *drv);
+extern int vio_cmo_entitlement_update(size_t);
+extern void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired);
+
extern void __devinit vio_unregister_device(struct vio_dev *dev);
struct device_node;
diff --git a/include/asm-s390/Kbuild b/include/asm-s390/Kbuild
index bb5e9edb982..63a23415fba 100644
--- a/include/asm-s390/Kbuild
+++ b/include/asm-s390/Kbuild
@@ -7,7 +7,6 @@ header-y += tape390.h
header-y += ucontext.h
header-y += vtoc.h
header-y += zcrypt.h
-header-y += kvm.h
header-y += chsc.h
unifdef-y += cmb.h
diff --git a/include/asm-s390/hugetlb.h b/include/asm-s390/hugetlb.h
index 600a776f8f7..670a1d1745d 100644
--- a/include/asm-s390/hugetlb.h
+++ b/include/asm-s390/hugetlb.h
@@ -22,7 +22,8 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
* If the arch doesn't supply something else, assume that hugepage
* size aligned regions are ok without further preparation.
*/
-static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+static inline int prepare_hugepage_range(struct file *file,
+ unsigned long addr, unsigned long len)
{
if (len & ~HPAGE_MASK)
return -EINVAL;
diff --git a/include/asm-s390/kvm_virtio.h b/include/asm-s390/kvm_virtio.h
index 5c871a990c2..146100224de 100644
--- a/include/asm-s390/kvm_virtio.h
+++ b/include/asm-s390/kvm_virtio.h
@@ -50,4 +50,14 @@ struct kvm_vqconfig {
#define KVM_S390_VIRTIO_RESET 1
#define KVM_S390_VIRTIO_SET_STATUS 2
+#ifdef __KERNEL__
+/* early virtio console setup */
+#ifdef CONFIG_VIRTIO_CONSOLE
+extern void s390_virtio_console_init(void);
+#else
+static inline void s390_virtio_console_init(void)
+{
+}
+#endif /* CONFIG_VIRTIO_CONSOLE */
+#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index 12fd9c4f0f1..991ba939408 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -138,9 +138,6 @@ void arch_alloc_page(struct page *page, int order);
#endif /* !__ASSEMBLY__ */
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
#define __PAGE_OFFSET 0x0UL
#define PAGE_OFFSET 0x0UL
#define __pa(x) (unsigned long)(x)
diff --git a/include/asm-s390/semaphore.h b/include/asm-s390/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-s390/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-s390/thread_info.h b/include/asm-s390/thread_info.h
index 99bbed99a3b..91a8f93ad35 100644
--- a/include/asm-s390/thread_info.h
+++ b/include/asm-s390/thread_info.h
@@ -78,10 +78,7 @@ static inline struct thread_info *current_thread_info(void)
return (struct thread_info *)((*(unsigned long *) __LC_KERNEL_STACK)-THREAD_SIZE);
}
-/* thread information allocation */
-#define alloc_thread_info(tsk) ((struct thread_info *) \
- __get_free_pages(GFP_KERNEL,THREAD_ORDER))
-#define free_thread_info(ti) free_pages((unsigned long) (ti),THREAD_ORDER)
+#define THREAD_SIZE_ORDER THREAD_ORDER
#endif
diff --git a/include/asm-sh/hugetlb.h b/include/asm-sh/hugetlb.h
index 02402303d89..967068fb79a 100644
--- a/include/asm-sh/hugetlb.h
+++ b/include/asm-sh/hugetlb.h
@@ -14,7 +14,8 @@ static inline int is_hugepage_only_range(struct mm_struct *mm,
* If the arch doesn't supply something else, assume that hugepage
* size aligned regions are ok without further preparation.
*/
-static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+static inline int prepare_hugepage_range(struct file *file,
+ unsigned long addr, unsigned long len)
{
if (len & ~HPAGE_MASK)
return -EINVAL;
@@ -26,7 +27,7 @@ static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm) {
}
-static inline void hugetlb_free_pgd_range(struct mmu_gather **tlb,
+static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
unsigned long addr, unsigned long end,
unsigned long floor,
unsigned long ceiling)
diff --git a/include/asm-sh/ide.h b/include/asm-sh/ide.h
deleted file mode 100644
index 58e0bdd52be..00000000000
--- a/include/asm-sh/ide.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * linux/include/asm-sh/ide.h
- *
- * Copyright (C) 1994-1996 Linus Torvalds & authors
- */
-
-/*
- * This file contains the i386 architecture specific IDE code.
- * In future, SuperH code.
- */
-
-#ifndef __ASM_SH_IDE_H
-#define __ASM_SH_IDE_H
-
-#ifdef __KERNEL__
-
-#include <asm-generic/ide_iops.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASM_SH_IDE_H */
diff --git a/include/asm-sh/kvm.h b/include/asm-sh/kvm.h
deleted file mode 100644
index 6af51dbab2d..00000000000
--- a/include/asm-sh/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_SH_H
-#define __LINUX_KVM_SH_H
-
-/* sh does not support KVM */
-
-#endif
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index 304c30b5d94..5dc01d2fcc4 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -22,9 +22,6 @@
#define PAGE_MASK (~(PAGE_SIZE-1))
#define PTE_MASK PAGE_MASK
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
#if defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
#define HPAGE_SHIFT 16
#elif defined(CONFIG_HUGETLB_PAGE_SIZE_256K)
diff --git a/include/asm-sh/ptrace.h b/include/asm-sh/ptrace.h
index 8d6c92b3e77..7d36dc3bee6 100644
--- a/include/asm-sh/ptrace.h
+++ b/include/asm-sh/ptrace.h
@@ -5,7 +5,7 @@
* Copyright (C) 1999, 2000 Niibe Yutaka
*
*/
-#if defined(__SH5__) || defined(CONFIG_SUPERH64)
+#if defined(__SH5__)
struct pt_regs {
unsigned long long pc;
unsigned long long sr;
diff --git a/include/asm-sh/semaphore.h b/include/asm-sh/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-sh/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-sh/sh7760fb.h b/include/asm-sh/sh7760fb.h
new file mode 100644
index 00000000000..8767f61acec
--- /dev/null
+++ b/include/asm-sh/sh7760fb.h
@@ -0,0 +1,197 @@
+/*
+ * sh7760fb.h -- platform data for SH7760/SH7763 LCDC framebuffer driver.
+ *
+ * (c) 2006-2008 MSC Vertriebsges.m.b.H.,
+ * Manuel Lauss <mano@roarinelk.homelinux.net>
+ * (c) 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
+ */
+
+#ifndef _ASM_SH_SH7760FB_H
+#define _ASM_SH_SH7760FB_H
+
+/*
+ * some bits of the colormap registers should be written as zero.
+ * create a mask for that.
+ */
+#define SH7760FB_PALETTE_MASK 0x00f8fcf8
+
+/* The LCDC dma engine always sets bits 27-26 to 1: this is Area3 */
+#define SH7760FB_DMA_MASK 0x0C000000
+
+/* palette */
+#define LDPR(x) (((x) << 2))
+
+/* framebuffer registers and bits */
+#define LDICKR 0x400
+#define LDMTR 0x402
+/* see sh7760fb.h for LDMTR bits */
+#define LDDFR 0x404
+#define LDDFR_PABD (1 << 8)
+#define LDDFR_COLOR_MASK 0x7F
+#define LDSMR 0x406
+#define LDSMR_ROT (1 << 13)
+#define LDSARU 0x408
+#define LDSARL 0x40c
+#define LDLAOR 0x410
+#define LDPALCR 0x412
+#define LDPALCR_PALS (1 << 4)
+#define LDPALCR_PALEN (1 << 0)
+#define LDHCNR 0x414
+#define LDHSYNR 0x416
+#define LDVDLNR 0x418
+#define LDVTLNR 0x41a
+#define LDVSYNR 0x41c
+#define LDACLNR 0x41e
+#define LDINTR 0x420
+#define LDPMMR 0x424
+#define LDPSPR 0x426
+#define LDCNTR 0x428
+#define LDCNTR_DON (1 << 0)
+#define LDCNTR_DON2 (1 << 4)
+
+#ifdef CONFIG_CPU_SUBTYPE_SH7763
+# define LDLIRNR 0x440
+/* LDINTR bit */
+# define LDINTR_MINTEN (1 << 15)
+# define LDINTR_FINTEN (1 << 14)
+# define LDINTR_VSINTEN (1 << 13)
+# define LDINTR_VEINTEN (1 << 12)
+# define LDINTR_MINTS (1 << 11)
+# define LDINTR_FINTS (1 << 10)
+# define LDINTR_VSINTS (1 << 9)
+# define LDINTR_VEINTS (1 << 8)
+# define VINT_START (LDINTR_VSINTEN)
+# define VINT_CHECK (LDINTR_VSINTS)
+#else
+/* LDINTR bit */
+# define LDINTR_VINTSEL (1 << 12)
+# define LDINTR_VINTE (1 << 8)
+# define LDINTR_VINTS (1 << 0)
+# define VINT_START (LDINTR_VINTSEL)
+# define VINT_CHECK (LDINTR_VINTS)
+#endif
+
+/* HSYNC polarity inversion */
+#define LDMTR_FLMPOL (1 << 15)
+
+/* VSYNC polarity inversion */
+#define LDMTR_CL1POL (1 << 14)
+
+/* DISPLAY-ENABLE polarity inversion */
+#define LDMTR_DISPEN_LOWACT (1 << 13)
+
+/* DISPLAY DATA BUS polarity inversion */
+#define LDMTR_DPOL_LOWACT (1 << 12)
+
+/* AC modulation signal enable */
+#define LDMTR_MCNT (1 << 10)
+
+/* Disable output of HSYNC during VSYNC period */
+#define LDMTR_CL1CNT (1 << 9)
+
+/* Disable output of VSYNC during VSYNC period */
+#define LDMTR_CL2CNT (1 << 8)
+
+/* Display types supported by the LCDC */
+#define LDMTR_STN_MONO_4 0x00
+#define LDMTR_STN_MONO_8 0x01
+#define LDMTR_STN_COLOR_4 0x08
+#define LDMTR_STN_COLOR_8 0x09
+#define LDMTR_STN_COLOR_12 0x0A
+#define LDMTR_STN_COLOR_16 0x0B
+#define LDMTR_DSTN_MONO_8 0x11
+#define LDMTR_DSTN_MONO_16 0x13
+#define LDMTR_DSTN_COLOR_8 0x19
+#define LDMTR_DSTN_COLOR_12 0x1A
+#define LDMTR_DSTN_COLOR_16 0x1B
+#define LDMTR_TFT_COLOR_16 0x2B
+
+/* framebuffer color layout */
+#define LDDFR_1BPP_MONO 0x00
+#define LDDFR_2BPP_MONO 0x01
+#define LDDFR_4BPP_MONO 0x02
+#define LDDFR_6BPP_MONO 0x04
+#define LDDFR_4BPP 0x0A
+#define LDDFR_8BPP 0x0C
+#define LDDFR_16BPP_RGB555 0x1D
+#define LDDFR_16BPP_RGB565 0x2D
+
+/* LCDC Pixclock sources */
+#define LCDC_CLKSRC_BUSCLOCK 0
+#define LCDC_CLKSRC_PERIPHERAL 1
+#define LCDC_CLKSRC_EXTERNAL 2
+
+#define LDICKR_CLKSRC(x) \
+ (((x) & 3) << 12)
+
+/* LCDC pixclock input divider. Set to 1 at a minimum! */
+#define LDICKR_CLKDIV(x) \
+ ((x) & 0x1f)
+
+struct sh7760fb_platdata {
+
+ /* Set this member to a valid fb_videmode for the display you
+ * wish to use. The following members must be initialized:
+ * xres, yres, hsync_len, vsync_len, sync,
+ * {left,right,upper,lower}_margin.
+ * The driver uses the above members to calculate register values
+ * and memory requirements. Other members are ignored but may
+ * be used by other framebuffer layer components.
+ */
+ struct fb_videomode *def_mode;
+
+ /* LDMTR includes display type and signal polarity. The
+ * HSYNC/VSYNC polarities are derived from the fb_var_screeninfo
+ * data above; however the polarities of the following signals
+ * must be encoded in the ldmtr member:
+ * Display Enable signal (default high-active) DISPEN_LOWACT
+ * Display Data signals (default high-active) DPOL_LOWACT
+ * AC Modulation signal (default off) MCNT
+ * Hsync-During-Vsync suppression (default off) CL1CNT
+ * Vsync-during-vsync suppression (default off) CL2CNT
+ * NOTE: also set a display type!
+ * (one of LDMTR_{STN,DSTN,TFT}_{MONO,COLOR}_{4,8,12,16})
+ */
+ u16 ldmtr;
+
+ /* LDDFR controls framebuffer image format (depth, organization)
+ * Use ONE of the LDDFR_?BPP_* macros!
+ */
+ u16 lddfr;
+
+ /* LDPMMR and LDPSPR control the timing of the power signals
+ * for the display. Please read the SH7760 Hardware Manual,
+ * Chapters 30.3.17, 30.3.18 and 30.4.6!
+ */
+ u16 ldpmmr;
+ u16 ldpspr;
+
+ /* LDACLNR contains the line numbers after which the AC modulation
+ * signal is to toggle. Set to ZERO for TFTs or displays which
+ * do not need it. (Chapter 30.3.15 in SH7760 Hardware Manual).
+ */
+ u16 ldaclnr;
+
+ /* LDICKR contains information on pixelclock source and config.
+ * Please use the LDICKR_CLKSRC() and LDICKR_CLKDIV() macros.
+ * minimal value for CLKDIV() must be 1!.
+ */
+ u16 ldickr;
+
+ /* set this member to 1 if you wish to use the LCDC's hardware
+ * rotation function. This is limited to displays <= 320x200
+ * pixels resolution!
+ */
+ int rotate; /* set to 1 to rotate 90 CCW */
+
+ /* set this to 1 to suppress vsync irq use. */
+ int novsync;
+
+ /* blanking hook for platform. Set this if your platform can do
+ * more than the LCDC in terms of blanking (e.g. disable clock
+ * generator / backlight power supply / etc.
+ */
+ void (*blank) (int);
+};
+
+#endif /* _ASM_SH_SH7760FB_H */
diff --git a/include/asm-sh/sh_mobile_lcdc.h b/include/asm-sh/sh_mobile_lcdc.h
new file mode 100644
index 00000000000..27677727df4
--- /dev/null
+++ b/include/asm-sh/sh_mobile_lcdc.h
@@ -0,0 +1,66 @@
+#ifndef __ASM_SH_MOBILE_LCDC_H__
+#define __ASM_SH_MOBILE_LCDC_H__
+
+#include <linux/fb.h>
+
+enum { RGB8, /* 24bpp, 8:8:8 */
+ RGB9, /* 18bpp, 9:9 */
+ RGB12A, /* 24bpp, 12:12 */
+ RGB12B, /* 12bpp */
+ RGB16, /* 16bpp */
+ RGB18, /* 18bpp */
+ RGB24, /* 24bpp */
+ SYS8A, /* 24bpp, 8:8:8 */
+ SYS8B, /* 18bpp, 8:8:2 */
+ SYS8C, /* 18bpp, 2:8:8 */
+ SYS8D, /* 16bpp, 8:8 */
+ SYS9, /* 18bpp, 9:9 */
+ SYS12, /* 24bpp, 12:12 */
+ SYS16A, /* 16bpp */
+ SYS16B, /* 18bpp, 16:2 */
+ SYS16C, /* 18bpp, 2:16 */
+ SYS18, /* 18bpp */
+ SYS24 };/* 24bpp */
+
+enum { LCDC_CHAN_DISABLED = 0,
+ LCDC_CHAN_MAINLCD,
+ LCDC_CHAN_SUBLCD };
+
+enum { LCDC_CLK_BUS, LCDC_CLK_PERIPHERAL, LCDC_CLK_EXTERNAL };
+
+struct sh_mobile_lcdc_sys_bus_cfg {
+ unsigned long ldmt2r;
+ unsigned long ldmt3r;
+};
+
+struct sh_mobile_lcdc_sys_bus_ops {
+ void (*write_index)(void *handle, unsigned long data);
+ void (*write_data)(void *handle, unsigned long data);
+ unsigned long (*read_data)(void *handle);
+};
+
+struct sh_mobile_lcdc_board_cfg {
+ void *board_data;
+ int (*setup_sys)(void *board_data, void *sys_ops_handle,
+ struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
+ void (*display_on)(void *board_data);
+ void (*display_off)(void *board_data);
+};
+
+struct sh_mobile_lcdc_chan_cfg {
+ int chan;
+ int bpp;
+ int interface_type; /* selects RGBn or SYSn I/F, see above */
+ int clock_divider;
+ struct fb_videomode lcd_cfg;
+ struct sh_mobile_lcdc_board_cfg board_cfg;
+ struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */
+};
+
+struct sh_mobile_lcdc_info {
+ unsigned long lddckr;
+ int clock_source;
+ struct sh_mobile_lcdc_chan_cfg ch[2];
+};
+
+#endif /* __ASM_SH_MOBILE_LCDC_H__ */
diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h
index c50e5d35fe8..5131e390752 100644
--- a/include/asm-sh/thread_info.h
+++ b/include/asm-sh/thread_info.h
@@ -92,6 +92,8 @@ static inline struct thread_info *current_thread_info(void)
return ti;
}
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
/* thread information allocation */
#ifdef CONFIG_DEBUG_STACK_USAGE
#define alloc_thread_info(ti) kzalloc(THREAD_SIZE, GFP_KERNEL)
diff --git a/include/asm-sparc/hugetlb.h b/include/asm-sparc/hugetlb.h
index 412af58926a..177061064ee 100644
--- a/include/asm-sparc/hugetlb.h
+++ b/include/asm-sparc/hugetlb.h
@@ -22,7 +22,8 @@ static inline int is_hugepage_only_range(struct mm_struct *mm,
* If the arch doesn't supply something else, assume that hugepage
* size aligned regions are ok without further preparation.
*/
-static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+static inline int prepare_hugepage_range(struct file *file,
+ unsigned long addr, unsigned long len)
{
if (len & ~HPAGE_MASK)
return -EINVAL;
@@ -31,7 +32,7 @@ static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
return 0;
}
-static inline void hugetlb_free_pgd_range(struct mmu_gather **tlb,
+static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
unsigned long addr, unsigned long end,
unsigned long floor,
unsigned long ceiling)
diff --git a/include/asm-sparc/ide.h b/include/asm-sparc/ide.h
index a3c7f5ff270..b7af3d65823 100644
--- a/include/asm-sparc/ide.h
+++ b/include/asm-sparc/ide.h
@@ -1,8 +1,97 @@
-#ifndef ___ASM_SPARC_IDE_H
-#define ___ASM_SPARC_IDE_H
-#if defined(__sparc__) && defined(__arch64__)
-#include <asm-sparc/ide_64.h>
+/* ide.h: SPARC PCI specific IDE glue.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
+ * Adaptation from sparc64 version to sparc by Pete Zaitcev.
+ */
+
+#ifndef _SPARC_IDE_H
+#define _SPARC_IDE_H
+
+#ifdef __KERNEL__
+
+#include <asm/io.h>
+#ifdef CONFIG_SPARC64
+#include <asm/pgalloc.h>
+#include <asm/spitfire.h>
+#include <asm/cacheflush.h>
+#include <asm/page.h>
#else
-#include <asm-sparc/ide_32.h>
+#include <asm/pgtable.h>
+#include <asm/psr.h>
#endif
+
+#define __ide_insl(data_reg, buffer, wcount) \
+ __ide_insw(data_reg, buffer, (wcount)<<1)
+#define __ide_outsl(data_reg, buffer, wcount) \
+ __ide_outsw(data_reg, buffer, (wcount)<<1)
+
+/* On sparc, I/O ports and MMIO registers are accessed identically. */
+#define __ide_mm_insw __ide_insw
+#define __ide_mm_insl __ide_insl
+#define __ide_mm_outsw __ide_outsw
+#define __ide_mm_outsl __ide_outsl
+
+static inline void __ide_insw(void __iomem *port, void *dst, u32 count)
+{
+#if defined(CONFIG_SPARC64) && defined(DCACHE_ALIASING_POSSIBLE)
+ unsigned long end = (unsigned long)dst + (count << 1);
#endif
+ u16 *ps = dst;
+ u32 *pi;
+
+ if(((unsigned long)ps) & 0x2) {
+ *ps++ = __raw_readw(port);
+ count--;
+ }
+ pi = (u32 *)ps;
+ while(count >= 2) {
+ u32 w;
+
+ w = __raw_readw(port) << 16;
+ w |= __raw_readw(port);
+ *pi++ = w;
+ count -= 2;
+ }
+ ps = (u16 *)pi;
+ if(count)
+ *ps++ = __raw_readw(port);
+
+#if defined(CONFIG_SPARC64) && defined(DCACHE_ALIASING_POSSIBLE)
+ __flush_dcache_range((unsigned long)dst, end);
+#endif
+}
+
+static inline void __ide_outsw(void __iomem *port, const void *src, u32 count)
+{
+#if defined(CONFIG_SPARC64) && defined(DCACHE_ALIASING_POSSIBLE)
+ unsigned long end = (unsigned long)src + (count << 1);
+#endif
+ const u16 *ps = src;
+ const u32 *pi;
+
+ if(((unsigned long)src) & 0x2) {
+ __raw_writew(*ps++, port);
+ count--;
+ }
+ pi = (const u32 *)ps;
+ while(count >= 2) {
+ u32 w;
+
+ w = *pi++;
+ __raw_writew((w >> 16), port);
+ __raw_writew(w, port);
+ count -= 2;
+ }
+ ps = (const u16 *)pi;
+ if(count)
+ __raw_writew(*ps, port);
+
+#if defined(CONFIG_SPARC64) && defined(DCACHE_ALIASING_POSSIBLE)
+ __flush_dcache_range((unsigned long)src, end);
+#endif
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _SPARC_IDE_H */
diff --git a/include/asm-sparc/ide_32.h b/include/asm-sparc/ide_32.h
deleted file mode 100644
index afd1736ed48..00000000000
--- a/include/asm-sparc/ide_32.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* ide.h: SPARC PCI specific IDE glue.
- *
- * Copyright (C) 1997 David S. Miller (davem@davemloft.net)
- * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
- * Adaptation from sparc64 version to sparc by Pete Zaitcev.
- */
-
-#ifndef _SPARC_IDE_H
-#define _SPARC_IDE_H
-
-#ifdef __KERNEL__
-
-#include <asm/pgtable.h>
-#include <asm/io.h>
-#include <asm/psr.h>
-
-#undef MAX_HWIFS
-#define MAX_HWIFS 2
-
-#define __ide_insl(data_reg, buffer, wcount) \
- __ide_insw(data_reg, buffer, (wcount)<<1)
-#define __ide_outsl(data_reg, buffer, wcount) \
- __ide_outsw(data_reg, buffer, (wcount)<<1)
-
-/* On sparc, I/O ports and MMIO registers are accessed identically. */
-#define __ide_mm_insw __ide_insw
-#define __ide_mm_insl __ide_insl
-#define __ide_mm_outsw __ide_outsw
-#define __ide_mm_outsl __ide_outsl
-
-static inline void __ide_insw(unsigned long port,
- void *dst,
- unsigned long count)
-{
- volatile unsigned short *data_port;
- /* unsigned long end = (unsigned long)dst + (count << 1); */ /* P3 */
- u16 *ps = dst;
- u32 *pi;
-
- data_port = (volatile unsigned short *)port;
-
- if(((unsigned long)ps) & 0x2) {
- *ps++ = *data_port;
- count--;
- }
- pi = (u32 *)ps;
- while(count >= 2) {
- u32 w;
-
- w = (*data_port) << 16;
- w |= (*data_port);
- *pi++ = w;
- count -= 2;
- }
- ps = (u16 *)pi;
- if(count)
- *ps++ = *data_port;
-
- /* __flush_dcache_range((unsigned long)dst, end); */ /* P3 see hme */
-}
-
-static inline void __ide_outsw(unsigned long port,
- const void *src,
- unsigned long count)
-{
- volatile unsigned short *data_port;
- /* unsigned long end = (unsigned long)src + (count << 1); */
- const u16 *ps = src;
- const u32 *pi;
-
- data_port = (volatile unsigned short *)port;
-
- if(((unsigned long)src) & 0x2) {
- *data_port = *ps++;
- count--;
- }
- pi = (const u32 *)ps;
- while(count >= 2) {
- u32 w;
-
- w = *pi++;
- *data_port = (w >> 16);
- *data_port = w;
- count -= 2;
- }
- ps = (const u16 *)pi;
- if(count)
- *data_port = *ps;
-
- /* __flush_dcache_range((unsigned long)src, end); */ /* P3 see hme */
-}
-
-#endif /* __KERNEL__ */
-
-#endif /* _SPARC_IDE_H */
diff --git a/include/asm-sparc/ide_64.h b/include/asm-sparc/ide_64.h
deleted file mode 100644
index 1282676da1c..00000000000
--- a/include/asm-sparc/ide_64.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * ide.h: Ultra/PCI specific IDE glue.
- *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
- */
-
-#ifndef _SPARC64_IDE_H
-#define _SPARC64_IDE_H
-
-#ifdef __KERNEL__
-
-#include <asm/pgalloc.h>
-#include <asm/io.h>
-#include <asm/spitfire.h>
-#include <asm/cacheflush.h>
-#include <asm/page.h>
-
-#ifndef MAX_HWIFS
-# ifdef CONFIG_BLK_DEV_IDEPCI
-#define MAX_HWIFS 10
-# else
-#define MAX_HWIFS 2
-# endif
-#endif
-
-#define __ide_insl(data_reg, buffer, wcount) \
- __ide_insw(data_reg, buffer, (wcount)<<1)
-#define __ide_outsl(data_reg, buffer, wcount) \
- __ide_outsw(data_reg, buffer, (wcount)<<1)
-
-/* On sparc64, I/O ports and MMIO registers are accessed identically. */
-#define __ide_mm_insw __ide_insw
-#define __ide_mm_insl __ide_insl
-#define __ide_mm_outsw __ide_outsw
-#define __ide_mm_outsl __ide_outsl
-
-static inline unsigned int inw_be(void __iomem *addr)
-{
- unsigned int ret;
-
- __asm__ __volatile__("lduha [%1] %2, %0"
- : "=r" (ret)
- : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-
- return ret;
-}
-
-static inline void __ide_insw(void __iomem *port, void *dst, u32 count)
-{
-#ifdef DCACHE_ALIASING_POSSIBLE
- unsigned long end = (unsigned long)dst + (count << 1);
-#endif
- u16 *ps = dst;
- u32 *pi;
-
- if(((u64)ps) & 0x2) {
- *ps++ = inw_be(port);
- count--;
- }
- pi = (u32 *)ps;
- while(count >= 2) {
- u32 w;
-
- w = inw_be(port) << 16;
- w |= inw_be(port);
- *pi++ = w;
- count -= 2;
- }
- ps = (u16 *)pi;
- if(count)
- *ps++ = inw_be(port);
-
-#ifdef DCACHE_ALIASING_POSSIBLE
- __flush_dcache_range((unsigned long)dst, end);
-#endif
-}
-
-static inline void outw_be(unsigned short w, void __iomem *addr)
-{
- __asm__ __volatile__("stha %0, [%1] %2"
- : /* no outputs */
- : "r" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-}
-
-static inline void __ide_outsw(void __iomem *port, void *src, u32 count)
-{
-#ifdef DCACHE_ALIASING_POSSIBLE
- unsigned long end = (unsigned long)src + (count << 1);
-#endif
- const u16 *ps = src;
- const u32 *pi;
-
- if(((u64)src) & 0x2) {
- outw_be(*ps++, port);
- count--;
- }
- pi = (const u32 *)ps;
- while(count >= 2) {
- u32 w;
-
- w = *pi++;
- outw_be((w >> 16), port);
- outw_be(w, port);
- count -= 2;
- }
- ps = (const u16 *)pi;
- if(count)
- outw_be(*ps, port);
-
-#ifdef DCACHE_ALIASING_POSSIBLE
- __flush_dcache_range((unsigned long)src, end);
-#endif
-}
-
-#endif /* __KERNEL__ */
-
-#endif /* _SPARC64_IDE_H */
diff --git a/include/asm-sparc/io_32.h b/include/asm-sparc/io_32.h
index c43af722ae8..10d7da45007 100644
--- a/include/asm-sparc/io_32.h
+++ b/include/asm-sparc/io_32.h
@@ -244,6 +244,7 @@ _memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n)
*/
extern void __iomem *ioremap(unsigned long offset, unsigned long size);
#define ioremap_nocache(X,Y) ioremap((X),(Y))
+#define ioremap_wc(X,Y) ioremap((X),(Y))
extern void iounmap(volatile void __iomem *addr);
#define ioread8(X) readb(X)
diff --git a/include/asm-sparc/io_64.h b/include/asm-sparc/io_64.h
index f4907414b39..0bff078ffdd 100644
--- a/include/asm-sparc/io_64.h
+++ b/include/asm-sparc/io_64.h
@@ -16,7 +16,6 @@
/* BIO layer definitions. */
extern unsigned long kern_base, kern_size;
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
-#define BIO_VMERGE_BOUNDARY 8192
static inline u8 _inb(unsigned long addr)
{
@@ -461,6 +460,7 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
}
#define ioremap_nocache(X,Y) ioremap((X),(Y))
+#define ioremap_wc(X,Y) ioremap((X),(Y))
static inline void iounmap(volatile void __iomem *addr)
{
diff --git a/include/asm-sparc/kvm.h b/include/asm-sparc/kvm.h
deleted file mode 100644
index 2e5478da381..00000000000
--- a/include/asm-sparc/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_SPARC_H
-#define __LINUX_KVM_SPARC_H
-
-/* sparc does not support KVM */
-
-#endif
diff --git a/include/asm-sparc/page_32.h b/include/asm-sparc/page_32.h
index 14de518cc38..cf5fb70ca1c 100644
--- a/include/asm-sparc/page_32.h
+++ b/include/asm-sparc/page_32.h
@@ -134,9 +134,6 @@ BTFIXUPDEF_SETHI(sparc_unmapped_base)
#endif /* !(__ASSEMBLY__) */
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
#define PAGE_OFFSET 0xf0000000
#ifndef __ASSEMBLY__
extern unsigned long phys_base;
diff --git a/include/asm-sparc/page_64.h b/include/asm-sparc/page_64.h
index a8a2bba032c..b579b910ef5 100644
--- a/include/asm-sparc/page_64.h
+++ b/include/asm-sparc/page_64.h
@@ -106,9 +106,6 @@ typedef struct page *pgtable_t;
#endif /* !(__ASSEMBLY__) */
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
/* We used to stick this into a hard-coded global register (%g4)
* but that does not make sense anymore.
*/
diff --git a/include/asm-sparc/semaphore.h b/include/asm-sparc/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-sparc/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-sparc/thread_info_32.h b/include/asm-sparc/thread_info_32.h
index 91b9f5888c8..2cf9db04405 100644
--- a/include/asm-sparc/thread_info_32.h
+++ b/include/asm-sparc/thread_info_32.h
@@ -86,6 +86,8 @@ register struct thread_info *current_thread_info_reg asm("g6");
#define THREAD_INFO_ORDER 1
#endif
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info, void)
#define alloc_thread_info(tsk) BTFIXUP_CALL(alloc_thread_info)()
diff --git a/include/asm-sparc/thread_info_64.h b/include/asm-sparc/thread_info_64.h
index c6d2e6c7f84..960969d5ad0 100644
--- a/include/asm-sparc/thread_info_64.h
+++ b/include/asm-sparc/thread_info_64.h
@@ -155,6 +155,8 @@ register struct thread_info *current_thread_info_reg asm("g6");
#define __THREAD_INFO_ORDER 0
#endif /* PAGE_SHIFT == 13 */
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
#ifdef CONFIG_DEBUG_STACK_USAGE
#define alloc_thread_info(tsk) \
({ \
diff --git a/include/asm-sparc/unistd_32.h b/include/asm-sparc/unistd_32.h
index 2338a027637..648643a9f13 100644
--- a/include/asm-sparc/unistd_32.h
+++ b/include/asm-sparc/unistd_32.h
@@ -332,8 +332,14 @@
#define __NR_fallocate 314
#define __NR_timerfd_settime 315
#define __NR_timerfd_gettime 316
+#define __NR_signalfd4 317
+#define __NR_eventfd2 318
+#define __NR_epoll_create1 319
+#define __NR_dup3 320
+#define __NR_pipe2 321
+#define __NR_inotify_init1 322
-#define NR_SYSCALLS 317
+#define NR_SYSCALLS 323
/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
* it never had the plain ones and there is no value to adding those
diff --git a/include/asm-sparc/unistd_64.h b/include/asm-sparc/unistd_64.h
index 13be4453a1f..c5cc0e05232 100644
--- a/include/asm-sparc/unistd_64.h
+++ b/include/asm-sparc/unistd_64.h
@@ -334,8 +334,14 @@
#define __NR_fallocate 314
#define __NR_timerfd_settime 315
#define __NR_timerfd_gettime 316
+#define __NR_signalfd4 317
+#define __NR_eventfd2 318
+#define __NR_epoll_create1 319
+#define __NR_dup3 320
+#define __NR_pipe2 321
+#define __NR_inotify_init1 322
-#define NR_SYSCALLS 317
+#define NR_SYSCALLS 323
#ifdef __KERNEL__
#define __ARCH_WANT_IPC_PARSE_VERSION
diff --git a/include/asm-sparc64/kvm.h b/include/asm-sparc64/kvm.h
deleted file mode 100644
index 53564ad86b1..00000000000
--- a/include/asm-sparc64/kvm.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/kvm.h>
diff --git a/include/asm-sparc64/semaphore.h b/include/asm-sparc64/semaphore.h
deleted file mode 100644
index 39362afde5f..00000000000
--- a/include/asm-sparc64/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-sparc/semaphore.h>
diff --git a/include/asm-um/kvm.h b/include/asm-um/kvm.h
deleted file mode 100644
index 66aa7709455..00000000000
--- a/include/asm-um/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_UM_H
-#define __LINUX_KVM_UM_H
-
-/* um does not support KVM */
-
-#endif
diff --git a/include/asm-um/page.h b/include/asm-um/page.h
index 916e1a61999..a6df1f13d73 100644
--- a/include/asm-um/page.h
+++ b/include/asm-um/page.h
@@ -92,9 +92,6 @@ typedef struct page *pgtable_t;
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
extern unsigned long uml_physmem;
#define PAGE_OFFSET (uml_physmem)
@@ -118,9 +115,6 @@ extern unsigned long uml_physmem;
#define pfn_valid(pfn) ((pfn) < max_mapnr)
#define virt_addr_valid(v) pfn_valid(phys_to_pfn(__pa(v)))
-extern struct page *arch_validate(struct page *page, gfp_t mask, int order);
-#define HAVE_ARCH_VALIDATE
-
#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
diff --git a/include/asm-um/ptrace-generic.h b/include/asm-um/ptrace-generic.h
index 6aefcd32fc6..315749705ea 100644
--- a/include/asm-um/ptrace-generic.h
+++ b/include/asm-um/ptrace-generic.h
@@ -47,9 +47,6 @@ extern int set_fpregs(struct user_i387_struct __user *buf,
extern void show_regs(struct pt_regs *regs);
-extern void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs,
- int error_code);
-
extern int arch_copy_tls(struct task_struct *new);
extern void clear_flushed_tls(struct task_struct *task);
diff --git a/include/asm-um/semaphore.h b/include/asm-um/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-um/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index 356b83e2c22..e07e72846c7 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -53,21 +53,7 @@ static inline struct thread_info *current_thread_info(void)
return ti;
}
-#ifdef CONFIG_DEBUG_STACK_USAGE
-
-#define alloc_thread_info(tsk) \
- ((struct thread_info *) __get_free_pages(GFP_KERNEL | __GFP_ZERO, \
- CONFIG_KERNEL_STACK_ORDER))
-#else
-
-/* thread information allocation */
-#define alloc_thread_info(tsk) \
- ((struct thread_info *) __get_free_pages(GFP_KERNEL, \
- CONFIG_KERNEL_STACK_ORDER))
-#endif
-
-#define free_thread_info(ti) \
- free_pages((unsigned long)(ti),CONFIG_KERNEL_STACK_ORDER)
+#define THREAD_SIZE_ORDER CONFIG_KERNEL_STACK_ORDER
#endif
diff --git a/include/asm-v850/Kbuild b/include/asm-v850/Kbuild
deleted file mode 100644
index c68e1680da0..00000000000
--- a/include/asm-v850/Kbuild
+++ /dev/null
@@ -1 +0,0 @@
-include include/asm-generic/Kbuild.asm
diff --git a/include/asm-v850/a.out.h b/include/asm-v850/a.out.h
deleted file mode 100644
index e9439a0708f..00000000000
--- a/include/asm-v850/a.out.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __V850_A_OUT_H__
-#define __V850_A_OUT_H__
-
-struct exec
-{
- unsigned long a_info; /* Use macros N_MAGIC, etc for access */
- unsigned a_text; /* length of text, in bytes */
- unsigned a_data; /* length of data, in bytes */
- unsigned a_bss; /* length of uninitialized data area for file, in bytes */
- unsigned a_syms; /* length of symbol table data in file, in bytes */
- unsigned a_entry; /* start address */
- unsigned a_trsize; /* length of relocation info for text, in bytes */
- unsigned a_drsize; /* length of relocation info for data, in bytes */
-};
-
-#define N_TRSIZE(a) ((a).a_trsize)
-#define N_DRSIZE(a) ((a).a_drsize)
-#define N_SYMSIZE(a) ((a).a_syms)
-
-
-#endif /* __V850_A_OUT_H__ */
diff --git a/include/asm-v850/anna.h b/include/asm-v850/anna.h
deleted file mode 100644
index cd5eaee103b..00000000000
--- a/include/asm-v850/anna.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * include/asm-v850/anna.h -- Anna V850E2 evaluation cpu chip/board
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_ANNA_H__
-#define __V850_ANNA_H__
-
-#include <asm/v850e2.h> /* Based on V850E2 core. */
-
-
-#define CPU_MODEL "v850e2/anna"
-#define CPU_MODEL_LONG "NEC V850E2/Anna"
-#define PLATFORM "anna"
-#define PLATFORM_LONG "NEC/Midas lab V850E2/Anna evaluation board"
-
-#define CPU_CLOCK_FREQ 200000000 /* 200MHz */
-#define SYS_CLOCK_FREQ 33300000 /* 33.3MHz */
-
-
-/* 1MB of static RAM. This memory is mirrored 64 times. */
-#define SRAM_ADDR 0x04000000
-#define SRAM_SIZE 0x00100000 /* 1MB */
-/* 64MB of DRAM. */
-#define SDRAM_ADDR 0x08000000
-#define SDRAM_SIZE 0x04000000 /* 64MB */
-
-
-/* For <asm/page.h> */
-#define PAGE_OFFSET SRAM_ADDR
-
-/* We use on-chip RAM, for a few miscellaneous variables that must be
- accessible using a load instruction relative to R0. The Anna chip has
- 128K of `dLB' ram nominally located at 0xFFF00000, but it's mirrored
- every 128K, so we can use the `last mirror' (except for the portion at
- the top which is overridden by I/O space). In addition, the early
- sample chip we're using has lots of memory errors in the dLB ram, so we
- use a specially chosen location that has at least 20 bytes of contiguous
- valid memory (xxxF0020 - xxxF003F). */
-#define R0_RAM_ADDR 0xFFFF8020
-
-
-/* Anna specific control registers. */
-#define ANNA_ILBEN_ADDR 0xFFFFF7F2
-#define ANNA_ILBEN (*(volatile u16 *)ANNA_ILBEN_ADDR)
-
-
-/* I/O port P0-P3. */
-/* Direct I/O. Bits 0-7 are pins Pn0-Pn7. */
-#define ANNA_PORT_IO_ADDR(n) (0xFFFFF400 + (n) * 2)
-#define ANNA_PORT_IO(n) (*(volatile u8 *)ANNA_PORT_IO_ADDR(n))
-/* Port mode (for direct I/O, 0 = output, 1 = input). */
-#define ANNA_PORT_PM_ADDR(n) (0xFFFFF410 + (n) * 2)
-#define ANNA_PORT_PM(n) (*(volatile u8 *)ANNA_PORT_PM_ADDR(n))
-
-
-/* Hardware-specific interrupt numbers (in the kernel IRQ namespace). */
-#define IRQ_INTP(n) (n) /* Pnnn (pin) interrupts 0-15 */
-#define IRQ_INTP_NUM 16
-#define IRQ_INTOV(n) (0x10 + (n)) /* 0-2 */
-#define IRQ_INTOV_NUM 2
-#define IRQ_INTCCC(n) (0x12 + (n))
-#define IRQ_INTCCC_NUM 4
-#define IRQ_INTCMD(n) (0x16 + (n)) /* interval timer interrupts 0-5 */
-#define IRQ_INTCMD_NUM 6
-#define IRQ_INTDMA(n) (0x1C + (n)) /* DMA interrupts 0-3 */
-#define IRQ_INTDMA_NUM 4
-#define IRQ_INTDMXER 0x20
-#define IRQ_INTSRE(n) (0x21 + (n)*3) /* UART 0-1 reception error */
-#define IRQ_INTSRE_NUM 2
-#define IRQ_INTSR(n) (0x22 + (n)*3) /* UART 0-1 reception completion */
-#define IRQ_INTSR_NUM 2
-#define IRQ_INTST(n) (0x23 + (n)*3) /* UART 0-1 transmission completion */
-#define IRQ_INTST_NUM 2
-
-#define NUM_CPU_IRQS 64
-
-#ifndef __ASSEMBLY__
-/* Initialize chip interrupts. */
-extern void anna_init_irqs (void);
-#endif
-
-
-/* Anna UART details (basically the same as the V850E/MA1, but 2 channels). */
-#define V850E_UART_NUM_CHANNELS 2
-#define V850E_UART_BASE_FREQ (SYS_CLOCK_FREQ / 2)
-#define V850E_UART_CHIP_NAME "V850E2/NA85E2A"
-
-/* This is the UART channel that's actually connected on the board. */
-#define V850E_UART_CONSOLE_CHANNEL 1
-
-/* This is a function that gets called before configuring the UART. */
-#define V850E_UART_PRE_CONFIGURE anna_uart_pre_configure
-#ifndef __ASSEMBLY__
-extern void anna_uart_pre_configure (unsigned chan,
- unsigned cflags, unsigned baud);
-#endif
-
-/* This board supports RTS/CTS for the on-chip UART, but only for channel 1. */
-
-/* CTS for UART channel 1 is pin P37 (bit 7 of port 3). */
-#define V850E_UART_CTS(chan) ((chan) == 1 ? !(ANNA_PORT_IO(3) & 0x80) : 1)
-/* RTS for UART channel 1 is pin P07 (bit 7 of port 0). */
-#define V850E_UART_SET_RTS(chan, val) \
- do { \
- if (chan == 1) { \
- unsigned old = ANNA_PORT_IO(0); \
- if (val) \
- ANNA_PORT_IO(0) = old & ~0x80; \
- else \
- ANNA_PORT_IO(0) = old | 0x80; \
- } \
- } while (0)
-
-
-/* Timer C details. */
-#define V850E_TIMER_C_BASE_ADDR 0xFFFFF600
-
-/* Timer D details (the Anna actually has 5 of these; should change later). */
-#define V850E_TIMER_D_BASE_ADDR 0xFFFFF540
-#define V850E_TIMER_D_TMD_BASE_ADDR (V850E_TIMER_D_BASE_ADDR + 0x0)
-#define V850E_TIMER_D_CMD_BASE_ADDR (V850E_TIMER_D_BASE_ADDR + 0x2)
-#define V850E_TIMER_D_TMCD_BASE_ADDR (V850E_TIMER_D_BASE_ADDR + 0x4)
-
-#define V850E_TIMER_D_BASE_FREQ SYS_CLOCK_FREQ
-#define V850E_TIMER_D_TMCD_CS_MIN 1 /* min 2^1 divider */
-
-
-#endif /* __V850_ANNA_H__ */
diff --git a/include/asm-v850/as85ep1.h b/include/asm-v850/as85ep1.h
deleted file mode 100644
index 5a5ca9073d0..00000000000
--- a/include/asm-v850/as85ep1.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * include/asm-v850/as85ep1.h -- AS85EP1 evaluation CPU chip/board
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_AS85EP1_H__
-#define __V850_AS85EP1_H__
-
-#include <asm/v850e.h>
-
-
-#define CPU_MODEL "as85ep1"
-#define CPU_MODEL_LONG "NEC V850E/AS85EP1"
-#define PLATFORM "AS85EP1"
-#define PLATFORM_LONG "NEC V850E/AS85EP1 evaluation board"
-
-#define CPU_CLOCK_FREQ 96000000 /* 96MHz */
-#define SYS_CLOCK_FREQ CPU_CLOCK_FREQ
-
-
-/* 1MB of static RAM. */
-#define SRAM_ADDR 0x00400000
-#define SRAM_SIZE 0x00100000 /* 1MB */
-/* About 58MB of DRAM. This can actually be at one of two positions,
- determined by jump JP3; we have to use the first position because the
- second is partially out of processor instruction addressing range
- (though in the second position there's actually 64MB available). */
-#define SDRAM_ADDR 0x00600000
-#define SDRAM_SIZE 0x039F8000 /* approx 58MB */
-
-/* For <asm/page.h> */
-#define PAGE_OFFSET SRAM_ADDR
-
-/* We use on-chip RAM, for a few miscellaneous variables that must be
- accessible using a load instruction relative to R0. The AS85EP1 chip
- 16K of internal RAM located slightly before I/O space. */
-#define R0_RAM_ADDR 0xFFFF8000
-
-
-/* AS85EP1 specific control registers. */
-#define AS85EP1_CSC_ADDR(n) (0xFFFFF060 + (n) * 2)
-#define AS85EP1_CSC(n) (*(volatile u16 *)AS85EP1_CSC_ADDR(n))
-#define AS85EP1_BSC_ADDR 0xFFFFF066
-#define AS85EP1_BSC (*(volatile u16 *)AS85EP1_BSC_ADDR)
-#define AS85EP1_BCT_ADDR(n) (0xFFFFF480 + (n) * 2)
-#define AS85EP1_BCT(n) (*(volatile u16 *)AS85EP1_BCT_ADDR(n))
-#define AS85EP1_DWC_ADDR(n) (0xFFFFF484 + (n) * 2)
-#define AS85EP1_DWC(n) (*(volatile u16 *)AS85EP1_DWC_ADDR(n))
-#define AS85EP1_BCC_ADDR 0xFFFFF488
-#define AS85EP1_BCC (*(volatile u16 *)AS85EP1_BCC_ADDR)
-#define AS85EP1_ASC_ADDR 0xFFFFF48A
-#define AS85EP1_ASC (*(volatile u16 *)AS85EP1_ASC_ADDR)
-#define AS85EP1_BCP_ADDR 0xFFFFF48C
-#define AS85EP1_BCP (*(volatile u16 *)AS85EP1_BCP_ADDR)
-#define AS85EP1_LBS_ADDR 0xFFFFF48E
-#define AS85EP1_LBS (*(volatile u16 *)AS85EP1_LBS_ADDR)
-#define AS85EP1_BMC_ADDR 0xFFFFF498
-#define AS85EP1_BMC (*(volatile u16 *)AS85EP1_BMC_ADDR)
-#define AS85EP1_PRC_ADDR 0xFFFFF49A
-#define AS85EP1_PRC (*(volatile u16 *)AS85EP1_PRC_ADDR)
-#define AS85EP1_SCR_ADDR(n) (0xFFFFF4A0 + (n) * 4)
-#define AS85EP1_SCR(n) (*(volatile u16 *)AS85EP1_SCR_ADDR(n))
-#define AS85EP1_RFS_ADDR(n) (0xFFFFF4A2 + (n) * 4)
-#define AS85EP1_RFS(n) (*(volatile u16 *)AS85EP1_RFS_ADDR(n))
-#define AS85EP1_IRAMM_ADDR 0xFFFFF80A
-#define AS85EP1_IRAMM (*(volatile u8 *)AS85EP1_IRAMM_ADDR)
-
-
-
-/* I/O port P0-P13. */
-/* Direct I/O. Bits 0-7 are pins Pn0-Pn7. */
-#define AS85EP1_PORT_IO_ADDR(n) (0xFFFFF400 + (n) * 2)
-#define AS85EP1_PORT_IO(n) (*(volatile u8 *)AS85EP1_PORT_IO_ADDR(n))
-/* Port mode (for direct I/O, 0 = output, 1 = input). */
-#define AS85EP1_PORT_PM_ADDR(n) (0xFFFFF420 + (n) * 2)
-#define AS85EP1_PORT_PM(n) (*(volatile u8 *)AS85EP1_PORT_PM_ADDR(n))
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode). */
-#define AS85EP1_PORT_PMC_ADDR(n) (0xFFFFF440 + (n) * 2)
-#define AS85EP1_PORT_PMC(n) (*(volatile u8 *)AS85EP1_PORT_PMC_ADDR(n))
-
-
-/* Hardware-specific interrupt numbers (in the kernel IRQ namespace). */
-#define IRQ_INTCCC(n) (0x0C + (n))
-#define IRQ_INTCCC_NUM 8
-#define IRQ_INTCMD(n) (0x14 + (n)) /* interval timer interrupts 0-5 */
-#define IRQ_INTCMD_NUM 6
-#define IRQ_INTSRE(n) (0x1E + (n)*3) /* UART 0-1 reception error */
-#define IRQ_INTSRE_NUM 2
-#define IRQ_INTSR(n) (0x1F + (n)*3) /* UART 0-1 reception completion */
-#define IRQ_INTSR_NUM 2
-#define IRQ_INTST(n) (0x20 + (n)*3) /* UART 0-1 transmission completion */
-#define IRQ_INTST_NUM 2
-
-#define NUM_CPU_IRQS 64
-
-#ifndef __ASSEMBLY__
-/* Initialize chip interrupts. */
-extern void as85ep1_init_irqs (void);
-#endif
-
-
-/* AS85EP1 UART details (basically the same as the V850E/MA1, but 2 channels). */
-#define V850E_UART_NUM_CHANNELS 2
-#define V850E_UART_BASE_FREQ (SYS_CLOCK_FREQ / 4)
-#define V850E_UART_CHIP_NAME "V850E/NA85E"
-
-/* This is a function that gets called before configuring the UART. */
-#define V850E_UART_PRE_CONFIGURE as85ep1_uart_pre_configure
-#ifndef __ASSEMBLY__
-extern void as85ep1_uart_pre_configure (unsigned chan,
- unsigned cflags, unsigned baud);
-#endif
-
-/* This board supports RTS/CTS for the on-chip UART, but only for channel 1. */
-
-/* CTS for UART channel 1 is pin P54 (bit 4 of port 5). */
-#define V850E_UART_CTS(chan) ((chan) == 1 ? !(AS85EP1_PORT_IO(5) & 0x10) : 1)
-/* RTS for UART channel 1 is pin P53 (bit 3 of port 5). */
-#define V850E_UART_SET_RTS(chan, val) \
- do { \
- if (chan == 1) { \
- unsigned old = AS85EP1_PORT_IO(5); \
- if (val) \
- AS85EP1_PORT_IO(5) = old & ~0x8; \
- else \
- AS85EP1_PORT_IO(5) = old | 0x8; \
- } \
- } while (0)
-
-
-/* Timer C details. */
-#define V850E_TIMER_C_BASE_ADDR 0xFFFFF600
-
-/* Timer D details (the AS85EP1 actually has 5 of these; should change later). */
-#define V850E_TIMER_D_BASE_ADDR 0xFFFFF540
-#define V850E_TIMER_D_TMD_BASE_ADDR (V850E_TIMER_D_BASE_ADDR + 0x0)
-#define V850E_TIMER_D_CMD_BASE_ADDR (V850E_TIMER_D_BASE_ADDR + 0x2)
-#define V850E_TIMER_D_TMCD_BASE_ADDR (V850E_TIMER_D_BASE_ADDR + 0x4)
-
-#define V850E_TIMER_D_BASE_FREQ SYS_CLOCK_FREQ
-#define V850E_TIMER_D_TMCD_CS_MIN 2 /* min 2^2 divider */
-
-
-#endif /* __V850_AS85EP1_H__ */
diff --git a/include/asm-v850/asm.h b/include/asm-v850/asm.h
deleted file mode 100644
index bf1e785a5dd..00000000000
--- a/include/asm-v850/asm.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * include/asm-v850/asm.h -- Macros for writing assembly code
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#define G_ENTRY(name) \
- .balign 4; \
- .globl name; \
- .type name,@function; \
- name
-#define G_DATA(name) \
- .globl name; \
- .type name,@object; \
- name
-#define END(name) \
- .size name,.-name
-
-#define L_ENTRY(name) \
- .balign 4; \
- .type name,@function; \
- name
-#define L_DATA(name) \
- .type name,@object; \
- name
diff --git a/include/asm-v850/atomic.h b/include/asm-v850/atomic.h
deleted file mode 100644
index e4e57de08f7..00000000000
--- a/include/asm-v850/atomic.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * include/asm-v850/atomic.h -- Atomic operations
- *
- * Copyright (C) 2001,02 NEC Corporation
- * Copyright (C) 2001,02 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_ATOMIC_H__
-#define __V850_ATOMIC_H__
-
-
-#include <asm/system.h>
-
-#ifdef CONFIG_SMP
-#error SMP not supported
-#endif
-
-typedef struct { int counter; } atomic_t;
-
-#define ATOMIC_INIT(i) { (i) }
-
-#ifdef __KERNEL__
-
-#define atomic_read(v) ((v)->counter)
-#define atomic_set(v,i) (((v)->counter) = (i))
-
-static inline int atomic_add_return (int i, volatile atomic_t *v)
-{
- unsigned long flags;
- int res;
-
- local_irq_save (flags);
- res = v->counter + i;
- v->counter = res;
- local_irq_restore (flags);
-
- return res;
-}
-
-static __inline__ int atomic_sub_return (int i, volatile atomic_t *v)
-{
- unsigned long flags;
- int res;
-
- local_irq_save (flags);
- res = v->counter - i;
- v->counter = res;
- local_irq_restore (flags);
-
- return res;
-}
-
-static __inline__ void atomic_clear_mask (unsigned long mask, unsigned long *addr)
-{
- unsigned long flags;
-
- local_irq_save (flags);
- *addr &= ~mask;
- local_irq_restore (flags);
-}
-
-#endif
-
-#define atomic_add(i, v) atomic_add_return ((i), (v))
-#define atomic_sub(i, v) atomic_sub_return ((i), (v))
-
-#define atomic_dec_return(v) atomic_sub_return (1, (v))
-#define atomic_inc_return(v) atomic_add_return (1, (v))
-#define atomic_inc(v) atomic_inc_return (v)
-#define atomic_dec(v) atomic_dec_return (v)
-
-/*
- * atomic_inc_and_test - increment and test
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1
- * and returns true if the result is zero, or false for all
- * other cases.
- */
-#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
-
-#define atomic_sub_and_test(i,v) (atomic_sub_return ((i), (v)) == 0)
-#define atomic_dec_and_test(v) (atomic_sub_return (1, (v)) == 0)
-#define atomic_add_negative(i,v) (atomic_add_return ((i), (v)) < 0)
-
-static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
-{
- int ret;
- unsigned long flags;
-
- local_irq_save(flags);
- ret = v->counter;
- if (likely(ret == old))
- v->counter = new;
- local_irq_restore(flags);
-
- return ret;
-}
-
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
-{
- int ret;
- unsigned long flags;
-
- local_irq_save(flags);
- ret = v->counter;
- if (ret != u)
- v->counter += a;
- local_irq_restore(flags);
-
- return ret != u;
-}
-
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-
-/* Atomic operations are already serializing on ARM */
-#define smp_mb__before_atomic_dec() barrier()
-#define smp_mb__after_atomic_dec() barrier()
-#define smp_mb__before_atomic_inc() barrier()
-#define smp_mb__after_atomic_inc() barrier()
-
-#include <asm-generic/atomic.h>
-#endif /* __V850_ATOMIC_H__ */
diff --git a/include/asm-v850/auxvec.h b/include/asm-v850/auxvec.h
deleted file mode 100644
index f493232d022..00000000000
--- a/include/asm-v850/auxvec.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __V850_AUXVEC_H__
-#define __V850_AUXVEC_H__
-
-#endif /* __V850_AUXVEC_H__ */
diff --git a/include/asm-v850/bitops.h b/include/asm-v850/bitops.h
deleted file mode 100644
index f82f5b4a56e..00000000000
--- a/include/asm-v850/bitops.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * include/asm-v850/bitops.h -- Bit operations
- *
- * Copyright (C) 2001,02,03,04,05 NEC Electronics Corporation
- * Copyright (C) 2001,02,03,04,05 Miles Bader <miles@gnu.org>
- * Copyright (C) 1992 Linus Torvalds.
- *
- * 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.
- */
-
-#ifndef __V850_BITOPS_H__
-#define __V850_BITOPS_H__
-
-#ifndef _LINUX_BITOPS_H
-#error only <linux/bitops.h> can be included directly
-#endif
-
-#include <linux/compiler.h> /* unlikely */
-#include <asm/byteorder.h> /* swab32 */
-#include <asm/system.h> /* interrupt enable/disable */
-
-
-#ifdef __KERNEL__
-
-#include <asm-generic/bitops/ffz.h>
-
-/*
- * The __ functions are not atomic
- */
-
-/* In the following constant-bit-op macros, a "g" constraint is used when
- we really need an integer ("i" constraint). This is to avoid
- warnings/errors from the compiler in the case where the associated
- operand _isn't_ an integer, and shouldn't produce bogus assembly because
- use of that form is protected by a guard statement that checks for
- constants, and should otherwise be removed by the optimizer. This
- _usually_ works -- however, __builtin_constant_p returns true for a
- variable with a known constant value too, and unfortunately gcc will
- happily put the variable in a register and use the register for the "g"
- constraint'd asm operand. To avoid the latter problem, we add a
- constant offset to the operand and subtract it back in the asm code;
- forcing gcc to do arithmetic on the value is usually enough to get it
- to use a real constant value. This is horrible, and ultimately
- unreliable too, but it seems to work for now (hopefully gcc will offer
- us more control in the future, so we can do a better job). */
-
-#define __const_bit_op(op, nr, addr) \
- ({ __asm__ (op " (%0 - 0x123), %1" \
- :: "g" (((nr) & 0x7) + 0x123), \
- "m" (*((char *)(addr) + ((nr) >> 3))) \
- : "memory"); })
-#define __var_bit_op(op, nr, addr) \
- ({ int __nr = (nr); \
- __asm__ (op " %0, [%1]" \
- :: "r" (__nr & 0x7), \
- "r" ((char *)(addr) + (__nr >> 3)) \
- : "memory"); })
-#define __bit_op(op, nr, addr) \
- ((__builtin_constant_p (nr) && (unsigned)(nr) <= 0x7FFFF) \
- ? __const_bit_op (op, nr, addr) \
- : __var_bit_op (op, nr, addr))
-
-#define __set_bit(nr, addr) __bit_op ("set1", nr, addr)
-#define __clear_bit(nr, addr) __bit_op ("clr1", nr, addr)
-#define __change_bit(nr, addr) __bit_op ("not1", nr, addr)
-
-/* The bit instructions used by `non-atomic' variants are actually atomic. */
-#define set_bit __set_bit
-#define clear_bit __clear_bit
-#define change_bit __change_bit
-
-
-#define __const_tns_bit_op(op, nr, addr) \
- ({ int __tns_res; \
- __asm__ __volatile__ ( \
- "tst1 (%1 - 0x123), %2; setf nz, %0; " op " (%1 - 0x123), %2" \
- : "=&r" (__tns_res) \
- : "g" (((nr) & 0x7) + 0x123), \
- "m" (*((char *)(addr) + ((nr) >> 3))) \
- : "memory"); \
- __tns_res; \
- })
-#define __var_tns_bit_op(op, nr, addr) \
- ({ int __nr = (nr); \
- int __tns_res; \
- __asm__ __volatile__ ( \
- "tst1 %1, [%2]; setf nz, %0; " op " %1, [%2]" \
- : "=&r" (__tns_res) \
- : "r" (__nr & 0x7), \
- "r" ((char *)(addr) + (__nr >> 3)) \
- : "memory"); \
- __tns_res; \
- })
-#define __tns_bit_op(op, nr, addr) \
- ((__builtin_constant_p (nr) && (unsigned)(nr) <= 0x7FFFF) \
- ? __const_tns_bit_op (op, nr, addr) \
- : __var_tns_bit_op (op, nr, addr))
-#define __tns_atomic_bit_op(op, nr, addr) \
- ({ int __tns_atomic_res, __tns_atomic_flags; \
- local_irq_save (__tns_atomic_flags); \
- __tns_atomic_res = __tns_bit_op (op, nr, addr); \
- local_irq_restore (__tns_atomic_flags); \
- __tns_atomic_res; \
- })
-
-#define __test_and_set_bit(nr, addr) __tns_bit_op ("set1", nr, addr)
-#define test_and_set_bit(nr, addr) __tns_atomic_bit_op ("set1", nr, addr)
-
-#define __test_and_clear_bit(nr, addr) __tns_bit_op ("clr1", nr, addr)
-#define test_and_clear_bit(nr, addr) __tns_atomic_bit_op ("clr1", nr, addr)
-
-#define __test_and_change_bit(nr, addr) __tns_bit_op ("not1", nr, addr)
-#define test_and_change_bit(nr, addr) __tns_atomic_bit_op ("not1", nr, addr)
-
-
-#define __const_test_bit(nr, addr) \
- ({ int __test_bit_res; \
- __asm__ __volatile__ ("tst1 (%1 - 0x123), %2; setf nz, %0" \
- : "=r" (__test_bit_res) \
- : "g" (((nr) & 0x7) + 0x123), \
- "m" (*((const char *)(addr) + ((nr) >> 3)))); \
- __test_bit_res; \
- })
-static inline int __test_bit (int nr, const void *addr)
-{
- int res;
- __asm__ __volatile__ ("tst1 %1, [%2]; setf nz, %0"
- : "=r" (res)
- : "r" (nr & 0x7), "r" (addr + (nr >> 3)));
- return res;
-}
-#define test_bit(nr,addr) \
- ((__builtin_constant_p (nr) && (unsigned)(nr) <= 0x7FFFF) \
- ? __const_test_bit ((nr), (addr)) \
- : __test_bit ((nr), (addr)))
-
-
-/* clear_bit doesn't provide any barrier for the compiler. */
-#define smp_mb__before_clear_bit() barrier ()
-#define smp_mb__after_clear_bit() barrier ()
-
-#include <asm-generic/bitops/ffs.h>
-#include <asm-generic/bitops/fls.h>
-#include <asm-generic/bitops/fls64.h>
-#include <asm-generic/bitops/__ffs.h>
-#include <asm-generic/bitops/find.h>
-#include <asm-generic/bitops/sched.h>
-#include <asm-generic/bitops/hweight.h>
-#include <asm-generic/bitops/lock.h>
-
-#include <asm-generic/bitops/ext2-non-atomic.h>
-#define ext2_set_bit_atomic(l,n,a) test_and_set_bit(n,a)
-#define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a)
-
-#include <asm-generic/bitops/minix.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* __V850_BITOPS_H__ */
diff --git a/include/asm-v850/bug.h b/include/asm-v850/bug.h
deleted file mode 100644
index b0ed2d35f3e..00000000000
--- a/include/asm-v850/bug.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * include/asm-v850/bug.h -- Bug reporting
- *
- * Copyright (C) 2003 NEC Electronics Corporation
- * Copyright (C) 2003 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_BUG_H__
-#define __V850_BUG_H__
-
-#ifdef CONFIG_BUG
-extern void __bug (void) __attribute__ ((noreturn));
-#define BUG() __bug()
-#define HAVE_ARCH_BUG
-#endif
-
-#include <asm-generic/bug.h>
-
-#endif /* __V850_BUG_H__ */
diff --git a/include/asm-v850/bugs.h b/include/asm-v850/bugs.h
deleted file mode 100644
index 71110a65c1d..00000000000
--- a/include/asm-v850/bugs.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-v850e/bugs.h
- *
- * Copyright (C) 1994 Linus Torvalds
- */
-
-/*
- * This is included by init/main.c to check for architecture-dependent bugs.
- *
- * Needs:
- * void check_bugs(void);
- */
-
-static void check_bugs(void)
-{
-}
diff --git a/include/asm-v850/byteorder.h b/include/asm-v850/byteorder.h
deleted file mode 100644
index a6f07530050..00000000000
--- a/include/asm-v850/byteorder.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * include/asm-v850/byteorder.h -- Endian id and conversion ops
- *
- * Copyright (C) 2001 NEC Corporation
- * Copyright (C) 2001 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_BYTEORDER_H__
-#define __V850_BYTEORDER_H__
-
-#include <asm/types.h>
-#include <linux/compiler.h>
-
-#ifdef __GNUC__
-
-static __inline__ __attribute_const__ __u32 ___arch__swab32 (__u32 word)
-{
- __u32 res;
- __asm__ ("bsw %1, %0" : "=r" (res) : "r" (word));
- return res;
-}
-
-static __inline__ __attribute_const__ __u16 ___arch__swab16 (__u16 half_word)
-{
- __u16 res;
- __asm__ ("bsh %1, %0" : "=r" (res) : "r" (half_word));
- return res;
-}
-
-#define __arch__swab32(x) ___arch__swab32(x)
-#define __arch__swab16(x) ___arch__swab16(x)
-
-#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-# define __BYTEORDER_HAS_U64__
-# define __SWAB_64_THRU_32__
-#endif
-
-#endif /* __GNUC__ */
-
-#include <linux/byteorder/little_endian.h>
-
-#endif /* __V850_BYTEORDER_H__ */
diff --git a/include/asm-v850/cache.h b/include/asm-v850/cache.h
deleted file mode 100644
index 8832c7ea324..00000000000
--- a/include/asm-v850/cache.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * include/asm-v850/cache.h -- Cache operations
- *
- * Copyright (C) 2001,05 NEC Corporation
- * Copyright (C) 2001,05 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_CACHE_H__
-#define __V850_CACHE_H__
-
-/* All cache operations are machine-dependent. */
-#include <asm/machdep.h>
-
-#ifndef L1_CACHE_BYTES
-/* This processor has no cache, so just choose an arbitrary value. */
-#define L1_CACHE_BYTES 16
-#define L1_CACHE_SHIFT 4
-#endif
-
-#endif /* __V850_CACHE_H__ */
diff --git a/include/asm-v850/cacheflush.h b/include/asm-v850/cacheflush.h
deleted file mode 100644
index 9ece05a202e..00000000000
--- a/include/asm-v850/cacheflush.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * include/asm-v850/cacheflush.h
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_CACHEFLUSH_H__
-#define __V850_CACHEFLUSH_H__
-
-/* Somebody depends on this; sigh... */
-#include <linux/mm.h>
-
-#include <asm/machdep.h>
-
-
-/* The following are all used by the kernel in ways that only affect
- systems with MMUs, so we don't need them. */
-#define flush_cache_all() ((void)0)
-#define flush_cache_mm(mm) ((void)0)
-#define flush_cache_dup_mm(mm) ((void)0)
-#define flush_cache_range(vma, start, end) ((void)0)
-#define flush_cache_page(vma, vmaddr, pfn) ((void)0)
-#define flush_dcache_page(page) ((void)0)
-#define flush_dcache_mmap_lock(mapping) ((void)0)
-#define flush_dcache_mmap_unlock(mapping) ((void)0)
-#define flush_cache_vmap(start, end) ((void)0)
-#define flush_cache_vunmap(start, end) ((void)0)
-
-#ifdef CONFIG_NO_CACHE
-
-/* Some systems have no cache at all, in which case we don't need these
- either. */
-#define flush_icache() ((void)0)
-#define flush_icache_range(start, end) ((void)0)
-#define flush_icache_page(vma,pg) ((void)0)
-#define flush_icache_user_range(vma,pg,adr,len) ((void)0)
-#define flush_cache_sigtramp(vaddr) ((void)0)
-
-#else /* !CONFIG_NO_CACHE */
-
-struct page;
-struct mm_struct;
-struct vm_area_struct;
-
-/* Otherwise, somebody had better define them. */
-extern void flush_icache (void);
-extern void flush_icache_range (unsigned long start, unsigned long end);
-extern void flush_icache_page (struct vm_area_struct *vma, struct page *page);
-extern void flush_icache_user_range (struct vm_area_struct *vma,
- struct page *page,
- unsigned long adr, int len);
-extern void flush_cache_sigtramp (unsigned long addr);
-
-#endif /* CONFIG_NO_CACHE */
-
-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-do { memcpy(dst, src, len); \
- flush_icache_user_range(vma, page, vaddr, len); \
-} while (0)
-#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
- memcpy(dst, src, len)
-
-#endif /* __V850_CACHEFLUSH_H__ */
diff --git a/include/asm-v850/checksum.h b/include/asm-v850/checksum.h
deleted file mode 100644
index d1dddd93826..00000000000
--- a/include/asm-v850/checksum.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * include/asm-v850/checksum.h -- Checksum ops
- *
- * Copyright (C) 2001,2005 NEC Corporation
- * Copyright (C) 2001,2005 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_CHECKSUM_H__
-#define __V850_CHECKSUM_H__
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-extern __wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- * the same as csum_partial, but copies from src while it
- * checksums
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-extern __wsum csum_partial_copy_nocheck(const void *src,
- void *dst, int len, __wsum sum);
-
-
-/*
- * the same as csum_partial_copy, but copies from user space.
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-extern __wsum csum_partial_copy_from_user (const void *src,
- void *dst,
- int len, __wsum sum,
- int *csum_err);
-
-__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
-
-/*
- * Fold a partial checksum
- */
-static inline __sum16 csum_fold (__wsum sum)
-{
- unsigned int result;
- /*
- %0 %1
- hsw %1, %0 H L L H
- add %1, %0 H L H+L+C H+L
- */
- asm ("hsw %1, %0; add %1, %0" : "=&r" (result) : "r" (sum));
- return (__force __sum16)(~result >> 16);
-}
-
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-static inline __wsum
-csum_tcpudp_nofold (__be32 saddr, __be32 daddr,
- unsigned short len,
- unsigned short proto, __wsum sum)
-{
- int __carry;
- __asm__ ("add %2, %0;"
- "setf c, %1;"
- "add %1, %0;"
- "add %3, %0;"
- "setf c, %1;"
- "add %1, %0;"
- "add %4, %0;"
- "setf c, %1;"
- "add %1, %0"
- : "=&r" (sum), "=&r" (__carry)
- : "r" (daddr), "r" (saddr),
- "r" ((len + proto) << 8),
- "0" (sum));
- return sum;
-}
-
-static inline __sum16
-csum_tcpudp_magic (__be32 saddr, __be32 daddr,
- unsigned short len,
- unsigned short proto, __wsum sum)
-{
- return csum_fold (csum_tcpudp_nofold (saddr, daddr, len, proto, sum));
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-extern __sum16 ip_compute_csum(const void *buff, int len);
-
-
-#endif /* __V850_CHECKSUM_H__ */
diff --git a/include/asm-v850/clinkage.h b/include/asm-v850/clinkage.h
deleted file mode 100644
index c389691d6f8..00000000000
--- a/include/asm-v850/clinkage.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * include/asm-v850/clinkage.h -- Macros to reflect C symbol-naming conventions
- *
- * Copyright (C) 2001,02 NEC Corporatione
- * Copyright (C) 2001,02 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_CLINKAGE_H__
-#define __V850_CLINKAGE_H__
-
-#include <asm/macrology.h>
-#include <asm/asm.h>
-
-#define C_SYMBOL_NAME(name) macrology_paste(_, name)
-#define C_SYMBOL_STRING(name) macrology_stringify(C_SYMBOL_NAME(name))
-#define C_ENTRY(name) G_ENTRY(C_SYMBOL_NAME(name))
-#define C_DATA(name) G_DATA(C_SYMBOL_NAME(name))
-#define C_END(name) END(C_SYMBOL_NAME(name))
-
-#endif /* __V850_CLINKAGE_H__ */
diff --git a/include/asm-v850/cputime.h b/include/asm-v850/cputime.h
deleted file mode 100644
index 7c799c33b8a..00000000000
--- a/include/asm-v850/cputime.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_CPUTIME_H
-#define __V850_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __V850_CPUTIME_H */
diff --git a/include/asm-v850/current.h b/include/asm-v850/current.h
deleted file mode 100644
index 30aae567377..00000000000
--- a/include/asm-v850/current.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * include/asm-v850/current.h -- Current task
- *
- * Copyright (C) 2001,02 NEC Corporation
- * Copyright (C) 2001,02 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_CURRENT_H__
-#define __V850_CURRENT_H__
-
-#ifndef __ASSEMBLY__ /* <linux/thread_info.h> is not asm-safe. */
-#include <linux/thread_info.h>
-#endif
-
-#include <asm/macrology.h>
-
-
-/* Register used to hold the current task pointer while in the kernel.
- Any `call clobbered' register without a special meaning should be OK,
- but check asm/v850/kernel/entry.S to be sure. */
-#define CURRENT_TASK_REGNUM 16
-#define CURRENT_TASK macrology_paste (r, CURRENT_TASK_REGNUM)
-
-
-#ifdef __ASSEMBLY__
-
-/* Put a pointer to the current task structure into REG. */
-#define GET_CURRENT_TASK(reg) \
- GET_CURRENT_THREAD(reg); \
- ld.w TI_TASK[reg], reg
-
-#else /* !__ASSEMBLY__ */
-
-/* A pointer to the current task. */
-register struct task_struct *current \
- __asm__ (macrology_stringify (CURRENT_TASK));
-
-#endif /* __ASSEMBLY__ */
-
-
-#endif /* _V850_CURRENT_H */
diff --git a/include/asm-v850/delay.h b/include/asm-v850/delay.h
deleted file mode 100644
index 6d028e6b235..00000000000
--- a/include/asm-v850/delay.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * include/asm-v850/delay.h -- Delay routines, using a pre-computed
- * "loops_per_second" value
- *
- * Copyright (C) 2001,03 NEC Corporation
- * Copyright (C) 2001,03 Miles Bader <miles@gnu.org>
- * Copyright (C) 1994 Hamish Macdonald
- *
- * 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.
- */
-
-#ifndef __V850_DELAY_H__
-#define __V850_DELAY_H__
-
-#include <asm/param.h>
-
-static inline void __delay(unsigned long loops)
-{
- if (loops)
- __asm__ __volatile__ ("1: add -1, %0; bnz 1b"
- : "=r" (loops) : "0" (loops));
-}
-
-/*
- * Use only for very small delays ( < 1 msec). Should probably use a
- * lookup table, really, as the multiplications take much too long with
- * short delays. This is a "reasonable" implementation, though (and the
- * first constant multiplications gets optimized away if the delay is
- * a constant)
- */
-
-extern unsigned long loops_per_jiffy;
-
-static inline void udelay(unsigned long usecs)
-{
- register unsigned long full_loops, part_loops;
-
- full_loops = ((usecs * HZ) / 1000000) * loops_per_jiffy;
- usecs %= (1000000 / HZ);
- part_loops = (usecs * HZ * loops_per_jiffy) / 1000000;
-
- __delay(full_loops + part_loops);
-}
-
-#endif /* __V850_DELAY_H__ */
diff --git a/include/asm-v850/device.h b/include/asm-v850/device.h
deleted file mode 100644
index d8f9872b0e2..00000000000
--- a/include/asm-v850/device.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#include <asm-generic/device.h>
-
diff --git a/include/asm-v850/div64.h b/include/asm-v850/div64.h
deleted file mode 100644
index 6cd978cefb2..00000000000
--- a/include/asm-v850/div64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/div64.h>
diff --git a/include/asm-v850/dma-mapping.h b/include/asm-v850/dma-mapping.h
deleted file mode 100644
index 1cc42c603a1..00000000000
--- a/include/asm-v850/dma-mapping.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __V850_DMA_MAPPING_H__
-#define __V850_DMA_MAPPING_H__
-
-
-#ifdef CONFIG_PCI
-#include <asm-generic/dma-mapping.h>
-#else
-#include <asm-generic/dma-mapping-broken.h>
-#endif
-
-#endif /* __V850_DMA_MAPPING_H__ */
diff --git a/include/asm-v850/dma.h b/include/asm-v850/dma.h
deleted file mode 100644
index 2369849e2d0..00000000000
--- a/include/asm-v850/dma.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef __V850_DMA_H__
-#define __V850_DMA_H__
-
-/* What should this be? */
-#define MAX_DMA_ADDRESS 0xFFFFFFFF
-
-/* reserve a DMA channel */
-extern int request_dma (unsigned int dmanr, const char * device_id);
-/* release it again */
-extern void free_dma (unsigned int dmanr);
-
-#ifdef CONFIG_PCI
-extern int isa_dma_bridge_buggy;
-#else
-#define isa_dma_bridge_buggy (0)
-#endif
-
-#endif /* __V850_DMA_H__ */
diff --git a/include/asm-v850/elf.h b/include/asm-v850/elf.h
deleted file mode 100644
index 28f5b176ff1..00000000000
--- a/include/asm-v850/elf.h
+++ /dev/null
@@ -1,99 +0,0 @@
-#ifndef __V850_ELF_H__
-#define __V850_ELF_H__
-
-/*
- * ELF register definitions..
- */
-
-#include <asm/ptrace.h>
-#include <asm/user.h>
-#include <asm/byteorder.h>
-
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct user_fpu_struct elf_fpregset_t;
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) \
- ((x)->e_machine == EM_V850 || (x)->e_machine == EM_CYGNUS_V850)
-
-
-/* v850 relocation types. */
-#define R_V850_NONE 0
-#define R_V850_9_PCREL 1
-#define R_V850_22_PCREL 2
-#define R_V850_HI16_S 3
-#define R_V850_HI16 4
-#define R_V850_LO16 5
-#define R_V850_32 6
-#define R_V850_16 7
-#define R_V850_8 8
-#define R_V850_SDA_16_16_OFFSET 9 /* For ld.b, st.b, set1, clr1,
- not1, tst1, movea, movhi */
-#define R_V850_SDA_15_16_OFFSET 10 /* For ld.w, ld.h, ld.hu, st.w, st.h */
-#define R_V850_ZDA_16_16_OFFSET 11 /* For ld.b, st.b, set1, clr1,
- not1, tst1, movea, movhi */
-#define R_V850_ZDA_15_16_OFFSET 12 /* For ld.w, ld.h, ld.hu, st.w, st.h */
-#define R_V850_TDA_6_8_OFFSET 13 /* For sst.w, sld.w */
-#define R_V850_TDA_7_8_OFFSET 14 /* For sst.h, sld.h */
-#define R_V850_TDA_7_7_OFFSET 15 /* For sst.b, sld.b */
-#define R_V850_TDA_16_16_OFFSET 16 /* For set1, clr1, not1, tst1,
- movea, movhi */
-#define R_V850_NUM 17
-
-
-/*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_CLASS ELFCLASS32
-#ifdef __LITTLE_ENDIAN__
-#define ELF_DATA ELFDATA2LSB
-#else
-#define ELF_DATA ELFDATA2MSB
-#endif
-#define ELF_ARCH EM_V850
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 4096
-
-
-#define ELF_CORE_COPY_REGS(_dest,_regs) \
- memcpy((char *) &_dest, (char *) _regs, \
- sizeof(struct pt_regs));
-
-/* This yields a mask that user programs can use to figure out what
- instruction set this CPU supports. This could be done in user space,
- but it's not easy, and we've already done it here. */
-
-#define ELF_HWCAP (0)
-
-/* This yields a string that ld.so will use to load implementation
- specific libraries for optimization. This is more specific in
- intent than poking at uname or /proc/cpuinfo.
-
- For the moment, we have only optimizations for the Intel generations,
- but that could change... */
-
-#define ELF_PLATFORM (NULL)
-
-#define ELF_PLAT_INIT(_r, load_addr) \
- do { \
- _r->gpr[0] = _r->gpr[1] = _r->gpr[2] = _r->gpr[3] = \
- _r->gpr[4] = _r->gpr[5] = _r->gpr[6] = _r->gpr[7] = \
- _r->gpr[8] = _r->gpr[9] = _r->gpr[10] = _r->gpr[11] = \
- _r->gpr[12] = _r->gpr[13] = _r->gpr[14] = _r->gpr[15] = \
- _r->gpr[16] = _r->gpr[17] = _r->gpr[18] = _r->gpr[19] = \
- _r->gpr[20] = _r->gpr[21] = _r->gpr[22] = _r->gpr[23] = \
- _r->gpr[24] = _r->gpr[25] = _r->gpr[26] = _r->gpr[27] = \
- _r->gpr[28] = _r->gpr[29] = _r->gpr[30] = _r->gpr[31] = \
- 0; \
- } while (0)
-
-#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
-
-#endif /* __V850_ELF_H__ */
diff --git a/include/asm-v850/emergency-restart.h b/include/asm-v850/emergency-restart.h
deleted file mode 100644
index 108d8c48e42..00000000000
--- a/include/asm-v850/emergency-restart.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/include/asm-v850/entry.h b/include/asm-v850/entry.h
deleted file mode 100644
index d9df8ac4858..00000000000
--- a/include/asm-v850/entry.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * include/asm-v850/entry.h -- Definitions used by low-level trap handlers
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_ENTRY_H__
-#define __V850_ENTRY_H__
-
-
-#include <asm/ptrace.h>
-#include <asm/machdep.h>
-
-
-/* These are special variables using by the kernel trap/interrupt code
- to save registers in, at a time when there are no spare registers we
- can use to do so, and we can't depend on the value of the stack
- pointer. This means that they must be within a signed 16-bit
- displacement of 0x00000000. */
-
-#define KERNEL_VAR_SPACE_ADDR R0_RAM_ADDR
-
-#ifdef __ASSEMBLY__
-#define KERNEL_VAR(addr) addr[r0]
-#else
-#define KERNEL_VAR(addr) (*(volatile unsigned long *)(addr))
-#endif
-
-/* Kernel stack pointer, 4 bytes. */
-#define KSP_ADDR (KERNEL_VAR_SPACE_ADDR + 0)
-#define KSP KERNEL_VAR (KSP_ADDR)
-/* 1 if in kernel-mode, 0 if in user mode, 1 byte. */
-#define KM_ADDR (KERNEL_VAR_SPACE_ADDR + 4)
-#define KM KERNEL_VAR (KM_ADDR)
-/* Temporary storage for interrupt handlers, 4 bytes. */
-#define INT_SCRATCH_ADDR (KERNEL_VAR_SPACE_ADDR + 8)
-#define INT_SCRATCH KERNEL_VAR (INT_SCRATCH_ADDR)
-/* Where the stack-pointer is saved when jumping to various sorts of
- interrupt handlers. ENTRY_SP is used by everything except NMIs,
- which have their own location. Higher-priority NMIs can clobber the
- value written by a lower priority NMI, since they can't be disabled,
- but that's OK, because only NMI0 (the lowest-priority one) is allowed
- to return. */
-#define ENTRY_SP_ADDR (KERNEL_VAR_SPACE_ADDR + 12)
-#define ENTRY_SP KERNEL_VAR (ENTRY_SP_ADDR)
-#define NMI_ENTRY_SP_ADDR (KERNEL_VAR_SPACE_ADDR + 16)
-#define NMI_ENTRY_SP KERNEL_VAR (NMI_ENTRY_SP_ADDR)
-
-#ifdef CONFIG_RESET_GUARD
-/* Used to detect unexpected resets (since the v850 has no MMU, any call
- through a null pointer will jump to the reset vector). We detect
- such resets by checking for a magic value, RESET_GUARD_ACTIVE, in
- this location. Properly resetting the machine stores zero there, so
- it shouldn't trigger the guard; the power-on value is uncertain, but
- it's unlikely to be RESET_GUARD_ACTIVE. */
-#define RESET_GUARD_ADDR (KERNEL_VAR_SPACE_ADDR + 28)
-#define RESET_GUARD KERNEL_VAR (RESET_GUARD_ADDR)
-#define RESET_GUARD_ACTIVE 0xFAB4BEEF
-#endif /* CONFIG_RESET_GUARD */
-
-#ifdef CONFIG_V850E_HIGHRES_TIMER
-#define HIGHRES_TIMER_SLOW_TICKS_ADDR (KERNEL_VAR_SPACE_ADDR + 32)
-#define HIGHRES_TIMER_SLOW_TICKS KERNEL_VAR (HIGHRES_TIMER_SLOW_TICKS_ADDR)
-#endif /* CONFIG_V850E_HIGHRES_TIMER */
-
-#ifndef __ASSEMBLY__
-
-#ifdef CONFIG_RESET_GUARD
-/* Turn off reset guard, so that resetting the machine works normally.
- This should be called in the various machine_halt, etc., functions. */
-static inline void disable_reset_guard (void)
-{
- RESET_GUARD = 0;
-}
-#endif /* CONFIG_RESET_GUARD */
-
-#endif /* !__ASSEMBLY__ */
-
-
-/* A `state save frame' is a struct pt_regs preceded by some extra space
- suitable for a function call stack frame. */
-
-/* Amount of room on the stack reserved for arguments and to satisfy the
- C calling conventions, in addition to the space used by the struct
- pt_regs that actually holds saved values. */
-#define STATE_SAVE_ARG_SPACE (6*4) /* Up to six arguments. */
-
-
-#ifdef __ASSEMBLY__
-
-/* The size of a state save frame. */
-#define STATE_SAVE_SIZE (PT_SIZE + STATE_SAVE_ARG_SPACE)
-
-#else /* !__ASSEMBLY__ */
-
-/* The size of a state save frame. */
-#define STATE_SAVE_SIZE (sizeof (struct pt_regs) + STATE_SAVE_ARG_SPACE)
-
-#endif /* __ASSEMBLY__ */
-
-
-/* Offset of the struct pt_regs in a state save frame. */
-#define STATE_SAVE_PT_OFFSET STATE_SAVE_ARG_SPACE
-
-
-#endif /* __V850_ENTRY_H__ */
diff --git a/include/asm-v850/errno.h b/include/asm-v850/errno.h
deleted file mode 100644
index 31c91df0120..00000000000
--- a/include/asm-v850/errno.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_ERRNO_H__
-#define __V850_ERRNO_H__
-
-#include <asm-generic/errno.h>
-
-#endif /* __V850_ERRNO_H__ */
diff --git a/include/asm-v850/fb.h b/include/asm-v850/fb.h
deleted file mode 100644
index c7df3803099..00000000000
--- a/include/asm-v850/fb.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _ASM_FB_H_
-#define _ASM_FB_H_
-#include <linux/fb.h>
-
-#define fb_pgprotect(...) do {} while (0)
-
-static inline int fb_is_primary_device(struct fb_info *info)
-{
- return 0;
-}
-
-#endif /* _ASM_FB_H_ */
diff --git a/include/asm-v850/fcntl.h b/include/asm-v850/fcntl.h
deleted file mode 100644
index 3af4d56776d..00000000000
--- a/include/asm-v850/fcntl.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __V850_FCNTL_H__
-#define __V850_FCNTL_H__
-
-#define O_DIRECTORY 040000 /* must be a directory */
-#define O_NOFOLLOW 0100000 /* don't follow links */
-#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */
-#define O_LARGEFILE 0400000
-
-#include <asm-generic/fcntl.h>
-
-#endif /* __V850_FCNTL_H__ */
diff --git a/include/asm-v850/flat.h b/include/asm-v850/flat.h
deleted file mode 100644
index 17f0ea56661..00000000000
--- a/include/asm-v850/flat.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * include/asm-v850/flat.h -- uClinux flat-format executables
- *
- * Copyright (C) 2002,03 NEC Electronics Corporation
- * Copyright (C) 2002,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_FLAT_H__
-#define __V850_FLAT_H__
-
-/* The amount by which a relocation can exceed the program image limits
- without being regarded as an error. On the v850, the relocations of
- some base-pointers can be offset by 0x8000 (to allow better usage of the
- space offered by 16-bit signed offsets -- in most cases the offsets used
- with such a base-pointer will be negative). */
-
-#define flat_reloc_valid(reloc, size) ((reloc) <= (size + 0x8000))
-
-#define flat_stack_align(sp) /* nothing needed */
-#define flat_argvp_envp_on_stack() 0
-#define flat_old_ram_flag(flags) (flags)
-#define flat_set_persistent(relval, p) 0
-
-/* We store the type of relocation in the top 4 bits of the `relval.' */
-
-/* Convert a relocation entry into an address. */
-static inline unsigned long
-flat_get_relocate_addr (unsigned long relval)
-{
- return relval & 0x0fffffff; /* Mask out top 4-bits */
-}
-
-#define flat_v850_get_reloc_type(relval) ((relval) >> 28)
-
-#define FLAT_V850_R_32 0 /* Normal 32-bit reloc */
-#define FLAT_V850_R_HI16S_LO15 1 /* High 16-bits + signed 15-bit low field */
-#define FLAT_V850_R_HI16S_LO16 2 /* High 16-bits + signed 16-bit low field */
-
-/* Extract the address to be relocated from the symbol reference at RP;
- RELVAL is the raw relocation-table entry from which RP is derived.
- For the v850, RP should always be half-word aligned. */
-static inline unsigned long flat_get_addr_from_rp (unsigned long *rp,
- unsigned long relval,
- unsigned long flags,
- unsigned long *persistent)
-{
- short *srp = (short *)rp;
-
- switch (flat_v850_get_reloc_type (relval))
- {
- case FLAT_V850_R_32:
- /* Simple 32-bit address. */
- return srp[0] | (srp[1] << 16);
-
- case FLAT_V850_R_HI16S_LO16:
- /* The high and low halves of the address are in the 16
- bits at RP, and the 2nd word of the 32-bit instruction
- following that, respectively. The low half is _signed_
- so we have to sign-extend it and add it to the upper
- half instead of simply or-ing them together.
-
- Unlike most relocated address, this one is stored in
- native (little-endian) byte-order to avoid problems with
- trashing the low-order bit, so we have to convert to
- network-byte-order before returning, as that's what the
- caller expects. */
- return htonl ((srp[0] << 16) + srp[2]);
-
- case FLAT_V850_R_HI16S_LO15:
- /* The high and low halves of the address are in the 16
- bits at RP, and the upper 15 bits of the 2nd word of the
- 32-bit instruction following that, respectively. The
- low half is _signed_ so we have to sign-extend it and
- add it to the upper half instead of simply or-ing them
- together. The lowest bit is always zero.
-
- Unlike most relocated address, this one is stored in
- native (little-endian) byte-order to avoid problems with
- trashing the low-order bit, so we have to convert to
- network-byte-order before returning, as that's what the
- caller expects. */
- return htonl ((srp[0] << 16) + (srp[2] & ~0x1));
-
- default:
- return ~0; /* bogus value */
- }
-}
-
-/* Insert the address ADDR into the symbol reference at RP;
- RELVAL is the raw relocation-table entry from which RP is derived.
- For the v850, RP should always be half-word aligned. */
-static inline void flat_put_addr_at_rp (unsigned long *rp, unsigned long addr,
- unsigned long relval)
-{
- short *srp = (short *)rp;
-
- switch (flat_v850_get_reloc_type (relval)) {
- case FLAT_V850_R_32:
- /* Simple 32-bit address. */
- srp[0] = addr & 0xFFFF;
- srp[1] = (addr >> 16);
- break;
-
- case FLAT_V850_R_HI16S_LO16:
- /* The high and low halves of the address are in the 16
- bits at RP, and the 2nd word of the 32-bit instruction
- following that, respectively. The low half is _signed_
- so we must carry its sign bit to the upper half before
- writing the upper half. */
- srp[0] = (addr >> 16) + ((addr >> 15) & 0x1);
- srp[2] = addr & 0xFFFF;
- break;
-
- case FLAT_V850_R_HI16S_LO15:
- /* The high and low halves of the address are in the 16
- bits at RP, and the upper 15 bits of the 2nd word of the
- 32-bit instruction following that, respectively. The
- low half is _signed_ so we must carry its sign bit to
- the upper half before writing the upper half. The
- lowest bit we preserve from the existing instruction. */
- srp[0] = (addr >> 16) + ((addr >> 15) & 0x1);
- srp[2] = (addr & 0xFFFE) | (srp[2] & 0x1);
- break;
- }
-}
-
-#endif /* __V850_FLAT_H__ */
diff --git a/include/asm-v850/fpga85e2c.h b/include/asm-v850/fpga85e2c.h
deleted file mode 100644
index 23aae666c71..00000000000
--- a/include/asm-v850/fpga85e2c.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * include/asm-v850/fpga85e2c.h -- Machine-dependent defs for
- * FPGA implementation of V850E2/NA85E2C
- *
- * Copyright (C) 2002,03 NEC Electronics Corporation
- * Copyright (C) 2002,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_FPGA85E2C_H__
-#define __V850_FPGA85E2C_H__
-
-#include <asm/v850e2.h>
-#include <asm/clinkage.h>
-
-
-#define CPU_MODEL "v850e2/fpga85e2c"
-#define CPU_MODEL_LONG "NEC V850E2/NA85E2C"
-#define PLATFORM "fpga85e2c"
-#define PLATFORM_LONG "NA85E2C FPGA implementation"
-
-
-/* `external ram'. */
-#define ERAM_ADDR 0
-#define ERAM_SIZE 0x00100000 /* 1MB */
-
-
-/* FPGA specific control registers. */
-
-/* Writing a non-zero value to FLGREG(0) will signal the controlling CPU
- to stop execution. */
-#define FLGREG_ADDR(n) (0xFFE80100 + 2*(n))
-#define FLGREG(n) (*(volatile unsigned char *)FLGREG_ADDR (n))
-#define FLGREG_NUM 2
-
-#define CSDEV_ADDR(n) (0xFFE80110 + 2*(n))
-#define CSDEV(n) (*(volatile unsigned char *)CSDEV_ADDR (n))
-
-
-/* Timer interrupts 0-3, interrupt at intervals from CLK/4096 to CLK/16384. */
-#define IRQ_RPU(n) (60 + (n))
-#define IRQ_RPU_NUM 4
-
-/* For <asm/irq.h> */
-#define NUM_CPU_IRQS 64
-
-
-/* General-purpose timer. */
-/* control/status register (can only be read/written via bit insns) */
-#define RPU_GTMC_ADDR 0xFFFFFB00
-#define RPU_GTMC (*(volatile unsigned char *)RPU_GTMC_ADDR)
-#define RPU_GTMC_CE_BIT 7 /* clock enable (control) */
-#define RPU_GTMC_OV_BIT 6 /* overflow (status) */
-#define RPU_GTMC_CLK_BIT 1 /* 0 = .5 MHz CLK, 1 = 1 Mhz (control) */
-/* 32-bit count (8 least-significant bits are always zero). */
-#define RPU_GTM_ADDR 0xFFFFFB28
-#define RPU_GTM (*(volatile unsigned long *)RPU_GTMC_ADDR)
-
-
-/* For <asm/page.h> */
-#define PAGE_OFFSET ERAM_ADDR /* minimum allocatable address */
-
-
-/* For <asm/entry.h> */
-/* `R0 RAM', used for a few miscellaneous variables that must be accessible
- using a load instruction relative to R0. The FPGA implementation
- actually has no on-chip RAM, so we use part of main ram just after the
- interrupt vectors. */
-#ifdef __ASSEMBLY__
-#define R0_RAM_ADDR lo(C_SYMBOL_NAME(_r0_ram))
-#else
-extern char _r0_ram;
-#define R0_RAM_ADDR ((unsigned long)&_r0_ram);
-#endif
-
-
-#endif /* __V850_FPGA85E2C_H__ */
diff --git a/include/asm-v850/futex.h b/include/asm-v850/futex.h
deleted file mode 100644
index 6a332a9f099..00000000000
--- a/include/asm-v850/futex.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
-
-#include <asm-generic/futex.h>
-
-#endif
diff --git a/include/asm-v850/gbus_int.h b/include/asm-v850/gbus_int.h
deleted file mode 100644
index 0c4bce753c7..00000000000
--- a/include/asm-v850/gbus_int.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * include/asm-v850/gbus_int.h -- Midas labs GBUS interrupt support
- *
- * Copyright (C) 2001,02 NEC Corporation
- * Copyright (C) 2001,02 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_GBUS_INT_H__
-#define __V850_GBUS_INT_H__
-
-
-/* The GBUS interrupt interface has 32 interrupts shared among 4
- processor interrupts. The 32 GBUS interrupts are divided into two
- sets of 16 each, for allocating among control registers, etc (there
- are two of each control register, with bits 0-15 controlling an
- interrupt each). */
-
-/* The GBUS interrupts themselves. */
-#define IRQ_GBUS_INT(n) (GBUS_INT_BASE_IRQ + (n))
-#define IRQ_GBUS_INT_NUM 32
-
-/* Control registers. */
-#define GBUS_INT_STATUS_ADDR(w) (GBUS_INT_BASE_ADDR + (w)*0x40)
-#define GBUS_INT_STATUS(w) (*(volatile u16 *)GBUS_INT_STATUS_ADDR(w))
-#define GBUS_INT_CLEAR_ADDR(w) (GBUS_INT_BASE_ADDR + 0x10 + (w)*0x40)
-#define GBUS_INT_CLEAR(w) (*(volatile u16 *)GBUS_INT_CLEAR_ADDR(w))
-#define GBUS_INT_EDGE_ADDR(w) (GBUS_INT_BASE_ADDR + 0x20 + (w)*0x40)
-#define GBUS_INT_EDGE(w) (*(volatile u16 *)GBUS_INT_EDGE_ADDR(w))
-#define GBUS_INT_POLARITY_ADDR(w) (GBUS_INT_BASE_ADDR + 0x30 + (w)*0x40)
-#define GBUS_INT_POLARITY(w) (*(volatile u16 *)GBUS_INT_POLARITY_ADDR(w))
-/* This allows enabling interrupt bits in word W for interrupt GINTn. */
-#define GBUS_INT_ENABLE_ADDR(w, n) \
- (GBUS_INT_BASE_ADDR + 0x100 + (w)*0x10 + (n)*0x20)
-#define GBUS_INT_ENABLE(w, n) (*(volatile u16 *)GBUS_INT_ENABLE_ADDR(w, n))
-
-/* Mapping between kernel interrupt numbers and hardware control regs/bits. */
-#define GBUS_INT_BITS_PER_WORD 16
-#define GBUS_INT_NUM_WORDS (IRQ_GBUS_INT_NUM / GBUS_INT_BITS_PER_WORD)
-#define GBUS_INT_IRQ_WORD(irq) (((irq) - GBUS_INT_BASE_IRQ) >> 4)
-#define GBUS_INT_IRQ_BIT(irq) (((irq) - GBUS_INT_BASE_IRQ) & 0xF)
-#define GBUS_INT_IRQ_MASK(irq) (1 << GBUS_INT_IRQ_BIT(irq))
-
-
-/* Possible priorities for GBUS interrupts. */
-#define GBUS_INT_PRIORITY_HIGH 2
-#define GBUS_INT_PRIORITY_MEDIUM 4
-#define GBUS_INT_PRIORITY_LOW 6
-
-
-#ifndef __ASSEMBLY__
-
-/* Enable interrupt handling for interrupt IRQ. */
-extern void gbus_int_enable_irq (unsigned irq);
-/* Disable interrupt handling for interrupt IRQ. Note that any
- interrupts received while disabled will be delivered once the
- interrupt is enabled again, unless they are explicitly cleared using
- `gbus_int_clear_pending_irq'. */
-extern void gbus_int_disable_irq (unsigned irq);
-/* Return true if interrupt handling for interrupt IRQ is enabled. */
-extern int gbus_int_irq_enabled (unsigned irq);
-/* Disable all GBUS irqs. */
-extern void gbus_int_disable_irqs (void);
-/* Clear any pending interrupts for IRQ. */
-extern void gbus_int_clear_pending_irq (unsigned irq);
-/* Return true if interrupt IRQ is pending (but disabled). */
-extern int gbus_int_irq_pending (unsigned irq);
-
-
-struct gbus_int_irq_init {
- const char *name; /* name of interrupt type */
-
- /* Range of kernel irq numbers for this type:
- BASE, BASE+INTERVAL, ..., BASE+INTERVAL*NUM */
- unsigned base, num, interval;
-
- unsigned priority; /* interrupt priority to assign */
-};
-struct hw_interrupt_type; /* fwd decl */
-
-/* Initialize HW_IRQ_TYPES for GBUS irqs described in array
- INITS (which is terminated by an entry with the name field == 0). */
-extern void gbus_int_init_irq_types (struct gbus_int_irq_init *inits,
- struct hw_interrupt_type *hw_irq_types);
-
-/* Initialize GBUS interrupts. */
-extern void gbus_int_init_irqs (void);
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_GBUS_INT_H__ */
diff --git a/include/asm-v850/hardirq.h b/include/asm-v850/hardirq.h
deleted file mode 100644
index 04e20127c5a..00000000000
--- a/include/asm-v850/hardirq.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __V850_HARDIRQ_H__
-#define __V850_HARDIRQ_H__
-
-#include <linux/threads.h>
-#include <linux/cache.h>
-
-#include <asm/irq.h>
-
-typedef struct {
- unsigned int __softirq_pending;
-} ____cacheline_aligned irq_cpustat_t;
-
-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
-
-#define HARDIRQ_BITS 8
-
-/*
- * The hardirq mask has to be large enough to have
- * space for potentially all IRQ sources in the system
- * nesting on a single CPU:
- */
-#if (1 << HARDIRQ_BITS) < NR_IRQS
-# error HARDIRQ_BITS is too low!
-#endif
-
-void ack_bad_irq(unsigned int irq);
-
-#endif /* __V850_HARDIRQ_H__ */
diff --git a/include/asm-v850/highres_timer.h b/include/asm-v850/highres_timer.h
deleted file mode 100644
index 486fb49ceab..00000000000
--- a/include/asm-v850/highres_timer.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * include/asm-v850/highres_timer.h -- High resolution timing routines
- *
- * Copyright (C) 2001,03 NEC Electronics Corporation
- * Copyright (C) 2001,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_HIGHRES_TIMER_H__
-#define __V850_HIGHRES_TIMER_H__
-
-#ifndef __ASSEMBLY__
-#include <linux/time.h>
-#endif
-
-#include <asm/entry.h>
-
-
-/* Frequency of the `slow ticks' (one tick each time the fast-tick
- counter overflows). */
-#define HIGHRES_TIMER_SLOW_TICK_RATE 25
-
-/* Which timer in the V850E `Timer D' we use. */
-#define HIGHRES_TIMER_TIMER_D_UNIT 3
-
-
-#ifndef __ASSEMBLY__
-
-extern void highres_timer_start (void), highres_timer_stop (void);
-extern void highres_timer_reset (void);
-extern void highres_timer_read_ticks (u32 *slow_ticks, u32 *fast_ticks);
-extern void highres_timer_ticks_to_timeval (u32 slow_ticks, u32 fast_ticks,
- struct timeval *tv);
-extern void highres_timer_read (struct timeval *tv);
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_HIGHRES_TIMER_H__ */
diff --git a/include/asm-v850/hw_irq.h b/include/asm-v850/hw_irq.h
deleted file mode 100644
index 043e94bb6bd..00000000000
--- a/include/asm-v850/hw_irq.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __V850_HW_IRQ_H__
-#define __V850_HW_IRQ_H__
-
-#endif /* __V850_HW_IRQ_H__ */
diff --git a/include/asm-v850/io.h b/include/asm-v850/io.h
deleted file mode 100644
index cdad251fba9..00000000000
--- a/include/asm-v850/io.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * include/asm-v850/io.h -- Misc I/O operations
- *
- * Copyright (C) 2001,02,03,04,05 NEC Electronics Corporation
- * Copyright (C) 2001,02,03,04,05 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_IO_H__
-#define __V850_IO_H__
-
-#define IO_SPACE_LIMIT 0xFFFFFFFF
-
-#define readb(addr) \
- ({ unsigned char __v = (*(volatile unsigned char *) (addr)); __v; })
-#define readw(addr) \
- ({ unsigned short __v = (*(volatile unsigned short *) (addr)); __v; })
-#define readl(addr) \
- ({ unsigned long __v = (*(volatile unsigned long *) (addr)); __v; })
-
-#define readb_relaxed(a) readb(a)
-#define readw_relaxed(a) readw(a)
-#define readl_relaxed(a) readl(a)
-
-#define writeb(val, addr) \
- (void)((*(volatile unsigned char *) (addr)) = (val))
-#define writew(val, addr) \
- (void)((*(volatile unsigned short *) (addr)) = (val))
-#define writel(val, addr) \
- (void)((*(volatile unsigned int *) (addr)) = (val))
-
-#define __raw_readb readb
-#define __raw_readw readw
-#define __raw_readl readl
-#define __raw_writeb writeb
-#define __raw_writew writew
-#define __raw_writel writel
-
-#define inb(addr) readb (addr)
-#define inw(addr) readw (addr)
-#define inl(addr) readl (addr)
-#define outb(x, addr) ((void) writeb (x, addr))
-#define outw(x, addr) ((void) writew (x, addr))
-#define outl(x, addr) ((void) writel (x, addr))
-
-#define inb_p(port) inb((port))
-#define outb_p(val, port) outb((val), (port))
-#define inw_p(port) inw((port))
-#define outw_p(val, port) outw((val), (port))
-#define inl_p(port) inl((port))
-#define outl_p(val, port) outl((val), (port))
-
-static inline void insb (unsigned long port, void *dst, unsigned long count)
-{
- unsigned char *p = dst;
- while (count--)
- *p++ = inb (port);
-}
-static inline void insw (unsigned long port, void *dst, unsigned long count)
-{
- unsigned short *p = dst;
- while (count--)
- *p++ = inw (port);
-}
-static inline void insl (unsigned long port, void *dst, unsigned long count)
-{
- unsigned long *p = dst;
- while (count--)
- *p++ = inl (port);
-}
-
-static inline void
-outsb (unsigned long port, const void *src, unsigned long count)
-{
- const unsigned char *p = src;
- while (count--)
- outb (*p++, port);
-}
-static inline void
-outsw (unsigned long port, const void *src, unsigned long count)
-{
- const unsigned short *p = src;
- while (count--)
- outw (*p++, port);
-}
-static inline void
-outsl (unsigned long port, const void *src, unsigned long count)
-{
- const unsigned long *p = src;
- while (count--)
- outl (*p++, port);
-}
-
-
-/* Some places try to pass in an loff_t for PHYSADDR (?!), so we cast it to
- long before casting it to a pointer to avoid compiler warnings. */
-#define ioremap(physaddr, size) ((void __iomem *)(unsigned long)(physaddr))
-#define iounmap(addr) ((void)0)
-
-#define ioremap_nocache(physaddr, size) ioremap (physaddr, size)
-#define ioremap_writethrough(physaddr, size) ioremap (physaddr, size)
-#define ioremap_fullcache(physaddr, size) ioremap (physaddr, size)
-
-#define ioread8(addr) readb (addr)
-#define ioread16(addr) readw (addr)
-#define ioread32(addr) readl (addr)
-#define iowrite8(val, addr) writeb (val, addr)
-#define iowrite16(val, addr) writew (val, addr)
-#define iowrite32(val, addr) writel (val, addr)
-
-#define mmiowb()
-
-#define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT)
-#if 0
-/* This is really stupid; don't define it. */
-#define page_to_bus(page) page_to_phys (page)
-#endif
-
-/* Conversion between virtual and physical mappings. */
-#define phys_to_virt(addr) ((void *)__phys_to_virt (addr))
-#define virt_to_phys(addr) ((unsigned long)__virt_to_phys (addr))
-
-#define memcpy_fromio(dst, src, len) memcpy (dst, (void *)src, len)
-#define memcpy_toio(dst, src, len) memcpy ((void *)dst, src, len)
-
-/*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p) __va(p)
-
-/*
- * Convert a virtual cached pointer to an uncached pointer
- */
-#define xlate_dev_kmem_ptr(p) p
-
-#endif /* __V850_IO_H__ */
diff --git a/include/asm-v850/ioctl.h b/include/asm-v850/ioctl.h
deleted file mode 100644
index b279fe06dfe..00000000000
--- a/include/asm-v850/ioctl.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff --git a/include/asm-v850/ioctls.h b/include/asm-v850/ioctls.h
deleted file mode 100644
index 5313abd5f38..00000000000
--- a/include/asm-v850/ioctls.h
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef __V850_IOCTLS_H__
-#define __V850_IOCTLS_H__
-
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS 0x5401
-#define TCSETS 0x5402
-#define TCSETSW 0x5403
-#define TCSETSF 0x5404
-#define TCGETA 0x5405
-#define TCSETA 0x5406
-#define TCSETAW 0x5407
-#define TCSETAF 0x5408
-#define TCSBRK 0x5409
-#define TCXONC 0x540A
-#define TCFLSH 0x540B
-#define TIOCEXCL 0x540C
-#define TIOCNXCL 0x540D
-#define TIOCSCTTY 0x540E
-#define TIOCGPGRP 0x540F
-#define TIOCSPGRP 0x5410
-#define TIOCOUTQ 0x5411
-#define TIOCSTI 0x5412
-#define TIOCGWINSZ 0x5413
-#define TIOCSWINSZ 0x5414
-#define TIOCMGET 0x5415
-#define TIOCMBIS 0x5416
-#define TIOCMBIC 0x5417
-#define TIOCMSET 0x5418
-#define TIOCGSOFTCAR 0x5419
-#define TIOCSSOFTCAR 0x541A
-#define FIONREAD 0x541B
-#define TIOCINQ FIONREAD
-#define TIOCLINUX 0x541C
-#define TIOCCONS 0x541D
-#define TIOCGSERIAL 0x541E
-#define TIOCSSERIAL 0x541F
-#define TIOCPKT 0x5420
-#define FIONBIO 0x5421
-#define TIOCNOTTY 0x5422
-#define TIOCSETD 0x5423
-#define TIOCGETD 0x5424
-#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK 0x5427 /* BSD compatibility */
-#define TIOCCBRK 0x5428 /* BSD compatibility */
-#define TIOCGSID 0x5429 /* Return the session ID of FD */
-#define TCGETS2 _IOR('T',0x2A, struct termios2)
-#define TCSETS2 _IOW('T',0x2B, struct termios2)
-#define TCSETSW2 _IOW('T',0x2C, struct termios2)
-#define TCSETSF2 _IOW('T',0x2D, struct termios2)
-#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
-
-#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
-#define FIOCLEX 0x5451
-#define FIOASYNC 0x5452
-#define TIOCSERCONFIG 0x5453
-#define TIOCSERGWILD 0x5454
-#define TIOCSERSWILD 0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR 0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
-#define FIOQSIZE 0x545E
-
-/* Used for packet mode */
-#define TIOCPKT_DATA 0
-#define TIOCPKT_FLUSHREAD 1
-#define TIOCPKT_FLUSHWRITE 2
-#define TIOCPKT_STOP 4
-#define TIOCPKT_START 8
-#define TIOCPKT_NOSTOP 16
-#define TIOCPKT_DOSTOP 32
-
-#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
-
-#endif /* __V850_IOCTLS_H__ */
diff --git a/include/asm-v850/ipcbuf.h b/include/asm-v850/ipcbuf.h
deleted file mode 100644
index d8cbe9886d9..00000000000
--- a/include/asm-v850/ipcbuf.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __V850E_IPCBUF_H__
-#define __V850E_IPCBUF_H__
-
-/*
- * The user_ipc_perm structure for v850e architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 32-bit mode_t and seq
- * - 2 miscellaneous 32-bit values
- */
-
-struct ipc64_perm
-{
- __kernel_key_t key;
- __kernel_uid32_t uid;
- __kernel_gid32_t gid;
- __kernel_uid32_t cuid;
- __kernel_gid32_t cgid;
- __kernel_mode_t mode;
- unsigned short __pad1;
- unsigned short seq;
- unsigned short __pad2;
- unsigned long __unused1;
- unsigned long __unused2;
-};
-
-#endif /* __V850E_IPCBUF_H__ */
diff --git a/include/asm-v850/irq.h b/include/asm-v850/irq.h
deleted file mode 100644
index 7d0d4cd1ce5..00000000000
--- a/include/asm-v850/irq.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * include/asm-v850/irq.h -- Machine interrupt handling
- *
- * Copyright (C) 2001,02,04 NEC Electronics Corporation
- * Copyright (C) 2001,02,04 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_IRQ_H__
-#define __V850_IRQ_H__
-
-#include <asm/machdep.h>
-
-/* Default NUM_MACH_IRQS. */
-#ifndef NUM_MACH_IRQS
-#define NUM_MACH_IRQS NUM_CPU_IRQS
-#endif
-
-/* NMIs have IRQ numbers from FIRST_NMI to FIRST_NMI+NUM_NMIS-1. */
-#define FIRST_NMI NUM_MACH_IRQS
-#define IRQ_NMI(n) (FIRST_NMI + (n))
-/* v850 processors have 3 non-maskable interrupts. */
-#define NUM_NMIS 3
-
-/* Includes both maskable and non-maskable irqs. */
-#define NR_IRQS (NUM_MACH_IRQS + NUM_NMIS)
-
-
-#ifndef __ASSEMBLY__
-
-struct pt_regs;
-struct hw_interrupt_type;
-struct irqaction;
-
-#define irq_canonicalize(irq) (irq)
-
-/* Initialize irq handling for IRQs.
- BASE_IRQ, BASE_IRQ+INTERVAL, ..., BASE_IRQ+NUM*INTERVAL
- to IRQ_TYPE. An IRQ_TYPE of 0 means to use a generic interrupt type. */
-extern void
-init_irq_handlers (int base_irq, int num, int interval,
- struct hw_interrupt_type *irq_type);
-
-/* Handle interrupt IRQ. REGS are the registers at the time of ther
- interrupt. */
-extern unsigned int handle_irq (int irq, struct pt_regs *regs);
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* __V850_IRQ_H__ */
diff --git a/include/asm-v850/irq_regs.h b/include/asm-v850/irq_regs.h
deleted file mode 100644
index 3dd9c0b7027..00000000000
--- a/include/asm-v850/irq_regs.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff --git a/include/asm-v850/kdebug.h b/include/asm-v850/kdebug.h
deleted file mode 100644
index 6ece1b03766..00000000000
--- a/include/asm-v850/kdebug.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff --git a/include/asm-v850/kmap_types.h b/include/asm-v850/kmap_types.h
deleted file mode 100644
index 3288976b161..00000000000
--- a/include/asm-v850/kmap_types.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __V850_KMAP_TYPES_H__
-#define __V850_KMAP_TYPES_H__
-
-enum km_type {
- KM_BOUNCE_READ,
- KM_SKB_SUNRPC_DATA,
- KM_SKB_DATA_SOFTIRQ,
- KM_USER0,
- KM_USER1,
- KM_BIO_SRC_IRQ,
- KM_BIO_DST_IRQ,
- KM_PTE0,
- KM_PTE1,
- KM_IRQ0,
- KM_IRQ1,
- KM_TYPE_NR
-};
-
-#endif /* __V850_KMAP_TYPES_H__ */
diff --git a/include/asm-v850/kvm.h b/include/asm-v850/kvm.h
deleted file mode 100644
index 3f729b79feb..00000000000
--- a/include/asm-v850/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_V850_H
-#define __LINUX_KVM_V850_H
-
-/* v850 does not support KVM */
-
-#endif
diff --git a/include/asm-v850/linkage.h b/include/asm-v850/linkage.h
deleted file mode 100644
index b6185d3cfe6..00000000000
--- a/include/asm-v850/linkage.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __ASM_LINKAGE_H
-#define __ASM_LINKAGE_H
-
-#ifdef __ASSEMBLY__
-#include <asm/asm.h>
-#endif
-
-#endif
diff --git a/include/asm-v850/local.h b/include/asm-v850/local.h
deleted file mode 100644
index 705148abe27..00000000000
--- a/include/asm-v850/local.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_LOCAL_H__
-#define __V850_LOCAL_H__
-
-#include <asm-generic/local.h>
-
-#endif /* __V850_LOCAL_H__ */
diff --git a/include/asm-v850/ma.h b/include/asm-v850/ma.h
deleted file mode 100644
index 89e66473a17..00000000000
--- a/include/asm-v850/ma.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * include/asm-v850/ma.h -- V850E/MA series of cpu chips
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_MA_H__
-#define __V850_MA_H__
-
-/* The MA series uses the V850E cpu core. */
-#include <asm/v850e.h>
-
-
-/* For <asm/entry.h> */
-/* We use on-chip RAM, for a few miscellaneous variables that must be
- accessible using a load instruction relative to R0. The amount
- varies between chip models, but there's always at least 4K, and it
- should always start at FFFFC000. */
-#define R0_RAM_ADDR 0xFFFFC000
-
-
-/* MA series UART details. */
-#define V850E_UART_BASE_FREQ CPU_CLOCK_FREQ
-
-/* This is a function that gets called before configuring the UART. */
-#define V850E_UART_PRE_CONFIGURE ma_uart_pre_configure
-#ifndef __ASSEMBLY__
-extern void ma_uart_pre_configure (unsigned chan,
- unsigned cflags, unsigned baud);
-#endif
-
-
-/* MA series timer C details. */
-#define V850E_TIMER_C_BASE_ADDR 0xFFFFF600
-
-
-/* MA series timer D details. */
-#define V850E_TIMER_D_BASE_ADDR 0xFFFFF540
-#define V850E_TIMER_D_TMD_BASE_ADDR (V850E_TIMER_D_BASE_ADDR + 0x0)
-#define V850E_TIMER_D_CMD_BASE_ADDR (V850E_TIMER_D_BASE_ADDR + 0x2)
-#define V850E_TIMER_D_TMCD_BASE_ADDR (V850E_TIMER_D_BASE_ADDR + 0x4)
-
-#define V850E_TIMER_D_BASE_FREQ CPU_CLOCK_FREQ
-
-
-/* Port 0 */
-/* Direct I/O. Bits 0-7 are pins P00-P07. */
-#define MA_PORT0_IO_ADDR 0xFFFFF400
-#define MA_PORT0_IO (*(volatile u8 *)MA_PORT0_IO_ADDR)
-/* Port mode (for direct I/O, 0 = output, 1 = input). */
-#define MA_PORT0_PM_ADDR 0xFFFFF420
-#define MA_PORT0_PM (*(volatile u8 *)MA_PORT0_PM_ADDR)
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode). */
-#define MA_PORT0_PMC_ADDR 0xFFFFF440
-#define MA_PORT0_PMC (*(volatile u8 *)MA_PORT0_PMC_ADDR)
-/* Port function control (for P04-P07, 0 = IRQ, 1 = DMARQ). */
-#define MA_PORT0_PFC_ADDR 0xFFFFF460
-#define MA_PORT0_PFC (*(volatile u8 *)MA_PORT0_PFC_ADDR)
-
-/* Port 1 */
-/* Direct I/O. Bits 0-3 are pins P10-P13. */
-#define MA_PORT1_IO_ADDR 0xFFFFF402
-#define MA_PORT1_IO (*(volatile u8 *)MA_PORT1_IO_ADDR)
-/* Port mode (for direct I/O, 0 = output, 1 = input). */
-#define MA_PORT1_PM_ADDR 0xFFFFF420
-#define MA_PORT1_PM (*(volatile u8 *)MA_PORT1_PM_ADDR)
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode). */
-#define MA_PORT1_PMC_ADDR 0xFFFFF442
-#define MA_PORT1_PMC (*(volatile u8 *)MA_PORT1_PMC_ADDR)
-
-/* Port 4 */
-/* Direct I/O. Bits 0-5 are pins P40-P45. */
-#define MA_PORT4_IO_ADDR 0xFFFFF408
-#define MA_PORT4_IO (*(volatile u8 *)MA_PORT4_IO_ADDR)
-/* Port mode (for direct I/O, 0 = output, 1 = input). */
-#define MA_PORT4_PM_ADDR 0xFFFFF428
-#define MA_PORT4_PM (*(volatile u8 *)MA_PORT4_PM_ADDR)
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode). */
-#define MA_PORT4_PMC_ADDR 0xFFFFF448
-#define MA_PORT4_PMC (*(volatile u8 *)MA_PORT4_PMC_ADDR)
-/* Port function control (for serial interfaces, 0 = CSI, 1 = UART). */
-#define MA_PORT4_PFC_ADDR 0xFFFFF468
-#define MA_PORT4_PFC (*(volatile u8 *)MA_PORT4_PFC_ADDR)
-
-
-#ifndef __ASSEMBLY__
-
-/* Initialize MA chip interrupts. */
-extern void ma_init_irqs (void);
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_MA_H__ */
diff --git a/include/asm-v850/ma1.h b/include/asm-v850/ma1.h
deleted file mode 100644
index ede1f1de2b7..00000000000
--- a/include/asm-v850/ma1.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * include/asm-v850/ma1.h -- V850E/MA1 cpu chip
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_MA1_H__
-#define __V850_MA1_H__
-
-/* Inherit more generic details from MA series. */
-#include <asm/ma.h>
-
-
-#define CPU_MODEL "v850e/ma1"
-#define CPU_MODEL_LONG "NEC V850E/MA1"
-
-
-/* Hardware-specific interrupt numbers (in the kernel IRQ namespace). */
-#define IRQ_INTOV(n) (n) /* 0-3 */
-#define IRQ_INTOV_NUM 4
-#define IRQ_INTP(n) (0x4 + (n)) /* Pnnn (pin) interrupts */
-#define IRQ_INTP_NUM 24
-#define IRQ_INTCMD(n) (0x1c + (n)) /* interval timer interrupts 0-3 */
-#define IRQ_INTCMD_NUM 4
-#define IRQ_INTDMA(n) (0x20 + (n)) /* DMA interrupts 0-3 */
-#define IRQ_INTDMA_NUM 4
-#define IRQ_INTCSI(n) (0x24 + (n)*4)/* CSI 0-2 transmit/receive completion */
-#define IRQ_INTCSI_NUM 3
-#define IRQ_INTSER(n) (0x25 + (n)*4) /* UART 0-2 reception error */
-#define IRQ_INTSER_NUM 3
-#define IRQ_INTSR(n) (0x26 + (n)*4) /* UART 0-2 reception completion */
-#define IRQ_INTSR_NUM 3
-#define IRQ_INTST(n) (0x27 + (n)*4) /* UART 0-2 transmission completion */
-#define IRQ_INTST_NUM 3
-
-#define NUM_CPU_IRQS 0x30
-
-
-/* The MA1 has a UART with 3 channels. */
-#define V850E_UART_NUM_CHANNELS 3
-
-
-#endif /* __V850_MA1_H__ */
diff --git a/include/asm-v850/machdep.h b/include/asm-v850/machdep.h
deleted file mode 100644
index f1e3b8b9150..00000000000
--- a/include/asm-v850/machdep.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * include/asm-v850/machdep.h -- Machine-dependent definitions
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_MACHDEP_H__
-#define __V850_MACHDEP_H__
-
-
-/* chips */
-#ifdef CONFIG_V850E_MA1
-#include <asm/ma1.h>
-#endif
-#ifdef CONFIG_V850E_ME2
-#include <asm/me2.h>
-#endif
-#ifdef CONFIG_V850E_TEG
-#include <asm/teg.h>
-#endif
-
-/* These are both chips _and_ platforms, so put them in the middle... */
-#ifdef CONFIG_V850E2_ANNA
-#include <asm/anna.h>
-#endif
-#ifdef CONFIG_V850E_AS85EP1
-#include <asm/as85ep1.h>
-#endif
-
-/* platforms */
-#ifdef CONFIG_RTE_CB_MA1
-#include <asm/rte_ma1_cb.h>
-#endif
-#ifdef CONFIG_RTE_CB_ME2
-#include <asm/rte_me2_cb.h>
-#endif
-#ifdef CONFIG_RTE_CB_NB85E
-#include <asm/rte_nb85e_cb.h>
-#endif
-#ifdef CONFIG_V850E_SIM
-#include <asm/sim.h>
-#endif
-#ifdef CONFIG_V850E2_SIM85E2C
-#include <asm/sim85e2c.h>
-#endif
-#ifdef CONFIG_V850E2_SIM85E2S
-#include <asm/sim85e2s.h>
-#endif
-#ifdef CONFIG_V850E2_FPGA85E2C
-#include <asm/fpga85e2c.h>
-#endif
-
-#endif /* __V850_MACHDEP_H__ */
diff --git a/include/asm-v850/macrology.h b/include/asm-v850/macrology.h
deleted file mode 100644
index 37abf874832..00000000000
--- a/include/asm-v850/macrology.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * include/asm-v850/macrology.h -- Various useful CPP macros
- *
- * Copyright (C) 2001 NEC Corporation
- * Copyright (C) 2001 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#define macrology_paste(arg1, arg2) macrology_paste_1(arg1, arg2)
-#define macrology_paste_1(arg1, arg2) arg1 ## arg2
-#define macrology_stringify(sym) macrology_stringify_1(sym)
-#define macrology_stringify_1(sym) #sym
diff --git a/include/asm-v850/me2.h b/include/asm-v850/me2.h
deleted file mode 100644
index ac7c9ce0bdc..00000000000
--- a/include/asm-v850/me2.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * include/asm-v850/me2.h -- V850E/ME2 cpu chip
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_ME2_H__
-#define __V850_ME2_H__
-
-#include <asm/v850e.h>
-#include <asm/v850e_cache.h>
-
-
-#define CPU_MODEL "v850e/me2"
-#define CPU_MODEL_LONG "NEC V850E/ME2"
-
-
-/* Hardware-specific interrupt numbers (in the kernel IRQ namespace). */
-#define IRQ_INTP(n) (n) /* Pnnn (pin) interrupts */
-#define IRQ_INTP_NUM 31
-#define IRQ_INTCMD(n) (0x31 + (n)) /* interval timer interrupts 0-3 */
-#define IRQ_INTCMD_NUM 4
-#define IRQ_INTDMA(n) (0x41 + (n)) /* DMA interrupts 0-3 */
-#define IRQ_INTDMA_NUM 4
-#define IRQ_INTUBTIRE(n) (0x49 + (n)*5)/* UARTB 0-1 reception error */
-#define IRQ_INTUBTIRE_NUM 2
-#define IRQ_INTUBTIR(n) (0x4a + (n)*5) /* UARTB 0-1 reception complete */
-#define IRQ_INTUBTIR_NUM 2
-#define IRQ_INTUBTIT(n) (0x4b + (n)*5) /* UARTB 0-1 transmission complete */
-#define IRQ_INTUBTIT_NUM 2
-#define IRQ_INTUBTIF(n) (0x4c + (n)*5) /* UARTB 0-1 FIFO trans. complete */
-#define IRQ_INTUBTIF_NUM 2
-#define IRQ_INTUBTITO(n) (0x4d + (n)*5) /* UARTB 0-1 reception timeout */
-#define IRQ_INTUBTITO_NUM 2
-
-/* For <asm/irq.h> */
-#define NUM_CPU_IRQS 0x59 /* V850E/ME2 */
-
-
-/* For <asm/entry.h> */
-/* We use on-chip RAM, for a few miscellaneous variables that must be
- accessible using a load instruction relative to R0. */
-#define R0_RAM_ADDR 0xFFFFB000 /* V850E/ME2 */
-
-
-/* V850E/ME2 UARTB details.*/
-#define V850E_UART_NUM_CHANNELS 2
-#define V850E_UARTB_BASE_FREQ (CPU_CLOCK_FREQ / 4)
-
-/* This is a function that gets called before configuring the UART. */
-#define V850E_UART_PRE_CONFIGURE me2_uart_pre_configure
-#ifndef __ASSEMBLY__
-extern void me2_uart_pre_configure (unsigned chan,
- unsigned cflags, unsigned baud);
-#endif /* __ASSEMBLY__ */
-
-
-/* V850E/ME2 timer C details. */
-#define V850E_TIMER_C_BASE_ADDR 0xFFFFF600
-
-
-/* V850E/ME2 timer D details. */
-#define V850E_TIMER_D_BASE_ADDR 0xFFFFF540
-#define V850E_TIMER_D_TMD_BASE_ADDR (V850E_TIMER_D_BASE_ADDR + 0x0)
-#define V850E_TIMER_D_CMD_BASE_ADDR (V850E_TIMER_D_BASE_ADDR + 0x2)
-#define V850E_TIMER_D_TMCD_BASE_ADDR (V850E_TIMER_D_BASE_ADDR + 0x4)
-
-#define V850E_TIMER_D_BASE_FREQ (CPU_CLOCK_FREQ / 2)
-
-
-/* Select iRAM mode. */
-#define ME2_IRAMM_ADDR 0xFFFFF80A
-#define ME2_IRAMM (*(volatile u8*)ME2_IRAMM_ADDR)
-
-
-/* Interrupt edge-detection configuration. INTF(n) and INTR(n) are only
- valid for n == 1, 2, or 5. */
-#define ME2_INTF_ADDR(n) (0xFFFFFC00 + (n) * 0x2)
-#define ME2_INTF(n) (*(volatile u8*)ME2_INTF_ADDR(n))
-#define ME2_INTR_ADDR(n) (0xFFFFFC20 + (n) * 0x2)
-#define ME2_INTR(n) (*(volatile u8*)ME2_INTR_ADDR(n))
-#define ME2_INTFAL_ADDR 0xFFFFFC10
-#define ME2_INTFAL (*(volatile u8*)ME2_INTFAL_ADDR)
-#define ME2_INTRAL_ADDR 0xFFFFFC30
-#define ME2_INTRAL (*(volatile u8*)ME2_INTRAL_ADDR)
-#define ME2_INTFDH_ADDR 0xFFFFFC16
-#define ME2_INTFDH (*(volatile u16*)ME2_INTFDH_ADDR)
-#define ME2_INTRDH_ADDR 0xFFFFFC36
-#define ME2_INTRDH (*(volatile u16*)ME2_INTRDH_ADDR)
-#define ME2_SESC_ADDR(n) (0xFFFFF609 + (n) * 0x10)
-#define ME2_SESC(n) (*(volatile u8*)ME2_SESC_ADDR(n))
-#define ME2_SESA10_ADDR 0xFFFFF5AD
-#define ME2_SESA10 (*(volatile u8*)ME2_SESA10_ADDR)
-#define ME2_SESA11_ADDR 0xFFFFF5DD
-#define ME2_SESA11 (*(volatile u8*)ME2_SESA11_ADDR)
-
-
-/* Port 1 */
-/* Direct I/O. Bits 0-3 are pins P10-P13. */
-#define ME2_PORT1_IO_ADDR 0xFFFFF402
-#define ME2_PORT1_IO (*(volatile u8 *)ME2_PORT1_IO_ADDR)
-/* Port mode (for direct I/O, 0 = output, 1 = input). */
-#define ME2_PORT1_PM_ADDR 0xFFFFF422
-#define ME2_PORT1_PM (*(volatile u8 *)ME2_PORT1_PM_ADDR)
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode). */
-#define ME2_PORT1_PMC_ADDR 0xFFFFF442
-#define ME2_PORT1_PMC (*(volatile u8 *)ME2_PORT1_PMC_ADDR)
-/* Port function control (for serial interfaces, 0 = CSI30, 1 = UARTB0 ). */
-#define ME2_PORT1_PFC_ADDR 0xFFFFF462
-#define ME2_PORT1_PFC (*(volatile u8 *)ME2_PORT1_PFC_ADDR)
-
-/* Port 2 */
-/* Direct I/O. Bits 0-3 are pins P20-P25. */
-#define ME2_PORT2_IO_ADDR 0xFFFFF404
-#define ME2_PORT2_IO (*(volatile u8 *)ME2_PORT2_IO_ADDR)
-/* Port mode (for direct I/O, 0 = output, 1 = input). */
-#define ME2_PORT2_PM_ADDR 0xFFFFF424
-#define ME2_PORT2_PM (*(volatile u8 *)ME2_PORT2_PM_ADDR)
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode). */
-#define ME2_PORT2_PMC_ADDR 0xFFFFF444
-#define ME2_PORT2_PMC (*(volatile u8 *)ME2_PORT2_PMC_ADDR)
-/* Port function control (for serial interfaces, 0 = INTP2x, 1 = UARTB1 ). */
-#define ME2_PORT2_PFC_ADDR 0xFFFFF464
-#define ME2_PORT2_PFC (*(volatile u8 *)ME2_PORT2_PFC_ADDR)
-
-/* Port 5 */
-/* Direct I/O. Bits 0-5 are pins P50-P55. */
-#define ME2_PORT5_IO_ADDR 0xFFFFF40A
-#define ME2_PORT5_IO (*(volatile u8 *)ME2_PORT5_IO_ADDR)
-/* Port mode (for direct I/O, 0 = output, 1 = input). */
-#define ME2_PORT5_PM_ADDR 0xFFFFF42A
-#define ME2_PORT5_PM (*(volatile u8 *)ME2_PORT5_PM_ADDR)
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode). */
-#define ME2_PORT5_PMC_ADDR 0xFFFFF44A
-#define ME2_PORT5_PMC (*(volatile u8 *)ME2_PORT5_PMC_ADDR)
-/* Port function control (). */
-#define ME2_PORT5_PFC_ADDR 0xFFFFF46A
-#define ME2_PORT5_PFC (*(volatile u8 *)ME2_PORT5_PFC_ADDR)
-
-/* Port 6 */
-/* Direct I/O. Bits 5-7 are pins P65-P67. */
-#define ME2_PORT6_IO_ADDR 0xFFFFF40C
-#define ME2_PORT6_IO (*(volatile u8 *)ME2_PORT6_IO_ADDR)
-/* Port mode (for direct I/O, 0 = output, 1 = input). */
-#define ME2_PORT6_PM_ADDR 0xFFFFF42C
-#define ME2_PORT6_PM (*(volatile u8 *)ME2_PORT6_PM_ADDR)
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode). */
-#define ME2_PORT6_PMC_ADDR 0xFFFFF44C
-#define ME2_PORT6_PMC (*(volatile u8 *)ME2_PORT6_PMC_ADDR)
-/* Port function control (). */
-#define ME2_PORT6_PFC_ADDR 0xFFFFF46C
-#define ME2_PORT6_PFC (*(volatile u8 *)ME2_PORT6_PFC_ADDR)
-
-/* Port 7 */
-/* Direct I/O. Bits 2-7 are pins P72-P77. */
-#define ME2_PORT7_IO_ADDR 0xFFFFF40E
-#define ME2_PORT7_IO (*(volatile u8 *)ME2_PORT7_IO_ADDR)
-/* Port mode (for direct I/O, 0 = output, 1 = input). */
-#define ME2_PORT7_PM_ADDR 0xFFFFF42E
-#define ME2_PORT7_PM (*(volatile u8 *)ME2_PORT7_PM_ADDR)
-/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode). */
-#define ME2_PORT7_PMC_ADDR 0xFFFFF44E
-#define ME2_PORT7_PMC (*(volatile u8 *)ME2_PORT7_PMC_ADDR)
-/* Port function control (). */
-#define ME2_PORT7_PFC_ADDR 0xFFFFF46E
-#define ME2_PORT7_PFC (*(volatile u8 *)ME2_PORT7_PFC_ADDR)
-
-
-#ifndef __ASSEMBLY__
-/* Initialize V850E/ME2 chip interrupts. */
-extern void me2_init_irqs (void);
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_ME2_H__ */
diff --git a/include/asm-v850/mman.h b/include/asm-v850/mman.h
deleted file mode 100644
index edbf6edbfb3..00000000000
--- a/include/asm-v850/mman.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __V850_MMAN_H__
-#define __V850_MMAN_H__
-
-#include <asm-generic/mman.h>
-
-#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
-#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
-#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
-#define MAP_LOCKED 0x2000 /* pages are locked */
-#define MAP_NORESERVE 0x4000 /* don't check for reservations */
-
-#define MCL_CURRENT 1 /* lock all current mappings */
-#define MCL_FUTURE 2 /* lock all future mappings */
-
-#endif /* __V850_MMAN_H__ */
diff --git a/include/asm-v850/mmu.h b/include/asm-v850/mmu.h
deleted file mode 100644
index 267768c66ef..00000000000
--- a/include/asm-v850/mmu.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/* Copyright (C) 2002, 2005, David McCullough <davidm@snapgear.com> */
-
-#ifndef __V850_MMU_H__
-#define __V850_MMU_H__
-
-typedef struct {
- struct vm_list_struct *vmlist;
- unsigned long end_brk;
-} mm_context_t;
-
-#endif /* __V850_MMU_H__ */
diff --git a/include/asm-v850/mmu_context.h b/include/asm-v850/mmu_context.h
deleted file mode 100644
index 01daacd5474..00000000000
--- a/include/asm-v850/mmu_context.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __V850_MMU_CONTEXT_H__
-#define __V850_MMU_CONTEXT_H__
-
-#include <asm-generic/mm_hooks.h>
-
-#define destroy_context(mm) ((void)0)
-#define init_new_context(tsk,mm) 0
-#define switch_mm(prev,next,tsk) ((void)0)
-#define deactivate_mm(tsk,mm) do { } while (0)
-#define activate_mm(prev,next) ((void)0)
-#define enter_lazy_tlb(mm,tsk) ((void)0)
-
-#endif /* __V850_MMU_CONTEXT_H__ */
diff --git a/include/asm-v850/module.h b/include/asm-v850/module.h
deleted file mode 100644
index 2c2f4944f09..00000000000
--- a/include/asm-v850/module.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * include/asm-v850/module.h -- Architecture-specific module hooks
- *
- * Copyright (C) 2001,02,03,04 NEC Corporation
- * Copyright (C) 2001,02,03,04 Miles Bader <miles@gnu.org>
- * Copyright (C) 2001,03 Rusty Russell
- *
- * 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.
- *
- * Written by Miles Bader <miles@gnu.org>
- *
- * Derived in part from include/asm-ppc/module.h
- */
-
-#ifndef __V850_MODULE_H__
-#define __V850_MODULE_H__
-
-#define MODULE_SYMBOL_PREFIX "_"
-
-struct v850_plt_entry
-{
- /* Indirect jump instruction sequence (6-byte mov + 2-byte jr). */
- unsigned long tramp[2];
-};
-
-struct mod_arch_specific
-{
- /* Indices of PLT sections within module. */
- unsigned int core_plt_section, init_plt_section;
-};
-
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Ehdr Elf32_Ehdr
-
-/* Make empty sections for module_frob_arch_sections to expand. */
-#ifdef MODULE
-asm(".section .plt,\"ax\",@nobits; .align 3; .previous");
-asm(".section .init.plt,\"ax\",@nobits; .align 3; .previous");
-#endif
-
-/* We don't do exception tables. */
-struct exception_table_entry;
-static inline const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
-{
- return 0;
-}
-#define ARCH_HAS_SEARCH_EXTABLE
-static inline void
-sort_extable(struct exception_table_entry *start,
- struct exception_table_entry *finish)
-{
- /* nada */
-}
-#define ARCH_HAS_SORT_EXTABLE
-
-#endif /* __V850_MODULE_H__ */
diff --git a/include/asm-v850/msgbuf.h b/include/asm-v850/msgbuf.h
deleted file mode 100644
index ed07dbd0163..00000000000
--- a/include/asm-v850/msgbuf.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef __V850_MSGBUF_H__
-#define __V850_MSGBUF_H__
-
-/*
- * The msqid64_ds structure for v850 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct msqid64_ds {
- struct ipc64_perm msg_perm;
- __kernel_time_t msg_stime; /* last msgsnd time */
- unsigned long __unused1;
- __kernel_time_t msg_rtime; /* last msgrcv time */
- unsigned long __unused2;
- __kernel_time_t msg_ctime; /* last change time */
- unsigned long __unused3;
- unsigned long msg_cbytes; /* current number of bytes on queue */
- unsigned long msg_qnum; /* number of messages in queue */
- unsigned long msg_qbytes; /* max number of bytes on queue */
- __kernel_pid_t msg_lspid; /* pid of last msgsnd */
- __kernel_pid_t msg_lrpid; /* last receive pid */
- unsigned long __unused4;
- unsigned long __unused5;
-};
-
-#endif /* __V850_MSGBUF_H__ */
diff --git a/include/asm-v850/mutex.h b/include/asm-v850/mutex.h
deleted file mode 100644
index 458c1f7fbc1..00000000000
--- a/include/asm-v850/mutex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-v850/page.h b/include/asm-v850/page.h
deleted file mode 100644
index 74a539a9bd5..00000000000
--- a/include/asm-v850/page.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * include/asm-v850/page.h -- VM ops
- *
- * Copyright (C) 2001,02,03,05 NEC Electronics Corporation
- * Copyright (C) 2001,02,03,05 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_PAGE_H__
-#define __V850_PAGE_H__
-
-#include <asm/machdep.h>
-
-
-#define PAGE_SHIFT 12
-#define PAGE_SIZE (1UL << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
-
-
-/*
- * PAGE_OFFSET -- the first address of the first page of memory. For archs with
- * no MMU this corresponds to the first free page in physical memory (aligned
- * on a page boundary).
- */
-#ifndef PAGE_OFFSET
-#define PAGE_OFFSET 0x0000000
-#endif
-
-
-#ifndef __ASSEMBLY__
-
-#define STRICT_MM_TYPECHECKS
-
-#define clear_page(page) memset ((void *)(page), 0, PAGE_SIZE)
-#define copy_page(to, from) memcpy ((void *)(to), (void *)from, PAGE_SIZE)
-
-#define clear_user_page(addr, vaddr, page) \
- do { clear_page(addr); \
- flush_dcache_page(page); \
- } while (0)
-#define copy_user_page(to, from, vaddr, page) \
- do { copy_page(to, from); \
- flush_dcache_page(page); \
- } while (0)
-
-#ifdef STRICT_MM_TYPECHECKS
-/*
- * These are used to make use of C type-checking..
- */
-
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pmd; } pmd_t;
-typedef struct { unsigned long pgd; } pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-typedef struct page *pgtable_t;
-
-#define pte_val(x) ((x).pte)
-#define pmd_val(x) ((x).pmd)
-#define pgd_val(x) ((x).pgd)
-#define pgprot_val(x) ((x).pgprot)
-
-#define __pte(x) ((pte_t) { (x) } )
-#define __pmd(x) ((pmd_t) { (x) } )
-#define __pgd(x) ((pgd_t) { (x) } )
-#define __pgprot(x) ((pgprot_t) { (x) } )
-
-#else /* !STRICT_MM_TYPECHECKS */
-/*
- * .. while these make it easier on the compiler
- */
-
-typedef unsigned long pte_t;
-typedef unsigned long pmd_t;
-typedef unsigned long pgd_t;
-typedef unsigned long pgprot_t;
-
-#define pte_val(x) (x)
-#define pmd_val(x) (x)
-#define pgd_val(x) (x)
-#define pgprot_val(x) (x)
-
-#define __pte(x) (x)
-#define __pmd(x) (x)
-#define __pgd(x) (x)
-#define __pgprot(x) (x)
-
-#endif /* STRICT_MM_TYPECHECKS */
-
-#endif /* !__ASSEMBLY__ */
-
-
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-
-
-/* No current v850 processor has virtual memory. */
-#define __virt_to_phys(addr) (addr)
-#define __phys_to_virt(addr) (addr)
-
-#define virt_to_pfn(kaddr) (__virt_to_phys (kaddr) >> PAGE_SHIFT)
-#define pfn_to_virt(pfn) __phys_to_virt ((pfn) << PAGE_SHIFT)
-
-#define MAP_NR(kaddr) \
- (((unsigned long)(kaddr) - PAGE_OFFSET) >> PAGE_SHIFT)
-#define virt_to_page(kaddr) (mem_map + MAP_NR (kaddr))
-#define page_to_virt(page) \
- ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
-
-#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
-#define pfn_valid(pfn) ((pfn) < max_mapnr)
-
-#define virt_addr_valid(kaddr) \
- (((void *)(kaddr) >= (void *)PAGE_OFFSET) && MAP_NR (kaddr) < max_mapnr)
-
-
-#define __pa(x) __virt_to_phys ((unsigned long)(x))
-#define __va(x) ((void *)__phys_to_virt ((unsigned long)(x)))
-
-
-#include <asm-generic/memory_model.h>
-#include <asm-generic/page.h>
-
-#endif /* __V850_PAGE_H__ */
diff --git a/include/asm-v850/param.h b/include/asm-v850/param.h
deleted file mode 100644
index 4391f5fe020..00000000000
--- a/include/asm-v850/param.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * include/asm-v850/param.h -- Varions kernel parameters
- *
- * Copyright (C) 2001,02 NEC Corporation
- * Copyright (C) 2001,02 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_PARAM_H__
-#define __V850_PARAM_H__
-
-#define EXEC_PAGESIZE 4096
-
-#ifndef NOGROUP
-#define NOGROUP (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64 /* max length of hostname */
-
-#ifdef __KERNEL__
-# define HZ CONFIG_HZ
-# define USER_HZ 100
-# define CLOCKS_PER_SEC USER_HZ
-#else
-# define HZ 100
-#endif
-
-#endif /* __V850_PARAM_H__ */
diff --git a/include/asm-v850/pci.h b/include/asm-v850/pci.h
deleted file mode 100644
index de2a7d0a81c..00000000000
--- a/include/asm-v850/pci.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * include/asm-v850/pci.h -- PCI support
- *
- * Copyright (C) 2001,02,05 NEC Corporation
- * Copyright (C) 2001,02,05 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_PCI_H__
-#define __V850_PCI_H__
-
-/* Get any platform-dependent definitions. */
-#include <asm/machdep.h>
-
-#define pcibios_scan_all_fns(a, b) 0
-
-/* Generic declarations. */
-
-struct scatterlist;
-
-extern void pcibios_set_master (struct pci_dev *dev);
-
-/* `Grant' to PDEV the memory block at CPU_ADDR, for doing DMA. The
- 32-bit PCI bus mastering address to use is returned. the device owns
- this memory until either pci_unmap_single or pci_dma_sync_single_for_cpu is
- performed. */
-extern dma_addr_t
-pci_map_single (struct pci_dev *pdev, void *cpu_addr, size_t size, int dir);
-
-/* Return to the CPU the PCI DMA memory block previously `granted' to
- PDEV, at DMA_ADDR. */
-extern void
-pci_unmap_single (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
- int dir);
-
-/* Make physical memory consistent for a single streaming mode DMA
- translation after a transfer.
-
- If you perform a pci_map_single() but wish to interrogate the
- buffer using the cpu, yet do not wish to teardown the PCI dma
- mapping, you must call this function before doing so. At the next
- point you give the PCI dma address back to the card, you must first
- perform a pci_dma_sync_for_device, and then the device again owns
- the buffer. */
-extern void
-pci_dma_sync_single_for_cpu (struct pci_dev *dev, dma_addr_t dma_addr,
- size_t size, int dir);
-
-extern void
-pci_dma_sync_single_for_device (struct pci_dev *dev, dma_addr_t dma_addr,
- size_t size, int dir);
-
-
-/* Do multiple DMA mappings at once. */
-extern int
-pci_map_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len, int dir);
-
-/* Unmap multiple DMA mappings at once. */
-extern void
-pci_unmap_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len,
- int dir);
-
-/* SG-list versions of pci_dma_sync functions. */
-extern void
-pci_dma_sync_sg_for_cpu (struct pci_dev *dev,
- struct scatterlist *sg, int sg_len,
- int dir);
-extern void
-pci_dma_sync_sg_for_device (struct pci_dev *dev,
- struct scatterlist *sg, int sg_len,
- int dir);
-
-#define pci_map_page(dev, page, offs, size, dir) \
- pci_map_single(dev, (page_address(page) + (offs)), size, dir)
-#define pci_unmap_page(dev,addr,sz,dir) \
- pci_unmap_single(dev, addr, sz, dir)
-
-/* Test for pci_map_single or pci_map_page having generated an error. */
-static inline int
-pci_dma_mapping_error (dma_addr_t dma_addr)
-{
- return dma_addr == 0;
-}
-
-/* Allocate and map kernel buffer using consistent mode DMA for PCI
- device. Returns non-NULL cpu-view pointer to the buffer if
- successful and sets *DMA_ADDR to the pci side dma address as well,
- else DMA_ADDR is undefined. */
-extern void *
-pci_alloc_consistent (struct pci_dev *pdev, size_t size, dma_addr_t *dma_addr);
-
-/* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must
- be values that were returned from pci_alloc_consistent. SIZE must be
- the same as what as passed into pci_alloc_consistent. References to
- the memory and mappings assosciated with CPU_ADDR or DMA_ADDR past
- this call are illegal. */
-extern void
-pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr,
- dma_addr_t dma_addr);
-
-#ifdef CONFIG_PCI
-static inline void pci_dma_burst_advice(struct pci_dev *pdev,
- enum pci_dma_burst_strategy *strat,
- unsigned long *strategy_parameter)
-{
- *strat = PCI_DMA_BURST_INFINITY;
- *strategy_parameter = ~0UL;
-}
-#endif
-
-extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
-extern void pci_iounmap (struct pci_dev *dev, void __iomem *addr);
-
-#endif /* __V850_PCI_H__ */
diff --git a/include/asm-v850/percpu.h b/include/asm-v850/percpu.h
deleted file mode 100644
index 755ac6522b6..00000000000
--- a/include/asm-v850/percpu.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __V850_PERCPU_H__
-#define __V850_PERCPU_H__
-
-#include <asm-generic/percpu.h>
-
-/* This is a stupid hack to satisfy some grotty implicit include-file
- dependency; basically, <linux/smp.h> uses BUG_ON, which calls BUG, but
- doesn't include the necessary headers to define it. In the twisted
- festering mess of includes this must all be resolved somehow on other
- platforms, but I haven't the faintest idea how, and don't care; here will
- do, even though doesn't actually make any sense. */
-#include <asm/page.h>
-
-#endif /* __V850_PERCPU_H__ */
diff --git a/include/asm-v850/pgalloc.h b/include/asm-v850/pgalloc.h
deleted file mode 100644
index b91eb2d02bf..00000000000
--- a/include/asm-v850/pgalloc.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * include/asm-v850/pgalloc.h
- *
- * Copyright (C) 2001,02 NEC Corporation
- * Copyright (C) 2001,02 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_PGALLOC_H__
-#define __V850_PGALLOC_H__
-
-#include <linux/mm.h> /* some crap code expects this */
-
-/* ... and then, there was one. */
-#define check_pgt_cache() ((void)0)
-
-#endif /* __V850_PGALLOC_H__ */
diff --git a/include/asm-v850/pgtable.h b/include/asm-v850/pgtable.h
deleted file mode 100644
index 1ea2a900f0f..00000000000
--- a/include/asm-v850/pgtable.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef __V850_PGTABLE_H__
-#define __V850_PGTABLE_H__
-
-#include <asm-generic/4level-fixup.h>
-
-#include <asm/page.h>
-
-
-#define pgd_present(pgd) (1) /* pages are always present on NO_MM */
-#define pgd_none(pgd) (0)
-#define pgd_bad(pgd) (0)
-#define pgd_clear(pgdp) ((void)0)
-
-#define pmd_offset(a, b) ((void *)0)
-
-#define kern_addr_valid(addr) (1)
-
-
-#define __swp_type(x) (0)
-#define __swp_offset(x) (0)
-#define __swp_entry(typ,off) ((swp_entry_t) { ((typ) | ((off) << 7)) })
-#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
-#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
-
-static inline int pte_file (pte_t pte) { return 0; }
-
-
-/* These mean nothing to !CONFIG_MMU. */
-#define PAGE_NONE __pgprot(0)
-#define PAGE_SHARED __pgprot(0)
-#define PAGE_COPY __pgprot(0)
-#define PAGE_READONLY __pgprot(0)
-#define PAGE_KERNEL __pgprot(0)
-
-
-/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc. When CONFIG_MMU is not defined, this
- * should never actually be used, so just define it to something that's
- * will hopefully cause a bus error if it is.
- */
-#define ZERO_PAGE(vaddr) ((void *)0x87654321)
-
-
-/* Some bogus code in procfs uses these; whatever. */
-#define VMALLOC_START 0
-#define VMALLOC_END (~0)
-
-
-extern void paging_init (void);
-#define swapper_pg_dir ((pgd_t *) 0)
-
-#define pgtable_cache_init() ((void)0)
-
-
-extern unsigned int kobjsize(const void *objp);
-
-
-#endif /* __V850_PGTABLE_H__ */
diff --git a/include/asm-v850/poll.h b/include/asm-v850/poll.h
deleted file mode 100644
index 803cad0b9b5..00000000000
--- a/include/asm-v850/poll.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __V850_POLL_H__
-#define __V850_POLL_H__
-
-#define POLLWRNORM POLLOUT
-#define POLLWRBAND 0x0100
-
-#include <asm-generic/poll.h>
-
-#endif /* __V850_POLL_H__ */
diff --git a/include/asm-v850/posix_types.h b/include/asm-v850/posix_types.h
deleted file mode 100644
index 7f403b76539..00000000000
--- a/include/asm-v850/posix_types.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * include/asm-v850/posix_types.h -- Kernel versions of standard types
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_POSIX_TYPES_H__
-#define __V850_POSIX_TYPES_H__
-
-typedef unsigned long __kernel_ino_t;
-typedef unsigned long long __kernel_ino64_t;
-typedef unsigned int __kernel_mode_t;
-typedef unsigned int __kernel_nlink_t;
-typedef long __kernel_off_t;
-typedef long long __kernel_loff_t;
-typedef int __kernel_pid_t;
-typedef unsigned short __kernel_ipc_pid_t;
-typedef unsigned int __kernel_uid_t;
-typedef unsigned int __kernel_gid_t;
-typedef unsigned int __kernel_size_t;
-typedef int __kernel_ssize_t;
-typedef int __kernel_ptrdiff_t;
-typedef long __kernel_time_t;
-typedef long __kernel_suseconds_t;
-typedef long __kernel_clock_t;
-typedef int __kernel_timer_t;
-typedef int __kernel_clockid_t;
-typedef int __kernel_daddr_t;
-typedef char * __kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef unsigned int __kernel_uid32_t;
-typedef unsigned int __kernel_gid32_t;
-
-/* Some bogus code depends on this; we don't care. */
-typedef __kernel_uid_t __kernel_old_uid_t;
-typedef unsigned int __kernel_old_dev_t;
-
-typedef struct {
- int val[2];
-} __kernel_fsid_t;
-
-
-#if defined(__KERNEL__)
-
-/* We used to include <asm/bitops.h> here, which seems the right thing, but
- it caused nasty include-file definition order problems. Removing the
- include seems to work, so fingers crossed... */
-
-#undef __FD_SET
-#define __FD_SET(fd, fd_set) \
- __set_bit (fd, (void *)&((__kernel_fd_set *)fd_set)->fds_bits)
-#undef __FD_CLR
-#define __FD_CLR(fd, fd_set) \
- __clear_bit (fd, (void *)&((__kernel_fd_set *)fd_set)->fds_bits)
-#undef __FD_ISSET
-#define __FD_ISSET(fd, fd_set) \
- __test_bit (fd, (void *)&((__kernel_fd_set *)fd_set)->fds_bits)
-#undef __FD_ZERO
-#define __FD_ZERO(fd_set) \
- memset (fd_set, 0, sizeof (*(fd_set *)fd_set))
-
-#endif /* defined(__KERNEL__) */
-
-#endif /* __V850_POSIX_TYPES_H__ */
diff --git a/include/asm-v850/processor.h b/include/asm-v850/processor.h
deleted file mode 100644
index 979e3467f9a..00000000000
--- a/include/asm-v850/processor.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * include/asm-v850/processor.h
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_PROCESSOR_H__
-#define __V850_PROCESSOR_H__
-
-#ifndef __ASSEMBLY__ /* <linux/thread_info.h> is not asm-safe. */
-#include <linux/thread_info.h>
-#endif
-
-#include <linux/compiler.h>
-#include <asm/ptrace.h>
-#include <asm/entry.h>
-
-/* Some code expects `segment' stuff to be defined here. */
-#include <asm/segment.h>
-
-
-/*
- * The only places this is used seem to be horrible bletcherous kludges,
- * so we just define it to be as large as possible.
- */
-#define TASK_SIZE (0xFFFFFFFF)
-
-/*
- * This decides where the kernel will search for a free chunk of vm
- * space during mmap's. We won't be using it.
- */
-#define TASK_UNMAPPED_BASE 0
-
-
-#ifndef __ASSEMBLY__
-
-
-/*
- * Default implementation of macro that returns current
- * instruction pointer ("program counter").
- */
-#define current_text_addr() ({ __label__ _l; _l: &&_l;})
-
-/* If you change this, you must change the associated assembly-languages
- constants defined below, THREAD_*. */
-struct thread_struct {
- /* kernel stack pointer (must be first field in structure) */
- unsigned long ksp;
-};
-
-#define INIT_THREAD { sizeof init_stack + (unsigned long)init_stack }
-
-
-/* Do necessary setup to start up a newly executed thread. */
-static inline void start_thread (struct pt_regs *regs,
- unsigned long pc, unsigned long usp)
-{
- regs->pc = pc;
- regs->gpr[GPR_SP] = usp;
- regs->kernel_mode = 0;
-}
-
-/* Free all resources held by a thread. */
-static inline void release_thread (struct task_struct *dead_task)
-{
-}
-
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk) do { } while (0)
-
-extern int kernel_thread (int (*fn)(void *), void * arg, unsigned long flags);
-
-/* Free current thread data structures etc. */
-static inline void exit_thread (void)
-{
-}
-
-
-/* Return the registers saved during context-switch by the currently
- not-running thread T. Note that this only includes some registers!
- See entry.S for details. */
-#define thread_saved_regs(t) \
- ((struct pt_regs*)((t)->thread.ksp + STATE_SAVE_PT_OFFSET))
-/* Return saved (kernel) PC of a blocked thread. Actually, we return the
- LP register, because the thread is actually blocked in switch_thread,
- and we're interested in the PC it will _return_ to. */
-#define thread_saved_pc(t) (thread_saved_regs(t)->gpr[GPR_LP])
-
-
-unsigned long get_wchan (struct task_struct *p);
-
-
-/* Return some info about the user process TASK. */
-#define task_tos(task) ((unsigned long)task_stack_page(task) + THREAD_SIZE)
-#define task_pt_regs(task) ((struct pt_regs *)task_tos (task) - 1)
-#define task_sp(task) (task_pt_regs (task)->gpr[GPR_SP])
-#define task_pc(task) (task_pt_regs (task)->pc)
-/* Grotty old names for some. */
-#define KSTK_EIP(task) task_pc (task)
-#define KSTK_ESP(task) task_sp (task)
-
-
-#define cpu_relax() barrier()
-
-
-#else /* __ASSEMBLY__ */
-
-#define THREAD_KSP 0
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_PROCESSOR_H__ */
diff --git a/include/asm-v850/ptrace.h b/include/asm-v850/ptrace.h
deleted file mode 100644
index 4f35cf2cd64..00000000000
--- a/include/asm-v850/ptrace.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * include/asm-v850/ptrace.h -- Access to CPU registers
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_PTRACE_H__
-#define __V850_PTRACE_H__
-
-
-/* v850 general purpose registers with special meanings. */
-#define GPR_ZERO 0 /* constant zero */
-#define GPR_ASM 1 /* reserved for assembler */
-#define GPR_SP 3 /* stack pointer */
-#define GPR_GP 4 /* global data pointer */
-#define GPR_TP 5 /* `text pointer' */
-#define GPR_EP 30 /* `element pointer' */
-#define GPR_LP 31 /* link pointer (current return address) */
-
-/* These aren't official names, but they make some code more descriptive. */
-#define GPR_ARG0 6
-#define GPR_ARG1 7
-#define GPR_ARG2 8
-#define GPR_ARG3 9
-#define GPR_RVAL0 10
-#define GPR_RVAL1 11
-#define GPR_RVAL GPR_RVAL0
-
-#define NUM_GPRS 32
-
-/* v850 `system' registers. */
-#define SR_EIPC 0
-#define SR_EIPSW 1
-#define SR_FEPC 2
-#define SR_FEPSW 3
-#define SR_ECR 4
-#define SR_PSW 5
-#define SR_CTPC 16
-#define SR_CTPSW 17
-#define SR_DBPC 18
-#define SR_DBPSW 19
-#define SR_CTBP 20
-#define SR_DIR 21
-#define SR_ASID 23
-
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned long v850_reg_t;
-
-/* How processor state is stored on the stack during a syscall/signal.
- If you change this structure, change the associated assembly-language
- macros below too (PT_*)! */
-struct pt_regs
-{
- /* General purpose registers. */
- v850_reg_t gpr[NUM_GPRS];
-
- v850_reg_t pc; /* program counter */
- v850_reg_t psw; /* program status word */
-
- /* Registers used by `callt' instruction: */
- v850_reg_t ctpc; /* saved program counter */
- v850_reg_t ctpsw; /* saved psw */
- v850_reg_t ctbp; /* base pointer for callt table */
-
- char kernel_mode; /* 1 if in `kernel mode', 0 if user mode */
-};
-
-
-#define instruction_pointer(regs) ((regs)->pc)
-#define profile_pc(regs) instruction_pointer(regs)
-#define user_mode(regs) (!(regs)->kernel_mode)
-
-/* When a struct pt_regs is used to save user state for a system call in
- the kernel, the system call is stored in the space for R0 (since it's
- never used otherwise, R0 being a constant 0). Non-system-calls
- simply store 0 there. */
-#define PT_REGS_SYSCALL(regs) (regs)->gpr[0]
-#define PT_REGS_SET_SYSCALL(regs, val) ((regs)->gpr[0] = (val))
-
-#endif /* !__ASSEMBLY__ */
-
-
-/* The number of bytes used to store each register. */
-#define _PT_REG_SIZE 4
-
-/* Offset of a general purpose register in a struct pt_regs. */
-#define PT_GPR(num) ((num) * _PT_REG_SIZE)
-
-/* Offsets of various special registers & fields in a struct pt_regs. */
-#define PT_PC ((NUM_GPRS + 0) * _PT_REG_SIZE)
-#define PT_PSW ((NUM_GPRS + 1) * _PT_REG_SIZE)
-#define PT_CTPC ((NUM_GPRS + 2) * _PT_REG_SIZE)
-#define PT_CTPSW ((NUM_GPRS + 3) * _PT_REG_SIZE)
-#define PT_CTBP ((NUM_GPRS + 4) * _PT_REG_SIZE)
-#define PT_KERNEL_MODE ((NUM_GPRS + 5) * _PT_REG_SIZE)
-
-/* Where the current syscall number is stashed; obviously only valid in
- the kernel! */
-#define PT_CUR_SYSCALL PT_GPR(0)
-
-/* Size of struct pt_regs, including alignment. */
-#define PT_SIZE ((NUM_GPRS + 6) * _PT_REG_SIZE)
-
-
-/* These are `magic' values for PTRACE_PEEKUSR that return info about where
- a process is located in memory. */
-#define PT_TEXT_ADDR (PT_SIZE + 1)
-#define PT_TEXT_LEN (PT_SIZE + 2)
-#define PT_DATA_ADDR (PT_SIZE + 3)
-
-
-#endif /* __V850_PTRACE_H__ */
diff --git a/include/asm-v850/resource.h b/include/asm-v850/resource.h
deleted file mode 100644
index 4b9dcd44f8d..00000000000
--- a/include/asm-v850/resource.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_RESOURCE_H__
-#define __V850_RESOURCE_H__
-
-#include <asm-generic/resource.h>
-
-#endif /* __V850_RESOURCE_H__ */
diff --git a/include/asm-v850/rte_cb.h b/include/asm-v850/rte_cb.h
deleted file mode 100644
index db9879f00aa..00000000000
--- a/include/asm-v850/rte_cb.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * include/asm-v850/rte_cb.h -- Midas labs RTE-CB series of evaluation boards
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_RTE_CB_H__
-#define __V850_RTE_CB_H__
-
-
-/* The SRAM on the Mother-A motherboard. */
-#define MB_A_SRAM_ADDR GCS0_ADDR
-#define MB_A_SRAM_SIZE 0x00200000 /* 2MB */
-
-
-#ifdef CONFIG_RTE_GBUS_INT
-/* GBUS interrupt support. */
-
-# include <asm/gbus_int.h>
-
-# define GBUS_INT_BASE_IRQ NUM_RTE_CB_IRQS
-# define GBUS_INT_BASE_ADDR (GCS2_ADDR + 0x00006000)
-
-/* Some specific interrupts. */
-# define IRQ_MB_A_LAN IRQ_GBUS_INT(10)
-# define IRQ_MB_A_PCI1(n) (IRQ_GBUS_INT(16) + (n))
-# define IRQ_MB_A_PCI1_NUM 4
-# define IRQ_MB_A_PCI2(n) (IRQ_GBUS_INT(20) + (n))
-# define IRQ_MB_A_PCI2_NUM 4
-# define IRQ_MB_A_EXT(n) (IRQ_GBUS_INT(24) + (n))
-# define IRQ_MB_A_EXT_NUM 4
-# define IRQ_MB_A_USB_OC(n) (IRQ_GBUS_INT(28) + (n))
-# define IRQ_MB_A_USB_OC_NUM 2
-# define IRQ_MB_A_PCMCIA_OC IRQ_GBUS_INT(30)
-
-/* We define NUM_MACH_IRQS to include extra interrupts from the GBUS. */
-# define NUM_MACH_IRQS (NUM_RTE_CB_IRQS + IRQ_GBUS_INT_NUM)
-
-#else /* !CONFIG_RTE_GBUS_INT */
-
-# define NUM_MACH_IRQS NUM_RTE_CB_IRQS
-
-#endif /* CONFIG_RTE_GBUS_INT */
-
-
-#ifdef CONFIG_RTE_MB_A_PCI
-/* Mother-A PCI bus support. */
-
-# include <asm/rte_mb_a_pci.h>
-
-/* These are the base addresses used for allocating device address
- space. 512K of the motherboard SRAM is in the same space, so we have
- to be careful not to let it be allocated. */
-# define PCIBIOS_MIN_MEM (MB_A_PCI_MEM_ADDR + 0x80000)
-# define PCIBIOS_MIN_IO MB_A_PCI_IO_ADDR
-
-/* As we don't really support PCI DMA to cpu memory, and use bounce-buffers
- instead, perversely enough, this becomes always true! */
-# define pci_dma_supported(dev, mask) 1
-# define pcibios_assign_all_busses() 1
-
-#endif /* CONFIG_RTE_MB_A_PCI */
-
-
-#ifndef __ASSEMBLY__
-extern void rte_cb_early_init (void);
-extern void rte_cb_init_irqs (void);
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_RTE_CB_H__ */
diff --git a/include/asm-v850/rte_ma1_cb.h b/include/asm-v850/rte_ma1_cb.h
deleted file mode 100644
index bd3162ab984..00000000000
--- a/include/asm-v850/rte_ma1_cb.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * include/asm-v850/rte_ma1_cb.h -- Midas labs RTE-V850/MA1-CB board
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_RTE_MA1_CB_H__
-#define __V850_RTE_MA1_CB_H__
-
-#include <asm/rte_cb.h> /* Common defs for Midas RTE-CB boards. */
-
-
-#define PLATFORM "rte-v850e/ma1-cb"
-#define PLATFORM_LONG "Midas lab RTE-V850E/MA1-CB"
-
-#define CPU_CLOCK_FREQ 50000000 /* 50MHz */
-
-/* 1MB of onboard SRAM. Note that the monitor ROM uses parts of this
- for its own purposes, so care must be taken. Some address lines are
- not decoded, so the SRAM area is mirrored every 1MB from 0x400000 to
- 0x800000 (exclusive). */
-#define SRAM_ADDR 0x00400000
-#define SRAM_SIZE 0x00100000 /* 1MB */
-
-/* 32MB of onbard SDRAM. */
-#define SDRAM_ADDR 0x00800000
-#define SDRAM_SIZE 0x02000000 /* 32MB */
-
-
-/* CPU addresses of GBUS memory spaces. */
-#define GCS0_ADDR 0x05000000 /* GCS0 - Common SRAM (2MB) */
-#define GCS0_SIZE 0x00200000 /* 2MB */
-#define GCS1_ADDR 0x06000000 /* GCS1 - Flash ROM (8MB) */
-#define GCS1_SIZE 0x00800000 /* 8MB */
-#define GCS2_ADDR 0x07900000 /* GCS2 - I/O registers */
-#define GCS2_SIZE 0x00400000 /* 4MB */
-#define GCS5_ADDR 0x04000000 /* GCS5 - PCI bus space */
-#define GCS5_SIZE 0x01000000 /* 16MB */
-#define GCS6_ADDR 0x07980000 /* GCS6 - PCI control registers */
-#define GCS6_SIZE 0x00000200 /* 512B */
-
-
-/* For <asm/page.h> */
-#define PAGE_OFFSET SRAM_ADDR
-
-
-/* The GBUS GINT0 - GINT3 interrupts are connected to the INTP000 - INTP011
- pins on the CPU. These are shared among the GBUS interrupts. */
-#define IRQ_GINT(n) IRQ_INTP(n)
-#define IRQ_GINT_NUM 4
-
-/* Used by <asm/rte_cb.h> to derive NUM_MACH_IRQS. */
-#define NUM_RTE_CB_IRQS NUM_CPU_IRQS
-
-
-#ifdef CONFIG_ROM_KERNEL
-/* Kernel is in ROM, starting at address 0. */
-
-#define INTV_BASE 0
-
-#else /* !CONFIG_ROM_KERNEL */
-
-#ifdef CONFIG_RTE_CB_MULTI
-/* Using RAM kernel with ROM monitor for Multi debugger. */
-
-/* The chip's real interrupt vectors are in ROM, but they jump to a
- secondary interrupt vector table in RAM. */
-#define INTV_BASE 0x004F8000
-
-/* Scratch memory used by the ROM monitor, which shouldn't be used by
- linux (except for the alternate interrupt vector area, defined
- above). */
-#define MON_SCRATCH_ADDR 0x004F8000
-#define MON_SCRATCH_SIZE 0x00008000 /* 32KB */
-
-#else /* !CONFIG_RTE_CB_MULTI */
-/* Using RAM-kernel. Assume some sort of boot-loader got us loaded at
- address 0. */
-
-#define INTV_BASE 0
-
-#endif /* CONFIG_RTE_CB_MULTI */
-
-#endif /* CONFIG_ROM_KERNEL */
-
-
-/* Some misc. on-board devices. */
-
-/* Seven-segment LED display (two digits). Write-only. */
-#define LED_ADDR(n) (0x07802000 + (n))
-#define LED(n) (*(volatile unsigned char *)LED_ADDR(n))
-#define LED_NUM_DIGITS 2
-
-
-/* Override the basic MA uart pre-initialization so that we can
- initialize extra stuff. */
-#undef V850E_UART_PRE_CONFIGURE /* should be defined by <asm/ma.h> */
-#define V850E_UART_PRE_CONFIGURE rte_ma1_cb_uart_pre_configure
-#ifndef __ASSEMBLY__
-extern void rte_ma1_cb_uart_pre_configure (unsigned chan,
- unsigned cflags, unsigned baud);
-#endif
-
-/* This board supports RTS/CTS for the on-chip UART, but only for channel 0. */
-
-/* CTS for UART channel 0 is pin P43 (bit 3 of port 4). */
-#define V850E_UART_CTS(chan) ((chan) == 0 ? !(MA_PORT4_IO & 0x8) : 1)
-/* RTS for UART channel 0 is pin P42 (bit 2 of port 4). */
-#define V850E_UART_SET_RTS(chan, val) \
- do { \
- if (chan == 0) { \
- unsigned old = MA_PORT4_IO; \
- if (val) \
- MA_PORT4_IO = old & ~0x4; \
- else \
- MA_PORT4_IO = old | 0x4; \
- } \
- } while (0)
-
-
-#endif /* __V850_RTE_MA1_CB_H__ */
diff --git a/include/asm-v850/rte_mb_a_pci.h b/include/asm-v850/rte_mb_a_pci.h
deleted file mode 100644
index 41ac185ca9c..00000000000
--- a/include/asm-v850/rte_mb_a_pci.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * include/asm-v850/mb_a_pci.h -- PCI support for Midas lab RTE-MOTHER-A board
- *
- * Copyright (C) 2001 NEC Corporation
- * Copyright (C) 2001 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_MB_A_PCI_H__
-#define __V850_MB_A_PCI_H__
-
-
-#define MB_A_PCI_MEM_ADDR GCS5_ADDR
-#define MB_A_PCI_MEM_SIZE (GCS5_SIZE / 2)
-#define MB_A_PCI_IO_ADDR (GCS5_ADDR + MB_A_PCI_MEM_SIZE)
-#define MB_A_PCI_IO_SIZE (GCS5_SIZE / 2)
-#define MB_A_PCI_REG_BASE_ADDR GCS6_ADDR
-
-#define MB_A_PCI_PCICR_ADDR (MB_A_PCI_REG_BASE_ADDR + 0x4)
-#define MB_A_PCI_PCICR (*(volatile u16 *)MB_A_PCI_PCICR_ADDR)
-#define MB_A_PCI_PCISR_ADDR (MB_A_PCI_REG_BASE_ADDR + 0x6)
-#define MB_A_PCI_PCISR (*(volatile u16 *)MB_A_PCI_PCISR_ADDR)
-#define MB_A_PCI_PCILTR_ADDR (MB_A_PCI_REG_BASE_ADDR + 0xD)
-#define MB_A_PCI_PCILTR (*(volatile u8 *)MB_A_PCI_PCILTR_ADDR)
-#define MB_A_PCI_PCIBAR0_ADDR (MB_A_PCI_REG_BASE_ADDR + 0x10)
-#define MB_A_PCI_PCIBAR0 (*(volatile u32 *)MB_A_PCI_PCIBAR0_ADDR)
-#define MB_A_PCI_PCIBAR1_ADDR (MB_A_PCI_REG_BASE_ADDR + 0x14)
-#define MB_A_PCI_PCIBAR1 (*(volatile u32 *)MB_A_PCI_PCIBAR1_ADDR)
-#define MB_A_PCI_PCIBAR2_ADDR (MB_A_PCI_REG_BASE_ADDR + 0x18)
-#define MB_A_PCI_PCIBAR2 (*(volatile u32 *)MB_A_PCI_PCIBAR2_ADDR)
-#define MB_A_PCI_VENDOR_ID_ADDR (MB_A_PCI_REG_BASE_ADDR + 0x2C)
-#define MB_A_PCI_VENDOR_ID (*(volatile u16 *)MB_A_PCI_VENDOR_ID_ADDR)
-#define MB_A_PCI_DEVICE_ID_ADDR (MB_A_PCI_REG_BASE_ADDR + 0x2E)
-#define MB_A_PCI_DEVICE_ID (*(volatile u16 *)MB_A_PCI_DEVICE_ID_ADDR)
-#define MB_A_PCI_DMRR_ADDR (MB_A_PCI_REG_BASE_ADDR + 0x9C)
-#define MB_A_PCI_DMRR (*(volatile u32 *)MB_A_PCI_DMRR_ADDR)
-#define MB_A_PCI_DMLBAM_ADDR (MB_A_PCI_REG_BASE_ADDR + 0xA0)
-#define MB_A_PCI_DMLBAM (*(volatile u32 *)MB_A_PCI_DMLBAM_ADDR)
-#define MB_A_PCI_DMLBAI_ADDR (MB_A_PCI_REG_BASE_ADDR + 0xA4)
-#define MB_A_PCI_DMLBAI (*(volatile u32 *)MB_A_PCI_DMLBAI_ADDR)
-#define MB_A_PCI_PCIPBAM_ADDR (MB_A_PCI_REG_BASE_ADDR + 0xA8)
-#define MB_A_PCI_PCIPBAM (*(volatile u32 *)MB_A_PCI_PCIPBAM_ADDR)
-/* `PCI Configuration Address Register for Direct Master to PCI IO/CFG' */
-#define MB_A_PCI_DMCFGA_ADDR (MB_A_PCI_REG_BASE_ADDR + 0xAC)
-#define MB_A_PCI_DMCFGA (*(volatile u32 *)MB_A_PCI_DMCFGA_ADDR)
-/* `PCI Permanent Configuration ID Register' */
-#define MB_A_PCI_PCIHIDR_ADDR (MB_A_PCI_REG_BASE_ADDR + 0xF0)
-#define MB_A_PCI_PCIHIDR (*(volatile u32 *)MB_A_PCI_PCIHIDR_ADDR)
-
-
-#endif /* __V850_MB_A_PCI_H__ */
diff --git a/include/asm-v850/rte_me2_cb.h b/include/asm-v850/rte_me2_cb.h
deleted file mode 100644
index 9922c85c85a..00000000000
--- a/include/asm-v850/rte_me2_cb.h
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * include/asm-v850/rte_me2_cb.h -- Midas labs RTE-V850E/ME2-CB board
- *
- * Copyright (C) 2001,02,03 NEC Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_RTE_ME2_CB_H__
-#define __V850_RTE_ME2_CB_H__
-
-#include <asm/rte_cb.h> /* Common defs for Midas RTE-CB boards. */
-
-
-#define PLATFORM "rte-v850e/me2-cb"
-#define PLATFORM_LONG "Midas lab RTE-V850E/ME2-CB"
-
-#define CPU_CLOCK_FREQ 150000000 /* 150MHz */
-#define FIXED_BOGOMIPS 50
-
-/* 32MB of onbard SDRAM. */
-#define SDRAM_ADDR 0x00800000
-#define SDRAM_SIZE 0x02000000 /* 32MB */
-
-
-/* CPU addresses of GBUS memory spaces. */
-#define GCS0_ADDR 0x04000000 /* GCS0 - Common SRAM (2MB) */
-#define GCS0_SIZE 0x00800000 /* 8MB */
-#define GCS1_ADDR 0x04800000 /* GCS1 - Flash ROM (8MB) */
-#define GCS1_SIZE 0x00800000 /* 8MB */
-#define GCS2_ADDR 0x07000000 /* GCS2 - I/O registers */
-#define GCS2_SIZE 0x00800000 /* 8MB */
-#define GCS5_ADDR 0x08000000 /* GCS5 - PCI bus space */
-#define GCS5_SIZE 0x02000000 /* 32MB */
-#define GCS6_ADDR 0x07800000 /* GCS6 - PCI control registers */
-#define GCS6_SIZE 0x00800000 /* 8MB */
-
-
-/* For <asm/page.h> */
-#define PAGE_OFFSET SDRAM_ADDR
-
-
-#ifdef CONFIG_ROM_KERNEL
-/* Kernel is in ROM, starting at address 0. */
-
-#define INTV_BASE 0
-#define ROOT_FS_IMAGE_RW 0
-
-#else /* !CONFIG_ROM_KERNEL */
-/* Using RAM-kernel. Assume some sort of boot-loader got us loaded at
- address 0. */
-
-#define INTV_BASE 0
-#define ROOT_FS_IMAGE_RW 1
-
-#endif /* CONFIG_ROM_KERNEL */
-
-
-/* Some misc. on-board devices. */
-
-/* Seven-segment LED display (four digits). */
-#define LED_ADDR(n) (0x0FE02000 + (n))
-#define LED(n) (*(volatile unsigned char *)LED_ADDR(n))
-#define LED_NUM_DIGITS 4
-
-
-/* On-board PIC. */
-
-#define CB_PIC_BASE_ADDR 0x0FE04000
-
-#define CB_PIC_INT0M_ADDR (CB_PIC_BASE_ADDR + 0x00)
-#define CB_PIC_INT0M (*(volatile u16 *)CB_PIC_INT0M_ADDR)
-#define CB_PIC_INT1M_ADDR (CB_PIC_BASE_ADDR + 0x10)
-#define CB_PIC_INT1M (*(volatile u16 *)CB_PIC_INT1M_ADDR)
-#define CB_PIC_INTR_ADDR (CB_PIC_BASE_ADDR + 0x20)
-#define CB_PIC_INTR (*(volatile u16 *)CB_PIC_INTR_ADDR)
-#define CB_PIC_INTEN_ADDR (CB_PIC_BASE_ADDR + 0x30)
-#define CB_PIC_INTEN (*(volatile u16 *)CB_PIC_INTEN_ADDR)
-
-#define CB_PIC_INT0EN 0x0001
-#define CB_PIC_INT1EN 0x0002
-#define CB_PIC_INT0SEL 0x0080
-
-/* The PIC interrupts themselves. */
-#define CB_PIC_BASE_IRQ NUM_CPU_IRQS
-#define IRQ_CB_PIC_NUM 10
-
-/* Some specific CB_PIC interrupts. */
-#define IRQ_CB_EXTTM0 (CB_PIC_BASE_IRQ + 0)
-#define IRQ_CB_EXTSIO (CB_PIC_BASE_IRQ + 1)
-#define IRQ_CB_TOVER (CB_PIC_BASE_IRQ + 2)
-#define IRQ_CB_GINT0 (CB_PIC_BASE_IRQ + 3)
-#define IRQ_CB_USB (CB_PIC_BASE_IRQ + 4)
-#define IRQ_CB_LANC (CB_PIC_BASE_IRQ + 5)
-#define IRQ_CB_USB_VBUS_ON (CB_PIC_BASE_IRQ + 6)
-#define IRQ_CB_USB_VBUS_OFF (CB_PIC_BASE_IRQ + 7)
-#define IRQ_CB_EXTTM1 (CB_PIC_BASE_IRQ + 8)
-#define IRQ_CB_EXTTM2 (CB_PIC_BASE_IRQ + 9)
-
-/* The GBUS GINT1 - GINT3 (note, not GINT0!) interrupts are connected to
- the INTP65 - INTP67 pins on the CPU. These are shared among the GBUS
- interrupts. */
-#define IRQ_GINT(n) IRQ_INTP((n) + 9) /* 0 is unused! */
-#define IRQ_GINT_NUM 4 /* 0 is unused! */
-
-/* The shared interrupt line from the PIC is connected to CPU pin INTP23. */
-#define IRQ_CB_PIC IRQ_INTP(4) /* P23 */
-
-/* Used by <asm/rte_cb.h> to derive NUM_MACH_IRQS. */
-#define NUM_RTE_CB_IRQS (NUM_CPU_IRQS + IRQ_CB_PIC_NUM)
-
-
-#ifndef __ASSEMBLY__
-struct cb_pic_irq_init {
- const char *name; /* name of interrupt type */
-
- /* Range of kernel irq numbers for this type:
- BASE, BASE+INTERVAL, ..., BASE+INTERVAL*NUM */
- unsigned base, num, interval;
-
- unsigned priority; /* interrupt priority to assign */
-};
-struct hw_interrupt_type; /* fwd decl */
-
-/* Enable interrupt handling for interrupt IRQ. */
-extern void cb_pic_enable_irq (unsigned irq);
-/* Disable interrupt handling for interrupt IRQ. Note that any interrupts
- received while disabled will be delivered once the interrupt is enabled
- again, unless they are explicitly cleared using `cb_pic_clear_pending_irq'. */
-extern void cb_pic_disable_irq (unsigned irq);
-/* Initialize HW_IRQ_TYPES for PIC irqs described in array INITS (which is
- terminated by an entry with the name field == 0). */
-extern void cb_pic_init_irq_types (struct cb_pic_irq_init *inits,
- struct hw_interrupt_type *hw_irq_types);
-/* Initialize PIC interrupts. */
-extern void cb_pic_init_irqs (void);
-#endif /* __ASSEMBLY__ */
-
-
-/* TL16C550C on board UART see also asm/serial.h */
-#define CB_UART_BASE 0x0FE08000
-#define CB_UART_REG_GAP 0x10
-#define CB_UART_CLOCK 0x16000000
-
-/* CompactFlash setting */
-#define CB_CF_BASE 0x0FE0C000
-#define CB_CF_CCR_ADDR (CB_CF_BASE+0x200)
-#define CB_CF_CCR (*(volatile u8 *)CB_CF_CCR_ADDR)
-#define CB_CF_REG0_ADDR (CB_CF_BASE+0x1000)
-#define CB_CF_REG0 (*(volatile u16 *)CB_CF_REG0_ADDR)
-#define CB_CF_STS0_ADDR (CB_CF_BASE+0x1004)
-#define CB_CF_STS0 (*(volatile u16 *)CB_CF_STS0_ADDR)
-#define CB_PCATA_BASE (CB_CF_BASE+0x800)
-#define CB_IDE_BASE (CB_CF_BASE+0x9F0)
-#define CB_IDE_CTRL (CB_CF_BASE+0xBF6)
-#define CB_IDE_REG_OFFS 0x1
-
-
-/* SMSC LAN91C111 setting */
-#if defined(CONFIG_SMC91111)
-#define CB_LANC_BASE 0x0FE10300
-#define CONFIG_SMC16BITONLY
-#define ETH0_ADDR CB_LANC_BASE
-#define ETH0_IRQ IRQ_CB_LANC
-#endif /* CONFIG_SMC16BITONLY */
-
-
-#undef V850E_UART_PRE_CONFIGURE
-#define V850E_UART_PRE_CONFIGURE rte_me2_cb_uart_pre_configure
-#ifndef __ASSEMBLY__
-extern void rte_me2_cb_uart_pre_configure (unsigned chan,
- unsigned cflags, unsigned baud);
-#endif /* __ASSEMBLY__ */
-
-/* This board supports RTS/CTS for the on-chip UART, but only for channel 0. */
-
-/* CTS for UART channel 0 is pin P22 (bit 2 of port 2). */
-#define V850E_UART_CTS(chan) ((chan) == 0 ? !(ME2_PORT2_IO & 0x4) : 1)
-/* RTS for UART channel 0 is pin P21 (bit 1 of port 2). */
-#define V850E_UART_SET_RTS(chan, val) \
- do { \
- if (chan == 0) { \
- unsigned old = ME2_PORT2_IO; \
- if (val) \
- ME2_PORT2_IO = old & ~0x2; \
- else \
- ME2_PORT2_IO = old | 0x2; \
- } \
- } while (0)
-
-
-#ifndef __ASSEMBLY__
-extern void rte_me2_cb_init_irqs (void);
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_RTE_ME2_CB_H__ */
diff --git a/include/asm-v850/rte_nb85e_cb.h b/include/asm-v850/rte_nb85e_cb.h
deleted file mode 100644
index f56591cad90..00000000000
--- a/include/asm-v850/rte_nb85e_cb.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * include/asm-v850/rte_nb85e_cb.h -- Midas labs RTE-V850/NB85E-CB board
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_RTE_NB85E_CB_H__
-#define __V850_RTE_NB85E_CB_H__
-
-#include <asm/rte_cb.h> /* Common defs for Midas RTE-CB boards. */
-
-
-#define PLATFORM "rte-v850e/nb85e-cb"
-#define PLATFORM_LONG "Midas lab RTE-V850E/NB85E-CB"
-
-#define CPU_CLOCK_FREQ 50000000 /* 50MHz */
-
-/* 1MB of onboard SRAM. Note that the monitor ROM uses parts of this
- for its own purposes, so care must be taken. */
-#define SRAM_ADDR 0x03C00000
-#define SRAM_SIZE 0x00100000 /* 1MB */
-
-/* 16MB of onbard SDRAM. */
-#define SDRAM_ADDR 0x01000000
-#define SDRAM_SIZE 0x01000000 /* 16MB */
-
-
-/* CPU addresses of GBUS memory spaces. */
-#define GCS0_ADDR 0x00400000 /* GCS0 - Common SRAM (2MB) */
-#define GCS0_SIZE 0x00400000 /* 4MB */
-#define GCS1_ADDR 0x02000000 /* GCS1 - Flash ROM (8MB) */
-#define GCS1_SIZE 0x00800000 /* 8MB */
-#define GCS2_ADDR 0x03900000 /* GCS2 - I/O registers */
-#define GCS2_SIZE 0x00080000 /* 512KB */
-#define GCS3_ADDR 0x02800000 /* GCS3 - EXT-bus: memory space */
-#define GCS3_SIZE 0x00800000 /* 8MB */
-#define GCS4_ADDR 0x03A00000 /* GCS4 - EXT-bus: I/O space */
-#define GCS4_SIZE 0x00200000 /* 2MB */
-#define GCS5_ADDR 0x00800000 /* GCS5 - PCI bus space */
-#define GCS5_SIZE 0x00800000 /* 8MB */
-#define GCS6_ADDR 0x03980000 /* GCS6 - PCI control registers */
-#define GCS6_SIZE 0x00010000 /* 64KB */
-
-
-/* The GBUS GINT0 - GINT3 interrupts are connected to CPU interrupts 10-12.
- These are shared among the GBUS interrupts. */
-#define IRQ_GINT(n) (10 + (n))
-#define IRQ_GINT_NUM 3
-
-/* Used by <asm/rte_cb.h> to derive NUM_MACH_IRQS. */
-#define NUM_RTE_CB_IRQS NUM_CPU_IRQS
-
-
-#ifdef CONFIG_ROM_KERNEL
-/* Kernel is in ROM, starting at address 0. */
-
-#define INTV_BASE 0
-
-#else /* !CONFIG_ROM_KERNEL */
-/* We're using the ROM monitor. */
-
-/* The chip's real interrupt vectors are in ROM, but they jump to a
- secondary interrupt vector table in RAM. */
-#define INTV_BASE 0x03CF8000
-
-/* Scratch memory used by the ROM monitor, which shouldn't be used by
- linux (except for the alternate interrupt vector area, defined
- above). */
-#define MON_SCRATCH_ADDR 0x03CE8000
-#define MON_SCRATCH_SIZE 0x00018000 /* 96KB */
-
-#endif /* CONFIG_ROM_KERNEL */
-
-
-/* Some misc. on-board devices. */
-
-/* Seven-segment LED display (two digits). Write-only. */
-#define LED_ADDR(n) (0x03802000 + (n))
-#define LED(n) (*(volatile unsigned char *)LED_ADDR(n))
-#define LED_NUM_DIGITS 4
-
-
-/* Override the basic TEG UART pre-initialization so that we can
- initialize extra stuff. */
-#undef V850E_UART_PRE_CONFIGURE /* should be defined by <asm/teg.h> */
-#define V850E_UART_PRE_CONFIGURE rte_nb85e_cb_uart_pre_configure
-#ifndef __ASSEMBLY__
-extern void rte_nb85e_cb_uart_pre_configure (unsigned chan,
- unsigned cflags, unsigned baud);
-#endif
-
-/* This board supports RTS/CTS for the on-chip UART. */
-
-/* CTS is pin P00. */
-#define V850E_UART_CTS(chan) (! (TEG_PORT0_IO & 0x1))
-/* RTS is pin P02. */
-#define V850E_UART_SET_RTS(chan, val) \
- do { \
- unsigned old = TEG_PORT0_IO; \
- TEG_PORT0_IO = val ? (old & ~0x4) : (old | 0x4); \
- } while (0)
-
-
-#endif /* __V850_RTE_NB85E_CB_H__ */
diff --git a/include/asm-v850/scatterlist.h b/include/asm-v850/scatterlist.h
deleted file mode 100644
index 02d27b3fb06..00000000000
--- a/include/asm-v850/scatterlist.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * include/asm-v850/scatterlist.h
- *
- * Copyright (C) 2001,02 NEC Corporation
- * Copyright (C) 2001,02 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_SCATTERLIST_H__
-#define __V850_SCATTERLIST_H__
-
-#include <asm/types.h>
-
-struct scatterlist {
-#ifdef CONFIG_DEBUG_SG
- unsigned long sg_magic;
-#endif
- unsigned long page_link;
- unsigned offset;
- dma_addr_t dma_address;
- unsigned length;
-};
-
-#define ISA_DMA_THRESHOLD (~0UL)
-
-#endif /* __V850_SCATTERLIST_H__ */
diff --git a/include/asm-v850/sections.h b/include/asm-v850/sections.h
deleted file mode 100644
index e0238253a0d..00000000000
--- a/include/asm-v850/sections.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_SECTIONS_H__
-#define __V850_SECTIONS_H__
-
-#include <asm-generic/sections.h>
-
-#endif /* __V850_SECTIONS_H__ */
diff --git a/include/asm-v850/segment.h b/include/asm-v850/segment.h
deleted file mode 100644
index 5e2b15dcf3d..00000000000
--- a/include/asm-v850/segment.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef __V850_SEGMENT_H__
-#define __V850_SEGMENT_H__
-
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned long mm_segment_t; /* domain register */
-
-#endif /* !__ASSEMBLY__ */
-
-
-#define __KERNEL_CS 0x0
-#define __KERNEL_DS 0x0
-
-#define __USER_CS 0x1
-#define __USER_DS 0x1
-
-#define KERNEL_DS __KERNEL_DS
-#define KERNEL_CS __KERNEL_CS
-#define USER_DS __USER_DS
-#define USER_CS __USER_CS
-
-#define segment_eq(a,b) ((a) == (b))
-
-#define get_ds() (KERNEL_DS)
-#define get_fs() (USER_DS)
-
-#define set_fs(seg) ((void)(seg))
-
-
-#define copy_segments(task, mm) ((void)((void)(task), (mm)))
-#define release_segments(mm) ((void)(mm))
-#define forget_segments() ((void)0)
-
-
-#endif /* __V850_SEGMENT_H__ */
diff --git a/include/asm-v850/semaphore.h b/include/asm-v850/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-v850/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-v850/sembuf.h b/include/asm-v850/sembuf.h
deleted file mode 100644
index 1622231a8b8..00000000000
--- a/include/asm-v850/sembuf.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef __V850_SEMBUF_H__
-#define __V850_SEMBUF_H__
-
-/*
- * The semid64_ds structure for v850 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
- struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
- __kernel_time_t sem_otime; /* last semop time */
- unsigned long __unused1;
- __kernel_time_t sem_ctime; /* last change time */
- unsigned long __unused2;
- unsigned long sem_nsems; /* no. of semaphores in array */
- unsigned long __unused3;
- unsigned long __unused4;
-};
-
-#endif /* __V850_SEMBUF_H__ */
diff --git a/include/asm-v850/serial.h b/include/asm-v850/serial.h
deleted file mode 100644
index 36d8f4cbbf3..00000000000
--- a/include/asm-v850/serial.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) 1999 by Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- */
-
-#ifdef CONFIG_RTE_CB_ME2
-
-#include <asm/rte_me2_cb.h>
-
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-
-#define irq_cannonicalize(x) (x)
-#define BASE_BAUD 250000 /* (16MHz / (16 * 38400)) * 9600 */
-#define SERIAL_PORT_DFNS \
- { 0, BASE_BAUD, CB_UART_BASE, IRQ_CB_EXTSIO, STD_COM_FLAGS },
-
-/* Redefine UART register offsets. */
-#undef UART_RX
-#undef UART_TX
-#undef UART_DLL
-#undef UART_TRG
-#undef UART_DLM
-#undef UART_IER
-#undef UART_FCTR
-#undef UART_IIR
-#undef UART_FCR
-#undef UART_EFR
-#undef UART_LCR
-#undef UART_MCR
-#undef UART_LSR
-#undef UART_MSR
-#undef UART_SCR
-#undef UART_EMSR
-
-#define UART_RX (0 * CB_UART_REG_GAP)
-#define UART_TX (0 * CB_UART_REG_GAP)
-#define UART_DLL (0 * CB_UART_REG_GAP)
-#define UART_TRG (0 * CB_UART_REG_GAP)
-#define UART_DLM (1 * CB_UART_REG_GAP)
-#define UART_IER (1 * CB_UART_REG_GAP)
-#define UART_FCTR (1 * CB_UART_REG_GAP)
-#define UART_IIR (2 * CB_UART_REG_GAP)
-#define UART_FCR (2 * CB_UART_REG_GAP)
-#define UART_EFR (2 * CB_UART_REG_GAP)
-#define UART_LCR (3 * CB_UART_REG_GAP)
-#define UART_MCR (4 * CB_UART_REG_GAP)
-#define UART_LSR (5 * CB_UART_REG_GAP)
-#define UART_MSR (6 * CB_UART_REG_GAP)
-#define UART_SCR (7 * CB_UART_REG_GAP)
-#define UART_EMSR (7 * CB_UART_REG_GAP)
-
-#endif /* CONFIG_RTE_CB_ME2 */
diff --git a/include/asm-v850/setup.h b/include/asm-v850/setup.h
deleted file mode 100644
index c48a9b97d05..00000000000
--- a/include/asm-v850/setup.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _V850_SETUP_H
-#define _V850_SETUP_H
-
-#define COMMAND_LINE_SIZE 512
-
-#endif /* __SETUP_H */
diff --git a/include/asm-v850/shmbuf.h b/include/asm-v850/shmbuf.h
deleted file mode 100644
index 3d085c9c418..00000000000
--- a/include/asm-v850/shmbuf.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef __V850_SHMBUF_H__
-#define __V850_SHMBUF_H__
-
-/*
- * The shmid64_ds structure for v850 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct shmid64_ds {
- struct ipc64_perm shm_perm; /* operation perms */
- size_t shm_segsz; /* size of segment (bytes) */
- __kernel_time_t shm_atime; /* last attach time */
- unsigned long __unused1;
- __kernel_time_t shm_dtime; /* last detach time */
- unsigned long __unused2;
- __kernel_time_t shm_ctime; /* last change time */
- unsigned long __unused3;
- __kernel_pid_t shm_cpid; /* pid of creator */
- __kernel_pid_t shm_lpid; /* pid of last operator */
- unsigned long shm_nattch; /* no. of current attaches */
- unsigned long __unused4;
- unsigned long __unused5;
-};
-
-struct shminfo64 {
- unsigned long shmmax;
- unsigned long shmmin;
- unsigned long shmmni;
- unsigned long shmseg;
- unsigned long shmall;
- unsigned long __unused1;
- unsigned long __unused2;
- unsigned long __unused3;
- unsigned long __unused4;
-};
-
-#endif /* __V850_SHMBUF_H__ */
diff --git a/include/asm-v850/shmparam.h b/include/asm-v850/shmparam.h
deleted file mode 100644
index 7dcb6739073..00000000000
--- a/include/asm-v850/shmparam.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_SHMPARAM_H__
-#define __V850_SHMPARAM_H__
-
-#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
-
-#endif /* __V850_SHMPARAM_H__ */
diff --git a/include/asm-v850/sigcontext.h b/include/asm-v850/sigcontext.h
deleted file mode 100644
index e0890f6f4bc..00000000000
--- a/include/asm-v850/sigcontext.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * include/asm-v850/sigcontext.h -- Signal contexts
- *
- * Copyright (C) 2001 NEC Corporation
- * Copyright (C) 2001 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_SIGCONTEXT_H__
-#define __V850_SIGCONTEXT_H__
-
-#include <asm/ptrace.h>
-
-struct sigcontext
-{
- struct pt_regs regs;
- unsigned long oldmask;
-};
-
-#endif /* __V850_SIGCONTEXT_H__ */
diff --git a/include/asm-v850/siginfo.h b/include/asm-v850/siginfo.h
deleted file mode 100644
index 7eb94703dce..00000000000
--- a/include/asm-v850/siginfo.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_SIGINFO_H__
-#define __V850_SIGINFO_H__
-
-#include <asm-generic/siginfo.h>
-
-#endif /* __V850_SIGINFO_H__ */
diff --git a/include/asm-v850/signal.h b/include/asm-v850/signal.h
deleted file mode 100644
index a38df0834bb..00000000000
--- a/include/asm-v850/signal.h
+++ /dev/null
@@ -1,168 +0,0 @@
-#ifndef __V850_SIGNAL_H__
-#define __V850_SIGNAL_H__
-
-#include <linux/types.h>
-
-/* Avoid too many header ordering problems. */
-struct siginfo;
-
-
-#ifdef __KERNEL__
-
-/* Most things should be clean enough to redefine this at will, if care
- is taken to make libc match. */
-#define _NSIG 64
-#define _NSIG_BPW 32
-#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
-
-typedef unsigned long old_sigset_t; /* at least 32 bits */
-
-typedef struct {
- unsigned long sig[_NSIG_WORDS];
-} sigset_t;
-
-#else /* !__KERNEL__ */
-
-/* Here we must cater to libcs that poke about in kernel headers. */
-
-#define NSIG 32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
-
-
-#define SIGHUP 1
-#define SIGINT 2
-#define SIGQUIT 3
-#define SIGILL 4
-#define SIGTRAP 5
-#define SIGABRT 6
-#define SIGIOT 6
-#define SIGBUS 7
-#define SIGFPE 8
-#define SIGKILL 9
-#define SIGUSR1 10
-#define SIGSEGV 11
-#define SIGUSR2 12
-#define SIGPIPE 13
-#define SIGALRM 14
-#define SIGTERM 15
-#define SIGSTKFLT 16
-#define SIGCHLD 17
-#define SIGCONT 18
-#define SIGSTOP 19
-#define SIGTSTP 20
-#define SIGTTIN 21
-#define SIGTTOU 22
-#define SIGURG 23
-#define SIGXCPU 24
-#define SIGXFSZ 25
-#define SIGVTALRM 26
-#define SIGPROF 27
-#define SIGWINCH 28
-#define SIGIO 29
-#define SIGPOLL SIGIO
-/*
-#define SIGLOST 29
-*/
-#define SIGPWR 30
-#define SIGSYS 31
-#define SIGUNUSED 31
-
-/* These should not be considered constants from userland. */
-#define SIGRTMIN 32
-#define SIGRTMAX _NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP 0x00000001
-#define SA_NOCLDWAIT 0x00000002
-#define SA_SIGINFO 0x00000004
-#define SA_ONSTACK 0x08000000
-#define SA_RESTART 0x10000000
-#define SA_NODEFER 0x40000000
-#define SA_RESETHAND 0x80000000
-
-#define SA_NOMASK SA_NODEFER
-#define SA_ONESHOT SA_RESETHAND
-
-#define SA_RESTORER 0x04000000
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK 1
-#define SS_DISABLE 2
-
-#define MINSIGSTKSZ 2048
-#define SIGSTKSZ 8192
-
-#include <asm-generic/signal.h>
-
-#ifdef __KERNEL__
-
-struct old_sigaction {
- __sighandler_t sa_handler;
- old_sigset_t sa_mask;
- unsigned long sa_flags;
- void (*sa_restorer)(void);
-};
-
-struct sigaction {
- __sighandler_t sa_handler;
- unsigned long sa_flags;
- void (*sa_restorer)(void);
- sigset_t sa_mask; /* mask last for extensibility */
-};
-
-struct k_sigaction {
- struct sigaction sa;
-};
-
-#else /* !__KERNEL__ */
-
-/* Here we must cater to libcs that poke about in kernel headers. */
-
-struct sigaction {
- union {
- __sighandler_t _sa_handler;
- void (*_sa_sigaction)(int, struct siginfo *, void *);
- } _u;
- sigset_t sa_mask;
- unsigned long sa_flags;
- void (*sa_restorer)(void);
-};
-
-#define sa_handler _u._sa_handler
-#define sa_sigaction _u._sa_sigaction
-
-#endif /* __KERNEL__ */
-
-
-typedef struct sigaltstack {
- void *ss_sp;
- int ss_flags;
- size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
-
-#include <asm/sigcontext.h>
-#undef __HAVE_ARCH_SIG_BITOPS
-
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
-#endif /* __KERNEL__ */
-
-#endif /* __V850_SIGNAL_H__ */
diff --git a/include/asm-v850/sim.h b/include/asm-v850/sim.h
deleted file mode 100644
index 026932d476c..00000000000
--- a/include/asm-v850/sim.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * include/asm-v850/sim.h -- Machine-dependent defs for GDB v850e simulator
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_SIM_H__
-#define __V850_SIM_H__
-
-
-#define CPU_ARCH "v850e"
-#define CPU_MODEL "v850e"
-#define CPU_MODEL_LONG "NEC V850E"
-#define PLATFORM "gdb/v850e"
-#define PLATFORM_LONG "GDB V850E simulator"
-
-
-/* We use a weird value for RAM, not just 0, for testing purposes.
- These must match the values used in the linker script. */
-#define RAM_ADDR 0x8F000000
-#define RAM_SIZE 0x03000000
-
-
-/* For <asm/page.h> */
-#define PAGE_OFFSET RAM_ADDR
-
-
-/* For <asm/entry.h> */
-/* `R0 RAM', used for a few miscellaneous variables that must be
- accessible using a load instruction relative to R0. On real
- processors, this usually is on-chip RAM, but here we just
- choose an arbitrary address that meets the above constraint. */
-#define R0_RAM_ADDR 0xFFFFF000
-
-
-/* For <asm/irq.h> */
-#define NUM_CPU_IRQS 6
-
-
-#endif /* __V850_SIM_H__ */
diff --git a/include/asm-v850/sim85e2.h b/include/asm-v850/sim85e2.h
deleted file mode 100644
index 8b4d6974066..00000000000
--- a/include/asm-v850/sim85e2.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * include/asm-v850/sim85e2.h -- Machine-dependent defs for
- * V850E2 RTL simulator
- *
- * Copyright (C) 2002,03 NEC Electronics Corporation
- * Copyright (C) 2002,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_SIM85E2_H__
-#define __V850_SIM85E2_H__
-
-
-#include <asm/v850e2.h> /* Based on V850E2 core. */
-
-
-/* Various memory areas supported by the simulator.
- These should match the corresponding definitions in the linker script. */
-
-/* `instruction RAM'; instruction fetches are much faster from IRAM than
- from DRAM. */
-#define IRAM_ADDR 0
-#define IRAM_SIZE 0x00100000 /* 1MB */
-/* `data RAM', below and contiguous with the I/O space.
- Data fetches are much faster from DRAM than from IRAM. */
-#define DRAM_ADDR 0xfff00000
-#define DRAM_SIZE 0x000ff000 /* 1020KB */
-/* `external ram'. Unlike the above RAM areas, this memory is cached,
- so both instruction and data fetches should be (mostly) fast --
- however, currently only write-through caching is supported, so writes
- to ERAM will be slow. */
-#define ERAM_ADDR 0x00100000
-#define ERAM_SIZE 0x07f00000 /* 127MB (max) */
-/* Dynamic RAM; uses memory controller. */
-#define SDRAM_ADDR 0x10000000
-#define SDRAM_SIZE 0x01000000 /* 16MB */
-
-
-/* Simulator specific control registers. */
-/* NOTHAL controls whether the simulator will stop at a `halt' insn. */
-#define SIM85E2_NOTHAL_ADDR 0xffffff22
-#define SIM85E2_NOTHAL (*(volatile u8 *)SIM85E2_NOTHAL_ADDR)
-/* The simulator will stop N cycles after N is written to SIMFIN. */
-#define SIM85E2_SIMFIN_ADDR 0xffffff24
-#define SIM85E2_SIMFIN (*(volatile u16 *)SIM85E2_SIMFIN_ADDR)
-
-
-/* For <asm/irq.h> */
-#define NUM_CPU_IRQS 64
-
-
-/* For <asm/page.h> */
-#define PAGE_OFFSET SDRAM_ADDR
-
-
-/* For <asm/entry.h> */
-/* `R0 RAM', used for a few miscellaneous variables that must be accessible
- using a load instruction relative to R0. The sim85e2 simulator
- actually puts 1020K of RAM from FFF00000 to FFFFF000, so we arbitarily
- choose a small portion at the end of that. */
-#define R0_RAM_ADDR 0xFFFFE000
-
-
-#endif /* __V850_SIM85E2_H__ */
diff --git a/include/asm-v850/sim85e2c.h b/include/asm-v850/sim85e2c.h
deleted file mode 100644
index eee543ff3af..00000000000
--- a/include/asm-v850/sim85e2c.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * include/asm-v850/sim85e2c.h -- Machine-dependent defs for
- * V850E2 RTL simulator
- *
- * Copyright (C) 2002 NEC Corporation
- * Copyright (C) 2002 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_SIM85E2C_H__
-#define __V850_SIM85E2C_H__
-
-/* Use generic sim85e2 settings, other than the various names. */
-#include <asm/sim85e2.h>
-
-#define CPU_MODEL "v850e2"
-#define CPU_MODEL_LONG "NEC V850E2"
-#define PLATFORM "sim85e2c"
-#define PLATFORM_LONG "SIM85E2C V850E2 simulator"
-
-#endif /* __V850_SIM85E2C_H__ */
diff --git a/include/asm-v850/sim85e2s.h b/include/asm-v850/sim85e2s.h
deleted file mode 100644
index ee066d5d3c5..00000000000
--- a/include/asm-v850/sim85e2s.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * include/asm-v850/sim85e2s.h -- Machine-dependent defs for
- * V850E2 RTL simulator
- *
- * Copyright (C) 2003 NEC Electronics Corporation
- * Copyright (C) 2003 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_SIM85E2S_H__
-#define __V850_SIM85E2S_H__
-
-#include <asm/sim85e2.h> /* Use generic sim85e2 settings. */
-#if 0
-#include <asm/v850e2_cache.h> /* + cache */
-#endif
-
-#define CPU_MODEL "v850e2"
-#define CPU_MODEL_LONG "NEC V850E2"
-#define PLATFORM "sim85e2s"
-#define PLATFORM_LONG "SIM85E2S V850E2 simulator"
-
-#endif /* __V850_SIM85E2S_H__ */
diff --git a/include/asm-v850/simsyscall.h b/include/asm-v850/simsyscall.h
deleted file mode 100644
index 4a19d5ae9d1..00000000000
--- a/include/asm-v850/simsyscall.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * include/asm-v850/simsyscall.h -- `System calls' under the v850e emulator
- *
- * Copyright (C) 2001 NEC Corporation
- * Copyright (C) 2001 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_SIMSYSCALL_H__
-#define __V850_SIMSYSCALL_H__
-
-#define V850_SIM_SYS_exit(a...) V850_SIM_SYSCALL_1 (1 , ##a)
-#define V850_SIM_SYS_fork(a...) V850_SIM_SYSCALL_0 (2 , ##a)
-#define V850_SIM_SYS_read(a...) V850_SIM_SYSCALL_3 (3 , ##a)
-#define V850_SIM_SYS_write(a...) V850_SIM_SYSCALL_3 (4 , ##a)
-#define V850_SIM_SYS_open(a...) V850_SIM_SYSCALL_2 (5 , ##a)
-#define V850_SIM_SYS_close(a...) V850_SIM_SYSCALL_1 (6 , ##a)
-#define V850_SIM_SYS_wait4(a...) V850_SIM_SYSCALL_4 (7 , ##a)
-/* #define V850_SIM_SYS_creat(a...) V850_SIM_SYSCALL_1 (8 , ##a) */
-/* #define V850_SIM_SYS_link(a...) V850_SIM_SYSCALL_1 (9 , ##a) */
-/* #define V850_SIM_SYS_unlink(a...) V850_SIM_SYSCALL_1 (10 , ##a) */
-#define V850_SIM_SYS_execv(a...) V850_SIM_SYSCALL_2 (11 , ##a)
-/* #define V850_SIM_SYS_chdir(a...) V850_SIM_SYSCALL_1 (12 , ##a) */
-/* #define V850_SIM_SYS_mknod(a...) V850_SIM_SYSCALL_1 (14 , ##a) */
-#define V850_SIM_SYS_chmod(a...) V850_SIM_SYSCALL_2 (15 , ##a)
-#define V850_SIM_SYS_chown(a...) V850_SIM_SYSCALL_2 (16 , ##a)
-#define V850_SIM_SYS_lseek(a...) V850_SIM_SYSCALL_3 (19 , ##a)
-/* #define V850_SIM_SYS_getpid(a...) V850_SIM_SYSCALL_1 (20 , ##a) */
-/* #define V850_SIM_SYS_isatty(a...) V850_SIM_SYSCALL_1 (21 , ##a) */
-/* #define V850_SIM_SYS_fstat(a...) V850_SIM_SYSCALL_1 (22 , ##a) */
-#define V850_SIM_SYS_time(a...) V850_SIM_SYSCALL_1 (23 , ##a)
-#define V850_SIM_SYS_poll(a...) V850_SIM_SYSCALL_3 (24 , ##a)
-#define V850_SIM_SYS_stat(a...) V850_SIM_SYSCALL_2 (38 , ##a)
-#define V850_SIM_SYS_pipe(a...) V850_SIM_SYSCALL_1 (42 , ##a)
-#define V850_SIM_SYS_times(a...) V850_SIM_SYSCALL_1 (43 , ##a)
-#define V850_SIM_SYS_execve(a...) V850_SIM_SYSCALL_3 (59 , ##a)
-#define V850_SIM_SYS_gettimeofday(a...) V850_SIM_SYSCALL_2 (116 , ##a)
-/* #define V850_SIM_SYS_utime(a...) V850_SIM_SYSCALL_2 (201 , ##a) */
-/* #define V850_SIM_SYS_wait(a...) V850_SIM_SYSCALL_1 (202 , ##a) */
-
-#define V850_SIM_SYS_make_raw(a...) V850_SIM_SYSCALL_1 (1024 , ##a)
-
-
-#define V850_SIM_SYSCALL_0(_call) \
-({ \
- register int call __asm__ ("r6") = _call; \
- register int rval __asm__ ("r10"); \
- __asm__ __volatile__ ("trap 31" \
- : "=r" (rval) \
- : "r" (call) \
- : "r11", "memory"); \
- rval; \
-})
-#define V850_SIM_SYSCALL_1(_call, _arg0) \
-({ \
- register int call __asm__ ("r6") = _call; \
- register long arg0 __asm__ ("r7") = (long)_arg0; \
- register int rval __asm__ ("r10"); \
- __asm__ __volatile__ ("trap 31" \
- : "=r" (rval) \
- : "r" (call), "r" (arg0) \
- : "r11", "memory"); \
- rval; \
-})
-#define V850_SIM_SYSCALL_2(_call, _arg0, _arg1) \
-({ \
- register int call __asm__ ("r6") = _call; \
- register long arg0 __asm__ ("r7") = (long)_arg0; \
- register long arg1 __asm__ ("r8") = (long)_arg1; \
- register int rval __asm__ ("r10"); \
- __asm__ __volatile__ ("trap 31" \
- : "=r" (rval) \
- : "r" (call), "r" (arg0), "r" (arg1) \
- : "r11", "memory"); \
- rval; \
-})
-#define V850_SIM_SYSCALL_3(_call, _arg0, _arg1, _arg2) \
-({ \
- register int call __asm__ ("r6") = _call; \
- register long arg0 __asm__ ("r7") = (long)_arg0; \
- register long arg1 __asm__ ("r8") = (long)_arg1; \
- register long arg2 __asm__ ("r9") = (long)_arg2; \
- register int rval __asm__ ("r10"); \
- __asm__ __volatile__ ("trap 31" \
- : "=r" (rval) \
- : "r" (call), "r" (arg0), "r" (arg1), "r" (arg2)\
- : "r11", "memory"); \
- rval; \
-})
-
-#define V850_SIM_SYSCALL(call, args...) \
- V850_SIM_SYS_##call (args)
-
-#endif /* __V850_SIMSYSCALL_H__ */
diff --git a/include/asm-v850/socket.h b/include/asm-v850/socket.h
deleted file mode 100644
index e199a2bf12a..00000000000
--- a/include/asm-v850/socket.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef __V850_SOCKET_H__
-#define __V850_SOCKET_H__
-
-#include <asm/sockios.h>
-
-/* For setsockoptions(2) */
-#define SOL_SOCKET 1
-
-#define SO_DEBUG 1
-#define SO_REUSEADDR 2
-#define SO_TYPE 3
-#define SO_ERROR 4
-#define SO_DONTROUTE 5
-#define SO_BROADCAST 6
-#define SO_SNDBUF 7
-#define SO_RCVBUF 8
-#define SO_SNDBUFFORCE 32
-#define SO_RCVBUFFORCE 33
-#define SO_KEEPALIVE 9
-#define SO_OOBINLINE 10
-#define SO_NO_CHECK 11
-#define SO_PRIORITY 12
-#define SO_LINGER 13
-#define SO_BSDCOMPAT 14
-/* To add :#define SO_REUSEPORT 15 */
-#define SO_PASSCRED 16
-#define SO_PEERCRED 17
-#define SO_RCVLOWAT 18
-#define SO_SNDLOWAT 19
-#define SO_RCVTIMEO 20
-#define SO_SNDTIMEO 21
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-#define SO_SECURITY_AUTHENTICATION 22
-#define SO_SECURITY_ENCRYPTION_TRANSPORT 23
-#define SO_SECURITY_ENCRYPTION_NETWORK 24
-
-#define SO_BINDTODEVICE 25
-
-/* Socket filtering */
-#define SO_ATTACH_FILTER 26
-#define SO_DETACH_FILTER 27
-
-#define SO_PEERNAME 28
-#define SO_TIMESTAMP 29
-#define SCM_TIMESTAMP SO_TIMESTAMP
-
-#define SO_ACCEPTCONN 30
-
-#define SO_PEERSEC 31
-#define SO_PASSSEC 34
-#define SO_TIMESTAMPNS 35
-#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
-
-#define SO_MARK 36
-
-#endif /* __V850_SOCKET_H__ */
diff --git a/include/asm-v850/sockios.h b/include/asm-v850/sockios.h
deleted file mode 100644
index 823e106e6cd..00000000000
--- a/include/asm-v850/sockios.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __V850_SOCKIOS_H__
-#define __V850_SOCKIOS_H__
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN 0x8901
-#define SIOCSPGRP 0x8902
-#define FIOGETOWN 0x8903
-#define SIOCGPGRP 0x8904
-#define SIOCATMARK 0x8905
-#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
-#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
-
-#endif /* __V850_SOCKIOS_H__ */
diff --git a/include/asm-v850/stat.h b/include/asm-v850/stat.h
deleted file mode 100644
index c68c60d06e2..00000000000
--- a/include/asm-v850/stat.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * include/asm-v850/stat.h -- v850 stat structure
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_STAT_H__
-#define __V850_STAT_H__
-
-#include <asm/posix_types.h>
-
-struct stat {
- unsigned int st_dev;
- unsigned long st_ino;
- unsigned int st_mode;
- unsigned int st_nlink;
- unsigned int st_uid;
- unsigned int st_gid;
- unsigned int st_rdev;
- long st_size;
- unsigned long st_blksize;
- unsigned long st_blocks;
- unsigned long st_atime;
- unsigned long __unused1;
- unsigned long st_mtime;
- unsigned long __unused2;
- unsigned long st_ctime;
- unsigned long __unused3;
- unsigned long __unused4;
- unsigned long __unused5;
-};
-
-struct stat64 {
- unsigned long long st_dev;
- unsigned long __unused1;
-
- unsigned long long st_ino;
-
- unsigned int st_mode;
- unsigned int st_nlink;
-
- unsigned int st_uid;
- unsigned int st_gid;
-
- unsigned long long st_rdev;
- unsigned long __unused3;
-
- long long st_size;
- unsigned long st_blksize;
-
- unsigned long st_blocks; /* No. of 512-byte blocks allocated */
- unsigned long __unused4; /* future possible st_blocks high bits */
-
- unsigned long st_atime;
- unsigned long st_atime_nsec;
-
- unsigned long st_mtime;
- unsigned long st_mtime_nsec;
-
- unsigned long st_ctime;
- unsigned long st_ctime_nsec;
-
- unsigned long __unused8;
-};
-
-#endif /* __V850_STAT_H__ */
diff --git a/include/asm-v850/statfs.h b/include/asm-v850/statfs.h
deleted file mode 100644
index ea1596607f2..00000000000
--- a/include/asm-v850/statfs.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_STATFS_H__
-#define __V850_STATFS_H__
-
-#include <asm-generic/statfs.h>
-
-#endif /* __V850_STATFS_H__ */
diff --git a/include/asm-v850/string.h b/include/asm-v850/string.h
deleted file mode 100644
index 478e234789d..00000000000
--- a/include/asm-v850/string.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * include/asm-v850/string.h -- Architecture specific string routines
- *
- * Copyright (C) 2001,02 NEC Corporation
- * Copyright (C) 2001,02 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_STRING_H__
-#define __V850_STRING_H__
-
-#define __HAVE_ARCH_MEMCPY
-#define __HAVE_ARCH_MEMSET
-#define __HAVE_ARCH_MEMMOVE
-
-extern void *memcpy (void *, const void *, __kernel_size_t);
-extern void *memset (void *, int, __kernel_size_t);
-extern void *memmove (void *, const void *, __kernel_size_t);
-
-#endif /* __V850_STRING_H__ */
diff --git a/include/asm-v850/system.h b/include/asm-v850/system.h
deleted file mode 100644
index 7daf1fdee11..00000000000
--- a/include/asm-v850/system.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * include/asm-v850/system.h -- Low-level interrupt/thread ops
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_SYSTEM_H__
-#define __V850_SYSTEM_H__
-
-#include <linux/linkage.h>
-#include <asm/ptrace.h>
-
-
-/*
- * switch_to(n) should switch tasks to task ptr, first checking that
- * ptr isn't the current task, in which case it does nothing.
- */
-struct thread_struct;
-extern void *switch_thread (struct thread_struct *last,
- struct thread_struct *next);
-#define switch_to(prev,next,last) \
- do { \
- if (prev != next) { \
- (last) = switch_thread (&prev->thread, &next->thread); \
- } \
- } while (0)
-
-
-/* Enable/disable interrupts. */
-#define local_irq_enable() __asm__ __volatile__ ("ei")
-#define local_irq_disable() __asm__ __volatile__ ("di")
-
-#define local_save_flags(flags) \
- __asm__ __volatile__ ("stsr %1, %0" : "=r" (flags) : "i" (SR_PSW))
-#define local_restore_flags(flags) \
- __asm__ __volatile__ ("ldsr %0, %1" :: "r" (flags), "i" (SR_PSW))
-
-/* For spinlocks etc */
-#define local_irq_save(flags) \
- do { local_save_flags (flags); local_irq_disable (); } while (0)
-#define local_irq_restore(flags) \
- local_restore_flags (flags);
-
-
-static inline int irqs_disabled (void)
-{
- unsigned flags;
- local_save_flags (flags);
- return !!(flags & 0x20);
-}
-
-
-/*
- * Force strict CPU ordering.
- * Not really required on v850...
- */
-#define nop() __asm__ __volatile__ ("nop")
-#define mb() __asm__ __volatile__ ("" ::: "memory")
-#define rmb() mb ()
-#define wmb() mb ()
-#define read_barrier_depends() ((void)0)
-#define set_mb(var, value) do { xchg (&var, value); } while (0)
-
-#define smp_mb() mb ()
-#define smp_rmb() rmb ()
-#define smp_wmb() wmb ()
-#define smp_read_barrier_depends() read_barrier_depends()
-
-#define xchg(ptr, with) \
- ((__typeof__ (*(ptr)))__xchg ((unsigned long)(with), (ptr), sizeof (*(ptr))))
-
-static inline unsigned long __xchg (unsigned long with,
- __volatile__ void *ptr, int size)
-{
- unsigned long tmp, flags;
-
- local_irq_save (flags);
-
- switch (size) {
- case 1:
- tmp = *(unsigned char *)ptr;
- *(unsigned char *)ptr = with;
- break;
- case 2:
- tmp = *(unsigned short *)ptr;
- *(unsigned short *)ptr = with;
- break;
- case 4:
- tmp = *(unsigned long *)ptr;
- *(unsigned long *)ptr = with;
- break;
- }
-
- local_irq_restore (flags);
-
- return tmp;
-}
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n) \
- ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
- (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#ifndef CONFIG_SMP
-#include <asm-generic/cmpxchg.h>
-#endif
-
-#define arch_align_stack(x) (x)
-
-#endif /* __V850_SYSTEM_H__ */
diff --git a/include/asm-v850/teg.h b/include/asm-v850/teg.h
deleted file mode 100644
index acc8c7d9532..00000000000
--- a/include/asm-v850/teg.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * include/asm-v850/teg.h -- NB85E-TEG cpu chip
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_TEG_H__
-#define __V850_TEG_H__
-
-
-/* The TEG uses the V850E cpu core. */
-#include <asm/v850e.h>
-#include <asm/v850e_cache.h>
-
-
-#define CPU_MODEL "v850e/nb85e-teg"
-#define CPU_MODEL_LONG "NEC V850E/NB85E TEG"
-
-
-/* For <asm/entry.h> */
-/* We use on-chip RAM, for a few miscellaneous variables that must be
- accessible using a load instruction relative to R0. On the NB85E/TEG,
- There's 60KB of iRAM starting at 0xFFFF0000, however we need the base
- address to be addressable by a 16-bit signed offset, so we only use the
- second half of it starting from 0xFFFF8000. */
-#define R0_RAM_ADDR 0xFFFF8000
-
-
-/* Hardware-specific interrupt numbers (in the kernel IRQ namespace).
- Some of these are parameterized even though there's only a single
- interrupt, for compatibility with some generic code that works on other
- processor models. */
-#define IRQ_INTCMD(n) 6 /* interval timer interrupt */
-#define IRQ_INTCMD_NUM 1
-#define IRQ_INTSER(n) 16 /* UART reception error */
-#define IRQ_INTSER_NUM 1
-#define IRQ_INTSR(n) 17 /* UART reception completion */
-#define IRQ_INTSR_NUM 1
-#define IRQ_INTST(n) 18 /* UART transmission completion */
-#define IRQ_INTST_NUM 1
-
-/* For <asm/irq.h> */
-#define NUM_CPU_IRQS 64
-
-
-/* TEG UART details. */
-#define V850E_UART_BASE_ADDR(n) (0xFFFFF600 + 0x10 * (n))
-#define V850E_UART_ASIM_ADDR(n) (V850E_UART_BASE_ADDR(n) + 0x0)
-#define V850E_UART_ASIS_ADDR(n) (V850E_UART_BASE_ADDR(n) + 0x2)
-#define V850E_UART_ASIF_ADDR(n) (V850E_UART_BASE_ADDR(n) + 0x4)
-#define V850E_UART_CKSR_ADDR(n) (V850E_UART_BASE_ADDR(n) + 0x6)
-#define V850E_UART_BRGC_ADDR(n) (V850E_UART_BASE_ADDR(n) + 0x8)
-#define V850E_UART_TXB_ADDR(n) (V850E_UART_BASE_ADDR(n) + 0xA)
-#define V850E_UART_RXB_ADDR(n) (V850E_UART_BASE_ADDR(n) + 0xC)
-#define V850E_UART_NUM_CHANNELS 1
-#define V850E_UART_BASE_FREQ CPU_CLOCK_FREQ
-/* This is a function that gets called before configuring the UART. */
-#define V850E_UART_PRE_CONFIGURE teg_uart_pre_configure
-#ifndef __ASSEMBLY__
-extern void teg_uart_pre_configure (unsigned chan,
- unsigned cflags, unsigned baud);
-#endif
-
-
-/* The TEG RTPU. */
-#define V850E_RTPU_BASE_ADDR 0xFFFFF210
-
-
-/* TEG series timer D details. */
-#define V850E_TIMER_D_BASE_ADDR 0xFFFFF210
-#define V850E_TIMER_D_TMCD_BASE_ADDR (V850E_TIMER_D_BASE_ADDR + 0x0)
-#define V850E_TIMER_D_TMD_BASE_ADDR (V850E_TIMER_D_BASE_ADDR + 0x4)
-#define V850E_TIMER_D_CMD_BASE_ADDR (V850E_TIMER_D_BASE_ADDR + 0x8)
-#define V850E_TIMER_D_BASE_FREQ CPU_CLOCK_FREQ
-
-
-/* `Interrupt Source Select' control register. */
-#define TEG_ISS_ADDR 0xFFFFF7FA
-#define TEG_ISS (*(volatile u8 *)TEG_ISS_ADDR)
-
-/* Port 0 I/O register (bits 0-3 used). */
-#define TEG_PORT0_IO_ADDR 0xFFFFF7F2
-#define TEG_PORT0_IO (*(volatile u8 *)TEG_PORT0_IO_ADDR)
-/* Port 0 control register (bits 0-3 control mode, 0 = output, 1 = input). */
-#define TEG_PORT0_PM_ADDR 0xFFFFF7F4
-#define TEG_PORT0_PM (*(volatile u8 *)TEG_PORT0_PM_ADDR)
-
-
-#ifndef __ASSEMBLY__
-extern void teg_init_irqs (void);
-#endif
-
-
-#endif /* __V850_TEG_H__ */
diff --git a/include/asm-v850/termbits.h b/include/asm-v850/termbits.h
deleted file mode 100644
index 295d7bf6945..00000000000
--- a/include/asm-v850/termbits.h
+++ /dev/null
@@ -1,200 +0,0 @@
-#ifndef __V850_TERMBITS_H__
-#define __V850_TERMBITS_H__
-
-#include <linux/posix_types.h>
-
-typedef unsigned char cc_t;
-typedef unsigned int speed_t;
-typedef unsigned int tcflag_t;
-
-#define NCCS 19
-struct termios {
- tcflag_t c_iflag; /* input mode flags */
- tcflag_t c_oflag; /* output mode flags */
- tcflag_t c_cflag; /* control mode flags */
- tcflag_t c_lflag; /* local mode flags */
- cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
-};
-
-struct termios2 {
- tcflag_t c_iflag; /* input mode flags */
- tcflag_t c_oflag; /* output mode flags */
- tcflag_t c_cflag; /* control mode flags */
- tcflag_t c_lflag; /* local mode flags */
- cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
- speed_t c_ispeed; /* input speed */
- speed_t c_ospeed; /* output speed */
-};
-
-struct ktermios {
- tcflag_t c_iflag; /* input mode flags */
- tcflag_t c_oflag; /* output mode flags */
- tcflag_t c_cflag; /* control mode flags */
- tcflag_t c_lflag; /* local mode flags */
- cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
- speed_t c_ispeed; /* input speed */
- speed_t c_ospeed; /* output speed */
-};
-
-/* c_cc characters */
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-
-/* c_iflag bits */
-#define IGNBRK 0000001
-#define BRKINT 0000002
-#define IGNPAR 0000004
-#define PARMRK 0000010
-#define INPCK 0000020
-#define ISTRIP 0000040
-#define INLCR 0000100
-#define IGNCR 0000200
-#define ICRNL 0000400
-#define IUCLC 0001000
-#define IXON 0002000
-#define IXANY 0004000
-#define IXOFF 0010000
-#define IMAXBEL 0020000
-#define IUTF8 0040000
-
-/* c_oflag bits */
-#define OPOST 0000001
-#define OLCUC 0000002
-#define ONLCR 0000004
-#define OCRNL 0000010
-#define ONOCR 0000020
-#define ONLRET 0000040
-#define OFILL 0000100
-#define OFDEL 0000200
-#define NLDLY 0000400
-#define NL0 0000000
-#define NL1 0000400
-#define CRDLY 0003000
-#define CR0 0000000
-#define CR1 0001000
-#define CR2 0002000
-#define CR3 0003000
-#define TABDLY 0014000
-#define TAB0 0000000
-#define TAB1 0004000
-#define TAB2 0010000
-#define TAB3 0014000
-#define XTABS 0014000
-#define BSDLY 0020000
-#define BS0 0000000
-#define BS1 0020000
-#define VTDLY 0040000
-#define VT0 0000000
-#define VT1 0040000
-#define FFDLY 0100000
-#define FF0 0000000
-#define FF1 0100000
-
-/* c_cflag bit meaning */
-#define CBAUD 0010017
-#define B0 0000000 /* hang up */
-#define B50 0000001
-#define B75 0000002
-#define B110 0000003
-#define B134 0000004
-#define B150 0000005
-#define B200 0000006
-#define B300 0000007
-#define B600 0000010
-#define B1200 0000011
-#define B1800 0000012
-#define B2400 0000013
-#define B4800 0000014
-#define B9600 0000015
-#define B19200 0000016
-#define B38400 0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE 0000060
-#define CS5 0000000
-#define CS6 0000020
-#define CS7 0000040
-#define CS8 0000060
-#define CSTOPB 0000100
-#define CREAD 0000200
-#define PARENB 0000400
-#define PARODD 0001000
-#define HUPCL 0002000
-#define CLOCAL 0004000
-#define CBAUDEX 0010000
-#define BOTHER 0010000
-#define B57600 0010001
-#define B115200 0010002
-#define B230400 0010003
-#define B460800 0010004
-#define B500000 0010005
-#define B576000 0010006
-#define B921600 0010007
-#define B1000000 0010010
-#define B1152000 0010011
-#define B1500000 0010012
-#define B2000000 0010013
-#define B2500000 0010014
-#define B3000000 0010015
-#define B3500000 0010016
-#define B4000000 0010017
-#define CIBAUD 002003600000 /* input baud rate */
-#define CMSPAR 010000000000 /* mark or space (stick) parity */
-#define CRTSCTS 020000000000 /* flow control */
-
-#define IBSHIFT 16 /* Shifr from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-#define ISIG 0000001
-#define ICANON 0000002
-#define XCASE 0000004
-#define ECHO 0000010
-#define ECHOE 0000020
-#define ECHOK 0000040
-#define ECHONL 0000100
-#define NOFLSH 0000200
-#define TOSTOP 0000400
-#define ECHOCTL 0001000
-#define ECHOPRT 0002000
-#define ECHOKE 0004000
-#define FLUSHO 0010000
-#define PENDIN 0040000
-#define IEXTEN 0100000
-
-
-/* tcflow() and TCXONC use these */
-#define TCOOFF 0
-#define TCOON 1
-#define TCIOFF 2
-#define TCION 3
-
-/* tcflush() and TCFLSH use these */
-#define TCIFLUSH 0
-#define TCOFLUSH 1
-#define TCIOFLUSH 2
-
-/* tcsetattr uses these */
-#define TCSANOW 0
-#define TCSADRAIN 1
-#define TCSAFLUSH 2
-
-#endif /* __V850_TERMBITS_H__ */
diff --git a/include/asm-v850/termios.h b/include/asm-v850/termios.h
deleted file mode 100644
index fcd171838d9..00000000000
--- a/include/asm-v850/termios.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef __V850_TERMIOS_H__
-#define __V850_TERMIOS_H__
-
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-
-struct winsize {
- unsigned short ws_row;
- unsigned short ws_col;
- unsigned short ws_xpixel;
- unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
- unsigned short c_iflag; /* input mode flags */
- unsigned short c_oflag; /* output mode flags */
- unsigned short c_cflag; /* control mode flags */
- unsigned short c_lflag; /* local mode flags */
- unsigned char c_line; /* line discipline */
- unsigned char c_cc[NCC]; /* control characters */
-};
-
-/* modem lines */
-#define TIOCM_LE 0x001
-#define TIOCM_DTR 0x002
-#define TIOCM_RTS 0x004
-#define TIOCM_ST 0x008
-#define TIOCM_SR 0x010
-#define TIOCM_CTS 0x020
-#define TIOCM_CAR 0x040
-#define TIOCM_RNG 0x080
-#define TIOCM_DSR 0x100
-#define TIOCM_CD TIOCM_CAR
-#define TIOCM_RI TIOCM_RNG
-#define TIOCM_OUT1 0x2000
-#define TIOCM_OUT2 0x4000
-#define TIOCM_LOOP 0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
-
-/* intr=^C quit=^\ erase=del kill=^U
- eof=^D vtime=\0 vmin=\1 sxtc=\0
- start=^Q stop=^S susp=^Z eol=\0
- reprint=^R discard=^U werase=^W lnext=^V
- eol2=\0
-*/
-#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-
-/*
- * Translate a "termio" structure into a "termios". Ugh.
- */
-#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
- unsigned short __tmp; \
- get_user(__tmp,&(termio)->x); \
- *(unsigned short *) &(termios)->x = __tmp; \
-}
-
-#define user_termio_to_kernel_termios(termios, termio) \
-({ \
- SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
- SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
- SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
- SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
- copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-})
-
-/*
- * Translate a "termios" structure into a "termio". Ugh.
- */
-#define kernel_termios_to_user_termio(termio, termios) \
-({ \
- put_user((termios)->c_iflag, &(termio)->c_iflag); \
- put_user((termios)->c_oflag, &(termio)->c_oflag); \
- put_user((termios)->c_cflag, &(termio)->c_cflag); \
- put_user((termios)->c_lflag, &(termio)->c_lflag); \
- put_user((termios)->c_line, &(termio)->c_line); \
- copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-})
-
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
-#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
-
-#endif /* __KERNEL__ */
-
-#endif /* __V850_TERMIOS_H__ */
diff --git a/include/asm-v850/thread_info.h b/include/asm-v850/thread_info.h
deleted file mode 100644
index 1a9e6ae0c5f..00000000000
--- a/include/asm-v850/thread_info.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * include/asm-v850/thread_info.h -- v850 low-level thread information
- *
- * Copyright (C) 2002 NEC Corporation
- * Copyright (C) 2002 Miles Bader <miles@gnu.org>
- * Copyright (C) 2002 David Howells (dhowells@redhat.com)
- * - Incorporating suggestions made by Linus Torvalds and Dave Miller
- *
- * 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.
- *
- * This file was derived from the PPC version, include/asm-ppc/thread_info.h
- * which was adapted from the i386 version by Paul Mackerras
- */
-
-#ifndef __V850_THREAD_INFO_H__
-#define __V850_THREAD_INFO_H__
-
-#ifdef __KERNEL__
-
-#ifndef __ASSEMBLY__
-
-/*
- * low level task data.
- * If you change this, change the TI_* offsets below to match.
- */
-struct thread_info {
- struct task_struct *task; /* main task structure */
- struct exec_domain *exec_domain; /* execution domain */
- unsigned long flags; /* low level flags */
- int cpu; /* cpu we're on */
- int preempt_count; /* 0 => preemptable,
- <0 => BUG */
- struct restart_block restart_block;
-};
-
-#define INIT_THREAD_INFO(tsk) \
-{ \
- .task = &tsk, \
- .exec_domain = &default_exec_domain, \
- .flags = 0, \
- .cpu = 0, \
- .preempt_count = 1, \
- .restart_block = { \
- .fn = do_no_restart_syscall, \
- }, \
-}
-
-#define init_thread_info (init_thread_union.thread_info)
-#define init_stack (init_thread_union.stack)
-
-/*
- * macros/functions for gaining access to the thread information structure
- */
-
-/* thread information allocation */
-#define alloc_thread_info(tsk) ((struct thread_info *) \
- __get_free_pages(GFP_KERNEL, 1))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
-
-#endif /* __ASSEMBLY__ */
-
-
-/*
- * Offsets in thread_info structure, used in assembly code
- */
-#define TI_TASK 0
-#define TI_EXECDOMAIN 4
-#define TI_FLAGS 8
-#define TI_CPU 12
-#define TI_PREEMPT 16
-
-#define PREEMPT_ACTIVE 0x4000000
-
-/*
- * thread information flag bit numbers
- */
-#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
-#define TIF_SIGPENDING 1 /* signal pending */
-#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
-#define TIF_POLLING_NRFLAG 3 /* true if poll_idle() is polling
- TIF_NEED_RESCHED */
-#define TIF_MEMDIE 4
-
-/* as above, but as bit values */
-#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
-#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
-#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
-
-
-/* Size of kernel stack for each process. */
-#define THREAD_SIZE 0x2000
-
-/* The alignment of kernel threads, with thread_info structures at their
- base. Thus, a pointer for a task's task structure can be derived from
- its kernel stack pointer. */
-#define THREAD_ALIGNMENT THREAD_SIZE
-#define THREAD_MASK (-THREAD_ALIGNMENT)
-
-
-#ifdef __ASSEMBLY__
-
-/* Put a pointer to the current thread_info structure into REG. Note that
- this definition requires THREAD_MASK to be representable as a signed
- 16-bit value. */
-#define GET_CURRENT_THREAD(reg) \
- /* Use `addi' and then `and' instead of just `andi', because \
- `addi' sign-extends the immediate value, whereas `andi' \
- zero-extends it. */ \
- addi THREAD_MASK, r0, reg; \
- and sp, reg
-
-#else
-
-/* Return a pointer to the current thread_info structure. */
-static inline struct thread_info *current_thread_info (void)
-{
- register unsigned long sp __asm__ ("sp");
- return (struct thread_info *)(sp & THREAD_MASK);
-}
-
-#endif /* __ASSEMBLY__ */
-
-
-#endif /* __KERNEL__ */
-
-#endif /* __V850_THREAD_INFO_H__ */
diff --git a/include/asm-v850/timex.h b/include/asm-v850/timex.h
deleted file mode 100644
index 6279e5a0ee8..00000000000
--- a/include/asm-v850/timex.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * linux/include/asm-v850/timex.h
- *
- * v850 architecture timex specifications
- */
-#ifndef __V850_TIMEX_H__
-#define __V850_TIMEX_H__
-
-#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
-
-typedef unsigned long cycles_t;
-
-static inline cycles_t get_cycles(void)
-{
- return 0;
-}
-
-#endif /* __V850_TIMEX_H__ */
diff --git a/include/asm-v850/tlb.h b/include/asm-v850/tlb.h
deleted file mode 100644
index 73bc9ead40d..00000000000
--- a/include/asm-v850/tlb.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * include/asm-v850/tlb.h
- *
- * Copyright (C) 2002 NEC Corporation
- * Copyright (C) 2002 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_TLB_H__
-#define __V850_TLB_H__
-
-#define tlb_flush(tlb) ((void)0)
-
-#include <asm-generic/tlb.h>
-
-#endif /* __V850_TLB_H__ */
diff --git a/include/asm-v850/tlbflush.h b/include/asm-v850/tlbflush.h
deleted file mode 100644
index c44aa64449c..00000000000
--- a/include/asm-v850/tlbflush.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * include/asm-v850/tlbflush.h
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_TLBFLUSH_H__
-#define __V850_TLBFLUSH_H__
-
-#include <asm/machdep.h>
-
-
-/*
- * flush all user-space atc entries.
- */
-static inline void __flush_tlb(void)
-{
- BUG ();
-}
-
-static inline void __flush_tlb_one(unsigned long addr)
-{
- BUG ();
-}
-
-#define flush_tlb() __flush_tlb()
-
-/*
- * flush all atc entries (both kernel and user-space entries).
- */
-static inline void flush_tlb_all(void)
-{
- BUG ();
-}
-
-static inline void flush_tlb_mm(struct mm_struct *mm)
-{
- BUG ();
-}
-
-static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
-{
- BUG ();
-}
-
-static inline void flush_tlb_range(struct vm_area_struct *vma,
- unsigned long start, unsigned long end)
-{
- BUG ();
-}
-
-static inline void flush_tlb_kernel_page(unsigned long addr)
-{
- BUG ();
-}
-
-#endif /* __V850_TLBFLUSH_H__ */
diff --git a/include/asm-v850/topology.h b/include/asm-v850/topology.h
deleted file mode 100644
index 6040e41d794..00000000000
--- a/include/asm-v850/topology.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __V850_TOPOLOGY_H__
-#define __V850_TOPOLOGY_H__
-
-#include <asm-generic/topology.h>
-
-#endif /* __V850_TOPOLOGY_H__ */
diff --git a/include/asm-v850/types.h b/include/asm-v850/types.h
deleted file mode 100644
index 89f735ee41d..00000000000
--- a/include/asm-v850/types.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef __V850_TYPES_H__
-#define __V850_TYPES_H__
-
-#ifndef __ASSEMBLY__
-
-/*
- * This file is never included by application software unless
- * explicitly requested (e.g., via linux/types.h) in which case the
- * application is Linux specific so (user-) name space pollution is
- * not a major issue. However, for interoperability, libraries still
- * need to be careful to avoid a name clashes.
- */
-#include <asm-generic/int-ll64.h>
-
-typedef unsigned short umode_t;
-
-#endif /* !__ASSEMBLY__ */
-
-/*
- * These aren't exported outside the kernel to avoid name space clashes
- */
-#ifdef __KERNEL__
-
-#define BITS_PER_LONG 32
-
-#ifndef __ASSEMBLY__
-
-/* Dma addresses are 32-bits wide. */
-
-typedef u32 dma_addr_t;
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* __KERNEL__ */
-
-#endif /* __V850_TYPES_H__ */
diff --git a/include/asm-v850/uaccess.h b/include/asm-v850/uaccess.h
deleted file mode 100644
index 64563c409bb..00000000000
--- a/include/asm-v850/uaccess.h
+++ /dev/null
@@ -1,159 +0,0 @@
-#ifndef __V850_UACCESS_H__
-#define __V850_UACCESS_H__
-
-/*
- * User space memory access functions
- */
-
-#include <linux/errno.h>
-#include <linux/string.h>
-
-#include <asm/segment.h>
-#include <asm/machdep.h>
-
-#define VERIFY_READ 0
-#define VERIFY_WRITE 1
-
-static inline int access_ok (int type, const void *addr, unsigned long size)
-{
- /* XXX I guess we should check against real ram bounds at least, and
- possibly make sure ADDR is not within the kernel.
- For now we just check to make sure it's not a small positive
- or negative value, as that will at least catch some kinds of
- error. In particular, we make sure that ADDR's not within the
- interrupt vector area, which we know starts at zero, or within the
- peripheral-I/O area, which is located just _before_ zero. */
- unsigned long val = (unsigned long)addr;
- return val >= (0x80 + NUM_CPU_IRQS*16) && val < 0xFFFFF000;
-}
-
-/*
- * The exception table consists of pairs of addresses: the first is the
- * address of an instruction that is allowed to fault, and the second is
- * the address at which the program should continue. No registers are
- * modified, so it is entirely up to the continuation code to figure out
- * what to do.
- *
- * All the routines below use bits of fixup code that are out of line
- * with the main instruction path. This means when everything is well,
- * we don't even have to jump over them. Further, they do not intrude
- * on our cache or tlb entries.
- */
-
-struct exception_table_entry
-{
- unsigned long insn, fixup;
-};
-
-/* Returns 0 if exception not found and fixup otherwise. */
-extern unsigned long search_exception_table (unsigned long);
-
-
-/*
- * These are the main single-value transfer routines. They automatically
- * use the right size if we just have the right pointer type.
- */
-
-extern int bad_user_access_length (void);
-
-#define __get_user(var, ptr) \
- ({ \
- int __gu_err = 0; \
- typeof(*(ptr)) __gu_val = 0; \
- switch (sizeof (*(ptr))) { \
- case 1: \
- case 2: \
- case 4: \
- __gu_val = *(ptr); \
- break; \
- case 8: \
- memcpy(&__gu_val, ptr, sizeof(__gu_val)); \
- break; \
- default: \
- __gu_val = 0; \
- __gu_err = __get_user_bad (); \
- break; \
- } \
- (var) = __gu_val; \
- __gu_err; \
- })
-#define __get_user_bad() (bad_user_access_length (), (-EFAULT))
-
-#define __put_user(var, ptr) \
- ({ \
- int __pu_err = 0; \
- switch (sizeof (*(ptr))) { \
- case 1: \
- case 2: \
- case 4: \
- *(ptr) = (var); \
- break; \
- case 8: { \
- typeof(*(ptr)) __pu_val = 0; \
- memcpy(ptr, &__pu_val, sizeof(__pu_val)); \
- } \
- break; \
- default: \
- __pu_err = __put_user_bad (); \
- break; \
- } \
- __pu_err; \
- })
-#define __put_user_bad() (bad_user_access_length (), (-EFAULT))
-
-#define put_user(x, ptr) __put_user(x, ptr)
-#define get_user(x, ptr) __get_user(x, ptr)
-
-#define __copy_from_user(to, from, n) (memcpy (to, from, n), 0)
-#define __copy_to_user(to, from, n) (memcpy(to, from, n), 0)
-
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
-
-#define copy_from_user(to, from, n) __copy_from_user (to, from, n)
-#define copy_to_user(to, from, n) __copy_to_user(to, from, n)
-
-#define copy_to_user_ret(to,from,n,retval) \
- ({ if (copy_to_user (to,from,n)) return retval; })
-
-#define copy_from_user_ret(to,from,n,retval) \
- ({ if (copy_from_user (to,from,n)) return retval; })
-
-/*
- * Copy a null terminated string from userspace.
- */
-
-static inline long
-strncpy_from_user (char *dst, const char *src, long count)
-{
- char *tmp;
- strncpy (dst, src, count);
- for (tmp = dst; *tmp && count > 0; tmp++, count--)
- ;
- return tmp - dst;
-}
-
-/*
- * Return the size of a string (including the ending 0)
- *
- * Return 0 on exception, a value greater than N if too long
- */
-static inline long strnlen_user (const char *src, long n)
-{
- return strlen (src) + 1;
-}
-
-#define strlen_user(str) strnlen_user (str, 32767)
-
-/*
- * Zero Userspace
- */
-
-static inline unsigned long
-clear_user (void *to, unsigned long n)
-{
- memset (to, 0, n);
- return 0;
-}
-
-#endif /* __V850_UACCESS_H__ */
diff --git a/include/asm-v850/ucontext.h b/include/asm-v850/ucontext.h
deleted file mode 100644
index 303c21590cf..00000000000
--- a/include/asm-v850/ucontext.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __V850_UCONTEXT_H__
-#define __V850_UCONTEXT_H__
-
-#include <asm/sigcontext.h>
-
-struct ucontext {
- unsigned long uc_flags;
- struct ucontext *uc_link;
- stack_t uc_stack;
- struct sigcontext uc_mcontext;
- sigset_t uc_sigmask; /* mask last for extensibility */
-};
-
-#endif /* __V850_UCONTEXT_H__ */
diff --git a/include/asm-v850/unaligned.h b/include/asm-v850/unaligned.h
deleted file mode 100644
index 53122b28491..00000000000
--- a/include/asm-v850/unaligned.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2001 NEC Corporation
- * Copyright (C) 2001 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
- * archive for more details.
- *
- * Note that some v850 chips support unaligned access, but it seems too
- * annoying to use.
- */
-#ifndef _ASM_V850_UNALIGNED_H
-#define _ASM_V850_UNALIGNED_H
-
-#include <linux/unaligned/be_byteshift.h>
-#include <linux/unaligned/le_byteshift.h>
-#include <linux/unaligned/generic.h>
-
-#define get_unaligned __get_unaligned_le
-#define put_unaligned __put_unaligned_le
-
-#endif /* _ASM_V850_UNALIGNED_H */
diff --git a/include/asm-v850/unistd.h b/include/asm-v850/unistd.h
deleted file mode 100644
index 2241ed45ecf..00000000000
--- a/include/asm-v850/unistd.h
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * include/asm-v850/unistd.h -- System call numbers and invocation mechanism
- *
- * Copyright (C) 2001,02,03,04 NEC Electronics Corporation
- * Copyright (C) 2001,02,03,04 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_UNISTD_H__
-#define __V850_UNISTD_H__
-
-#define __NR_restart_syscall 0
-#define __NR_exit 1
-#define __NR_fork 2
-#define __NR_read 3
-#define __NR_write 4
-#define __NR_open 5
-#define __NR_close 6
-#define __NR_waitpid 7
-#define __NR_creat 8
-#define __NR_link 9
-#define __NR_unlink 10
-#define __NR_execve 11
-#define __NR_chdir 12
-#define __NR_time 13
-#define __NR_mknod 14
-#define __NR_chmod 15
-#define __NR_chown 16
-#define __NR_break 17
-#define __NR_lseek 19
-#define __NR_getpid 20
-#define __NR_mount 21
-#define __NR_umount 22
-#define __NR_setuid 23
-#define __NR_getuid 24
-#define __NR_stime 25
-#define __NR_ptrace 26
-#define __NR_alarm 27
-#define __NR_pause 29
-#define __NR_utime 30
-#define __NR_stty 31
-#define __NR_gtty 32
-#define __NR_access 33
-#define __NR_nice 34
-#define __NR_ftime 35
-#define __NR_sync 36
-#define __NR_kill 37
-#define __NR_rename 38
-#define __NR_mkdir 39
-#define __NR_rmdir 40
-#define __NR_dup 41
-#define __NR_pipe 42
-#define __NR_times 43
-#define __NR_prof 44
-#define __NR_brk 45
-#define __NR_setgid 46
-#define __NR_getgid 47
-#define __NR_signal 48
-#define __NR_geteuid 49
-#define __NR_getegid 50
-#define __NR_acct 51
-#define __NR_umount2 52
-#define __NR_lock 53
-#define __NR_ioctl 54
-#define __NR_fcntl 55
-#define __NR_setpgid 57
-#define __NR_umask 60
-#define __NR_chroot 61
-#define __NR_ustat 62
-#define __NR_dup2 63
-#define __NR_getppid 64
-#define __NR_getpgrp 65
-#define __NR_setsid 66
-#define __NR_sigaction 67
-#define __NR_sgetmask 68
-#define __NR_ssetmask 69
-#define __NR_setreuid 70
-#define __NR_setregid 71
-#define __NR_sigsuspend 72
-#define __NR_sigpending 73
-#define __NR_sethostname 74
-#define __NR_setrlimit 75
-#define __NR_ugetrlimit 76
-#define __NR_getrusage 77
-#define __NR_gettimeofday 78
-#define __NR_settimeofday 79
-#define __NR_getgroups 80
-#define __NR_setgroups 81
-#define __NR_select 82
-#define __NR_symlink 83
-#define __NR_readlink 85
-#define __NR_uselib 86
-#define __NR_swapon 87
-#define __NR_reboot 88
-#define __NR_readdir 89
-#define __NR_mmap 90
-#define __NR_munmap 91
-#define __NR_truncate 92
-#define __NR_ftruncate 93
-#define __NR_fchmod 94
-#define __NR_fchown 95
-#define __NR_getpriority 96
-#define __NR_setpriority 97
-#define __NR_profil 98
-#define __NR_statfs 99
-#define __NR_fstatfs 100
-#define __NR_socketcall 102
-#define __NR_syslog 103
-#define __NR_setitimer 104
-#define __NR_getitimer 105
-#define __NR_stat 106
-#define __NR_lstat 107
-#define __NR_fstat 108
-#define __NR_vhangup 111
-#define __NR_wait4 114
-#define __NR_swapoff 115
-#define __NR_sysinfo 116
-#define __NR_ipc 117
-#define __NR_fsync 118
-#define __NR_sigreturn 119
-#define __NR_clone 120
-#define __NR_setdomainname 121
-#define __NR_uname 122
-#define __NR_cacheflush 123
-#define __NR_adjtimex 124
-#define __NR_mprotect 125
-#define __NR_sigprocmask 126
-#define __NR_create_module 127
-#define __NR_init_module 128
-#define __NR_delete_module 129
-#define __NR_get_kernel_syms 130
-#define __NR_quotactl 131
-#define __NR_getpgid 132
-#define __NR_fchdir 133
-#define __NR_bdflush 134
-#define __NR_sysfs 135
-#define __NR_personality 136
-#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
-#define __NR_setfsuid 138
-#define __NR_setfsgid 139
-#define __NR__llseek 140
-#define __NR_getdents 141
-#define __NR_flock 143
-#define __NR_msync 144
-#define __NR_readv 145
-#define __NR_writev 146
-#define __NR_getsid 147
-#define __NR_fdatasync 148
-#define __NR__sysctl 149
-#define __NR_mlock 150
-#define __NR_munlock 151
-#define __NR_mlockall 152
-#define __NR_munlockall 153
-#define __NR_sched_setparam 154
-#define __NR_sched_getparam 155
-#define __NR_sched_setscheduler 156
-#define __NR_sched_getscheduler 157
-#define __NR_sched_yield 158
-#define __NR_sched_get_priority_max 159
-#define __NR_sched_get_priority_min 160
-#define __NR_sched_rr_get_interval 161
-#define __NR_nanosleep 162
-#define __NR_mremap 163
-#define __NR_setresuid 164
-#define __NR_getresuid 165
-#define __NR_query_module 167
-#define __NR_poll 168
-#define __NR_nfsservctl 169
-#define __NR_setresgid 170
-#define __NR_getresgid 171
-#define __NR_prctl 172
-#define __NR_rt_sigreturn 173
-#define __NR_rt_sigaction 174
-#define __NR_rt_sigprocmask 175
-#define __NR_rt_sigpending 176
-#define __NR_rt_sigtimedwait 177
-#define __NR_rt_sigqueueinfo 178
-#define __NR_rt_sigsuspend 179
-#define __NR_pread 180
-#define __NR_pwrite 181
-#define __NR_lchown 182
-#define __NR_getcwd 183
-#define __NR_capget 184
-#define __NR_capset 185
-#define __NR_sigaltstack 186
-#define __NR_sendfile 187
-#define __NR_getpmsg 188 /* some people actually want streams */
-#define __NR_putpmsg 189 /* some people actually want streams */
-#define __NR_vfork 190
-#define __NR_mmap2 192
-#define __NR_truncate64 193
-#define __NR_ftruncate64 194
-#define __NR_stat64 195
-#define __NR_lstat64 196
-#define __NR_fstat64 197
-#define __NR_fcntl64 198
-#define __NR_getdents64 199
-#define __NR_pivot_root 200
-#define __NR_gettid 201
-#define __NR_tkill 202
-
-#ifdef __KERNEL__
-
-#define __ARCH_WANT_IPC_PARSE_VERSION
-#define __ARCH_WANT_OLD_READDIR
-#define __ARCH_WANT_STAT64
-#define __ARCH_WANT_SYS_ALARM
-#define __ARCH_WANT_SYS_GETHOSTNAME
-#define __ARCH_WANT_SYS_PAUSE
-#define __ARCH_WANT_SYS_SGETMASK
-#define __ARCH_WANT_SYS_SIGNAL
-#define __ARCH_WANT_SYS_TIME
-#define __ARCH_WANT_SYS_UTIME
-#define __ARCH_WANT_SYS_WAITPID
-#define __ARCH_WANT_SYS_SOCKETCALL
-#define __ARCH_WANT_SYS_FADVISE64
-#define __ARCH_WANT_SYS_GETPGRP
-#define __ARCH_WANT_SYS_LLSEEK
-#define __ARCH_WANT_SYS_NICE
-#define __ARCH_WANT_SYS_OLDUMOUNT
-#define __ARCH_WANT_SYS_SIGPENDING
-#define __ARCH_WANT_SYS_SIGPROCMASK
-#define __ARCH_WANT_SYS_RT_SIGACTION
-
-/*
- * "Conditional" syscalls
- */
-#define cond_syscall(name) \
- asm (".weak\t" C_SYMBOL_STRING(name) ";" \
- ".set\t" C_SYMBOL_STRING(name) "," C_SYMBOL_STRING(sys_ni_syscall))
-#if 0
-/* This doesn't work if there's a function prototype for NAME visible,
- because the argument types probably won't match. */
-#define cond_syscall(name) \
- void name (void) __attribute__ ((weak, alias ("sys_ni_syscall")));
-#endif
-
-#endif /* __KERNEL__ */
-#endif /* __V850_UNISTD_H__ */
diff --git a/include/asm-v850/user.h b/include/asm-v850/user.h
deleted file mode 100644
index 63cdc567d27..00000000000
--- a/include/asm-v850/user.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef __V850_USER_H__
-#define __V850_USER_H__
-
-/* Adapted from <asm-ppc/user.h>. */
-
-#include <linux/ptrace.h>
-#include <asm/page.h>
-
-/*
- * Core file format: The core file is written in such a way that gdb
- * can understand it and provide useful information to the user (under
- * linux we use the `trad-core' bfd, NOT the osf-core). The file contents
- * are as follows:
- *
- * upage: 1 page consisting of a user struct that tells gdb
- * what is present in the file. Directly after this is a
- * copy of the task_struct, which is currently not used by gdb,
- * but it may come in handy at some point. All of the registers
- * are stored as part of the upage. The upage should always be
- * only one page long.
- * data: The data segment follows next. We use current->end_text to
- * current->brk to pick up all of the user variables, plus any memory
- * that may have been sbrk'ed. No attempt is made to determine if a
- * page is demand-zero or if a page is totally unused, we just cover
- * the entire range. All of the addresses are rounded in such a way
- * that an integral number of pages is written.
- * stack: We need the stack information in order to get a meaningful
- * backtrace. We need to write the data from usp to
- * current->start_stack, so we round each of these in order to be able
- * to write an integer number of pages.
- */
-struct user {
- struct pt_regs regs; /* entire machine state */
- size_t u_tsize; /* text size (pages) */
- size_t u_dsize; /* data size (pages) */
- size_t u_ssize; /* stack size (pages) */
- unsigned long start_code; /* text starting address */
- unsigned long start_data; /* data starting address */
- unsigned long start_stack; /* stack starting address */
- long int signal; /* signal causing core dump */
- unsigned long u_ar0; /* help gdb find registers */
- unsigned long magic; /* identifies a core file */
- char u_comm[32]; /* user command name */
-};
-
-#define NBPG PAGE_SIZE
-#define UPAGES 1
-#define HOST_TEXT_START_ADDR (u.start_code)
-#define HOST_DATA_START_ADDR (u.start_data)
-#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
-
-#endif /* __V850_USER_H__ */
diff --git a/include/asm-v850/v850e.h b/include/asm-v850/v850e.h
deleted file mode 100644
index 5a222eb5117..00000000000
--- a/include/asm-v850/v850e.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * include/asm-v850/v850e.h -- V850E CPU
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_V850E_H__
-#define __V850_V850E_H__
-
-#include <asm/v850e_intc.h>
-
-#define CPU_ARCH "v850e"
-
-#endif /* __V850_V850E_H__ */
diff --git a/include/asm-v850/v850e2.h b/include/asm-v850/v850e2.h
deleted file mode 100644
index 48680408ab7..00000000000
--- a/include/asm-v850/v850e2.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * include/asm-v850/v850e2.h -- Machine-dependent defs for V850E2 CPUs
- *
- * Copyright (C) 2002,03 NEC Electronics Corporation
- * Copyright (C) 2002,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_V850E2_H__
-#define __V850_V850E2_H__
-
-#include <asm/v850e_intc.h> /* v850e-style interrupt system. */
-
-
-#define CPU_ARCH "v850e2"
-
-
-/* Control registers. */
-
-/* Chip area select control */
-#define V850E2_CSC_ADDR(n) (0xFFFFF060 + (n) * 2)
-#define V850E2_CSC(n) (*(volatile u16 *)V850E2_CSC_ADDR(n))
-/* I/O area select control */
-#define V850E2_BPC_ADDR 0xFFFFF064
-#define V850E2_BPC (*(volatile u16 *)V850E2_BPC_ADDR)
-/* Bus size configuration */
-#define V850E2_BSC_ADDR 0xFFFFF066
-#define V850E2_BSC (*(volatile u16 *)V850E2_BSC_ADDR)
-/* Endian configuration */
-#define V850E2_BEC_ADDR 0xFFFFF068
-#define V850E2_BEC (*(volatile u16 *)V850E2_BEC_ADDR)
-/* Cache configuration */
-#define V850E2_BHC_ADDR 0xFFFFF06A
-#define V850E2_BHC (*(volatile u16 *)V850E2_BHC_ADDR)
-/* NPB strobe-wait configuration */
-#define V850E2_VSWC_ADDR 0xFFFFF06E
-#define V850E2_VSWC (*(volatile u16 *)V850E2_VSWC_ADDR)
-/* Bus cycle type */
-#define V850E2_BCT_ADDR(n) (0xFFFFF480 + (n) * 2)
-#define V850E2_BCT(n) (*(volatile u16 *)V850E2_BCT_ADDR(n))
-/* Data wait control */
-#define V850E2_DWC_ADDR(n) (0xFFFFF484 + (n) * 2)
-#define V850E2_DWC(n) (*(volatile u16 *)V850E2_DWC_ADDR(n))
-/* Bus cycle control */
-#define V850E2_BCC_ADDR 0xFFFFF488
-#define V850E2_BCC (*(volatile u16 *)V850E2_BCC_ADDR)
-/* Address wait control */
-#define V850E2_ASC_ADDR 0xFFFFF48A
-#define V850E2_ASC (*(volatile u16 *)V850E2_ASC_ADDR)
-/* Local bus sizing control */
-#define V850E2_LBS_ADDR 0xFFFFF48E
-#define V850E2_LBS (*(volatile u16 *)V850E2_LBS_ADDR)
-/* Line buffer control */
-#define V850E2_LBC_ADDR(n) (0xFFFFF490 + (n) * 2)
-#define V850E2_LBC(n) (*(volatile u16 *)V850E2_LBC_ADDR(n))
-/* SDRAM configuration */
-#define V850E2_SCR_ADDR(n) (0xFFFFF4A0 + (n) * 4)
-#define V850E2_SCR(n) (*(volatile u16 *)V850E2_SCR_ADDR(n))
-/* SDRAM refresh cycle control */
-#define V850E2_RFS_ADDR(n) (0xFFFFF4A2 + (n) * 4)
-#define V850E2_RFS(n) (*(volatile u16 *)V850E2_RFS_ADDR(n))
-
-
-#endif /* __V850_V850E2_H__ */
diff --git a/include/asm-v850/v850e2_cache.h b/include/asm-v850/v850e2_cache.h
deleted file mode 100644
index 87edf0d311d..00000000000
--- a/include/asm-v850/v850e2_cache.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * include/asm-v850/v850e2_cache_cache.h -- Cache control for V850E2
- * cache memories
- *
- * Copyright (C) 2003,05 NEC Electronics Corporation
- * Copyright (C) 2003,05 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_V850E2_CACHE_H__
-#define __V850_V850E2_CACHE_H__
-
-#include <asm/types.h>
-
-
-/* Cache control registers. */
-
-/* Bus Transaction Control */
-#define V850E2_CACHE_BTSC_ADDR 0xFFFFF070
-#define V850E2_CACHE_BTSC (*(volatile u16 *)V850E2_CACHE_BTSC_ADDR)
-#define V850E2_CACHE_BTSC_ICM 0x0001 /* icache enable */
-#define V850E2_CACHE_BTSC_DCM0 0x0004 /* dcache enable, bit 0 */
-#define V850E2_CACHE_BTSC_DCM1 0x0008 /* dcache enable, bit 1 */
-#define V850E2_CACHE_BTSC_DCM_WT /* write-through */ \
- V850E2_CACHE_BTSC_DCM0
-#ifdef CONFIG_V850E2_V850E2S
-# define V850E2_CACHE_BTSC_DCM_WB_NO_ALLOC /* write-back, non-alloc */ \
- V850E2_CACHE_BTSC_DCM1
-# define V850E2_CACHE_BTSC_DCM_WB_ALLOC /* write-back, non-alloc */ \
- (V850E2_CACHE_BTSC_DCM1 | V850E2_CACHE_BTSC_DCM0)
-# define V850E2_CACHE_BTSC_ISEQ 0x0010 /* icache `address sequence mode' */
-# define V850E2_CACHE_BTSC_DSEQ 0x0020 /* dcache `address sequence mode' */
-# define V850E2_CACHE_BTSC_IRFC 0x0030
-# define V850E2_CACHE_BTSC_ILCD 0x4000
-# define V850E2_CACHE_BTSC_VABE 0x8000
-#endif /* CONFIG_V850E2_V850E2S */
-
-/* Cache operation start address register (low-bits). */
-#define V850E2_CACHE_CADL_ADDR 0xFFFFF074
-#define V850E2_CACHE_CADL (*(volatile u16 *)V850E2_CACHE_CADL_ADDR)
-/* Cache operation start address register (high-bits). */
-#define V850E2_CACHE_CADH_ADDR 0xFFFFF076
-#define V850E2_CACHE_CADH (*(volatile u16 *)V850E2_CACHE_CADH_ADDR)
-/* Cache operation count register. */
-#define V850E2_CACHE_CCNT_ADDR 0xFFFFF078
-#define V850E2_CACHE_CCNT (*(volatile u16 *)V850E2_CACHE_CCNT_ADDR)
-/* Cache operation specification register. */
-#define V850E2_CACHE_COPR_ADDR 0xFFFFF07A
-#define V850E2_CACHE_COPR (*(volatile u16 *)V850E2_CACHE_COPR_ADDR)
-#define V850E2_CACHE_COPR_STRT 0x0001 /* start cache operation */
-#define V850E2_CACHE_COPR_LBSL 0x0100 /* 0 = icache, 1 = dcache */
-#define V850E2_CACHE_COPR_WSLE 0x0200 /* operate on cache way */
-#define V850E2_CACHE_COPR_WSL(way) ((way) * 0x0400) /* way select */
-#define V850E2_CACHE_COPR_CFC(op) ((op) * 0x1000) /* cache function code */
-
-
-/* Size of a cache line in bytes. */
-#define V850E2_CACHE_LINE_SIZE_BITS 4
-#define V850E2_CACHE_LINE_SIZE (1 << V850E2_CACHE_LINE_SIZE_BITS)
-
-/* The size of each cache `way' in lines. */
-#define V850E2_CACHE_WAY_SIZE 256
-
-
-/* For <asm/cache.h> */
-#define L1_CACHE_BYTES V850E2_CACHE_LINE_SIZE
-#define L1_CACHE_SHIFT V850E2_CACHE_LINE_SIZE_BITS
-
-
-#endif /* __V850_V850E2_CACHE_H__ */
diff --git a/include/asm-v850/v850e_cache.h b/include/asm-v850/v850e_cache.h
deleted file mode 100644
index aa7d7eb9da5..00000000000
--- a/include/asm-v850/v850e_cache.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * include/asm-v850/v850e_cache.h -- Cache control for V850E cache memories
- *
- * Copyright (C) 2001,03 NEC Electronics Corporation
- * Copyright (C) 2001,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-/* This file implements cache control for the rather simple cache used on
- some V850E CPUs, specifically the NB85E/TEG CPU-core and the V850E/ME2
- CPU. V850E2 processors have their own (better) cache
- implementation. */
-
-#ifndef __V850_V850E_CACHE_H__
-#define __V850_V850E_CACHE_H__
-
-#include <asm/types.h>
-
-
-/* Cache control registers. */
-#define V850E_CACHE_BHC_ADDR 0xFFFFF06A
-#define V850E_CACHE_BHC (*(volatile u16 *)V850E_CACHE_BHC_ADDR)
-#define V850E_CACHE_ICC_ADDR 0xFFFFF070
-#define V850E_CACHE_ICC (*(volatile u16 *)V850E_CACHE_ICC_ADDR)
-#define V850E_CACHE_ISI_ADDR 0xFFFFF072
-#define V850E_CACHE_ISI (*(volatile u16 *)V850E_CACHE_ISI_ADDR)
-#define V850E_CACHE_DCC_ADDR 0xFFFFF078
-#define V850E_CACHE_DCC (*(volatile u16 *)V850E_CACHE_DCC_ADDR)
-
-/* Size of a cache line in bytes. */
-#define V850E_CACHE_LINE_SIZE 16
-
-/* For <asm/cache.h> */
-#define L1_CACHE_BYTES V850E_CACHE_LINE_SIZE
-
-
-#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
-/* Set caching params via the BHC, ICC, and DCC registers. */
-void v850e_cache_enable (u16 bhc, u16 icc, u16 dcc);
-#endif /* __KERNEL__ && !__ASSEMBLY__ */
-
-
-#endif /* __V850_V850E_CACHE_H__ */
diff --git a/include/asm-v850/v850e_intc.h b/include/asm-v850/v850e_intc.h
deleted file mode 100644
index 6fdf9570831..00000000000
--- a/include/asm-v850/v850e_intc.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * include/asm-v850/v850e_intc.h -- V850E CPU interrupt controller (INTC)
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_V850E_INTC_H__
-#define __V850_V850E_INTC_H__
-
-
-/* There are 4 16-bit `Interrupt Mask Registers' located contiguously
- starting from this base. Each interrupt uses a single bit to
- indicated enabled/disabled status. */
-#define V850E_INTC_IMR_BASE_ADDR 0xFFFFF100
-#define V850E_INTC_IMR_ADDR(irq) (V850E_INTC_IMR_BASE_ADDR + ((irq) >> 3))
-#define V850E_INTC_IMR_BIT(irq) ((irq) & 0x7)
-
-/* Each maskable interrupt has a single-byte control register at this
- address. */
-#define V850E_INTC_IC_BASE_ADDR 0xFFFFF110
-#define V850E_INTC_IC_ADDR(irq) (V850E_INTC_IC_BASE_ADDR + ((irq) << 1))
-#define V850E_INTC_IC(irq) (*(volatile u8 *)V850E_INTC_IC_ADDR(irq))
-/* Encode priority PR for storing in an interrupt control register. */
-#define V850E_INTC_IC_PR(pr) (pr)
-/* Interrupt disable bit in an interrupt control register. */
-#define V850E_INTC_IC_MK_BIT 6
-#define V850E_INTC_IC_MK (1 << V850E_INTC_IC_MK_BIT)
-/* Interrupt pending flag in an interrupt control register. */
-#define V850E_INTC_IC_IF_BIT 7
-#define V850E_INTC_IC_IF (1 << V850E_INTC_IC_IF_BIT)
-
-/* The ISPR (In-service priority register) contains one bit for each interrupt
- priority level, which is set to one when that level is currently being
- serviced (and thus blocking any interrupts of equal or lesser level). */
-#define V850E_INTC_ISPR_ADDR 0xFFFFF1FA
-#define V850E_INTC_ISPR (*(volatile u8 *)V850E_INTC_ISPR_ADDR)
-
-
-#ifndef __ASSEMBLY__
-
-/* Enable interrupt handling for interrupt IRQ. */
-static inline void v850e_intc_enable_irq (unsigned irq)
-{
- __asm__ __volatile__ ("clr1 %0, [%1]"
- :: "r" (V850E_INTC_IMR_BIT (irq)),
- "r" (V850E_INTC_IMR_ADDR (irq))
- : "memory");
-}
-
-/* Disable interrupt handling for interrupt IRQ. Note that any
- interrupts received while disabled will be delivered once the
- interrupt is enabled again, unless they are explicitly cleared using
- `v850e_intc_clear_pending_irq'. */
-static inline void v850e_intc_disable_irq (unsigned irq)
-{
- __asm__ __volatile__ ("set1 %0, [%1]"
- :: "r" (V850E_INTC_IMR_BIT (irq)),
- "r" (V850E_INTC_IMR_ADDR (irq))
- : "memory");
-}
-
-/* Return true if interrupt handling for interrupt IRQ is enabled. */
-static inline int v850e_intc_irq_enabled (unsigned irq)
-{
- int rval;
- __asm__ __volatile__ ("tst1 %1, [%2]; setf z, %0"
- : "=r" (rval)
- : "r" (V850E_INTC_IMR_BIT (irq)),
- "r" (V850E_INTC_IMR_ADDR (irq)));
- return rval;
-}
-
-/* Disable irqs from 0 until LIMIT. LIMIT must be a multiple of 8. */
-static inline void _v850e_intc_disable_irqs (unsigned limit)
-{
- unsigned long addr;
- for (addr = V850E_INTC_IMR_BASE_ADDR; limit >= 8; addr++, limit -= 8)
- *(char *)addr = 0xFF;
-}
-
-/* Disable all irqs. This is purposely a macro, because NUM_MACH_IRQS
- will be only be defined later. */
-#define v850e_intc_disable_irqs() _v850e_intc_disable_irqs (NUM_MACH_IRQS)
-
-/* Clear any pending interrupts for IRQ. */
-static inline void v850e_intc_clear_pending_irq (unsigned irq)
-{
- __asm__ __volatile__ ("clr1 %0, 0[%1]"
- :: "i" (V850E_INTC_IC_IF_BIT),
- "r" (V850E_INTC_IC_ADDR (irq))
- : "memory");
-}
-
-/* Return true if interrupt IRQ is pending (but disabled). */
-static inline int v850e_intc_irq_pending (unsigned irq)
-{
- int rval;
- __asm__ __volatile__ ("tst1 %1, 0[%2]; setf nz, %0"
- : "=r" (rval)
- : "i" (V850E_INTC_IC_IF_BIT),
- "r" (V850E_INTC_IC_ADDR (irq)));
- return rval;
-}
-
-
-struct v850e_intc_irq_init {
- const char *name; /* name of interrupt type */
-
- /* Range of kernel irq numbers for this type:
- BASE, BASE+INTERVAL, ..., BASE+INTERVAL*NUM */
- unsigned base, num, interval;
-
- unsigned priority; /* interrupt priority to assign */
-};
-struct hw_interrupt_type; /* fwd decl */
-
-/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
- INITS (which is terminated by an entry with the name field == 0). */
-extern void v850e_intc_init_irq_types (struct v850e_intc_irq_init *inits,
- struct hw_interrupt_type *hw_irq_types);
-
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_V850E_INTC_H__ */
diff --git a/include/asm-v850/v850e_timer_c.h b/include/asm-v850/v850e_timer_c.h
deleted file mode 100644
index f70575df6ea..00000000000
--- a/include/asm-v850/v850e_timer_c.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * include/asm-v850/v850e_timer_c.h -- `Timer C' component often used
- * with the V850E cpu core
- *
- * Copyright (C) 2001,03 NEC Electronics Corporation
- * Copyright (C) 2001,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-/* NOTE: this include file currently contains only enough to allow us to
- use timer C as an interrupt pass-through. */
-
-#ifndef __V850_V850E_TIMER_C_H__
-#define __V850_V850E_TIMER_C_H__
-
-#include <asm/types.h>
-#include <asm/machdep.h> /* Pick up chip-specific defs. */
-
-
-/* Timer C (16-bit interval timers). */
-
-/* Control register 0 for timer C. */
-#define V850E_TIMER_C_TMCC0_ADDR(n) (V850E_TIMER_C_BASE_ADDR + 0x6 + 0x10 *(n))
-#define V850E_TIMER_C_TMCC0(n) (*(volatile u8 *)V850E_TIMER_C_TMCC0_ADDR(n))
-#define V850E_TIMER_C_TMCC0_CAE 0x01 /* clock action enable */
-#define V850E_TIMER_C_TMCC0_CE 0x02 /* count enable */
-/* ... */
-
-/* Control register 1 for timer C. */
-#define V850E_TIMER_C_TMCC1_ADDR(n) (V850E_TIMER_C_BASE_ADDR + 0x8 + 0x10 *(n))
-#define V850E_TIMER_C_TMCC1(n) (*(volatile u8 *)V850E_TIMER_C_TMCC1_ADDR(n))
-#define V850E_TIMER_C_TMCC1_CMS0 0x01 /* capture/compare mode select (ccc0) */
-#define V850E_TIMER_C_TMCC1_CMS1 0x02 /* capture/compare mode select (ccc1) */
-/* ... */
-
-/* Interrupt edge-sensitivity control for timer C. */
-#define V850E_TIMER_C_SESC_ADDR(n) (V850E_TIMER_C_BASE_ADDR + 0x9 + 0x10 *(n))
-#define V850E_TIMER_C_SESC(n) (*(volatile u8 *)V850E_TIMER_C_SESC_ADDR(n))
-
-/* ...etc... */
-
-
-#endif /* __V850_V850E_TIMER_C_H__ */
diff --git a/include/asm-v850/v850e_timer_d.h b/include/asm-v850/v850e_timer_d.h
deleted file mode 100644
index 417612c5b22..00000000000
--- a/include/asm-v850/v850e_timer_d.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * include/asm-v850/v850e_timer_d.h -- `Timer D' component often used
- * with the V850E cpu core
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_V850E_TIMER_D_H__
-#define __V850_V850E_TIMER_D_H__
-
-#include <asm/types.h>
-#include <asm/machdep.h> /* Pick up chip-specific defs. */
-
-
-/* Timer D (16-bit interval timers). */
-
-/* Count registers for timer D. */
-#define V850E_TIMER_D_TMD_ADDR(n) (V850E_TIMER_D_TMD_BASE_ADDR + 0x10 * (n))
-#define V850E_TIMER_D_TMD(n) (*(volatile u16 *)V850E_TIMER_D_TMD_ADDR(n))
-
-/* Count compare registers for timer D. */
-#define V850E_TIMER_D_CMD_ADDR(n) (V850E_TIMER_D_CMD_BASE_ADDR + 0x10 * (n))
-#define V850E_TIMER_D_CMD(n) (*(volatile u16 *)V850E_TIMER_D_CMD_ADDR(n))
-
-/* Control registers for timer D. */
-#define V850E_TIMER_D_TMCD_ADDR(n) (V850E_TIMER_D_TMCD_BASE_ADDR + 0x10 * (n))
-#define V850E_TIMER_D_TMCD(n) (*(volatile u8 *)V850E_TIMER_D_TMCD_ADDR(n))
-/* Control bits for timer D. */
-#define V850E_TIMER_D_TMCD_CE 0x2 /* count enable */
-#define V850E_TIMER_D_TMCD_CAE 0x1 /* clock action enable */
-/* Clock divider setting (log2). */
-#define V850E_TIMER_D_TMCD_CS(divlog2) (((divlog2) - V850E_TIMER_D_TMCD_CS_MIN) << 4)
-/* Minimum clock divider setting (log2). */
-#ifndef V850E_TIMER_D_TMCD_CS_MIN /* Can be overridden by mach-specific hdrs */
-#define V850E_TIMER_D_TMCD_CS_MIN 2 /* Default is correct for the v850e/ma1 */
-#endif
-/* Maximum clock divider setting (log2). */
-#define V850E_TIMER_D_TMCD_CS_MAX (V850E_TIMER_D_TMCD_CS_MIN + 7)
-
-/* Return the clock-divider (log2) of timer D unit N. */
-#define V850E_TIMER_D_DIVLOG2(n) \
- (((V850E_TIMER_D_TMCD(n) >> 4) & 0x7) + V850E_TIMER_D_TMCD_CS_MIN)
-
-
-#ifndef __ASSEMBLY__
-
-/* Start interval timer TIMER (0-3). The timer will issue the
- corresponding INTCMD interrupt RATE times per second. This function
- does not enable the interrupt. */
-extern void v850e_timer_d_configure (unsigned timer, unsigned rate);
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_V850E_TIMER_D_H__ */
diff --git a/include/asm-v850/v850e_uart.h b/include/asm-v850/v850e_uart.h
deleted file mode 100644
index 5182fb4cc98..00000000000
--- a/include/asm-v850/v850e_uart.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * include/asm-v850/v850e_uart.h -- common V850E on-chip UART driver
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-/* There's not actually a single UART implementation used by V850E CPUs,
- but rather a series of implementations that are all `close' to one
- another. This file corresponds to the single driver which handles all
- of them. */
-
-#ifndef __V850_V850E_UART_H__
-#define __V850_V850E_UART_H__
-
-#include <linux/termios.h>
-
-#include <asm/v850e_utils.h>
-#include <asm/types.h>
-#include <asm/machdep.h> /* Pick up chip-specific defs. */
-
-
-/* Include model-specific definitions. */
-#ifdef CONFIG_V850E_UART
-# ifdef CONFIG_V850E_UARTB
-# include <asm-v850/v850e_uartb.h>
-# else
-# include <asm-v850/v850e_uarta.h> /* original V850E UART */
-# endif
-#endif
-
-
-/* Optional capabilities some hardware provides. */
-
-/* This UART doesn't implement RTS/CTS by default, but some platforms
- implement them externally, so check to see if <asm/machdep.h> defined
- anything. */
-#ifdef V850E_UART_CTS
-#define v850e_uart_cts(n) V850E_UART_CTS(n)
-#else
-#define v850e_uart_cts(n) (1)
-#endif
-
-/* Do the same for RTS. */
-#ifdef V850E_UART_SET_RTS
-#define v850e_uart_set_rts(n,v) V850E_UART_SET_RTS(n,v)
-#else
-#define v850e_uart_set_rts(n,v) ((void)0)
-#endif
-
-
-/* This is the serial channel to use for the boot console (if desired). */
-#ifndef V850E_UART_CONSOLE_CHANNEL
-# define V850E_UART_CONSOLE_CHANNEL 0
-#endif
-
-
-#ifndef __ASSEMBLY__
-
-/* Setup a console using channel 0 of the builtin uart. */
-extern void v850e_uart_cons_init (unsigned chan);
-
-/* Configure and turn on uart channel CHAN, using the termios `control
- modes' bits in CFLAGS, and a baud-rate of BAUD. */
-void v850e_uart_configure (unsigned chan, unsigned cflags, unsigned baud);
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_V850E_UART_H__ */
diff --git a/include/asm-v850/v850e_uarta.h b/include/asm-v850/v850e_uarta.h
deleted file mode 100644
index e483e095072..00000000000
--- a/include/asm-v850/v850e_uarta.h
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * include/asm-v850/v850e_uarta.h -- original V850E on-chip UART
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-/* This is the original V850E UART implementation is called just `UART' in
- the docs, but we name this header file <asm/v850e_uarta.h> because the
- name <asm/v850e_uart.h> is used for the common driver that handles both
- `UART' and `UARTB' implementations. */
-
-#ifndef __V850_V850E_UARTA_H__
-#define __V850_V850E_UARTA_H__
-
-
-/* Raw hardware interface. */
-
-/* The base address of the UART control registers for channel N.
- The default is the address used on the V850E/MA1. */
-#ifndef V850E_UART_BASE_ADDR
-#define V850E_UART_BASE_ADDR(n) (0xFFFFFA00 + 0x10 * (n))
-#endif
-
-/* Addresses of specific UART control registers for channel N.
- The defaults are the addresses used on the V850E/MA1; if a platform
- wants to redefine any of these, it must redefine them all. */
-#ifndef V850E_UART_ASIM_ADDR
-#define V850E_UART_ASIM_ADDR(n) (V850E_UART_BASE_ADDR(n) + 0x0)
-#define V850E_UART_RXB_ADDR(n) (V850E_UART_BASE_ADDR(n) + 0x2)
-#define V850E_UART_ASIS_ADDR(n) (V850E_UART_BASE_ADDR(n) + 0x3)
-#define V850E_UART_TXB_ADDR(n) (V850E_UART_BASE_ADDR(n) + 0x4)
-#define V850E_UART_ASIF_ADDR(n) (V850E_UART_BASE_ADDR(n) + 0x5)
-#define V850E_UART_CKSR_ADDR(n) (V850E_UART_BASE_ADDR(n) + 0x6)
-#define V850E_UART_BRGC_ADDR(n) (V850E_UART_BASE_ADDR(n) + 0x7)
-#endif
-
-/* UART config registers. */
-#define V850E_UART_ASIM(n) (*(volatile u8 *)V850E_UART_ASIM_ADDR(n))
-/* Control bits for config registers. */
-#define V850E_UART_ASIM_CAE 0x80 /* clock enable */
-#define V850E_UART_ASIM_TXE 0x40 /* transmit enable */
-#define V850E_UART_ASIM_RXE 0x20 /* receive enable */
-#define V850E_UART_ASIM_PS_MASK 0x18 /* mask covering parity-select bits */
-#define V850E_UART_ASIM_PS_NONE 0x00 /* no parity */
-#define V850E_UART_ASIM_PS_ZERO 0x08 /* zero parity */
-#define V850E_UART_ASIM_PS_ODD 0x10 /* odd parity */
-#define V850E_UART_ASIM_PS_EVEN 0x18 /* even parity */
-#define V850E_UART_ASIM_CL_8 0x04 /* char len is 8 bits (otherwise, 7) */
-#define V850E_UART_ASIM_SL_2 0x02 /* 2 stop bits (otherwise, 1) */
-#define V850E_UART_ASIM_ISRM 0x01 /* generate INTSR interrupt on errors
- (otherwise, generate INTSER) */
-
-/* UART serial interface status registers. */
-#define V850E_UART_ASIS(n) (*(volatile u8 *)V850E_UART_ASIS_ADDR(n))
-/* Control bits for status registers. */
-#define V850E_UART_ASIS_PE 0x04 /* parity error */
-#define V850E_UART_ASIS_FE 0x02 /* framing error */
-#define V850E_UART_ASIS_OVE 0x01 /* overrun error */
-
-/* UART serial interface transmission status registers. */
-#define V850E_UART_ASIF(n) (*(volatile u8 *)V850E_UART_ASIF_ADDR(n))
-#define V850E_UART_ASIF_TXBF 0x02 /* transmit buffer flag (data in TXB) */
-#define V850E_UART_ASIF_TXSF 0x01 /* transmit shift flag (sending data) */
-
-/* UART receive buffer register. */
-#define V850E_UART_RXB(n) (*(volatile u8 *)V850E_UART_RXB_ADDR(n))
-
-/* UART transmit buffer register. */
-#define V850E_UART_TXB(n) (*(volatile u8 *)V850E_UART_TXB_ADDR(n))
-
-/* UART baud-rate generator control registers. */
-#define V850E_UART_CKSR(n) (*(volatile u8 *)V850E_UART_CKSR_ADDR(n))
-#define V850E_UART_CKSR_MAX 11
-#define V850E_UART_BRGC(n) (*(volatile u8 *)V850E_UART_BRGC_ADDR(n))
-#define V850E_UART_BRGC_MIN 8
-
-
-#ifndef V850E_UART_CKSR_MAX_FREQ
-#define V850E_UART_CKSR_MAX_FREQ (25*1000*1000)
-#endif
-
-/* Calculate the minimum value for CKSR on this processor. */
-static inline unsigned v850e_uart_cksr_min (void)
-{
- int min = 0;
- unsigned freq = V850E_UART_BASE_FREQ;
- while (freq > V850E_UART_CKSR_MAX_FREQ) {
- freq >>= 1;
- min++;
- }
- return min;
-}
-
-
-/* Slightly abstract interface used by driver. */
-
-
-/* Interrupts used by the UART. */
-
-/* Received when the most recently transmitted character has been sent. */
-#define V850E_UART_TX_IRQ(chan) IRQ_INTST (chan)
-/* Received when a new character has been received. */
-#define V850E_UART_RX_IRQ(chan) IRQ_INTSR (chan)
-
-
-/* UART clock generator interface. */
-
-/* This type encapsulates a particular uart frequency. */
-typedef struct {
- unsigned clk_divlog2;
- unsigned brgen_count;
-} v850e_uart_speed_t;
-
-/* Calculate a uart speed from BAUD for this uart. */
-static inline v850e_uart_speed_t v850e_uart_calc_speed (unsigned baud)
-{
- v850e_uart_speed_t speed;
-
- /* Calculate the log2 clock divider and baud-rate counter values
- (note that the UART divides the resulting clock by 2, so
- multiply BAUD by 2 here to compensate). */
- calc_counter_params (V850E_UART_BASE_FREQ, baud * 2,
- v850e_uart_cksr_min(),
- V850E_UART_CKSR_MAX, 8/*bits*/,
- &speed.clk_divlog2, &speed.brgen_count);
-
- return speed;
-}
-
-/* Return the current speed of uart channel CHAN. */
-static inline v850e_uart_speed_t v850e_uart_speed (unsigned chan)
-{
- v850e_uart_speed_t speed;
- speed.clk_divlog2 = V850E_UART_CKSR (chan);
- speed.brgen_count = V850E_UART_BRGC (chan);
- return speed;
-}
-
-/* Set the current speed of uart channel CHAN. */
-static inline void v850e_uart_set_speed(unsigned chan,v850e_uart_speed_t speed)
-{
- V850E_UART_CKSR (chan) = speed.clk_divlog2;
- V850E_UART_BRGC (chan) = speed.brgen_count;
-}
-
-static inline int
-v850e_uart_speed_eq (v850e_uart_speed_t speed1, v850e_uart_speed_t speed2)
-{
- return speed1.clk_divlog2 == speed2.clk_divlog2
- && speed1.brgen_count == speed2.brgen_count;
-}
-
-/* Minimum baud rate possible. */
-#define v850e_uart_min_baud() \
- ((V850E_UART_BASE_FREQ >> V850E_UART_CKSR_MAX) / (2 * 255) + 1)
-
-/* Maximum baud rate possible. The error is quite high at max, though. */
-#define v850e_uart_max_baud() \
- ((V850E_UART_BASE_FREQ >> v850e_uart_cksr_min()) / (2 *V850E_UART_BRGC_MIN))
-
-/* The `maximum' clock rate the uart can used, which is wanted (though not
- really used in any useful way) by the serial framework. */
-#define v850e_uart_max_clock() \
- ((V850E_UART_BASE_FREQ >> v850e_uart_cksr_min()) / 2)
-
-
-/* UART configuration interface. */
-
-/* Type of the uart config register; must be a scalar. */
-typedef u16 v850e_uart_config_t;
-
-/* The uart hardware config register for channel CHAN. */
-#define V850E_UART_CONFIG(chan) V850E_UART_ASIM (chan)
-
-/* This config bit set if the uart is enabled. */
-#define V850E_UART_CONFIG_ENABLED V850E_UART_ASIM_CAE
-/* If the uart _isn't_ enabled, store this value to it to do so. */
-#define V850E_UART_CONFIG_INIT V850E_UART_ASIM_CAE
-/* Store this config value to disable the uart channel completely. */
-#define V850E_UART_CONFIG_FINI 0
-
-/* Setting/clearing these bits enable/disable TX/RX, respectively (but
- otherwise generally leave things running). */
-#define V850E_UART_CONFIG_RX_ENABLE V850E_UART_ASIM_RXE
-#define V850E_UART_CONFIG_TX_ENABLE V850E_UART_ASIM_TXE
-
-/* These masks define which config bits affect TX/RX modes, respectively. */
-#define V850E_UART_CONFIG_RX_BITS \
- (V850E_UART_ASIM_PS_MASK | V850E_UART_ASIM_CL_8 | V850E_UART_ASIM_ISRM)
-#define V850E_UART_CONFIG_TX_BITS \
- (V850E_UART_ASIM_PS_MASK | V850E_UART_ASIM_CL_8 | V850E_UART_ASIM_SL_2)
-
-static inline v850e_uart_config_t v850e_uart_calc_config (unsigned cflags)
-{
- v850e_uart_config_t config = 0;
-
- /* Figure out new configuration of control register. */
- if (cflags & CSTOPB)
- /* Number of stop bits, 1 or 2. */
- config |= V850E_UART_ASIM_SL_2;
- if ((cflags & CSIZE) == CS8)
- /* Number of data bits, 7 or 8. */
- config |= V850E_UART_ASIM_CL_8;
- if (! (cflags & PARENB))
- /* No parity check/generation. */
- config |= V850E_UART_ASIM_PS_NONE;
- else if (cflags & PARODD)
- /* Odd parity check/generation. */
- config |= V850E_UART_ASIM_PS_ODD;
- else
- /* Even parity check/generation. */
- config |= V850E_UART_ASIM_PS_EVEN;
- if (cflags & CREAD)
- /* Reading enabled. */
- config |= V850E_UART_ASIM_RXE;
-
- config |= V850E_UART_ASIM_CAE;
- config |= V850E_UART_ASIM_TXE; /* Writing is always enabled. */
- config |= V850E_UART_ASIM_ISRM; /* Errors generate a read-irq. */
-
- return config;
-}
-
-/* This should delay as long as necessary for a recently written config
- setting to settle, before we turn the uart back on. */
-static inline void
-v850e_uart_config_delay (v850e_uart_config_t config, v850e_uart_speed_t speed)
-{
- /* The UART may not be reset properly unless we wait at least 2
- `basic-clocks' until turning on the TXE/RXE bits again.
- A `basic clock' is the clock used by the baud-rate generator,
- i.e., the cpu clock divided by the 2^new_clk_divlog2.
- The loop takes 2 insns, so loop CYCLES / 2 times. */
- register unsigned count = 1 << speed.clk_divlog2;
- while (--count != 0)
- /* nothing */;
-}
-
-
-/* RX/TX interface. */
-
-/* Return true if all characters awaiting transmission on uart channel N
- have been transmitted. */
-#define v850e_uart_xmit_done(n) \
- (! (V850E_UART_ASIF(n) & V850E_UART_ASIF_TXBF))
-/* Wait for this to be true. */
-#define v850e_uart_wait_for_xmit_done(n) \
- do { } while (! v850e_uart_xmit_done (n))
-
-/* Return true if uart channel N is ready to transmit a character. */
-#define v850e_uart_xmit_ok(n) \
- (v850e_uart_xmit_done(n) && v850e_uart_cts(n))
-/* Wait for this to be true. */
-#define v850e_uart_wait_for_xmit_ok(n) \
- do { } while (! v850e_uart_xmit_ok (n))
-
-/* Write character CH to uart channel CHAN. */
-#define v850e_uart_putc(chan, ch) (V850E_UART_TXB(chan) = (ch))
-
-/* Return latest character read on channel CHAN. */
-#define v850e_uart_getc(chan) V850E_UART_RXB (chan)
-
-/* Return bit-mask of uart error status. */
-#define v850e_uart_err(chan) V850E_UART_ASIS (chan)
-/* Various error bits set in the error result. */
-#define V850E_UART_ERR_OVERRUN V850E_UART_ASIS_OVE
-#define V850E_UART_ERR_FRAME V850E_UART_ASIS_FE
-#define V850E_UART_ERR_PARITY V850E_UART_ASIS_PE
-
-
-#endif /* __V850_V850E_UARTA_H__ */
diff --git a/include/asm-v850/v850e_uartb.h b/include/asm-v850/v850e_uartb.h
deleted file mode 100644
index 6d4767d5a83..00000000000
--- a/include/asm-v850/v850e_uartb.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * include/asm-v850/v850e_uartb.h -- V850E on-chip `UARTB' UART
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-/* The V850E UARTB is basically a superset of the original V850E UART, but
- even where it's the same, the names and details have changed a bit.
- It's similar enough to use the same driver (v850e_uart.c), but the
- details have been abstracted slightly to do so. */
-
-#ifndef __V850_V850E_UARTB_H__
-#define __V850_V850E_UARTB_H__
-
-
-/* Raw hardware interface. */
-
-#define V850E_UARTB_BASE_ADDR(n) (0xFFFFFA00 + 0x10 * (n))
-
-/* Addresses of specific UART control registers for channel N. */
-#define V850E_UARTB_CTL0_ADDR(n) (V850E_UARTB_BASE_ADDR(n) + 0x0)
-#define V850E_UARTB_CTL2_ADDR(n) (V850E_UARTB_BASE_ADDR(n) + 0x2)
-#define V850E_UARTB_STR_ADDR(n) (V850E_UARTB_BASE_ADDR(n) + 0x4)
-#define V850E_UARTB_RX_ADDR(n) (V850E_UARTB_BASE_ADDR(n) + 0x6)
-#define V850E_UARTB_RXAP_ADDR(n) (V850E_UARTB_BASE_ADDR(n) + 0x6)
-#define V850E_UARTB_TX_ADDR(n) (V850E_UARTB_BASE_ADDR(n) + 0x8)
-#define V850E_UARTB_FIC0_ADDR(n) (V850E_UARTB_BASE_ADDR(n) + 0xA)
-#define V850E_UARTB_FIC1_ADDR(n) (V850E_UARTB_BASE_ADDR(n) + 0xB)
-#define V850E_UARTB_FIC2_ADDR(n) (V850E_UARTB_BASE_ADDR(n) + 0xC)
-#define V850E_UARTB_FIS0_ADDR(n) (V850E_UARTB_BASE_ADDR(n) + 0xE)
-#define V850E_UARTB_FIS1_ADDR(n) (V850E_UARTB_BASE_ADDR(n) + 0xF)
-
-/* UARTB control register 0 (general config). */
-#define V850E_UARTB_CTL0(n) (*(volatile u8 *)V850E_UARTB_CTL0_ADDR(n))
-/* Control bits for config registers. */
-#define V850E_UARTB_CTL0_PWR 0x80 /* clock enable */
-#define V850E_UARTB_CTL0_TXE 0x40 /* transmit enable */
-#define V850E_UARTB_CTL0_RXE 0x20 /* receive enable */
-#define V850E_UARTB_CTL0_DIR 0x10 /* */
-#define V850E_UARTB_CTL0_PS1 0x08 /* parity */
-#define V850E_UARTB_CTL0_PS0 0x04 /* parity */
-#define V850E_UARTB_CTL0_CL 0x02 /* char len 1:8bit, 0:7bit */
-#define V850E_UARTB_CTL0_SL 0x01 /* stop bit 1:2bit, 0:1bit */
-#define V850E_UARTB_CTL0_PS_MASK 0x0C /* mask covering parity bits */
-#define V850E_UARTB_CTL0_PS_NONE 0x00 /* no parity */
-#define V850E_UARTB_CTL0_PS_ZERO 0x04 /* zero parity */
-#define V850E_UARTB_CTL0_PS_ODD 0x08 /* odd parity */
-#define V850E_UARTB_CTL0_PS_EVEN 0x0C /* even parity */
-#define V850E_UARTB_CTL0_CL_8 0x02 /* char len 1:8bit, 0:7bit */
-#define V850E_UARTB_CTL0_SL_2 0x01 /* stop bit 1:2bit, 0:1bit */
-
-/* UARTB control register 2 (clock divider). */
-#define V850E_UARTB_CTL2(n) (*(volatile u16 *)V850E_UARTB_CTL2_ADDR(n))
-#define V850E_UARTB_CTL2_MIN 4
-#define V850E_UARTB_CTL2_MAX 0xFFFF
-
-/* UARTB serial interface status register. */
-#define V850E_UARTB_STR(n) (*(volatile u8 *)V850E_UARTB_STR_ADDR(n))
-/* Control bits for status registers. */
-#define V850E_UARTB_STR_TSF 0x80 /* UBTX or FIFO exist data */
-#define V850E_UARTB_STR_OVF 0x08 /* overflow error */
-#define V850E_UARTB_STR_PE 0x04 /* parity error */
-#define V850E_UARTB_STR_FE 0x02 /* framing error */
-#define V850E_UARTB_STR_OVE 0x01 /* overrun error */
-
-/* UARTB receive data register. */
-#define V850E_UARTB_RX(n) (*(volatile u8 *)V850E_UARTB_RX_ADDR(n))
-#define V850E_UARTB_RXAP(n) (*(volatile u16 *)V850E_UARTB_RXAP_ADDR(n))
-/* Control bits for status registers. */
-#define V850E_UARTB_RXAP_PEF 0x0200 /* parity error */
-#define V850E_UARTB_RXAP_FEF 0x0100 /* framing error */
-
-/* UARTB transmit data register. */
-#define V850E_UARTB_TX(n) (*(volatile u8 *)V850E_UARTB_TX_ADDR(n))
-
-/* UARTB FIFO control register 0. */
-#define V850E_UARTB_FIC0(n) (*(volatile u8 *)V850E_UARTB_FIC0_ADDR(n))
-
-/* UARTB FIFO control register 1. */
-#define V850E_UARTB_FIC1(n) (*(volatile u8 *)V850E_UARTB_FIC1_ADDR(n))
-
-/* UARTB FIFO control register 2. */
-#define V850E_UARTB_FIC2(n) (*(volatile u16 *)V850E_UARTB_FIC2_ADDR(n))
-
-/* UARTB FIFO status register 0. */
-#define V850E_UARTB_FIS0(n) (*(volatile u8 *)V850E_UARTB_FIS0_ADDR(n))
-
-/* UARTB FIFO status register 1. */
-#define V850E_UARTB_FIS1(n) (*(volatile u8 *)V850E_UARTB_FIS1_ADDR(n))
-
-
-/* Slightly abstract interface used by driver. */
-
-
-/* Interrupts used by the UART. */
-
-/* Received when the most recently transmitted character has been sent. */
-#define V850E_UART_TX_IRQ(chan) IRQ_INTUBTIT (chan)
-/* Received when a new character has been received. */
-#define V850E_UART_RX_IRQ(chan) IRQ_INTUBTIR (chan)
-
-/* Use by serial driver for information purposes. */
-#define V850E_UART_BASE_ADDR(chan) V850E_UARTB_BASE_ADDR(chan)
-
-
-/* UART clock generator interface. */
-
-/* This type encapsulates a particular uart frequency. */
-typedef u16 v850e_uart_speed_t;
-
-/* Calculate a uart speed from BAUD for this uart. */
-static inline v850e_uart_speed_t v850e_uart_calc_speed (unsigned baud)
-{
- v850e_uart_speed_t speed;
-
- /*
- * V850E/ME2 UARTB baud rate is determined by the value of UBCTL2
- * fx = V850E_UARTB_BASE_FREQ = CPU_CLOCK_FREQ/4
- * baud = fx / 2*speed [ speed >= 4 ]
- */
- speed = V850E_UARTB_CTL2_MIN;
- while (((V850E_UARTB_BASE_FREQ / 2) / speed ) > baud)
- speed++;
-
- return speed;
-}
-
-/* Return the current speed of uart channel CHAN. */
-#define v850e_uart_speed(chan) V850E_UARTB_CTL2 (chan)
-
-/* Set the current speed of uart channel CHAN. */
-#define v850e_uart_set_speed(chan, speed) (V850E_UARTB_CTL2 (chan) = (speed))
-
-/* Return true if SPEED1 and SPEED2 are the same. */
-#define v850e_uart_speed_eq(speed1, speed2) ((speed1) == (speed2))
-
-/* Minimum baud rate possible. */
-#define v850e_uart_min_baud() \
- ((V850E_UARTB_BASE_FREQ / 2) / V850E_UARTB_CTL2_MAX)
-
-/* Maximum baud rate possible. The error is quite high at max, though. */
-#define v850e_uart_max_baud() \
- ((V850E_UARTB_BASE_FREQ / 2) / V850E_UARTB_CTL2_MIN)
-
-/* The `maximum' clock rate the uart can used, which is wanted (though not
- really used in any useful way) by the serial framework. */
-#define v850e_uart_max_clock() \
- (V850E_UARTB_BASE_FREQ / 2)
-
-
-/* UART configuration interface. */
-
-/* Type of the uart config register; must be a scalar. */
-typedef u16 v850e_uart_config_t;
-
-/* The uart hardware config register for channel CHAN. */
-#define V850E_UART_CONFIG(chan) V850E_UARTB_CTL0 (chan)
-
-/* This config bit set if the uart is enabled. */
-#define V850E_UART_CONFIG_ENABLED V850E_UARTB_CTL0_PWR
-/* If the uart _isn't_ enabled, store this value to it to do so. */
-#define V850E_UART_CONFIG_INIT V850E_UARTB_CTL0_PWR
-/* Store this config value to disable the uart channel completely. */
-#define V850E_UART_CONFIG_FINI 0
-
-/* Setting/clearing these bits enable/disable TX/RX, respectively (but
- otherwise generally leave things running). */
-#define V850E_UART_CONFIG_RX_ENABLE V850E_UARTB_CTL0_RXE
-#define V850E_UART_CONFIG_TX_ENABLE V850E_UARTB_CTL0_TXE
-
-/* These masks define which config bits affect TX/RX modes, respectively. */
-#define V850E_UART_CONFIG_RX_BITS \
- (V850E_UARTB_CTL0_PS_MASK | V850E_UARTB_CTL0_CL_8)
-#define V850E_UART_CONFIG_TX_BITS \
- (V850E_UARTB_CTL0_PS_MASK | V850E_UARTB_CTL0_CL_8 | V850E_UARTB_CTL0_SL_2)
-
-static inline v850e_uart_config_t v850e_uart_calc_config (unsigned cflags)
-{
- v850e_uart_config_t config = 0;
-
- /* Figure out new configuration of control register. */
- if (cflags & CSTOPB)
- /* Number of stop bits, 1 or 2. */
- config |= V850E_UARTB_CTL0_SL_2;
- if ((cflags & CSIZE) == CS8)
- /* Number of data bits, 7 or 8. */
- config |= V850E_UARTB_CTL0_CL_8;
- if (! (cflags & PARENB))
- /* No parity check/generation. */
- config |= V850E_UARTB_CTL0_PS_NONE;
- else if (cflags & PARODD)
- /* Odd parity check/generation. */
- config |= V850E_UARTB_CTL0_PS_ODD;
- else
- /* Even parity check/generation. */
- config |= V850E_UARTB_CTL0_PS_EVEN;
- if (cflags & CREAD)
- /* Reading enabled. */
- config |= V850E_UARTB_CTL0_RXE;
-
- config |= V850E_UARTB_CTL0_PWR;
- config |= V850E_UARTB_CTL0_TXE; /* Writing is always enabled. */
- config |= V850E_UARTB_CTL0_DIR; /* LSB first. */
-
- return config;
-}
-
-/* This should delay as long as necessary for a recently written config
- setting to settle, before we turn the uart back on. */
-static inline void
-v850e_uart_config_delay (v850e_uart_config_t config, v850e_uart_speed_t speed)
-{
- /* The UART may not be reset properly unless we wait at least 2
- `basic-clocks' until turning on the TXE/RXE bits again.
- A `basic clock' is the clock used by the baud-rate generator,
- i.e., the cpu clock divided by the 2^new_clk_divlog2.
- The loop takes 2 insns, so loop CYCLES / 2 times. */
- register unsigned count = 1 << speed;
- while (--count != 0)
- /* nothing */;
-}
-
-
-/* RX/TX interface. */
-
-/* Return true if all characters awaiting transmission on uart channel N
- have been transmitted. */
-#define v850e_uart_xmit_done(n) \
- (! (V850E_UARTB_STR(n) & V850E_UARTB_STR_TSF))
-/* Wait for this to be true. */
-#define v850e_uart_wait_for_xmit_done(n) \
- do { } while (! v850e_uart_xmit_done (n))
-
-/* Return true if uart channel N is ready to transmit a character. */
-#define v850e_uart_xmit_ok(n) \
- (v850e_uart_xmit_done(n) && v850e_uart_cts(n))
-/* Wait for this to be true. */
-#define v850e_uart_wait_for_xmit_ok(n) \
- do { } while (! v850e_uart_xmit_ok (n))
-
-/* Write character CH to uart channel CHAN. */
-#define v850e_uart_putc(chan, ch) (V850E_UARTB_TX(chan) = (ch))
-
-/* Return latest character read on channel CHAN. */
-#define v850e_uart_getc(chan) V850E_UARTB_RX (chan)
-
-/* Return bit-mask of uart error status. */
-#define v850e_uart_err(chan) V850E_UARTB_STR (chan)
-/* Various error bits set in the error result. */
-#define V850E_UART_ERR_OVERRUN V850E_UARTB_STR_OVE
-#define V850E_UART_ERR_FRAME V850E_UARTB_STR_FE
-#define V850E_UART_ERR_PARITY V850E_UARTB_STR_PE
-
-
-#endif /* __V850_V850E_UARTB_H__ */
diff --git a/include/asm-v850/v850e_utils.h b/include/asm-v850/v850e_utils.h
deleted file mode 100644
index 52eb72822d3..00000000000
--- a/include/asm-v850/v850e_utils.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * include/asm-v850/v850e_utils.h -- Utility functions associated with
- * V850E CPUs
- *
- * Copyright (C) 2001,03 NEC Electronics Corporation
- * Copyright (C) 2001,03 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
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_V850E_UTILS_H__
-#define __V850_V850E_UTILS_H__
-
-/* Calculate counter clock-divider and count values to attain the
- desired frequency RATE from the base frequency BASE_FREQ. The
- counter is expected to have a clock-divider, which can divide the
- system cpu clock by a power of two value from MIN_DIVLOG2 to
- MAX_DIV_LOG2, and a word-size of COUNTER_SIZE bits (the counter
- counts up and resets whenever it's equal to the compare register,
- generating an interrupt or whatever when it does so). The returned
- values are: *DIVLOG2 -- log2 of the desired clock divider and *COUNT
- -- the counter compare value to use. Returns true if it was possible
- to find a reasonable value, otherwise false (and the other return
- values will be set to be as good as possible). */
-extern int calc_counter_params (unsigned long base_freq,
- unsigned long rate,
- unsigned min_divlog2, unsigned max_divlog2,
- unsigned counter_size,
- unsigned *divlog2, unsigned *count);
-
-#endif /* __V850_V850E_UTILS_H__ */
diff --git a/include/asm-x86/Kbuild b/include/asm-x86/Kbuild
index 1e3554596f7..4a8e80cdcfa 100644
--- a/include/asm-x86/Kbuild
+++ b/include/asm-x86/Kbuild
@@ -3,7 +3,6 @@ include include/asm-generic/Kbuild.asm
header-y += boot.h
header-y += bootparam.h
header-y += debugreg.h
-header-y += kvm.h
header-y += ldt.h
header-y += msr-index.h
header-y += prctl.h
@@ -19,7 +18,6 @@ unifdef-y += msr.h
unifdef-y += mtrr.h
unifdef-y += posix_types_32.h
unifdef-y += posix_types_64.h
-unifdef-y += ptrace.h
unifdef-y += unistd_32.h
unifdef-y += unistd_64.h
unifdef-y += vm86.h
diff --git a/include/asm-x86/gpio.h b/include/asm-x86/gpio.h
index f269ff9cd40..f9e8f8918a9 100644
--- a/include/asm-x86/gpio.h
+++ b/include/asm-x86/gpio.h
@@ -1,6 +1,62 @@
-#ifndef ASM_X86__GPIO_H
-#define ASM_X86__GPIO_H
+/*
+ * Generic GPIO API implementation for x86.
+ *
+ * Derived from the generic GPIO API for powerpc:
+ *
+ * Copyright (c) 2007-2008 MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.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.
+ */
+#ifndef _ASM_I386_GPIO_H
+#define _ASM_I386_GPIO_H
+
+#ifdef CONFIG_X86_RDC321X
#include <gpio.h>
+#else /* CONFIG_X86_RDC321X */
+
+#include <asm-generic/gpio.h>
+
+#ifdef CONFIG_GPIOLIB
+
+/*
+ * Just call gpiolib.
+ */
+static inline int gpio_get_value(unsigned int gpio)
+{
+ return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned int gpio, int value)
+{
+ __gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned int gpio)
+{
+ return __gpio_cansleep(gpio);
+}
+
+/*
+ * Not implemented, yet.
+ */
+static inline int gpio_to_irq(unsigned int gpio)
+{
+ return -ENOSYS;
+}
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+ return -EINVAL;
+}
+
+#endif /* CONFIG_GPIOLIB */
+
+#endif /* CONFIG_X86_RDC321X */
#endif /* ASM_X86__GPIO_H */
diff --git a/include/asm-x86/hugetlb.h b/include/asm-x86/hugetlb.h
index 0e0a0828182..0b7ec5dc088 100644
--- a/include/asm-x86/hugetlb.h
+++ b/include/asm-x86/hugetlb.h
@@ -14,11 +14,13 @@ static inline int is_hugepage_only_range(struct mm_struct *mm,
* If the arch doesn't supply something else, assume that hugepage
* size aligned regions are ok without further preparation.
*/
-static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+static inline int prepare_hugepage_range(struct file *file,
+ unsigned long addr, unsigned long len)
{
- if (len & ~HPAGE_MASK)
+ struct hstate *h = hstate_file(file);
+ if (len & ~huge_page_mask(h))
return -EINVAL;
- if (addr & ~HPAGE_MASK)
+ if (addr & ~huge_page_mask(h))
return -EINVAL;
return 0;
}
@@ -26,7 +28,7 @@ static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm) {
}
-static inline void hugetlb_free_pgd_range(struct mmu_gather **tlb,
+static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
unsigned long addr, unsigned long end,
unsigned long floor,
unsigned long ceiling)
diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h
index 3e83cbb728a..6f60a6b8997 100644
--- a/include/asm-x86/i387.h
+++ b/include/asm-x86/i387.h
@@ -137,60 +137,6 @@ static inline void __save_init_fpu(struct task_struct *tsk)
task_thread_info(tsk)->status &= ~TS_USEDFPU;
}
-/*
- * Signal frame handlers.
- */
-
-static inline int save_i387(struct _fpstate __user *buf)
-{
- struct task_struct *tsk = current;
- int err = 0;
-
- BUILD_BUG_ON(sizeof(struct user_i387_struct) !=
- sizeof(tsk->thread.xstate->fxsave));
-
- if ((unsigned long)buf % 16)
- printk("save_i387: bad fpstate %p\n", buf);
-
- if (!used_math())
- return 0;
- clear_used_math(); /* trigger finit */
- if (task_thread_info(tsk)->status & TS_USEDFPU) {
- err = save_i387_checking((struct i387_fxsave_struct __user *)
- buf);
- if (err)
- return err;
- task_thread_info(tsk)->status &= ~TS_USEDFPU;
- stts();
- } else {
- if (__copy_to_user(buf, &tsk->thread.xstate->fxsave,
- sizeof(struct i387_fxsave_struct)))
- return -1;
- }
- return 1;
-}
-
-/*
- * This restores directly out of user space. Exceptions are handled.
- */
-static inline int restore_i387(struct _fpstate __user *buf)
-{
- struct task_struct *tsk = current;
- int err;
-
- if (!used_math()) {
- err = init_fpu(tsk);
- if (err)
- return err;
- }
-
- if (!(task_thread_info(current)->status & TS_USEDFPU)) {
- clts();
- task_thread_info(current)->status |= TS_USEDFPU;
- }
- return restore_fpu_checking((__force struct i387_fxsave_struct *)buf);
-}
-
#else /* CONFIG_X86_32 */
extern void finit(void);
diff --git a/include/asm-x86/ide.h b/include/asm-x86/ide.h
deleted file mode 100644
index 8bf3cdc6bb4..00000000000
--- a/include/asm-x86/ide.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 1994-1996 Linus Torvalds & authors
- */
-
-/*
- * This file contains the i386 architecture specific IDE code.
- */
-
-#ifndef ASM_X86__IDE_H
-#define ASM_X86__IDE_H
-
-#ifdef __KERNEL__
-
-
-#ifndef MAX_HWIFS
-# ifdef CONFIG_BLK_DEV_IDEPCI
-#define MAX_HWIFS 10
-# else
-#define MAX_HWIFS 6
-# endif
-#endif
-
-static __inline__ int ide_default_irq(unsigned long base)
-{
- switch (base) {
- case 0x1f0: return 14;
- case 0x170: return 15;
- case 0x1e8: return 11;
- case 0x168: return 10;
- case 0x1e0: return 8;
- case 0x160: return 12;
- default:
- return 0;
- }
-}
-
-static __inline__ unsigned long ide_default_io_base(int index)
-{
- /*
- * If PCI is present then it is not safe to poke around
- * the other legacy IDE ports. Only 0x1f0 and 0x170 are
- * defined compatibility mode ports for PCI. A user can
- * override this using ide= but we must default safe.
- */
- if (no_pci_devices()) {
- switch(index) {
- case 2: return 0x1e8;
- case 3: return 0x168;
- case 4: return 0x1e0;
- case 5: return 0x160;
- }
- }
- switch (index) {
- case 0: return 0x1f0;
- case 1: return 0x170;
- default:
- return 0;
- }
-}
-
-#include <asm-generic/ide_iops.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* ASM_X86__IDE_H */
diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
index d9d1e3f269a..4f7d878bda1 100644
--- a/include/asm-x86/io_32.h
+++ b/include/asm-x86/io_32.h
@@ -110,6 +110,8 @@ static inline void *phys_to_virt(unsigned long address)
*/
extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size);
extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size);
+extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size,
+ unsigned long prot_val);
/*
* The default ioremap() behavior is non-cached:
diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h
index 00ac4729e52..f436532f193 100644
--- a/include/asm-x86/io_64.h
+++ b/include/asm-x86/io_64.h
@@ -175,6 +175,8 @@ extern void early_iounmap(void *addr, unsigned long size);
*/
extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size);
extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size);
+extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size,
+ unsigned long prot_val);
/*
* The default ioremap() behavior is non-cached:
diff --git a/include/asm-x86/ipi.h b/include/asm-x86/ipi.h
index 63390ea87d1..c1b22679751 100644
--- a/include/asm-x86/ipi.h
+++ b/include/asm-x86/ipi.h
@@ -122,7 +122,7 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
* - mbligh
*/
local_irq_save(flags);
- for_each_cpu_mask(query_cpu, mask) {
+ for_each_cpu_mask_nr(query_cpu, mask) {
__send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, query_cpu),
vector, APIC_DEST_PHYSICAL);
}
diff --git a/include/asm-x86/page.h b/include/asm-x86/page.h
index 068a636e0bb..79544e6ffb8 100644
--- a/include/asm-x86/page.h
+++ b/include/asm-x86/page.h
@@ -18,8 +18,11 @@
(ie, 32-bit PAE). */
#define PHYSICAL_PAGE_MASK (((signed long)PAGE_MASK) & __PHYSICAL_MASK)
-/* PTE_MASK extracts the PFN from a (pte|pmd|pud|pgd)val_t */
-#define PTE_MASK ((pteval_t)PHYSICAL_PAGE_MASK)
+/* PTE_PFN_MASK extracts the PFN from a (pte|pmd|pud|pgd)val_t */
+#define PTE_PFN_MASK ((pteval_t)PHYSICAL_PAGE_MASK)
+
+/* PTE_FLAGS_MASK extracts the flags from a (pte|pmd|pud|pgd)val_t */
+#define PTE_FLAGS_MASK (~PTE_PFN_MASK)
#define PMD_PAGE_SIZE (_AC(1, UL) << PMD_SHIFT)
#define PMD_PAGE_MASK (~(PMD_PAGE_SIZE-1))
@@ -29,8 +32,7 @@
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
+#define HUGE_MAX_HSTATE 2
#ifndef __ASSEMBLY__
#include <linux/types.h>
@@ -144,6 +146,11 @@ static inline pteval_t native_pte_val(pte_t pte)
return pte.pte;
}
+static inline pteval_t native_pte_flags(pte_t pte)
+{
+ return native_pte_val(pte) & PTE_FLAGS_MASK;
+}
+
#define pgprot_val(x) ((x).pgprot)
#define __pgprot(x) ((pgprot_t) { (x) } )
@@ -165,7 +172,7 @@ static inline pteval_t native_pte_val(pte_t pte)
#endif
#define pte_val(x) native_pte_val(x)
-#define pte_flags(x) native_pte_val(x)
+#define pte_flags(x) native_pte_flags(x)
#define __pte(x) native_make_pte(x)
#endif /* CONFIG_PARAVIRT */
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index 1b7eff0b41b..2e6821a0b6e 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -1088,6 +1088,9 @@ static inline pteval_t pte_flags(pte_t pte)
ret = PVOP_CALL1(pteval_t, pv_mmu_ops.pte_flags,
pte.pte);
+#ifdef CONFIG_PARAVIRT_DEBUG
+ BUG_ON(ret & PTE_PFN_MASK);
+#endif
return ret;
}
diff --git a/include/asm-x86/pgtable-3level.h b/include/asm-x86/pgtable-3level.h
index a9ad971a733..e713bd5f39a 100644
--- a/include/asm-x86/pgtable-3level.h
+++ b/include/asm-x86/pgtable-3level.h
@@ -25,7 +25,7 @@ static inline int pud_none(pud_t pud)
static inline int pud_bad(pud_t pud)
{
- return (pud_val(pud) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER)) != 0;
+ return (pud_val(pud) & ~(PTE_PFN_MASK | _KERNPG_TABLE | _PAGE_USER)) != 0;
}
static inline int pud_present(pud_t pud)
@@ -120,9 +120,9 @@ static inline void pud_clear(pud_t *pudp)
write_cr3(pgd);
}
-#define pud_page(pud) ((struct page *) __va(pud_val(pud) & PTE_MASK))
+#define pud_page(pud) ((struct page *) __va(pud_val(pud) & PTE_PFN_MASK))
-#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PTE_MASK))
+#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PTE_PFN_MASK))
/* Find an entry in the second-level page table.. */
@@ -160,7 +160,7 @@ static inline int pte_none(pte_t pte)
static inline unsigned long pte_pfn(pte_t pte)
{
- return (pte_val(pte) & PTE_MASK) >> PAGE_SHIFT;
+ return (pte_val(pte) & PTE_PFN_MASK) >> PAGE_SHIFT;
}
/*
diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h
index b8d7c530054..3ca03f902e0 100644
--- a/include/asm-x86/pgtable.h
+++ b/include/asm-x86/pgtable.h
@@ -53,7 +53,7 @@
_PAGE_DIRTY)
/* Set of bits not changed in pte_modify */
-#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_PCD | _PAGE_PWT | \
+#define _PAGE_CHG_MASK (PTE_PFN_MASK | _PAGE_PCD | _PAGE_PWT | \
_PAGE_ACCESSED | _PAGE_DIRTY)
#define _PAGE_CACHE_MASK (_PAGE_PCD | _PAGE_PWT)
@@ -286,7 +286,7 @@ static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
return __pgprot(preservebits | addbits);
}
-#define pte_pgprot(x) __pgprot(pte_flags(x) & ~PTE_MASK)
+#define pte_pgprot(x) __pgprot(pte_flags(x) & PTE_FLAGS_MASK)
#define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask)
diff --git a/include/asm-x86/pgtable_32.h b/include/asm-x86/pgtable_32.h
index 4fa3b046e1b..bbc136f3ac5 100644
--- a/include/asm-x86/pgtable_32.h
+++ b/include/asm-x86/pgtable_32.h
@@ -88,7 +88,7 @@ extern unsigned long pg0[];
/* To avoid harmful races, pmd_none(x) should check only the lower when PAE */
#define pmd_none(x) (!(unsigned long)pmd_val((x)))
#define pmd_present(x) (pmd_val((x)) & _PAGE_PRESENT)
-#define pmd_bad(x) ((pmd_val(x) & (~PTE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
+#define pmd_bad(x) ((pmd_val(x) & (PTE_FLAGS_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
@@ -139,7 +139,7 @@ static inline int pud_large(pud_t pud) { return 0; }
#define pmd_page(pmd) (pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT))
#define pmd_page_vaddr(pmd) \
- ((unsigned long)__va(pmd_val((pmd)) & PTE_MASK))
+ ((unsigned long)__va(pmd_val((pmd)) & PTE_PFN_MASK))
#if defined(CONFIG_HIGHPTE)
#define pte_offset_map(dir, address) \
diff --git a/include/asm-x86/pgtable_64.h b/include/asm-x86/pgtable_64.h
index b80c0d7658c..609c24975c6 100644
--- a/include/asm-x86/pgtable_64.h
+++ b/include/asm-x86/pgtable_64.h
@@ -158,17 +158,17 @@ static inline void native_pgd_clear(pgd_t *pgd)
static inline int pgd_bad(pgd_t pgd)
{
- return (pgd_val(pgd) & ~(PTE_MASK | _PAGE_USER)) != _KERNPG_TABLE;
+ return (pgd_val(pgd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE;
}
static inline int pud_bad(pud_t pud)
{
- return (pud_val(pud) & ~(PTE_MASK | _PAGE_USER)) != _KERNPG_TABLE;
+ return (pud_val(pud) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE;
}
static inline int pmd_bad(pmd_t pmd)
{
- return (pmd_val(pmd) & ~(PTE_MASK | _PAGE_USER)) != _KERNPG_TABLE;
+ return (pmd_val(pmd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE;
}
#define pte_none(x) (!pte_val((x)))
@@ -193,7 +193,7 @@ static inline int pmd_bad(pmd_t pmd)
* Level 4 access.
*/
#define pgd_page_vaddr(pgd) \
- ((unsigned long)__va((unsigned long)pgd_val((pgd)) & PTE_MASK))
+ ((unsigned long)__va((unsigned long)pgd_val((pgd)) & PTE_PFN_MASK))
#define pgd_page(pgd) (pfn_to_page(pgd_val((pgd)) >> PAGE_SHIFT))
#define pgd_present(pgd) (pgd_val(pgd) & _PAGE_PRESENT)
static inline int pgd_large(pgd_t pgd) { return 0; }
@@ -216,7 +216,7 @@ static inline int pud_large(pud_t pte)
}
/* PMD - Level 2 access */
-#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val((pmd)) & PTE_MASK))
+#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val((pmd)) & PTE_PFN_MASK))
#define pmd_page(pmd) (pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT))
#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
diff --git a/include/asm-x86/processor-flags.h b/include/asm-x86/processor-flags.h
index ae1d434f197..5dd79774f69 100644
--- a/include/asm-x86/processor-flags.h
+++ b/include/asm-x86/processor-flags.h
@@ -88,10 +88,12 @@
#define CX86_ARR_BASE 0xc4
#define CX86_RCR_BASE 0xdc
+#ifdef __KERNEL__
#ifdef CONFIG_VM86
#define X86_VM_MASK X86_EFLAGS_VM
#else
#define X86_VM_MASK 0 /* No VM86 support */
#endif
+#endif
#endif /* ASM_X86__PROCESSOR_FLAGS_H */
diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h
index a9a28baef69..d60b4d81feb 100644
--- a/include/asm-x86/processor.h
+++ b/include/asm-x86/processor.h
@@ -134,7 +134,7 @@ extern __u32 cleared_cpu_caps[NCAPINTS];
#ifdef CONFIG_SMP
DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
#define cpu_data(cpu) per_cpu(cpu_info, cpu)
-#define current_cpu_data cpu_data(smp_processor_id())
+#define current_cpu_data __get_cpu_var(cpu_info)
#else
#define cpu_data(cpu) boot_cpu_data
#define current_cpu_data boot_cpu_data
diff --git a/include/asm-x86/semaphore.h b/include/asm-x86/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-x86/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-x86/thread_info.h b/include/asm-x86/thread_info.h
index 50315a5dd18..e64be8863b7 100644
--- a/include/asm-x86/thread_info.h
+++ b/include/asm-x86/thread_info.h
@@ -79,7 +79,6 @@ struct thread_info {
#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
#define TIF_SECCOMP 8 /* secure computing */
#define TIF_MCE_NOTIFY 10 /* notify userspace of an MCE */
-#define TIF_HRTICK_RESCHED 11 /* reprogram hrtick timer */
#define TIF_NOTSC 16 /* TSC is not accessible in userland */
#define TIF_IA32 17 /* 32bit process */
#define TIF_FORK 18 /* ret_from_fork */
@@ -102,7 +101,6 @@ struct thread_info {
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
#define _TIF_MCE_NOTIFY (1 << TIF_MCE_NOTIFY)
-#define _TIF_HRTICK_RESCHED (1 << TIF_HRTICK_RESCHED)
#define _TIF_NOTSC (1 << TIF_NOTSC)
#define _TIF_IA32 (1 << TIF_IA32)
#define _TIF_FORK (1 << TIF_FORK)
@@ -135,7 +133,7 @@ struct thread_info {
/* Only used for 64 bit */
#define _TIF_DO_NOTIFY_MASK \
- (_TIF_SIGPENDING|_TIF_MCE_NOTIFY|_TIF_HRTICK_RESCHED)
+ (_TIF_SIGPENDING|_TIF_MCE_NOTIFY)
/* flags to check in __switch_to() */
#define _TIF_WORK_CTXSW \
@@ -154,6 +152,8 @@ struct thread_info {
#define THREAD_FLAGS GFP_KERNEL
#endif
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+
#define alloc_thread_info(tsk) \
((struct thread_info *)__get_free_pages(THREAD_FLAGS, THREAD_ORDER))
diff --git a/include/asm-x86/unistd_32.h b/include/asm-x86/unistd_32.h
index 602ddd88c68..017f4a87c91 100644
--- a/include/asm-x86/unistd_32.h
+++ b/include/asm-x86/unistd_32.h
@@ -332,6 +332,12 @@
#define __NR_fallocate 324
#define __NR_timerfd_settime 325
#define __NR_timerfd_gettime 326
+#define __NR_signalfd4 327
+#define __NR_eventfd2 328
+#define __NR_epoll_create1 329
+#define __NR_dup3 330
+#define __NR_pipe2 331
+#define __NR_inotify_init1 332
#ifdef __KERNEL__
diff --git a/include/asm-x86/unistd_64.h b/include/asm-x86/unistd_64.h
index 1e10189ed6b..ace83f1f678 100644
--- a/include/asm-x86/unistd_64.h
+++ b/include/asm-x86/unistd_64.h
@@ -639,6 +639,20 @@ __SYSCALL(__NR_fallocate, sys_fallocate)
__SYSCALL(__NR_timerfd_settime, sys_timerfd_settime)
#define __NR_timerfd_gettime 287
__SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime)
+#define __NR_paccept 288
+__SYSCALL(__NR_paccept, sys_paccept)
+#define __NR_signalfd4 289
+__SYSCALL(__NR_signalfd4, sys_signalfd4)
+#define __NR_eventfd2 290
+__SYSCALL(__NR_eventfd2, sys_eventfd2)
+#define __NR_epoll_create1 291
+__SYSCALL(__NR_epoll_create1, sys_epoll_create1)
+#define __NR_dup3 292
+__SYSCALL(__NR_dup3, sys_dup3)
+#define __NR_pipe2 293
+__SYSCALL(__NR_pipe2, sys_pipe2)
+#define __NR_inotify_init1 294
+__SYSCALL(__NR_inotify_init1, sys_inotify_init1)
#ifndef __NO_STUBS
diff --git a/include/asm-x86/xen/page.h b/include/asm-x86/xen/page.h
index a17a86433c7..c50185dccec 100644
--- a/include/asm-x86/xen/page.h
+++ b/include/asm-x86/xen/page.h
@@ -124,7 +124,7 @@ static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
static inline unsigned long pte_mfn(pte_t pte)
{
- return (pte.pte & PTE_MASK) >> PAGE_SHIFT;
+ return (pte.pte & PTE_PFN_MASK) >> PAGE_SHIFT;
}
static inline pte_t mfn_pte(unsigned long page_nr, pgprot_t pgprot)
diff --git a/include/asm-xtensa/ide.h b/include/asm-xtensa/ide.h
deleted file mode 100644
index 6b912742a42..00000000000
--- a/include/asm-xtensa/ide.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * include/asm-xtensa/ide.h
- *
- * 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.
- *
- * Copyright (C) 1994 - 1996 Linus Torvalds & authors
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_IDE_H
-#define _XTENSA_IDE_H
-
-#ifdef __KERNEL__
-
-
-#ifndef MAX_HWIFS
-# define MAX_HWIFS 1
-#endif
-
-static __inline__ int ide_default_irq(unsigned long base)
-{
- /* Unsupported! */
- return 0;
-}
-
-static __inline__ unsigned long ide_default_io_base(int index)
-{
- /* Unsupported! */
- return 0;
-}
-
-#endif /* __KERNEL__ */
-#endif /* _XTENSA_IDE_H */
diff --git a/include/asm-xtensa/kvm.h b/include/asm-xtensa/kvm.h
deleted file mode 100644
index bda4e331e98..00000000000
--- a/include/asm-xtensa/kvm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __LINUX_KVM_XTENSA_H
-#define __LINUX_KVM_XTENSA_H
-
-/* xtensa does not support KVM */
-
-#endif
diff --git a/include/asm-xtensa/page.h b/include/asm-xtensa/page.h
index 80a6ae0dd25..11f7dc2dbec 100644
--- a/include/asm-xtensa/page.h
+++ b/include/asm-xtensa/page.h
@@ -26,13 +26,11 @@
/*
* PAGE_SHIFT determines the page size
- * PAGE_ALIGN(x) aligns the pointer to the (next) page boundary
*/
#define PAGE_SHIFT 12
#define PAGE_SIZE (__XTENSA_UL_CONST(1) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE - 1) & PAGE_MASK)
#define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR
#define MAX_MEM_PFN XCHAL_KSEG_SIZE
diff --git a/include/asm-xtensa/ptrace.h b/include/asm-xtensa/ptrace.h
index 422c73e2693..089b0db4481 100644
--- a/include/asm-xtensa/ptrace.h
+++ b/include/asm-xtensa/ptrace.h
@@ -73,10 +73,10 @@
#define PTRACE_GETXTREGS 18
#define PTRACE_SETXTREGS 19
-#ifndef __ASSEMBLY__
-
#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
/*
* This struct defines the way the registers are stored on the
* kernel stack during a system call or other kernel entry.
@@ -122,14 +122,14 @@ extern void show_regs(struct pt_regs *);
# ifndef CONFIG_SMP
# define profile_pc(regs) instruction_pointer(regs)
# endif
-#endif /* __KERNEL__ */
#else /* __ASSEMBLY__ */
-#ifdef __KERNEL__
# include <asm/asm-offsets.h>
#define PT_REGS_OFFSET (KERNEL_STACK_SIZE - PT_USER_SIZE)
-#endif
#endif /* !__ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
#endif /* _XTENSA_PTRACE_H */
diff --git a/include/asm-xtensa/semaphore.h b/include/asm-xtensa/semaphore.h
deleted file mode 100644
index d9b2034ed1d..00000000000
--- a/include/asm-xtensa/semaphore.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/semaphore.h>
diff --git a/include/asm-xtensa/thread_info.h b/include/asm-xtensa/thread_info.h
index a2c640682ed..7e4131dd546 100644
--- a/include/asm-xtensa/thread_info.h
+++ b/include/asm-xtensa/thread_info.h
@@ -111,10 +111,6 @@ static inline struct thread_info *current_thread_info(void)
return ti;
}
-/* thread information allocation */
-#define alloc_thread_info(tsk) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
-
#else /* !__ASSEMBLY__ */
/* how to get the thread information struct from ASM */
@@ -160,6 +156,7 @@ static inline struct thread_info *current_thread_info(void)
#define TS_USEDFPU 0x0001 /* FPU was used by this task this quantum (SMP) */
#define THREAD_SIZE 8192 //(2*PAGE_SIZE)
+#define THREAD_SIZE_ORDER 1
#endif /* __KERNEL__ */
#endif /* _XTENSA_THREAD_INFO */
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 71d70d1fbce..4c4142c5aa6 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -189,7 +189,6 @@ unifdef-y += connector.h
unifdef-y += cuda.h
unifdef-y += cyclades.h
unifdef-y += dccp.h
-unifdef-y += dirent.h
unifdef-y += dlm.h
unifdef-y += dlm_plock.h
unifdef-y += edd.h
@@ -256,7 +255,9 @@ unifdef-y += kd.h
unifdef-y += kernelcapi.h
unifdef-y += kernel.h
unifdef-y += keyboard.h
+ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/kvm.h),)
unifdef-y += kvm.h
+endif
unifdef-y += llc.h
unifdef-y += loop.h
unifdef-y += lp.h
diff --git a/include/linux/acct.h b/include/linux/acct.h
index e8cae54e8d8..882dc724876 100644
--- a/include/linux/acct.h
+++ b/include/linux/acct.h
@@ -120,17 +120,20 @@ struct acct_v3
struct vfsmount;
struct super_block;
struct pacct_struct;
+struct pid_namespace;
extern void acct_auto_close_mnt(struct vfsmount *m);
extern void acct_auto_close(struct super_block *sb);
extern void acct_init_pacct(struct pacct_struct *pacct);
extern void acct_collect(long exitcode, int group_dead);
extern void acct_process(void);
+extern void acct_exit_ns(struct pid_namespace *);
#else
#define acct_auto_close_mnt(x) do { } while (0)
#define acct_auto_close(x) do { } while (0)
#define acct_init_pacct(x) do { } while (0)
#define acct_collect(x,y) do { } while (0)
#define acct_process() do { } while (0)
+#define acct_exit_ns(ns) do { } while (0)
#endif
/*
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index a1717763937..702f79dad16 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -236,6 +236,7 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n,
const char *name);
#ifdef CONFIG_PM_SLEEP
+void __init acpi_no_s4_hw_signature(void);
void __init acpi_old_suspend_ordering(void);
#endif /* CONFIG_PM_SLEEP */
#else /* CONFIG_ACPI */
diff --git a/include/linux/anon_inodes.h b/include/linux/anon_inodes.h
index 6129e58ca7c..e0a0cdc2da4 100644
--- a/include/linux/anon_inodes.h
+++ b/include/linux/anon_inodes.h
@@ -9,7 +9,7 @@
#define _LINUX_ANON_INODES_H
int anon_inode_getfd(const char *name, const struct file_operations *fops,
- void *priv);
+ void *priv, int flags);
#endif /* _LINUX_ANON_INODES_H */
diff --git a/include/linux/async_tx.h b/include/linux/async_tx.h
index eb640f0acfa..0f50d4cc436 100644
--- a/include/linux/async_tx.h
+++ b/include/linux/async_tx.h
@@ -101,21 +101,14 @@ async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
/**
* async_tx_sync_epilog - actions to take if an operation is run synchronously
- * @flags: async_tx flags
- * @depend_tx: transaction depends on depend_tx
* @cb_fn: function to call when the transaction completes
* @cb_fn_param: parameter to pass to the callback routine
*/
static inline void
-async_tx_sync_epilog(unsigned long flags,
- struct dma_async_tx_descriptor *depend_tx,
- dma_async_tx_callback cb_fn, void *cb_fn_param)
+async_tx_sync_epilog(dma_async_tx_callback cb_fn, void *cb_fn_param)
{
if (cb_fn)
cb_fn(cb_fn_param);
-
- if (depend_tx && (flags & ASYNC_TX_DEP_ACK))
- async_tx_ack(depend_tx);
}
void
@@ -152,4 +145,6 @@ struct dma_async_tx_descriptor *
async_trigger_callback(enum async_tx_flags flags,
struct dma_async_tx_descriptor *depend_tx,
dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+void async_tx_quiesce(struct dma_async_tx_descriptor **tx);
#endif /* _ASYNC_TX_H_ */
diff --git a/include/linux/atmel-pwm-bl.h b/include/linux/atmel-pwm-bl.h
new file mode 100644
index 00000000000..0153a47806c
--- /dev/null
+++ b/include/linux/atmel-pwm-bl.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * Driver for the AT32AP700X PS/2 controller (PSIF).
+ *
+ * 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.
+ */
+
+#ifndef __INCLUDE_ATMEL_PWM_BL_H
+#define __INCLUDE_ATMEL_PWM_BL_H
+
+/**
+ * struct atmel_pwm_bl_platform_data
+ * @pwm_channel: which PWM channel in the PWM module to use.
+ * @pwm_frequency: PWM frequency to generate, the driver will try to be as
+ * close as the prescaler allows.
+ * @pwm_compare_max: value to use in the PWM channel compare register.
+ * @pwm_duty_max: maximum duty cycle value, must be less than or equal to
+ * pwm_compare_max.
+ * @pwm_duty_min: minimum duty cycle value, must be less than pwm_duty_max.
+ * @pwm_active_low: set to one if the low part of the PWM signal increases the
+ * brightness of the backlight.
+ * @gpio_on: GPIO line to control the backlight on/off, set to -1 if not used.
+ * @on_active_low: set to one if the on/off signal is on when GPIO is low.
+ *
+ * This struct must be added to the platform device in the board code. It is
+ * used by the atmel-pwm-bl driver to setup the GPIO to control on/off and the
+ * PWM device.
+ */
+struct atmel_pwm_bl_platform_data {
+ unsigned int pwm_channel;
+ unsigned int pwm_frequency;
+ unsigned int pwm_compare_max;
+ unsigned int pwm_duty_max;
+ unsigned int pwm_duty_min;
+ unsigned int pwm_active_low;
+ int gpio_on;
+ unsigned int on_active_low;
+};
+
+#endif /* __INCLUDE_ATMEL_PWM_BL_H */
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 8b82974bdc1..6272a395d43 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -286,7 +286,6 @@
#define AUDIT_ARCH_SHEL64 (EM_SH|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
#define AUDIT_ARCH_SPARC (EM_SPARC)
#define AUDIT_ARCH_SPARC64 (EM_SPARCV9|__AUDIT_ARCH_64BIT)
-#define AUDIT_ARCH_V850 (EM_V850|__AUDIT_ARCH_LE)
#define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
#define AUDIT_PERM_EXEC 1
diff --git a/include/linux/auto_fs4.h b/include/linux/auto_fs4.h
index 31a29541b50..b785c6f8644 100644
--- a/include/linux/auto_fs4.h
+++ b/include/linux/auto_fs4.h
@@ -98,8 +98,6 @@ union autofs_v5_packet_union {
#define AUTOFS_IOC_EXPIRE_INDIRECT AUTOFS_IOC_EXPIRE_MULTI
#define AUTOFS_IOC_EXPIRE_DIRECT AUTOFS_IOC_EXPIRE_MULTI
#define AUTOFS_IOC_PROTOSUBVER _IOR(0x93,0x67,int)
-#define AUTOFS_IOC_ASKREGHOST _IOR(0x93,0x68,int)
-#define AUTOFS_IOC_TOGGLEREGHOST _IOR(0x93,0x69,int)
#define AUTOFS_IOC_ASKUMOUNT _IOR(0x93,0x70,int)
diff --git a/include/linux/auxvec.h b/include/linux/auxvec.h
index ad895455ab7..d7afa9dd663 100644
--- a/include/linux/auxvec.h
+++ b/include/linux/auxvec.h
@@ -26,8 +26,14 @@
#define AT_SECURE 23 /* secure mode boolean */
+#define AT_BASE_PLATFORM 24 /* string identifying real platform, may
+ * differ from AT_PLATFORM. */
+
+#define AT_EXECFN 31 /* filename of program */
+
#ifdef __KERNEL__
-#define AT_VECTOR_SIZE_BASE (14 + 2) /* NEW_AUX_ENT entries in auxiliary table */
+#define AT_VECTOR_SIZE_BASE 18 /* NEW_AUX_ENT entries in auxiliary table */
+ /* number of "#define AT_.*" above, minus {AT_NULL, AT_IGNORE, AT_NOTELF} */
#endif
#endif /* _LINUX_AUXVEC_H */
diff --git a/include/linux/bcd.h b/include/linux/bcd.h
index c545308125b..7ac518e3c15 100644
--- a/include/linux/bcd.h
+++ b/include/linux/bcd.h
@@ -10,8 +10,13 @@
#ifndef _BCD_H
#define _BCD_H
-#define BCD2BIN(val) (((val) & 0x0f) + ((val)>>4)*10)
-#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10)
+#include <linux/compiler.h>
+
+unsigned bcd2bin(unsigned char val) __attribute_const__;
+unsigned char bin2bcd(unsigned val) __attribute_const__;
+
+#define BCD2BIN(val) bcd2bin(val)
+#define BIN2BCD(val) bin2bcd(val)
/* backwards compat */
#define BCD_TO_BIN(val) ((val)=BCD2BIN(val))
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index ee0ed48e834..826f6235080 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -38,7 +38,7 @@ struct linux_binprm{
misc_bang:1;
struct file * file;
int e_uid, e_gid;
- kernel_cap_t cap_inheritable, cap_permitted;
+ kernel_cap_t cap_post_exec_permitted;
bool cap_effective;
void *security;
int argc, envc;
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index a1d9b79078e..652470b687c 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -28,52 +28,73 @@ extern unsigned long saved_max_pfn;
* memory pages (including holes) on the node.
*/
typedef struct bootmem_data {
- unsigned long node_boot_start;
+ unsigned long node_min_pfn;
unsigned long node_low_pfn;
void *node_bootmem_map;
- unsigned long last_offset;
- unsigned long last_pos;
- unsigned long last_success; /* Previous allocation point. To speed
- * up searching */
+ unsigned long last_end_off;
+ unsigned long hint_idx;
struct list_head list;
} bootmem_data_t;
+extern bootmem_data_t bootmem_node_data[];
+
extern unsigned long bootmem_bootmap_pages(unsigned long);
+
+extern unsigned long init_bootmem_node(pg_data_t *pgdat,
+ unsigned long freepfn,
+ unsigned long startpfn,
+ unsigned long endpfn);
extern unsigned long init_bootmem(unsigned long addr, unsigned long memend);
+
+extern unsigned long free_all_bootmem_node(pg_data_t *pgdat);
+extern unsigned long free_all_bootmem(void);
+
+extern void free_bootmem_node(pg_data_t *pgdat,
+ unsigned long addr,
+ unsigned long size);
extern void free_bootmem(unsigned long addr, unsigned long size);
-extern void *__alloc_bootmem(unsigned long size,
+
+/*
+ * Flags for reserve_bootmem (also if CONFIG_HAVE_ARCH_BOOTMEM_NODE,
+ * the architecture-specific code should honor this).
+ *
+ * If flags is 0, then the return value is always 0 (success). If
+ * flags contains BOOTMEM_EXCLUSIVE, then -EBUSY is returned if the
+ * memory already was reserved.
+ */
+#define BOOTMEM_DEFAULT 0
+#define BOOTMEM_EXCLUSIVE (1<<0)
+
+extern int reserve_bootmem_node(pg_data_t *pgdat,
+ unsigned long physaddr,
+ unsigned long size,
+ int flags);
+#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
+extern int reserve_bootmem(unsigned long addr, unsigned long size, int flags);
+#endif
+
+extern void *__alloc_bootmem_nopanic(unsigned long size,
unsigned long align,
unsigned long goal);
-extern void *__alloc_bootmem_nopanic(unsigned long size,
+extern void *__alloc_bootmem(unsigned long size,
unsigned long align,
unsigned long goal);
extern void *__alloc_bootmem_low(unsigned long size,
unsigned long align,
unsigned long goal);
+extern void *__alloc_bootmem_node(pg_data_t *pgdat,
+ unsigned long size,
+ unsigned long align,
+ unsigned long goal);
+extern void *__alloc_bootmem_node_nopanic(pg_data_t *pgdat,
+ unsigned long size,
+ unsigned long align,
+ unsigned long goal);
extern void *__alloc_bootmem_low_node(pg_data_t *pgdat,
unsigned long size,
unsigned long align,
unsigned long goal);
-extern void *__alloc_bootmem_core(struct bootmem_data *bdata,
- unsigned long size,
- unsigned long align,
- unsigned long goal,
- unsigned long limit);
-
-/*
- * flags for reserve_bootmem (also if CONFIG_HAVE_ARCH_BOOTMEM_NODE,
- * the architecture-specific code should honor this)
- */
-#define BOOTMEM_DEFAULT 0
-#define BOOTMEM_EXCLUSIVE (1<<0)
-
#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
-/*
- * If flags is 0, then the return value is always 0 (success). If
- * flags contains BOOTMEM_EXCLUSIVE, then -EBUSY is returned if the
- * memory already was reserved.
- */
-extern int reserve_bootmem(unsigned long addr, unsigned long size, int flags);
#define alloc_bootmem(x) \
__alloc_bootmem(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
#define alloc_bootmem_low(x) \
@@ -82,31 +103,6 @@ extern int reserve_bootmem(unsigned long addr, unsigned long size, int flags);
__alloc_bootmem(x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
#define alloc_bootmem_low_pages(x) \
__alloc_bootmem_low(x, PAGE_SIZE, 0)
-#endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
-
-extern int reserve_bootmem_generic(unsigned long addr, unsigned long size,
- int flags);
-extern unsigned long free_all_bootmem(void);
-extern unsigned long free_all_bootmem_node(pg_data_t *pgdat);
-extern void *__alloc_bootmem_node(pg_data_t *pgdat,
- unsigned long size,
- unsigned long align,
- unsigned long goal);
-extern unsigned long init_bootmem_node(pg_data_t *pgdat,
- unsigned long freepfn,
- unsigned long startpfn,
- unsigned long endpfn);
-extern int reserve_bootmem_node(pg_data_t *pgdat,
- unsigned long physaddr,
- unsigned long size,
- int flags);
-extern void free_bootmem_node(pg_data_t *pgdat,
- unsigned long addr,
- unsigned long size);
-extern void *alloc_bootmem_section(unsigned long size,
- unsigned long section_nr);
-
-#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
#define alloc_bootmem_node(pgdat, x) \
__alloc_bootmem_node(pgdat, x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
#define alloc_bootmem_pages_node(pgdat, x) \
@@ -115,6 +111,12 @@ extern void *alloc_bootmem_section(unsigned long size,
__alloc_bootmem_low_node(pgdat, x, PAGE_SIZE, 0)
#endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
+extern int reserve_bootmem_generic(unsigned long addr, unsigned long size,
+ int flags);
+
+extern void *alloc_bootmem_section(unsigned long size,
+ unsigned long section_nr);
+
#ifdef CONFIG_HAVE_ARCH_ALLOC_REMAP
extern void *alloc_remap(int nid, unsigned long size);
#else
diff --git a/include/linux/byteorder/big_endian.h b/include/linux/byteorder/big_endian.h
index 961ed4b48d8..44f95b92393 100644
--- a/include/linux/byteorder/big_endian.h
+++ b/include/linux/byteorder/big_endian.h
@@ -94,12 +94,12 @@ static inline __u16 __be16_to_cpup(const __be16 *p)
#define __le32_to_cpus(x) __swab32s((x))
#define __cpu_to_le16s(x) __swab16s((x))
#define __le16_to_cpus(x) __swab16s((x))
-#define __cpu_to_be64s(x) do {} while (0)
-#define __be64_to_cpus(x) do {} while (0)
-#define __cpu_to_be32s(x) do {} while (0)
-#define __be32_to_cpus(x) do {} while (0)
-#define __cpu_to_be16s(x) do {} while (0)
-#define __be16_to_cpus(x) do {} while (0)
+#define __cpu_to_be64s(x) do { (void)(x); } while (0)
+#define __be64_to_cpus(x) do { (void)(x); } while (0)
+#define __cpu_to_be32s(x) do { (void)(x); } while (0)
+#define __be32_to_cpus(x) do { (void)(x); } while (0)
+#define __cpu_to_be16s(x) do { (void)(x); } while (0)
+#define __be16_to_cpus(x) do { (void)(x); } while (0)
#ifdef __KERNEL__
#include <linux/byteorder/generic.h>
diff --git a/include/linux/byteorder/little_endian.h b/include/linux/byteorder/little_endian.h
index 05dc7c35b3b..4cc170a3176 100644
--- a/include/linux/byteorder/little_endian.h
+++ b/include/linux/byteorder/little_endian.h
@@ -88,12 +88,12 @@ static inline __u16 __be16_to_cpup(const __be16 *p)
{
return __swab16p((__u16 *)p);
}
-#define __cpu_to_le64s(x) do {} while (0)
-#define __le64_to_cpus(x) do {} while (0)
-#define __cpu_to_le32s(x) do {} while (0)
-#define __le32_to_cpus(x) do {} while (0)
-#define __cpu_to_le16s(x) do {} while (0)
-#define __le16_to_cpus(x) do {} while (0)
+#define __cpu_to_le64s(x) do { (void)(x); } while (0)
+#define __le64_to_cpus(x) do { (void)(x); } while (0)
+#define __cpu_to_le32s(x) do { (void)(x); } while (0)
+#define __le32_to_cpus(x) do { (void)(x); } while (0)
+#define __cpu_to_le16s(x) do { (void)(x); } while (0)
+#define __le16_to_cpus(x) do { (void)(x); } while (0)
#define __cpu_to_be64s(x) __swab64s((x))
#define __be64_to_cpus(x) __swab64s((x))
#define __cpu_to_be32s(x) __swab32s((x))
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index e155aa78d85..c98dd7cb707 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -21,11 +21,13 @@
struct cgroupfs_root;
struct cgroup_subsys;
struct inode;
+struct cgroup;
extern int cgroup_init_early(void);
extern int cgroup_init(void);
extern void cgroup_init_smp(void);
extern void cgroup_lock(void);
+extern bool cgroup_lock_live_group(struct cgroup *cgrp);
extern void cgroup_unlock(void);
extern void cgroup_fork(struct task_struct *p);
extern void cgroup_fork_callbacks(struct task_struct *p);
@@ -205,50 +207,64 @@ struct cftype {
* subsystem, followed by a period */
char name[MAX_CFTYPE_NAME];
int private;
- int (*open) (struct inode *inode, struct file *file);
- ssize_t (*read) (struct cgroup *cgrp, struct cftype *cft,
- struct file *file,
- char __user *buf, size_t nbytes, loff_t *ppos);
+
+ /*
+ * If non-zero, defines the maximum length of string that can
+ * be passed to write_string; defaults to 64
+ */
+ size_t max_write_len;
+
+ int (*open)(struct inode *inode, struct file *file);
+ ssize_t (*read)(struct cgroup *cgrp, struct cftype *cft,
+ struct file *file,
+ char __user *buf, size_t nbytes, loff_t *ppos);
/*
* read_u64() is a shortcut for the common case of returning a
* single integer. Use it in place of read()
*/
- u64 (*read_u64) (struct cgroup *cgrp, struct cftype *cft);
+ u64 (*read_u64)(struct cgroup *cgrp, struct cftype *cft);
/*
* read_s64() is a signed version of read_u64()
*/
- s64 (*read_s64) (struct cgroup *cgrp, struct cftype *cft);
+ s64 (*read_s64)(struct cgroup *cgrp, struct cftype *cft);
/*
* read_map() is used for defining a map of key/value
* pairs. It should call cb->fill(cb, key, value) for each
* entry. The key/value pairs (and their ordering) should not
* change between reboots.
*/
- int (*read_map) (struct cgroup *cont, struct cftype *cft,
- struct cgroup_map_cb *cb);
+ int (*read_map)(struct cgroup *cont, struct cftype *cft,
+ struct cgroup_map_cb *cb);
/*
* read_seq_string() is used for outputting a simple sequence
* using seqfile.
*/
- int (*read_seq_string) (struct cgroup *cont, struct cftype *cft,
- struct seq_file *m);
+ int (*read_seq_string)(struct cgroup *cont, struct cftype *cft,
+ struct seq_file *m);
- ssize_t (*write) (struct cgroup *cgrp, struct cftype *cft,
- struct file *file,
- const char __user *buf, size_t nbytes, loff_t *ppos);
+ ssize_t (*write)(struct cgroup *cgrp, struct cftype *cft,
+ struct file *file,
+ const char __user *buf, size_t nbytes, loff_t *ppos);
/*
* write_u64() is a shortcut for the common case of accepting
* a single integer (as parsed by simple_strtoull) from
* userspace. Use in place of write(); return 0 or error.
*/
- int (*write_u64) (struct cgroup *cgrp, struct cftype *cft, u64 val);
+ int (*write_u64)(struct cgroup *cgrp, struct cftype *cft, u64 val);
/*
* write_s64() is a signed version of write_u64()
*/
- int (*write_s64) (struct cgroup *cgrp, struct cftype *cft, s64 val);
+ int (*write_s64)(struct cgroup *cgrp, struct cftype *cft, s64 val);
/*
+ * write_string() is passed a nul-terminated kernelspace
+ * buffer of maximum length determined by max_write_len.
+ * Returns 0 or -ve error code.
+ */
+ int (*write_string)(struct cgroup *cgrp, struct cftype *cft,
+ const char *buffer);
+ /*
* trigger() callback can be used to get some kick from the
* userspace, when the actual string written is not important
* at all. The private field can be used to determine the
@@ -256,7 +272,7 @@ struct cftype {
*/
int (*trigger)(struct cgroup *cgrp, unsigned int event);
- int (*release) (struct inode *inode, struct file *file);
+ int (*release)(struct inode *inode, struct file *file);
};
struct cgroup_scanner {
@@ -348,7 +364,8 @@ static inline struct cgroup* task_cgroup(struct task_struct *task,
return task_subsys_state(task, subsys_id)->cgroup;
}
-int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *ss);
+int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *ss,
+ char *nodename);
/* A cgroup_iter should be treated as an opaque object */
struct cgroup_iter {
diff --git a/include/linux/coda.h b/include/linux/coda.h
index b5cf0780c51..96c87693800 100644
--- a/include/linux/coda.h
+++ b/include/linux/coda.h
@@ -199,28 +199,6 @@ typedef u_int32_t vuid_t;
typedef u_int32_t vgid_t;
#endif /*_VUID_T_ */
-#ifdef CONFIG_CODA_FS_OLD_API
-struct CodaFid {
- u_int32_t opaque[3];
-};
-
-static __inline__ ino_t coda_f2i(struct CodaFid *fid)
-{
- if ( ! fid )
- return 0;
- if (fid->opaque[1] == 0xfffffffe || fid->opaque[1] == 0xffffffff)
- return ((fid->opaque[0] << 20) | (fid->opaque[2] & 0xfffff));
- else
- return (fid->opaque[2] + (fid->opaque[1]<<10) + (fid->opaque[0]<<20));
-}
-
-struct coda_cred {
- vuid_t cr_uid, cr_euid, cr_suid, cr_fsuid; /* Real, efftve, set, fs uid*/
- vgid_t cr_groupid, cr_egid, cr_sgid, cr_fsgid; /* same for groups */
-};
-
-#else /* not defined(CONFIG_CODA_FS_OLD_API) */
-
struct CodaFid {
u_int32_t opaque[4];
};
@@ -228,8 +206,6 @@ struct CodaFid {
#define coda_f2i(fid)\
(fid ? (fid->opaque[3] ^ (fid->opaque[2]<<10) ^ (fid->opaque[1]<<20) ^ fid->opaque[0]) : 0)
-#endif
-
#ifndef _VENUS_VATTR_T_
#define _VENUS_VATTR_T_
/*
@@ -313,15 +289,7 @@ struct coda_statfs {
#define CIOC_KERNEL_VERSION _IOWR('c', 10, size_t)
-#if 0
-#define CODA_KERNEL_VERSION 0 /* don't care about kernel version number */
-#define CODA_KERNEL_VERSION 1 /* The old venus 4.6 compatible interface */
-#endif
-#ifdef CONFIG_CODA_FS_OLD_API
-#define CODA_KERNEL_VERSION 2 /* venus_lookup got an extra parameter */
-#else
#define CODA_KERNEL_VERSION 3 /* 128-bit file identifiers */
-#endif
/*
* Venus <-> Coda RPC arguments
@@ -329,16 +297,9 @@ struct coda_statfs {
struct coda_in_hdr {
u_int32_t opcode;
u_int32_t unique; /* Keep multiple outstanding msgs distinct */
-#ifdef CONFIG_CODA_FS_OLD_API
- u_int16_t pid; /* Common to all */
- u_int16_t pgid; /* Common to all */
- u_int16_t sid; /* Common to all */
- struct coda_cred cred; /* Common to all */
-#else
pid_t pid;
pid_t pgid;
vuid_t uid;
-#endif
};
/* Really important that opcode and unique are 1st two fields! */
@@ -613,11 +574,7 @@ struct coda_vget_out {
/* CODA_PURGEUSER is a venus->kernel call */
struct coda_purgeuser_out {
struct coda_out_hdr oh;
-#ifdef CONFIG_CODA_FS_OLD_API
- struct coda_cred cred;
-#else
vuid_t uid;
-#endif
};
/* coda_zapfile: */
diff --git a/include/linux/consolemap.h b/include/linux/consolemap.h
index e2bf7e5db39..c4811da1338 100644
--- a/include/linux/consolemap.h
+++ b/include/linux/consolemap.h
@@ -3,6 +3,9 @@
*
* Interface between console.c, selection.c and consolemap.c
*/
+#ifndef __LINUX_CONSOLEMAP_H__
+#define __LINUX_CONSOLEMAP_H__
+
#define LAT1_MAP 0
#define GRAF_MAP 1
#define IBMPC_MAP 2
@@ -10,6 +13,7 @@
#include <linux/types.h>
+#ifdef CONFIG_CONSOLE_TRANSLATIONS
struct vc_data;
extern u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode);
@@ -18,3 +22,13 @@ extern int conv_uni_to_pc(struct vc_data *conp, long ucs);
extern u32 conv_8bit_to_uni(unsigned char c);
extern int conv_uni_to_8bit(u32 uni);
void console_map_init(void);
+#else
+#define inverse_translate(conp, glyph, uni) ((uint16_t)glyph)
+#define set_translate(m, vc) ((unsigned short *)NULL)
+#define conv_uni_to_pc(conp, ucs) ((int) (ucs > 0xff ? -1: ucs))
+#define conv_8bit_to_uni(c) ((uint32_t)(c))
+#define conv_uni_to_8bit(c) ((int) ((c) & 0xff))
+#define console_map_init(c) do { ; } while (0)
+#endif /* CONFIG_CONSOLE_TRANSLATIONS */
+
+#endif /* __LINUX_CONSOLEMAP_H__ */
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 7464ba3b433..d7faf880849 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -69,10 +69,11 @@ static inline void unregister_cpu_notifier(struct notifier_block *nb)
#endif
int cpu_up(unsigned int cpu);
-
extern void cpu_hotplug_init(void);
+extern void cpu_maps_update_begin(void);
+extern void cpu_maps_update_done(void);
-#else
+#else /* CONFIG_SMP */
static inline int register_cpu_notifier(struct notifier_block *nb)
{
@@ -87,10 +88,16 @@ static inline void cpu_hotplug_init(void)
{
}
+static inline void cpu_maps_update_begin(void)
+{
+}
+
+static inline void cpu_maps_update_done(void)
+{
+}
+
#endif /* CONFIG_SMP */
extern struct sysdev_class cpu_sysdev_class;
-extern void cpu_maps_update_begin(void);
-extern void cpu_maps_update_done(void);
#ifdef CONFIG_HOTPLUG_CPU
/* Stop CPUs going up and down. */
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index c24875bd9c5..1b5c98e7fef 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -17,6 +17,20 @@
* For details of cpus_onto(), see bitmap_onto in lib/bitmap.c.
* For details of cpus_fold(), see bitmap_fold in lib/bitmap.c.
*
+ * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+ * Note: The alternate operations with the suffix "_nr" are used
+ * to limit the range of the loop to nr_cpu_ids instead of
+ * NR_CPUS when NR_CPUS > 64 for performance reasons.
+ * If NR_CPUS is <= 64 then most assembler bitmask
+ * operators execute faster with a constant range, so
+ * the operator will continue to use NR_CPUS.
+ *
+ * Another consideration is that nr_cpu_ids is initialized
+ * to NR_CPUS and isn't lowered until the possible cpus are
+ * discovered (including any disabled cpus). So early uses
+ * will span the entire range of NR_CPUS.
+ * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+ *
* The available cpumask operations are:
*
* void cpu_set(cpu, mask) turn on bit 'cpu' in mask
@@ -38,18 +52,60 @@
* int cpus_empty(mask) Is mask empty (no bits sets)?
* int cpus_full(mask) Is mask full (all bits sets)?
* int cpus_weight(mask) Hamming weigh - number of set bits
+ * int cpus_weight_nr(mask) Same using nr_cpu_ids instead of NR_CPUS
*
* void cpus_shift_right(dst, src, n) Shift right
* void cpus_shift_left(dst, src, n) Shift left
*
* int first_cpu(mask) Number lowest set bit, or NR_CPUS
* int next_cpu(cpu, mask) Next cpu past 'cpu', or NR_CPUS
+ * int next_cpu_nr(cpu, mask) Next cpu past 'cpu', or nr_cpu_ids
*
* cpumask_t cpumask_of_cpu(cpu) Return cpumask with bit 'cpu' set
+ *ifdef CONFIG_HAS_CPUMASK_OF_CPU
+ * cpumask_of_cpu_ptr_declare(v) Declares cpumask_t *v
+ * cpumask_of_cpu_ptr_next(v, cpu) Sets v = &cpumask_of_cpu_map[cpu]
+ * cpumask_of_cpu_ptr(v, cpu) Combines above two operations
+ *else
+ * cpumask_of_cpu_ptr_declare(v) Declares cpumask_t _v and *v = &_v
+ * cpumask_of_cpu_ptr_next(v, cpu) Sets _v = cpumask_of_cpu(cpu)
+ * cpumask_of_cpu_ptr(v, cpu) Combines above two operations
+ *endif
* CPU_MASK_ALL Initializer - all bits set
* CPU_MASK_NONE Initializer - no bits set
* unsigned long *cpus_addr(mask) Array of unsigned long's in mask
*
+ * CPUMASK_ALLOC kmalloc's a structure that is a composite of many cpumask_t
+ * variables, and CPUMASK_PTR provides pointers to each field.
+ *
+ * The structure should be defined something like this:
+ * struct my_cpumasks {
+ * cpumask_t mask1;
+ * cpumask_t mask2;
+ * };
+ *
+ * Usage is then:
+ * CPUMASK_ALLOC(my_cpumasks);
+ * CPUMASK_PTR(mask1, my_cpumasks);
+ * CPUMASK_PTR(mask2, my_cpumasks);
+ *
+ * --- DO NOT reference cpumask_t pointers until this check ---
+ * if (my_cpumasks == NULL)
+ * "kmalloc failed"...
+ *
+ * References are now pointers to the cpumask_t variables (*mask1, ...)
+ *
+ *if NR_CPUS > BITS_PER_LONG
+ * CPUMASK_ALLOC(m) Declares and allocates struct m *m =
+ * kmalloc(sizeof(*m), GFP_KERNEL)
+ * CPUMASK_FREE(m) Macro for kfree(m)
+ *else
+ * CPUMASK_ALLOC(m) Declares struct m _m, *m = &_m
+ * CPUMASK_FREE(m) Nop
+ *endif
+ * CPUMASK_PTR(v, m) Declares cpumask_t *v = &(m->v)
+ * ------------------------------------------------------------------------
+ *
* int cpumask_scnprintf(buf, len, mask) Format cpumask for printing
* int cpumask_parse_user(ubuf, ulen, mask) Parse ascii string as cpumask
* int cpulist_scnprintf(buf, len, mask) Format cpumask as list for printing
@@ -59,7 +115,8 @@
* void cpus_onto(dst, orig, relmap) *dst = orig relative to relmap
* void cpus_fold(dst, orig, sz) dst bits = orig bits mod sz
*
- * for_each_cpu_mask(cpu, mask) for-loop cpu over mask
+ * for_each_cpu_mask(cpu, mask) for-loop cpu over mask using NR_CPUS
+ * for_each_cpu_mask_nr(cpu, mask) for-loop cpu over mask using nr_cpu_ids
*
* int num_online_cpus() Number of online CPUs
* int num_possible_cpus() Number of all possible CPUs
@@ -216,23 +273,19 @@ static inline void __cpus_shift_left(cpumask_t *dstp,
bitmap_shift_left(dstp->bits, srcp->bits, n, nbits);
}
-#ifdef CONFIG_SMP
-int __first_cpu(const cpumask_t *srcp);
-#define first_cpu(src) __first_cpu(&(src))
-int __next_cpu(int n, const cpumask_t *srcp);
-#define next_cpu(n, src) __next_cpu((n), &(src))
-#else
-#define first_cpu(src) ({ (void)(src); 0; })
-#define next_cpu(n, src) ({ (void)(src); 1; })
-#endif
#ifdef CONFIG_HAVE_CPUMASK_OF_CPU_MAP
extern cpumask_t *cpumask_of_cpu_map;
-#define cpumask_of_cpu(cpu) (cpumask_of_cpu_map[cpu])
-
+#define cpumask_of_cpu(cpu) (cpumask_of_cpu_map[cpu])
+#define cpumask_of_cpu_ptr(v, cpu) \
+ const cpumask_t *v = &cpumask_of_cpu(cpu)
+#define cpumask_of_cpu_ptr_declare(v) \
+ const cpumask_t *v
+#define cpumask_of_cpu_ptr_next(v, cpu) \
+ v = &cpumask_of_cpu(cpu)
#else
#define cpumask_of_cpu(cpu) \
-(*({ \
+({ \
typeof(_unused_cpumask_arg_) m; \
if (sizeof(m) == sizeof(unsigned long)) { \
m.bits[0] = 1UL<<(cpu); \
@@ -240,8 +293,16 @@ extern cpumask_t *cpumask_of_cpu_map;
cpus_clear(m); \
cpu_set((cpu), m); \
} \
- &m; \
-}))
+ m; \
+})
+#define cpumask_of_cpu_ptr(v, cpu) \
+ cpumask_t _##v = cpumask_of_cpu(cpu); \
+ const cpumask_t *v = &_##v
+#define cpumask_of_cpu_ptr_declare(v) \
+ cpumask_t _##v; \
+ const cpumask_t *v = &_##v
+#define cpumask_of_cpu_ptr_next(v, cpu) \
+ _##v = cpumask_of_cpu(cpu)
#endif
#define CPU_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(NR_CPUS)
@@ -281,6 +342,15 @@ extern cpumask_t cpu_mask_all;
#define cpus_addr(src) ((src).bits)
+#if NR_CPUS > BITS_PER_LONG
+#define CPUMASK_ALLOC(m) struct m *m = kmalloc(sizeof(*m), GFP_KERNEL)
+#define CPUMASK_FREE(m) kfree(m)
+#else
+#define CPUMASK_ALLOC(m) struct m _m, *m = &_m
+#define CPUMASK_FREE(m)
+#endif
+#define CPUMASK_PTR(v, m) cpumask_t *v = &(m->v)
+
#define cpumask_scnprintf(buf, len, src) \
__cpumask_scnprintf((buf), (len), &(src), NR_CPUS)
static inline int __cpumask_scnprintf(char *buf, int len,
@@ -343,29 +413,59 @@ static inline void __cpus_fold(cpumask_t *dstp, const cpumask_t *origp,
bitmap_fold(dstp->bits, origp->bits, sz, nbits);
}
-#if NR_CPUS > 1
-#define for_each_cpu_mask(cpu, mask) \
- for ((cpu) = first_cpu(mask); \
- (cpu) < NR_CPUS; \
- (cpu) = next_cpu((cpu), (mask)))
-#else /* NR_CPUS == 1 */
-#define for_each_cpu_mask(cpu, mask) \
+#if NR_CPUS == 1
+
+#define nr_cpu_ids 1
+#define first_cpu(src) ({ (void)(src); 0; })
+#define next_cpu(n, src) ({ (void)(src); 1; })
+#define any_online_cpu(mask) 0
+#define for_each_cpu_mask(cpu, mask) \
for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask)
-#endif /* NR_CPUS */
+
+#else /* NR_CPUS > 1 */
+
+extern int nr_cpu_ids;
+int __first_cpu(const cpumask_t *srcp);
+int __next_cpu(int n, const cpumask_t *srcp);
+int __any_online_cpu(const cpumask_t *mask);
+
+#define first_cpu(src) __first_cpu(&(src))
+#define next_cpu(n, src) __next_cpu((n), &(src))
+#define any_online_cpu(mask) __any_online_cpu(&(mask))
+#define for_each_cpu_mask(cpu, mask) \
+ for ((cpu) = -1; \
+ (cpu) = next_cpu((cpu), (mask)), \
+ (cpu) < NR_CPUS; )
+#endif
+
+#if NR_CPUS <= 64
#define next_cpu_nr(n, src) next_cpu(n, src)
#define cpus_weight_nr(cpumask) cpus_weight(cpumask)
#define for_each_cpu_mask_nr(cpu, mask) for_each_cpu_mask(cpu, mask)
+#else /* NR_CPUS > 64 */
+
+int __next_cpu_nr(int n, const cpumask_t *srcp);
+#define next_cpu_nr(n, src) __next_cpu_nr((n), &(src))
+#define cpus_weight_nr(cpumask) __cpus_weight(&(cpumask), nr_cpu_ids)
+#define for_each_cpu_mask_nr(cpu, mask) \
+ for ((cpu) = -1; \
+ (cpu) = next_cpu_nr((cpu), (mask)), \
+ (cpu) < nr_cpu_ids; )
+
+#endif /* NR_CPUS > 64 */
+
/*
* The following particular system cpumasks and operations manage
- * possible, present and online cpus. Each of them is a fixed size
+ * possible, present, active and online cpus. Each of them is a fixed size
* bitmap of size NR_CPUS.
*
* #ifdef CONFIG_HOTPLUG_CPU
* cpu_possible_map - has bit 'cpu' set iff cpu is populatable
* cpu_present_map - has bit 'cpu' set iff cpu is populated
* cpu_online_map - has bit 'cpu' set iff cpu available to scheduler
+ * cpu_active_map - has bit 'cpu' set iff cpu available to migration
* #else
* cpu_possible_map - has bit 'cpu' set iff cpu is populated
* cpu_present_map - copy of cpu_possible_map
@@ -416,14 +516,16 @@ static inline void __cpus_fold(cpumask_t *dstp, const cpumask_t *origp,
extern cpumask_t cpu_possible_map;
extern cpumask_t cpu_online_map;
extern cpumask_t cpu_present_map;
+extern cpumask_t cpu_active_map;
#if NR_CPUS > 1
-#define num_online_cpus() cpus_weight(cpu_online_map)
-#define num_possible_cpus() cpus_weight(cpu_possible_map)
-#define num_present_cpus() cpus_weight(cpu_present_map)
+#define num_online_cpus() cpus_weight_nr(cpu_online_map)
+#define num_possible_cpus() cpus_weight_nr(cpu_possible_map)
+#define num_present_cpus() cpus_weight_nr(cpu_present_map)
#define cpu_online(cpu) cpu_isset((cpu), cpu_online_map)
#define cpu_possible(cpu) cpu_isset((cpu), cpu_possible_map)
#define cpu_present(cpu) cpu_isset((cpu), cpu_present_map)
+#define cpu_active(cpu) cpu_isset((cpu), cpu_active_map)
#else
#define num_online_cpus() 1
#define num_possible_cpus() 1
@@ -431,21 +533,13 @@ extern cpumask_t cpu_present_map;
#define cpu_online(cpu) ((cpu) == 0)
#define cpu_possible(cpu) ((cpu) == 0)
#define cpu_present(cpu) ((cpu) == 0)
+#define cpu_active(cpu) ((cpu) == 0)
#endif
#define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
-#ifdef CONFIG_SMP
-extern int nr_cpu_ids;
-#define any_online_cpu(mask) __any_online_cpu(&(mask))
-int __any_online_cpu(const cpumask_t *mask);
-#else
-#define nr_cpu_ids 1
-#define any_online_cpu(mask) 0
-#endif
-
-#define for_each_possible_cpu(cpu) for_each_cpu_mask((cpu), cpu_possible_map)
-#define for_each_online_cpu(cpu) for_each_cpu_mask((cpu), cpu_online_map)
-#define for_each_present_cpu(cpu) for_each_cpu_mask((cpu), cpu_present_map)
+#define for_each_possible_cpu(cpu) for_each_cpu_mask_nr((cpu), cpu_possible_map)
+#define for_each_online_cpu(cpu) for_each_cpu_mask_nr((cpu), cpu_online_map)
+#define for_each_present_cpu(cpu) for_each_cpu_mask_nr((cpu), cpu_present_map)
#endif /* __LINUX_CPUMASK_H */
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 038578362b4..e8f450c499b 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -78,6 +78,8 @@ extern void cpuset_track_online_nodes(void);
extern int current_cpuset_is_being_rebound(void);
+extern void rebuild_sched_domains(void);
+
#else /* !CONFIG_CPUSETS */
static inline int cpuset_init_early(void) { return 0; }
@@ -156,6 +158,11 @@ static inline int current_cpuset_is_being_rebound(void)
return 0;
}
+static inline void rebuild_sched_domains(void)
+{
+ partition_sched_domains(0, NULL, NULL);
+}
+
#endif /* !CONFIG_CPUSETS */
#endif /* _LINUX_CPUSET_H */
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h
index 22c7ac5cd80..6cd39a927e1 100644
--- a/include/linux/crash_dump.h
+++ b/include/linux/crash_dump.h
@@ -22,5 +22,13 @@ extern struct proc_dir_entry *proc_vmcore;
#define vmcore_elf_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
+static inline int is_kdump_kernel(void)
+{
+ return (elfcorehdr_addr != ELFCORE_ADDR_MAX) ? 1 : 0;
+}
+#else /* !CONFIG_CRASH_DUMP */
+static inline int is_kdump_kernel(void) { return 0; }
#endif /* CONFIG_CRASH_DUMP */
+
+extern unsigned long saved_max_pfn;
#endif /* LINUX_CRASHDUMP_H */
diff --git a/include/linux/dca.h b/include/linux/dca.h
index af61cd1f37e..b00a753eda5 100644
--- a/include/linux/dca.h
+++ b/include/linux/dca.h
@@ -10,6 +10,7 @@ void dca_unregister_notify(struct notifier_block *nb);
#define DCA_PROVIDER_REMOVE 0x0002
struct dca_provider {
+ struct list_head node;
struct dca_ops *ops;
struct device *cd;
int id;
@@ -18,7 +19,9 @@ struct dca_provider {
struct dca_ops {
int (*add_requester) (struct dca_provider *, struct device *);
int (*remove_requester) (struct dca_provider *, struct device *);
- u8 (*get_tag) (struct dca_provider *, int cpu);
+ u8 (*get_tag) (struct dca_provider *, struct device *,
+ int cpu);
+ int (*dev_managed) (struct dca_provider *, struct device *);
};
struct dca_provider *alloc_dca_provider(struct dca_ops *ops, int priv_size);
@@ -32,9 +35,11 @@ static inline void *dca_priv(struct dca_provider *dca)
}
/* Requester API */
+#define DCA_GET_TAG_TWO_ARGS
int dca_add_requester(struct device *dev);
int dca_remove_requester(struct device *dev);
u8 dca_get_tag(int cpu);
+u8 dca3_get_tag(struct device *dev, int cpu);
/* internal stuff */
int __init dca_sysfs_init(void);
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 32755cdf68d..e1a6c046cea 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -44,6 +44,7 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
const char *dest);
void debugfs_remove(struct dentry *dentry);
+void debugfs_remove_recursive(struct dentry *dentry);
struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
struct dentry *new_dir, const char *new_name);
@@ -101,6 +102,9 @@ static inline struct dentry *debugfs_create_symlink(const char *name,
static inline void debugfs_remove(struct dentry *dentry)
{ }
+static inline void debugfs_remove_recursive(struct dentry *dentry)
+{ }
+
static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
struct dentry *new_dir, char *new_name)
{
diff --git a/include/linux/delayacct.h b/include/linux/delayacct.h
index ab94bc08355..f352f06fa06 100644
--- a/include/linux/delayacct.h
+++ b/include/linux/delayacct.h
@@ -39,6 +39,8 @@ extern void __delayacct_blkio_start(void);
extern void __delayacct_blkio_end(void);
extern int __delayacct_add_tsk(struct taskstats *, struct task_struct *);
extern __u64 __delayacct_blkio_ticks(struct task_struct *);
+extern void __delayacct_freepages_start(void);
+extern void __delayacct_freepages_end(void);
static inline int delayacct_is_task_waiting_on_io(struct task_struct *p)
{
@@ -107,6 +109,18 @@ static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
return 0;
}
+static inline void delayacct_freepages_start(void)
+{
+ if (current->delays)
+ __delayacct_freepages_start();
+}
+
+static inline void delayacct_freepages_end(void)
+{
+ if (current->delays)
+ __delayacct_freepages_end();
+}
+
#else
static inline void delayacct_set_flag(int flag)
{}
@@ -129,6 +143,11 @@ static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
{ return 0; }
static inline int delayacct_is_task_waiting_on_io(struct task_struct *p)
{ return 0; }
+static inline void delayacct_freepages_start(void)
+{}
+static inline void delayacct_freepages_end(void)
+{}
+
#endif /* CONFIG_TASK_DELAY_ACCT */
#endif
diff --git a/include/linux/device.h b/include/linux/device.h
index f71a78d123a..d24a47f80f9 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -16,6 +16,7 @@
#include <linux/kobject.h>
#include <linux/klist.h>
#include <linux/list.h>
+#include <linux/lockdep.h>
#include <linux/compiler.h>
#include <linux/types.h>
#include <linux/module.h>
@@ -24,17 +25,13 @@
#include <asm/atomic.h>
#include <asm/device.h>
-#define DEVICE_NAME_SIZE 50
-/* DEVICE_NAME_HALF is really less than half to accommodate slop */
-#define DEVICE_NAME_HALF __stringify(20)
-#define DEVICE_ID_SIZE 32
-#define BUS_ID_SIZE KOBJ_NAME_LEN
-
+#define BUS_ID_SIZE 20
struct device;
struct device_driver;
struct driver_private;
struct class;
+struct class_private;
struct bus_type;
struct bus_type_private;
@@ -186,13 +183,9 @@ struct class {
const char *name;
struct module *owner;
- struct kset subsys;
- struct list_head devices;
- struct list_head interfaces;
- struct kset class_dirs;
- struct semaphore sem; /* locks children, devices, interfaces */
struct class_attribute *class_attrs;
struct device_attribute *dev_attrs;
+ struct kobject *dev_kobj;
int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
@@ -203,13 +196,28 @@ struct class {
int (*resume)(struct device *dev);
struct pm_ops *pm;
+ struct class_private *p;
};
-extern int __must_check class_register(struct class *class);
+extern struct kobject *sysfs_dev_block_kobj;
+extern struct kobject *sysfs_dev_char_kobj;
+extern int __must_check __class_register(struct class *class,
+ struct lock_class_key *key);
extern void class_unregister(struct class *class);
-extern int class_for_each_device(struct class *class, void *data,
+
+/* This is a #define to keep the compiler from merging different
+ * instances of the __key variable */
+#define class_register(class) \
+({ \
+ static struct lock_class_key __key; \
+ __class_register(class, &__key); \
+})
+
+extern int class_for_each_device(struct class *class, struct device *start,
+ void *data,
int (*fn)(struct device *dev, void *data));
-extern struct device *class_find_device(struct class *class, void *data,
+extern struct device *class_find_device(struct class *class,
+ struct device *start, void *data,
int (*match)(struct device *, void *));
struct class_attribute {
@@ -237,9 +245,19 @@ struct class_interface {
extern int __must_check class_interface_register(struct class_interface *);
extern void class_interface_unregister(struct class_interface *);
-extern struct class *class_create(struct module *owner, const char *name);
+extern struct class * __must_check __class_create(struct module *owner,
+ const char *name,
+ struct lock_class_key *key);
extern void class_destroy(struct class *cls);
+/* This is a #define to keep the compiler from merging different
+ * instances of the __key variable */
+#define class_create(owner, name) \
+({ \
+ static struct lock_class_key __key; \
+ __class_create(owner, name, &__key); \
+})
+
/*
* The type of device, "struct device" is embedded in. A class
* or bus can contain devices of different types
@@ -468,14 +486,10 @@ extern struct device *device_create_vargs(struct class *cls,
const char *fmt,
va_list vargs);
extern struct device *device_create(struct class *cls, struct device *parent,
- dev_t devt, const char *fmt, ...)
- __attribute__((format(printf, 4, 5)));
-extern struct device *device_create_drvdata(struct class *cls,
- struct device *parent,
- dev_t devt,
- void *drvdata,
- const char *fmt, ...)
+ dev_t devt, void *drvdata,
+ const char *fmt, ...)
__attribute__((format(printf, 5, 6)));
+#define device_create_drvdata device_create
extern void device_destroy(struct class *cls, dev_t devt);
/*
diff --git a/include/linux/dirent.h b/include/linux/dirent.h
index 5d6023b8780..f072fb8d10a 100644
--- a/include/linux/dirent.h
+++ b/include/linux/dirent.h
@@ -1,23 +1,6 @@
#ifndef _LINUX_DIRENT_H
#define _LINUX_DIRENT_H
-struct dirent {
- long d_ino;
- __kernel_off_t d_off;
- unsigned short d_reclen;
- char d_name[256]; /* We must not include limits.h! */
-};
-
-struct dirent64 {
- __u64 d_ino;
- __s64 d_off;
- unsigned short d_reclen;
- unsigned char d_type;
- char d_name[256];
-};
-
-#ifdef __KERNEL__
-
struct linux_dirent64 {
u64 d_ino;
s64 d_off;
@@ -26,7 +9,4 @@ struct linux_dirent64 {
char d_name[0];
};
-#endif /* __KERNEL__ */
-
-
#endif
diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h
index 1677e2bfa00..71ad34eca6e 100644
--- a/include/linux/dma-attrs.h
+++ b/include/linux/dma-attrs.h
@@ -12,6 +12,7 @@
*/
enum dma_attr {
DMA_ATTR_WRITE_BARRIER,
+ DMA_ATTR_WEAK_ORDERING,
DMA_ATTR_MAX,
};
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index d08a5c5eb92..adb0b084eb5 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -89,10 +89,23 @@ enum dma_transaction_type {
DMA_MEMSET,
DMA_MEMCPY_CRC32C,
DMA_INTERRUPT,
+ DMA_SLAVE,
};
/* last transaction type for creation of the capabilities mask */
-#define DMA_TX_TYPE_END (DMA_INTERRUPT + 1)
+#define DMA_TX_TYPE_END (DMA_SLAVE + 1)
+
+/**
+ * enum dma_slave_width - DMA slave register access width.
+ * @DMA_SLAVE_WIDTH_8BIT: Do 8-bit slave register accesses
+ * @DMA_SLAVE_WIDTH_16BIT: Do 16-bit slave register accesses
+ * @DMA_SLAVE_WIDTH_32BIT: Do 32-bit slave register accesses
+ */
+enum dma_slave_width {
+ DMA_SLAVE_WIDTH_8BIT,
+ DMA_SLAVE_WIDTH_16BIT,
+ DMA_SLAVE_WIDTH_32BIT,
+};
/**
* enum dma_ctrl_flags - DMA flags to augment operation preparation,
@@ -102,10 +115,14 @@ enum dma_transaction_type {
* @DMA_CTRL_ACK - the descriptor cannot be reused until the client
* acknowledges receipt, i.e. has has a chance to establish any
* dependency chains
+ * @DMA_COMPL_SKIP_SRC_UNMAP - set to disable dma-unmapping the source buffer(s)
+ * @DMA_COMPL_SKIP_DEST_UNMAP - set to disable dma-unmapping the destination(s)
*/
enum dma_ctrl_flags {
DMA_PREP_INTERRUPT = (1 << 0),
DMA_CTRL_ACK = (1 << 1),
+ DMA_COMPL_SKIP_SRC_UNMAP = (1 << 2),
+ DMA_COMPL_SKIP_DEST_UNMAP = (1 << 3),
};
/**
@@ -115,6 +132,32 @@ enum dma_ctrl_flags {
typedef struct { DECLARE_BITMAP(bits, DMA_TX_TYPE_END); } dma_cap_mask_t;
/**
+ * struct dma_slave - Information about a DMA slave
+ * @dev: device acting as DMA slave
+ * @dma_dev: required DMA master device. If non-NULL, the client can not be
+ * bound to other masters than this.
+ * @tx_reg: physical address of data register used for
+ * memory-to-peripheral transfers
+ * @rx_reg: physical address of data register used for
+ * peripheral-to-memory transfers
+ * @reg_width: peripheral register width
+ *
+ * If dma_dev is non-NULL, the client can not be bound to other DMA
+ * masters than the one corresponding to this device. The DMA master
+ * driver may use this to determine if there is controller-specific
+ * data wrapped around this struct. Drivers of platform code that sets
+ * the dma_dev field must therefore make sure to use an appropriate
+ * controller-specific dma slave structure wrapping this struct.
+ */
+struct dma_slave {
+ struct device *dev;
+ struct device *dma_dev;
+ dma_addr_t tx_reg;
+ dma_addr_t rx_reg;
+ enum dma_slave_width reg_width;
+};
+
+/**
* struct dma_chan_percpu - the per-CPU part of struct dma_chan
* @refcount: local_t used for open-coded "bigref" counting
* @memcpy_count: transaction counter
@@ -139,6 +182,7 @@ struct dma_chan_percpu {
* @rcu: the DMA channel's RCU head
* @device_node: used to add this to the device chan list
* @local: per-cpu pointer to a struct dma_chan_percpu
+ * @client-count: how many clients are using this channel
*/
struct dma_chan {
struct dma_device *device;
@@ -154,6 +198,7 @@ struct dma_chan {
struct list_head device_node;
struct dma_chan_percpu *local;
+ int client_count;
};
#define to_dma_chan(p) container_of(p, struct dma_chan, dev)
@@ -202,11 +247,14 @@ typedef enum dma_state_client (*dma_event_callback) (struct dma_client *client,
* @event_callback: func ptr to call when something happens
* @cap_mask: only return channels that satisfy the requested capabilities
* a value of zero corresponds to any capability
+ * @slave: data for preparing slave transfer. Must be non-NULL iff the
+ * DMA_SLAVE capability is requested.
* @global_node: list_head for global dma_client_list
*/
struct dma_client {
dma_event_callback event_callback;
dma_cap_mask_t cap_mask;
+ struct dma_slave *slave;
struct list_head global_node;
};
@@ -263,6 +311,8 @@ struct dma_async_tx_descriptor {
* @device_prep_dma_zero_sum: prepares a zero_sum operation
* @device_prep_dma_memset: prepares a memset operation
* @device_prep_dma_interrupt: prepares an end of chain interrupt operation
+ * @device_prep_slave_sg: prepares a slave dma operation
+ * @device_terminate_all: terminate all pending operations
* @device_issue_pending: push pending transactions to hardware
*/
struct dma_device {
@@ -279,7 +329,8 @@ struct dma_device {
int dev_id;
struct device *dev;
- int (*device_alloc_chan_resources)(struct dma_chan *chan);
+ int (*device_alloc_chan_resources)(struct dma_chan *chan,
+ struct dma_client *client);
void (*device_free_chan_resources)(struct dma_chan *chan);
struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)(
@@ -297,6 +348,12 @@ struct dma_device {
struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(
struct dma_chan *chan, unsigned long flags);
+ struct dma_async_tx_descriptor *(*device_prep_slave_sg)(
+ struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_data_direction direction,
+ unsigned long flags);
+ void (*device_terminate_all)(struct dma_chan *chan);
+
enum dma_status (*device_is_tx_complete)(struct dma_chan *chan,
dma_cookie_t cookie, dma_cookie_t *last,
dma_cookie_t *used);
@@ -318,16 +375,14 @@ dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan,
void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
struct dma_chan *chan);
-static inline void
-async_tx_ack(struct dma_async_tx_descriptor *tx)
+static inline void async_tx_ack(struct dma_async_tx_descriptor *tx)
{
tx->flags |= DMA_CTRL_ACK;
}
-static inline int
-async_tx_test_ack(struct dma_async_tx_descriptor *tx)
+static inline bool async_tx_test_ack(struct dma_async_tx_descriptor *tx)
{
- return tx->flags & DMA_CTRL_ACK;
+ return (tx->flags & DMA_CTRL_ACK) == DMA_CTRL_ACK;
}
#define first_dma_cap(mask) __first_dma_cap(&(mask))
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
new file mode 100644
index 00000000000..04d217b442b
--- /dev/null
+++ b/include/linux/dw_dmac.h
@@ -0,0 +1,62 @@
+/*
+ * Driver for the Synopsys DesignWare DMA Controller (aka DMACA on
+ * AVR32 systems.)
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * 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.
+ */
+#ifndef DW_DMAC_H
+#define DW_DMAC_H
+
+#include <linux/dmaengine.h>
+
+/**
+ * struct dw_dma_platform_data - Controller configuration parameters
+ * @nr_channels: Number of channels supported by hardware (max 8)
+ */
+struct dw_dma_platform_data {
+ unsigned int nr_channels;
+};
+
+/**
+ * struct dw_dma_slave - Controller-specific information about a slave
+ * @slave: Generic information about the slave
+ * @ctl_lo: Platform-specific initializer for the CTL_LO register
+ * @cfg_hi: Platform-specific initializer for the CFG_HI register
+ * @cfg_lo: Platform-specific initializer for the CFG_LO register
+ */
+struct dw_dma_slave {
+ struct dma_slave slave;
+ u32 cfg_hi;
+ u32 cfg_lo;
+};
+
+/* Platform-configurable bits in CFG_HI */
+#define DWC_CFGH_FCMODE (1 << 0)
+#define DWC_CFGH_FIFO_MODE (1 << 1)
+#define DWC_CFGH_PROTCTL(x) ((x) << 2)
+#define DWC_CFGH_SRC_PER(x) ((x) << 7)
+#define DWC_CFGH_DST_PER(x) ((x) << 11)
+
+/* Platform-configurable bits in CFG_LO */
+#define DWC_CFGL_PRIO(x) ((x) << 5) /* priority */
+#define DWC_CFGL_LOCK_CH_XFER (0 << 12) /* scope of LOCK_CH */
+#define DWC_CFGL_LOCK_CH_BLOCK (1 << 12)
+#define DWC_CFGL_LOCK_CH_XACT (2 << 12)
+#define DWC_CFGL_LOCK_BUS_XFER (0 << 14) /* scope of LOCK_BUS */
+#define DWC_CFGL_LOCK_BUS_BLOCK (1 << 14)
+#define DWC_CFGL_LOCK_BUS_XACT (2 << 14)
+#define DWC_CFGL_LOCK_CH (1 << 15) /* channel lockout */
+#define DWC_CFGL_LOCK_BUS (1 << 16) /* busmaster lockout */
+#define DWC_CFGL_HS_DST_POL (1 << 18) /* dst handshake active low */
+#define DWC_CFGL_HS_SRC_POL (1 << 19) /* src handshake active low */
+
+static inline struct dw_dma_slave *to_dw_dma_slave(struct dma_slave *slave)
+{
+ return container_of(slave, struct dw_dma_slave, slave);
+}
+
+#endif /* DW_DMAC_H */
diff --git a/include/linux/eisa.h b/include/linux/eisa.h
index fe806b6f030..e61c0be2a45 100644
--- a/include/linux/eisa.h
+++ b/include/linux/eisa.h
@@ -40,7 +40,7 @@ struct eisa_device {
u64 dma_mask;
struct device dev; /* generic device */
#ifdef CONFIG_EISA_NAMES
- char pretty_name[DEVICE_NAME_SIZE];
+ char pretty_name[50];
#endif
};
diff --git a/include/linux/eventfd.h b/include/linux/eventfd.h
index a701399b7fe..a667637b54e 100644
--- a/include/linux/eventfd.h
+++ b/include/linux/eventfd.h
@@ -10,6 +10,13 @@
#ifdef CONFIG_EVENTFD
+/* For O_CLOEXEC and O_NONBLOCK */
+#include <linux/fcntl.h>
+
+/* Flags for eventfd2. */
+#define EFD_CLOEXEC O_CLOEXEC
+#define EFD_NONBLOCK O_NONBLOCK
+
struct file *eventfd_fget(int fd);
int eventfd_signal(struct file *file, int n);
diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h
index cf79853967f..f1e1d3c4712 100644
--- a/include/linux/eventpoll.h
+++ b/include/linux/eventpoll.h
@@ -14,8 +14,12 @@
#ifndef _LINUX_EVENTPOLL_H
#define _LINUX_EVENTPOLL_H
+/* For O_CLOEXEC */
+#include <linux/fcntl.h>
#include <linux/types.h>
+/* Flags for epoll_create1. */
+#define EPOLL_CLOEXEC O_CLOEXEC
/* Valid opcodes to issue to sys_epoll_ctl() */
#define EPOLL_CTL_ADD 1
diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h
index 84cec2aa9f1..2efe7b863cf 100644
--- a/include/linux/ext2_fs.h
+++ b/include/linux/ext2_fs.h
@@ -284,8 +284,8 @@ struct ext2_inode {
#ifdef __hurd__
#define i_translator osd1.hurd1.h_i_translator
-#define i_frag osd2.hurd2.h_i_frag;
-#define i_fsize osd2.hurd2.h_i_fsize;
+#define i_frag osd2.hurd2.h_i_frag
+#define i_fsize osd2.hurd2.h_i_fsize
#define i_uid_high osd2.hurd2.h_i_uid_high
#define i_gid_high osd2.hurd2.h_i_gid_high
#define i_author osd2.hurd2.h_i_author
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 36c54039637..80171ee89a2 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -832,6 +832,7 @@ extern void ext3_discard_reservation (struct inode *);
extern void ext3_dirty_inode(struct inode *);
extern int ext3_change_inode_journal_flag(struct inode *, int);
extern int ext3_get_inode_loc(struct inode *, struct ext3_iloc *);
+extern int ext3_can_truncate(struct inode *inode);
extern void ext3_truncate (struct inode *);
extern void ext3_set_inode_flags(struct inode *);
extern void ext3_get_inode_flags(struct ext3_inode_info *);
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 72295b09922..3b8870e32af 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -8,7 +8,6 @@ struct dentry;
/* Definitions of frame buffers */
-#define FB_MAJOR 29
#define FB_MAX 32 /* sufficient for now */
/* ioctls
@@ -120,6 +119,10 @@ struct dentry;
#define FB_ACCEL_XGI_VOLARI_V 47 /* XGI Volari V3XT, V5, V8 */
#define FB_ACCEL_XGI_VOLARI_Z 48 /* XGI Volari Z7 */
#define FB_ACCEL_OMAP1610 49 /* TI OMAP16xx */
+#define FB_ACCEL_TRIDENT_TGUI 50 /* Trident TGUI */
+#define FB_ACCEL_TRIDENT_3DIMAGE 51 /* Trident 3DImage */
+#define FB_ACCEL_TRIDENT_BLADE3D 52 /* Trident Blade3D */
+#define FB_ACCEL_TRIDENT_BLADEXP 53 /* Trident BladeXP */
#define FB_ACCEL_NEOMAGIC_NM2070 90 /* NeoMagic NM2070 */
#define FB_ACCEL_NEOMAGIC_NM2090 91 /* NeoMagic NM2090 */
#define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */
diff --git a/include/linux/fd1772.h b/include/linux/fd1772.h
deleted file mode 100644
index 871d6e4c677..00000000000
--- a/include/linux/fd1772.h
+++ /dev/null
@@ -1,80 +0,0 @@
-#ifndef _LINUX_FD1772REG_H
-#define _LINUX_FD1772REG_H
-
-/*
-** WD1772 stuff - originally from the M68K Linux
- * Modified for Archimedes by Dave Gilbert (gilbertd@cs.man.ac.uk)
- */
-
-/* register codes */
-
-#define FDC1772SELREG_STP (0x80) /* command/status register */
-#define FDC1772SELREG_TRA (0x82) /* track register */
-#define FDC1772SELREG_SEC (0x84) /* sector register */
-#define FDC1772SELREG_DTA (0x86) /* data register */
-
-/* register names for FDC1772_READ/WRITE macros */
-
-#define FDC1772REG_CMD 0
-#define FDC1772REG_STATUS 0
-#define FDC1772REG_TRACK 2
-#define FDC1772REG_SECTOR 4
-#define FDC1772REG_DATA 6
-
-/* command opcodes */
-
-#define FDC1772CMD_RESTORE (0x00) /* - */
-#define FDC1772CMD_SEEK (0x10) /* | */
-#define FDC1772CMD_STEP (0x20) /* | TYP 1 Commands */
-#define FDC1772CMD_STIN (0x40) /* | */
-#define FDC1772CMD_STOT (0x60) /* - */
-#define FDC1772CMD_RDSEC (0x80) /* - TYP 2 Commands */
-#define FDC1772CMD_WRSEC (0xa0) /* - " */
-#define FDC1772CMD_RDADR (0xc0) /* - */
-#define FDC1772CMD_RDTRA (0xe0) /* | TYP 3 Commands */
-#define FDC1772CMD_WRTRA (0xf0) /* - */
-#define FDC1772CMD_FORCI (0xd0) /* - TYP 4 Command */
-
-/* command modifier bits */
-
-#define FDC1772CMDADD_SR6 (0x00) /* step rate settings */
-#define FDC1772CMDADD_SR12 (0x01)
-#define FDC1772CMDADD_SR2 (0x02)
-#define FDC1772CMDADD_SR3 (0x03)
-#define FDC1772CMDADD_V (0x04) /* verify */
-#define FDC1772CMDADD_H (0x08) /* wait for spin-up */
-#define FDC1772CMDADD_U (0x10) /* update track register */
-#define FDC1772CMDADD_M (0x10) /* multiple sector access */
-#define FDC1772CMDADD_E (0x04) /* head settling flag */
-#define FDC1772CMDADD_P (0x02) /* precompensation */
-#define FDC1772CMDADD_A0 (0x01) /* DAM flag */
-
-/* status register bits */
-
-#define FDC1772STAT_MOTORON (0x80) /* motor on */
-#define FDC1772STAT_WPROT (0x40) /* write protected (FDC1772CMD_WR*) */
-#define FDC1772STAT_SPINUP (0x20) /* motor speed stable (Type I) */
-#define FDC1772STAT_DELDAM (0x20) /* sector has deleted DAM (Type II+III) */
-#define FDC1772STAT_RECNF (0x10) /* record not found */
-#define FDC1772STAT_CRC (0x08) /* CRC error */
-#define FDC1772STAT_TR00 (0x04) /* Track 00 flag (Type I) */
-#define FDC1772STAT_LOST (0x04) /* Lost Data (Type II+III) */
-#define FDC1772STAT_IDX (0x02) /* Index status (Type I) */
-#define FDC1772STAT_DRQ (0x02) /* DRQ status (Type II+III) */
-#define FDC1772STAT_BUSY (0x01) /* FDC1772 is busy */
-
-
-/* PSG Port A Bit Nr 0 .. Side Sel .. 0 -> Side 1 1 -> Side 2 */
-#define DSKSIDE (0x01)
-
-#define DSKDRVNONE (0x06)
-#define DSKDRV0 (0x02)
-#define DSKDRV1 (0x04)
-
-/* step rates */
-#define FDC1772STEP_6 0x00
-#define FDC1772STEP_12 0x01
-#define FDC1772STEP_2 0x02
-#define FDC1772STEP_3 0x03
-
-#endif
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9c2ac5c0ef5..49d8eb7a71b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -886,6 +886,12 @@ static inline int file_check_writeable(struct file *filp)
#define FL_SLEEP 128 /* A blocking lock */
/*
+ * Special return value from posix_lock_file() and vfs_lock_file() for
+ * asynchronous locking.
+ */
+#define FILE_LOCK_DEFERRED 1
+
+/*
* The POSIX file lock owner is determined by
* the "struct files_struct" in the thread group
* (or NULL for no owner - BSD locks).
@@ -1025,6 +1031,7 @@ extern int send_sigurg(struct fown_struct *fown);
extern struct list_head super_blocks;
extern spinlock_t sb_lock;
+#define sb_entry(list) list_entry((list), struct super_block, s_list)
#define S_BIAS (1<<30)
struct super_block {
struct list_head s_list; /* Keep this first */
@@ -1058,6 +1065,9 @@ struct super_block {
struct list_head s_more_io; /* parked for more writeback */
struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */
struct list_head s_files;
+ /* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */
+ struct list_head s_dentry_lru; /* unused dentry lru */
+ int s_nr_dentry_unused; /* # of dentry on lru */
struct block_device *s_bdev;
struct mtd_info *s_mtd;
@@ -1773,8 +1783,9 @@ static inline void allow_write_access(struct file *file)
atomic_inc(&file->f_path.dentry->d_inode->i_writecount);
}
extern int do_pipe(int *);
-extern struct file *create_read_pipe(struct file *f);
-extern struct file *create_write_pipe(void);
+extern int do_pipe_flags(int *, int);
+extern struct file *create_read_pipe(struct file *f, int flags);
+extern struct file *create_write_pipe(int flags);
extern void free_write_pipe(struct file *);
extern struct file *do_filp_open(int dfd, const char *pathname,
@@ -2006,8 +2017,6 @@ extern void simple_release_fs(struct vfsmount **mount, int *count);
extern ssize_t simple_read_from_buffer(void __user *to, size_t count,
loff_t *ppos, const void *from, size_t available);
-extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
- const void *from, size_t available);
#ifdef CONFIG_MIGRATION
extern int buffer_migrate_page(struct address_space *,
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 9bc045b8c47..8300cab30f9 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -103,10 +103,6 @@ struct fs_mii_bb_platform_info {
struct fs_mii_bit mdio_dir;
struct fs_mii_bit mdio_dat;
struct fs_mii_bit mdc_dat;
- int mdio_port; /* port & bit for MDIO */
- int mdio_bit;
- int mdc_port; /* port & bit for MDC */
- int mdc_bit;
int delay; /* delay in us */
int irq[32]; /* irqs per phy's */
};
@@ -135,11 +131,7 @@ struct fs_platform_info {
u32 device_flags;
int phy_addr; /* the phy address (-1 no phy) */
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
char bus_id[16];
-#else
- const char* bus_id;
-#endif
int phy_irq; /* the phy irq (if it exists) */
const struct fs_mii_bus_info *bus_info;
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index c415a496de3..4e625e0094c 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -69,6 +69,7 @@ struct gianfar_mdio_data {
#define FSL_GIANFAR_DEV_HAS_VLAN 0x00000020
#define FSL_GIANFAR_DEV_HAS_EXTENDED_HASH 0x00000040
#define FSL_GIANFAR_DEV_HAS_PADDING 0x00000080
+#define FSL_GIANFAR_DEV_HAS_MAGIC_PACKET 0x00000100
/* Flags in gianfar_platform_data */
#define FSL_GIANFAR_BRD_HAS_PHY_INTR 0x00000001 /* set or use a timer */
@@ -125,4 +126,10 @@ struct mpc8xx_pcmcia_ops {
int(*voltage_set)(int slot, int vcc, int vpp);
};
+/* Returns non-zero if the current suspend operation would
+ * lead to a deep sleep (i.e. power removed from the core,
+ * instead of just the clock).
+ */
+int fsl_deep_sleep(void);
+
#endif /* _FSL_DEVICE_H_ */
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index d4828219769..265635dc990 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -104,11 +104,14 @@ struct fuse_file_lock {
/**
* INIT request/reply flags
+ *
+ * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".."
*/
#define FUSE_ASYNC_READ (1 << 0)
#define FUSE_POSIX_LOCKS (1 << 1)
#define FUSE_FILE_OPS (1 << 2)
#define FUSE_ATOMIC_O_TRUNC (1 << 3)
+#define FUSE_EXPORT_SUPPORT (1 << 4)
#define FUSE_BIG_WRITES (1 << 5)
/**
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index e8787417f65..118216f1bd3 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -541,7 +541,7 @@ extern dev_t blk_lookup_devt(const char *name, int part);
extern char *disk_name (struct gendisk *hd, int part, char *buf);
extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
-extern void add_partition(struct gendisk *, int, sector_t, sector_t, int);
+extern int __must_check add_partition(struct gendisk *, int, sector_t, sector_t, int);
extern void delete_partition(struct gendisk *, int);
extern void printk_all_partitions(void);
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index b414be38718..e8003afeffb 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -173,11 +173,24 @@ static inline void arch_free_page(struct page *page, int order) { }
static inline void arch_alloc_page(struct page *page, int order) { }
#endif
-extern struct page *__alloc_pages(gfp_t, unsigned int, struct zonelist *);
+struct page *
+__alloc_pages_internal(gfp_t gfp_mask, unsigned int order,
+ struct zonelist *zonelist, nodemask_t *nodemask);
+
+static inline struct page *
+__alloc_pages(gfp_t gfp_mask, unsigned int order,
+ struct zonelist *zonelist)
+{
+ return __alloc_pages_internal(gfp_mask, order, zonelist, NULL);
+}
+
+static inline struct page *
+__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
+ struct zonelist *zonelist, nodemask_t *nodemask)
+{
+ return __alloc_pages_internal(gfp_mask, order, zonelist, nodemask);
+}
-extern struct page *
-__alloc_pages_nodemask(gfp_t, unsigned int,
- struct zonelist *, nodemask_t *nodemask);
static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask,
unsigned int order)
@@ -215,6 +228,9 @@ extern struct page *alloc_page_vma(gfp_t gfp_mask,
extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);
extern unsigned long get_zeroed_page(gfp_t gfp_mask);
+void *alloc_pages_exact(size_t size, gfp_t gfp_mask);
+void free_pages_exact(void *virt, size_t size);
+
#define __get_free_page(gfp_mask) \
__get_free_pages((gfp_mask),0)
diff --git a/include/linux/gpio.h b/include/linux/gpio.h
index 98be6c5762b..730a20b8357 100644
--- a/include/linux/gpio.h
+++ b/include/linux/gpio.h
@@ -79,6 +79,19 @@ static inline void gpio_set_value_cansleep(unsigned gpio, int value)
WARN_ON(1);
}
+static inline int gpio_export(unsigned gpio, bool direction_may_change)
+{
+ /* GPIO can never have been requested or set as {in,out}put */
+ WARN_ON(1);
+ return -EINVAL;
+}
+
+static inline void gpio_unexport(unsigned gpio)
+{
+ /* GPIO can never have been exported */
+ WARN_ON(1);
+}
+
static inline int gpio_to_irq(unsigned gpio)
{
/* GPIO can never have been requested or set as input */
diff --git a/include/linux/hid.h b/include/linux/hid.h
index fe56b86f2c6..ac4e678a04e 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -512,7 +512,7 @@ struct hid_descriptor {
/* Applications from HID Usage Tables 4/8/99 Version 1.1 */
/* We ignore a few input applications that are not widely used */
-#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001))
+#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001) || (a == 0x000d0002))
/* HID core API */
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index a79e80b689d..9a71d4cc88c 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -8,7 +8,6 @@
#include <linux/mempolicy.h>
#include <linux/shm.h>
#include <asm/tlbflush.h>
-#include <asm/hugetlb.h>
struct ctl_table;
@@ -17,38 +16,45 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
return vma->vm_flags & VM_HUGETLB;
}
+void reset_vma_resv_huge_pages(struct vm_area_struct *vma);
int hugetlb_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
int hugetlb_overcommit_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
int hugetlb_treat_movable_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *);
int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int, int);
-void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
-void __unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
+void unmap_hugepage_range(struct vm_area_struct *,
+ unsigned long, unsigned long, struct page *);
+void __unmap_hugepage_range(struct vm_area_struct *,
+ unsigned long, unsigned long, struct page *);
int hugetlb_prefault(struct address_space *, struct vm_area_struct *);
int hugetlb_report_meminfo(char *);
int hugetlb_report_node_meminfo(int, char *);
unsigned long hugetlb_total_pages(void);
int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long address, int write_access);
-int hugetlb_reserve_pages(struct inode *inode, long from, long to);
+int hugetlb_reserve_pages(struct inode *inode, long from, long to,
+ struct vm_area_struct *vma);
void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed);
-extern unsigned long max_huge_pages;
-extern unsigned long sysctl_overcommit_huge_pages;
extern unsigned long hugepages_treat_as_movable;
extern const unsigned long hugetlb_zero, hugetlb_infinity;
extern int sysctl_hugetlb_shm_group;
+extern struct list_head huge_boot_pages;
/* arch callbacks */
-pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr);
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+ unsigned long addr, unsigned long sz);
pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr);
int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep);
struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
int write);
struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
pmd_t *pmd, int write);
+struct page *follow_huge_pud(struct mm_struct *mm, unsigned long address,
+ pud_t *pud, int write);
int pmd_huge(pmd_t pmd);
+int pud_huge(pud_t pmd);
void hugetlb_change_protection(struct vm_area_struct *vma,
unsigned long address, unsigned long end, pgprot_t newprot);
@@ -58,6 +64,11 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
{
return 0;
}
+
+static inline void reset_vma_resv_huge_pages(struct vm_area_struct *vma)
+{
+}
+
static inline unsigned long hugetlb_total_pages(void)
{
return 0;
@@ -67,12 +78,14 @@ static inline unsigned long hugetlb_total_pages(void)
#define follow_huge_addr(mm, addr, write) ERR_PTR(-EINVAL)
#define copy_hugetlb_page_range(src, dst, vma) ({ BUG(); 0; })
#define hugetlb_prefault(mapping, vma) ({ BUG(); 0; })
-#define unmap_hugepage_range(vma, start, end) BUG()
+#define unmap_hugepage_range(vma, start, end, page) BUG()
#define hugetlb_report_meminfo(buf) 0
#define hugetlb_report_node_meminfo(n, buf) 0
#define follow_huge_pmd(mm, addr, pmd, write) NULL
-#define prepare_hugepage_range(addr,len) (-EINVAL)
+#define follow_huge_pud(mm, addr, pud, write) NULL
+#define prepare_hugepage_range(file, addr, len) (-EINVAL)
#define pmd_huge(x) 0
+#define pud_huge(x) 0
#define is_hugepage_only_range(mm, addr, len) 0
#define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) ({BUG(); 0; })
#define hugetlb_fault(mm, vma, addr, write) ({ BUG(); 0; })
@@ -93,6 +106,7 @@ struct hugetlbfs_config {
umode_t mode;
long nr_blocks;
long nr_inodes;
+ struct hstate *hstate;
};
struct hugetlbfs_sb_info {
@@ -101,6 +115,7 @@ struct hugetlbfs_sb_info {
long max_inodes; /* inodes allowed */
long free_inodes; /* inodes free */
spinlock_t stat_lock;
+ struct hstate *hstate;
};
@@ -125,8 +140,6 @@ struct file *hugetlb_file_setup(const char *name, size_t);
int hugetlb_get_quota(struct address_space *mapping, long delta);
void hugetlb_put_quota(struct address_space *mapping, long delta);
-#define BLOCKS_PER_HUGEPAGE (HPAGE_SIZE / 512)
-
static inline int is_file_hugepages(struct file *file)
{
if (file->f_op == &hugetlbfs_file_operations)
@@ -155,4 +168,112 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
unsigned long flags);
#endif /* HAVE_ARCH_HUGETLB_UNMAPPED_AREA */
+#ifdef CONFIG_HUGETLB_PAGE
+
+#define HSTATE_NAME_LEN 32
+/* Defines one hugetlb page size */
+struct hstate {
+ int hugetlb_next_nid;
+ unsigned int order;
+ unsigned long mask;
+ unsigned long max_huge_pages;
+ unsigned long nr_huge_pages;
+ unsigned long free_huge_pages;
+ unsigned long resv_huge_pages;
+ unsigned long surplus_huge_pages;
+ unsigned long nr_overcommit_huge_pages;
+ struct list_head hugepage_freelists[MAX_NUMNODES];
+ unsigned int nr_huge_pages_node[MAX_NUMNODES];
+ unsigned int free_huge_pages_node[MAX_NUMNODES];
+ unsigned int surplus_huge_pages_node[MAX_NUMNODES];
+ char name[HSTATE_NAME_LEN];
+};
+
+struct huge_bootmem_page {
+ struct list_head list;
+ struct hstate *hstate;
+};
+
+/* arch callback */
+int __init alloc_bootmem_huge_page(struct hstate *h);
+
+void __init hugetlb_add_hstate(unsigned order);
+struct hstate *size_to_hstate(unsigned long size);
+
+#ifndef HUGE_MAX_HSTATE
+#define HUGE_MAX_HSTATE 1
+#endif
+
+extern struct hstate hstates[HUGE_MAX_HSTATE];
+extern unsigned int default_hstate_idx;
+
+#define default_hstate (hstates[default_hstate_idx])
+
+static inline struct hstate *hstate_inode(struct inode *i)
+{
+ struct hugetlbfs_sb_info *hsb;
+ hsb = HUGETLBFS_SB(i->i_sb);
+ return hsb->hstate;
+}
+
+static inline struct hstate *hstate_file(struct file *f)
+{
+ return hstate_inode(f->f_dentry->d_inode);
+}
+
+static inline struct hstate *hstate_vma(struct vm_area_struct *vma)
+{
+ return hstate_file(vma->vm_file);
+}
+
+static inline unsigned long huge_page_size(struct hstate *h)
+{
+ return (unsigned long)PAGE_SIZE << h->order;
+}
+
+static inline unsigned long huge_page_mask(struct hstate *h)
+{
+ return h->mask;
+}
+
+static inline unsigned int huge_page_order(struct hstate *h)
+{
+ return h->order;
+}
+
+static inline unsigned huge_page_shift(struct hstate *h)
+{
+ return h->order + PAGE_SHIFT;
+}
+
+static inline unsigned int pages_per_huge_page(struct hstate *h)
+{
+ return 1 << h->order;
+}
+
+static inline unsigned int blocks_per_huge_page(struct hstate *h)
+{
+ return huge_page_size(h) / 512;
+}
+
+#include <asm/hugetlb.h>
+
+static inline struct hstate *page_hstate(struct page *page)
+{
+ return size_to_hstate(PAGE_SIZE << compound_order(page));
+}
+
+#else
+struct hstate {};
+#define alloc_bootmem_huge_page(h) NULL
+#define hstate_file(f) NULL
+#define hstate_vma(v) NULL
+#define hstate_inode(i) NULL
+#define huge_page_size(h) PAGE_SIZE
+#define huge_page_mask(h) PAGE_MASK
+#define huge_page_order(h) 0
+#define huge_page_shift(h) PAGE_SHIFT
+#define pages_per_huge_page(h) 1
+#endif
+
#endif /* _LINUX_HUGETLB_H */
diff --git a/include/linux/i2c/max732x.h b/include/linux/i2c/max732x.h
new file mode 100644
index 00000000000..e10336631c6
--- /dev/null
+++ b/include/linux/i2c/max732x.h
@@ -0,0 +1,19 @@
+#ifndef __LINUX_I2C_MAX732X_H
+#define __LINUX_I2C_MAX732X_H
+
+/* platform data for the MAX732x 8/16-bit I/O expander driver */
+
+struct max732x_platform_data {
+ /* number of the first GPIO */
+ unsigned gpio_base;
+
+ void *context; /* param to setup/teardown */
+
+ int (*setup)(struct i2c_client *client,
+ unsigned gpio, unsigned ngpio,
+ void *context);
+ int (*teardown)(struct i2c_client *client,
+ unsigned gpio, unsigned ngpio,
+ void *context);
+};
+#endif /* __LINUX_I2C_MAX732X_H */
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 4726126f5a5..b846bc44a27 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -178,6 +178,7 @@ typedef struct hw_regs_s {
ide_ack_intr_t *ack_intr; /* acknowledge interrupt */
hwif_chipset_t chipset;
struct device *dev, *parent;
+ unsigned long config;
} hw_regs_t;
void ide_init_port_data(struct hwif_s *, unsigned int);
@@ -210,7 +211,21 @@ static inline int __ide_default_irq(unsigned long base)
return 0;
}
+#if defined(CONFIG_ARM) || defined(CONFIG_FRV) || defined(CONFIG_M68K) || \
+ defined(CONFIG_MIPS) || defined(CONFIG_MN10300) || defined(CONFIG_PARISC) \
+ || defined(CONFIG_PPC) || defined(CONFIG_SPARC) || defined(CONFIG_SPARC64)
#include <asm/ide.h>
+#else
+#include <asm-generic/ide_iops.h>
+#endif
+
+#ifndef MAX_HWIFS
+#if defined(CONFIG_BLACKFIN) || defined(CONFIG_H8300) || defined(CONFIG_XTENSA)
+# define MAX_HWIFS 1
+#else
+# define MAX_HWIFS 10
+#endif
+#endif
#if !defined(MAX_HWIFS) || defined(CONFIG_EMBEDDED)
#undef MAX_HWIFS
@@ -307,7 +322,65 @@ struct ide_acpi_drive_link;
struct ide_acpi_hwif_link;
#endif
-typedef struct ide_drive_s {
+/* ATAPI device flags */
+enum {
+ IDE_AFLAG_DRQ_INTERRUPT = (1 << 0),
+ IDE_AFLAG_MEDIA_CHANGED = (1 << 1),
+
+ /* ide-cd */
+ /* Drive cannot lock the door. */
+ IDE_AFLAG_NO_DOORLOCK = (1 << 2),
+ /* Drive cannot eject the disc. */
+ IDE_AFLAG_NO_EJECT = (1 << 3),
+ /* Drive is a pre ATAPI 1.2 drive. */
+ IDE_AFLAG_PRE_ATAPI12 = (1 << 4),
+ /* TOC addresses are in BCD. */
+ IDE_AFLAG_TOCADDR_AS_BCD = (1 << 5),
+ /* TOC track numbers are in BCD. */
+ IDE_AFLAG_TOCTRACKS_AS_BCD = (1 << 6),
+ /*
+ * Drive does not provide data in multiples of SECTOR_SIZE
+ * when more than one interrupt is needed.
+ */
+ IDE_AFLAG_LIMIT_NFRAMES = (1 << 7),
+ /* Seeking in progress. */
+ IDE_AFLAG_SEEKING = (1 << 8),
+ /* Saved TOC information is current. */
+ IDE_AFLAG_TOC_VALID = (1 << 9),
+ /* We think that the drive door is locked. */
+ IDE_AFLAG_DOOR_LOCKED = (1 << 10),
+ /* SET_CD_SPEED command is unsupported. */
+ IDE_AFLAG_NO_SPEED_SELECT = (1 << 11),
+ IDE_AFLAG_VERTOS_300_SSD = (1 << 12),
+ IDE_AFLAG_VERTOS_600_ESD = (1 << 13),
+ IDE_AFLAG_SANYO_3CD = (1 << 14),
+ IDE_AFLAG_FULL_CAPS_PAGE = (1 << 15),
+ IDE_AFLAG_PLAY_AUDIO_OK = (1 << 16),
+ IDE_AFLAG_LE_SPEED_FIELDS = (1 << 17),
+
+ /* ide-floppy */
+ /* Format in progress */
+ IDE_AFLAG_FORMAT_IN_PROGRESS = (1 << 18),
+ /* Avoid commands not supported in Clik drive */
+ IDE_AFLAG_CLIK_DRIVE = (1 << 19),
+ /* Requires BH algorithm for packets */
+ IDE_AFLAG_ZIP_DRIVE = (1 << 20),
+
+ /* ide-tape */
+ IDE_AFLAG_IGNORE_DSC = (1 << 21),
+ /* 0 When the tape position is unknown */
+ IDE_AFLAG_ADDRESS_VALID = (1 << 22),
+ /* Device already opened */
+ IDE_AFLAG_BUSY = (1 << 23),
+ /* Attempt to auto-detect the current user block size */
+ IDE_AFLAG_DETECT_BS = (1 << 24),
+ /* Currently on a filemark */
+ IDE_AFLAG_FILEMARK = (1 << 25),
+ /* 0 = no tape is loaded, so we don't rewind after ejecting */
+ IDE_AFLAG_MEDIUM_PRESENT = (1 << 26)
+};
+
+struct ide_drive_s {
char name[4]; /* drive name, such as "hda" */
char driver_req[10]; /* requests specific driver */
@@ -355,7 +428,6 @@ typedef struct ide_drive_s {
unsigned nodma : 1; /* disallow DMA */
unsigned remap_0_to_1 : 1; /* 0=noremap, 1=remap 0->1 (for EZDrive) */
unsigned blocked : 1; /* 1=powermanagment told us not to do anything, so sleep nicely */
- unsigned vdma : 1; /* 1=doing PIO over DMA 0=doing normal DMA */
unsigned scsi : 1; /* 0=default, 1=ide-scsi emulation */
unsigned sleeping : 1; /* 1=sleeping & sleep field valid */
unsigned post_reset : 1;
@@ -400,7 +472,14 @@ typedef struct ide_drive_s {
struct list_head list;
struct device gendev;
struct completion gendev_rel_comp; /* to deal with device release() */
-} ide_drive_t;
+
+ /* callback for packet commands */
+ void (*pc_callback)(struct ide_drive_s *);
+
+ unsigned long atapi_flags;
+};
+
+typedef struct ide_drive_s ide_drive_t;
#define to_ide_device(dev)container_of(dev, ide_drive_t, gendev)
@@ -408,8 +487,28 @@ typedef struct ide_drive_s {
((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx))
#define IDE_CHIPSET_IS_PCI(c) ((IDE_CHIPSET_PCI_MASK >> (c)) & 1)
+struct ide_task_s;
struct ide_port_info;
+struct ide_tp_ops {
+ void (*exec_command)(struct hwif_s *, u8);
+ u8 (*read_status)(struct hwif_s *);
+ u8 (*read_altstatus)(struct hwif_s *);
+ u8 (*read_sff_dma_status)(struct hwif_s *);
+
+ void (*set_irq)(struct hwif_s *, int);
+
+ void (*tf_load)(ide_drive_t *, struct ide_task_s *);
+ void (*tf_read)(ide_drive_t *, struct ide_task_s *);
+
+ void (*input_data)(ide_drive_t *, struct request *, void *,
+ unsigned int);
+ void (*output_data)(ide_drive_t *, struct request *, void *,
+ unsigned int);
+};
+
+extern const struct ide_tp_ops default_tp_ops;
+
struct ide_port_ops {
/* host specific initialization of a device */
void (*init_dev)(ide_drive_t *);
@@ -447,7 +546,7 @@ struct ide_dma_ops {
void (*dma_timeout)(struct ide_drive_s *);
};
-struct ide_task_s;
+struct ide_host;
typedef struct hwif_s {
struct hwif_s *next; /* for linked-list in ide_hwgroup_t */
@@ -455,6 +554,8 @@ typedef struct hwif_s {
struct hwgroup_s *hwgroup; /* actually (ide_hwgroup_t *) */
struct proc_dir_entry *proc; /* /proc/ide/ directory entry */
+ struct ide_host *host;
+
char name[6]; /* name of interface, eg. "ide0" */
struct ide_io_ports io_ports;
@@ -486,22 +587,12 @@ typedef struct hwif_s {
void (*rw_disk)(ide_drive_t *, struct request *);
+ const struct ide_tp_ops *tp_ops;
const struct ide_port_ops *port_ops;
const struct ide_dma_ops *dma_ops;
- void (*tf_load)(ide_drive_t *, struct ide_task_s *);
- void (*tf_read)(ide_drive_t *, struct ide_task_s *);
-
- void (*input_data)(ide_drive_t *, struct request *, void *, unsigned);
- void (*output_data)(ide_drive_t *, struct request *, void *, unsigned);
-
void (*ide_dma_clear_irq)(ide_drive_t *drive);
- void (*OUTB)(u8 addr, unsigned long port);
- void (*OUTBSYNC)(struct hwif_s *hwif, u8 addr, unsigned long port);
-
- u8 (*INB)(unsigned long port);
-
/* dma physical region descriptor table (cpu view) */
unsigned int *dmatable_cpu;
/* dma physical region descriptor table (dma view) */
@@ -524,8 +615,6 @@ typedef struct hwif_s {
int irq; /* our irq number */
unsigned long dma_base; /* base addr for dma ports */
- unsigned long dma_command; /* dma command register */
- unsigned long dma_status; /* dma status register */
unsigned long config_data; /* for use by chipset-specific code */
unsigned long select_data; /* for use by chipset-specific code */
@@ -552,6 +641,14 @@ typedef struct hwif_s {
#endif
} ____cacheline_internodealigned_in_smp ide_hwif_t;
+struct ide_host {
+ ide_hwif_t *ports[MAX_HWIFS];
+ unsigned int n_ports;
+ struct device *dev[2];
+ unsigned long host_flags;
+ void *host_priv;
+};
+
/*
* internal ide interrupt handler type
*/
@@ -611,8 +708,6 @@ enum {
PC_FLAG_WRITING = (1 << 6),
/* command timed out */
PC_FLAG_TIMEDOUT = (1 << 7),
- PC_FLAG_ZIP_DRIVE = (1 << 8),
- PC_FLAG_DRQ_INTERRUPT = (1 << 9),
};
struct ide_atapi_pc {
@@ -646,8 +741,6 @@ struct ide_atapi_pc {
*/
u8 pc_buf[256];
- void (*callback)(ide_drive_t *);
-
/* idetape only */
struct idetape_bh *bh;
char *b_data;
@@ -802,18 +895,14 @@ struct ide_driver_s {
#define to_ide_driver(drv) container_of(drv, ide_driver_t, gen_driver)
+int ide_device_get(ide_drive_t *);
+void ide_device_put(ide_drive_t *);
+
int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long);
extern int ide_vlb_clk;
extern int ide_pci_clk;
-ide_hwif_t *ide_find_port_slot(const struct ide_port_info *);
-
-static inline ide_hwif_t *ide_find_port(void)
-{
- return ide_find_port_slot(NULL);
-}
-
extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
int uptodate, int nr_sectors);
@@ -884,6 +973,7 @@ enum {
IDE_TFLAG_IN_HOB = IDE_TFLAG_IN_HOB_FEATURE |
IDE_TFLAG_IN_HOB_NSECT |
IDE_TFLAG_IN_HOB_LBA,
+ IDE_TFLAG_IN_FEATURE = (1 << 1),
IDE_TFLAG_IN_NSECT = (1 << 25),
IDE_TFLAG_IN_LBAL = (1 << 26),
IDE_TFLAG_IN_LBAM = (1 << 27),
@@ -948,9 +1038,25 @@ typedef struct ide_task_s {
void ide_tf_dump(const char *, struct ide_taskfile *);
+void ide_exec_command(ide_hwif_t *, u8);
+u8 ide_read_status(ide_hwif_t *);
+u8 ide_read_altstatus(ide_hwif_t *);
+u8 ide_read_sff_dma_status(ide_hwif_t *);
+
+void ide_set_irq(ide_hwif_t *, int);
+
+void ide_tf_load(ide_drive_t *, ide_task_t *);
+void ide_tf_read(ide_drive_t *, ide_task_t *);
+
+void ide_input_data(ide_drive_t *, struct request *, void *, unsigned int);
+void ide_output_data(ide_drive_t *, struct request *, void *, unsigned int);
+
extern void SELECT_DRIVE(ide_drive_t *);
void SELECT_MASK(ide_drive_t *, int);
+u8 ide_read_error(ide_drive_t *);
+void ide_read_bcount_and_ireason(ide_drive_t *, u16 *, u8 *);
+
extern int drive_is_ready(ide_drive_t *);
void ide_pktcmd_tf_load(ide_drive_t *, u32, u16, u8);
@@ -1000,12 +1106,15 @@ extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *o
#define ide_pci_register_driver(d) pci_register_driver(d)
#endif
-void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int, u8 *);
+void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int,
+ hw_regs_t *, hw_regs_t **);
void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *);
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
int ide_pci_set_master(struct pci_dev *, const char *);
unsigned long ide_pci_dma_base(ide_hwif_t *, const struct ide_port_info *);
+extern const struct ide_dma_ops sff_dma_ops;
+int ide_pci_check_simplex(ide_hwif_t *, const struct ide_port_info *);
int ide_hwif_setup_dma(ide_hwif_t *, const struct ide_port_info *);
#else
static inline int ide_hwif_setup_dma(ide_hwif_t *hwif,
@@ -1015,10 +1124,6 @@ static inline int ide_hwif_setup_dma(ide_hwif_t *hwif,
}
#endif
-extern void default_hwif_iops(ide_hwif_t *);
-extern void default_hwif_mmiops(ide_hwif_t *);
-extern void default_hwif_transport(ide_hwif_t *);
-
typedef struct ide_pci_enablebit_s {
u8 reg; /* byte pci reg holding the enable-bit */
u8 mask; /* mask to isolate the enable-bit */
@@ -1081,7 +1186,6 @@ enum {
IDE_HFLAG_IO_32BIT = (1 << 24),
/* unmask IRQs */
IDE_HFLAG_UNMASK_IRQS = (1 << 25),
- IDE_HFLAG_ABUSE_SET_DMA_MODE = (1 << 26),
/* serialize ports if DMA is possible (for sl82c105) */
IDE_HFLAG_SERIALIZE_DMA = (1 << 27),
/* force host out of "simplex" mode */
@@ -1092,8 +1196,6 @@ enum {
IDE_HFLAG_NO_IO_32BIT = (1 << 30),
/* never unmask IRQs */
IDE_HFLAG_NO_UNMASK_IRQS = (1 << 31),
- /* host uses VDMA (disabled for now) */
- IDE_HFLAG_VDMA = 0,
};
#ifdef CONFIG_BLK_DEV_OFFBOARD
@@ -1104,12 +1206,13 @@ enum {
struct ide_port_info {
char *name;
- unsigned int (*init_chipset)(struct pci_dev *, const char *);
+ unsigned int (*init_chipset)(struct pci_dev *);
void (*init_iops)(ide_hwif_t *);
void (*init_hwif)(ide_hwif_t *);
int (*init_dma)(ide_hwif_t *,
const struct ide_port_info *);
+ const struct ide_tp_ops *tp_ops;
const struct ide_port_ops *port_ops;
const struct ide_dma_ops *dma_ops;
@@ -1122,8 +1225,10 @@ struct ide_port_info {
u8 udma_mask;
};
-int ide_setup_pci_device(struct pci_dev *, const struct ide_port_info *);
-int ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, const struct ide_port_info *);
+int ide_pci_init_one(struct pci_dev *, const struct ide_port_info *, void *);
+int ide_pci_init_two(struct pci_dev *, struct pci_dev *,
+ const struct ide_port_info *, void *);
+void ide_pci_remove(struct pci_dev *);
void ide_map_sg(ide_drive_t *, struct request *);
void ide_init_sg_cmd(ide_drive_t *, struct request *);
@@ -1163,7 +1268,6 @@ void ide_destroy_dmatable(ide_drive_t *);
extern int ide_build_dmatable(ide_drive_t *, struct request *);
int ide_allocate_dma_engine(ide_hwif_t *);
void ide_release_dma_engine(ide_hwif_t *);
-void ide_setup_dma(ide_hwif_t *, unsigned long);
void ide_dma_host_set(ide_drive_t *, int);
extern int ide_dma_setup(ide_drive_t *);
@@ -1217,8 +1321,14 @@ void ide_undecoded_slave(ide_drive_t *);
void ide_port_apply_params(ide_hwif_t *);
-int ide_device_add_all(u8 *idx, const struct ide_port_info *);
-int ide_device_add(u8 idx[4], const struct ide_port_info *);
+struct ide_host *ide_host_alloc_all(const struct ide_port_info *, hw_regs_t **);
+struct ide_host *ide_host_alloc(const struct ide_port_info *, hw_regs_t **);
+void ide_host_free(struct ide_host *);
+int ide_host_register(struct ide_host *, const struct ide_port_info *,
+ hw_regs_t **);
+int ide_host_add(const struct ide_port_info *, hw_regs_t **,
+ struct ide_host **);
+void ide_host_remove(struct ide_host *);
int ide_legacy_device_add(const struct ide_port_info *, unsigned long);
void ide_port_unregister_devices(ide_hwif_t *);
void ide_port_scan(ide_hwif_t *);
@@ -1350,33 +1460,4 @@ static inline ide_drive_t *ide_get_paired_drive(ide_drive_t *drive)
return &hwif->drives[(drive->dn ^ 1) & 1];
}
-
-static inline void ide_set_irq(ide_drive_t *drive, int on)
-{
- ide_hwif_t *hwif = drive->hwif;
-
- hwif->OUTBSYNC(hwif, ATA_DEVCTL_OBS | (on ? 0 : 2),
- hwif->io_ports.ctl_addr);
-}
-
-static inline u8 ide_read_status(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
-
- return hwif->INB(hwif->io_ports.status_addr);
-}
-
-static inline u8 ide_read_altstatus(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
-
- return hwif->INB(hwif->io_ports.ctl_addr);
-}
-
-static inline u8 ide_read_error(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
-
- return hwif->INB(hwif->io_ports.error_addr);
-}
#endif /* _IDE_H */
diff --git a/include/linux/idr.h b/include/linux/idr.h
index 9a2d762124d..fa035f96f2a 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -15,6 +15,7 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/init.h>
+#include <linux/rcupdate.h>
#if BITS_PER_LONG == 32
# define IDR_BITS 5
@@ -51,6 +52,7 @@ struct idr_layer {
unsigned long bitmap; /* A zero bit means "space here" */
struct idr_layer *ary[1<<IDR_BITS];
int count; /* When zero, we can release it */
+ struct rcu_head rcu_head;
};
struct idr {
@@ -71,6 +73,28 @@ struct idr {
}
#define DEFINE_IDR(name) struct idr name = IDR_INIT(name)
+/* Actions to be taken after a call to _idr_sub_alloc */
+#define IDR_NEED_TO_GROW -2
+#define IDR_NOMORE_SPACE -3
+
+#define _idr_rc_to_errno(rc) ((rc) == -1 ? -EAGAIN : -ENOSPC)
+
+/**
+ * idr synchronization (stolen from radix-tree.h)
+ *
+ * idr_find() is able to be called locklessly, using RCU. The caller must
+ * ensure calls to this function are made within rcu_read_lock() regions.
+ * Other readers (lock-free or otherwise) and modifications may be running
+ * concurrently.
+ *
+ * It is still required that the caller manage the synchronization and
+ * lifetimes of the items. So if RCU lock-free lookups are used, typically
+ * this would mean that the items have their own locks, or are amenable to
+ * lock-free access; and that the items are freed by RCU (or only freed after
+ * having been deleted from the idr tree *and* a synchronize_rcu() grace
+ * period).
+ */
+
/*
* This is what we export.
*/
diff --git a/include/linux/init.h b/include/linux/init.h
index 21d658cdfa2..42ae95411a9 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -275,13 +275,7 @@ void __init parse_early_param(void);
#define security_initcall(fn) module_init(fn)
-/* These macros create a dummy inline: gcc 2.9x does not count alias
- as usage, hence the `unused function' warning when __init functions
- are declared static. We use the dummy __*_module_inline functions
- both to kill the warning and check the type of the init/cleanup
- function. */
-
-/* Each module must use one module_init(), or one no_module_init */
+/* Each module must use one module_init(). */
#define module_init(initfn) \
static inline initcall_t __inittest(void) \
{ return initfn; } \
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 93c45acf249..021d8e720c7 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -122,7 +122,7 @@ extern struct group_info init_groups;
.state = 0, \
.stack = &init_thread_info, \
.usage = ATOMIC_INIT(2), \
- .flags = 0, \
+ .flags = PF_KTHREAD, \
.lock_depth = -1, \
.prio = MAX_PRIO-20, \
.static_prio = MAX_PRIO-20, \
diff --git a/include/linux/inotify.h b/include/linux/inotify.h
index 742b917e7d1..bd578578a8b 100644
--- a/include/linux/inotify.h
+++ b/include/linux/inotify.h
@@ -7,6 +7,8 @@
#ifndef _LINUX_INOTIFY_H
#define _LINUX_INOTIFY_H
+/* For O_CLOEXEC and O_NONBLOCK */
+#include <linux/fcntl.h>
#include <linux/types.h>
/*
@@ -63,6 +65,10 @@ struct inotify_event {
IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | \
IN_MOVE_SELF)
+/* Flags for sys_inotify_init1. */
+#define IN_CLOEXEC O_CLOEXEC
+#define IN_NONBLOCK O_NONBLOCK
+
#ifdef __KERNEL__
#include <linux/dcache.h>
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index ea6c18a8b0d..ea330f9e710 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -36,6 +36,7 @@ struct ipc_namespace {
int msg_ctlmni;
atomic_t msg_bytes;
atomic_t msg_hdrs;
+ int auto_msgmni;
size_t shm_ctlmax;
size_t shm_ctlall;
@@ -53,7 +54,7 @@ extern atomic_t nr_ipc_ns;
extern int register_ipcns_notifier(struct ipc_namespace *);
extern int cond_register_ipcns_notifier(struct ipc_namespace *);
-extern int unregister_ipcns_notifier(struct ipc_namespace *);
+extern void unregister_ipcns_notifier(struct ipc_namespace *);
extern int ipcns_notify(unsigned long);
#else /* CONFIG_SYSVIPC */
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 391ad0843a4..641e026eee8 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -123,6 +123,7 @@ struct ipv6hdr {
struct in6_addr daddr;
};
+#ifdef __KERNEL__
/*
* This structure contains configuration options per IPv6 link.
*/
@@ -167,6 +168,7 @@ struct ipv6_devconf {
__s32 accept_dad;
void *sysctl;
};
+#endif
/* index values for the variables in ipv6_devconf */
enum {
diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h
index 2b1c2e58566..74bde13224c 100644
--- a/include/linux/irqflags.h
+++ b/include/linux/irqflags.h
@@ -11,6 +11,8 @@
#ifndef _LINUX_TRACE_IRQFLAGS_H
#define _LINUX_TRACE_IRQFLAGS_H
+#include <linux/typecheck.h>
+
#ifdef CONFIG_TRACE_IRQFLAGS
extern void trace_softirqs_on(unsigned long ip);
extern void trace_softirqs_off(unsigned long ip);
@@ -58,18 +60,24 @@
do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0)
#define local_irq_disable() \
do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0)
-#define local_irq_save(flags) \
- do { raw_local_irq_save(flags); trace_hardirqs_off(); } while (0)
+#define local_irq_save(flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ raw_local_irq_save(flags); \
+ trace_hardirqs_off(); \
+ } while (0)
-#define local_irq_restore(flags) \
- do { \
- if (raw_irqs_disabled_flags(flags)) { \
- raw_local_irq_restore(flags); \
- trace_hardirqs_off(); \
- } else { \
- trace_hardirqs_on(); \
- raw_local_irq_restore(flags); \
- } \
+
+#define local_irq_restore(flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ if (raw_irqs_disabled_flags(flags)) { \
+ raw_local_irq_restore(flags); \
+ trace_hardirqs_off(); \
+ } else { \
+ trace_hardirqs_on(); \
+ raw_local_irq_restore(flags); \
+ } \
} while (0)
#else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */
/*
@@ -78,8 +86,16 @@
*/
# define raw_local_irq_disable() local_irq_disable()
# define raw_local_irq_enable() local_irq_enable()
-# define raw_local_irq_save(flags) local_irq_save(flags)
-# define raw_local_irq_restore(flags) local_irq_restore(flags)
+# define raw_local_irq_save(flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ local_irq_save(flags); \
+ } while (0)
+# define raw_local_irq_restore(flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ local_irq_restore(flags); \
+ } while (0)
#endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */
#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
@@ -89,7 +105,11 @@
raw_safe_halt(); \
} while (0)
-#define local_save_flags(flags) raw_local_save_flags(flags)
+#define local_save_flags(flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ raw_local_save_flags(flags); \
+ } while (0)
#define irqs_disabled() \
({ \
@@ -99,7 +119,11 @@
raw_irqs_disabled_flags(_flags); \
})
-#define irqs_disabled_flags(flags) raw_irqs_disabled_flags(flags)
+#define irqs_disabled_flags(flags) \
+({ \
+ typecheck(unsigned long, flags); \
+ raw_irqs_disabled_flags(flags); \
+})
#endif /* CONFIG_X86 */
#endif
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index 00c1801099f..57aefa160a9 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -6,6 +6,7 @@
#define _LINUX_KALLSYMS_H
#include <linux/errno.h>
+#include <linux/kernel.h>
#include <linux/stddef.h>
#define KSYM_NAME_LEN 128
@@ -105,18 +106,10 @@ static inline void print_fn_descriptor_symbol(const char *fmt, void *addr)
print_symbol(fmt, (unsigned long)addr);
}
-#ifndef CONFIG_64BIT
-#define print_ip_sym(ip) \
-do { \
- printk("[<%08lx>]", ip); \
- print_symbol(" %s\n", ip); \
-} while(0)
-#else
-#define print_ip_sym(ip) \
-do { \
- printk("[<%016lx>]", ip); \
- print_symbol(" %s\n", ip); \
-} while(0)
-#endif
+static inline void print_ip_sym(unsigned long ip)
+{
+ printk("[<%p>]", (void *) ip);
+ print_symbol(" %s\n", ip);
+}
#endif /*_LINUX_KALLSYMS_H*/
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index f9cd7a513f9..fdbbf72ca2e 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -14,6 +14,8 @@
#include <linux/compiler.h>
#include <linux/bitops.h>
#include <linux/log2.h>
+#include <linux/typecheck.h>
+#include <linux/ratelimit.h>
#include <asm/byteorder.h>
#include <asm/bug.h>
@@ -188,11 +190,8 @@ asmlinkage int vprintk(const char *fmt, va_list args)
asmlinkage int printk(const char * fmt, ...)
__attribute__ ((format (printf, 1, 2))) __cold;
-extern int printk_ratelimit_jiffies;
-extern int printk_ratelimit_burst;
+extern struct ratelimit_state printk_ratelimit_state;
extern int printk_ratelimit(void);
-extern int __ratelimit(int ratelimit_jiffies, int ratelimit_burst);
-extern int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst);
extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
unsigned int interval_msec);
#else
@@ -203,8 +202,6 @@ static inline int printk(const char *s, ...)
__attribute__ ((format (printf, 1, 2)));
static inline int __cold printk(const char *s, ...) { return 0; }
static inline int printk_ratelimit(void) { return 0; }
-static inline int __printk_ratelimit(int ratelimit_jiffies, \
- int ratelimit_burst) { return 0; }
static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies, \
unsigned int interval_msec) \
{ return false; }
@@ -441,26 +438,6 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
-/*
- * Check at compile time that something is of a particular type.
- * Always evaluates to 1 so you may use it easily in comparisons.
- */
-#define typecheck(type,x) \
-({ type __dummy; \
- typeof(x) __dummy2; \
- (void)(&__dummy == &__dummy2); \
- 1; \
-})
-
-/*
- * Check at compile time that 'function' is a certain type, or is a pointer
- * to that type (needs to use typedef for the function type.)
- */
-#define typecheck_fn(type,function) \
-({ typeof(type) __tmp = function; \
- (void)__tmp; \
-})
-
struct sysinfo;
extern int do_sysinfo(struct sysinfo *info);
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index 5dc13848891..a1a91577813 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -19,29 +19,31 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/gfp.h>
#include <linux/stddef.h>
#include <linux/errno.h>
#include <linux/compiler.h>
#define KMOD_PATH_LEN 256
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
/* modprobe exit status on success, -ve on error. Return value
* usually useless though. */
extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2)));
+#define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x)))
#else
static inline int request_module(const char * name, ...) { return -ENOSYS; }
+#define try_then_request_module(x, mod...) (x)
#endif
-#define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x)))
struct key;
struct file;
struct subprocess_info;
/* Allocate a subprocess_info structure */
-struct subprocess_info *call_usermodehelper_setup(char *path,
- char **argv, char **envp);
+struct subprocess_info *call_usermodehelper_setup(char *path, char **argv,
+ char **envp, gfp_t gfp_mask);
/* Set various pieces of state into the subprocess_info structure */
void call_usermodehelper_setkeys(struct subprocess_info *info,
@@ -68,8 +70,9 @@ static inline int
call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait)
{
struct subprocess_info *info;
+ gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL;
- info = call_usermodehelper_setup(path, argv, envp);
+ info = call_usermodehelper_setup(path, argv, envp, gfp_mask);
if (info == NULL)
return -ENOMEM;
return call_usermodehelper_exec(info, wait);
@@ -80,8 +83,9 @@ call_usermodehelper_keys(char *path, char **argv, char **envp,
struct key *session_keyring, enum umh_wait wait)
{
struct subprocess_info *info;
+ gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL;
- info = call_usermodehelper_setup(path, argv, envp);
+ info = call_usermodehelper_setup(path, argv, envp, gfp_mask);
if (info == NULL)
return -ENOMEM;
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 39e709f88aa..5437ac0276e 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -26,7 +26,6 @@
#include <linux/wait.h>
#include <asm/atomic.h>
-#define KOBJ_NAME_LEN 20
#define UEVENT_HELPER_PATH_LEN 256
#define UEVENT_NUM_ENVP 32 /* number of env pointers */
#define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */
@@ -59,12 +58,12 @@ enum kobject_action {
struct kobject {
const char *name;
- struct kref kref;
struct list_head entry;
struct kobject *parent;
struct kset *kset;
struct kobj_type *ktype;
struct sysfs_dirent *sd;
+ struct kref kref;
unsigned int state_initialized:1;
unsigned int state_in_sysfs:1;
unsigned int state_add_uevent_sent:1;
@@ -187,6 +186,8 @@ extern struct kobject *kset_find_obj(struct kset *, const char *);
/* The global /sys/kernel/ kobject for people to chain off of */
extern struct kobject *kernel_kobj;
+/* The global /sys/kernel/mm/ kobject for people to chain off of */
+extern struct kobject *mm_kobj;
/* The global /sys/hypervisor/ kobject for people to chain off of */
extern struct kobject *hypervisor_kobj;
/* The global /sys/power/ kobject for people to chain off of */
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 04a3556bdea..0be7795655f 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -157,11 +157,10 @@ struct kretprobe {
int nmissed;
size_t data_size;
struct hlist_head free_instances;
- struct hlist_head used_instances;
+ spinlock_t lock;
};
struct kretprobe_instance {
- struct hlist_node uflist; /* either on free list or used list */
struct hlist_node hlist;
struct kretprobe *rp;
kprobe_opcode_t *ret_addr;
@@ -201,7 +200,6 @@ static inline int init_test_probes(void)
}
#endif /* CONFIG_KPROBES_SANITY_TEST */
-extern spinlock_t kretprobe_lock;
extern struct mutex kprobe_mutex;
extern int arch_prepare_kprobe(struct kprobe *p);
extern void arch_arm_kprobe(struct kprobe *p);
@@ -214,6 +212,9 @@ extern void kprobes_inc_nmissed_count(struct kprobe *p);
/* Get the kprobe at this addr (if any) - called with preemption disabled */
struct kprobe *get_kprobe(void *addr);
+void kretprobe_hash_lock(struct task_struct *tsk,
+ struct hlist_head **head, unsigned long *flags);
+void kretprobe_hash_unlock(struct task_struct *tsk, unsigned long *flags);
struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk);
/* kprobe_running() will just return the current_kprobe on this CPU */
diff --git a/include/linux/kthread.h b/include/linux/kthread.h
index 00dd957e245..aabc8a13ba7 100644
--- a/include/linux/kthread.h
+++ b/include/linux/kthread.h
@@ -6,7 +6,8 @@
struct task_struct *kthread_create(int (*threadfn)(void *data),
void *data,
- const char namefmt[], ...);
+ const char namefmt[], ...)
+ __attribute__((format(printf, 3, 4)));
/**
* kthread_run - create and wake a thread.
diff --git a/include/linux/lcd.h b/include/linux/lcd.h
index 1d379787f2e..173febac665 100644
--- a/include/linux/lcd.h
+++ b/include/linux/lcd.h
@@ -47,7 +47,7 @@ struct lcd_ops {
int (*set_contrast)(struct lcd_device *, int contrast);
/* Check if given framebuffer device is the one LCD is bound to;
return 0 if not, !=0 if it is. If NULL, lcd always matches the fb. */
- int (*check_fb)(struct fb_info *);
+ int (*check_fb)(struct lcd_device *, struct fb_info *);
};
struct lcd_device {
diff --git a/include/linux/leds-pca9532.h b/include/linux/leds-pca9532.h
new file mode 100644
index 00000000000..81b4207deb9
--- /dev/null
+++ b/include/linux/leds-pca9532.h
@@ -0,0 +1,45 @@
+/*
+ * pca9532.h - platform data structure for pca9532 led controller
+ *
+ * Copyright (C) 2008 Riku Voipio <riku.voipio@movial.fi>
+ *
+ * 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; version 2 of the License.
+ *
+ * Datasheet: http://www.nxp.com/acrobat/datasheets/PCA9532_3.pdf
+ *
+ */
+
+#ifndef __LINUX_PCA9532_H
+#define __LINUX_PCA9532_H
+
+#include <linux/leds.h>
+
+enum pca9532_state {
+ PCA9532_OFF = 0x0,
+ PCA9532_ON = 0x1,
+ PCA9532_PWM0 = 0x2,
+ PCA9532_PWM1 = 0x3
+};
+
+enum pca9532_type { PCA9532_TYPE_NONE, PCA9532_TYPE_LED,
+ PCA9532_TYPE_N2100_BEEP };
+
+struct pca9532_led {
+ u8 id;
+ struct i2c_client *client;
+ char *name;
+ struct led_classdev ldev;
+ enum pca9532_type type;
+ enum pca9532_state state;
+};
+
+struct pca9532_platform_data {
+ struct pca9532_led leds[16];
+ u8 pwm[2];
+ u8 psc[2];
+};
+
+#endif /* __LINUX_PCA9532_H */
+
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 519df72e939..d41ccb56146 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -48,7 +48,7 @@ struct led_classdev {
struct device *dev;
struct list_head node; /* LED Device list */
- char *default_trigger; /* Trigger to use */
+ const char *default_trigger; /* Trigger to use */
#ifdef CONFIG_LEDS_TRIGGERS
/* Protects the trigger data below */
@@ -118,6 +118,20 @@ extern void ledtrig_ide_activity(void);
#define ledtrig_ide_activity() do {} while(0)
#endif
+/*
+ * Generic LED platform data for describing LED names and default triggers.
+ */
+struct led_info {
+ const char *name;
+ char *default_trigger;
+ int flags;
+};
+
+struct led_platform_data {
+ int num_leds;
+ struct led_info *leds;
+};
+
/* For the leds-gpio driver */
struct gpio_led {
const char *name;
diff --git a/include/linux/list.h b/include/linux/list.h
index 139ec41d9c2..453916bc041 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -61,14 +61,10 @@ extern void __list_add(struct list_head *new,
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
-#ifndef CONFIG_DEBUG_LIST
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
-#else
-extern void list_add(struct list_head *new, struct list_head *head);
-#endif
/**
diff --git a/include/linux/major.h b/include/linux/major.h
index 0cb98053537..53d5fafd85c 100644
--- a/include/linux/major.h
+++ b/include/linux/major.h
@@ -53,7 +53,7 @@
#define STL_SIOMEMMAJOR 28
#define ACSI_MAJOR 28
#define AZTECH_CDROM_MAJOR 29
-#define GRAPHDEV_MAJOR 29 /* SparcLinux & Linux/68k /dev/fb */
+#define FB_MAJOR 29 /* /dev/fb* framebuffers */
#define CM206_CDROM_MAJOR 32
#define IDE2_MAJOR 33
#define IDE3_MAJOR 34
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index e6608776bc9..fdf3967e139 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -35,7 +35,10 @@ extern int mem_cgroup_charge(struct page *page, struct mm_struct *mm,
extern int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
gfp_t gfp_mask);
extern void mem_cgroup_uncharge_page(struct page *page);
+extern void mem_cgroup_uncharge_cache_page(struct page *page);
extern void mem_cgroup_move_lists(struct page *page, bool active);
+extern int mem_cgroup_shrink_usage(struct mm_struct *mm, gfp_t gfp_mask);
+
extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
struct list_head *dst,
unsigned long *scanned, int order,
@@ -50,9 +53,9 @@ extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p);
#define mm_match_cgroup(mm, cgroup) \
((cgroup) == mem_cgroup_from_task((mm)->owner))
-extern int mem_cgroup_prepare_migration(struct page *page);
+extern int
+mem_cgroup_prepare_migration(struct page *page, struct page *newpage);
extern void mem_cgroup_end_migration(struct page *page);
-extern void mem_cgroup_page_migration(struct page *page, struct page *newpage);
/*
* For memory reclaim.
@@ -97,6 +100,15 @@ static inline void mem_cgroup_uncharge_page(struct page *page)
{
}
+static inline void mem_cgroup_uncharge_cache_page(struct page *page)
+{
+}
+
+static inline int mem_cgroup_shrink_usage(struct mm_struct *mm, gfp_t gfp_mask)
+{
+ return 0;
+}
+
static inline void mem_cgroup_move_lists(struct page *page, bool active)
{
}
@@ -112,7 +124,8 @@ static inline int task_in_mem_cgroup(struct task_struct *task,
return 1;
}
-static inline int mem_cgroup_prepare_migration(struct page *page)
+static inline int
+mem_cgroup_prepare_migration(struct page *page, struct page *newpage)
{
return 0;
}
@@ -121,11 +134,6 @@ static inline void mem_cgroup_end_migration(struct page *page)
{
}
-static inline void
-mem_cgroup_page_migration(struct page *page, struct page *newpage)
-{
-}
-
static inline int mem_cgroup_calc_mapped_ratio(struct mem_cgroup *mem)
{
return 0;
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index ea9f5ad9ec8..763ba81fc0f 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -13,12 +13,12 @@ struct mem_section;
#ifdef CONFIG_MEMORY_HOTPLUG
/*
- * Magic number for free bootmem.
+ * Types for free bootmem.
* The normal smallest mapcount is -1. Here is smaller value than it.
*/
-#define SECTION_INFO 0xfffffffe
-#define MIX_INFO 0xfffffffd
-#define NODE_INFO 0xfffffffc
+#define SECTION_INFO (-1 - 1)
+#define MIX_SECTION_INFO (-1 - 2)
+#define NODE_INFO (-1 - 3)
/*
* pgdat resizing functions
@@ -199,6 +199,18 @@ extern int walk_memory_resource(unsigned long start_pfn,
unsigned long nr_pages, void *arg,
int (*func)(unsigned long, unsigned long, void *));
+#ifdef CONFIG_MEMORY_HOTREMOVE
+
+extern int is_mem_section_removable(unsigned long pfn, unsigned long nr_pages);
+
+#else
+static inline int is_mem_section_removable(unsigned long pfn,
+ unsigned long nr_pages)
+{
+ return 0;
+}
+#endif /* CONFIG_MEMORY_HOTREMOVE */
+
extern int add_memory(int nid, u64 start, u64 size);
extern int arch_add_memory(int nid, u64 start, u64 size);
extern int remove_memory(u64 start, u64 size);
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 3a39570b81b..085c903fe0f 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -59,6 +59,7 @@ enum {
#include <linux/rbtree.h>
#include <linux/spinlock.h>
#include <linux/nodemask.h>
+#include <linux/pagemap.h>
struct mm_struct;
@@ -220,6 +221,24 @@ extern int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context);
extern int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol,
int no_context);
#endif
+
+/* Check if a vma is migratable */
+static inline int vma_migratable(struct vm_area_struct *vma)
+{
+ if (vma->vm_flags & (VM_IO|VM_HUGETLB|VM_PFNMAP|VM_RESERVED))
+ return 0;
+ /*
+ * Migration allocates pages in the highest zone. If we cannot
+ * do so then migration (at least from node to node) is not
+ * possible.
+ */
+ if (vma->vm_file &&
+ gfp_zone(mapping_gfp_mask(vma->vm_file->f_mapping))
+ < policy_zone)
+ return 0;
+ return 1;
+}
+
#else
struct mempolicy {};
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
new file mode 100644
index 00000000000..bb3dd054592
--- /dev/null
+++ b/include/linux/mfd/core.h
@@ -0,0 +1,55 @@
+#ifndef MFD_CORE_H
+#define MFD_CORE_H
+/*
+ * drivers/mfd/mfd-core.h
+ *
+ * core MFD support
+ * Copyright (c) 2006 Ian Molton
+ * Copyright (c) 2007 Dmitry Baryshkov
+ *
+ * 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/platform_device.h>
+
+/*
+ * This struct describes the MFD part ("cell").
+ * After registration the copy of this structure will become the platform data
+ * of the resulting platform_device
+ */
+struct mfd_cell {
+ const char *name;
+
+ int (*enable)(struct platform_device *dev);
+ int (*disable)(struct platform_device *dev);
+ int (*suspend)(struct platform_device *dev);
+ int (*resume)(struct platform_device *dev);
+
+ void *driver_data; /* driver-specific data */
+
+ /*
+ * This resources can be specified relatievly to the parent device.
+ * For accessing device you should use resources from device
+ */
+ int num_resources;
+ const struct resource *resources;
+};
+
+static inline struct mfd_cell *
+mfd_get_cell(struct platform_device *pdev)
+{
+ return (struct mfd_cell *)pdev->dev.platform_data;
+}
+
+extern int mfd_add_devices(
+ struct platform_device *parent,
+ const struct mfd_cell *cells, int n_devs,
+ struct resource *mem_base,
+ int irq_base);
+
+extern void mfd_remove_devices(struct platform_device *parent);
+
+#endif
diff --git a/include/linux/mfd/tc6393xb.h b/include/linux/mfd/tc6393xb.h
new file mode 100644
index 00000000000..7cc824a58f7
--- /dev/null
+++ b/include/linux/mfd/tc6393xb.h
@@ -0,0 +1,49 @@
+/*
+ * Toshiba TC6393XB SoC support
+ *
+ * Copyright(c) 2005-2006 Chris Humbert
+ * Copyright(c) 2005 Dirk Opfer
+ * Copyright(c) 2005 Ian Molton <spyro@f2s.com>
+ * Copyright(c) 2007 Dmitry Baryshkov
+ *
+ * Based on code written by Sharp/Lineo for 2.4 kernels
+ * Based on locomo.c
+ *
+ * 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.
+ */
+
+#ifndef TC6393XB_H
+#define TC6393XB_H
+
+/* Also one should provide the CK3P6MI clock */
+struct tc6393xb_platform_data {
+ u16 scr_pll2cr; /* PLL2 Control */
+ u16 scr_gper; /* GP Enable */
+ u32 scr_gpo_doecr; /* GPO Data OE Control */
+ u32 scr_gpo_dsr; /* GPO Data Set */
+
+ int (*enable)(struct platform_device *dev);
+ int (*disable)(struct platform_device *dev);
+ int (*suspend)(struct platform_device *dev);
+ int (*resume)(struct platform_device *dev);
+
+ int irq_base; /* a base for cascaded irq */
+ int gpio_base;
+
+ struct tmio_nand_data *nand_data;
+};
+
+/*
+ * Relative to irq_base
+ */
+#define IRQ_TC6393_NAND 0
+#define IRQ_TC6393_MMC 1
+#define IRQ_TC6393_OHCI 2
+#define IRQ_TC6393_SERIAL 3
+#define IRQ_TC6393_FB 4
+
+#define TC6393XB_NR_IRQS 8
+
+#endif
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
new file mode 100644
index 00000000000..9438d8c9ac1
--- /dev/null
+++ b/include/linux/mfd/tmio.h
@@ -0,0 +1,17 @@
+#ifndef MFD_TMIO_H
+#define MFD_TMIO_H
+
+/*
+ * data for the NAND controller
+ */
+struct tmio_nand_data {
+ struct nand_bbt_descr *badblock_pattern;
+ struct mtd_partition *partition;
+ unsigned int num_partitions;
+};
+
+#define TMIO_NAND_CONFIG "tmio-nand-config"
+#define TMIO_NAND_CONTROL "tmio-nand-control"
+#define TMIO_NAND_IRQ "tmio-nand"
+
+#endif
diff --git a/include/linux/migrate.h b/include/linux/migrate.h
index e10a90a93b5..03aea612d28 100644
--- a/include/linux/migrate.h
+++ b/include/linux/migrate.h
@@ -3,28 +3,10 @@
#include <linux/mm.h>
#include <linux/mempolicy.h>
-#include <linux/pagemap.h>
typedef struct page *new_page_t(struct page *, unsigned long private, int **);
#ifdef CONFIG_MIGRATION
-/* Check if a vma is migratable */
-static inline int vma_migratable(struct vm_area_struct *vma)
-{
- if (vma->vm_flags & (VM_IO|VM_HUGETLB|VM_PFNMAP|VM_RESERVED))
- return 0;
- /*
- * Migration allocates pages in the highest zone. If we cannot
- * do so then migration (at least from node to node) is not
- * possible.
- */
- if (vma->vm_file &&
- gfp_zone(mapping_gfp_mask(vma->vm_file->f_mapping))
- < policy_zone)
- return 0;
- return 1;
-}
-
extern int isolate_lru_page(struct page *p, struct list_head *pagelist);
extern int putback_lru_pages(struct list_head *l);
extern int migrate_page(struct address_space *,
@@ -39,9 +21,6 @@ extern int migrate_vmas(struct mm_struct *mm,
const nodemask_t *from, const nodemask_t *to,
unsigned long flags);
#else
-static inline int vma_migratable(struct vm_area_struct *vma)
- { return 0; }
-
static inline int isolate_lru_page(struct page *p, struct list_head *list)
{ return -ENOSYS; }
static inline int putback_lru_pages(struct list_head *l) { return 0; }
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 81b3dd5206e..655ea0d1ee1 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -68,6 +68,14 @@ enum {
MLX4_DEV_CAP_FLAG_UD_MCAST = 1 << 21
};
+enum {
+ MLX4_BMME_FLAG_LOCAL_INV = 1 << 6,
+ MLX4_BMME_FLAG_REMOTE_INV = 1 << 7,
+ MLX4_BMME_FLAG_TYPE_2_WIN = 1 << 9,
+ MLX4_BMME_FLAG_RESERVED_LKEY = 1 << 10,
+ MLX4_BMME_FLAG_FAST_REG_WR = 1 << 11,
+};
+
enum mlx4_event {
MLX4_EVENT_TYPE_COMP = 0x00,
MLX4_EVENT_TYPE_PATH_MIG = 0x01,
@@ -184,6 +192,8 @@ struct mlx4_caps {
u32 max_msg_sz;
u32 page_size_cap;
u32 flags;
+ u32 bmme_flags;
+ u32 reserved_lkey;
u16 stat_rate_support;
u8 port_width_cap[MLX4_MAX_PORTS + 1];
int max_gso_sz;
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h
index 7f128b266fa..e27082cd650 100644
--- a/include/linux/mlx4/qp.h
+++ b/include/linux/mlx4/qp.h
@@ -219,7 +219,7 @@ struct mlx4_wqe_datagram_seg {
__be32 reservd[2];
};
-struct mlx4_lso_seg {
+struct mlx4_wqe_lso_seg {
__be32 mss_hdr_size;
__be32 header[0];
};
@@ -233,6 +233,14 @@ struct mlx4_wqe_bind_seg {
__be64 length;
};
+enum {
+ MLX4_WQE_FMR_PERM_LOCAL_READ = 1 << 27,
+ MLX4_WQE_FMR_PERM_LOCAL_WRITE = 1 << 28,
+ MLX4_WQE_FMR_PERM_REMOTE_READ = 1 << 29,
+ MLX4_WQE_FMR_PERM_REMOTE_WRITE = 1 << 30,
+ MLX4_WQE_FMR_PERM_ATOMIC = 1 << 31
+};
+
struct mlx4_wqe_fmr_seg {
__be32 flags;
__be32 mem_key;
@@ -255,11 +263,11 @@ struct mlx4_wqe_fmr_ext_seg {
};
struct mlx4_wqe_local_inval_seg {
- u8 flags;
- u8 reserved1[3];
+ __be32 flags;
+ u32 reserved1;
__be32 mem_key;
- u8 reserved2[3];
- u8 guest_id;
+ u32 reserved2[2];
+ __be32 guest_id;
__be64 pa;
};
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 2128ef7780c..d87a5a5fe87 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -41,6 +41,9 @@ extern unsigned long mmap_min_addr;
#define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE)
+
/*
* Linux kernel virtual memory manager primitives.
* The idea being to have a "virtual" mm in the same way
@@ -100,6 +103,7 @@ extern unsigned int kobjsize(const void *objp);
#define VM_DONTEXPAND 0x00040000 /* Cannot expand with mremap() */
#define VM_RESERVED 0x00080000 /* Count as reserved_vm like IO */
#define VM_ACCOUNT 0x00100000 /* Is a VM accounted object */
+#define VM_NORESERVE 0x00200000 /* should the VM suppress accounting */
#define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */
#define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */
#define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */
@@ -166,12 +170,16 @@ struct vm_operations_struct {
void (*open)(struct vm_area_struct * area);
void (*close)(struct vm_area_struct * area);
int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
- unsigned long (*nopfn)(struct vm_area_struct *area,
- unsigned long address);
/* notification that a previously read-only page is about to become
* writable, if an error is returned it will cause a SIGBUS */
int (*page_mkwrite)(struct vm_area_struct *vma, struct page *page);
+
+ /* called by access_process_vm when get_user_pages() fails, typically
+ * for use by special VMAs that can switch between memory and hardware
+ */
+ int (*access)(struct vm_area_struct *vma, unsigned long addr,
+ void *buf, int len, int write);
#ifdef CONFIG_NUMA
/*
* set_policy() op must add a reference to any non-NULL @new mempolicy
@@ -675,13 +683,6 @@ static inline int page_mapped(struct page *page)
}
/*
- * Error return values for the *_nopfn functions
- */
-#define NOPFN_SIGBUS ((unsigned long) -1)
-#define NOPFN_OOM ((unsigned long) -2)
-#define NOPFN_REFAULT ((unsigned long) -3)
-
-/*
* Different kinds of faults, as returned by handle_mm_fault().
* Used to decide whether a process gets delivered SIGBUS or
* just gets major/minor fault counters bumped up.
@@ -772,14 +773,14 @@ struct mm_walk {
int walk_page_range(unsigned long addr, unsigned long end,
struct mm_walk *walk);
-void free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
+void free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
unsigned long end, unsigned long floor, unsigned long ceiling);
-void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *start_vma,
- unsigned long floor, unsigned long ceiling);
int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
struct vm_area_struct *vma);
void unmap_mapping_range(struct address_space *mapping,
loff_t const holebegin, loff_t const holelen, int even_cows);
+int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
+ void *buf, int len, int write);
static inline void unmap_shared_mapping_range(struct address_space *mapping,
loff_t const holebegin, loff_t const holelen)
@@ -965,9 +966,8 @@ static inline void pgtable_page_dtor(struct page *page)
NULL: pte_offset_kernel(pmd, address))
extern void free_area_init(unsigned long * zones_size);
-extern void free_area_init_node(int nid, pg_data_t *pgdat,
- unsigned long * zones_size, unsigned long zone_start_pfn,
- unsigned long *zholes_size);
+extern void free_area_init_node(int nid, unsigned long * zones_size,
+ unsigned long zone_start_pfn, unsigned long *zholes_size);
#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
/*
* With CONFIG_ARCH_POPULATES_NODE_MAP set, an architecture may initialise its
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 02a27ae7853..746f975b58e 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -159,6 +159,17 @@ struct vm_area_struct {
#endif
};
+struct core_thread {
+ struct task_struct *task;
+ struct core_thread *next;
+};
+
+struct core_state {
+ atomic_t nr_threads;
+ struct core_thread dumper;
+ struct completion startup;
+};
+
struct mm_struct {
struct vm_area_struct * mmap; /* list of VMAs */
struct rb_root mm_rb;
@@ -175,7 +186,6 @@ struct mm_struct {
atomic_t mm_users; /* How many users with user space? */
atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */
int map_count; /* number of VMAs */
- int core_waiters;
struct rw_semaphore mmap_sem;
spinlock_t page_table_lock; /* Protects page tables and some counters */
@@ -219,8 +229,7 @@ struct mm_struct {
unsigned long flags; /* Must use atomic bitops to access the bits */
- /* coredumping support */
- struct completion *core_startup_done, core_done;
+ struct core_state *core_state; /* coredumping support */
/* aio bits */
rwlock_t ioctx_list_lock; /* aio lock */
diff --git a/include/linux/module.h b/include/linux/module.h
index 3e03b1acbc9..68e09557c95 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -23,7 +23,7 @@
/* Not Yet Implemented */
#define MODULE_SUPPORTED_DEVICE(name)
-/* v850 toolchain uses a `_' prefix for all user symbols */
+/* some toolchains uses a `_' prefix for all user symbols */
#ifndef MODULE_SYMBOL_PREFIX
#define MODULE_SYMBOL_PREFIX ""
#endif
@@ -249,27 +249,30 @@ struct module
/* Exported symbols */
const struct kernel_symbol *syms;
- unsigned int num_syms;
const unsigned long *crcs;
+ unsigned int num_syms;
/* GPL-only exported symbols. */
- const struct kernel_symbol *gpl_syms;
unsigned int num_gpl_syms;
+ const struct kernel_symbol *gpl_syms;
const unsigned long *gpl_crcs;
+#ifdef CONFIG_UNUSED_SYMBOLS
/* unused exported symbols. */
const struct kernel_symbol *unused_syms;
- unsigned int num_unused_syms;
const unsigned long *unused_crcs;
+ unsigned int num_unused_syms;
+
/* GPL-only, unused exported symbols. */
- const struct kernel_symbol *unused_gpl_syms;
unsigned int num_unused_gpl_syms;
+ const struct kernel_symbol *unused_gpl_syms;
const unsigned long *unused_gpl_crcs;
+#endif
/* symbols that will be GPL-only in the near future. */
const struct kernel_symbol *gpl_future_syms;
- unsigned int num_gpl_future_syms;
const unsigned long *gpl_future_crcs;
+ unsigned int num_gpl_future_syms;
/* Exception table */
unsigned int num_exentries;
@@ -285,10 +288,10 @@ struct module
void *module_core;
/* Here are the sizes of the init and core sections */
- unsigned long init_size, core_size;
+ unsigned int init_size, core_size;
/* The size of the executable code in each section. */
- unsigned long init_text_size, core_text_size;
+ unsigned int init_text_size, core_text_size;
/* The handle returned from unwind_add_table. */
void *unwind_info;
@@ -300,29 +303,15 @@ struct module
#ifdef CONFIG_GENERIC_BUG
/* Support for BUG */
+ unsigned num_bugs;
struct list_head bug_list;
struct bug_entry *bug_table;
- unsigned num_bugs;
-#endif
-
-#ifdef CONFIG_MODULE_UNLOAD
- /* Reference counts */
- struct module_ref ref[NR_CPUS];
-
- /* What modules depend on me? */
- struct list_head modules_which_use_me;
-
- /* Who is waiting for us to be unloaded */
- struct task_struct *waiter;
-
- /* Destruction function. */
- void (*exit)(void);
#endif
#ifdef CONFIG_KALLSYMS
/* We keep the symbol and string tables for kallsyms. */
Elf_Sym *symtab;
- unsigned long num_symtab;
+ unsigned int num_symtab;
char *strtab;
/* Section attributes */
@@ -342,6 +331,21 @@ struct module
struct marker *markers;
unsigned int num_markers;
#endif
+
+#ifdef CONFIG_MODULE_UNLOAD
+ /* What modules depend on me? */
+ struct list_head modules_which_use_me;
+
+ /* Who is waiting for us to be unloaded */
+ struct task_struct *waiter;
+
+ /* Destruction function. */
+ void (*exit)(void);
+
+ /* Reference counts */
+ struct module_ref ref[NR_CPUS];
+#endif
+
};
#ifndef MODULE_ARCH_INIT
#define MODULE_ARCH_INIT {}
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index 81cd36b735b..ba63858056c 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -2,11 +2,11 @@
#define _LINUX_MSDOS_FS_H
#include <linux/magic.h>
+#include <asm/byteorder.h>
/*
* The MS-DOS filesystem constants/structures
*/
-#include <asm/byteorder.h>
#define SECTOR_SIZE 512 /* sector size (bytes) */
#define SECTOR_BITS 9 /* log2(SECTOR_SIZE) */
@@ -89,24 +89,22 @@
#define IS_FSINFO(x) (le32_to_cpu((x)->signature1) == FAT_FSINFO_SIG1 \
&& le32_to_cpu((x)->signature2) == FAT_FSINFO_SIG2)
+struct __fat_dirent {
+ long d_ino;
+ __kernel_off_t d_off;
+ unsigned short d_reclen;
+ char d_name[256]; /* We must not include limits.h! */
+};
+
/*
* ioctl commands
*/
-#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
-#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2])
+#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct __fat_dirent[2])
+#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct __fat_dirent[2])
/* <linux/videotext.h> has used 0x72 ('r') in collision, so skip a few */
#define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32)
#define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32)
-/*
- * vfat shortname flags
- */
-#define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */
-#define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */
-#define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */
-#define VFAT_SFN_CREATE_WIN95 0x0100 /* emulate win95 rule for create */
-#define VFAT_SFN_CREATE_WINNT 0x0200 /* emulate winnt rule for create */
-
struct fat_boot_sector {
__u8 ignored[3]; /* Boot strap short or near jump */
__u8 system_id[8]; /* Name - can be used to special case
@@ -168,14 +166,6 @@ struct msdos_dir_slot {
__u8 name11_12[4]; /* last 2 characters in name */
};
-struct fat_slot_info {
- loff_t i_pos; /* on-disk position of directory entry */
- loff_t slot_off; /* offset for slot or de start */
- int nr_slots; /* number of slots + 1(de) in filename */
- struct msdos_dir_entry *de;
- struct buffer_head *bh;
-};
-
#ifdef __KERNEL__
#include <linux/buffer_head.h>
@@ -184,6 +174,15 @@ struct fat_slot_info {
#include <linux/fs.h>
#include <linux/mutex.h>
+/*
+ * vfat shortname flags
+ */
+#define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */
+#define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */
+#define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */
+#define VFAT_SFN_CREATE_WIN95 0x0100 /* emulate win95 rule for create */
+#define VFAT_SFN_CREATE_WINNT 0x0200 /* emulate winnt rule for create */
+
struct fat_mount_options {
uid_t fs_uid;
gid_t fs_gid;
@@ -202,10 +201,10 @@ struct fat_mount_options {
utf8:1, /* Use of UTF-8 character set (Default) */
unicode_xlate:1, /* create escape sequences for unhandled Unicode */
numtail:1, /* Does first alias have a numeric '~1' type tail? */
- atari:1, /* Use Atari GEMDOS variation of MS-DOS fs */
flush:1, /* write things quickly */
nocase:1, /* Does this need case conversion? 0=need case conversion*/
- usefree:1; /* Use free_clusters for FAT32 */
+ usefree:1, /* Use free_clusters for FAT32 */
+ tz_utc:1; /* Filesystem timestamps are in UTC */
};
#define FAT_HASH_BITS 8
@@ -267,6 +266,14 @@ struct msdos_inode_info {
struct inode vfs_inode;
};
+struct fat_slot_info {
+ loff_t i_pos; /* on-disk position of directory entry */
+ loff_t slot_off; /* offset for slot or de start */
+ int nr_slots; /* number of slots + 1(de) in filename */
+ struct msdos_dir_entry *de;
+ struct buffer_head *bh;
+};
+
static inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb)
{
return sb->s_fs_info;
@@ -428,8 +435,9 @@ extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
extern void fat_fs_panic(struct super_block *s, const char *fmt, ...);
extern void fat_clusters_flush(struct super_block *sb);
extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster);
-extern int date_dos2unix(unsigned short time, unsigned short date);
-extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date);
+extern int date_dos2unix(unsigned short time, unsigned short date, int tz_utc);
+extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date,
+ int tz_utc);
extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
int fat_cache_init(void);
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index a9fae032ba8..9c1d95491f8 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -189,7 +189,7 @@ typedef union {
*/
struct map_info {
- char *name;
+ const char *name;
unsigned long size;
resource_size_t phys;
#define NO_XIP (-1UL)
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 245f9098e17..8b5d49133ec 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -121,7 +121,7 @@ struct mtd_info {
u_int32_t oobavail; // Available OOB bytes per block
// Kernel-only stuff starts here.
- char *name;
+ const char *name;
int index;
/* ecc layout structure pointer - read only ! */
diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h
index f71201d0f3e..6316fafe5c2 100644
--- a/include/linux/mtd/ubi.h
+++ b/include/linux/mtd/ubi.h
@@ -45,13 +45,13 @@ enum {
* @size: how many physical eraseblocks are reserved for this volume
* @used_bytes: how many bytes of data this volume contains
* @used_ebs: how many physical eraseblocks of this volume actually contain any
- * data
+ * data
* @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
* @corrupted: non-zero if the volume is corrupted (static volumes only)
* @upd_marker: non-zero if the volume has update marker set
* @alignment: volume alignment
* @usable_leb_size: how many bytes are available in logical eraseblocks of
- * this volume
+ * this volume
* @name_len: volume name length
* @name: volume name
* @cdev: UBI volume character device major and minor numbers
@@ -152,6 +152,7 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum);
int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum);
int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype);
int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum);
+int ubi_sync(int ubi_num);
/*
* This function is the same as the 'ubi_leb_read()' function, but it does not
diff --git a/include/linux/net.h b/include/linux/net.h
index 150a48c68d5..4a9a30f2d68 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -20,6 +20,7 @@
#include <linux/wait.h>
#include <linux/socket.h>
+#include <linux/fcntl.h> /* For O_CLOEXEC and O_NONBLOCK */
#include <asm/socket.h>
struct poll_table_struct;
@@ -46,6 +47,7 @@ struct net;
#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */
#define SYS_SENDMSG 16 /* sys_sendmsg(2) */
#define SYS_RECVMSG 17 /* sys_recvmsg(2) */
+#define SYS_PACCEPT 18 /* sys_paccept(2) */
typedef enum {
SS_FREE = 0, /* not allocated */
@@ -94,6 +96,15 @@ enum sock_type {
};
#define SOCK_MAX (SOCK_PACKET + 1)
+/* Mask which covers at least up to SOCK_MASK-1. The
+ * remaining bits are used as flags. */
+#define SOCK_TYPE_MASK 0xf
+
+/* Flags for socket, socketpair, paccept */
+#define SOCK_CLOEXEC O_CLOEXEC
+#ifndef SOCK_NONBLOCK
+#define SOCK_NONBLOCK O_NONBLOCK
+#endif
#endif /* ARCH_HAS_SOCKET_TYPES */
@@ -208,10 +219,12 @@ extern int sock_sendmsg(struct socket *sock, struct msghdr *msg,
size_t len);
extern int sock_recvmsg(struct socket *sock, struct msghdr *msg,
size_t size, int flags);
-extern int sock_map_fd(struct socket *sock);
+extern int sock_map_fd(struct socket *sock, int flags);
extern struct socket *sockfd_lookup(int fd, int *err);
#define sockfd_put(sock) fput(sock->file)
extern int net_ratelimit(void);
+extern long do_accept(int fd, struct sockaddr __user *upeer_sockaddr,
+ int __user *upeer_addrlen, int flags);
#define net_random() random32()
#define net_srandom(seed) srandom32((__force u32)seed)
@@ -338,8 +351,7 @@ static const struct proto_ops name##_ops = { \
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
-extern int net_msg_cost;
-extern int net_msg_burst;
+extern struct ratelimit_state net_ratelimit_state;
#endif
#endif /* __KERNEL__ */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 812bcd8b436..b4d056ceab9 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -996,17 +996,17 @@ static inline void netif_tx_schedule_all(struct net_device *dev)
netif_schedule_queue(netdev_get_tx_queue(dev, i));
}
+static inline void netif_tx_start_queue(struct netdev_queue *dev_queue)
+{
+ clear_bit(__QUEUE_STATE_XOFF, &dev_queue->state);
+}
+
/**
* netif_start_queue - allow transmit
* @dev: network device
*
* Allow upper layers to call the device hard_start_xmit routine.
*/
-static inline void netif_tx_start_queue(struct netdev_queue *dev_queue)
-{
- clear_bit(__QUEUE_STATE_XOFF, &dev_queue->state);
-}
-
static inline void netif_start_queue(struct net_device *dev)
{
netif_tx_start_queue(netdev_get_tx_queue(dev, 0));
@@ -1022,13 +1022,6 @@ static inline void netif_tx_start_all_queues(struct net_device *dev)
}
}
-/**
- * netif_wake_queue - restart transmit
- * @dev: network device
- *
- * Allow upper layers to call the device hard_start_xmit routine.
- * Used for flow control when transmit resources are available.
- */
static inline void netif_tx_wake_queue(struct netdev_queue *dev_queue)
{
#ifdef CONFIG_NETPOLL_TRAP
@@ -1041,6 +1034,13 @@ static inline void netif_tx_wake_queue(struct netdev_queue *dev_queue)
__netif_schedule(dev_queue->qdisc);
}
+/**
+ * netif_wake_queue - restart transmit
+ * @dev: network device
+ *
+ * Allow upper layers to call the device hard_start_xmit routine.
+ * Used for flow control when transmit resources are available.
+ */
static inline void netif_wake_queue(struct net_device *dev)
{
netif_tx_wake_queue(netdev_get_tx_queue(dev, 0));
@@ -1056,6 +1056,11 @@ static inline void netif_tx_wake_all_queues(struct net_device *dev)
}
}
+static inline void netif_tx_stop_queue(struct netdev_queue *dev_queue)
+{
+ set_bit(__QUEUE_STATE_XOFF, &dev_queue->state);
+}
+
/**
* netif_stop_queue - stop transmitted packets
* @dev: network device
@@ -1063,11 +1068,6 @@ static inline void netif_tx_wake_all_queues(struct net_device *dev)
* Stop upper layers calling the device hard_start_xmit routine.
* Used for flow control when transmit resources are unavailable.
*/
-static inline void netif_tx_stop_queue(struct netdev_queue *dev_queue)
-{
- set_bit(__QUEUE_STATE_XOFF, &dev_queue->state);
-}
-
static inline void netif_stop_queue(struct net_device *dev)
{
netif_tx_stop_queue(netdev_get_tx_queue(dev, 0));
@@ -1083,17 +1083,17 @@ static inline void netif_tx_stop_all_queues(struct net_device *dev)
}
}
+static inline int netif_tx_queue_stopped(const struct netdev_queue *dev_queue)
+{
+ return test_bit(__QUEUE_STATE_XOFF, &dev_queue->state);
+}
+
/**
* netif_queue_stopped - test if transmit queue is flowblocked
* @dev: network device
*
* Test if transmit queue on device is currently unable to send.
*/
-static inline int netif_tx_queue_stopped(const struct netdev_queue *dev_queue)
-{
- return test_bit(__QUEUE_STATE_XOFF, &dev_queue->state);
-}
-
static inline int netif_queue_stopped(const struct net_device *dev)
{
return netif_tx_queue_stopped(netdev_get_tx_queue(dev, 0));
@@ -1463,13 +1463,6 @@ static inline void netif_rx_complete(struct net_device *dev,
local_irq_restore(flags);
}
-/**
- * netif_tx_lock - grab network device transmit lock
- * @dev: network device
- * @cpu: cpu number of lock owner
- *
- * Get network device transmit lock
- */
static inline void __netif_tx_lock(struct netdev_queue *txq, int cpu)
{
spin_lock(&txq->_xmit_lock);
@@ -1482,6 +1475,13 @@ static inline void __netif_tx_lock_bh(struct netdev_queue *txq)
txq->xmit_lock_owner = smp_processor_id();
}
+/**
+ * netif_tx_lock - grab network device transmit lock
+ * @dev: network device
+ * @cpu: cpu number of lock owner
+ *
+ * Get network device transmit lock
+ */
static inline void netif_tx_lock(struct net_device *dev)
{
int cpu = smp_processor_id();
@@ -1645,6 +1645,8 @@ extern void dev_seq_stop(struct seq_file *seq, void *v);
extern int netdev_class_create_file(struct class_attribute *class_attr);
extern void netdev_class_remove_file(struct class_attribute *class_attr);
+extern char *netdev_drivername(struct net_device *dev, char *buffer, int len);
+
extern void linkwatch_run_queue(void);
extern int netdev_compute_features(unsigned long all, unsigned long one);
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index a2861d95ecc..108f47e5fd9 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -12,7 +12,6 @@
#include <linux/types.h>
#include <linux/unistd.h>
-#include <linux/dirent.h>
#include <linux/fs.h>
#include <linux/posix_acl.h>
#include <linux/mount.h>
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index bd3d72ddf33..da2698b0fdd 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -214,6 +214,8 @@ static inline int notifier_to_errno(int ret)
#define CPU_DEAD 0x0007 /* CPU (unsigned)v dead */
#define CPU_DYING 0x0008 /* CPU (unsigned)v not running any task,
* not handling interrupts, soon dead */
+#define CPU_POST_DEAD 0x0009 /* CPU (unsigned)v dead, cpu_hotplug
+ * lock is dropped */
/* Used for CPU hotplug events occuring while tasks are frozen due to a suspend
* operation in progress
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index 0e66b57631f..c8a768e5964 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -82,9 +82,12 @@ static inline void get_nsproxy(struct nsproxy *ns)
}
#ifdef CONFIG_CGROUP_NS
-int ns_cgroup_clone(struct task_struct *tsk);
+int ns_cgroup_clone(struct task_struct *tsk, struct pid *pid);
#else
-static inline int ns_cgroup_clone(struct task_struct *tsk) { return 0; }
+static inline int ns_cgroup_clone(struct task_struct *tsk, struct pid *pid)
+{
+ return 0;
+}
#endif
#endif
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
index 2ee97e9877a..67db101d0eb 100644
--- a/include/linux/of_gpio.h
+++ b/include/linux/of_gpio.h
@@ -15,7 +15,7 @@
#define __LINUX_OF_GPIO_H
#include <linux/errno.h>
-#include <asm/gpio.h>
+#include <linux/gpio.h>
#ifdef CONFIG_OF_GPIO
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 0d2a4e7012a..54590a9a103 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -96,7 +96,22 @@ enum pageflags {
#ifdef CONFIG_IA64_UNCACHED_ALLOCATOR
PG_uncached, /* Page has been mapped as uncached */
#endif
- __NR_PAGEFLAGS
+ __NR_PAGEFLAGS,
+
+ /* Filesystems */
+ PG_checked = PG_owner_priv_1,
+
+ /* XEN */
+ PG_pinned = PG_owner_priv_1,
+ PG_savepinned = PG_dirty,
+
+ /* SLOB */
+ PG_slob_page = PG_active,
+ PG_slob_free = PG_private,
+
+ /* SLUB */
+ PG_slub_frozen = PG_active,
+ PG_slub_debug = PG_error,
};
#ifndef __GENERATING_BOUNDS_H
@@ -155,13 +170,19 @@ PAGEFLAG(Dirty, dirty) TESTSCFLAG(Dirty, dirty) __CLEARPAGEFLAG(Dirty, dirty)
PAGEFLAG(LRU, lru) __CLEARPAGEFLAG(LRU, lru)
PAGEFLAG(Active, active) __CLEARPAGEFLAG(Active, active)
__PAGEFLAG(Slab, slab)
-PAGEFLAG(Checked, owner_priv_1) /* Used by some filesystems */
-PAGEFLAG(Pinned, owner_priv_1) TESTSCFLAG(Pinned, owner_priv_1) /* Xen */
-PAGEFLAG(SavePinned, dirty); /* Xen */
+PAGEFLAG(Checked, checked) /* Used by some filesystems */
+PAGEFLAG(Pinned, pinned) TESTSCFLAG(Pinned, pinned) /* Xen */
+PAGEFLAG(SavePinned, savepinned); /* Xen */
PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved)
PAGEFLAG(Private, private) __CLEARPAGEFLAG(Private, private)
__SETPAGEFLAG(Private, private)
+__PAGEFLAG(SlobPage, slob_page)
+__PAGEFLAG(SlobFree, slob_free)
+
+__PAGEFLAG(SlubFrozen, slub_frozen)
+__PAGEFLAG(SlubDebug, slub_debug)
+
/*
* Only test-and-set exist for PG_writeback. The unconditional operators are
* risky: they bypass page accounting.
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index d2fca802f80..ee1ec2c7723 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -22,7 +22,7 @@
static inline void mapping_set_error(struct address_space *mapping, int error)
{
- if (error) {
+ if (unlikely(error)) {
if (error == -ENOSPC)
set_bit(AS_ENOSPC, &mapping->flags);
else
diff --git a/include/linux/parser.h b/include/linux/parser.h
index 7dcd0507575..cc554ca8bc7 100644
--- a/include/linux/parser.h
+++ b/include/linux/parser.h
@@ -14,7 +14,7 @@ struct match_token {
const char *pattern;
};
-typedef struct match_token match_table_t[];
+typedef const struct match_token match_table_t[];
/* Maximum number of arguments that match_token will find in a pattern */
enum {MAX_OPT_ARGS = 3};
diff --git a/include/linux/pci.h b/include/linux/pci.h
index a6a088e1a80..1d296d31abe 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -638,7 +638,9 @@ int pci_save_state(struct pci_dev *dev);
int pci_restore_state(struct pci_dev *dev);
int pci_set_power_state(struct pci_dev *dev, pci_power_t state);
pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
+bool pci_pme_capable(struct pci_dev *dev, pci_power_t state);
int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable);
+pci_power_t pci_target_state(struct pci_dev *dev);
int pci_prepare_to_sleep(struct pci_dev *dev);
int pci_back_from_sleep(struct pci_dev *dev);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index d8507eb394c..c3b1761aba2 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2371,6 +2371,14 @@
#define PCI_DEVICE_ID_INTEL_ICH9_7 0x2916
#define PCI_DEVICE_ID_INTEL_ICH9_8 0x2918
#define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG4 0x3429
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG5 0x342a
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG6 0x342b
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG7 0x342c
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG0 0x3430
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG1 0x3431
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG2 0x3432
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG3 0x3433
#define PCI_DEVICE_ID_INTEL_82830_HB 0x3575
#define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577
#define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580
@@ -2392,6 +2400,9 @@
#define PCI_DEVICE_ID_INTEL_ICH10_4 0x3a30
#define PCI_DEVICE_ID_INTEL_ICH10_5 0x3a60
#define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f
+#define PCI_DEVICE_ID_INTEL_5100_16 0x65f0
+#define PCI_DEVICE_ID_INTEL_5100_21 0x65f5
+#define PCI_DEVICE_ID_INTEL_5100_22 0x65f6
#define PCI_DEVICE_ID_INTEL_5400_ERR 0x4030
#define PCI_DEVICE_ID_INTEL_5400_FBD0 0x4035
#define PCI_DEVICE_ID_INTEL_5400_FBD1 0x4036
diff --git a/include/linux/pid.h b/include/linux/pid.h
index c21c7e8124a..22921ac4cfd 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -48,7 +48,7 @@ enum pid_type
*/
struct upid {
- /* Try to keep pid_chain in the same cacheline as nr for find_pid */
+ /* Try to keep pid_chain in the same cacheline as nr for find_vpid */
int nr;
struct pid_namespace *ns;
struct hlist_node pid_chain;
@@ -57,10 +57,10 @@ struct upid {
struct pid
{
atomic_t count;
+ unsigned int level;
/* lists of tasks that use this pid */
struct hlist_head tasks[PIDTYPE_MAX];
struct rcu_head rcu;
- unsigned int level;
struct upid numbers[1];
};
@@ -105,14 +105,12 @@ extern struct pid_namespace init_pid_ns;
* or rcu_read_lock() held.
*
* find_pid_ns() finds the pid in the namespace specified
- * find_pid() find the pid by its global id, i.e. in the init namespace
* find_vpid() finr the pid by its virtual id, i.e. in the current namespace
*
- * see also find_task_by_pid() set in include/linux/sched.h
+ * see also find_task_by_vpid() set in include/linux/sched.h
*/
extern struct pid *find_pid_ns(int nr, struct pid_namespace *ns);
extern struct pid *find_vpid(int nr);
-extern struct pid *find_pid(int nr);
/*
* Lookup a PID in the hash table, and return with it's count elevated.
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index caff5283d15..1af82c4e17d 100644
--- a/include/linux/pid_namespace.h
+++ b/include/linux/pid_namespace.h
@@ -14,6 +14,8 @@ struct pidmap {
#define PIDMAP_ENTRIES ((PID_MAX_LIMIT + 8*PAGE_SIZE - 1)/PAGE_SIZE/8)
+struct bsd_acct_struct;
+
struct pid_namespace {
struct kref kref;
struct pidmap pidmap[PIDMAP_ENTRIES];
@@ -25,6 +27,9 @@ struct pid_namespace {
#ifdef CONFIG_PROC_FS
struct vfsmount *proc_mnt;
#endif
+#ifdef CONFIG_BSD_PROCESS_ACCT
+ struct bsd_acct_struct *bacct;
+#endif
};
extern struct pid_namespace init_pid_ns;
@@ -85,4 +90,7 @@ static inline struct task_struct *task_child_reaper(struct task_struct *tsk)
return tsk->nsproxy->pid_ns->child_reaper;
}
+void pidhash_init(void);
+void pidmap_init(void);
+
#endif /* _LINUX_PID_NS_H */
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 4ad9de94449..4dcce54b6d7 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -22,78 +22,6 @@
#define _LINUX_PM_H
#include <linux/list.h>
-#include <asm/atomic.h>
-#include <asm/errno.h>
-
-/*
- * Power management requests... these are passed to pm_send_all() and friends.
- *
- * these functions are old and deprecated, see below.
- */
-typedef int __bitwise pm_request_t;
-
-#define PM_SUSPEND ((__force pm_request_t) 1) /* enter D1-D3 */
-#define PM_RESUME ((__force pm_request_t) 2) /* enter D0 */
-
-
-/*
- * Device types... these are passed to pm_register
- */
-typedef int __bitwise pm_dev_t;
-
-#define PM_UNKNOWN_DEV ((__force pm_dev_t) 0) /* generic */
-#define PM_SYS_DEV ((__force pm_dev_t) 1) /* system device (fan, KB controller, ...) */
-#define PM_PCI_DEV ((__force pm_dev_t) 2) /* PCI device */
-#define PM_USB_DEV ((__force pm_dev_t) 3) /* USB device */
-#define PM_SCSI_DEV ((__force pm_dev_t) 4) /* SCSI device */
-#define PM_ISA_DEV ((__force pm_dev_t) 5) /* ISA device */
-#define PM_MTD_DEV ((__force pm_dev_t) 6) /* Memory Technology Device */
-
-/*
- * System device hardware ID (PnP) values
- */
-enum
-{
- PM_SYS_UNKNOWN = 0x00000000, /* generic */
- PM_SYS_KBC = 0x41d00303, /* keyboard controller */
- PM_SYS_COM = 0x41d00500, /* serial port */
- PM_SYS_IRDA = 0x41d00510, /* IRDA controller */
- PM_SYS_FDC = 0x41d00700, /* floppy controller */
- PM_SYS_VGA = 0x41d00900, /* VGA controller */
- PM_SYS_PCMCIA = 0x41d00e00, /* PCMCIA controller */
-};
-
-/*
- * Device identifier
- */
-#define PM_PCI_ID(dev) ((dev)->bus->number << 16 | (dev)->devfn)
-
-/*
- * Request handler callback
- */
-struct pm_dev;
-
-typedef int (*pm_callback)(struct pm_dev *dev, pm_request_t rqst, void *data);
-
-/*
- * Dynamic device information
- */
-struct pm_dev
-{
- pm_dev_t type;
- unsigned long id;
- pm_callback callback;
- void *data;
-
- unsigned long flags;
- unsigned long state;
- unsigned long prev_state;
-
- struct list_head entry;
-};
-
-/* Functions above this comment are list-based old-style power
- * management. Please avoid using them. */
/*
* Callbacks for platform drivers to implement.
@@ -317,6 +245,21 @@ struct pm_ext_ops {
* RECOVER Creation of a hibernation image or restoration of the main
* memory contents from a hibernation image has failed, call
* ->thaw() and ->complete() for all devices.
+ *
+ * The following PM_EVENT_ messages are defined for internal use by
+ * kernel subsystems. They are never issued by the PM core.
+ *
+ * USER_SUSPEND Manual selective suspend was issued by userspace.
+ *
+ * USER_RESUME Manual selective resume was issued by userspace.
+ *
+ * REMOTE_WAKEUP Remote-wakeup request was received from the device.
+ *
+ * AUTO_SUSPEND Automatic (device idle) runtime suspend was
+ * initiated by the subsystem.
+ *
+ * AUTO_RESUME Automatic (device needed) runtime resume was
+ * requested by a driver.
*/
#define PM_EVENT_ON 0x0000
@@ -328,9 +271,18 @@ struct pm_ext_ops {
#define PM_EVENT_THAW 0x0020
#define PM_EVENT_RESTORE 0x0040
#define PM_EVENT_RECOVER 0x0080
+#define PM_EVENT_USER 0x0100
+#define PM_EVENT_REMOTE 0x0200
+#define PM_EVENT_AUTO 0x0400
-#define PM_EVENT_SLEEP (PM_EVENT_SUSPEND | PM_EVENT_HIBERNATE)
+#define PM_EVENT_SLEEP (PM_EVENT_SUSPEND | PM_EVENT_HIBERNATE)
+#define PM_EVENT_USER_SUSPEND (PM_EVENT_USER | PM_EVENT_SUSPEND)
+#define PM_EVENT_USER_RESUME (PM_EVENT_USER | PM_EVENT_RESUME)
+#define PM_EVENT_REMOTE_WAKEUP (PM_EVENT_REMOTE | PM_EVENT_RESUME)
+#define PM_EVENT_AUTO_SUSPEND (PM_EVENT_AUTO | PM_EVENT_SUSPEND)
+#define PM_EVENT_AUTO_RESUME (PM_EVENT_AUTO | PM_EVENT_RESUME)
+#define PMSG_ON ((struct pm_message){ .event = PM_EVENT_ON, })
#define PMSG_FREEZE ((struct pm_message){ .event = PM_EVENT_FREEZE, })
#define PMSG_QUIESCE ((struct pm_message){ .event = PM_EVENT_QUIESCE, })
#define PMSG_SUSPEND ((struct pm_message){ .event = PM_EVENT_SUSPEND, })
@@ -339,7 +291,16 @@ struct pm_ext_ops {
#define PMSG_THAW ((struct pm_message){ .event = PM_EVENT_THAW, })
#define PMSG_RESTORE ((struct pm_message){ .event = PM_EVENT_RESTORE, })
#define PMSG_RECOVER ((struct pm_message){ .event = PM_EVENT_RECOVER, })
-#define PMSG_ON ((struct pm_message){ .event = PM_EVENT_ON, })
+#define PMSG_USER_SUSPEND ((struct pm_messge) \
+ { .event = PM_EVENT_USER_SUSPEND, })
+#define PMSG_USER_RESUME ((struct pm_messge) \
+ { .event = PM_EVENT_USER_RESUME, })
+#define PMSG_REMOTE_RESUME ((struct pm_messge) \
+ { .event = PM_EVENT_REMOTE_RESUME, })
+#define PMSG_AUTO_SUSPEND ((struct pm_messge) \
+ { .event = PM_EVENT_AUTO_SUSPEND, })
+#define PMSG_AUTO_RESUME ((struct pm_messge) \
+ { .event = PM_EVENT_AUTO_RESUME, })
/**
* Device power management states
diff --git a/include/linux/pm_legacy.h b/include/linux/pm_legacy.h
deleted file mode 100644
index 446f4f42b95..00000000000
--- a/include/linux/pm_legacy.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef __LINUX_PM_LEGACY_H__
-#define __LINUX_PM_LEGACY_H__
-
-
-#ifdef CONFIG_PM_LEGACY
-
-/*
- * Register a device with power management
- */
-struct pm_dev __deprecated *
-pm_register(pm_dev_t type, unsigned long id, pm_callback callback);
-
-/*
- * Send a request to all devices
- */
-int __deprecated pm_send_all(pm_request_t rqst, void *data);
-
-#else /* CONFIG_PM_LEGACY */
-
-static inline struct pm_dev *pm_register(pm_dev_t type,
- unsigned long id,
- pm_callback callback)
-{
- return NULL;
-}
-
-static inline int pm_send_all(pm_request_t rqst, void *data)
-{
- return 0;
-}
-
-#endif /* CONFIG_PM_LEGACY */
-
-#endif /* __LINUX_PM_LEGACY_H__ */
-
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index fff1d27ddb4..f560d1705af 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -79,6 +79,7 @@ struct proc_dir_entry {
int pde_users; /* number of callers into module in progress */
spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
struct completion *pde_unload_completion;
+ struct list_head pde_openers; /* who did ->open, but not ->release */
};
struct kcore_list {
@@ -138,7 +139,6 @@ extern int proc_readdir(struct file *, void *, filldir_t);
extern struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *);
extern const struct file_operations proc_kcore_operations;
-extern const struct file_operations proc_kmsg_operations;
extern const struct file_operations ppc_htab_operations;
extern int pid_ns_prepare_proc(struct pid_namespace *ns);
@@ -305,8 +305,6 @@ static inline struct net *PDE_NET(struct proc_dir_entry *pde)
return pde->parent->data;
}
-struct net *get_proc_net(const struct inode *inode);
-
struct proc_maps_private {
struct pid *pid;
struct task_struct *task;
diff --git a/include/linux/profile.h b/include/linux/profile.h
index 05c1cc73693..7e7087239af 100644
--- a/include/linux/profile.h
+++ b/include/linux/profile.h
@@ -8,8 +8,6 @@
#include <asm/errno.h>
-extern int prof_on __read_mostly;
-
#define CPU_PROFILING 1
#define SCHED_PROFILING 2
#define SLEEP_PROFILING 3
@@ -19,14 +17,31 @@ struct proc_dir_entry;
struct pt_regs;
struct notifier_block;
+#if defined(CONFIG_PROFILING) && defined(CONFIG_PROC_FS)
+void create_prof_cpu_mask(struct proc_dir_entry *de);
+#else
+static inline void create_prof_cpu_mask(struct proc_dir_entry *de)
+{
+}
+#endif
+
+enum profile_type {
+ PROFILE_TASK_EXIT,
+ PROFILE_MUNMAP
+};
+
+#ifdef CONFIG_PROFILING
+
+extern int prof_on __read_mostly;
+
/* init basic kernel profiler */
void __init profile_init(void);
-void profile_tick(int);
+void profile_tick(int type);
/*
* Add multiple profiler hits to a given address:
*/
-void profile_hits(int, void *ip, unsigned int nr_hits);
+void profile_hits(int type, void *ip, unsigned int nr_hits);
/*
* Single profiler hit:
@@ -40,19 +55,6 @@ static inline void profile_hit(int type, void *ip)
profile_hits(type, ip, 1);
}
-#ifdef CONFIG_PROC_FS
-void create_prof_cpu_mask(struct proc_dir_entry *);
-#else
-#define create_prof_cpu_mask(x) do { (void)(x); } while (0)
-#endif
-
-enum profile_type {
- PROFILE_TASK_EXIT,
- PROFILE_MUNMAP
-};
-
-#ifdef CONFIG_PROFILING
-
struct task_struct;
struct mm_struct;
@@ -80,6 +82,28 @@ struct pt_regs;
#else
+#define prof_on 0
+
+static inline void profile_init(void)
+{
+ return;
+}
+
+static inline void profile_tick(int type)
+{
+ return;
+}
+
+static inline void profile_hits(int type, void *ip, unsigned int nr_hits)
+{
+ return;
+}
+
+static inline void profile_hit(int type, void *ip)
+{
+ return;
+}
+
static inline int task_handoff_register(struct notifier_block * n)
{
return -ENOSYS;
diff --git a/include/linux/quota.h b/include/linux/quota.h
index dcddfb20094..376a05048bc 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -41,9 +41,6 @@
#define __DQUOT_VERSION__ "dquot_6.5.1"
#define __DQUOT_NUM_VERSION__ 6*10000+5*100+1
-typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */
-typedef __u64 qsize_t; /* Type in which we store sizes */
-
/* Size of blocks in which are counted size limits */
#define QUOTABLOCK_BITS 10
#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
@@ -138,6 +135,10 @@ struct if_dqinfo {
#define QUOTA_NL_BHARDWARN 4 /* Block hardlimit reached */
#define QUOTA_NL_BSOFTLONGWARN 5 /* Block grace time expired */
#define QUOTA_NL_BSOFTWARN 6 /* Block softlimit reached */
+#define QUOTA_NL_IHARDBELOW 7 /* Usage got below inode hardlimit */
+#define QUOTA_NL_ISOFTBELOW 8 /* Usage got below inode softlimit */
+#define QUOTA_NL_BHARDBELOW 9 /* Usage got below block hardlimit */
+#define QUOTA_NL_BSOFTBELOW 10 /* Usage got below block softlimit */
enum {
QUOTA_NL_C_UNSPEC,
@@ -172,6 +173,9 @@ enum {
#include <asm/atomic.h>
+typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */
+typedef __u64 qsize_t; /* Type in which we store sizes */
+
extern spinlock_t dq_data_lock;
/* Maximal numbers of writes for quota operation (insert/delete/update)
@@ -223,12 +227,10 @@ struct super_block;
#define DQF_INFO_DIRTY (1 << DQF_INFO_DIRTY_B) /* Is info dirty? */
extern void mark_info_dirty(struct super_block *sb, int type);
-#define info_dirty(info) test_bit(DQF_INFO_DIRTY_B, &(info)->dqi_flags)
-#define info_any_dquot_dirty(info) (!list_empty(&(info)->dqi_dirty_list))
-#define info_any_dirty(info) (info_dirty(info) || info_any_dquot_dirty(info))
-
-#define sb_dqopt(sb) (&(sb)->s_dquot)
-#define sb_dqinfo(sb, type) (sb_dqopt(sb)->info+(type))
+static inline int info_dirty(struct mem_dqinfo *info)
+{
+ return test_bit(DQF_INFO_DIRTY_B, &info->dqi_flags);
+}
struct dqstats {
int lookups;
@@ -337,19 +339,6 @@ struct quota_info {
struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */
};
-#define sb_has_quota_enabled(sb, type) ((type)==USRQUOTA ? \
- (sb_dqopt(sb)->flags & DQUOT_USR_ENABLED) : (sb_dqopt(sb)->flags & DQUOT_GRP_ENABLED))
-
-#define sb_any_quota_enabled(sb) (sb_has_quota_enabled(sb, USRQUOTA) | \
- sb_has_quota_enabled(sb, GRPQUOTA))
-
-#define sb_has_quota_suspended(sb, type) \
- ((type) == USRQUOTA ? (sb_dqopt(sb)->flags & DQUOT_USR_SUSPENDED) : \
- (sb_dqopt(sb)->flags & DQUOT_GRP_SUSPENDED))
-
-#define sb_any_quota_suspended(sb) (sb_has_quota_suspended(sb, USRQUOTA) | \
- sb_has_quota_suspended(sb, GRPQUOTA))
-
int register_quota_format(struct quota_format_type *fmt);
void unregister_quota_format(struct quota_format_type *fmt);
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index f8670205385..742187f7a05 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -11,42 +11,85 @@
#define _LINUX_QUOTAOPS_
#include <linux/smp_lock.h>
-
#include <linux/fs.h>
+static inline struct quota_info *sb_dqopt(struct super_block *sb)
+{
+ return &sb->s_dquot;
+}
+
#if defined(CONFIG_QUOTA)
/*
* declaration of quota_function calls in kernel.
*/
-extern void sync_dquots(struct super_block *sb, int type);
-
-extern int dquot_initialize(struct inode *inode, int type);
-extern int dquot_drop(struct inode *inode);
-
-extern int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
-extern int dquot_alloc_inode(const struct inode *inode, unsigned long number);
-
-extern int dquot_free_space(struct inode *inode, qsize_t number);
-extern int dquot_free_inode(const struct inode *inode, unsigned long number);
-
-extern int dquot_transfer(struct inode *inode, struct iattr *iattr);
-extern int dquot_commit(struct dquot *dquot);
-extern int dquot_acquire(struct dquot *dquot);
-extern int dquot_release(struct dquot *dquot);
-extern int dquot_commit_info(struct super_block *sb, int type);
-extern int dquot_mark_dquot_dirty(struct dquot *dquot);
-
-extern int vfs_quota_on(struct super_block *sb, int type, int format_id,
- char *path, int remount);
-extern int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
- int format_id, int type);
-extern int vfs_quota_off(struct super_block *sb, int type, int remount);
-extern int vfs_quota_sync(struct super_block *sb, int type);
-extern int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
-extern int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
-extern int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di);
-extern int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di);
+void sync_dquots(struct super_block *sb, int type);
+
+int dquot_initialize(struct inode *inode, int type);
+int dquot_drop(struct inode *inode);
+
+int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
+int dquot_alloc_inode(const struct inode *inode, unsigned long number);
+
+int dquot_free_space(struct inode *inode, qsize_t number);
+int dquot_free_inode(const struct inode *inode, unsigned long number);
+
+int dquot_transfer(struct inode *inode, struct iattr *iattr);
+int dquot_commit(struct dquot *dquot);
+int dquot_acquire(struct dquot *dquot);
+int dquot_release(struct dquot *dquot);
+int dquot_commit_info(struct super_block *sb, int type);
+int dquot_mark_dquot_dirty(struct dquot *dquot);
+
+int vfs_quota_on(struct super_block *sb, int type, int format_id,
+ char *path, int remount);
+int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
+ int format_id, int type);
+int vfs_quota_off(struct super_block *sb, int type, int remount);
+int vfs_quota_sync(struct super_block *sb, int type);
+int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
+int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
+int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di);
+int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di);
+
+void vfs_dq_drop(struct inode *inode);
+int vfs_dq_transfer(struct inode *inode, struct iattr *iattr);
+int vfs_dq_quota_on_remount(struct super_block *sb);
+
+static inline struct mem_dqinfo *sb_dqinfo(struct super_block *sb, int type)
+{
+ return sb_dqopt(sb)->info + type;
+}
+
+/*
+ * Functions for checking status of quota
+ */
+
+static inline int sb_has_quota_enabled(struct super_block *sb, int type)
+{
+ if (type == USRQUOTA)
+ return sb_dqopt(sb)->flags & DQUOT_USR_ENABLED;
+ return sb_dqopt(sb)->flags & DQUOT_GRP_ENABLED;
+}
+
+static inline int sb_any_quota_enabled(struct super_block *sb)
+{
+ return sb_has_quota_enabled(sb, USRQUOTA) ||
+ sb_has_quota_enabled(sb, GRPQUOTA);
+}
+
+static inline int sb_has_quota_suspended(struct super_block *sb, int type)
+{
+ if (type == USRQUOTA)
+ return sb_dqopt(sb)->flags & DQUOT_USR_SUSPENDED;
+ return sb_dqopt(sb)->flags & DQUOT_GRP_SUSPENDED;
+}
+
+static inline int sb_any_quota_suspended(struct super_block *sb)
+{
+ return sb_has_quota_suspended(sb, USRQUOTA) ||
+ sb_has_quota_suspended(sb, GRPQUOTA);
+}
/*
* Operations supported for diskquotas.
@@ -59,38 +102,16 @@ extern struct quotactl_ops vfs_quotactl_ops;
/* It is better to call this function outside of any transaction as it might
* need a lot of space in journal for dquot structure allocation. */
-static inline void DQUOT_INIT(struct inode *inode)
+static inline void vfs_dq_init(struct inode *inode)
{
BUG_ON(!inode->i_sb);
if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode))
inode->i_sb->dq_op->initialize(inode, -1);
}
-/* The same as with DQUOT_INIT */
-static inline void DQUOT_DROP(struct inode *inode)
-{
- /* Here we can get arbitrary inode from clear_inode() so we have
- * to be careful. OTOH we don't need locking as quota operations
- * are allowed to change only at mount time */
- if (!IS_NOQUOTA(inode) && inode->i_sb && inode->i_sb->dq_op
- && inode->i_sb->dq_op->drop) {
- int cnt;
- /* Test before calling to rule out calls from proc and such
- * where we are not allowed to block. Note that this is
- * actually reliable test even without the lock - the caller
- * must assure that nobody can come after the DQUOT_DROP and
- * add quota pointers back anyway */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- if (inode->i_dquot[cnt] != NODQUOT)
- break;
- if (cnt < MAXQUOTAS)
- inode->i_sb->dq_op->drop(inode);
- }
-}
-
/* The following allocation/freeing/transfer functions *must* be called inside
* a transaction (deadlocks possible otherwise) */
-static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_prealloc_space_nodirty(struct inode *inode, qsize_t nr)
{
if (sb_any_quota_enabled(inode->i_sb)) {
/* Used space is updated in alloc_space() */
@@ -102,15 +123,15 @@ static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
return 0;
}
-static inline int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_prealloc_space(struct inode *inode, qsize_t nr)
{
int ret;
- if (!(ret = DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr)))
+ if (!(ret = vfs_dq_prealloc_space_nodirty(inode, nr)))
mark_inode_dirty(inode);
return ret;
}
-static inline int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_alloc_space_nodirty(struct inode *inode, qsize_t nr)
{
if (sb_any_quota_enabled(inode->i_sb)) {
/* Used space is updated in alloc_space() */
@@ -122,25 +143,25 @@ static inline int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
return 0;
}
-static inline int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr)
{
int ret;
- if (!(ret = DQUOT_ALLOC_SPACE_NODIRTY(inode, nr)))
+ if (!(ret = vfs_dq_alloc_space_nodirty(inode, nr)))
mark_inode_dirty(inode);
return ret;
}
-static inline int DQUOT_ALLOC_INODE(struct inode *inode)
+static inline int vfs_dq_alloc_inode(struct inode *inode)
{
if (sb_any_quota_enabled(inode->i_sb)) {
- DQUOT_INIT(inode);
+ vfs_dq_init(inode);
if (inode->i_sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA)
return 1;
}
return 0;
}
-static inline void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
{
if (sb_any_quota_enabled(inode->i_sb))
inode->i_sb->dq_op->free_space(inode, nr);
@@ -148,35 +169,25 @@ static inline void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
inode_sub_bytes(inode, nr);
}
-static inline void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
+static inline void vfs_dq_free_space(struct inode *inode, qsize_t nr)
{
- DQUOT_FREE_SPACE_NODIRTY(inode, nr);
+ vfs_dq_free_space_nodirty(inode, nr);
mark_inode_dirty(inode);
}
-static inline void DQUOT_FREE_INODE(struct inode *inode)
+static inline void vfs_dq_free_inode(struct inode *inode)
{
if (sb_any_quota_enabled(inode->i_sb))
inode->i_sb->dq_op->free_inode(inode, 1);
}
-static inline int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr)
-{
- if (sb_any_quota_enabled(inode->i_sb) && !IS_NOQUOTA(inode)) {
- DQUOT_INIT(inode);
- if (inode->i_sb->dq_op->transfer(inode, iattr) == NO_QUOTA)
- return 1;
- }
- return 0;
-}
-
/* The following two functions cannot be called inside a transaction */
-static inline void DQUOT_SYNC(struct super_block *sb)
+static inline void vfs_dq_sync(struct super_block *sb)
{
sync_dquots(sb, -1);
}
-static inline int DQUOT_OFF(struct super_block *sb, int remount)
+static inline int vfs_dq_off(struct super_block *sb, int remount)
{
int ret = -ENOSYS;
@@ -185,22 +196,27 @@ static inline int DQUOT_OFF(struct super_block *sb, int remount)
return ret;
}
-static inline int DQUOT_ON_REMOUNT(struct super_block *sb)
+#else
+
+static inline int sb_has_quota_enabled(struct super_block *sb, int type)
{
- int cnt;
- int ret = 0, err;
+ return 0;
+}
- if (!sb->s_qcop || !sb->s_qcop->quota_on)
- return -ENOSYS;
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- err = sb->s_qcop->quota_on(sb, cnt, 0, NULL, 1);
- if (err < 0 && !ret)
- ret = err;
- }
- return ret;
+static inline int sb_any_quota_enabled(struct super_block *sb)
+{
+ return 0;
}
-#else
+static inline int sb_has_quota_suspended(struct super_block *sb, int type)
+{
+ return 0;
+}
+
+static inline int sb_any_quota_suspended(struct super_block *sb)
+{
+ return 0;
+}
/*
* NO-OP when quota not configured.
@@ -208,113 +224,144 @@ static inline int DQUOT_ON_REMOUNT(struct super_block *sb)
#define sb_dquot_ops (NULL)
#define sb_quotactl_ops (NULL)
-static inline void DQUOT_INIT(struct inode *inode)
+static inline void vfs_dq_init(struct inode *inode)
{
}
-static inline void DQUOT_DROP(struct inode *inode)
+static inline void vfs_dq_drop(struct inode *inode)
{
}
-static inline int DQUOT_ALLOC_INODE(struct inode *inode)
+static inline int vfs_dq_alloc_inode(struct inode *inode)
{
return 0;
}
-static inline void DQUOT_FREE_INODE(struct inode *inode)
+static inline void vfs_dq_free_inode(struct inode *inode)
{
}
-static inline void DQUOT_SYNC(struct super_block *sb)
+static inline void vfs_dq_sync(struct super_block *sb)
{
}
-static inline int DQUOT_OFF(struct super_block *sb, int remount)
+static inline int vfs_dq_off(struct super_block *sb, int remount)
{
return 0;
}
-static inline int DQUOT_ON_REMOUNT(struct super_block *sb)
+static inline int vfs_dq_quota_on_remount(struct super_block *sb)
{
return 0;
}
-static inline int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr)
+static inline int vfs_dq_transfer(struct inode *inode, struct iattr *iattr)
{
return 0;
}
-static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_prealloc_space_nodirty(struct inode *inode, qsize_t nr)
{
inode_add_bytes(inode, nr);
return 0;
}
-static inline int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_prealloc_space(struct inode *inode, qsize_t nr)
{
- DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr);
+ vfs_dq_prealloc_space_nodirty(inode, nr);
mark_inode_dirty(inode);
return 0;
}
-static inline int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_alloc_space_nodirty(struct inode *inode, qsize_t nr)
{
inode_add_bytes(inode, nr);
return 0;
}
-static inline int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr)
{
- DQUOT_ALLOC_SPACE_NODIRTY(inode, nr);
+ vfs_dq_alloc_space_nodirty(inode, nr);
mark_inode_dirty(inode);
return 0;
}
-static inline void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
{
inode_sub_bytes(inode, nr);
}
-static inline void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
+static inline void vfs_dq_free_space(struct inode *inode, qsize_t nr)
{
- DQUOT_FREE_SPACE_NODIRTY(inode, nr);
+ vfs_dq_free_space_nodirty(inode, nr);
mark_inode_dirty(inode);
}
#endif /* CONFIG_QUOTA */
-static inline int DQUOT_PREALLOC_BLOCK_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_prealloc_block_nodirty(struct inode *inode, qsize_t nr)
{
- return DQUOT_PREALLOC_SPACE_NODIRTY(inode,
+ return vfs_dq_prealloc_space_nodirty(inode,
nr << inode->i_sb->s_blocksize_bits);
}
-static inline int DQUOT_PREALLOC_BLOCK(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_prealloc_block(struct inode *inode, qsize_t nr)
{
- return DQUOT_PREALLOC_SPACE(inode,
+ return vfs_dq_prealloc_space(inode,
nr << inode->i_sb->s_blocksize_bits);
}
-static inline int DQUOT_ALLOC_BLOCK_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_alloc_block_nodirty(struct inode *inode, qsize_t nr)
{
- return DQUOT_ALLOC_SPACE_NODIRTY(inode,
+ return vfs_dq_alloc_space_nodirty(inode,
nr << inode->i_sb->s_blocksize_bits);
}
-static inline int DQUOT_ALLOC_BLOCK(struct inode *inode, qsize_t nr)
+static inline int vfs_dq_alloc_block(struct inode *inode, qsize_t nr)
{
- return DQUOT_ALLOC_SPACE(inode,
+ return vfs_dq_alloc_space(inode,
nr << inode->i_sb->s_blocksize_bits);
}
-static inline void DQUOT_FREE_BLOCK_NODIRTY(struct inode *inode, qsize_t nr)
+static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr)
{
- DQUOT_FREE_SPACE_NODIRTY(inode, nr << inode->i_sb->s_blocksize_bits);
+ vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits);
}
-static inline void DQUOT_FREE_BLOCK(struct inode *inode, qsize_t nr)
+static inline void vfs_dq_free_block(struct inode *inode, qsize_t nr)
{
- DQUOT_FREE_SPACE(inode, nr << inode->i_sb->s_blocksize_bits);
+ vfs_dq_free_space(inode, nr << inode->i_sb->s_blocksize_bits);
}
+/*
+ * Define uppercase equivalents for compatibility with old function names
+ * Can go away when we think all users have been converted (15/04/2008)
+ */
+#define DQUOT_INIT(inode) vfs_dq_init(inode)
+#define DQUOT_DROP(inode) vfs_dq_drop(inode)
+#define DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr) \
+ vfs_dq_prealloc_space_nodirty(inode, nr)
+#define DQUOT_PREALLOC_SPACE(inode, nr) vfs_dq_prealloc_space(inode, nr)
+#define DQUOT_ALLOC_SPACE_NODIRTY(inode, nr) \
+ vfs_dq_alloc_space_nodirty(inode, nr)
+#define DQUOT_ALLOC_SPACE(inode, nr) vfs_dq_alloc_space(inode, nr)
+#define DQUOT_PREALLOC_BLOCK_NODIRTY(inode, nr) \
+ vfs_dq_prealloc_block_nodirty(inode, nr)
+#define DQUOT_PREALLOC_BLOCK(inode, nr) vfs_dq_prealloc_block(inode, nr)
+#define DQUOT_ALLOC_BLOCK_NODIRTY(inode, nr) \
+ vfs_dq_alloc_block_nodirty(inode, nr)
+#define DQUOT_ALLOC_BLOCK(inode, nr) vfs_dq_alloc_block(inode, nr)
+#define DQUOT_ALLOC_INODE(inode) vfs_dq_alloc_inode(inode)
+#define DQUOT_FREE_SPACE_NODIRTY(inode, nr) \
+ vfs_dq_free_space_nodirty(inode, nr)
+#define DQUOT_FREE_SPACE(inode, nr) vfs_dq_free_space(inode, nr)
+#define DQUOT_FREE_BLOCK_NODIRTY(inode, nr) \
+ vfs_dq_free_block_nodirty(inode, nr)
+#define DQUOT_FREE_BLOCK(inode, nr) vfs_dq_free_block(inode, nr)
+#define DQUOT_FREE_INODE(inode) vfs_dq_free_inode(inode)
+#define DQUOT_TRANSFER(inode, iattr) vfs_dq_transfer(inode, iattr)
+#define DQUOT_SYNC(sb) vfs_dq_sync(sb)
+#define DQUOT_OFF(sb, remount) vfs_dq_off(sb, remount)
+#define DQUOT_ON_REMOUNT(sb) vfs_dq_quota_on_remount(sb)
+
#endif /* _LINUX_QUOTAOPS_ */
diff --git a/include/linux/ratelimit.h b/include/linux/ratelimit.h
new file mode 100644
index 00000000000..18a5b9ba9d4
--- /dev/null
+++ b/include/linux/ratelimit.h
@@ -0,0 +1,27 @@
+#ifndef _LINUX_RATELIMIT_H
+#define _LINUX_RATELIMIT_H
+#include <linux/param.h>
+
+#define DEFAULT_RATELIMIT_INTERVAL (5 * HZ)
+#define DEFAULT_RATELIMIT_BURST 10
+
+struct ratelimit_state {
+ int interval;
+ int burst;
+ int printed;
+ int missed;
+ unsigned long begin;
+};
+
+#define DEFINE_RATELIMIT_STATE(name, interval, burst) \
+ struct ratelimit_state name = {interval, burst,}
+
+extern int __ratelimit(struct ratelimit_state *rs);
+
+static inline int ratelimit(void)
+{
+ static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
+ DEFAULT_RATELIMIT_BURST);
+ return __ratelimit(&rs);
+}
+#endif
diff --git a/include/linux/rcupreempt.h b/include/linux/rcupreempt.h
index f04b64eca63..0967f03b070 100644
--- a/include/linux/rcupreempt.h
+++ b/include/linux/rcupreempt.h
@@ -115,16 +115,21 @@ DECLARE_PER_CPU(struct rcu_dyntick_sched, rcu_dyntick_sched);
static inline void rcu_enter_nohz(void)
{
+ static DEFINE_RATELIMIT_STATE(rs, 10 * HZ, 1);
+
smp_mb(); /* CPUs seeing ++ must see prior RCU read-side crit sects */
__get_cpu_var(rcu_dyntick_sched).dynticks++;
- WARN_ON(__get_cpu_var(rcu_dyntick_sched).dynticks & 0x1);
+ WARN_ON_RATELIMIT(__get_cpu_var(rcu_dyntick_sched).dynticks & 0x1, &rs);
}
static inline void rcu_exit_nohz(void)
{
+ static DEFINE_RATELIMIT_STATE(rs, 10 * HZ, 1);
+
smp_mb(); /* CPUs seeing ++ must see later RCU read-side crit sects */
__get_cpu_var(rcu_dyntick_sched).dynticks++;
- WARN_ON(!(__get_cpu_var(rcu_dyntick_sched).dynticks & 0x1));
+ WARN_ON_RATELIMIT(!(__get_cpu_var(rcu_dyntick_sched).dynticks & 0x1),
+ &rs);
}
#else /* CONFIG_NO_HZ */
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index 4aacaeecb56..e9963af16cd 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -526,8 +526,8 @@ struct item_head {
** p is the array of __u32, i is the index into the array, v is the value
** to store there.
*/
-#define get_block_num(p, i) le32_to_cpu(get_unaligned((p) + (i)))
-#define put_block_num(p, i, v) put_unaligned(cpu_to_le32(v), (p) + (i))
+#define get_block_num(p, i) get_unaligned_le32((p) + (i))
+#define put_block_num(p, i, v) put_unaligned_le32((v), (p) + (i))
//
// in old version uniqueness field shows key type
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
index 336ee43ed7d..315517e8bfa 100644
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -152,7 +152,7 @@ struct reiserfs_journal_list {
atomic_t j_nonzerolen;
atomic_t j_commit_left;
atomic_t j_older_commits_done; /* all commits older than this on disk */
- struct semaphore j_commit_lock;
+ struct mutex j_commit_mutex;
unsigned long j_trans_id;
time_t j_timestamp;
struct reiserfs_list_bitmap *j_list_bitmap;
@@ -193,8 +193,8 @@ struct reiserfs_journal {
struct buffer_head *j_header_bh;
time_t j_trans_start_time; /* time this transaction started */
- struct semaphore j_lock;
- struct semaphore j_flush_sem;
+ struct mutex j_mutex;
+ struct mutex j_flush_mutex;
wait_queue_head_t j_join_wait; /* wait for current transaction to finish before starting new one */
atomic_t j_jlock; /* lock for j_join_wait */
int j_list_bitmap_index; /* number of next list bitmap to use */
diff --git a/include/linux/res_counter.h b/include/linux/res_counter.h
index 6d9e1fca098..fdeadd9740d 100644
--- a/include/linux/res_counter.h
+++ b/include/linux/res_counter.h
@@ -63,9 +63,14 @@ u64 res_counter_read_u64(struct res_counter *counter, int member);
ssize_t res_counter_read(struct res_counter *counter, int member,
const char __user *buf, size_t nbytes, loff_t *pos,
int (*read_strategy)(unsigned long long val, char *s));
-ssize_t res_counter_write(struct res_counter *counter, int member,
- const char __user *buf, size_t nbytes, loff_t *pos,
- int (*write_strategy)(char *buf, unsigned long long *val));
+
+typedef int (*write_strategy_fn)(const char *buf, unsigned long long *val);
+
+int res_counter_memparse_write_strategy(const char *buf,
+ unsigned long long *res);
+
+int res_counter_write(struct res_counter *counter, int member,
+ const char *buffer, write_strategy_fn write_strategy);
/*
* the field descriptors. one for each member of res_counter
@@ -95,8 +100,10 @@ void res_counter_init(struct res_counter *counter);
* counter->limit _locked call expects the counter->lock to be taken
*/
-int res_counter_charge_locked(struct res_counter *counter, unsigned long val);
-int res_counter_charge(struct res_counter *counter, unsigned long val);
+int __must_check res_counter_charge_locked(struct res_counter *counter,
+ unsigned long val);
+int __must_check res_counter_charge(struct res_counter *counter,
+ unsigned long val);
/*
* uncharge - tell that some portion of the resource is released
@@ -151,4 +158,20 @@ static inline void res_counter_reset_failcnt(struct res_counter *cnt)
cnt->failcnt = 0;
spin_unlock_irqrestore(&cnt->lock, flags);
}
+
+static inline int res_counter_set_limit(struct res_counter *cnt,
+ unsigned long long limit)
+{
+ unsigned long flags;
+ int ret = -EBUSY;
+
+ spin_lock_irqsave(&cnt->lock, flags);
+ if (cnt->usage < limit) {
+ cnt->limit = limit;
+ ret = 0;
+ }
+ spin_unlock_irqrestore(&cnt->lock, flags);
+ return ret;
+}
+
#endif
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index f2d0d152772..b01fe004cb5 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -115,6 +115,23 @@ extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm);
extern struct class *rtc_class;
+/*
+ * For these RTC methods the device parameter is the physical device
+ * on whatever bus holds the hardware (I2C, Platform, SPI, etc), which
+ * was passed to rtc_device_register(). Its driver_data normally holds
+ * device state, including the rtc_device pointer for the RTC.
+ *
+ * Most of these methods are called with rtc_device.ops_lock held,
+ * through the rtc_*(struct rtc_device *, ...) calls.
+ *
+ * The (current) exceptions are mostly filesystem hooks:
+ * - the proc() hook for procfs
+ * - non-ioctl() chardev hooks: open(), release(), read_callback()
+ * - periodic irq calls: irq_set_state(), irq_set_freq()
+ *
+ * REVISIT those periodic irq calls *do* have ops_lock when they're
+ * issued through ioctl() ...
+ */
struct rtc_class_ops {
int (*open)(struct device *);
void (*release)(struct device *);
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 71fc8136004..e5996984ddd 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -224,4 +224,42 @@ size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
*/
#define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist))
+
+/*
+ * Mapping sg iterator
+ *
+ * Iterates over sg entries mapping page-by-page. On each successful
+ * iteration, @miter->page points to the mapped page and
+ * @miter->length bytes of data can be accessed at @miter->addr. As
+ * long as an interation is enclosed between start and stop, the user
+ * is free to choose control structure and when to stop.
+ *
+ * @miter->consumed is set to @miter->length on each iteration. It
+ * can be adjusted if the user can't consume all the bytes in one go.
+ * Also, a stopped iteration can be resumed by calling next on it.
+ * This is useful when iteration needs to release all resources and
+ * continue later (e.g. at the next interrupt).
+ */
+
+#define SG_MITER_ATOMIC (1 << 0) /* use kmap_atomic */
+
+struct sg_mapping_iter {
+ /* the following three fields can be accessed directly */
+ struct page *page; /* currently mapped page */
+ void *addr; /* pointer to the mapped area */
+ size_t length; /* length of the mapped area */
+ size_t consumed; /* number of consumed bytes */
+
+ /* these are internal states, keep away */
+ struct scatterlist *__sg; /* current entry */
+ unsigned int __nents; /* nr of remaining entries */
+ unsigned int __offset; /* offset within sg */
+ unsigned int __flags;
+};
+
+void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl,
+ unsigned int nents, unsigned int flags);
+bool sg_miter_next(struct sg_mapping_iter *miter);
+void sg_miter_stop(struct sg_mapping_iter *miter);
+
#endif /* _LINUX_SCATTERLIST_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 1941d8b5cf1..42036ffe6b0 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -295,10 +295,11 @@ extern void softlockup_tick(void);
extern void spawn_softlockup_task(void);
extern void touch_softlockup_watchdog(void);
extern void touch_all_softlockup_watchdogs(void);
-extern unsigned long softlockup_thresh;
+extern unsigned int softlockup_panic;
extern unsigned long sysctl_hung_task_check_count;
extern unsigned long sysctl_hung_task_timeout_secs;
extern unsigned long sysctl_hung_task_warnings;
+extern int softlockup_thresh;
#else
static inline void softlockup_tick(void)
{
@@ -505,6 +506,10 @@ struct signal_struct {
unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;
unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
unsigned long inblock, oublock, cinblock, coublock;
+#ifdef CONFIG_TASK_XACCT
+ u64 rchar, wchar, syscr, syscw;
+#endif
+ struct task_io_accounting ioac;
/*
* Cumulative ns of scheduled CPU time for dead threads in the
@@ -667,6 +672,10 @@ struct task_delay_info {
/* io operations performed */
u32 swapin_count; /* total count of the number of swapin block */
/* io operations performed */
+
+ struct timespec freepages_start, freepages_end;
+ u64 freepages_delay; /* wait for memory reclaim */
+ u32 freepages_count; /* total count of memory reclaim */
};
#endif /* CONFIG_TASK_DELAY_ACCT */
@@ -824,7 +833,16 @@ extern void partition_sched_domains(int ndoms_new, cpumask_t *doms_new,
struct sched_domain_attr *dattr_new);
extern int arch_reinit_sched_domains(void);
-#endif /* CONFIG_SMP */
+#else /* CONFIG_SMP */
+
+struct sched_domain_attr;
+
+static inline void
+partition_sched_domains(int ndoms_new, cpumask_t *doms_new,
+ struct sched_domain_attr *dattr_new)
+{
+}
+#endif /* !CONFIG_SMP */
struct io_context; /* See blkdev.h */
#define NGROUPS_SMALL 32
@@ -1247,7 +1265,7 @@ struct task_struct {
#if defined(CONFIG_TASK_XACCT)
u64 acct_rss_mem1; /* accumulated rss usage */
u64 acct_vm_mem1; /* accumulated virtual memory usage */
- cputime_t acct_stimexpd;/* stime since last update */
+ cputime_t acct_timexpd; /* stime + utime since last update */
#endif
#ifdef CONFIG_CPUSETS
nodemask_t mems_allowed;
@@ -1486,7 +1504,7 @@ static inline void put_task_struct(struct task_struct *t)
#define PF_KSWAPD 0x00040000 /* I am kswapd */
#define PF_SWAPOFF 0x00080000 /* I am in swapoff */
#define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */
-#define PF_BORROWED_MM 0x00200000 /* I am a kthread doing use_mm */
+#define PF_KTHREAD 0x00200000 /* I am a kernel thread */
#define PF_RANDOMIZE 0x00400000 /* randomize virtual address space */
#define PF_SWAPWRITE 0x00800000 /* Allowed to write to swap */
#define PF_SPREAD_PAGE 0x01000000 /* Spread page cache over cpuset */
@@ -1705,19 +1723,13 @@ extern struct pid_namespace init_pid_ns;
* finds a task by its pid in the specified namespace
* find_task_by_vpid():
* finds a task by its virtual pid
- * find_task_by_pid():
- * finds a task by its global pid
*
- * see also find_pid() etc in include/linux/pid.h
+ * see also find_vpid() etc in include/linux/pid.h
*/
extern struct task_struct *find_task_by_pid_type_ns(int type, int pid,
struct pid_namespace *ns);
-static inline struct task_struct *__deprecated find_task_by_pid(pid_t nr)
-{
- return find_task_by_pid_type_ns(PIDTYPE_PID, nr, &init_pid_ns);
-}
extern struct task_struct *find_task_by_vpid(pid_t nr);
extern struct task_struct *find_task_by_pid_ns(pid_t nr,
struct pid_namespace *ns);
@@ -1790,7 +1802,6 @@ extern void force_sig(int, struct task_struct *);
extern void force_sig_specific(int, struct task_struct *);
extern int send_sig(int, struct task_struct *, int);
extern void zap_other_threads(struct task_struct *p);
-extern int kill_proc(pid_t, int, int);
extern struct sigqueue *sigqueue_alloc(void);
extern void sigqueue_free(struct sigqueue *);
extern int send_sigqueue(struct sigqueue *, struct task_struct *, int group);
@@ -1973,6 +1984,13 @@ static inline unsigned long *end_of_stack(struct task_struct *p)
#endif
+static inline int object_is_on_stack(void *obj)
+{
+ void *stack = task_stack_page(current);
+
+ return (obj >= stack) && (obj < (stack + THREAD_SIZE));
+}
+
extern void thread_info_cache_init(void);
/* set thread flags in other task's structures
@@ -2037,9 +2055,6 @@ static inline int signal_pending_state(long state, struct task_struct *p)
if (!signal_pending(p))
return 0;
- if (state & (__TASK_STOPPED | __TASK_TRACED))
- return 0;
-
return (state & TASK_INTERRUPTIBLE) || __fatal_signal_pending(p);
}
diff --git a/include/linux/security.h b/include/linux/security.h
index 31c8851ec5d..f0e9adb22ac 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -102,9 +102,7 @@ extern unsigned long mmap_min_addr;
#define LSM_SETID_FS 8
/* forward declares to avoid warnings */
-struct nfsctl_arg;
struct sched_param;
-struct swap_info_struct;
struct request_sock;
/* bprm_apply_creds unsafe reasons */
diff --git a/include/linux/sem.h b/include/linux/sem.h
index c8eaad9e4b7..1b191c176bc 100644
--- a/include/linux/sem.h
+++ b/include/linux/sem.h
@@ -78,6 +78,7 @@ struct seminfo {
#ifdef __KERNEL__
#include <asm/atomic.h>
+#include <linux/rcupdate.h>
struct task_struct;
@@ -93,23 +94,19 @@ struct sem_array {
time_t sem_otime; /* last semop time */
time_t sem_ctime; /* last change time */
struct sem *sem_base; /* ptr to first semaphore in array */
- struct sem_queue *sem_pending; /* pending operations to be processed */
- struct sem_queue **sem_pending_last; /* last pending operation */
- struct sem_undo *undo; /* undo requests on this array */
+ struct list_head sem_pending; /* pending operations to be processed */
+ struct list_head list_id; /* undo requests on this array */
unsigned long sem_nsems; /* no. of semaphores in array */
};
/* One queue for each sleeping process in the system. */
struct sem_queue {
- struct sem_queue * next; /* next entry in the queue */
- struct sem_queue ** prev; /* previous entry in the queue, *(q->prev) == q */
- struct task_struct* sleeper; /* this process */
- struct sem_undo * undo; /* undo structure */
+ struct list_head list; /* queue of pending operations */
+ struct task_struct *sleeper; /* this process */
+ struct sem_undo *undo; /* undo structure */
int pid; /* process id of requesting process */
int status; /* completion status of operation */
- struct sem_array * sma; /* semaphore array for operations */
- int id; /* internal sem id */
- struct sembuf * sops; /* array of pending operations */
+ struct sembuf *sops; /* array of pending operations */
int nsops; /* number of operations */
int alter; /* does the operation alter the array? */
};
@@ -118,8 +115,11 @@ struct sem_queue {
* when the process exits.
*/
struct sem_undo {
- struct sem_undo * proc_next; /* next entry on this process */
- struct sem_undo * id_next; /* next entry on this semaphore set */
+ struct list_head list_proc; /* per-process list: all undos from one process. */
+ /* rcu protected */
+ struct rcu_head rcu; /* rcu struct for sem_undo() */
+ struct sem_undo_list *ulp; /* sem_undo_list for the process */
+ struct list_head list_id; /* per semaphore array list: all undos for one array */
int semid; /* semaphore set identifier */
short * semadj; /* array of adjustments, one per semaphore */
};
@@ -128,9 +128,9 @@ struct sem_undo {
* that may be shared among all a CLONE_SYSVSEM task group.
*/
struct sem_undo_list {
- atomic_t refcnt;
- spinlock_t lock;
- struct sem_undo *proc_list;
+ atomic_t refcnt;
+ spinlock_t lock;
+ struct list_head list_proc;
};
struct sysv_sem {
diff --git a/include/linux/semaphore.h b/include/linux/semaphore.h
index 9cae64b00d6..7415839ac89 100644
--- a/include/linux/semaphore.h
+++ b/include/linux/semaphore.h
@@ -26,10 +26,8 @@ struct semaphore {
.wait_list = LIST_HEAD_INIT((name).wait_list), \
}
-#define __DECLARE_SEMAPHORE_GENERIC(name, count) \
- struct semaphore name = __SEMAPHORE_INITIALIZER(name, count)
-
-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
+#define DECLARE_MUTEX(name) \
+ struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
static inline void sema_init(struct semaphore *sem, int val)
{
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index f3a1c0e4502..3b2f6c04855 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -59,9 +59,6 @@
#define PORT_SUNZILOG 38
#define PORT_SUNSAB 39
-/* NEC v850. */
-#define PORT_V850E_UART 40
-
/* DEC */
#define PORT_DZ 46
#define PORT_ZS 47
diff --git a/include/linux/signalfd.h b/include/linux/signalfd.h
index ea037f28df9..bef0c46d471 100644
--- a/include/linux/signalfd.h
+++ b/include/linux/signalfd.h
@@ -8,6 +8,12 @@
#ifndef _LINUX_SIGNALFD_H
#define _LINUX_SIGNALFD_H
+/* For O_CLOEXEC and O_NONBLOCK */
+#include <linux/fcntl.h>
+
+/* Flags for signalfd4. */
+#define SFD_CLOEXEC O_CLOEXEC
+#define SFD_NONBLOCK O_NONBLOCK
struct signalfd_siginfo {
__u32 ssi_signo;
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 9aa90a6f20e..41103910f8a 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -180,7 +180,7 @@ size_t ksize(const void *);
*/
static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
{
- if (n != 0 && size > ULONG_MAX / n)
+ if (size != 0 && n > ULONG_MAX / size)
return NULL;
return __kmalloc(n * size, flags | __GFP_ZERO);
}
diff --git a/include/linux/sm501.h b/include/linux/sm501.h
index 95c1c39ba44..214f93209b8 100644
--- a/include/linux/sm501.h
+++ b/include/linux/sm501.h
@@ -46,24 +46,6 @@ extern unsigned long sm501_modify_reg(struct device *dev,
unsigned long set,
unsigned long clear);
-/* sm501_gpio_set
- *
- * set the state of the given GPIO line
-*/
-
-extern void sm501_gpio_set(struct device *dev,
- unsigned long gpio,
- unsigned int to,
- unsigned int dir);
-
-/* sm501_gpio_get
- *
- * get the state of the given GPIO line
-*/
-
-extern unsigned long sm501_gpio_get(struct device *dev,
- unsigned long gpio);
-
/* Platform data definitions */
@@ -73,6 +55,8 @@ extern unsigned long sm501_gpio_get(struct device *dev,
#define SM501FB_FLAG_USE_HWACCEL (1<<3)
#define SM501FB_FLAG_PANEL_NO_FPEN (1<<4)
#define SM501FB_FLAG_PANEL_NO_VBIASEN (1<<5)
+#define SM501FB_FLAG_PANEL_INV_FPEN (1<<6)
+#define SM501FB_FLAG_PANEL_INV_VBIASEN (1<<7)
struct sm501_platdata_fbsub {
struct fb_videomode *def_mode;
@@ -102,11 +86,19 @@ struct sm501_platdata_fb {
struct sm501_platdata_fbsub *fb_pnl;
};
-/* gpio i2c */
+/* gpio i2c
+ *
+ * Note, we have to pass in the bus number, as the number used will be
+ * passed to the i2c-gpio driver's platform_device.id, subsequently used
+ * to register the i2c bus.
+*/
struct sm501_platdata_gpio_i2c {
+ unsigned int bus_num;
unsigned int pin_sda;
unsigned int pin_scl;
+ int udelay;
+ int timeout;
};
/* sm501_initdata
@@ -129,6 +121,7 @@ struct sm501_reg_init {
#define SM501_USE_FBACCEL (1<<6)
#define SM501_USE_AC97 (1<<7)
#define SM501_USE_I2S (1<<8)
+#define SM501_USE_GPIO (1<<9)
#define SM501_USE_ALL (0xffffffff)
@@ -155,6 +148,8 @@ struct sm501_init_gpio {
struct sm501_reg_init gpio_ddr_high;
};
+#define SM501_FLAG_SUSPEND_OFF (1<<4)
+
/* sm501_platdata
*
* This is passed with the platform device to allow the board
@@ -168,6 +163,12 @@ struct sm501_platdata {
struct sm501_init_gpio *init_gpiop;
struct sm501_platdata_fb *fb;
+ int flags;
+ int gpio_base;
+
+ int (*get_power)(struct device *dev);
+ int (*set_power)(struct device *dev, unsigned int on);
+
struct sm501_platdata_gpio_i2c *gpio_i2c;
unsigned int gpio_i2c_nr;
};
diff --git a/include/linux/smb_fs.h b/include/linux/smb_fs.h
index 2c5cd55f44f..923cd8a247b 100644
--- a/include/linux/smb_fs.h
+++ b/include/linux/smb_fs.h
@@ -43,18 +43,13 @@ static inline struct smb_inode_info *SMB_I(struct inode *inode)
}
/* macro names are short for word, double-word, long value (?) */
-#define WVAL(buf,pos) \
- (le16_to_cpu(get_unaligned((__le16 *)((u8 *)(buf) + (pos)))))
-#define DVAL(buf,pos) \
- (le32_to_cpu(get_unaligned((__le32 *)((u8 *)(buf) + (pos)))))
-#define LVAL(buf,pos) \
- (le64_to_cpu(get_unaligned((__le64 *)((u8 *)(buf) + (pos)))))
-#define WSET(buf,pos,val) \
- put_unaligned(cpu_to_le16((u16)(val)), (__le16 *)((u8 *)(buf) + (pos)))
-#define DSET(buf,pos,val) \
- put_unaligned(cpu_to_le32((u32)(val)), (__le32 *)((u8 *)(buf) + (pos)))
-#define LSET(buf,pos,val) \
- put_unaligned(cpu_to_le64((u64)(val)), (__le64 *)((u8 *)(buf) + (pos)))
+#define WVAL(buf, pos) (get_unaligned_le16((u8 *)(buf) + (pos)))
+#define DVAL(buf, pos) (get_unaligned_le32((u8 *)(buf) + (pos)))
+#define LVAL(buf, pos) (get_unaligned_le64((u8 *)(buf) + (pos)))
+
+#define WSET(buf, pos, val) put_unaligned_le16((val), (u8 *)(buf) + (pos))
+#define DSET(buf, pos, val) put_unaligned_le32((val), (u8 *)(buf) + (pos))
+#define LSET(buf, pos, val) put_unaligned_le64((val), (u8 *)(buf) + (pos))
/* where to find the base of the SMB packet proper */
#define smb_base(buf) ((u8 *)(((u8 *)(buf))+4))
diff --git a/include/linux/smc91x.h b/include/linux/smc91x.h
index 8e0556b8781..3827b922ba1 100644
--- a/include/linux/smc91x.h
+++ b/include/linux/smc91x.h
@@ -5,9 +5,19 @@
#define SMC91X_USE_16BIT (1 << 1)
#define SMC91X_USE_32BIT (1 << 2)
+#define SMC91X_NOWAIT (1 << 3)
+
+/* two bits for IO_SHIFT, let's hope later designs will keep this sane */
+#define SMC91X_IO_SHIFT_0 (0 << 4)
+#define SMC91X_IO_SHIFT_1 (1 << 4)
+#define SMC91X_IO_SHIFT_2 (2 << 4)
+#define SMC91X_IO_SHIFT_3 (3 << 4)
+#define SMC91X_IO_SHIFT(x) (((x) >> 4) & 0x3)
+
+#define SMC91X_USE_DMA (1 << 6)
+
struct smc91x_platdata {
unsigned long flags;
- unsigned long irq_flags; /* IRQF_... */
};
#endif /* __SMC91X_H__ */
diff --git a/include/linux/spi/ds1305.h b/include/linux/spi/ds1305.h
new file mode 100644
index 00000000000..287ec830eab
--- /dev/null
+++ b/include/linux/spi/ds1305.h
@@ -0,0 +1,35 @@
+#ifndef __LINUX_SPI_DS1305_H
+#define __LINUX_SPI_DS1305_H
+
+/*
+ * One-time configuration for ds1305 and ds1306 RTC chips.
+ *
+ * Put a pointer to this in spi_board_info.platform_data if you want to
+ * be sure that Linux (re)initializes this as needed ... after losing
+ * backup power, and potentially on the first boot.
+ */
+struct ds1305_platform_data {
+
+ /* Trickle charge configuration: it's OK to leave out the MAGIC
+ * bitmask; mask in either DS1 or DS2, and then one of 2K/4k/8K.
+ */
+#define DS1305_TRICKLE_MAGIC 0xa0
+#define DS1305_TRICKLE_DS2 0x08 /* two diodes */
+#define DS1305_TRICKLE_DS1 0x04 /* one diode */
+#define DS1305_TRICKLE_2K 0x01 /* 2 KOhm resistance */
+#define DS1305_TRICKLE_4K 0x02 /* 4 KOhm resistance */
+#define DS1305_TRICKLE_8K 0x03 /* 8 KOhm resistance */
+ u8 trickle;
+
+ /* set only on ds1306 parts */
+ bool is_ds1306;
+
+ /* ds1306 only: enable 1 Hz output */
+ bool en_1hz;
+
+ /* REVISIT: the driver currently expects nINT0 to be wired
+ * as the alarm IRQ. ALM1 may also need to be set up ...
+ */
+};
+
+#endif /* __LINUX_SPI_DS1305_H */
diff --git a/include/linux/spi/max7301.h b/include/linux/spi/max7301.h
new file mode 100644
index 00000000000..6dfd83f19b4
--- /dev/null
+++ b/include/linux/spi/max7301.h
@@ -0,0 +1,9 @@
+#ifndef LINUX_SPI_MAX7301_H
+#define LINUX_SPI_MAX7301_H
+
+struct max7301_platform_data {
+ /* number assigned to the first GPIO */
+ unsigned base;
+};
+
+#endif
diff --git a/include/linux/spi/mcp23s08.h b/include/linux/spi/mcp23s08.h
index 835ddf47d45..22ef107d770 100644
--- a/include/linux/spi/mcp23s08.h
+++ b/include/linux/spi/mcp23s08.h
@@ -1,18 +1,25 @@
-/* FIXME driver should be able to handle all four slaves that
- * can be hooked up to each chipselect, as well as IRQs...
- */
+/* FIXME driver should be able to handle IRQs... */
+
+struct mcp23s08_chip_info {
+ bool is_present; /* true iff populated */
+ u8 pullups; /* BIT(x) means enable pullup x */
+};
struct mcp23s08_platform_data {
- /* four slaves can share one SPI chipselect */
- u8 slave;
+ /* Four slaves (numbered 0..3) can share one SPI chipselect, and
+ * will provide 8..32 GPIOs using 1..4 gpio_chip instances.
+ */
+ struct mcp23s08_chip_info chip[4];
- /* number assigned to the first GPIO */
+ /* "base" is the number of the first GPIO. Dynamic assignment is
+ * not currently supported, and even if there are gaps in chip
+ * addressing the GPIO numbers are sequential .. so for example
+ * if only slaves 0 and 3 are present, their GPIOs range from
+ * base to base+15.
+ */
unsigned base;
- /* pins with pullups */
- u8 pullups;
-
void *context; /* param to setup/teardown */
int (*setup)(struct spi_device *spi,
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 387e428f1cd..a9cc29d4665 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -82,7 +82,7 @@ struct spi_device {
int irq;
void *controller_state;
void *controller_data;
- const char *modalias;
+ char modalias[32];
/*
* likely need more hooks for more protocol options affecting how
@@ -733,7 +733,7 @@ struct spi_board_info {
* controller_data goes to spi_device.controller_data,
* irq is copied too
*/
- char modalias[KOBJ_NAME_LEN];
+ char modalias[32];
const void *platform_data;
void *controller_data;
int irq;
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index d311a090fae..61e5610ad16 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -46,6 +46,7 @@
* linux/spinlock.h: builds the final spin_*() APIs.
*/
+#include <linux/typecheck.h>
#include <linux/preempt.h>
#include <linux/linkage.h>
#include <linux/compiler.h>
@@ -191,23 +192,53 @@ do { \
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
-#define spin_lock_irqsave(lock, flags) flags = _spin_lock_irqsave(lock)
-#define read_lock_irqsave(lock, flags) flags = _read_lock_irqsave(lock)
-#define write_lock_irqsave(lock, flags) flags = _write_lock_irqsave(lock)
+#define spin_lock_irqsave(lock, flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ flags = _spin_lock_irqsave(lock); \
+ } while (0)
+#define read_lock_irqsave(lock, flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ flags = _read_lock_irqsave(lock); \
+ } while (0)
+#define write_lock_irqsave(lock, flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ flags = _write_lock_irqsave(lock); \
+ } while (0)
#ifdef CONFIG_DEBUG_LOCK_ALLOC
-#define spin_lock_irqsave_nested(lock, flags, subclass) \
- flags = _spin_lock_irqsave_nested(lock, subclass)
+#define spin_lock_irqsave_nested(lock, flags, subclass) \
+ do { \
+ typecheck(unsigned long, flags); \
+ flags = _spin_lock_irqsave_nested(lock, subclass); \
+ } while (0)
#else
-#define spin_lock_irqsave_nested(lock, flags, subclass) \
- flags = _spin_lock_irqsave(lock)
+#define spin_lock_irqsave_nested(lock, flags, subclass) \
+ do { \
+ typecheck(unsigned long, flags); \
+ flags = _spin_lock_irqsave(lock); \
+ } while (0)
#endif
#else
-#define spin_lock_irqsave(lock, flags) _spin_lock_irqsave(lock, flags)
-#define read_lock_irqsave(lock, flags) _read_lock_irqsave(lock, flags)
-#define write_lock_irqsave(lock, flags) _write_lock_irqsave(lock, flags)
+#define spin_lock_irqsave(lock, flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ _spin_lock_irqsave(lock, flags); \
+ } while (0)
+#define read_lock_irqsave(lock, flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ _read_lock_irqsave(lock, flags); \
+ } while (0)
+#define write_lock_irqsave(lock, flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ _write_lock_irqsave(lock, flags); \
+ } while (0)
#define spin_lock_irqsave_nested(lock, flags, subclass) \
spin_lock_irqsave(lock, flags)
@@ -260,16 +291,25 @@ do { \
} while (0)
#endif
-#define spin_unlock_irqrestore(lock, flags) \
- _spin_unlock_irqrestore(lock, flags)
+#define spin_unlock_irqrestore(lock, flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ _spin_unlock_irqrestore(lock, flags); \
+ } while (0)
#define spin_unlock_bh(lock) _spin_unlock_bh(lock)
-#define read_unlock_irqrestore(lock, flags) \
- _read_unlock_irqrestore(lock, flags)
+#define read_unlock_irqrestore(lock, flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ _read_unlock_irqrestore(lock, flags); \
+ } while (0)
#define read_unlock_bh(lock) _read_unlock_bh(lock)
-#define write_unlock_irqrestore(lock, flags) \
- _write_unlock_irqrestore(lock, flags)
+#define write_unlock_irqrestore(lock, flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ _write_unlock_irqrestore(lock, flags); \
+ } while (0)
#define write_unlock_bh(lock) _write_unlock_bh(lock)
#define spin_trylock_bh(lock) __cond_lock(lock, _spin_trylock_bh(lock))
diff --git a/include/linux/string.h b/include/linux/string.h
index efdc44593b5..810d80df0a1 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -111,5 +111,8 @@ extern void argv_free(char **argv);
extern bool sysfs_streq(const char *s1, const char *s2);
+extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
+ const void *from, size_t available);
+
#endif
#endif /* _LINUX_STRING_H_ */
diff --git a/include/linux/synclink.h b/include/linux/synclink.h
index 45f6bc82d31..c844a229acc 100644
--- a/include/linux/synclink.h
+++ b/include/linux/synclink.h
@@ -136,6 +136,7 @@
#define MGSL_INTERFACE_RTS_EN 0x10
#define MGSL_INTERFACE_LL 0x20
#define MGSL_INTERFACE_RL 0x40
+#define MGSL_INTERFACE_MSB_FIRST 0x80
typedef struct _MGSL_PARAMS
{
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 0522f368f9d..d6ff145919c 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -305,6 +305,7 @@ asmlinkage long sys_fcntl64(unsigned int fd,
#endif
asmlinkage long sys_dup(unsigned int fildes);
asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd);
+asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags);
asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd,
unsigned long arg);
@@ -409,6 +410,8 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname,
asmlinkage long sys_bind(int, struct sockaddr __user *, int);
asmlinkage long sys_connect(int, struct sockaddr __user *, int);
asmlinkage long sys_accept(int, struct sockaddr __user *, int __user *);
+asmlinkage long sys_paccept(int, struct sockaddr __user *, int __user *,
+ const __user sigset_t *, size_t, int);
asmlinkage long sys_getsockname(int, struct sockaddr __user *, int __user *);
asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *);
asmlinkage long sys_send(int, void __user *, size_t, unsigned);
@@ -428,6 +431,7 @@ asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
fd_set __user *exp, struct timeval __user *tvp);
asmlinkage long sys_epoll_create(int size);
+asmlinkage long sys_epoll_create1(int flags);
asmlinkage long sys_epoll_ctl(int epfd, int op, int fd,
struct epoll_event __user *event);
asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events,
@@ -443,7 +447,7 @@ asmlinkage long sys_newuname(struct new_utsname __user *name);
asmlinkage long sys_getrlimit(unsigned int resource,
struct rlimit __user *rlim);
-#if defined(COMPAT_RLIM_OLD_INFINITY) || !(defined(CONFIG_IA64) || defined(CONFIG_V850))
+#if defined(COMPAT_RLIM_OLD_INFINITY) || !(defined(CONFIG_IA64))
asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *rlim);
#endif
asmlinkage long sys_setrlimit(unsigned int resource,
@@ -543,6 +547,7 @@ asmlinkage long sys_get_mempolicy(int __user *policy,
unsigned long addr, unsigned long flags);
asmlinkage long sys_inotify_init(void);
+asmlinkage long sys_inotify_init1(int flags);
asmlinkage long sys_inotify_add_watch(int fd, const char __user *path,
u32 mask);
asmlinkage long sys_inotify_rm_watch(int fd, u32 wd);
@@ -608,12 +613,14 @@ asmlinkage long sys_set_robust_list(struct robust_list_head __user *head,
size_t len);
asmlinkage long sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct getcpu_cache __user *cache);
asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask);
+asmlinkage long sys_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, int flags);
asmlinkage long sys_timerfd_create(int clockid, int flags);
asmlinkage long sys_timerfd_settime(int ufd, int flags,
const struct itimerspec __user *utmr,
struct itimerspec __user *otmr);
asmlinkage long sys_timerfd_gettime(int ufd, struct itimerspec __user *otmr);
asmlinkage long sys_eventfd(unsigned int count);
+asmlinkage long sys_eventfd2(unsigned int count, int flags);
asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len);
int kernel_execve(const char *filename, char *const argv[], char *const envp[]);
diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h
index f2767bc6b73..f395bb3fa2f 100644
--- a/include/linux/sysdev.h
+++ b/include/linux/sysdev.h
@@ -99,8 +99,9 @@ extern void sysdev_unregister(struct sys_device *);
struct sysdev_attribute {
struct attribute attr;
- ssize_t (*show)(struct sys_device *, char *);
- ssize_t (*store)(struct sys_device *, const char *, size_t);
+ ssize_t (*show)(struct sys_device *, struct sysdev_attribute *, char *);
+ ssize_t (*store)(struct sys_device *, struct sysdev_attribute *,
+ const char *, size_t);
};
@@ -118,4 +119,38 @@ struct sysdev_attribute {
extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *);
extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *);
+struct sysdev_ext_attribute {
+ struct sysdev_attribute attr;
+ void *var;
+};
+
+/*
+ * Support for simple variable sysdev attributes.
+ * The pointer to the variable is stored in a sysdev_ext_attribute
+ */
+
+/* Add more types as needed */
+
+extern ssize_t sysdev_show_ulong(struct sys_device *, struct sysdev_attribute *,
+ char *);
+extern ssize_t sysdev_store_ulong(struct sys_device *,
+ struct sysdev_attribute *, const char *, size_t);
+extern ssize_t sysdev_show_int(struct sys_device *, struct sysdev_attribute *,
+ char *);
+extern ssize_t sysdev_store_int(struct sys_device *,
+ struct sysdev_attribute *, const char *, size_t);
+
+#define _SYSDEV_ULONG_ATTR(_name, _mode, _var) \
+ { _SYSDEV_ATTR(_name, _mode, sysdev_show_ulong, sysdev_store_ulong), \
+ &(_var) }
+#define SYSDEV_ULONG_ATTR(_name, _mode, _var) \
+ struct sysdev_ext_attribute attr_##_name = \
+ _SYSDEV_ULONG_ATTR(_name, _mode, _var);
+#define _SYSDEV_INT_ATTR(_name, _mode, _var) \
+ { _SYSDEV_ATTR(_name, _mode, sysdev_show_int, sysdev_store_int), \
+ &(_var) }
+#define SYSDEV_INT_ATTR(_name, _mode, _var) \
+ struct sysdev_ext_attribute attr_##_name = \
+ _SYSDEV_INT_ATTR(_name, _mode, _var);
+
#endif /* _SYSDEV_H_ */
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 7858eac40aa..37fa24152bd 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -101,6 +101,9 @@ void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr);
int __must_check sysfs_create_link(struct kobject *kobj, struct kobject *target,
const char *name);
+int __must_check sysfs_create_link_nowarn(struct kobject *kobj,
+ struct kobject *target,
+ const char *name);
void sysfs_remove_link(struct kobject *kobj, const char *name);
int __must_check sysfs_create_group(struct kobject *kobj,
@@ -180,6 +183,13 @@ static inline int sysfs_create_link(struct kobject *kobj,
return 0;
}
+static inline int sysfs_create_link_nowarn(struct kobject *kobj,
+ struct kobject *target,
+ const char *name)
+{
+ return 0;
+}
+
static inline void sysfs_remove_link(struct kobject *kobj, const char *name)
{
}
diff --git a/include/linux/taskstats.h b/include/linux/taskstats.h
index 5d69c0744ff..18269e956a7 100644
--- a/include/linux/taskstats.h
+++ b/include/linux/taskstats.h
@@ -31,7 +31,7 @@
*/
-#define TASKSTATS_VERSION 6
+#define TASKSTATS_VERSION 7
#define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN
* in linux/sched.h */
@@ -157,6 +157,10 @@ struct taskstats {
__u64 ac_utimescaled; /* utime scaled on frequency etc */
__u64 ac_stimescaled; /* stime scaled on frequency etc */
__u64 cpu_scaled_run_real_total; /* scaled cpu_run_real_total */
+
+ /* Delay waiting for memory reclaim */
+ __u64 freepages_count;
+ __u64 freepages_delay_total;
};
diff --git a/include/linux/tick.h b/include/linux/tick.h
index a881c652f7e..d3c02695dc5 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -49,6 +49,7 @@ struct tick_sched {
unsigned long check_clocks;
enum tick_nohz_mode nohz_mode;
ktime_t idle_tick;
+ int inidle;
int tick_stopped;
unsigned long idle_jiffies;
unsigned long idle_calls;
@@ -105,14 +106,14 @@ static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
# ifdef CONFIG_NO_HZ
-extern void tick_nohz_stop_sched_tick(void);
+extern void tick_nohz_stop_sched_tick(int inidle);
extern void tick_nohz_restart_sched_tick(void);
extern void tick_nohz_update_jiffies(void);
extern ktime_t tick_nohz_get_sleep_length(void);
extern void tick_nohz_stop_idle(int cpu);
extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time);
# else
-static inline void tick_nohz_stop_sched_tick(void) { }
+static inline void tick_nohz_stop_sched_tick(int inidle) { }
static inline void tick_nohz_restart_sched_tick(void) { }
static inline void tick_nohz_update_jiffies(void) { }
static inline ktime_t tick_nohz_get_sleep_length(void)
diff --git a/include/linux/timerfd.h b/include/linux/timerfd.h
index cf2b10d7573..86cb0501d3e 100644
--- a/include/linux/timerfd.h
+++ b/include/linux/timerfd.h
@@ -8,9 +8,15 @@
#ifndef _LINUX_TIMERFD_H
#define _LINUX_TIMERFD_H
+/* For O_CLOEXEC and O_NONBLOCK */
+#include <linux/fcntl.h>
+/* Flags for timerfd_settime. */
#define TFD_TIMER_ABSTIME (1 << 0)
+/* Flags for timerfd_create. */
+#define TFD_CLOEXEC O_CLOEXEC
+#define TFD_NONBLOCK O_NONBLOCK
#endif /* _LINUX_TIMERFD_H */
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 4e5833073aa..e3579cb086e 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -317,8 +317,6 @@ extern void tty_wait_until_sent(struct tty_struct *tty, long timeout);
extern int tty_check_change(struct tty_struct *tty);
extern void stop_tty(struct tty_struct *tty);
extern void start_tty(struct tty_struct *tty);
-extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
-extern int tty_unregister_ldisc(int disc);
extern int tty_register_driver(struct tty_driver *driver);
extern int tty_unregister_driver(struct tty_driver *driver);
extern struct device *tty_register_device(struct tty_driver *driver,
@@ -383,6 +381,15 @@ extern void tty_port_init(struct tty_port *port);
extern int tty_port_alloc_xmit_buf(struct tty_port *port);
extern void tty_port_free_xmit_buf(struct tty_port *port);
+extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
+extern int tty_unregister_ldisc(int disc);
+extern int tty_set_ldisc(struct tty_struct *tty, int ldisc);
+extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty);
+extern void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty);
+extern void tty_ldisc_init(struct tty_struct *tty);
+extern void tty_ldisc_begin(void);
+/* This last one is just for the tty layer internals and shouldn't be used elsewhere */
+extern void tty_ldisc_enable(struct tty_struct *tty);
/* n_tty.c */
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index d2a00358676..e1065ac0d92 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -135,7 +135,7 @@
*
* Optional:
*
- * void (*break_ctl)(struct tty_stuct *tty, int state);
+ * int (*break_ctl)(struct tty_stuct *tty, int state);
*
* This optional routine requests the tty driver to turn on or
* off BREAK status on the RS-232 port. If state is -1,
@@ -146,6 +146,10 @@
* handle the following ioctls: TCSBRK, TCSBRKP, TIOCSBRK,
* TIOCCBRK.
*
+ * If the driver sets TTY_DRIVER_HARDWARE_BREAK then the interface
+ * will also be called with actual times and the hardware is expected
+ * to do the delay work itself. 0 and -1 are still used for on/off.
+ *
* Optional: Required for TCSBRK/BRKP/etc handling.
*
* void (*wait_until_sent)(struct tty_struct *tty, int timeout);
@@ -192,7 +196,7 @@ struct tty_operations {
void (*stop)(struct tty_struct *tty);
void (*start)(struct tty_struct *tty);
void (*hangup)(struct tty_struct *tty);
- void (*break_ctl)(struct tty_struct *tty, int state);
+ int (*break_ctl)(struct tty_struct *tty, int state);
void (*flush_buffer)(struct tty_struct *tty);
void (*set_ldisc)(struct tty_struct *tty);
void (*wait_until_sent)(struct tty_struct *tty, int timeout);
@@ -285,12 +289,18 @@ extern struct tty_driver *tty_find_polling_driver(char *name, int *line);
* TTY_DRIVER_DEVPTS_MEM -- don't use the standard arrays, instead
* use dynamic memory keyed through the devpts filesystem. This
* is only applicable to the pty driver.
+ *
+ * TTY_DRIVER_HARDWARE_BREAK -- hardware handles break signals. Pass
+ * the requested timeout to the caller instead of using a simple
+ * on/off interface.
+ *
*/
#define TTY_DRIVER_INSTALLED 0x0001
#define TTY_DRIVER_RESET_TERMIOS 0x0002
#define TTY_DRIVER_REAL_RAW 0x0004
#define TTY_DRIVER_DYNAMIC_DEV 0x0008
#define TTY_DRIVER_DEVPTS_MEM 0x0010
+#define TTY_DRIVER_HARDWARE_BREAK 0x0020
/* tty driver types */
#define TTY_DRIVER_TYPE_SYSTEM 0x0001
diff --git a/include/linux/typecheck.h b/include/linux/typecheck.h
new file mode 100644
index 00000000000..eb5b74a575b
--- /dev/null
+++ b/include/linux/typecheck.h
@@ -0,0 +1,24 @@
+#ifndef TYPECHECK_H_INCLUDED
+#define TYPECHECK_H_INCLUDED
+
+/*
+ * Check at compile time that something is of a particular type.
+ * Always evaluates to 1 so you may use it easily in comparisons.
+ */
+#define typecheck(type,x) \
+({ type __dummy; \
+ typeof(x) __dummy2; \
+ (void)(&__dummy == &__dummy2); \
+ 1; \
+})
+
+/*
+ * Check at compile time that 'function' is a certain type, or is a pointer
+ * to that type (needs to use typedef for the function type.)
+ */
+#define typecheck_fn(type,function) \
+({ typeof(type) __tmp = function; \
+ (void)__tmp; \
+})
+
+#endif /* TYPECHECK_H_INCLUDED */
diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h
index 973386d439d..cdf338d94b7 100644
--- a/include/linux/uio_driver.h
+++ b/include/linux/uio_driver.h
@@ -36,7 +36,7 @@ struct uio_mem {
struct uio_map *map;
};
-#define MAX_UIO_MAPS 5
+#define MAX_UIO_MAPS 5
struct uio_device;
@@ -53,6 +53,7 @@ struct uio_device;
* @mmap: mmap operation for this uio device
* @open: open operation for this uio device
* @release: release operation for this uio device
+ * @irqcontrol: disable/enable irqs when 0/1 is written to /dev/uioX
*/
struct uio_info {
struct uio_device *uio_dev;
@@ -66,6 +67,7 @@ struct uio_info {
int (*mmap)(struct uio_info *info, struct vm_area_struct *vma);
int (*open)(struct uio_info *info, struct inode *inode);
int (*release)(struct uio_info *info, struct inode *inode);
+ int (*irqcontrol)(struct uio_info *info, s32 irq_on);
};
extern int __must_check
@@ -80,11 +82,11 @@ static inline int __must_check
extern void uio_unregister_device(struct uio_info *info);
extern void uio_event_notify(struct uio_info *info);
-/* defines for uio_device->irq */
+/* defines for uio_info->irq */
#define UIO_IRQ_CUSTOM -1
#define UIO_IRQ_NONE -2
-/* defines for uio_device->memtype */
+/* defines for uio_mem->memtype */
#define UIO_MEM_NONE 0
#define UIO_MEM_PHYS 1
#define UIO_MEM_LOGICAL 2
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 747c3a49cdc..c932390c6da 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -330,7 +330,7 @@ extern int usb_string_id(struct usb_composite_dev *c);
dev_vdbg(&(d)->gadget->dev , fmt , ## args)
#define ERROR(d, fmt, args...) \
dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARN(d, fmt, args...) \
+#define WARNING(d, fmt, args...) \
dev_warn(&(d)->gadget->dev , fmt , ## args)
#define INFO(d, fmt, args...) \
dev_info(&(d)->gadget->dev , fmt , ## args)
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 8f891cbaf9a..09a3e6a7518 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -62,7 +62,7 @@
*/
struct usb_serial_port {
struct usb_serial *serial;
- struct tty_struct *tty;
+ struct tty_port port;
spinlock_t lock;
struct mutex mutex;
unsigned char number;
@@ -89,7 +89,6 @@ struct usb_serial_port {
wait_queue_head_t write_wait;
struct work_struct work;
- int open_count;
char throttled;
char throttle_req;
char console;
@@ -217,22 +216,27 @@ struct usb_serial_driver {
int (*resume)(struct usb_serial *serial);
/* serial function calls */
- int (*open)(struct usb_serial_port *port, struct file *filp);
- void (*close)(struct usb_serial_port *port, struct file *filp);
- int (*write)(struct usb_serial_port *port, const unsigned char *buf,
- int count);
- int (*write_room)(struct usb_serial_port *port);
- int (*ioctl)(struct usb_serial_port *port, struct file *file,
+ /* Called by console with tty = NULL and by tty */
+ int (*open)(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+ void (*close)(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+ int (*write)(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+ /* Called only by the tty layer */
+ int (*write_room)(struct tty_struct *tty);
+ int (*ioctl)(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
- void (*set_termios)(struct usb_serial_port *port, struct ktermios *old);
- void (*break_ctl)(struct usb_serial_port *port, int break_state);
- int (*chars_in_buffer)(struct usb_serial_port *port);
- void (*throttle)(struct usb_serial_port *port);
- void (*unthrottle)(struct usb_serial_port *port);
- int (*tiocmget)(struct usb_serial_port *port, struct file *file);
- int (*tiocmset)(struct usb_serial_port *port, struct file *file,
+ void (*set_termios)(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
+ void (*break_ctl)(struct tty_struct *tty, int break_state);
+ int (*chars_in_buffer)(struct tty_struct *tty);
+ void (*throttle)(struct tty_struct *tty);
+ void (*unthrottle)(struct tty_struct *tty);
+ int (*tiocmget)(struct tty_struct *tty, struct file *file);
+ int (*tiocmset)(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
-
+ /* USB events */
void (*read_int_callback)(struct urb *urb);
void (*write_int_callback)(struct urb *urb);
void (*read_bulk_callback)(struct urb *urb);
@@ -270,19 +274,19 @@ static inline void usb_serial_console_disconnect(struct usb_serial *serial) {}
/* Functions needed by other parts of the usbserial core */
extern struct usb_serial *usb_serial_get_by_index(unsigned int minor);
extern void usb_serial_put(struct usb_serial *serial);
-extern int usb_serial_generic_open(struct usb_serial_port *port,
- struct file *filp);
-extern int usb_serial_generic_write(struct usb_serial_port *port,
- const unsigned char *buf, int count);
-extern void usb_serial_generic_close(struct usb_serial_port *port,
- struct file *filp);
+extern int usb_serial_generic_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+extern int usb_serial_generic_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count);
+extern void usb_serial_generic_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
extern int usb_serial_generic_resume(struct usb_serial *serial);
-extern int usb_serial_generic_write_room(struct usb_serial_port *port);
-extern int usb_serial_generic_chars_in_buffer(struct usb_serial_port *port);
+extern int usb_serial_generic_write_room(struct tty_struct *tty);
+extern int usb_serial_generic_chars_in_buffer(struct tty_struct *tty);
extern void usb_serial_generic_read_bulk_callback(struct urb *urb);
extern void usb_serial_generic_write_bulk_callback(struct urb *urb);
-extern void usb_serial_generic_throttle(struct usb_serial_port *port);
-extern void usb_serial_generic_unthrottle(struct usb_serial_port *port);
+extern void usb_serial_generic_throttle(struct tty_struct *tty);
+extern void usb_serial_generic_unthrottle(struct tty_struct *tty);
extern void usb_serial_generic_shutdown(struct usb_serial *serial);
extern int usb_serial_generic_register(int debug);
extern void usb_serial_generic_deregister(void);
diff --git a/include/linux/virtio_9p.h b/include/linux/virtio_9p.h
index 8eff0b53910..b3c4a60ceeb 100644
--- a/include/linux/virtio_9p.h
+++ b/include/linux/virtio_9p.h
@@ -1,5 +1,7 @@
#ifndef _LINUX_VIRTIO_9P_H
#define _LINUX_VIRTIO_9P_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers. */
#include <linux/virtio_config.h>
/* The ID for virtio console */
diff --git a/include/linux/virtio_balloon.h b/include/linux/virtio_balloon.h
index 979524ee75b..c30c7bfbf39 100644
--- a/include/linux/virtio_balloon.h
+++ b/include/linux/virtio_balloon.h
@@ -1,5 +1,7 @@
#ifndef _LINUX_VIRTIO_BALLOON_H
#define _LINUX_VIRTIO_BALLOON_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers. */
#include <linux/virtio_config.h>
/* The ID for virtio_balloon */
diff --git a/include/linux/virtio_blk.h b/include/linux/virtio_blk.h
index 5f79a5f9de7..c1aef85243b 100644
--- a/include/linux/virtio_blk.h
+++ b/include/linux/virtio_blk.h
@@ -1,5 +1,7 @@
#ifndef _LINUX_VIRTIO_BLK_H
#define _LINUX_VIRTIO_BLK_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers. */
#include <linux/virtio_config.h>
/* The ID for virtio_block */
@@ -11,6 +13,7 @@
#define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */
#define VIRTIO_BLK_F_GEOMETRY 4 /* Legacy geometry available */
#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */
+#define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/
struct virtio_blk_config
{
@@ -26,6 +29,8 @@ struct virtio_blk_config
__u8 heads;
__u8 sectors;
} geometry;
+ /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */
+ __u32 blk_size;
} __attribute__((packed));
/* These two define direction. */
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index f364bbf63c3..bf8ec283b23 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -1,5 +1,8 @@
#ifndef _LINUX_VIRTIO_CONFIG_H
#define _LINUX_VIRTIO_CONFIG_H
+/* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so
+ * anyone can use the definitions to implement compatible drivers/servers. */
+
/* Virtio devices use a standardized configuration space to define their
* features and pass configuration information, but each implementation can
* store and access that space differently. */
@@ -15,6 +18,12 @@
/* We've given up on this device. */
#define VIRTIO_CONFIG_S_FAILED 0x80
+/* Some virtio feature bits (currently bits 28 through 31) are reserved for the
+ * transport being used (eg. virtio_ring), the rest are per-device feature
+ * bits. */
+#define VIRTIO_TRANSPORT_F_START 28
+#define VIRTIO_TRANSPORT_F_END 32
+
/* Do we get callbacks when the ring is completely used, even if we've
* suppressed them? */
#define VIRTIO_F_NOTIFY_ON_EMPTY 24
@@ -52,9 +61,10 @@
* @get_features: get the array of feature bits for this device.
* vdev: the virtio_device
* Returns the first 32 feature bits (all we currently need).
- * @set_features: confirm what device features we'll be using.
+ * @finalize_features: confirm what device features we'll be using.
* vdev: the virtio_device
- * feature: the first 32 feature bits
+ * This gives the final feature bits for the device: it can change
+ * the dev->feature bits if it wants.
*/
struct virtio_config_ops
{
@@ -70,7 +80,7 @@ struct virtio_config_ops
void (*callback)(struct virtqueue *));
void (*del_vq)(struct virtqueue *vq);
u32 (*get_features)(struct virtio_device *vdev);
- void (*set_features)(struct virtio_device *vdev, u32 features);
+ void (*finalize_features)(struct virtio_device *vdev);
};
/* If driver didn't advertise the feature, it will never appear. */
diff --git a/include/linux/virtio_console.h b/include/linux/virtio_console.h
index ed2d4ead7eb..19a0da0dba4 100644
--- a/include/linux/virtio_console.h
+++ b/include/linux/virtio_console.h
@@ -1,6 +1,8 @@
#ifndef _LINUX_VIRTIO_CONSOLE_H
#define _LINUX_VIRTIO_CONSOLE_H
#include <linux/virtio_config.h>
+/* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so
+ * anyone can use the definitions to implement compatible drivers/servers. */
/* The ID for virtio console */
#define VIRTIO_ID_CONSOLE 3
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index 38c0571820f..5e33761b9b8 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -1,5 +1,7 @@
#ifndef _LINUX_VIRTIO_NET_H
#define _LINUX_VIRTIO_NET_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers. */
#include <linux/virtio_config.h>
/* The ID for virtio_net */
diff --git a/include/linux/virtio_pci.h b/include/linux/virtio_pci.h
index b3151659cf4..cdef3574293 100644
--- a/include/linux/virtio_pci.h
+++ b/include/linux/virtio_pci.h
@@ -9,9 +9,8 @@
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
*/
#ifndef _LINUX_VIRTIO_PCI_H
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h
index abe481ed990..c4a598fb382 100644
--- a/include/linux/virtio_ring.h
+++ b/include/linux/virtio_ring.h
@@ -120,6 +120,8 @@ struct virtqueue *vring_new_virtqueue(unsigned int num,
void (*notify)(struct virtqueue *vq),
void (*callback)(struct virtqueue *vq));
void vring_del_virtqueue(struct virtqueue *vq);
+/* Filter out transport-specific feature bits. */
+void vring_transport_features(struct virtio_device *vdev);
irqreturn_t vring_interrupt(int irq, void *_vq);
#endif /* __KERNEL__ */
diff --git a/include/linux/virtio_rng.h b/include/linux/virtio_rng.h
index 331afb6c9f6..1a85dab8a94 100644
--- a/include/linux/virtio_rng.h
+++ b/include/linux/virtio_rng.h
@@ -1,5 +1,7 @@
#ifndef _LINUX_VIRTIO_RNG_H
#define _LINUX_VIRTIO_RNG_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers. */
#include <linux/virtio_config.h>
/* The ID for virtio_rng */
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index e83b69346d2..58334d43951 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -44,6 +44,12 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
NR_VM_EVENT_ITEMS
};
+extern const struct seq_operations fragmentation_op;
+extern const struct seq_operations pagetypeinfo_op;
+extern const struct seq_operations zoneinfo_op;
+extern const struct seq_operations vmstat_op;
+extern int sysctl_stat_interval;
+
#ifdef CONFIG_VM_EVENT_COUNTERS
/*
* Light weight per cpu counter implementation.
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index 9448ffbdcbf..14c0e91be9b 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -12,6 +12,7 @@
#include <linux/mutex.h>
#include <linux/console_struct.h>
#include <linux/mm.h>
+#include <linux/consolemap.h>
/*
* Presently, a lot of graphics programs do not restore the contents of
@@ -54,6 +55,7 @@ void redraw_screen(struct vc_data *vc, int is_switch);
struct tty_struct;
int tioclinux(struct tty_struct *tty, unsigned long arg);
+#ifdef CONFIG_CONSOLE_TRANSLATIONS
/* consolemap.c */
struct unimapinit;
@@ -71,6 +73,23 @@ void con_free_unimap(struct vc_data *vc);
void con_protect_unimap(struct vc_data *vc, int rdonly);
int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);
+#define vc_translate(vc, c) ((vc)->vc_translate[(c) | \
+ (vc)->vc_toggle_meta ? 0x80 : 0])
+#else
+#define con_set_trans_old(arg) (0)
+#define con_get_trans_old(arg) (-EINVAL)
+#define con_set_trans_new(arg) (0)
+#define con_get_trans_new(arg) (-EINVAL)
+#define con_clear_unimap(vc, ui) (0)
+#define con_set_unimap(vc, ct, list) (0)
+#define con_set_default_unimap(vc) (0)
+#define con_copy_unimap(d, s) (0)
+#define con_get_unimap(vc, ct, uct, list) (-EINVAL)
+#define con_free_unimap(vc) do { ; } while (0)
+
+#define vc_translate(vc, c) (c)
+#endif
+
/* vt.c */
int vt_waitactive(int vt);
void change_console(struct vc_data *new_vc);
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 542526c6e8e..5c158c477ac 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -179,6 +179,8 @@ __create_workqueue_key(const char *name, int singlethread,
extern void destroy_workqueue(struct workqueue_struct *wq);
extern int queue_work(struct workqueue_struct *wq, struct work_struct *work);
+extern int queue_work_on(int cpu, struct workqueue_struct *wq,
+ struct work_struct *work);
extern int queue_delayed_work(struct workqueue_struct *wq,
struct delayed_work *work, unsigned long delay);
extern int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
@@ -188,6 +190,7 @@ extern void flush_workqueue(struct workqueue_struct *wq);
extern void flush_scheduled_work(void);
extern int schedule_work(struct work_struct *work);
+extern int schedule_work_on(int cpu, struct work_struct *work);
extern int schedule_delayed_work(struct delayed_work *work, unsigned long delay);
extern int schedule_delayed_work_on(int cpu, struct delayed_work *work,
unsigned long delay);
@@ -198,6 +201,8 @@ extern int keventd_up(void);
extern void init_workqueues(void);
int execute_in_process_context(work_func_t fn, struct execute_work *);
+extern int flush_work(struct work_struct *work);
+
extern int cancel_work_sync(struct work_struct *work);
/*
diff --git a/include/mtd/ubi-user.h b/include/mtd/ubi-user.h
index a7421f130cc..ccdc562e444 100644
--- a/include/mtd/ubi-user.h
+++ b/include/mtd/ubi-user.h
@@ -58,6 +58,13 @@
* device should be used. A &struct ubi_rsvol_req object has to be properly
* filled and a pointer to it has to be passed to the IOCTL.
*
+ * UBI volumes re-name
+ * ~~~~~~~~~~~~~~~~~~~
+ *
+ * To re-name several volumes atomically at one go, the %UBI_IOCRNVOL command
+ * of the UBI character device should be used. A &struct ubi_rnvol_req object
+ * has to be properly filled and a pointer to it has to be passed to the IOCTL.
+ *
* UBI volume update
* ~~~~~~~~~~~~~~~~~
*
@@ -104,6 +111,8 @@
#define UBI_IOCRMVOL _IOW(UBI_IOC_MAGIC, 1, int32_t)
/* Re-size an UBI volume */
#define UBI_IOCRSVOL _IOW(UBI_IOC_MAGIC, 2, struct ubi_rsvol_req)
+/* Re-name volumes */
+#define UBI_IOCRNVOL _IOW(UBI_IOC_MAGIC, 3, struct ubi_rnvol_req)
/* IOCTL commands of the UBI control character device */
@@ -128,6 +137,9 @@
/* Maximum MTD device name length supported by UBI */
#define MAX_UBI_MTD_NAME_LEN 127
+/* Maximum amount of UBI volumes that can be re-named at one go */
+#define UBI_MAX_RNVOL 32
+
/*
* UBI data type hint constants.
*
@@ -176,20 +188,20 @@ enum {
* it will be 512 in case of a 2KiB page NAND flash with 4 512-byte sub-pages.
*
* But in rare cases, if this optimizes things, the VID header may be placed to
- * a different offset. For example, the boot-loader might do things faster if the
- * VID header sits at the end of the first 2KiB NAND page with 4 sub-pages. As
- * the boot-loader would not normally need to read EC headers (unless it needs
- * UBI in RW mode), it might be faster to calculate ECC. This is weird example,
- * but it real-life example. So, in this example, @vid_hdr_offer would be
- * 2KiB-64 bytes = 1984. Note, that this position is not even 512-bytes
- * aligned, which is OK, as UBI is clever enough to realize this is 4th sub-page
- * of the first page and add needed padding.
+ * a different offset. For example, the boot-loader might do things faster if
+ * the VID header sits at the end of the first 2KiB NAND page with 4 sub-pages.
+ * As the boot-loader would not normally need to read EC headers (unless it
+ * needs UBI in RW mode), it might be faster to calculate ECC. This is weird
+ * example, but it real-life example. So, in this example, @vid_hdr_offer would
+ * be 2KiB-64 bytes = 1984. Note, that this position is not even 512-bytes
+ * aligned, which is OK, as UBI is clever enough to realize this is 4th
+ * sub-page of the first page and add needed padding.
*/
struct ubi_attach_req {
int32_t ubi_num;
int32_t mtd_num;
int32_t vid_hdr_offset;
- uint8_t padding[12];
+ int8_t padding[12];
};
/**
@@ -251,6 +263,48 @@ struct ubi_rsvol_req {
} __attribute__ ((packed));
/**
+ * struct ubi_rnvol_req - volumes re-name request.
+ * @count: count of volumes to re-name
+ * @padding1: reserved for future, not used, has to be zeroed
+ * @vol_id: ID of the volume to re-name
+ * @name_len: name length
+ * @padding2: reserved for future, not used, has to be zeroed
+ * @name: new volume name
+ *
+ * UBI allows to re-name up to %32 volumes at one go. The count of volumes to
+ * re-name is specified in the @count field. The ID of the volumes to re-name
+ * and the new names are specified in the @vol_id and @name fields.
+ *
+ * The UBI volume re-name operation is atomic, which means that should power cut
+ * happen, the volumes will have either old name or new name. So the possible
+ * use-cases of this command is atomic upgrade. Indeed, to upgrade, say, volumes
+ * A and B one may create temporary volumes %A1 and %B1 with the new contents,
+ * then atomically re-name A1->A and B1->B, in which case old %A and %B will
+ * be removed.
+ *
+ * If it is not desirable to remove old A and B, the re-name request has to
+ * contain 4 entries: A1->A, A->A1, B1->B, B->B1, in which case old A1 and B1
+ * become A and B, and old A and B will become A1 and B1.
+ *
+ * It is also OK to request: A1->A, A1->X, B1->B, B->Y, in which case old A1
+ * and B1 become A and B, and old A and B become X and Y.
+ *
+ * In other words, in case of re-naming into an existing volume name, the
+ * existing volume is removed, unless it is re-named as well at the same
+ * re-name request.
+ */
+struct ubi_rnvol_req {
+ int32_t count;
+ int8_t padding1[12];
+ struct {
+ int32_t vol_id;
+ int16_t name_len;
+ int8_t padding2[2];
+ char name[UBI_MAX_VOLUME_NAME + 1];
+ } ents[UBI_MAX_RNVOL];
+} __attribute__ ((packed));
+
+/**
* struct ubi_leb_change_req - a data structure used in atomic logical
* eraseblock change requests.
* @lnum: logical eraseblock number to change
@@ -261,8 +315,8 @@ struct ubi_rsvol_req {
struct ubi_leb_change_req {
int32_t lnum;
int32_t bytes;
- uint8_t dtype;
- uint8_t padding[7];
+ int8_t dtype;
+ int8_t padding[7];
} __attribute__ ((packed));
#endif /* __UBI_USER_H__ */
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
index dfd8bf66ce2..d364fd594ea 100644
--- a/include/net/ieee80211_radiotap.h
+++ b/include/net/ieee80211_radiotap.h
@@ -262,7 +262,7 @@ static inline int ieee80211_get_radiotap_len(unsigned char *data)
struct ieee80211_radiotap_header *hdr =
(struct ieee80211_radiotap_header *)data;
- return le16_to_cpu(get_unaligned(&hdr->it_len));
+ return get_unaligned_le16(&hdr->it_len);
}
#endif /* IEEE80211_RADIOTAP_H */
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index db66c792774..c8effa4b1fe 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -193,8 +193,6 @@ struct inet6_dev
struct rcu_head rcu;
};
-extern struct ipv6_devconf ipv6_devconf;
-
static inline void ipv6_eth_mc_map(struct in6_addr *addr, char *buf)
{
/*
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 9313491e3da..2f8b3c06a10 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -68,7 +68,7 @@ extern struct rt6_info *rt6_lookup(struct net *net,
extern struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
struct neighbour *neigh,
const struct in6_addr *addr);
-extern int icmp6_dst_gc(int *more);
+extern int icmp6_dst_gc(void);
extern void fib6_force_start_gc(struct net *net);
diff --git a/include/net/ipcomp.h b/include/net/ipcomp.h
index 330b74e813a..2a1092abaa0 100644
--- a/include/net/ipcomp.h
+++ b/include/net/ipcomp.h
@@ -14,6 +14,12 @@ struct ipcomp_data {
struct ip_comp_hdr;
struct sk_buff;
+struct xfrm_state;
+
+int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb);
+int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb);
+void ipcomp_destroy(struct xfrm_state *x);
+int ipcomp_init_state(struct xfrm_state *x);
static inline struct ip_comp_hdr *ip_comp_hdr(const struct sk_buff *skb)
{
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 5bacd838e88..2932721180c 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -39,7 +39,7 @@ struct netns_ipv6 {
#endif
struct rt6_info *ip6_null_entry;
struct rt6_statistics *rt6_stats;
- struct timer_list *ip6_fib_timer;
+ struct timer_list ip6_fib_timer;
struct hlist_head *fib_table_hash;
struct fib6_table *fib6_main_tbl;
struct dst_ops *ip6_dst_ops;
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 70eb64a7e1a..535a18f57a1 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1161,7 +1161,6 @@ void sctp_outq_init(struct sctp_association *, struct sctp_outq *);
void sctp_outq_teardown(struct sctp_outq *);
void sctp_outq_free(struct sctp_outq*);
int sctp_outq_tail(struct sctp_outq *, struct sctp_chunk *chunk);
-int sctp_outq_flush(struct sctp_outq *, int);
int sctp_outq_sack(struct sctp_outq *, struct sctp_sackhdr *);
int sctp_outq_is_empty(const struct sctp_outq *);
void sctp_outq_restart(struct sctp_outq *);
diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h
index 22bb2e7bab1..df7faf09d66 100644
--- a/include/rdma/rdma_cm.h
+++ b/include/rdma/rdma_cm.h
@@ -57,7 +57,9 @@ enum rdma_cm_event_type {
RDMA_CM_EVENT_DISCONNECTED,
RDMA_CM_EVENT_DEVICE_REMOVAL,
RDMA_CM_EVENT_MULTICAST_JOIN,
- RDMA_CM_EVENT_MULTICAST_ERROR
+ RDMA_CM_EVENT_MULTICAST_ERROR,
+ RDMA_CM_EVENT_ADDR_CHANGE,
+ RDMA_CM_EVENT_TIMEWAIT_EXIT
};
enum rdma_port_space {
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 1834fdfe82a..a594bac4a77 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -623,7 +623,7 @@ struct Scsi_Host {
/*
* Optional work queue to be utilized by the transport
*/
- char work_q_name[KOBJ_NAME_LEN];
+ char work_q_name[20];
struct workqueue_struct *work_q;
/*
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 06f72bab9df..878373c32ef 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -489,9 +489,9 @@ struct fc_host_attrs {
u16 npiv_vports_inuse;
/* work queues for rport state manipulation */
- char work_q_name[KOBJ_NAME_LEN];
+ char work_q_name[20];
struct workqueue_struct *work_q;
- char devloss_work_q_name[KOBJ_NAME_LEN];
+ char devloss_work_q_name[20];
struct workqueue_struct *devloss_work_q;
};
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index f5444e033cc..8b6c91df4c7 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -198,7 +198,7 @@ struct iscsi_cls_host {
atomic_t nr_scans;
struct mutex mutex;
struct workqueue_struct *scan_workq;
- char scan_workq_name[KOBJ_NAME_LEN];
+ char scan_workq_name[20];
};
extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h
index ed64862c4e1..1ccf462b433 100644
--- a/include/video/atmel_lcdc.h
+++ b/include/video/atmel_lcdc.h
@@ -37,6 +37,7 @@ struct atmel_lcdfb_info {
struct fb_info *info;
void __iomem *mmio;
unsigned long irq_base;
+ struct work_struct task;
unsigned int guard_time;
struct platform_device *pdev;
diff --git a/include/video/ili9320.h b/include/video/ili9320.h
new file mode 100644
index 00000000000..e5d1622e3f3
--- /dev/null
+++ b/include/video/ili9320.h
@@ -0,0 +1,201 @@
+/* include/video/ili9320.c
+ *
+ * ILI9320 LCD controller configuration control.
+ *
+ * Copyright 2007 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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.
+*/
+
+#define ILI9320_REG(x) (x)
+
+#define ILI9320_INDEX ILI9320_REG(0x00)
+
+#define ILI9320_OSCILATION ILI9320_REG(0x00)
+#define ILI9320_DRIVER ILI9320_REG(0x01)
+#define ILI9320_DRIVEWAVE ILI9320_REG(0x02)
+#define ILI9320_ENTRYMODE ILI9320_REG(0x03)
+#define ILI9320_RESIZING ILI9320_REG(0x04)
+#define ILI9320_DISPLAY1 ILI9320_REG(0x07)
+#define ILI9320_DISPLAY2 ILI9320_REG(0x08)
+#define ILI9320_DISPLAY3 ILI9320_REG(0x09)
+#define ILI9320_DISPLAY4 ILI9320_REG(0x0A)
+#define ILI9320_RGB_IF1 ILI9320_REG(0x0C)
+#define ILI9320_FRAMEMAKER ILI9320_REG(0x0D)
+#define ILI9320_RGB_IF2 ILI9320_REG(0x0F)
+
+#define ILI9320_POWER1 ILI9320_REG(0x10)
+#define ILI9320_POWER2 ILI9320_REG(0x11)
+#define ILI9320_POWER3 ILI9320_REG(0x12)
+#define ILI9320_POWER4 ILI9320_REG(0x13)
+#define ILI9320_GRAM_HORIZ_ADDR ILI9320_REG(0x20)
+#define ILI9320_GRAM_VERT_ADD ILI9320_REG(0x21)
+#define ILI9320_POWER7 ILI9320_REG(0x29)
+#define ILI9320_FRAME_RATE_COLOUR ILI9320_REG(0x2B)
+
+#define ILI9320_GAMMA1 ILI9320_REG(0x30)
+#define ILI9320_GAMMA2 ILI9320_REG(0x31)
+#define ILI9320_GAMMA3 ILI9320_REG(0x32)
+#define ILI9320_GAMMA4 ILI9320_REG(0x35)
+#define ILI9320_GAMMA5 ILI9320_REG(0x36)
+#define ILI9320_GAMMA6 ILI9320_REG(0x37)
+#define ILI9320_GAMMA7 ILI9320_REG(0x38)
+#define ILI9320_GAMMA8 ILI9320_REG(0x39)
+#define ILI9320_GAMMA9 ILI9320_REG(0x3C)
+#define ILI9320_GAMMA10 ILI9320_REG(0x3D)
+
+#define ILI9320_HORIZ_START ILI9320_REG(0x50)
+#define ILI9320_HORIZ_END ILI9320_REG(0x51)
+#define ILI9320_VERT_START ILI9320_REG(0x52)
+#define ILI9320_VERT_END ILI9320_REG(0x53)
+
+#define ILI9320_DRIVER2 ILI9320_REG(0x60)
+#define ILI9320_BASE_IMAGE ILI9320_REG(0x61)
+#define ILI9320_VERT_SCROLL ILI9320_REG(0x6a)
+
+#define ILI9320_PARTIAL1_POSITION ILI9320_REG(0x80)
+#define ILI9320_PARTIAL1_START ILI9320_REG(0x81)
+#define ILI9320_PARTIAL1_END ILI9320_REG(0x82)
+#define ILI9320_PARTIAL2_POSITION ILI9320_REG(0x83)
+#define ILI9320_PARTIAL2_START ILI9320_REG(0x84)
+#define ILI9320_PARTIAL2_END ILI9320_REG(0x85)
+
+#define ILI9320_INTERFACE1 ILI9320_REG(0x90)
+#define ILI9320_INTERFACE2 ILI9320_REG(0x92)
+#define ILI9320_INTERFACE3 ILI9320_REG(0x93)
+#define ILI9320_INTERFACE4 ILI9320_REG(0x95)
+#define ILI9320_INTERFACE5 ILI9320_REG(0x97)
+#define ILI9320_INTERFACE6 ILI9320_REG(0x98)
+
+/* Register contents definitions. */
+
+#define ILI9320_OSCILATION_OSC (1 << 0)
+
+#define ILI9320_DRIVER_SS (1 << 8)
+#define ILI9320_DRIVER_SM (1 << 10)
+
+#define ILI9320_DRIVEWAVE_EOR (1 << 8)
+#define ILI9320_DRIVEWAVE_BC (1 << 9)
+#define ILI9320_DRIVEWAVE_MUSTSET (1 << 10)
+
+#define ILI9320_ENTRYMODE_AM (1 << 3)
+#define ILI9320_ENTRYMODE_ID(x) ((x) << 4)
+#define ILI9320_ENTRYMODE_ORG (1 << 7)
+#define ILI9320_ENTRYMODE_HWM (1 << 8)
+#define ILI9320_ENTRYMODE_BGR (1 << 12)
+#define ILI9320_ENTRYMODE_DFM (1 << 14)
+#define ILI9320_ENTRYMODE_TRI (1 << 15)
+
+
+#define ILI9320_RESIZING_RSZ(x) ((x) << 0)
+#define ILI9320_RESIZING_RCH(x) ((x) << 4)
+#define ILI9320_RESIZING_RCV(x) ((x) << 8)
+
+
+#define ILI9320_DISPLAY1_D(x) ((x) << 0)
+#define ILI9320_DISPLAY1_CL (1 << 3)
+#define ILI9320_DISPLAY1_DTE (1 << 4)
+#define ILI9320_DISPLAY1_GON (1 << 5)
+#define ILI9320_DISPLAY1_BASEE (1 << 8)
+#define ILI9320_DISPLAY1_PTDE(x) ((x) << 12)
+
+
+#define ILI9320_DISPLAY2_BP(x) ((x) << 0)
+#define ILI9320_DISPLAY2_FP(x) ((x) << 8)
+
+
+#define ILI9320_RGBIF1_RIM_RGB18 (0 << 0)
+#define ILI9320_RGBIF1_RIM_RGB16 (1 << 0)
+#define ILI9320_RGBIF1_RIM_RGB6 (2 << 0)
+
+#define ILI9320_RGBIF1_CLK_INT (0 << 4)
+#define ILI9320_RGBIF1_CLK_RGBIF (1 << 4)
+#define ILI9320_RGBIF1_CLK_VSYNC (2 << 4)
+
+#define ILI9320_RGBIF1_RM (1 << 8)
+
+#define ILI9320_RGBIF1_ENC_FRAMES(x) (((x) - 1)<< 13)
+
+#define ILI9320_RGBIF2_DPL (1 << 0)
+#define ILI9320_RGBIF2_EPL (1 << 1)
+#define ILI9320_RGBIF2_HSPL (1 << 3)
+#define ILI9320_RGBIF2_VSPL (1 << 4)
+
+
+#define ILI9320_POWER1_SLP (1 << 1)
+#define ILI9320_POWER1_DSTB (1 << 2)
+#define ILI9320_POWER1_AP(x) ((x) << 4)
+#define ILI9320_POWER1_APE (1 << 7)
+#define ILI9320_POWER1_BT(x) ((x) << 8)
+#define ILI9320_POWER1_SAP (1 << 12)
+
+
+#define ILI9320_POWER2_VC(x) ((x) << 0)
+#define ILI9320_POWER2_DC0(x) ((x) << 4)
+#define ILI9320_POWER2_DC1(x) ((x) << 8)
+
+
+#define ILI9320_POWER3_VRH(x) ((x) << 0)
+#define ILI9320_POWER3_PON (1 << 4)
+#define ILI9320_POWER3_VCMR (1 << 8)
+
+
+#define ILI9320_POWER4_VREOUT(x) ((x) << 8)
+
+
+#define ILI9320_DRIVER2_SCNL(x) ((x) << 0)
+#define ILI9320_DRIVER2_NL(x) ((x) << 8)
+#define ILI9320_DRIVER2_GS (1 << 15)
+
+
+#define ILI9320_BASEIMAGE_REV (1 << 0)
+#define ILI9320_BASEIMAGE_VLE (1 << 1)
+#define ILI9320_BASEIMAGE_NDL (1 << 2)
+
+
+#define ILI9320_INTERFACE4_RTNE(x) (x)
+#define ILI9320_INTERFACE4_DIVE(x) ((x) << 8)
+
+/* SPI interface definitions */
+
+#define ILI9320_SPI_IDCODE (0x70)
+#define ILI9320_SPI_ID(x) ((x) << 2)
+#define ILI9320_SPI_READ (0x01)
+#define ILI9320_SPI_WRITE (0x00)
+#define ILI9320_SPI_DATA (0x02)
+#define ILI9320_SPI_INDEX (0x00)
+
+/* platform data to pass configuration from lcd */
+
+enum ili9320_suspend {
+ ILI9320_SUSPEND_OFF,
+ ILI9320_SUSPEND_DEEP,
+};
+
+struct ili9320_platdata {
+ unsigned short hsize;
+ unsigned short vsize;
+
+ enum ili9320_suspend suspend;
+
+ /* set the reset line, 0 = reset asserted, 1 = normal */
+ void (*reset)(unsigned int val);
+
+ unsigned short entry_mode;
+ unsigned short display2;
+ unsigned short display3;
+ unsigned short display4;
+ unsigned short rgb_if1;
+ unsigned short rgb_if2;
+ unsigned short interface2;
+ unsigned short interface3;
+ unsigned short interface4;
+ unsigned short interface5;
+ unsigned short interface6;
+};
+
diff --git a/include/video/neomagic.h b/include/video/neomagic.h
index a9e118a1cd1..38910da0ae5 100644
--- a/include/video/neomagic.h
+++ b/include/video/neomagic.h
@@ -90,23 +90,6 @@
#define PCI_CHIP_NM2360 0x0006
#define PCI_CHIP_NM2380 0x0016
-
-struct xtimings {
- unsigned int pixclock;
- unsigned int HDisplay;
- unsigned int HSyncStart;
- unsigned int HSyncEnd;
- unsigned int HTotal;
- unsigned int VDisplay;
- unsigned int VSyncStart;
- unsigned int VSyncEnd;
- unsigned int VTotal;
- unsigned int sync;
- int dblscan;
- int interlaced;
-};
-
-
/* --------------------------------------------------------------------- */
typedef volatile struct {
diff --git a/include/video/platform_lcd.h b/include/video/platform_lcd.h
new file mode 100644
index 00000000000..ad3bdfe743b
--- /dev/null
+++ b/include/video/platform_lcd.h
@@ -0,0 +1,21 @@
+/* include/video/platform_lcd.h
+ *
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Generic platform-device LCD power control interface.
+ *
+ * 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.
+ *
+*/
+
+struct plat_lcd_data;
+struct fb_info;
+
+struct plat_lcd_data {
+ void (*set_power)(struct plat_lcd_data *, unsigned int power);
+ int (*match_fb)(struct plat_lcd_data *, struct fb_info *);
+};
+
diff --git a/include/video/trident.h b/include/video/trident.h
index 200be255168..b6ce19d1b61 100644
--- a/include/video/trident.h
+++ b/include/video/trident.h
@@ -4,9 +4,9 @@
#endif
#if TRIDENTFB_DEBUG
-#define debug(f,a...) printk("%s:" f, __FUNCTION__ , ## a);mdelay(1000);
+#define debug(f, a...) printk("%s:" f, __func__ , ## a);
#else
-#define debug(f,a...)
+#define debug(f, a...)
#endif
#define output(f, a...) pr_info("tridentfb: " f, ## a)
@@ -24,7 +24,9 @@
#define CYBER9397DVD 0x939A
#define CYBER9520 0x9520
#define CYBER9525DVD 0x9525
+#define TGUI9440 0x9440
#define TGUI9660 0x9660
+#define PROVIDIA9685 0x9685
#define IMAGE975 0x9750
#define IMAGE985 0x9850
#define BLADE3D 0x9880
@@ -39,36 +41,11 @@
#define CYBERBLADEXPm8 0x9910
#define CYBERBLADEXPm16 0x9930
-/* acceleration families */
-#define IMAGE 0
-#define BLADE 1
-#define XP 2
-
-#define is_image(id)
-#define is_xp(id) ((id == CYBERBLADEXPAi1) ||\
- (id == CYBERBLADEXPm8) ||\
- (id == CYBERBLADEXPm16))
-
-#define is_blade(id) ((id == BLADE3D) ||\
- (id == CYBERBLADEE4) ||\
- (id == CYBERBLADEi7) ||\
- (id == CYBERBLADEi7D) ||\
- (id == CYBERBLADEi1) ||\
- (id == CYBERBLADEi1D) ||\
- (id == CYBERBLADEAi1) ||\
- (id == CYBERBLADEAi1D))
-
/* these defines are for 'lcd' variable */
#define LCD_STRETCH 0
#define LCD_CENTER 1
#define LCD_BIOS 2
-/* display types */
-#define DISPLAY_CRT 0
-#define DISPLAY_FP 1
-
-#define flatpanel (displaytype == DISPLAY_FP)
-
/* General Registers */
#define SPR 0x1F /* Software Programming Register (videoram) */
@@ -88,33 +65,7 @@
#define SKey 0x37
#define SPKey 0x57
-/* 0x3x4 */
-#define CRTHTotal 0x00
-#define CRTHDispEnd 0x01
-#define CRTHBlankStart 0x02
-#define CRTHBlankEnd 0x03
-#define CRTHSyncStart 0x04
-#define CRTHSyncEnd 0x05
-
-#define CRTVTotal 0x06
-#define CRTVDispEnd 0x12
-#define CRTVBlankStart 0x15
-#define CRTVBlankEnd 0x16
-#define CRTVSyncStart 0x10
-#define CRTVSyncEnd 0x11
-
-#define CRTOverflow 0x07
-#define CRTPRowScan 0x08
-#define CRTMaxScanLine 0x09
-#define CRTModeControl 0x17
-#define CRTLineCompare 0x18
-
/* 3x4 */
-#define StartAddrHigh 0x0C
-#define StartAddrLow 0x0D
-#define Offset 0x13
-#define Underline 0x14
-#define CRTCMode 0x17
#define CRTCModuleTest 0x1E
#define FIFOControl 0x20
#define LinearAddReg 0x21
@@ -173,3 +124,23 @@
#define BiosMode 0x5c
#define BiosReg 0x5d
+/* Graphics Engine */
+#define STATUS 0x2120
+#define OLDCMD 0x2124
+#define DRAWFL 0x2128
+#define OLDCLR 0x212C
+#define OLDDST 0x2138
+#define OLDSRC 0x213C
+#define OLDDIM 0x2140
+#define CMD 0x2144
+#define ROP 0x2148
+#define COLOR 0x2160
+#define BGCOLOR 0x2164
+#define SRC1 0x2100
+#define SRC2 0x2104
+#define DST1 0x2108
+#define DST2 0x210C
+
+#define ROP_S 0xCC
+#define ROP_P 0xF0
+#define ROP_X 0x66
diff --git a/init/Kconfig b/init/Kconfig
index 6199d112090..a50bdfed2df 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -856,8 +856,8 @@ config MODULE_UNLOAD
help
Without this option you will not be able to unload any
modules (note that some modules may not be unloadable
- anyway), which makes your kernel slightly smaller and
- simpler. If unsure, say Y.
+ anyway), which makes your kernel smaller, faster
+ and simpler. If unsure, say Y.
config MODULE_FORCE_UNLOAD
bool "Forced module unloading"
@@ -893,16 +893,11 @@ config MODULE_SRCVERSION_ALL
will be created for all modules. If unsure, say N.
config KMOD
- bool "Automatic kernel module loading"
+ def_bool y
depends on MODULES
help
- Normally when you have selected some parts of the kernel to
- be created as kernel modules, you must load them (using the
- "modprobe" command) before you can use them. If you say Y
- here, some parts of the kernel will be able to load modules
- automatically: when a part of the kernel needs a module, it
- runs modprobe with the appropriate arguments, thereby
- loading the module if it is available. If unsure, say Y.
+ This is being removed soon. These days, CONFIG_MODULES
+ implies CONFIG_KMOD, so use that instead.
config STOP_MACHINE
bool
diff --git a/init/do_mounts.c b/init/do_mounts.c
index a1de1bf3d6b..f769fac4f4c 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -12,6 +12,7 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/fs.h>
+#include <linux/initrd.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_fs_sb.h>
diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c
index 46dfd64ae8f..fedef93b586 100644
--- a/init/do_mounts_rd.c
+++ b/init/do_mounts_rd.c
@@ -10,8 +10,6 @@
#include "do_mounts.h"
-#define BUILD_CRAMDISK
-
int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */
static int __init prompt_ramdisk(char *str)
@@ -162,14 +160,8 @@ int __init rd_load_image(char *from)
goto done;
if (nblocks == 0) {
-#ifdef BUILD_CRAMDISK
if (crd_load(in_fd, out_fd) == 0)
goto successful_load;
-#else
- printk(KERN_NOTICE
- "RAMDISK: Kernel does not support compressed "
- "RAM disk images\n");
-#endif
goto done;
}
@@ -267,8 +259,6 @@ int __init rd_load_disk(int n)
return rd_load_image("/dev/root");
}
-#ifdef BUILD_CRAMDISK
-
/*
* gzip declarations
*/
@@ -313,32 +303,11 @@ static int crd_infd, crd_outfd;
static int __init fill_inbuf(void);
static void __init flush_window(void);
-static void __init *malloc(size_t size);
-static void __init free(void *where);
static void __init error(char *m);
-static void __init gzip_mark(void **);
-static void __init gzip_release(void **);
-
-#include "../lib/inflate.c"
-static void __init *malloc(size_t size)
-{
- return kmalloc(size, GFP_KERNEL);
-}
-
-static void __init free(void *where)
-{
- kfree(where);
-}
-
-static void __init gzip_mark(void **ptr)
-{
-}
-
-static void __init gzip_release(void **ptr)
-{
-}
+#define NO_INFLATE_MALLOC
+#include "../lib/inflate.c"
/* ===========================================================================
* Fill the input buffer. This is called only when the buffer is empty
@@ -425,5 +394,3 @@ static int __init crd_load(int in_fd, int out_fd)
kfree(window);
return result;
}
-
-#endif /* BUILD_CRAMDISK */
diff --git a/init/initramfs.c b/init/initramfs.c
index 8eeeccb328c..644fc01ad5f 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -14,16 +14,6 @@ static void __init error(char *x)
message = x;
}
-static void __init *malloc(size_t size)
-{
- return kmalloc(size, GFP_KERNEL);
-}
-
-static void __init free(void *where)
-{
- kfree(where);
-}
-
/* link hash */
#define N_ALIGN(len) ((((len) + 1) & ~3) + 2)
@@ -407,18 +397,10 @@ static long bytes_out;
static void __init flush_window(void);
static void __init error(char *m);
-static void __init gzip_mark(void **);
-static void __init gzip_release(void **);
-#include "../lib/inflate.c"
+#define NO_INFLATE_MALLOC
-static void __init gzip_mark(void **ptr)
-{
-}
-
-static void __init gzip_release(void **ptr)
-{
-}
+#include "../lib/inflate.c"
/* ===========================================================================
* Write the output window window[0..outcnt-1] and update crc and bytes_out.
diff --git a/init/main.c b/init/main.c
index 756eca4b821..0604cbcaf1e 100644
--- a/init/main.c
+++ b/init/main.c
@@ -87,8 +87,6 @@ extern void init_IRQ(void);
extern void fork_init(unsigned long);
extern void mca_init(void);
extern void sbus_init(void);
-extern void pidhash_init(void);
-extern void pidmap_init(void);
extern void prio_tree_init(void);
extern void radix_tree_init(void);
extern void free_initmem(void);
@@ -415,6 +413,13 @@ static void __init smp_init(void)
{
unsigned int cpu;
+ /*
+ * Set up the current CPU as possible to migrate to.
+ * The other ones will be done by cpu_up/cpu_down()
+ */
+ cpu = smp_processor_id();
+ cpu_set(cpu, cpu_active_map);
+
/* FIXME: This should be done in userspace --RR */
for_each_present_cpu(cpu) {
if (num_online_cpus() >= setup_max_cpus)
diff --git a/init/version.c b/init/version.c
index 9d17d70ee02..52a8b98642b 100644
--- a/init/version.c
+++ b/init/version.c
@@ -13,10 +13,13 @@
#include <linux/utsrelease.h>
#include <linux/version.h>
+#ifndef CONFIG_KALLSYMS
#define version(a) Version_ ## a
#define version_string(a) version(a)
+extern int version_string(LINUX_VERSION_CODE);
int version_string(LINUX_VERSION_CODE);
+#endif
struct uts_namespace init_uts_ns = {
.kref = {
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index d3497465cc0..69bc85978ba 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -27,15 +27,17 @@ static void *get_ipc(ctl_table *table)
}
/*
- * Routine that is called when a tunable has successfully been changed by
- * hand and it has a callback routine registered on the ipc namespace notifier
- * chain: we don't want such tunables to be recomputed anymore upon memory
- * add/remove or ipc namespace creation/removal.
- * They can come back to a recomputable state by being set to a <0 value.
+ * Routine that is called when the file "auto_msgmni" has successfully been
+ * written.
+ * Two values are allowed:
+ * 0: unregister msgmni's callback routine from the ipc namespace notifier
+ * chain. This means that msgmni won't be recomputed anymore upon memory
+ * add/remove or ipc namespace creation/removal.
+ * 1: register back the callback routine.
*/
-static void tunable_set_callback(int val)
+static void ipc_auto_callback(int val)
{
- if (val >= 0)
+ if (!val)
unregister_ipcns_notifier(current->nsproxy->ipc_ns);
else {
/*
@@ -71,7 +73,12 @@ static int proc_ipc_callback_dointvec(ctl_table *table, int write,
rc = proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos);
if (write && !rc && lenp_bef == *lenp)
- tunable_set_callback(*((int *)(ipc_table.data)));
+ /*
+ * Tunable has successfully been changed by hand. Disable its
+ * automatic adjustment. This simply requires unregistering
+ * the notifiers that trigger recalculation.
+ */
+ unregister_ipcns_notifier(current->nsproxy->ipc_ns);
return rc;
}
@@ -87,10 +94,39 @@ static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
lenp, ppos);
}
+static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
+ struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ struct ctl_table ipc_table;
+ size_t lenp_bef = *lenp;
+ int oldval;
+ int rc;
+
+ memcpy(&ipc_table, table, sizeof(ipc_table));
+ ipc_table.data = get_ipc(table);
+ oldval = *((int *)(ipc_table.data));
+
+ rc = proc_dointvec_minmax(&ipc_table, write, filp, buffer, lenp, ppos);
+
+ if (write && !rc && lenp_bef == *lenp) {
+ int newval = *((int *)(ipc_table.data));
+ /*
+ * The file "auto_msgmni" has correctly been set.
+ * React by (un)registering the corresponding tunable, if the
+ * value has changed.
+ */
+ if (newval != oldval)
+ ipc_auto_callback(newval);
+ }
+
+ return rc;
+}
+
#else
#define proc_ipc_doulongvec_minmax NULL
#define proc_ipc_dointvec NULL
#define proc_ipc_callback_dointvec NULL
+#define proc_ipcauto_dointvec_minmax NULL
#endif
#ifdef CONFIG_SYSCTL_SYSCALL
@@ -142,14 +178,11 @@ static int sysctl_ipc_registered_data(ctl_table *table, int __user *name,
rc = sysctl_ipc_data(table, name, nlen, oldval, oldlenp, newval,
newlen);
- if (newval && newlen && rc > 0) {
+ if (newval && newlen && rc > 0)
/*
* Tunable has successfully been changed from userland
*/
- int *data = get_ipc(table);
-
- tunable_set_callback(*data);
- }
+ unregister_ipcns_notifier(current->nsproxy->ipc_ns);
return rc;
}
@@ -158,6 +191,9 @@ static int sysctl_ipc_registered_data(ctl_table *table, int __user *name,
#define sysctl_ipc_registered_data NULL
#endif
+static int zero;
+static int one = 1;
+
static struct ctl_table ipc_kern_table[] = {
{
.ctl_name = KERN_SHMMAX,
@@ -222,6 +258,16 @@ static struct ctl_table ipc_kern_table[] = {
.proc_handler = proc_ipc_dointvec,
.strategy = sysctl_ipc_data,
},
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "auto_msgmni",
+ .data = &init_ipc_ns.auto_msgmni,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_ipcauto_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
{}
};
diff --git a/ipc/ipcns_notifier.c b/ipc/ipcns_notifier.c
index 70ff09183f7..b9b31a4f77e 100644
--- a/ipc/ipcns_notifier.c
+++ b/ipc/ipcns_notifier.c
@@ -55,25 +55,35 @@ static int ipcns_callback(struct notifier_block *self,
int register_ipcns_notifier(struct ipc_namespace *ns)
{
+ int rc;
+
memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb));
ns->ipcns_nb.notifier_call = ipcns_callback;
ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI;
- return blocking_notifier_chain_register(&ipcns_chain, &ns->ipcns_nb);
+ rc = blocking_notifier_chain_register(&ipcns_chain, &ns->ipcns_nb);
+ if (!rc)
+ ns->auto_msgmni = 1;
+ return rc;
}
int cond_register_ipcns_notifier(struct ipc_namespace *ns)
{
+ int rc;
+
memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb));
ns->ipcns_nb.notifier_call = ipcns_callback;
ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI;
- return blocking_notifier_chain_cond_register(&ipcns_chain,
+ rc = blocking_notifier_chain_cond_register(&ipcns_chain,
&ns->ipcns_nb);
+ if (!rc)
+ ns->auto_msgmni = 1;
+ return rc;
}
-int unregister_ipcns_notifier(struct ipc_namespace *ns)
+void unregister_ipcns_notifier(struct ipc_namespace *ns)
{
- return blocking_notifier_chain_unregister(&ipcns_chain,
- &ns->ipcns_nb);
+ blocking_notifier_chain_unregister(&ipcns_chain, &ns->ipcns_nb);
+ ns->auto_msgmni = 0;
}
int ipcns_notify(unsigned long val)
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 3e84b958186..1fdc2eb2f6d 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -314,15 +314,11 @@ static int mqueue_unlink(struct inode *dir, struct dentry *dentry)
* through std routines)
*/
static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
- size_t count, loff_t * off)
+ size_t count, loff_t *off)
{
struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode);
char buffer[FILENT_SIZE];
- size_t slen;
- loff_t o;
-
- if (!count)
- return 0;
+ ssize_t ret;
spin_lock(&info->lock);
snprintf(buffer, sizeof(buffer),
@@ -335,21 +331,14 @@ static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
pid_vnr(info->notify_owner));
spin_unlock(&info->lock);
buffer[sizeof(buffer)-1] = '\0';
- slen = strlen(buffer)+1;
-
- o = *off;
- if (o > slen)
- return 0;
-
- if (o + count > slen)
- count = slen - o;
- if (copy_to_user(u_data, buffer + o, count))
- return -EFAULT;
+ ret = simple_read_from_buffer(u_data, count, off, buffer,
+ strlen(buffer));
+ if (ret <= 0)
+ return ret;
- *off = o + count;
filp->f_path.dentry->d_inode->i_atime = filp->f_path.dentry->d_inode->i_ctime = CURRENT_TIME;
- return count;
+ return ret;
}
static int mqueue_flush_file(struct file *filp, fl_owner_t id)
diff --git a/ipc/sem.c b/ipc/sem.c
index e9418df5ff3..bf1bc36cb7e 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -272,9 +272,8 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
ns->used_sems += nsems;
sma->sem_base = (struct sem *) &sma[1];
- /* sma->sem_pending = NULL; */
- sma->sem_pending_last = &sma->sem_pending;
- /* sma->undo = NULL; */
+ INIT_LIST_HEAD(&sma->sem_pending);
+ INIT_LIST_HEAD(&sma->list_id);
sma->sem_nsems = nsems;
sma->sem_ctime = get_seconds();
sem_unlock(sma);
@@ -331,38 +330,6 @@ asmlinkage long sys_semget(key_t key, int nsems, int semflg)
return ipcget(ns, &sem_ids(ns), &sem_ops, &sem_params);
}
-/* Manage the doubly linked list sma->sem_pending as a FIFO:
- * insert new queue elements at the tail sma->sem_pending_last.
- */
-static inline void append_to_queue (struct sem_array * sma,
- struct sem_queue * q)
-{
- *(q->prev = sma->sem_pending_last) = q;
- *(sma->sem_pending_last = &q->next) = NULL;
-}
-
-static inline void prepend_to_queue (struct sem_array * sma,
- struct sem_queue * q)
-{
- q->next = sma->sem_pending;
- *(q->prev = &sma->sem_pending) = q;
- if (q->next)
- q->next->prev = &q->next;
- else /* sma->sem_pending_last == &sma->sem_pending */
- sma->sem_pending_last = &q->next;
-}
-
-static inline void remove_from_queue (struct sem_array * sma,
- struct sem_queue * q)
-{
- *(q->prev) = q->next;
- if (q->next)
- q->next->prev = q->prev;
- else /* sma->sem_pending_last == &q->next */
- sma->sem_pending_last = q->prev;
- q->prev = NULL; /* mark as removed */
-}
-
/*
* Determine whether a sequence of semaphore operations would succeed
* all at once. Return 0 if yes, 1 if need to sleep, else return error code.
@@ -438,16 +405,15 @@ static void update_queue (struct sem_array * sma)
int error;
struct sem_queue * q;
- q = sma->sem_pending;
- while(q) {
+ q = list_entry(sma->sem_pending.next, struct sem_queue, list);
+ while (&q->list != &sma->sem_pending) {
error = try_atomic_semop(sma, q->sops, q->nsops,
q->undo, q->pid);
/* Does q->sleeper still need to sleep? */
if (error <= 0) {
struct sem_queue *n;
- remove_from_queue(sma,q);
- q->status = IN_WAKEUP;
+
/*
* Continue scanning. The next operation
* that must be checked depends on the type of the
@@ -458,11 +424,26 @@ static void update_queue (struct sem_array * sma)
* for semaphore values to become 0.
* - if the operation didn't modify the array,
* then just continue.
+ * The order of list_del() and reading ->next
+ * is crucial: In the former case, the list_del()
+ * must be done first [because we might be the
+ * first entry in ->sem_pending], in the latter
+ * case the list_del() must be done last
+ * [because the list is invalid after the list_del()]
*/
- if (q->alter)
- n = sma->sem_pending;
- else
- n = q->next;
+ if (q->alter) {
+ list_del(&q->list);
+ n = list_entry(sma->sem_pending.next,
+ struct sem_queue, list);
+ } else {
+ n = list_entry(q->list.next, struct sem_queue,
+ list);
+ list_del(&q->list);
+ }
+
+ /* wake up the waiting thread */
+ q->status = IN_WAKEUP;
+
wake_up_process(q->sleeper);
/* hands-off: q will disappear immediately after
* writing q->status.
@@ -471,7 +452,7 @@ static void update_queue (struct sem_array * sma)
q->status = error;
q = n;
} else {
- q = q->next;
+ q = list_entry(q->list.next, struct sem_queue, list);
}
}
}
@@ -491,7 +472,7 @@ static int count_semncnt (struct sem_array * sma, ushort semnum)
struct sem_queue * q;
semncnt = 0;
- for (q = sma->sem_pending; q; q = q->next) {
+ list_for_each_entry(q, &sma->sem_pending, list) {
struct sembuf * sops = q->sops;
int nsops = q->nsops;
int i;
@@ -503,13 +484,14 @@ static int count_semncnt (struct sem_array * sma, ushort semnum)
}
return semncnt;
}
+
static int count_semzcnt (struct sem_array * sma, ushort semnum)
{
int semzcnt;
struct sem_queue * q;
semzcnt = 0;
- for (q = sma->sem_pending; q; q = q->next) {
+ list_for_each_entry(q, &sma->sem_pending, list) {
struct sembuf * sops = q->sops;
int nsops = q->nsops;
int i;
@@ -522,35 +504,41 @@ static int count_semzcnt (struct sem_array * sma, ushort semnum)
return semzcnt;
}
+void free_un(struct rcu_head *head)
+{
+ struct sem_undo *un = container_of(head, struct sem_undo, rcu);
+ kfree(un);
+}
+
/* Free a semaphore set. freeary() is called with sem_ids.rw_mutex locked
* as a writer and the spinlock for this semaphore set hold. sem_ids.rw_mutex
* remains locked on exit.
*/
static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
{
- struct sem_undo *un;
- struct sem_queue *q;
+ struct sem_undo *un, *tu;
+ struct sem_queue *q, *tq;
struct sem_array *sma = container_of(ipcp, struct sem_array, sem_perm);
- /* Invalidate the existing undo structures for this semaphore set.
- * (They will be freed without any further action in exit_sem()
- * or during the next semop.)
- */
- for (un = sma->undo; un; un = un->id_next)
+ /* Free the existing undo structures for this semaphore set. */
+ assert_spin_locked(&sma->sem_perm.lock);
+ list_for_each_entry_safe(un, tu, &sma->list_id, list_id) {
+ list_del(&un->list_id);
+ spin_lock(&un->ulp->lock);
un->semid = -1;
+ list_del_rcu(&un->list_proc);
+ spin_unlock(&un->ulp->lock);
+ call_rcu(&un->rcu, free_un);
+ }
/* Wake up all pending processes and let them fail with EIDRM. */
- q = sma->sem_pending;
- while(q) {
- struct sem_queue *n;
- /* lazy remove_from_queue: we are killing the whole queue */
- q->prev = NULL;
- n = q->next;
+ list_for_each_entry_safe(q, tq, &sma->sem_pending, list) {
+ list_del(&q->list);
+
q->status = IN_WAKEUP;
wake_up_process(q->sleeper); /* doesn't sleep */
smp_wmb();
q->status = -EIDRM; /* hands-off q */
- q = n;
}
/* Remove the semaphore set from the IDR */
@@ -763,9 +751,12 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
for (i = 0; i < nsems; i++)
sma->sem_base[i].semval = sem_io[i];
- for (un = sma->undo; un; un = un->id_next)
+
+ assert_spin_locked(&sma->sem_perm.lock);
+ list_for_each_entry(un, &sma->list_id, list_id) {
for (i = 0; i < nsems; i++)
un->semadj[i] = 0;
+ }
sma->sem_ctime = get_seconds();
/* maybe some queued-up processes were waiting for this */
update_queue(sma);
@@ -797,12 +788,15 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
{
int val = arg.val;
struct sem_undo *un;
+
err = -ERANGE;
if (val > SEMVMX || val < 0)
goto out_unlock;
- for (un = sma->undo; un; un = un->id_next)
+ assert_spin_locked(&sma->sem_perm.lock);
+ list_for_each_entry(un, &sma->list_id, list_id)
un->semadj[semnum] = 0;
+
curr->semval = val;
curr->sempid = task_tgid_vnr(current);
sma->sem_ctime = get_seconds();
@@ -952,6 +946,8 @@ static inline int get_undo_list(struct sem_undo_list **undo_listp)
return -ENOMEM;
spin_lock_init(&undo_list->lock);
atomic_set(&undo_list->refcnt, 1);
+ INIT_LIST_HEAD(&undo_list->list_proc);
+
current->sysvsem.undo_list = undo_list;
}
*undo_listp = undo_list;
@@ -960,25 +956,27 @@ static inline int get_undo_list(struct sem_undo_list **undo_listp)
static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid)
{
- struct sem_undo **last, *un;
+ struct sem_undo *walk;
- last = &ulp->proc_list;
- un = *last;
- while(un != NULL) {
- if(un->semid==semid)
- break;
- if(un->semid==-1) {
- *last=un->proc_next;
- kfree(un);
- } else {
- last=&un->proc_next;
- }
- un=*last;
+ list_for_each_entry_rcu(walk, &ulp->list_proc, list_proc) {
+ if (walk->semid == semid)
+ return walk;
}
- return un;
+ return NULL;
}
-static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
+/**
+ * find_alloc_undo - Lookup (and if not present create) undo array
+ * @ns: namespace
+ * @semid: semaphore array id
+ *
+ * The function looks up (and if not present creates) the undo structure.
+ * The size of the undo structure depends on the size of the semaphore
+ * array, thus the alloc path is not that straightforward.
+ * Lifetime-rules: sem_undo is rcu-protected, on success, the function
+ * performs a rcu_read_lock().
+ */
+static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
{
struct sem_array *sma;
struct sem_undo_list *ulp;
@@ -990,13 +988,16 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
if (error)
return ERR_PTR(error);
+ rcu_read_lock();
spin_lock(&ulp->lock);
un = lookup_undo(ulp, semid);
spin_unlock(&ulp->lock);
if (likely(un!=NULL))
goto out;
+ rcu_read_unlock();
/* no undo structure around - allocate one. */
+ /* step 1: figure out the size of the semaphore array */
sma = sem_lock_check(ns, semid);
if (IS_ERR(sma))
return ERR_PTR(PTR_ERR(sma));
@@ -1004,37 +1005,45 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
nsems = sma->sem_nsems;
sem_getref_and_unlock(sma);
+ /* step 2: allocate new undo structure */
new = kzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL);
if (!new) {
sem_putref(sma);
return ERR_PTR(-ENOMEM);
}
- new->semadj = (short *) &new[1];
- new->semid = semid;
- spin_lock(&ulp->lock);
- un = lookup_undo(ulp, semid);
- if (un) {
- spin_unlock(&ulp->lock);
- kfree(new);
- sem_putref(sma);
- goto out;
- }
+ /* step 3: Acquire the lock on semaphore array */
sem_lock_and_putref(sma);
if (sma->sem_perm.deleted) {
sem_unlock(sma);
- spin_unlock(&ulp->lock);
kfree(new);
un = ERR_PTR(-EIDRM);
goto out;
}
- new->proc_next = ulp->proc_list;
- ulp->proc_list = new;
- new->id_next = sma->undo;
- sma->undo = new;
- sem_unlock(sma);
+ spin_lock(&ulp->lock);
+
+ /*
+ * step 4: check for races: did someone else allocate the undo struct?
+ */
+ un = lookup_undo(ulp, semid);
+ if (un) {
+ kfree(new);
+ goto success;
+ }
+ /* step 5: initialize & link new undo structure */
+ new->semadj = (short *) &new[1];
+ new->ulp = ulp;
+ new->semid = semid;
+ assert_spin_locked(&ulp->lock);
+ list_add_rcu(&new->list_proc, &ulp->list_proc);
+ assert_spin_locked(&sma->sem_perm.lock);
+ list_add(&new->list_id, &sma->list_id);
un = new;
+
+success:
spin_unlock(&ulp->lock);
+ rcu_read_lock();
+ sem_unlock(sma);
out:
return un;
}
@@ -1090,9 +1099,8 @@ asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops,
alter = 1;
}
-retry_undos:
if (undos) {
- un = find_undo(ns, semid);
+ un = find_alloc_undo(ns, semid);
if (IS_ERR(un)) {
error = PTR_ERR(un);
goto out_free;
@@ -1102,19 +1110,37 @@ retry_undos:
sma = sem_lock_check(ns, semid);
if (IS_ERR(sma)) {
+ if (un)
+ rcu_read_unlock();
error = PTR_ERR(sma);
goto out_free;
}
/*
- * semid identifiers are not unique - find_undo may have
+ * semid identifiers are not unique - find_alloc_undo may have
* allocated an undo structure, it was invalidated by an RMID
- * and now a new array with received the same id. Check and retry.
+ * and now a new array with received the same id. Check and fail.
+ * This case can be detected checking un->semid. The existance of
+ * "un" itself is guaranteed by rcu.
*/
- if (un && un->semid == -1) {
- sem_unlock(sma);
- goto retry_undos;
+ error = -EIDRM;
+ if (un) {
+ if (un->semid == -1) {
+ rcu_read_unlock();
+ goto out_unlock_free;
+ } else {
+ /*
+ * rcu lock can be released, "un" cannot disappear:
+ * - sem_lock is acquired, thus IPC_RMID is
+ * impossible.
+ * - exit_sem is impossible, it always operates on
+ * current (or a dead task).
+ */
+
+ rcu_read_unlock();
+ }
}
+
error = -EFBIG;
if (max >= sma->sem_nsems)
goto out_unlock_free;
@@ -1138,17 +1164,15 @@ retry_undos:
* task into the pending queue and go to sleep.
*/
- queue.sma = sma;
queue.sops = sops;
queue.nsops = nsops;
queue.undo = un;
queue.pid = task_tgid_vnr(current);
- queue.id = semid;
queue.alter = alter;
if (alter)
- append_to_queue(sma ,&queue);
+ list_add_tail(&queue.list, &sma->sem_pending);
else
- prepend_to_queue(sma ,&queue);
+ list_add(&queue.list, &sma->sem_pending);
queue.status = -EINTR;
queue.sleeper = current;
@@ -1174,7 +1198,6 @@ retry_undos:
sma = sem_lock(ns, semid);
if (IS_ERR(sma)) {
- BUG_ON(queue.prev != NULL);
error = -EIDRM;
goto out_free;
}
@@ -1192,7 +1215,7 @@ retry_undos:
*/
if (timeout && jiffies_left == 0)
error = -EAGAIN;
- remove_from_queue(sma,&queue);
+ list_del(&queue.list);
goto out_unlock_free;
out_unlock_free:
@@ -1243,56 +1266,62 @@ int copy_semundo(unsigned long clone_flags, struct task_struct *tsk)
*/
void exit_sem(struct task_struct *tsk)
{
- struct sem_undo_list *undo_list;
- struct sem_undo *u, **up;
- struct ipc_namespace *ns;
+ struct sem_undo_list *ulp;
- undo_list = tsk->sysvsem.undo_list;
- if (!undo_list)
+ ulp = tsk->sysvsem.undo_list;
+ if (!ulp)
return;
tsk->sysvsem.undo_list = NULL;
- if (!atomic_dec_and_test(&undo_list->refcnt))
+ if (!atomic_dec_and_test(&ulp->refcnt))
return;
- ns = tsk->nsproxy->ipc_ns;
- /* There's no need to hold the semundo list lock, as current
- * is the last task exiting for this undo list.
- */
- for (up = &undo_list->proc_list; (u = *up); *up = u->proc_next, kfree(u)) {
+ for (;;) {
struct sem_array *sma;
- int nsems, i;
- struct sem_undo *un, **unp;
+ struct sem_undo *un;
int semid;
-
- semid = u->semid;
+ int i;
- if(semid == -1)
- continue;
- sma = sem_lock(ns, semid);
+ rcu_read_lock();
+ un = list_entry(rcu_dereference(ulp->list_proc.next),
+ struct sem_undo, list_proc);
+ if (&un->list_proc == &ulp->list_proc)
+ semid = -1;
+ else
+ semid = un->semid;
+ rcu_read_unlock();
+
+ if (semid == -1)
+ break;
+
+ sma = sem_lock_check(tsk->nsproxy->ipc_ns, un->semid);
+
+ /* exit_sem raced with IPC_RMID, nothing to do */
if (IS_ERR(sma))
continue;
- if (u->semid == -1)
- goto next_entry;
+ un = lookup_undo(ulp, semid);
+ if (un == NULL) {
+ /* exit_sem raced with IPC_RMID+semget() that created
+ * exactly the same semid. Nothing to do.
+ */
+ sem_unlock(sma);
+ continue;
+ }
- BUG_ON(sem_checkid(sma, u->semid));
+ /* remove un from the linked lists */
+ assert_spin_locked(&sma->sem_perm.lock);
+ list_del(&un->list_id);
- /* remove u from the sma->undo list */
- for (unp = &sma->undo; (un = *unp); unp = &un->id_next) {
- if (u == un)
- goto found;
- }
- printk ("exit_sem undo list error id=%d\n", u->semid);
- goto next_entry;
-found:
- *unp = un->id_next;
- /* perform adjustments registered in u */
- nsems = sma->sem_nsems;
- for (i = 0; i < nsems; i++) {
+ spin_lock(&ulp->lock);
+ list_del_rcu(&un->list_proc);
+ spin_unlock(&ulp->lock);
+
+ /* perform adjustments registered in un */
+ for (i = 0; i < sma->sem_nsems; i++) {
struct sem * semaphore = &sma->sem_base[i];
- if (u->semadj[i]) {
- semaphore->semval += u->semadj[i];
+ if (un->semadj[i]) {
+ semaphore->semval += un->semadj[i];
/*
* Range checks of the new semaphore value,
* not defined by sus:
@@ -1316,10 +1345,11 @@ found:
sma->sem_otime = get_seconds();
/* maybe some queued-up processes were waiting for this */
update_queue(sma);
-next_entry:
sem_unlock(sma);
+
+ call_rcu(&un->rcu, free_un);
}
- kfree(undo_list);
+ kfree(ulp);
}
#ifdef CONFIG_PROC_FS
diff --git a/ipc/shm.c b/ipc/shm.c
index 790240cd067..e77ec698cf4 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -112,23 +112,8 @@ void __init shm_init (void)
}
/*
- * shm_lock_(check_)down routines are called in the paths where the rw_mutex
- * is held to protect access to the idr tree.
- */
-static inline struct shmid_kernel *shm_lock_down(struct ipc_namespace *ns,
- int id)
-{
- struct kern_ipc_perm *ipcp = ipc_lock_down(&shm_ids(ns), id);
-
- if (IS_ERR(ipcp))
- return (struct shmid_kernel *)ipcp;
-
- return container_of(ipcp, struct shmid_kernel, shm_perm);
-}
-
-/*
* shm_lock_(check_) routines are called in the paths where the rw_mutex
- * is not held.
+ * is not necessarily held.
*/
static inline struct shmid_kernel *shm_lock(struct ipc_namespace *ns, int id)
{
@@ -211,7 +196,7 @@ static void shm_close(struct vm_area_struct *vma)
down_write(&shm_ids(ns).rw_mutex);
/* remove from the list of attaches of the shm segment */
- shp = shm_lock_down(ns, sfd->id);
+ shp = shm_lock(ns, sfd->id);
BUG_ON(IS_ERR(shp));
shp->shm_lprid = task_tgid_vnr(current);
shp->shm_dtim = get_seconds();
@@ -577,7 +562,8 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
if (is_file_hugepages(shp->shm_file)) {
struct address_space *mapping = inode->i_mapping;
- *rss += (HPAGE_SIZE/PAGE_SIZE)*mapping->nrpages;
+ struct hstate *h = hstate_file(shp->shm_file);
+ *rss += pages_per_huge_page(h) * mapping->nrpages;
} else {
struct shmem_inode_info *info = SHMEM_I(inode);
spin_lock(&info->lock);
@@ -931,7 +917,7 @@ invalid:
out_nattch:
down_write(&shm_ids(ns).rw_mutex);
- shp = shm_lock_down(ns, shmid);
+ shp = shm_lock(ns, shmid);
BUG_ON(IS_ERR(shp));
shp->shm_nattch--;
if(shp->shm_nattch == 0 &&
diff --git a/ipc/util.c b/ipc/util.c
index 3339177b336..49b3ea615dc 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -688,10 +688,6 @@ void ipc64_perm_to_ipc_perm (struct ipc64_perm *in, struct ipc_perm *out)
* Look for an id in the ipc ids idr and lock the associated ipc object.
*
* The ipc object is locked on exit.
- *
- * This is the routine that should be called when the rw_mutex is not already
- * held, i.e. idr tree not protected: it protects the idr tree in read mode
- * during the idr_find().
*/
struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)
@@ -699,18 +695,13 @@ struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)
struct kern_ipc_perm *out;
int lid = ipcid_to_idx(id);
- down_read(&ids->rw_mutex);
-
rcu_read_lock();
out = idr_find(&ids->ipcs_idr, lid);
if (out == NULL) {
rcu_read_unlock();
- up_read(&ids->rw_mutex);
return ERR_PTR(-EINVAL);
}
- up_read(&ids->rw_mutex);
-
spin_lock(&out->lock);
/* ipc_rmid() may have already freed the ID while ipc_lock
@@ -725,56 +716,6 @@ struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)
return out;
}
-/**
- * ipc_lock_down - Lock an ipc structure with rw_sem held
- * @ids: IPC identifier set
- * @id: ipc id to look for
- *
- * Look for an id in the ipc ids idr and lock the associated ipc object.
- *
- * The ipc object is locked on exit.
- *
- * This is the routine that should be called when the rw_mutex is already
- * held, i.e. idr tree protected.
- */
-
-struct kern_ipc_perm *ipc_lock_down(struct ipc_ids *ids, int id)
-{
- struct kern_ipc_perm *out;
- int lid = ipcid_to_idx(id);
-
- rcu_read_lock();
- out = idr_find(&ids->ipcs_idr, lid);
- if (out == NULL) {
- rcu_read_unlock();
- return ERR_PTR(-EINVAL);
- }
-
- spin_lock(&out->lock);
-
- /*
- * No need to verify that the structure is still valid since the
- * rw_mutex is held.
- */
- return out;
-}
-
-struct kern_ipc_perm *ipc_lock_check_down(struct ipc_ids *ids, int id)
-{
- struct kern_ipc_perm *out;
-
- out = ipc_lock_down(ids, id);
- if (IS_ERR(out))
- return out;
-
- if (ipc_checkid(out, id)) {
- ipc_unlock(out);
- return ERR_PTR(-EIDRM);
- }
-
- return out;
-}
-
struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id)
{
struct kern_ipc_perm *out;
@@ -846,7 +787,7 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd,
int err;
down_write(&ids->rw_mutex);
- ipcp = ipc_lock_check_down(ids, id);
+ ipcp = ipc_lock_check(ids, id);
if (IS_ERR(ipcp)) {
err = PTR_ERR(ipcp);
goto out_up;
diff --git a/ipc/util.h b/ipc/util.h
index cdb966aebe0..3646b45a03c 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -102,11 +102,6 @@ void* ipc_rcu_alloc(int size);
void ipc_rcu_getref(void *ptr);
void ipc_rcu_putref(void *ptr);
-/*
- * ipc_lock_down: called with rw_mutex held
- * ipc_lock: called without that lock held
- */
-struct kern_ipc_perm *ipc_lock_down(struct ipc_ids *, int);
struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int);
void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
@@ -155,7 +150,6 @@ static inline void ipc_unlock(struct kern_ipc_perm *perm)
rcu_read_unlock();
}
-struct kern_ipc_perm *ipc_lock_check_down(struct ipc_ids *ids, int id);
struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id);
int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
struct ipc_ops *ops, struct ipc_params *params);
diff --git a/kernel/Kconfig.hz b/kernel/Kconfig.hz
index 526128a2e62..382dd5a8b2d 100644
--- a/kernel/Kconfig.hz
+++ b/kernel/Kconfig.hz
@@ -55,4 +55,4 @@ config HZ
default 1000 if HZ_1000
config SCHED_HRTICK
- def_bool HIGH_RES_TIMERS && X86
+ def_bool HIGH_RES_TIMERS && USE_GENERIC_SMP_HELPERS
diff --git a/kernel/Makefile b/kernel/Makefile
index 985ddb7da4d..54f69837d35 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -2,7 +2,7 @@
# Makefile for the linux kernel.
#
-obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
+obj-y = sched.o fork.o exec_domain.o panic.o printk.o \
cpu.o exit.o itimer.o time.o softirq.o resource.o \
sysctl.o capability.o ptrace.o timer.o user.o \
signal.o sys.o kmod.o workqueue.o pid.o \
@@ -11,6 +11,8 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
notifier.o ksysfs.o pm_qos_params.o sched_clock.o
+CFLAGS_REMOVE_sched.o = -mno-spe
+
ifdef CONFIG_FTRACE
# Do not trace debug files and internal ftrace files
CFLAGS_REMOVE_lockdep.o = -pg
@@ -22,6 +24,7 @@ CFLAGS_REMOVE_sched_clock.o = -pg
CFLAGS_REMOVE_sched.o = -mno-spe -pg
endif
+obj-$(CONFIG_PROFILING) += profile.o
obj-$(CONFIG_SYSCTL_SYSCALL_CHECK) += sysctl_check.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-y += time/
diff --git a/kernel/acct.c b/kernel/acct.c
index 91e1cfd734d..dd68b905941 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -75,37 +75,39 @@ int acct_parm[3] = {4, 2, 30};
/*
* External references and all of the globals.
*/
-static void do_acct_process(struct pid_namespace *ns, struct file *);
+static void do_acct_process(struct bsd_acct_struct *acct,
+ struct pid_namespace *ns, struct file *);
/*
* This structure is used so that all the data protected by lock
* can be placed in the same cache line as the lock. This primes
* the cache line to have the data after getting the lock.
*/
-struct acct_glbs {
- spinlock_t lock;
+struct bsd_acct_struct {
volatile int active;
volatile int needcheck;
struct file *file;
struct pid_namespace *ns;
struct timer_list timer;
+ struct list_head list;
};
-static struct acct_glbs acct_globals __cacheline_aligned =
- {__SPIN_LOCK_UNLOCKED(acct_globals.lock)};
+static DEFINE_SPINLOCK(acct_lock);
+static LIST_HEAD(acct_list);
/*
* Called whenever the timer says to check the free space.
*/
-static void acct_timeout(unsigned long unused)
+static void acct_timeout(unsigned long x)
{
- acct_globals.needcheck = 1;
+ struct bsd_acct_struct *acct = (struct bsd_acct_struct *)x;
+ acct->needcheck = 1;
}
/*
* Check the amount of free space and suspend/resume accordingly.
*/
-static int check_free_space(struct file *file)
+static int check_free_space(struct bsd_acct_struct *acct, struct file *file)
{
struct kstatfs sbuf;
int res;
@@ -113,11 +115,11 @@ static int check_free_space(struct file *file)
sector_t resume;
sector_t suspend;
- spin_lock(&acct_globals.lock);
- res = acct_globals.active;
- if (!file || !acct_globals.needcheck)
+ spin_lock(&acct_lock);
+ res = acct->active;
+ if (!file || !acct->needcheck)
goto out;
- spin_unlock(&acct_globals.lock);
+ spin_unlock(&acct_lock);
/* May block */
if (vfs_statfs(file->f_path.dentry, &sbuf))
@@ -136,35 +138,35 @@ static int check_free_space(struct file *file)
act = 0;
/*
- * If some joker switched acct_globals.file under us we'ld better be
+ * If some joker switched acct->file under us we'ld better be
* silent and _not_ touch anything.
*/
- spin_lock(&acct_globals.lock);
- if (file != acct_globals.file) {
+ spin_lock(&acct_lock);
+ if (file != acct->file) {
if (act)
res = act>0;
goto out;
}
- if (acct_globals.active) {
+ if (acct->active) {
if (act < 0) {
- acct_globals.active = 0;
+ acct->active = 0;
printk(KERN_INFO "Process accounting paused\n");
}
} else {
if (act > 0) {
- acct_globals.active = 1;
+ acct->active = 1;
printk(KERN_INFO "Process accounting resumed\n");
}
}
- del_timer(&acct_globals.timer);
- acct_globals.needcheck = 0;
- acct_globals.timer.expires = jiffies + ACCT_TIMEOUT*HZ;
- add_timer(&acct_globals.timer);
- res = acct_globals.active;
+ del_timer(&acct->timer);
+ acct->needcheck = 0;
+ acct->timer.expires = jiffies + ACCT_TIMEOUT*HZ;
+ add_timer(&acct->timer);
+ res = acct->active;
out:
- spin_unlock(&acct_globals.lock);
+ spin_unlock(&acct_lock);
return res;
}
@@ -172,39 +174,41 @@ out:
* Close the old accounting file (if currently open) and then replace
* it with file (if non-NULL).
*
- * NOTE: acct_globals.lock MUST be held on entry and exit.
+ * NOTE: acct_lock MUST be held on entry and exit.
*/
-static void acct_file_reopen(struct file *file)
+static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file,
+ struct pid_namespace *ns)
{
struct file *old_acct = NULL;
struct pid_namespace *old_ns = NULL;
- if (acct_globals.file) {
- old_acct = acct_globals.file;
- old_ns = acct_globals.ns;
- del_timer(&acct_globals.timer);
- acct_globals.active = 0;
- acct_globals.needcheck = 0;
- acct_globals.file = NULL;
+ if (acct->file) {
+ old_acct = acct->file;
+ old_ns = acct->ns;
+ del_timer(&acct->timer);
+ acct->active = 0;
+ acct->needcheck = 0;
+ acct->file = NULL;
+ acct->ns = NULL;
+ list_del(&acct->list);
}
if (file) {
- acct_globals.file = file;
- acct_globals.ns = get_pid_ns(task_active_pid_ns(current));
- acct_globals.needcheck = 0;
- acct_globals.active = 1;
+ acct->file = file;
+ acct->ns = ns;
+ acct->needcheck = 0;
+ acct->active = 1;
+ list_add(&acct->list, &acct_list);
/* It's been deleted if it was used before so this is safe */
- init_timer(&acct_globals.timer);
- acct_globals.timer.function = acct_timeout;
- acct_globals.timer.expires = jiffies + ACCT_TIMEOUT*HZ;
- add_timer(&acct_globals.timer);
+ setup_timer(&acct->timer, acct_timeout, (unsigned long)acct);
+ acct->timer.expires = jiffies + ACCT_TIMEOUT*HZ;
+ add_timer(&acct->timer);
}
if (old_acct) {
mnt_unpin(old_acct->f_path.mnt);
- spin_unlock(&acct_globals.lock);
- do_acct_process(old_ns, old_acct);
+ spin_unlock(&acct_lock);
+ do_acct_process(acct, old_ns, old_acct);
filp_close(old_acct, NULL);
- put_pid_ns(old_ns);
- spin_lock(&acct_globals.lock);
+ spin_lock(&acct_lock);
}
}
@@ -212,6 +216,8 @@ static int acct_on(char *name)
{
struct file *file;
int error;
+ struct pid_namespace *ns;
+ struct bsd_acct_struct *acct = NULL;
/* Difference from BSD - they don't do O_APPEND */
file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0);
@@ -228,18 +234,34 @@ static int acct_on(char *name)
return -EIO;
}
+ ns = task_active_pid_ns(current);
+ if (ns->bacct == NULL) {
+ acct = kzalloc(sizeof(struct bsd_acct_struct), GFP_KERNEL);
+ if (acct == NULL) {
+ filp_close(file, NULL);
+ return -ENOMEM;
+ }
+ }
+
error = security_acct(file);
if (error) {
+ kfree(acct);
filp_close(file, NULL);
return error;
}
- spin_lock(&acct_globals.lock);
+ spin_lock(&acct_lock);
+ if (ns->bacct == NULL) {
+ ns->bacct = acct;
+ acct = NULL;
+ }
+
mnt_pin(file->f_path.mnt);
- acct_file_reopen(file);
- spin_unlock(&acct_globals.lock);
+ acct_file_reopen(ns->bacct, file, ns);
+ spin_unlock(&acct_lock);
mntput(file->f_path.mnt); /* it's pinned, now give up active reference */
+ kfree(acct);
return 0;
}
@@ -269,11 +291,17 @@ asmlinkage long sys_acct(const char __user *name)
error = acct_on(tmp);
putname(tmp);
} else {
+ struct bsd_acct_struct *acct;
+
+ acct = task_active_pid_ns(current)->bacct;
+ if (acct == NULL)
+ return 0;
+
error = security_acct(NULL);
if (!error) {
- spin_lock(&acct_globals.lock);
- acct_file_reopen(NULL);
- spin_unlock(&acct_globals.lock);
+ spin_lock(&acct_lock);
+ acct_file_reopen(acct, NULL, NULL);
+ spin_unlock(&acct_lock);
}
}
return error;
@@ -288,10 +316,16 @@ asmlinkage long sys_acct(const char __user *name)
*/
void acct_auto_close_mnt(struct vfsmount *m)
{
- spin_lock(&acct_globals.lock);
- if (acct_globals.file && acct_globals.file->f_path.mnt == m)
- acct_file_reopen(NULL);
- spin_unlock(&acct_globals.lock);
+ struct bsd_acct_struct *acct;
+
+ spin_lock(&acct_lock);
+restart:
+ list_for_each_entry(acct, &acct_list, list)
+ if (acct->file && acct->file->f_path.mnt == m) {
+ acct_file_reopen(acct, NULL, NULL);
+ goto restart;
+ }
+ spin_unlock(&acct_lock);
}
/**
@@ -303,12 +337,31 @@ void acct_auto_close_mnt(struct vfsmount *m)
*/
void acct_auto_close(struct super_block *sb)
{
- spin_lock(&acct_globals.lock);
- if (acct_globals.file &&
- acct_globals.file->f_path.mnt->mnt_sb == sb) {
- acct_file_reopen(NULL);
+ struct bsd_acct_struct *acct;
+
+ spin_lock(&acct_lock);
+restart:
+ list_for_each_entry(acct, &acct_list, list)
+ if (acct->file && acct->file->f_path.mnt->mnt_sb == sb) {
+ acct_file_reopen(acct, NULL, NULL);
+ goto restart;
+ }
+ spin_unlock(&acct_lock);
+}
+
+void acct_exit_ns(struct pid_namespace *ns)
+{
+ struct bsd_acct_struct *acct;
+
+ spin_lock(&acct_lock);
+ acct = ns->bacct;
+ if (acct != NULL) {
+ if (acct->file != NULL)
+ acct_file_reopen(acct, NULL, NULL);
+
+ kfree(acct);
}
- spin_unlock(&acct_globals.lock);
+ spin_unlock(&acct_lock);
}
/*
@@ -425,7 +478,8 @@ static u32 encode_float(u64 value)
/*
* do_acct_process does all actual work. Caller holds the reference to file.
*/
-static void do_acct_process(struct pid_namespace *ns, struct file *file)
+static void do_acct_process(struct bsd_acct_struct *acct,
+ struct pid_namespace *ns, struct file *file)
{
struct pacct_struct *pacct = &current->signal->pacct;
acct_t ac;
@@ -440,7 +494,7 @@ static void do_acct_process(struct pid_namespace *ns, struct file *file)
* First check to see if there is enough free_space to continue
* the process accounting system.
*/
- if (!check_free_space(file))
+ if (!check_free_space(acct, file))
return;
/*
@@ -577,34 +631,46 @@ void acct_collect(long exitcode, int group_dead)
spin_unlock_irq(&current->sighand->siglock);
}
-/**
- * acct_process - now just a wrapper around do_acct_process
- * @exitcode: task exit code
- *
- * handles process accounting for an exiting task
- */
-void acct_process(void)
+static void acct_process_in_ns(struct pid_namespace *ns)
{
struct file *file = NULL;
- struct pid_namespace *ns;
+ struct bsd_acct_struct *acct;
+ acct = ns->bacct;
/*
* accelerate the common fastpath:
*/
- if (!acct_globals.file)
+ if (!acct || !acct->file)
return;
- spin_lock(&acct_globals.lock);
- file = acct_globals.file;
+ spin_lock(&acct_lock);
+ file = acct->file;
if (unlikely(!file)) {
- spin_unlock(&acct_globals.lock);
+ spin_unlock(&acct_lock);
return;
}
get_file(file);
- ns = get_pid_ns(acct_globals.ns);
- spin_unlock(&acct_globals.lock);
+ spin_unlock(&acct_lock);
- do_acct_process(ns, file);
+ do_acct_process(acct, ns, file);
fput(file);
- put_pid_ns(ns);
+}
+
+/**
+ * acct_process - now just a wrapper around acct_process_in_ns,
+ * which in turn is a wrapper around do_acct_process.
+ *
+ * handles process accounting for an exiting task
+ */
+void acct_process(void)
+{
+ struct pid_namespace *ns;
+
+ /*
+ * This loop is safe lockless, since current is still
+ * alive and holds its namespace, which in turn holds
+ * its parent.
+ */
+ for (ns = task_active_pid_ns(current); ns != NULL; ns = ns->parent)
+ acct_process_in_ns(ns);
}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index c10e7aae04d..4699950e65b 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1476,7 +1476,8 @@ void audit_syscall_entry(int arch, int major,
struct audit_context *context = tsk->audit_context;
enum audit_state state;
- BUG_ON(!context);
+ if (unlikely(!context))
+ return;
/*
* This happens only on certain architectures that make system
diff --git a/kernel/capability.c b/kernel/capability.c
index 901e0fdc3ff..0101e847603 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -115,11 +115,208 @@ static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy)
return 0;
}
+#ifndef CONFIG_SECURITY_FILE_CAPABILITIES
+
+/*
+ * Without filesystem capability support, we nominally support one process
+ * setting the capabilities of another
+ */
+static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
+ kernel_cap_t *pIp, kernel_cap_t *pPp)
+{
+ struct task_struct *target;
+ int ret;
+
+ spin_lock(&task_capability_lock);
+ read_lock(&tasklist_lock);
+
+ if (pid && pid != task_pid_vnr(current)) {
+ target = find_task_by_vpid(pid);
+ if (!target) {
+ ret = -ESRCH;
+ goto out;
+ }
+ } else
+ target = current;
+
+ ret = security_capget(target, pEp, pIp, pPp);
+
+out:
+ read_unlock(&tasklist_lock);
+ spin_unlock(&task_capability_lock);
+
+ return ret;
+}
+
+/*
+ * cap_set_pg - set capabilities for all processes in a given process
+ * group. We call this holding task_capability_lock and tasklist_lock.
+ */
+static inline int cap_set_pg(int pgrp_nr, kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted)
+{
+ struct task_struct *g, *target;
+ int ret = -EPERM;
+ int found = 0;
+ struct pid *pgrp;
+
+ spin_lock(&task_capability_lock);
+ read_lock(&tasklist_lock);
+
+ pgrp = find_vpid(pgrp_nr);
+ do_each_pid_task(pgrp, PIDTYPE_PGID, g) {
+ target = g;
+ while_each_thread(g, target) {
+ if (!security_capset_check(target, effective,
+ inheritable, permitted)) {
+ security_capset_set(target, effective,
+ inheritable, permitted);
+ ret = 0;
+ }
+ found = 1;
+ }
+ } while_each_pid_task(pgrp, PIDTYPE_PGID, g);
+
+ read_unlock(&tasklist_lock);
+ spin_unlock(&task_capability_lock);
+
+ if (!found)
+ ret = 0;
+ return ret;
+}
+
/*
- * For sys_getproccap() and sys_setproccap(), any of the three
- * capability set pointers may be NULL -- indicating that that set is
- * uninteresting and/or not to be changed.
+ * cap_set_all - set capabilities for all processes other than init
+ * and self. We call this holding task_capability_lock and tasklist_lock.
*/
+static inline int cap_set_all(kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted)
+{
+ struct task_struct *g, *target;
+ int ret = -EPERM;
+ int found = 0;
+
+ spin_lock(&task_capability_lock);
+ read_lock(&tasklist_lock);
+
+ do_each_thread(g, target) {
+ if (target == current
+ || is_container_init(target->group_leader))
+ continue;
+ found = 1;
+ if (security_capset_check(target, effective, inheritable,
+ permitted))
+ continue;
+ ret = 0;
+ security_capset_set(target, effective, inheritable, permitted);
+ } while_each_thread(g, target);
+
+ read_unlock(&tasklist_lock);
+ spin_unlock(&task_capability_lock);
+
+ if (!found)
+ ret = 0;
+
+ return ret;
+}
+
+/*
+ * Given the target pid does not refer to the current process we
+ * need more elaborate support... (This support is not present when
+ * filesystem capabilities are configured.)
+ */
+static inline int do_sys_capset_other_tasks(pid_t pid, kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted)
+{
+ struct task_struct *target;
+ int ret;
+
+ if (!capable(CAP_SETPCAP))
+ return -EPERM;
+
+ if (pid == -1) /* all procs other than current and init */
+ return cap_set_all(effective, inheritable, permitted);
+
+ else if (pid < 0) /* all procs in process group */
+ return cap_set_pg(-pid, effective, inheritable, permitted);
+
+ /* target != current */
+ spin_lock(&task_capability_lock);
+ read_lock(&tasklist_lock);
+
+ target = find_task_by_vpid(pid);
+ if (!target)
+ ret = -ESRCH;
+ else {
+ ret = security_capset_check(target, effective, inheritable,
+ permitted);
+
+ /* having verified that the proposed changes are legal,
+ we now put them into effect. */
+ if (!ret)
+ security_capset_set(target, effective, inheritable,
+ permitted);
+ }
+
+ read_unlock(&tasklist_lock);
+ spin_unlock(&task_capability_lock);
+
+ return ret;
+}
+
+#else /* ie., def CONFIG_SECURITY_FILE_CAPABILITIES */
+
+/*
+ * If we have configured with filesystem capability support, then the
+ * only thing that can change the capabilities of the current process
+ * is the current process. As such, we can't be in this code at the
+ * same time as we are in the process of setting capabilities in this
+ * process. The net result is that we can limit our use of locks to
+ * when we are reading the caps of another process.
+ */
+static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
+ kernel_cap_t *pIp, kernel_cap_t *pPp)
+{
+ int ret;
+
+ if (pid && (pid != task_pid_vnr(current))) {
+ struct task_struct *target;
+
+ spin_lock(&task_capability_lock);
+ read_lock(&tasklist_lock);
+
+ target = find_task_by_vpid(pid);
+ if (!target)
+ ret = -ESRCH;
+ else
+ ret = security_capget(target, pEp, pIp, pPp);
+
+ read_unlock(&tasklist_lock);
+ spin_unlock(&task_capability_lock);
+ } else
+ ret = security_capget(current, pEp, pIp, pPp);
+
+ return ret;
+}
+
+/*
+ * With filesystem capability support configured, the kernel does not
+ * permit the changing of capabilities in one process by another
+ * process. (CAP_SETPCAP has much less broad semantics when configured
+ * this way.)
+ */
+static inline int do_sys_capset_other_tasks(pid_t pid,
+ kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted)
+{
+ return -EPERM;
+}
+
+#endif /* ie., ndef CONFIG_SECURITY_FILE_CAPABILITIES */
/*
* Atomically modify the effective capabilities returning the original
@@ -155,7 +352,6 @@ asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
{
int ret = 0;
pid_t pid;
- struct task_struct *target;
unsigned tocopy;
kernel_cap_t pE, pI, pP;
@@ -169,23 +365,7 @@ asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
if (pid < 0)
return -EINVAL;
- spin_lock(&task_capability_lock);
- read_lock(&tasklist_lock);
-
- if (pid && pid != task_pid_vnr(current)) {
- target = find_task_by_vpid(pid);
- if (!target) {
- ret = -ESRCH;
- goto out;
- }
- } else
- target = current;
-
- ret = security_capget(target, &pE, &pI, &pP);
-
-out:
- read_unlock(&tasklist_lock);
- spin_unlock(&task_capability_lock);
+ ret = cap_get_target_pid(pid, &pE, &pI, &pP);
if (!ret) {
struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S];
@@ -216,7 +396,6 @@ out:
* before modification is attempted and the application
* fails.
*/
-
if (copy_to_user(dataptr, kdata, tocopy
* sizeof(struct __user_cap_data_struct))) {
return -EFAULT;
@@ -226,70 +405,8 @@ out:
return ret;
}
-/*
- * cap_set_pg - set capabilities for all processes in a given process
- * group. We call this holding task_capability_lock and tasklist_lock.
- */
-static inline int cap_set_pg(int pgrp_nr, kernel_cap_t *effective,
- kernel_cap_t *inheritable,
- kernel_cap_t *permitted)
-{
- struct task_struct *g, *target;
- int ret = -EPERM;
- int found = 0;
- struct pid *pgrp;
-
- pgrp = find_vpid(pgrp_nr);
- do_each_pid_task(pgrp, PIDTYPE_PGID, g) {
- target = g;
- while_each_thread(g, target) {
- if (!security_capset_check(target, effective,
- inheritable,
- permitted)) {
- security_capset_set(target, effective,
- inheritable,
- permitted);
- ret = 0;
- }
- found = 1;
- }
- } while_each_pid_task(pgrp, PIDTYPE_PGID, g);
-
- if (!found)
- ret = 0;
- return ret;
-}
-
-/*
- * cap_set_all - set capabilities for all processes other than init
- * and self. We call this holding task_capability_lock and tasklist_lock.
- */
-static inline int cap_set_all(kernel_cap_t *effective,
- kernel_cap_t *inheritable,
- kernel_cap_t *permitted)
-{
- struct task_struct *g, *target;
- int ret = -EPERM;
- int found = 0;
-
- do_each_thread(g, target) {
- if (target == current || is_container_init(target->group_leader))
- continue;
- found = 1;
- if (security_capset_check(target, effective, inheritable,
- permitted))
- continue;
- ret = 0;
- security_capset_set(target, effective, inheritable, permitted);
- } while_each_thread(g, target);
-
- if (!found)
- ret = 0;
- return ret;
-}
-
/**
- * sys_capset - set capabilities for a process or a group of processes
+ * sys_capset - set capabilities for a process or (*) a group of processes
* @header: pointer to struct that contains capability version and
* target pid data
* @data: pointer to struct that contains the effective, permitted,
@@ -313,7 +430,6 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S];
unsigned i, tocopy;
kernel_cap_t inheritable, permitted, effective;
- struct task_struct *target;
int ret;
pid_t pid;
@@ -324,9 +440,6 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
if (get_user(pid, &header->pid))
return -EFAULT;
- if (pid && pid != task_pid_vnr(current) && !capable(CAP_SETPCAP))
- return -EPERM;
-
if (copy_from_user(&kdata, data, tocopy
* sizeof(struct __user_cap_data_struct))) {
return -EFAULT;
@@ -344,40 +457,31 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
i++;
}
- spin_lock(&task_capability_lock);
- read_lock(&tasklist_lock);
-
- if (pid > 0 && pid != task_pid_vnr(current)) {
- target = find_task_by_vpid(pid);
- if (!target) {
- ret = -ESRCH;
- goto out;
- }
- } else
- target = current;
-
- ret = 0;
-
- /* having verified that the proposed changes are legal,
- we now put them into effect. */
- if (pid < 0) {
- if (pid == -1) /* all procs other than current and init */
- ret = cap_set_all(&effective, &inheritable, &permitted);
+ if (pid && (pid != task_pid_vnr(current)))
+ ret = do_sys_capset_other_tasks(pid, &effective, &inheritable,
+ &permitted);
+ else {
+ /*
+ * This lock is required even when filesystem
+ * capability support is configured - it protects the
+ * sys_capget() call from returning incorrect data in
+ * the case that the targeted process is not the
+ * current one.
+ */
+ spin_lock(&task_capability_lock);
- else /* all procs in process group */
- ret = cap_set_pg(-pid, &effective, &inheritable,
- &permitted);
- } else {
- ret = security_capset_check(target, &effective, &inheritable,
+ ret = security_capset_check(current, &effective, &inheritable,
&permitted);
+ /*
+ * Having verified that the proposed changes are
+ * legal, we now put them into effect.
+ */
if (!ret)
- security_capset_set(target, &effective, &inheritable,
+ security_capset_set(current, &effective, &inheritable,
&permitted);
+ spin_unlock(&task_capability_lock);
}
-out:
- read_unlock(&tasklist_lock);
- spin_unlock(&task_capability_lock);
return ret;
}
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 15ac0e1e4f4..66ec9fd21e0 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -89,11 +89,7 @@ struct cgroupfs_root {
/* Hierarchy-specific flags */
unsigned long flags;
- /* The path to use for release notifications. No locking
- * between setting and use - so if userspace updates this
- * while child cgroups exist, you could miss a
- * notification. We ensure that it's always a valid
- * NUL-terminated string */
+ /* The path to use for release notifications. */
char release_agent_path[PATH_MAX];
};
@@ -118,7 +114,7 @@ static int root_count;
* extra work in the fork/exit path if none of the subsystems need to
* be called.
*/
-static int need_forkexit_callback;
+static int need_forkexit_callback __read_mostly;
static int need_mm_owner_callback __read_mostly;
/* convenient tests for these bits */
@@ -220,7 +216,7 @@ static struct hlist_head *css_set_hash(struct cgroup_subsys_state *css[])
* task until after the first call to cgroup_iter_start(). This
* reduces the fork()/exit() overhead for people who have cgroups
* compiled into their kernel but not actually in use */
-static int use_task_css_set_links;
+static int use_task_css_set_links __read_mostly;
/* When we create or destroy a css_set, the operation simply
* takes/releases a reference count on all the cgroups referenced
@@ -241,17 +237,20 @@ static int use_task_css_set_links;
*/
static void unlink_css_set(struct css_set *cg)
{
+ struct cg_cgroup_link *link;
+ struct cg_cgroup_link *saved_link;
+
write_lock(&css_set_lock);
hlist_del(&cg->hlist);
css_set_count--;
- while (!list_empty(&cg->cg_links)) {
- struct cg_cgroup_link *link;
- link = list_entry(cg->cg_links.next,
- struct cg_cgroup_link, cg_link_list);
+
+ list_for_each_entry_safe(link, saved_link, &cg->cg_links,
+ cg_link_list) {
list_del(&link->cg_link_list);
list_del(&link->cgrp_link_list);
kfree(link);
}
+
write_unlock(&css_set_lock);
}
@@ -363,15 +362,14 @@ static struct css_set *find_existing_css_set(
static int allocate_cg_links(int count, struct list_head *tmp)
{
struct cg_cgroup_link *link;
+ struct cg_cgroup_link *saved_link;
int i;
INIT_LIST_HEAD(tmp);
for (i = 0; i < count; i++) {
link = kmalloc(sizeof(*link), GFP_KERNEL);
if (!link) {
- while (!list_empty(tmp)) {
- link = list_entry(tmp->next,
- struct cg_cgroup_link,
- cgrp_link_list);
+ list_for_each_entry_safe(link, saved_link, tmp,
+ cgrp_link_list) {
list_del(&link->cgrp_link_list);
kfree(link);
}
@@ -384,11 +382,10 @@ static int allocate_cg_links(int count, struct list_head *tmp)
static void free_cg_links(struct list_head *tmp)
{
- while (!list_empty(tmp)) {
- struct cg_cgroup_link *link;
- link = list_entry(tmp->next,
- struct cg_cgroup_link,
- cgrp_link_list);
+ struct cg_cgroup_link *link;
+ struct cg_cgroup_link *saved_link;
+
+ list_for_each_entry_safe(link, saved_link, tmp, cgrp_link_list) {
list_del(&link->cgrp_link_list);
kfree(link);
}
@@ -415,11 +412,11 @@ static struct css_set *find_css_set(
/* First see if we already have a cgroup group that matches
* the desired set */
- write_lock(&css_set_lock);
+ read_lock(&css_set_lock);
res = find_existing_css_set(oldcg, cgrp, template);
if (res)
get_css_set(res);
- write_unlock(&css_set_lock);
+ read_unlock(&css_set_lock);
if (res)
return res;
@@ -507,10 +504,6 @@ static struct css_set *find_css_set(
* knows that the cgroup won't be removed, as cgroup_rmdir()
* needs that mutex.
*
- * The cgroup_common_file_write handler for operations that modify
- * the cgroup hierarchy holds cgroup_mutex across the entire operation,
- * single threading all such cgroup modifications across the system.
- *
* The fork and exit callbacks cgroup_fork() and cgroup_exit(), don't
* (usually) take cgroup_mutex. These are the two most performance
* critical pieces of code here. The exception occurs on cgroup_exit(),
@@ -1093,6 +1086,8 @@ static void cgroup_kill_sb(struct super_block *sb) {
struct cgroupfs_root *root = sb->s_fs_info;
struct cgroup *cgrp = &root->top_cgroup;
int ret;
+ struct cg_cgroup_link *link;
+ struct cg_cgroup_link *saved_link;
BUG_ON(!root);
@@ -1112,10 +1107,9 @@ static void cgroup_kill_sb(struct super_block *sb) {
* root cgroup
*/
write_lock(&css_set_lock);
- while (!list_empty(&cgrp->css_sets)) {
- struct cg_cgroup_link *link;
- link = list_entry(cgrp->css_sets.next,
- struct cg_cgroup_link, cgrp_link_list);
+
+ list_for_each_entry_safe(link, saved_link, &cgrp->css_sets,
+ cgrp_link_list) {
list_del(&link->cg_link_list);
list_del(&link->cgrp_link_list);
kfree(link);
@@ -1281,18 +1275,14 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
}
/*
- * Attach task with pid 'pid' to cgroup 'cgrp'. Call with
- * cgroup_mutex, may take task_lock of task
+ * Attach task with pid 'pid' to cgroup 'cgrp'. Call with cgroup_mutex
+ * held. May take task_lock of task
*/
-static int attach_task_by_pid(struct cgroup *cgrp, char *pidbuf)
+static int attach_task_by_pid(struct cgroup *cgrp, u64 pid)
{
- pid_t pid;
struct task_struct *tsk;
int ret;
- if (sscanf(pidbuf, "%d", &pid) != 1)
- return -EIO;
-
if (pid) {
rcu_read_lock();
tsk = find_task_by_vpid(pid);
@@ -1318,6 +1308,16 @@ static int attach_task_by_pid(struct cgroup *cgrp, char *pidbuf)
return ret;
}
+static int cgroup_tasks_write(struct cgroup *cgrp, struct cftype *cft, u64 pid)
+{
+ int ret;
+ if (!cgroup_lock_live_group(cgrp))
+ return -ENODEV;
+ ret = attach_task_by_pid(cgrp, pid);
+ cgroup_unlock();
+ return ret;
+}
+
/* The various types of files and directories in a cgroup file system */
enum cgroup_filetype {
FILE_ROOT,
@@ -1327,12 +1327,54 @@ enum cgroup_filetype {
FILE_RELEASE_AGENT,
};
+/**
+ * cgroup_lock_live_group - take cgroup_mutex and check that cgrp is alive.
+ * @cgrp: the cgroup to be checked for liveness
+ *
+ * On success, returns true; the lock should be later released with
+ * cgroup_unlock(). On failure returns false with no lock held.
+ */
+bool cgroup_lock_live_group(struct cgroup *cgrp)
+{
+ mutex_lock(&cgroup_mutex);
+ if (cgroup_is_removed(cgrp)) {
+ mutex_unlock(&cgroup_mutex);
+ return false;
+ }
+ return true;
+}
+
+static int cgroup_release_agent_write(struct cgroup *cgrp, struct cftype *cft,
+ const char *buffer)
+{
+ BUILD_BUG_ON(sizeof(cgrp->root->release_agent_path) < PATH_MAX);
+ if (!cgroup_lock_live_group(cgrp))
+ return -ENODEV;
+ strcpy(cgrp->root->release_agent_path, buffer);
+ cgroup_unlock();
+ return 0;
+}
+
+static int cgroup_release_agent_show(struct cgroup *cgrp, struct cftype *cft,
+ struct seq_file *seq)
+{
+ if (!cgroup_lock_live_group(cgrp))
+ return -ENODEV;
+ seq_puts(seq, cgrp->root->release_agent_path);
+ seq_putc(seq, '\n');
+ cgroup_unlock();
+ return 0;
+}
+
+/* A buffer size big enough for numbers or short strings */
+#define CGROUP_LOCAL_BUFFER_SIZE 64
+
static ssize_t cgroup_write_X64(struct cgroup *cgrp, struct cftype *cft,
struct file *file,
const char __user *userbuf,
size_t nbytes, loff_t *unused_ppos)
{
- char buffer[64];
+ char buffer[CGROUP_LOCAL_BUFFER_SIZE];
int retval = 0;
char *end;
@@ -1361,68 +1403,36 @@ static ssize_t cgroup_write_X64(struct cgroup *cgrp, struct cftype *cft,
return retval;
}
-static ssize_t cgroup_common_file_write(struct cgroup *cgrp,
- struct cftype *cft,
- struct file *file,
- const char __user *userbuf,
- size_t nbytes, loff_t *unused_ppos)
+static ssize_t cgroup_write_string(struct cgroup *cgrp, struct cftype *cft,
+ struct file *file,
+ const char __user *userbuf,
+ size_t nbytes, loff_t *unused_ppos)
{
- enum cgroup_filetype type = cft->private;
- char *buffer;
+ char local_buffer[CGROUP_LOCAL_BUFFER_SIZE];
int retval = 0;
+ size_t max_bytes = cft->max_write_len;
+ char *buffer = local_buffer;
- if (nbytes >= PATH_MAX)
+ if (!max_bytes)
+ max_bytes = sizeof(local_buffer) - 1;
+ if (nbytes >= max_bytes)
return -E2BIG;
-
- /* +1 for nul-terminator */
- buffer = kmalloc(nbytes + 1, GFP_KERNEL);
- if (buffer == NULL)
- return -ENOMEM;
-
- if (copy_from_user(buffer, userbuf, nbytes)) {
- retval = -EFAULT;
- goto out1;
+ /* Allocate a dynamic buffer if we need one */
+ if (nbytes >= sizeof(local_buffer)) {
+ buffer = kmalloc(nbytes + 1, GFP_KERNEL);
+ if (buffer == NULL)
+ return -ENOMEM;
}
- buffer[nbytes] = 0; /* nul-terminate */
- strstrip(buffer); /* strip -just- trailing whitespace */
-
- mutex_lock(&cgroup_mutex);
+ if (nbytes && copy_from_user(buffer, userbuf, nbytes))
+ return -EFAULT;
- /*
- * This was already checked for in cgroup_file_write(), but
- * check again now we're holding cgroup_mutex.
- */
- if (cgroup_is_removed(cgrp)) {
- retval = -ENODEV;
- goto out2;
- }
-
- switch (type) {
- case FILE_TASKLIST:
- retval = attach_task_by_pid(cgrp, buffer);
- break;
- case FILE_NOTIFY_ON_RELEASE:
- clear_bit(CGRP_RELEASABLE, &cgrp->flags);
- if (simple_strtoul(buffer, NULL, 10) != 0)
- set_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
- else
- clear_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
- break;
- case FILE_RELEASE_AGENT:
- BUILD_BUG_ON(sizeof(cgrp->root->release_agent_path) < PATH_MAX);
- strcpy(cgrp->root->release_agent_path, buffer);
- break;
- default:
- retval = -EINVAL;
- goto out2;
- }
-
- if (retval == 0)
+ buffer[nbytes] = 0; /* nul-terminate */
+ strstrip(buffer);
+ retval = cft->write_string(cgrp, cft, buffer);
+ if (!retval)
retval = nbytes;
-out2:
- mutex_unlock(&cgroup_mutex);
-out1:
- kfree(buffer);
+ if (buffer != local_buffer)
+ kfree(buffer);
return retval;
}
@@ -1438,6 +1448,8 @@ static ssize_t cgroup_file_write(struct file *file, const char __user *buf,
return cft->write(cgrp, cft, file, buf, nbytes, ppos);
if (cft->write_u64 || cft->write_s64)
return cgroup_write_X64(cgrp, cft, file, buf, nbytes, ppos);
+ if (cft->write_string)
+ return cgroup_write_string(cgrp, cft, file, buf, nbytes, ppos);
if (cft->trigger) {
int ret = cft->trigger(cgrp, (unsigned int)cft->private);
return ret ? ret : nbytes;
@@ -1450,7 +1462,7 @@ static ssize_t cgroup_read_u64(struct cgroup *cgrp, struct cftype *cft,
char __user *buf, size_t nbytes,
loff_t *ppos)
{
- char tmp[64];
+ char tmp[CGROUP_LOCAL_BUFFER_SIZE];
u64 val = cft->read_u64(cgrp, cft);
int len = sprintf(tmp, "%llu\n", (unsigned long long) val);
@@ -1462,56 +1474,13 @@ static ssize_t cgroup_read_s64(struct cgroup *cgrp, struct cftype *cft,
char __user *buf, size_t nbytes,
loff_t *ppos)
{
- char tmp[64];
+ char tmp[CGROUP_LOCAL_BUFFER_SIZE];
s64 val = cft->read_s64(cgrp, cft);
int len = sprintf(tmp, "%lld\n", (long long) val);
return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
}
-static ssize_t cgroup_common_file_read(struct cgroup *cgrp,
- struct cftype *cft,
- struct file *file,
- char __user *buf,
- size_t nbytes, loff_t *ppos)
-{
- enum cgroup_filetype type = cft->private;
- char *page;
- ssize_t retval = 0;
- char *s;
-
- if (!(page = (char *)__get_free_page(GFP_KERNEL)))
- return -ENOMEM;
-
- s = page;
-
- switch (type) {
- case FILE_RELEASE_AGENT:
- {
- struct cgroupfs_root *root;
- size_t n;
- mutex_lock(&cgroup_mutex);
- root = cgrp->root;
- n = strnlen(root->release_agent_path,
- sizeof(root->release_agent_path));
- n = min(n, (size_t) PAGE_SIZE);
- strncpy(s, root->release_agent_path, n);
- mutex_unlock(&cgroup_mutex);
- s += n;
- break;
- }
- default:
- retval = -EINVAL;
- goto out;
- }
- *s++ = '\n';
-
- retval = simple_read_from_buffer(buf, nbytes, ppos, page, s - page);
-out:
- free_page((unsigned long)page);
- return retval;
-}
-
static ssize_t cgroup_file_read(struct file *file, char __user *buf,
size_t nbytes, loff_t *ppos)
{
@@ -1569,6 +1538,7 @@ int cgroup_seqfile_release(struct inode *inode, struct file *file)
static struct file_operations cgroup_seqfile_operations = {
.read = seq_read,
+ .write = cgroup_file_write,
.llseek = seq_lseek,
.release = cgroup_seqfile_release,
};
@@ -1756,15 +1726,11 @@ int cgroup_add_files(struct cgroup *cgrp,
int cgroup_task_count(const struct cgroup *cgrp)
{
int count = 0;
- struct list_head *l;
+ struct cg_cgroup_link *link;
read_lock(&css_set_lock);
- l = cgrp->css_sets.next;
- while (l != &cgrp->css_sets) {
- struct cg_cgroup_link *link =
- list_entry(l, struct cg_cgroup_link, cgrp_link_list);
+ list_for_each_entry(link, &cgrp->css_sets, cgrp_link_list) {
count += atomic_read(&link->cg->ref.refcount);
- l = l->next;
}
read_unlock(&css_set_lock);
return count;
@@ -2227,6 +2193,18 @@ static u64 cgroup_read_notify_on_release(struct cgroup *cgrp,
return notify_on_release(cgrp);
}
+static int cgroup_write_notify_on_release(struct cgroup *cgrp,
+ struct cftype *cft,
+ u64 val)
+{
+ clear_bit(CGRP_RELEASABLE, &cgrp->flags);
+ if (val)
+ set_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
+ else
+ clear_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
+ return 0;
+}
+
/*
* for the common functions, 'private' gives the type of file
*/
@@ -2235,7 +2213,7 @@ static struct cftype files[] = {
.name = "tasks",
.open = cgroup_tasks_open,
.read = cgroup_tasks_read,
- .write = cgroup_common_file_write,
+ .write_u64 = cgroup_tasks_write,
.release = cgroup_tasks_release,
.private = FILE_TASKLIST,
},
@@ -2243,15 +2221,16 @@ static struct cftype files[] = {
{
.name = "notify_on_release",
.read_u64 = cgroup_read_notify_on_release,
- .write = cgroup_common_file_write,
+ .write_u64 = cgroup_write_notify_on_release,
.private = FILE_NOTIFY_ON_RELEASE,
},
};
static struct cftype cft_release_agent = {
.name = "release_agent",
- .read = cgroup_common_file_read,
- .write = cgroup_common_file_write,
+ .read_seq_string = cgroup_release_agent_show,
+ .write_string = cgroup_release_agent_write,
+ .max_write_len = PATH_MAX,
.private = FILE_RELEASE_AGENT,
};
@@ -2869,16 +2848,17 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
* cgroup_clone - clone the cgroup the given subsystem is attached to
* @tsk: the task to be moved
* @subsys: the given subsystem
+ * @nodename: the name for the new cgroup
*
* Duplicate the current cgroup in the hierarchy that the given
* subsystem is attached to, and move this task into the new
* child.
*/
-int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys)
+int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys,
+ char *nodename)
{
struct dentry *dentry;
int ret = 0;
- char nodename[MAX_CGROUP_TYPE_NAMELEN];
struct cgroup *parent, *child;
struct inode *inode;
struct css_set *cg;
@@ -2903,8 +2883,6 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys)
cg = tsk->cgroups;
parent = task_cgroup(tsk, subsys->subsys_id);
- snprintf(nodename, MAX_CGROUP_TYPE_NAMELEN, "%d", tsk->pid);
-
/* Pin the hierarchy */
atomic_inc(&parent->root->sb->s_active);
@@ -3078,27 +3056,24 @@ static void cgroup_release_agent(struct work_struct *work)
while (!list_empty(&release_list)) {
char *argv[3], *envp[3];
int i;
- char *pathbuf;
+ char *pathbuf = NULL, *agentbuf = NULL;
struct cgroup *cgrp = list_entry(release_list.next,
struct cgroup,
release_list);
list_del_init(&cgrp->release_list);
spin_unlock(&release_list_lock);
pathbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
- if (!pathbuf) {
- spin_lock(&release_list_lock);
- continue;
- }
-
- if (cgroup_path(cgrp, pathbuf, PAGE_SIZE) < 0) {
- kfree(pathbuf);
- spin_lock(&release_list_lock);
- continue;
- }
+ if (!pathbuf)
+ goto continue_free;
+ if (cgroup_path(cgrp, pathbuf, PAGE_SIZE) < 0)
+ goto continue_free;
+ agentbuf = kstrdup(cgrp->root->release_agent_path, GFP_KERNEL);
+ if (!agentbuf)
+ goto continue_free;
i = 0;
- argv[i++] = cgrp->root->release_agent_path;
- argv[i++] = (char *)pathbuf;
+ argv[i++] = agentbuf;
+ argv[i++] = pathbuf;
argv[i] = NULL;
i = 0;
@@ -3112,8 +3087,10 @@ static void cgroup_release_agent(struct work_struct *work)
* be a slow process */
mutex_unlock(&cgroup_mutex);
call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
- kfree(pathbuf);
mutex_lock(&cgroup_mutex);
+ continue_free:
+ kfree(pathbuf);
+ kfree(agentbuf);
spin_lock(&release_list_lock);
}
spin_unlock(&release_list_lock);
diff --git a/kernel/cpu.c b/kernel/cpu.c
index cfb1d43ab80..10ba5f1004a 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -64,6 +64,8 @@ void __init cpu_hotplug_init(void)
cpu_hotplug.refcount = 0;
}
+cpumask_t cpu_active_map;
+
#ifdef CONFIG_HOTPLUG_CPU
void get_online_cpus(void)
@@ -283,6 +285,11 @@ out_allowed:
set_cpus_allowed_ptr(current, &old_allowed);
out_release:
cpu_hotplug_done();
+ if (!err) {
+ if (raw_notifier_call_chain(&cpu_chain, CPU_POST_DEAD | mod,
+ hcpu) == NOTIFY_BAD)
+ BUG();
+ }
return err;
}
@@ -291,11 +298,30 @@ int __ref cpu_down(unsigned int cpu)
int err = 0;
cpu_maps_update_begin();
- if (cpu_hotplug_disabled)
+
+ if (cpu_hotplug_disabled) {
err = -EBUSY;
- else
- err = _cpu_down(cpu, 0);
+ goto out;
+ }
+
+ cpu_clear(cpu, cpu_active_map);
+
+ /*
+ * Make sure the all cpus did the reschedule and are not
+ * using stale version of the cpu_active_map.
+ * This is not strictly necessary becuase stop_machine()
+ * that we run down the line already provides the required
+ * synchronization. But it's really a side effect and we do not
+ * want to depend on the innards of the stop_machine here.
+ */
+ synchronize_sched();
+
+ err = _cpu_down(cpu, 0);
+
+ if (cpu_online(cpu))
+ cpu_set(cpu, cpu_active_map);
+out:
cpu_maps_update_done();
return err;
}
@@ -355,11 +381,18 @@ int __cpuinit cpu_up(unsigned int cpu)
}
cpu_maps_update_begin();
- if (cpu_hotplug_disabled)
+
+ if (cpu_hotplug_disabled) {
err = -EBUSY;
- else
- err = _cpu_up(cpu, 0);
+ goto out;
+ }
+
+ err = _cpu_up(cpu, 0);
+ if (cpu_online(cpu))
+ cpu_set(cpu, cpu_active_map);
+
+out:
cpu_maps_update_done();
return err;
}
@@ -413,7 +446,7 @@ void __ref enable_nonboot_cpus(void)
goto out;
printk("Enabling non-boot CPUs ...\n");
- for_each_cpu_mask(cpu, frozen_cpus) {
+ for_each_cpu_mask_nr(cpu, frozen_cpus) {
error = _cpu_up(cpu, 1);
if (!error) {
printk("CPU%d is up\n", cpu);
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 459d601947a..91cf85b36dd 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -227,10 +227,6 @@ static struct cpuset top_cpuset = {
* The task_struct fields mems_allowed and mems_generation may only
* be accessed in the context of that task, so require no locks.
*
- * The cpuset_common_file_write handler for operations that modify
- * the cpuset hierarchy holds cgroup_mutex across the entire operation,
- * single threading all such cpuset modifications across the system.
- *
* The cpuset_common_file_read() handlers only hold callback_mutex across
* small pieces of code, such as when reading out possibly multi-word
* cpumasks and nodemasks.
@@ -369,7 +365,7 @@ void cpuset_update_task_memory_state(void)
my_cpusets_mem_gen = top_cpuset.mems_generation;
} else {
rcu_read_lock();
- my_cpusets_mem_gen = task_cs(current)->mems_generation;
+ my_cpusets_mem_gen = task_cs(tsk)->mems_generation;
rcu_read_unlock();
}
@@ -500,11 +496,16 @@ update_domain_attr(struct sched_domain_attr *dattr, struct cpuset *c)
/*
* rebuild_sched_domains()
*
- * If the flag 'sched_load_balance' of any cpuset with non-empty
- * 'cpus' changes, or if the 'cpus' allowed changes in any cpuset
- * which has that flag enabled, or if any cpuset with a non-empty
- * 'cpus' is removed, then call this routine to rebuild the
- * scheduler's dynamic sched domains.
+ * This routine will be called to rebuild the scheduler's dynamic
+ * sched domains:
+ * - if the flag 'sched_load_balance' of any cpuset with non-empty
+ * 'cpus' changes,
+ * - or if the 'cpus' allowed changes in any cpuset which has that
+ * flag enabled,
+ * - or if the 'sched_relax_domain_level' of any cpuset which has
+ * that flag enabled and with non-empty 'cpus' changes,
+ * - or if any cpuset with non-empty 'cpus' is removed,
+ * - or if a cpu gets offlined.
*
* This routine builds a partial partition of the systems CPUs
* (the set of non-overlappping cpumask_t's in the array 'part'
@@ -564,7 +565,7 @@ update_domain_attr(struct sched_domain_attr *dattr, struct cpuset *c)
* partition_sched_domains().
*/
-static void rebuild_sched_domains(void)
+void rebuild_sched_domains(void)
{
struct kfifo *q; /* queue of cpusets to be scanned */
struct cpuset *cp; /* scans q */
@@ -609,8 +610,13 @@ static void rebuild_sched_domains(void)
while (__kfifo_get(q, (void *)&cp, sizeof(cp))) {
struct cgroup *cont;
struct cpuset *child; /* scans child cpusets of cp */
+
+ if (cpus_empty(cp->cpus_allowed))
+ continue;
+
if (is_sched_load_balance(cp))
csa[csn++] = cp;
+
list_for_each_entry(cont, &cp->css.cgroup->children, sibling) {
child = cgroup_cs(cont);
__kfifo_put(q, (void *)&child, sizeof(cp));
@@ -679,7 +685,9 @@ restart:
if (apn == b->pn) {
cpus_or(*dp, *dp, b->cpus_allowed);
b->pn = -1;
- update_domain_attr(dattr, b);
+ if (dattr)
+ update_domain_attr(dattr
+ + nslot, b);
}
}
nslot++;
@@ -701,36 +709,6 @@ done:
/* Don't kfree(dattr) -- partition_sched_domains() does that. */
}
-static inline int started_after_time(struct task_struct *t1,
- struct timespec *time,
- struct task_struct *t2)
-{
- int start_diff = timespec_compare(&t1->start_time, time);
- if (start_diff > 0) {
- return 1;
- } else if (start_diff < 0) {
- return 0;
- } else {
- /*
- * Arbitrarily, if two processes started at the same
- * time, we'll say that the lower pointer value
- * started first. Note that t2 may have exited by now
- * so this may not be a valid pointer any longer, but
- * that's fine - it still serves to distinguish
- * between two tasks started (effectively)
- * simultaneously.
- */
- return t1 > t2;
- }
-}
-
-static inline int started_after(void *p1, void *p2)
-{
- struct task_struct *t1 = p1;
- struct task_struct *t2 = p2;
- return started_after_time(t1, &t2->start_time, t2);
-}
-
/**
* cpuset_test_cpumask - test a task's cpus_allowed versus its cpuset's
* @tsk: task to test
@@ -766,15 +744,49 @@ static void cpuset_change_cpumask(struct task_struct *tsk,
}
/**
+ * update_tasks_cpumask - Update the cpumasks of tasks in the cpuset.
+ * @cs: the cpuset in which each task's cpus_allowed mask needs to be changed
+ *
+ * Called with cgroup_mutex held
+ *
+ * The cgroup_scan_tasks() function will scan all the tasks in a cgroup,
+ * calling callback functions for each.
+ *
+ * Return 0 if successful, -errno if not.
+ */
+static int update_tasks_cpumask(struct cpuset *cs)
+{
+ struct cgroup_scanner scan;
+ struct ptr_heap heap;
+ int retval;
+
+ /*
+ * cgroup_scan_tasks() will initialize heap->gt for us.
+ * heap_init() is still needed here for we should not change
+ * cs->cpus_allowed when heap_init() fails.
+ */
+ retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, NULL);
+ if (retval)
+ return retval;
+
+ scan.cg = cs->css.cgroup;
+ scan.test_task = cpuset_test_cpumask;
+ scan.process_task = cpuset_change_cpumask;
+ scan.heap = &heap;
+ retval = cgroup_scan_tasks(&scan);
+
+ heap_free(&heap);
+ return retval;
+}
+
+/**
* update_cpumask - update the cpus_allowed mask of a cpuset and all tasks in it
* @cs: the cpuset to consider
* @buf: buffer of cpu numbers written to this cpuset
*/
-static int update_cpumask(struct cpuset *cs, char *buf)
+static int update_cpumask(struct cpuset *cs, const char *buf)
{
struct cpuset trialcs;
- struct cgroup_scanner scan;
- struct ptr_heap heap;
int retval;
int is_load_balanced;
@@ -790,7 +802,6 @@ static int update_cpumask(struct cpuset *cs, char *buf)
* that parsing. The validate_change() call ensures that cpusets
* with tasks have cpus.
*/
- buf = strstrip(buf);
if (!*buf) {
cpus_clear(trialcs.cpus_allowed);
} else {
@@ -809,10 +820,6 @@ static int update_cpumask(struct cpuset *cs, char *buf)
if (cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed))
return 0;
- retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, &started_after);
- if (retval)
- return retval;
-
is_load_balanced = is_sched_load_balance(&trialcs);
mutex_lock(&callback_mutex);
@@ -823,12 +830,9 @@ static int update_cpumask(struct cpuset *cs, char *buf)
* Scan tasks in the cpuset, and update the cpumasks of any
* that need an update.
*/
- scan.cg = cs->css.cgroup;
- scan.test_task = cpuset_test_cpumask;
- scan.process_task = cpuset_change_cpumask;
- scan.heap = &heap;
- cgroup_scan_tasks(&scan);
- heap_free(&heap);
+ retval = update_tasks_cpumask(cs);
+ if (retval < 0)
+ return retval;
if (is_load_balanced)
rebuild_sched_domains();
@@ -884,74 +888,25 @@ static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from,
mutex_unlock(&callback_mutex);
}
-/*
- * Handle user request to change the 'mems' memory placement
- * of a cpuset. Needs to validate the request, update the
- * cpusets mems_allowed and mems_generation, and for each
- * task in the cpuset, rebind any vma mempolicies and if
- * the cpuset is marked 'memory_migrate', migrate the tasks
- * pages to the new memory.
- *
- * Call with cgroup_mutex held. May take callback_mutex during call.
- * Will take tasklist_lock, scan tasklist for tasks in cpuset cs,
- * lock each such tasks mm->mmap_sem, scan its vma's and rebind
- * their mempolicies to the cpusets new mems_allowed.
- */
-
static void *cpuset_being_rebound;
-static int update_nodemask(struct cpuset *cs, char *buf)
+/**
+ * update_tasks_nodemask - Update the nodemasks of tasks in the cpuset.
+ * @cs: the cpuset in which each task's mems_allowed mask needs to be changed
+ * @oldmem: old mems_allowed of cpuset cs
+ *
+ * Called with cgroup_mutex held
+ * Return 0 if successful, -errno if not.
+ */
+static int update_tasks_nodemask(struct cpuset *cs, const nodemask_t *oldmem)
{
- struct cpuset trialcs;
- nodemask_t oldmem;
struct task_struct *p;
struct mm_struct **mmarray;
int i, n, ntasks;
int migrate;
int fudge;
- int retval;
struct cgroup_iter it;
-
- /*
- * top_cpuset.mems_allowed tracks node_stats[N_HIGH_MEMORY];
- * it's read-only
- */
- if (cs == &top_cpuset)
- return -EACCES;
-
- trialcs = *cs;
-
- /*
- * An empty mems_allowed is ok iff there are no tasks in the cpuset.
- * Since nodelist_parse() fails on an empty mask, we special case
- * that parsing. The validate_change() call ensures that cpusets
- * with tasks have memory.
- */
- buf = strstrip(buf);
- if (!*buf) {
- nodes_clear(trialcs.mems_allowed);
- } else {
- retval = nodelist_parse(buf, trialcs.mems_allowed);
- if (retval < 0)
- goto done;
-
- if (!nodes_subset(trialcs.mems_allowed,
- node_states[N_HIGH_MEMORY]))
- return -EINVAL;
- }
- oldmem = cs->mems_allowed;
- if (nodes_equal(oldmem, trialcs.mems_allowed)) {
- retval = 0; /* Too easy - nothing to do */
- goto done;
- }
- retval = validate_change(cs, &trialcs);
- if (retval < 0)
- goto done;
-
- mutex_lock(&callback_mutex);
- cs->mems_allowed = trialcs.mems_allowed;
- cs->mems_generation = cpuset_mems_generation++;
- mutex_unlock(&callback_mutex);
+ int retval;
cpuset_being_rebound = cs; /* causes mpol_dup() rebind */
@@ -1018,7 +973,7 @@ static int update_nodemask(struct cpuset *cs, char *buf)
mpol_rebind_mm(mm, &cs->mems_allowed);
if (migrate)
- cpuset_migrate_mm(mm, &oldmem, &cs->mems_allowed);
+ cpuset_migrate_mm(mm, oldmem, &cs->mems_allowed);
mmput(mm);
}
@@ -1030,6 +985,70 @@ done:
return retval;
}
+/*
+ * Handle user request to change the 'mems' memory placement
+ * of a cpuset. Needs to validate the request, update the
+ * cpusets mems_allowed and mems_generation, and for each
+ * task in the cpuset, rebind any vma mempolicies and if
+ * the cpuset is marked 'memory_migrate', migrate the tasks
+ * pages to the new memory.
+ *
+ * Call with cgroup_mutex held. May take callback_mutex during call.
+ * Will take tasklist_lock, scan tasklist for tasks in cpuset cs,
+ * lock each such tasks mm->mmap_sem, scan its vma's and rebind
+ * their mempolicies to the cpusets new mems_allowed.
+ */
+static int update_nodemask(struct cpuset *cs, const char *buf)
+{
+ struct cpuset trialcs;
+ nodemask_t oldmem;
+ int retval;
+
+ /*
+ * top_cpuset.mems_allowed tracks node_stats[N_HIGH_MEMORY];
+ * it's read-only
+ */
+ if (cs == &top_cpuset)
+ return -EACCES;
+
+ trialcs = *cs;
+
+ /*
+ * An empty mems_allowed is ok iff there are no tasks in the cpuset.
+ * Since nodelist_parse() fails on an empty mask, we special case
+ * that parsing. The validate_change() call ensures that cpusets
+ * with tasks have memory.
+ */
+ if (!*buf) {
+ nodes_clear(trialcs.mems_allowed);
+ } else {
+ retval = nodelist_parse(buf, trialcs.mems_allowed);
+ if (retval < 0)
+ goto done;
+
+ if (!nodes_subset(trialcs.mems_allowed,
+ node_states[N_HIGH_MEMORY]))
+ return -EINVAL;
+ }
+ oldmem = cs->mems_allowed;
+ if (nodes_equal(oldmem, trialcs.mems_allowed)) {
+ retval = 0; /* Too easy - nothing to do */
+ goto done;
+ }
+ retval = validate_change(cs, &trialcs);
+ if (retval < 0)
+ goto done;
+
+ mutex_lock(&callback_mutex);
+ cs->mems_allowed = trialcs.mems_allowed;
+ cs->mems_generation = cpuset_mems_generation++;
+ mutex_unlock(&callback_mutex);
+
+ retval = update_tasks_nodemask(cs, &oldmem);
+done:
+ return retval;
+}
+
int current_cpuset_is_being_rebound(void)
{
return task_cs(current) == cpuset_being_rebound;
@@ -1042,7 +1061,8 @@ static int update_relax_domain_level(struct cpuset *cs, s64 val)
if (val != cs->relax_domain_level) {
cs->relax_domain_level = val;
- rebuild_sched_domains();
+ if (!cpus_empty(cs->cpus_allowed) && is_sched_load_balance(cs))
+ rebuild_sched_domains();
}
return 0;
@@ -1254,72 +1274,14 @@ typedef enum {
FILE_SPREAD_SLAB,
} cpuset_filetype_t;
-static ssize_t cpuset_common_file_write(struct cgroup *cont,
- struct cftype *cft,
- struct file *file,
- const char __user *userbuf,
- size_t nbytes, loff_t *unused_ppos)
-{
- struct cpuset *cs = cgroup_cs(cont);
- cpuset_filetype_t type = cft->private;
- char *buffer;
- int retval = 0;
-
- /* Crude upper limit on largest legitimate cpulist user might write. */
- if (nbytes > 100U + 6 * max(NR_CPUS, MAX_NUMNODES))
- return -E2BIG;
-
- /* +1 for nul-terminator */
- buffer = kmalloc(nbytes + 1, GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
-
- if (copy_from_user(buffer, userbuf, nbytes)) {
- retval = -EFAULT;
- goto out1;
- }
- buffer[nbytes] = 0; /* nul-terminate */
-
- cgroup_lock();
-
- if (cgroup_is_removed(cont)) {
- retval = -ENODEV;
- goto out2;
- }
-
- switch (type) {
- case FILE_CPULIST:
- retval = update_cpumask(cs, buffer);
- break;
- case FILE_MEMLIST:
- retval = update_nodemask(cs, buffer);
- break;
- default:
- retval = -EINVAL;
- goto out2;
- }
-
- if (retval == 0)
- retval = nbytes;
-out2:
- cgroup_unlock();
-out1:
- kfree(buffer);
- return retval;
-}
-
static int cpuset_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val)
{
int retval = 0;
struct cpuset *cs = cgroup_cs(cgrp);
cpuset_filetype_t type = cft->private;
- cgroup_lock();
-
- if (cgroup_is_removed(cgrp)) {
- cgroup_unlock();
+ if (!cgroup_lock_live_group(cgrp))
return -ENODEV;
- }
switch (type) {
case FILE_CPU_EXCLUSIVE:
@@ -1365,12 +1327,9 @@ static int cpuset_write_s64(struct cgroup *cgrp, struct cftype *cft, s64 val)
struct cpuset *cs = cgroup_cs(cgrp);
cpuset_filetype_t type = cft->private;
- cgroup_lock();
-
- if (cgroup_is_removed(cgrp)) {
- cgroup_unlock();
+ if (!cgroup_lock_live_group(cgrp))
return -ENODEV;
- }
+
switch (type) {
case FILE_SCHED_RELAX_DOMAIN_LEVEL:
retval = update_relax_domain_level(cs, val);
@@ -1384,6 +1343,32 @@ static int cpuset_write_s64(struct cgroup *cgrp, struct cftype *cft, s64 val)
}
/*
+ * Common handling for a write to a "cpus" or "mems" file.
+ */
+static int cpuset_write_resmask(struct cgroup *cgrp, struct cftype *cft,
+ const char *buf)
+{
+ int retval = 0;
+
+ if (!cgroup_lock_live_group(cgrp))
+ return -ENODEV;
+
+ switch (cft->private) {
+ case FILE_CPULIST:
+ retval = update_cpumask(cgroup_cs(cgrp), buf);
+ break;
+ case FILE_MEMLIST:
+ retval = update_nodemask(cgroup_cs(cgrp), buf);
+ break;
+ default:
+ retval = -EINVAL;
+ break;
+ }
+ cgroup_unlock();
+ return retval;
+}
+
+/*
* These ascii lists should be read in a single call, by using a user
* buffer large enough to hold the entire map. If read in smaller
* chunks, there is no guarantee of atomicity. Since the display format
@@ -1502,14 +1487,16 @@ static struct cftype files[] = {
{
.name = "cpus",
.read = cpuset_common_file_read,
- .write = cpuset_common_file_write,
+ .write_string = cpuset_write_resmask,
+ .max_write_len = (100U + 6 * NR_CPUS),
.private = FILE_CPULIST,
},
{
.name = "mems",
.read = cpuset_common_file_read,
- .write = cpuset_common_file_write,
+ .write_string = cpuset_write_resmask,
+ .max_write_len = (100U + 6 * MAX_NUMNODES),
.private = FILE_MEMLIST,
},
@@ -1790,7 +1777,7 @@ static void move_member_tasks_to_cpuset(struct cpuset *from, struct cpuset *to)
scan.scan.heap = NULL;
scan.to = to->css.cgroup;
- if (cgroup_scan_tasks((struct cgroup_scanner *)&scan))
+ if (cgroup_scan_tasks(&scan.scan))
printk(KERN_ERR "move_member_tasks_to_cpuset: "
"cgroup_scan_tasks failed\n");
}
@@ -1850,6 +1837,7 @@ static void scan_for_empty_cpusets(const struct cpuset *root)
struct cpuset *child; /* scans child cpusets of cp */
struct list_head queue;
struct cgroup *cont;
+ nodemask_t oldmems;
INIT_LIST_HEAD(&queue);
@@ -1869,6 +1857,8 @@ static void scan_for_empty_cpusets(const struct cpuset *root)
nodes_subset(cp->mems_allowed, node_states[N_HIGH_MEMORY]))
continue;
+ oldmems = cp->mems_allowed;
+
/* Remove offline cpus and mems from this cpuset. */
mutex_lock(&callback_mutex);
cpus_and(cp->cpus_allowed, cp->cpus_allowed, cpu_online_map);
@@ -1880,6 +1870,10 @@ static void scan_for_empty_cpusets(const struct cpuset *root)
if (cpus_empty(cp->cpus_allowed) ||
nodes_empty(cp->mems_allowed))
remove_tasks_in_empty_cpuset(cp);
+ else {
+ update_tasks_cpumask(cp);
+ update_tasks_nodemask(cp, &oldmems);
+ }
}
}
@@ -1972,7 +1966,6 @@ void __init cpuset_init_smp(void)
}
/**
-
* cpuset_cpus_allowed - return cpus_allowed mask from a tasks cpuset.
* @tsk: pointer to task_struct from which to obtain cpuset->cpus_allowed.
* @pmask: pointer to cpumask_t variable to receive cpus_allowed set.
diff --git a/kernel/delayacct.c b/kernel/delayacct.c
index 10e43fd8b72..b3179dad71b 100644
--- a/kernel/delayacct.c
+++ b/kernel/delayacct.c
@@ -145,8 +145,11 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
d->blkio_delay_total = (tmp < d->blkio_delay_total) ? 0 : tmp;
tmp = d->swapin_delay_total + tsk->delays->swapin_delay;
d->swapin_delay_total = (tmp < d->swapin_delay_total) ? 0 : tmp;
+ tmp = d->freepages_delay_total + tsk->delays->freepages_delay;
+ d->freepages_delay_total = (tmp < d->freepages_delay_total) ? 0 : tmp;
d->blkio_count += tsk->delays->blkio_count;
d->swapin_count += tsk->delays->swapin_count;
+ d->freepages_count += tsk->delays->freepages_count;
spin_unlock_irqrestore(&tsk->delays->lock, flags);
done:
@@ -165,3 +168,16 @@ __u64 __delayacct_blkio_ticks(struct task_struct *tsk)
return ret;
}
+void __delayacct_freepages_start(void)
+{
+ delayacct_start(&current->delays->freepages_start);
+}
+
+void __delayacct_freepages_end(void)
+{
+ delayacct_end(&current->delays->freepages_start,
+ &current->delays->freepages_end,
+ &current->delays->freepages_delay,
+ &current->delays->freepages_count);
+}
+
diff --git a/kernel/exec_domain.c b/kernel/exec_domain.c
index a9e6bad9f70..c1ef192aa65 100644
--- a/kernel/exec_domain.c
+++ b/kernel/exec_domain.c
@@ -65,7 +65,7 @@ lookup_exec_domain(u_long personality)
goto out;
}
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
read_unlock(&exec_domains_lock);
request_module("personality-%ld", pers);
read_lock(&exec_domains_lock);
diff --git a/kernel/exit.c b/kernel/exit.c
index 93d2711b938..ad933bb29ec 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -85,7 +85,6 @@ static void __exit_signal(struct task_struct *tsk)
BUG_ON(!sig);
BUG_ON(!atomic_read(&sig->count));
- rcu_read_lock();
sighand = rcu_dereference(tsk->sighand);
spin_lock(&sighand->siglock);
@@ -121,6 +120,18 @@ static void __exit_signal(struct task_struct *tsk)
sig->nivcsw += tsk->nivcsw;
sig->inblock += task_io_get_inblock(tsk);
sig->oublock += task_io_get_oublock(tsk);
+#ifdef CONFIG_TASK_XACCT
+ sig->rchar += tsk->rchar;
+ sig->wchar += tsk->wchar;
+ sig->syscr += tsk->syscr;
+ sig->syscw += tsk->syscw;
+#endif /* CONFIG_TASK_XACCT */
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+ sig->ioac.read_bytes += tsk->ioac.read_bytes;
+ sig->ioac.write_bytes += tsk->ioac.write_bytes;
+ sig->ioac.cancelled_write_bytes +=
+ tsk->ioac.cancelled_write_bytes;
+#endif /* CONFIG_TASK_IO_ACCOUNTING */
sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
sig = NULL; /* Marker for below. */
}
@@ -136,7 +147,6 @@ static void __exit_signal(struct task_struct *tsk)
tsk->signal = NULL;
tsk->sighand = NULL;
spin_unlock(&sighand->siglock);
- rcu_read_unlock();
__cleanup_sighand(sighand);
clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
@@ -432,7 +442,7 @@ void daemonize(const char *name, ...)
* We don't want to have TIF_FREEZE set if the system-wide hibernation
* or suspend transition begins right now.
*/
- current->flags |= PF_NOFREEZE;
+ current->flags |= (PF_NOFREEZE | PF_KTHREAD);
if (current->nsproxy != &init_nsproxy) {
get_nsproxy(&init_nsproxy);
@@ -666,26 +676,40 @@ assign_new_owner:
static void exit_mm(struct task_struct * tsk)
{
struct mm_struct *mm = tsk->mm;
+ struct core_state *core_state;
mm_release(tsk, mm);
if (!mm)
return;
/*
* Serialize with any possible pending coredump.
- * We must hold mmap_sem around checking core_waiters
+ * We must hold mmap_sem around checking core_state
* and clearing tsk->mm. The core-inducing thread
- * will increment core_waiters for each thread in the
+ * will increment ->nr_threads for each thread in the
* group with ->mm != NULL.
*/
down_read(&mm->mmap_sem);
- if (mm->core_waiters) {
+ core_state = mm->core_state;
+ if (core_state) {
+ struct core_thread self;
up_read(&mm->mmap_sem);
- down_write(&mm->mmap_sem);
- if (!--mm->core_waiters)
- complete(mm->core_startup_done);
- up_write(&mm->mmap_sem);
- wait_for_completion(&mm->core_done);
+ self.task = tsk;
+ self.next = xchg(&core_state->dumper.next, &self);
+ /*
+ * Implies mb(), the result of xchg() must be visible
+ * to core_state->dumper.
+ */
+ if (atomic_dec_and_test(&core_state->nr_threads))
+ complete(&core_state->startup);
+
+ for (;;) {
+ set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+ if (!self.task) /* see coredump_finish() */
+ break;
+ schedule();
+ }
+ __set_task_state(tsk, TASK_RUNNING);
down_read(&mm->mmap_sem);
}
atomic_inc(&mm->mm_count);
@@ -1354,6 +1378,21 @@ static int wait_task_zombie(struct task_struct *p, int options,
psig->coublock +=
task_io_get_oublock(p) +
sig->oublock + sig->coublock;
+#ifdef CONFIG_TASK_XACCT
+ psig->rchar += p->rchar + sig->rchar;
+ psig->wchar += p->wchar + sig->wchar;
+ psig->syscr += p->syscr + sig->syscr;
+ psig->syscw += p->syscw + sig->syscw;
+#endif /* CONFIG_TASK_XACCT */
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+ psig->ioac.read_bytes +=
+ p->ioac.read_bytes + sig->ioac.read_bytes;
+ psig->ioac.write_bytes +=
+ p->ioac.write_bytes + sig->ioac.write_bytes;
+ psig->ioac.cancelled_write_bytes +=
+ p->ioac.cancelled_write_bytes +
+ sig->ioac.cancelled_write_bytes;
+#endif /* CONFIG_TASK_IO_ACCOUNTING */
spin_unlock_irq(&p->parent->sighand->siglock);
}
diff --git a/kernel/fork.c b/kernel/fork.c
index adefc1131f2..b99d73e971a 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -33,6 +33,7 @@
#include <linux/cpu.h>
#include <linux/cgroup.h>
#include <linux/security.h>
+#include <linux/hugetlb.h>
#include <linux/swap.h>
#include <linux/syscalls.h>
#include <linux/jiffies.h>
@@ -92,6 +93,23 @@ int nr_processes(void)
static struct kmem_cache *task_struct_cachep;
#endif
+#ifndef __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+static inline struct thread_info *alloc_thread_info(struct task_struct *tsk)
+{
+#ifdef CONFIG_DEBUG_STACK_USAGE
+ gfp_t mask = GFP_KERNEL | __GFP_ZERO;
+#else
+ gfp_t mask = GFP_KERNEL;
+#endif
+ return (struct thread_info *)__get_free_pages(mask, THREAD_SIZE_ORDER);
+}
+
+static inline void free_thread_info(struct thread_info *ti)
+{
+ free_pages((unsigned long)ti, THREAD_SIZE_ORDER);
+}
+#endif
+
/* SLAB cache for signal_struct structures (tsk->signal) */
static struct kmem_cache *signal_cachep;
@@ -307,6 +325,14 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
}
/*
+ * Clear hugetlb-related page reserves for children. This only
+ * affects MAP_PRIVATE mappings. Faults generated by the child
+ * are not guaranteed to succeed, even if read-only
+ */
+ if (is_vm_hugetlb_page(tmp))
+ reset_vma_resv_huge_pages(tmp);
+
+ /*
* Link in the new vma and copy the page table entries.
*/
*pprev = tmp;
@@ -374,7 +400,7 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
INIT_LIST_HEAD(&mm->mmlist);
mm->flags = (current->mm) ? current->mm->flags
: MMF_DUMP_FILTER_DEFAULT;
- mm->core_waiters = 0;
+ mm->core_state = NULL;
mm->nr_ptes = 0;
set_mm_counter(mm, file_rss, 0);
set_mm_counter(mm, anon_rss, 0);
@@ -448,7 +474,7 @@ EXPORT_SYMBOL_GPL(mmput);
/**
* get_task_mm - acquire a reference to the task's mm
*
- * Returns %NULL if the task has no mm. Checks PF_BORROWED_MM (meaning
+ * Returns %NULL if the task has no mm. Checks PF_KTHREAD (meaning
* this kernel workthread has transiently adopted a user mm with use_mm,
* to do its AIO) is not set and if so returns a reference to it, after
* bumping up the use count. User must release the mm via mmput()
@@ -461,7 +487,7 @@ struct mm_struct *get_task_mm(struct task_struct *task)
task_lock(task);
mm = task->mm;
if (mm) {
- if (task->flags & PF_BORROWED_MM)
+ if (task->flags & PF_KTHREAD)
mm = NULL;
else
atomic_inc(&mm->mm_users);
@@ -786,6 +812,12 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0;
+#ifdef CONFIG_TASK_XACCT
+ sig->rchar = sig->wchar = sig->syscr = sig->syscw = 0;
+#endif
+#ifdef CONFIG_TASK_IO_ACCOUNTING
+ memset(&sig->ioac, 0, sizeof(sig->ioac));
+#endif
sig->sum_sched_runtime = 0;
INIT_LIST_HEAD(&sig->cpu_timers[0]);
INIT_LIST_HEAD(&sig->cpu_timers[1]);
@@ -1081,6 +1113,12 @@ static struct task_struct *copy_process(unsigned long clone_flags,
if (clone_flags & CLONE_THREAD)
p->tgid = current->tgid;
+ if (current->nsproxy != p->nsproxy) {
+ retval = ns_cgroup_clone(p, pid);
+ if (retval)
+ goto bad_fork_free_pid;
+ }
+
p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
/*
* Clear TID on mm_release()?
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 77a51be3601..f8914b92b66 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -217,6 +217,17 @@ void enable_irq(unsigned int irq)
}
EXPORT_SYMBOL(enable_irq);
+int set_irq_wake_real(unsigned int irq, unsigned int on)
+{
+ struct irq_desc *desc = irq_desc + irq;
+ int ret = -ENXIO;
+
+ if (desc->chip->set_wake)
+ ret = desc->chip->set_wake(irq, on);
+
+ return ret;
+}
+
/**
* set_irq_wake - control irq power management wakeup
* @irq: interrupt to control
@@ -233,30 +244,32 @@ 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;
+ int ret = 0;
/* 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 (on) {
- if (desc->wake_depth++ == 0)
- desc->status |= IRQ_WAKEUP;
- else
- set_wake = NULL;
+ if (desc->wake_depth++ == 0) {
+ ret = set_irq_wake_real(irq, on);
+ if (ret)
+ desc->wake_depth = 0;
+ else
+ desc->status |= IRQ_WAKEUP;
+ }
} 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;
+ WARN(1, "Unbalanced IRQ %d wake disable\n", irq);
+ } else if (--desc->wake_depth == 0) {
+ ret = set_irq_wake_real(irq, on);
+ if (ret)
+ desc->wake_depth = 1;
+ else
+ desc->status &= ~IRQ_WAKEUP;
+ }
}
- if (set_wake)
- ret = desc->chip->set_wake(irq, on);
+
spin_unlock_irqrestore(&desc->lock, flags);
return ret;
}
@@ -293,6 +306,30 @@ void compat_irq_chip_set_default_handler(struct irq_desc *desc)
desc->handle_irq = NULL;
}
+static int __irq_set_trigger(struct irq_chip *chip, unsigned int irq,
+ unsigned long flags)
+{
+ int ret;
+
+ if (!chip || !chip->set_type) {
+ /*
+ * IRQF_TRIGGER_* but the PIC does not support multiple
+ * flow-types?
+ */
+ pr_warning("No set_type function for IRQ %d (%s)\n", irq,
+ chip ? (chip->name ? : "unknown") : "unknown");
+ return 0;
+ }
+
+ ret = chip->set_type(irq, flags & IRQF_TRIGGER_MASK);
+
+ if (ret)
+ pr_err("setting flow type for irq %u failed (%pF)\n",
+ irq, chip->set_type);
+
+ return ret;
+}
+
/*
* Internal function to register an irqaction - typically used to
* allocate special interrupts that are part of the architecture.
@@ -304,6 +341,7 @@ int setup_irq(unsigned int irq, struct irqaction *new)
const char *old_name = NULL;
unsigned long flags;
int shared = 0;
+ int ret;
if (irq >= NR_IRQS)
return -EINVAL;
@@ -361,35 +399,23 @@ int setup_irq(unsigned int irq, struct irqaction *new)
shared = 1;
}
- *p = new;
-
- /* Exclude IRQ from balancing */
- if (new->flags & IRQF_NOBALANCING)
- desc->status |= IRQ_NO_BALANCING;
-
if (!shared) {
irq_chip_set_defaults(desc->chip);
-#if defined(CONFIG_IRQ_PER_CPU)
- if (new->flags & IRQF_PERCPU)
- desc->status |= IRQ_PER_CPU;
-#endif
-
/* Setup the type (level, edge polarity) if configured: */
if (new->flags & IRQF_TRIGGER_MASK) {
- if (desc->chip->set_type)
- desc->chip->set_type(irq,
- new->flags & IRQF_TRIGGER_MASK);
- else
- /*
- * IRQF_TRIGGER_* but the PIC does not support
- * multiple flow-types?
- */
- printk(KERN_WARNING "No IRQF_TRIGGER set_type "
- "function for IRQ %d (%s)\n", irq,
- desc->chip->name);
+ ret = __irq_set_trigger(desc->chip, irq, new->flags);
+
+ if (ret) {
+ spin_unlock_irqrestore(&desc->lock, flags);
+ return ret;
+ }
} else
compat_irq_chip_set_default_handler(desc);
+#if defined(CONFIG_IRQ_PER_CPU)
+ if (new->flags & IRQF_PERCPU)
+ desc->status |= IRQ_PER_CPU;
+#endif
desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING |
IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED);
@@ -408,6 +434,13 @@ int setup_irq(unsigned int irq, struct irqaction *new)
/* Set default affinity mask once everything is setup */
irq_select_affinity(irq);
}
+
+ *p = new;
+
+ /* Exclude IRQ from balancing */
+ if (new->flags & IRQF_NOBALANCING)
+ desc->status |= IRQ_NO_BALANCING;
+
/* Reset broken irq detection when installing new handler */
desc->irq_count = 0;
desc->irqs_unhandled = 0;
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 6fc0040f3e3..38fc10ac754 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -176,7 +176,7 @@ static unsigned long get_symbol_pos(unsigned long addr,
high = kallsyms_num_syms;
while (high - low > 1) {
- mid = (low + high) / 2;
+ mid = low + (high - low) / 2;
if (kallsyms_addresses[mid] <= addr)
low = mid;
else
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 8df97d3dfda..2456d1a0bef 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -42,7 +42,7 @@ extern int max_threads;
static struct workqueue_struct *khelper_wq;
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
/*
modprobe_path is set via /proc/sys.
@@ -352,16 +352,17 @@ static inline void register_pm_notifier_callback(void) {}
* @path: path to usermode executable
* @argv: arg vector for process
* @envp: environment for process
+ * @gfp_mask: gfp mask for memory allocation
*
* Returns either %NULL on allocation failure, or a subprocess_info
* structure. This should be passed to call_usermodehelper_exec to
* exec the process and free the structure.
*/
-struct subprocess_info *call_usermodehelper_setup(char *path,
- char **argv, char **envp)
+struct subprocess_info *call_usermodehelper_setup(char *path, char **argv,
+ char **envp, gfp_t gfp_mask)
{
struct subprocess_info *sub_info;
- sub_info = kzalloc(sizeof(struct subprocess_info), GFP_ATOMIC);
+ sub_info = kzalloc(sizeof(struct subprocess_info), gfp_mask);
if (!sub_info)
goto out;
@@ -417,12 +418,12 @@ int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info,
{
struct file *f;
- f = create_write_pipe();
+ f = create_write_pipe(0);
if (IS_ERR(f))
return PTR_ERR(f);
*filp = f;
- f = create_read_pipe(f);
+ f = create_read_pipe(f, 0);
if (IS_ERR(f)) {
free_write_pipe(*filp);
return PTR_ERR(f);
@@ -494,7 +495,7 @@ int call_usermodehelper_pipe(char *path, char **argv, char **envp,
struct subprocess_info *sub_info;
int ret;
- sub_info = call_usermodehelper_setup(path, argv, envp);
+ sub_info = call_usermodehelper_setup(path, argv, envp, GFP_KERNEL);
if (sub_info == NULL)
return -ENOMEM;
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 1485ca8d0e0..75bc2cd9ebc 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -62,6 +62,7 @@
addr = ((kprobe_opcode_t *)(kallsyms_lookup_name(name)))
#endif
+static int kprobes_initialized;
static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
@@ -69,8 +70,15 @@ static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
static bool kprobe_enabled;
DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */
-DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */
static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
+static struct {
+ spinlock_t lock ____cacheline_aligned;
+} kretprobe_table_locks[KPROBE_TABLE_SIZE];
+
+static spinlock_t *kretprobe_table_lock_ptr(unsigned long hash)
+{
+ return &(kretprobe_table_locks[hash].lock);
+}
/*
* Normally, functions that we'd want to prohibit kprobes in, are marked
@@ -368,26 +376,53 @@ void __kprobes kprobes_inc_nmissed_count(struct kprobe *p)
return;
}
-/* Called with kretprobe_lock held */
void __kprobes recycle_rp_inst(struct kretprobe_instance *ri,
struct hlist_head *head)
{
+ struct kretprobe *rp = ri->rp;
+
/* remove rp inst off the rprobe_inst_table */
hlist_del(&ri->hlist);
- if (ri->rp) {
- /* remove rp inst off the used list */
- hlist_del(&ri->uflist);
- /* put rp inst back onto the free list */
- INIT_HLIST_NODE(&ri->uflist);
- hlist_add_head(&ri->uflist, &ri->rp->free_instances);
+ INIT_HLIST_NODE(&ri->hlist);
+ if (likely(rp)) {
+ spin_lock(&rp->lock);
+ hlist_add_head(&ri->hlist, &rp->free_instances);
+ spin_unlock(&rp->lock);
} else
/* Unregistering */
hlist_add_head(&ri->hlist, head);
}
-struct hlist_head __kprobes *kretprobe_inst_table_head(struct task_struct *tsk)
+void kretprobe_hash_lock(struct task_struct *tsk,
+ struct hlist_head **head, unsigned long *flags)
{
- return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)];
+ unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS);
+ spinlock_t *hlist_lock;
+
+ *head = &kretprobe_inst_table[hash];
+ hlist_lock = kretprobe_table_lock_ptr(hash);
+ spin_lock_irqsave(hlist_lock, *flags);
+}
+
+void kretprobe_table_lock(unsigned long hash, unsigned long *flags)
+{
+ spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash);
+ spin_lock_irqsave(hlist_lock, *flags);
+}
+
+void kretprobe_hash_unlock(struct task_struct *tsk, unsigned long *flags)
+{
+ unsigned long hash = hash_ptr(tsk, KPROBE_HASH_BITS);
+ spinlock_t *hlist_lock;
+
+ hlist_lock = kretprobe_table_lock_ptr(hash);
+ spin_unlock_irqrestore(hlist_lock, *flags);
+}
+
+void kretprobe_table_unlock(unsigned long hash, unsigned long *flags)
+{
+ spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash);
+ spin_unlock_irqrestore(hlist_lock, *flags);
}
/*
@@ -401,17 +436,21 @@ void __kprobes kprobe_flush_task(struct task_struct *tk)
struct kretprobe_instance *ri;
struct hlist_head *head, empty_rp;
struct hlist_node *node, *tmp;
- unsigned long flags = 0;
+ unsigned long hash, flags = 0;
- INIT_HLIST_HEAD(&empty_rp);
- spin_lock_irqsave(&kretprobe_lock, flags);
- head = kretprobe_inst_table_head(tk);
+ if (unlikely(!kprobes_initialized))
+ /* Early boot. kretprobe_table_locks not yet initialized. */
+ return;
+
+ hash = hash_ptr(tk, KPROBE_HASH_BITS);
+ head = &kretprobe_inst_table[hash];
+ kretprobe_table_lock(hash, &flags);
hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
if (ri->task == tk)
recycle_rp_inst(ri, &empty_rp);
}
- spin_unlock_irqrestore(&kretprobe_lock, flags);
-
+ kretprobe_table_unlock(hash, &flags);
+ INIT_HLIST_HEAD(&empty_rp);
hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
hlist_del(&ri->hlist);
kfree(ri);
@@ -423,24 +462,29 @@ static inline void free_rp_inst(struct kretprobe *rp)
struct kretprobe_instance *ri;
struct hlist_node *pos, *next;
- hlist_for_each_entry_safe(ri, pos, next, &rp->free_instances, uflist) {
- hlist_del(&ri->uflist);
+ hlist_for_each_entry_safe(ri, pos, next, &rp->free_instances, hlist) {
+ hlist_del(&ri->hlist);
kfree(ri);
}
}
static void __kprobes cleanup_rp_inst(struct kretprobe *rp)
{
- unsigned long flags;
+ unsigned long flags, hash;
struct kretprobe_instance *ri;
struct hlist_node *pos, *next;
+ struct hlist_head *head;
+
/* No race here */
- spin_lock_irqsave(&kretprobe_lock, flags);
- hlist_for_each_entry_safe(ri, pos, next, &rp->used_instances, uflist) {
- ri->rp = NULL;
- hlist_del(&ri->uflist);
+ for (hash = 0; hash < KPROBE_TABLE_SIZE; hash++) {
+ kretprobe_table_lock(hash, &flags);
+ head = &kretprobe_inst_table[hash];
+ hlist_for_each_entry_safe(ri, pos, next, head, hlist) {
+ if (ri->rp == rp)
+ ri->rp = NULL;
+ }
+ kretprobe_table_unlock(hash, &flags);
}
- spin_unlock_irqrestore(&kretprobe_lock, flags);
free_rp_inst(rp);
}
@@ -831,32 +875,37 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p,
struct pt_regs *regs)
{
struct kretprobe *rp = container_of(p, struct kretprobe, kp);
- unsigned long flags = 0;
+ unsigned long hash, flags = 0;
+ struct kretprobe_instance *ri;
/*TODO: consider to only swap the RA after the last pre_handler fired */
- spin_lock_irqsave(&kretprobe_lock, flags);
+ hash = hash_ptr(current, KPROBE_HASH_BITS);
+ spin_lock_irqsave(&rp->lock, flags);
if (!hlist_empty(&rp->free_instances)) {
- struct kretprobe_instance *ri;
-
ri = hlist_entry(rp->free_instances.first,
- struct kretprobe_instance, uflist);
+ struct kretprobe_instance, hlist);
+ hlist_del(&ri->hlist);
+ spin_unlock_irqrestore(&rp->lock, flags);
+
ri->rp = rp;
ri->task = current;
if (rp->entry_handler && rp->entry_handler(ri, regs)) {
- spin_unlock_irqrestore(&kretprobe_lock, flags);
+ spin_unlock_irqrestore(&rp->lock, flags);
return 0;
}
arch_prepare_kretprobe(ri, regs);
/* XXX(hch): why is there no hlist_move_head? */
- hlist_del(&ri->uflist);
- hlist_add_head(&ri->uflist, &ri->rp->used_instances);
- hlist_add_head(&ri->hlist, kretprobe_inst_table_head(ri->task));
- } else
+ INIT_HLIST_NODE(&ri->hlist);
+ kretprobe_table_lock(hash, &flags);
+ hlist_add_head(&ri->hlist, &kretprobe_inst_table[hash]);
+ kretprobe_table_unlock(hash, &flags);
+ } else {
rp->nmissed++;
- spin_unlock_irqrestore(&kretprobe_lock, flags);
+ spin_unlock_irqrestore(&rp->lock, flags);
+ }
return 0;
}
@@ -892,7 +941,7 @@ static int __kprobes __register_kretprobe(struct kretprobe *rp,
rp->maxactive = NR_CPUS;
#endif
}
- INIT_HLIST_HEAD(&rp->used_instances);
+ spin_lock_init(&rp->lock);
INIT_HLIST_HEAD(&rp->free_instances);
for (i = 0; i < rp->maxactive; i++) {
inst = kmalloc(sizeof(struct kretprobe_instance) +
@@ -901,8 +950,8 @@ static int __kprobes __register_kretprobe(struct kretprobe *rp,
free_rp_inst(rp);
return -ENOMEM;
}
- INIT_HLIST_NODE(&inst->uflist);
- hlist_add_head(&inst->uflist, &rp->free_instances);
+ INIT_HLIST_NODE(&inst->hlist);
+ hlist_add_head(&inst->hlist, &rp->free_instances);
}
rp->nmissed = 0;
@@ -1009,6 +1058,7 @@ static int __init init_kprobes(void)
for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
INIT_HLIST_HEAD(&kprobe_table[i]);
INIT_HLIST_HEAD(&kretprobe_inst_table[i]);
+ spin_lock_init(&(kretprobe_table_locks[i].lock));
}
/*
@@ -1050,6 +1100,7 @@ static int __init init_kprobes(void)
err = arch_init_kprobes();
if (!err)
err = register_die_notifier(&kprobe_exceptions_nb);
+ kprobes_initialized = (err == 0);
if (!err)
init_test_probes();
@@ -1286,13 +1337,8 @@ EXPORT_SYMBOL_GPL(register_jprobe);
EXPORT_SYMBOL_GPL(unregister_jprobe);
EXPORT_SYMBOL_GPL(register_jprobes);
EXPORT_SYMBOL_GPL(unregister_jprobes);
-#ifdef CONFIG_KPROBES
EXPORT_SYMBOL_GPL(jprobe_return);
-#endif
-
-#ifdef CONFIG_KPROBES
EXPORT_SYMBOL_GPL(register_kretprobe);
EXPORT_SYMBOL_GPL(unregister_kretprobe);
EXPORT_SYMBOL_GPL(register_kretprobes);
EXPORT_SYMBOL_GPL(unregister_kretprobes);
-#endif
diff --git a/kernel/kthread.c b/kernel/kthread.c
index ac3fb732664..6111c27491b 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -106,7 +106,7 @@ static void create_kthread(struct kthread_create_info *create)
*/
sched_setscheduler(create->result, SCHED_NORMAL, &param);
set_user_nice(create->result, KTHREAD_NICE_LEVEL);
- set_cpus_allowed(create->result, CPU_MASK_ALL);
+ set_cpus_allowed_ptr(create->result, CPU_MASK_ALL_PTR);
}
complete(&create->done);
}
@@ -233,7 +233,7 @@ int kthreadd(void *unused)
set_task_comm(tsk, "kthreadd");
ignore_signals(tsk);
set_user_nice(tsk, KTHREAD_NICE_LEVEL);
- set_cpus_allowed(tsk, CPU_MASK_ALL);
+ set_cpus_allowed_ptr(tsk, CPU_MASK_ALL_PTR);
current->flags |= PF_NOFREEZE | PF_FREEZER_NOSIG;
diff --git a/kernel/marker.c b/kernel/marker.c
index 1abfb923b76..971da531790 100644
--- a/kernel/marker.c
+++ b/kernel/marker.c
@@ -441,7 +441,7 @@ static int remove_marker(const char *name)
hlist_del(&e->hlist);
/* Make sure the call_rcu has been executed */
if (e->rcu_pending)
- rcu_barrier();
+ rcu_barrier_sched();
kfree(e);
return 0;
}
@@ -476,7 +476,7 @@ static int marker_set_format(struct marker_entry **entry, const char *format)
hlist_del(&(*entry)->hlist);
/* Make sure the call_rcu has been executed */
if ((*entry)->rcu_pending)
- rcu_barrier();
+ rcu_barrier_sched();
kfree(*entry);
*entry = e;
trace_mark(core_marker_format, "name %s format %s",
@@ -655,7 +655,7 @@ int marker_probe_register(const char *name, const char *format,
* make sure it's executed now.
*/
if (entry->rcu_pending)
- rcu_barrier();
+ rcu_barrier_sched();
old = marker_entry_add_probe(entry, probe, probe_private);
if (IS_ERR(old)) {
ret = PTR_ERR(old);
@@ -670,10 +670,7 @@ int marker_probe_register(const char *name, const char *format,
entry->rcu_pending = 1;
/* write rcu_pending before calling the RCU callback */
smp_wmb();
-#ifdef CONFIG_PREEMPT_RCU
- synchronize_sched(); /* Until we have the call_rcu_sched() */
-#endif
- call_rcu(&entry->rcu, free_old_closure);
+ call_rcu_sched(&entry->rcu, free_old_closure);
end:
mutex_unlock(&markers_mutex);
return ret;
@@ -704,7 +701,7 @@ int marker_probe_unregister(const char *name,
if (!entry)
goto end;
if (entry->rcu_pending)
- rcu_barrier();
+ rcu_barrier_sched();
old = marker_entry_remove_probe(entry, probe, probe_private);
mutex_unlock(&markers_mutex);
marker_update_probes(); /* may update entry */
@@ -716,10 +713,7 @@ int marker_probe_unregister(const char *name,
entry->rcu_pending = 1;
/* write rcu_pending before calling the RCU callback */
smp_wmb();
-#ifdef CONFIG_PREEMPT_RCU
- synchronize_sched(); /* Until we have the call_rcu_sched() */
-#endif
- call_rcu(&entry->rcu, free_old_closure);
+ call_rcu_sched(&entry->rcu, free_old_closure);
remove_marker(name); /* Ignore busy error message */
ret = 0;
end:
@@ -786,7 +780,7 @@ int marker_probe_unregister_private_data(marker_probe_func *probe,
goto end;
}
if (entry->rcu_pending)
- rcu_barrier();
+ rcu_barrier_sched();
old = marker_entry_remove_probe(entry, NULL, probe_private);
mutex_unlock(&markers_mutex);
marker_update_probes(); /* may update entry */
@@ -797,10 +791,7 @@ int marker_probe_unregister_private_data(marker_probe_func *probe,
entry->rcu_pending = 1;
/* write rcu_pending before calling the RCU callback */
smp_wmb();
-#ifdef CONFIG_PREEMPT_RCU
- synchronize_sched(); /* Until we have the call_rcu_sched() */
-#endif
- call_rcu(&entry->rcu, free_old_closure);
+ call_rcu_sched(&entry->rcu, free_old_closure);
remove_marker(entry->name); /* Ignore busy error message */
end:
mutex_unlock(&markers_mutex);
diff --git a/kernel/module.c b/kernel/module.c
index 5f80478b746..d8b5605132a 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -70,6 +70,9 @@ static DECLARE_WAIT_QUEUE_HEAD(module_wq);
static BLOCKING_NOTIFIER_HEAD(module_notify_list);
+/* Bounds of module allocation, for speeding __module_text_address */
+static unsigned long module_addr_min = -1UL, module_addr_max = 0;
+
int register_module_notifier(struct notifier_block * nb)
{
return blocking_notifier_chain_register(&module_notify_list, nb);
@@ -134,17 +137,19 @@ extern const struct kernel_symbol __start___ksymtab_gpl[];
extern const struct kernel_symbol __stop___ksymtab_gpl[];
extern const struct kernel_symbol __start___ksymtab_gpl_future[];
extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
-extern const struct kernel_symbol __start___ksymtab_unused[];
-extern const struct kernel_symbol __stop___ksymtab_unused[];
-extern const struct kernel_symbol __start___ksymtab_unused_gpl[];
-extern const struct kernel_symbol __stop___ksymtab_unused_gpl[];
extern const struct kernel_symbol __start___ksymtab_gpl_future[];
extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
extern const unsigned long __start___kcrctab[];
extern const unsigned long __start___kcrctab_gpl[];
extern const unsigned long __start___kcrctab_gpl_future[];
+#ifdef CONFIG_UNUSED_SYMBOLS
+extern const struct kernel_symbol __start___ksymtab_unused[];
+extern const struct kernel_symbol __stop___ksymtab_unused[];
+extern const struct kernel_symbol __start___ksymtab_unused_gpl[];
+extern const struct kernel_symbol __stop___ksymtab_unused_gpl[];
extern const unsigned long __start___kcrctab_unused[];
extern const unsigned long __start___kcrctab_unused_gpl[];
+#endif
#ifndef CONFIG_MODVERSIONS
#define symversion(base, idx) NULL
@@ -152,156 +157,186 @@ extern const unsigned long __start___kcrctab_unused_gpl[];
#define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL)
#endif
-/* lookup symbol in given range of kernel_symbols */
-static const struct kernel_symbol *lookup_symbol(const char *name,
- const struct kernel_symbol *start,
- const struct kernel_symbol *stop)
-{
- const struct kernel_symbol *ks = start;
- for (; ks < stop; ks++)
- if (strcmp(ks->name, name) == 0)
- return ks;
- return NULL;
-}
-
-static bool always_ok(bool gplok, bool warn, const char *name)
-{
- return true;
-}
-
-static bool printk_unused_warning(bool gplok, bool warn, const char *name)
-{
- if (warn) {
- printk(KERN_WARNING "Symbol %s is marked as UNUSED, "
- "however this module is using it.\n", name);
- printk(KERN_WARNING
- "This symbol will go away in the future.\n");
- printk(KERN_WARNING
- "Please evalute if this is the right api to use and if "
- "it really is, submit a report the linux kernel "
- "mailinglist together with submitting your code for "
- "inclusion.\n");
- }
- return true;
-}
-
-static bool gpl_only_unused_warning(bool gplok, bool warn, const char *name)
-{
- if (!gplok)
- return false;
- return printk_unused_warning(gplok, warn, name);
-}
-
-static bool gpl_only(bool gplok, bool warn, const char *name)
-{
- return gplok;
-}
-
-static bool warn_if_not_gpl(bool gplok, bool warn, const char *name)
-{
- if (!gplok && warn) {
- printk(KERN_WARNING "Symbol %s is being used "
- "by a non-GPL module, which will not "
- "be allowed in the future\n", name);
- printk(KERN_WARNING "Please see the file "
- "Documentation/feature-removal-schedule.txt "
- "in the kernel source tree for more details.\n");
- }
- return true;
-}
-
struct symsearch {
const struct kernel_symbol *start, *stop;
const unsigned long *crcs;
- bool (*check)(bool gplok, bool warn, const char *name);
+ enum {
+ NOT_GPL_ONLY,
+ GPL_ONLY,
+ WILL_BE_GPL_ONLY,
+ } licence;
+ bool unused;
};
-/* Look through this array of symbol tables for a symbol match which
- * passes the check function. */
-static const struct kernel_symbol *search_symarrays(const struct symsearch *arr,
- unsigned int num,
- const char *name,
- bool gplok,
- bool warn,
- const unsigned long **crc)
+static bool each_symbol_in_section(const struct symsearch *arr,
+ unsigned int arrsize,
+ struct module *owner,
+ bool (*fn)(const struct symsearch *syms,
+ struct module *owner,
+ unsigned int symnum, void *data),
+ void *data)
{
- unsigned int i;
- const struct kernel_symbol *ks;
+ unsigned int i, j;
- for (i = 0; i < num; i++) {
- ks = lookup_symbol(name, arr[i].start, arr[i].stop);
- if (!ks || !arr[i].check(gplok, warn, name))
- continue;
-
- if (crc)
- *crc = symversion(arr[i].crcs, ks - arr[i].start);
- return ks;
+ for (j = 0; j < arrsize; j++) {
+ for (i = 0; i < arr[j].stop - arr[j].start; i++)
+ if (fn(&arr[j], owner, i, data))
+ return true;
}
- return NULL;
+
+ return false;
}
-/* Find a symbol, return value, (optional) crc and (optional) module
- * which owns it */
-static unsigned long find_symbol(const char *name,
- struct module **owner,
- const unsigned long **crc,
- bool gplok,
- bool warn)
+/* Returns true as soon as fn returns true, otherwise false. */
+static bool each_symbol(bool (*fn)(const struct symsearch *arr,
+ struct module *owner,
+ unsigned int symnum, void *data),
+ void *data)
{
struct module *mod;
- const struct kernel_symbol *ks;
const struct symsearch arr[] = {
{ __start___ksymtab, __stop___ksymtab, __start___kcrctab,
- always_ok },
+ NOT_GPL_ONLY, false },
{ __start___ksymtab_gpl, __stop___ksymtab_gpl,
- __start___kcrctab_gpl, gpl_only },
+ __start___kcrctab_gpl,
+ GPL_ONLY, false },
{ __start___ksymtab_gpl_future, __stop___ksymtab_gpl_future,
- __start___kcrctab_gpl_future, warn_if_not_gpl },
+ __start___kcrctab_gpl_future,
+ WILL_BE_GPL_ONLY, false },
+#ifdef CONFIG_UNUSED_SYMBOLS
{ __start___ksymtab_unused, __stop___ksymtab_unused,
- __start___kcrctab_unused, printk_unused_warning },
+ __start___kcrctab_unused,
+ NOT_GPL_ONLY, true },
{ __start___ksymtab_unused_gpl, __stop___ksymtab_unused_gpl,
- __start___kcrctab_unused_gpl, gpl_only_unused_warning },
+ __start___kcrctab_unused_gpl,
+ GPL_ONLY, true },
+#endif
};
- /* Core kernel first. */
- ks = search_symarrays(arr, ARRAY_SIZE(arr), name, gplok, warn, crc);
- if (ks) {
- if (owner)
- *owner = NULL;
- return ks->value;
- }
+ if (each_symbol_in_section(arr, ARRAY_SIZE(arr), NULL, fn, data))
+ return true;
- /* Now try modules. */
list_for_each_entry(mod, &modules, list) {
struct symsearch arr[] = {
{ mod->syms, mod->syms + mod->num_syms, mod->crcs,
- always_ok },
+ NOT_GPL_ONLY, false },
{ mod->gpl_syms, mod->gpl_syms + mod->num_gpl_syms,
- mod->gpl_crcs, gpl_only },
+ mod->gpl_crcs,
+ GPL_ONLY, false },
{ mod->gpl_future_syms,
mod->gpl_future_syms + mod->num_gpl_future_syms,
- mod->gpl_future_crcs, warn_if_not_gpl },
+ mod->gpl_future_crcs,
+ WILL_BE_GPL_ONLY, false },
+#ifdef CONFIG_UNUSED_SYMBOLS
{ mod->unused_syms,
mod->unused_syms + mod->num_unused_syms,
- mod->unused_crcs, printk_unused_warning },
+ mod->unused_crcs,
+ NOT_GPL_ONLY, true },
{ mod->unused_gpl_syms,
mod->unused_gpl_syms + mod->num_unused_gpl_syms,
- mod->unused_gpl_crcs, gpl_only_unused_warning },
+ mod->unused_gpl_crcs,
+ GPL_ONLY, true },
+#endif
};
- ks = search_symarrays(arr, ARRAY_SIZE(arr),
- name, gplok, warn, crc);
- if (ks) {
- if (owner)
- *owner = mod;
- return ks->value;
+ if (each_symbol_in_section(arr, ARRAY_SIZE(arr), mod, fn, data))
+ return true;
+ }
+ return false;
+}
+
+struct find_symbol_arg {
+ /* Input */
+ const char *name;
+ bool gplok;
+ bool warn;
+
+ /* Output */
+ struct module *owner;
+ const unsigned long *crc;
+ unsigned long value;
+};
+
+static bool find_symbol_in_section(const struct symsearch *syms,
+ struct module *owner,
+ unsigned int symnum, void *data)
+{
+ struct find_symbol_arg *fsa = data;
+
+ if (strcmp(syms->start[symnum].name, fsa->name) != 0)
+ return false;
+
+ if (!fsa->gplok) {
+ if (syms->licence == GPL_ONLY)
+ return false;
+ if (syms->licence == WILL_BE_GPL_ONLY && fsa->warn) {
+ printk(KERN_WARNING "Symbol %s is being used "
+ "by a non-GPL module, which will not "
+ "be allowed in the future\n", fsa->name);
+ printk(KERN_WARNING "Please see the file "
+ "Documentation/feature-removal-schedule.txt "
+ "in the kernel source tree for more details.\n");
}
}
+#ifdef CONFIG_UNUSED_SYMBOLS
+ if (syms->unused && fsa->warn) {
+ printk(KERN_WARNING "Symbol %s is marked as UNUSED, "
+ "however this module is using it.\n", fsa->name);
+ printk(KERN_WARNING
+ "This symbol will go away in the future.\n");
+ printk(KERN_WARNING
+ "Please evalute if this is the right api to use and if "
+ "it really is, submit a report the linux kernel "
+ "mailinglist together with submitting your code for "
+ "inclusion.\n");
+ }
+#endif
+
+ fsa->owner = owner;
+ fsa->crc = symversion(syms->crcs, symnum);
+ fsa->value = syms->start[symnum].value;
+ return true;
+}
+
+/* Find a symbol, return value, (optional) crc and (optional) module
+ * which owns it */
+static unsigned long find_symbol(const char *name,
+ struct module **owner,
+ const unsigned long **crc,
+ bool gplok,
+ bool warn)
+{
+ struct find_symbol_arg fsa;
+
+ fsa.name = name;
+ fsa.gplok = gplok;
+ fsa.warn = warn;
+
+ if (each_symbol(find_symbol_in_section, &fsa)) {
+ if (owner)
+ *owner = fsa.owner;
+ if (crc)
+ *crc = fsa.crc;
+ return fsa.value;
+ }
+
DEBUGP("Failed to find symbol %s\n", name);
return -ENOENT;
}
+/* lookup symbol in given range of kernel_symbols */
+static const struct kernel_symbol *lookup_symbol(const char *name,
+ const struct kernel_symbol *start,
+ const struct kernel_symbol *stop)
+{
+ const struct kernel_symbol *ks = start;
+ for (; ks < stop; ks++)
+ if (strcmp(ks->name, name) == 0)
+ return ks;
+ return NULL;
+}
+
/* Search for module by name: must hold module_mutex. */
static struct module *find_module(const char *name)
{
@@ -639,8 +674,8 @@ static int __try_stop_module(void *_sref)
{
struct stopref *sref = _sref;
- /* If it's not unused, quit unless we are told to block. */
- if ((sref->flags & O_NONBLOCK) && module_refcount(sref->mod) != 0) {
+ /* If it's not unused, quit unless we're forcing. */
+ if (module_refcount(sref->mod) != 0) {
if (!(*sref->forced = try_force_unload(sref->flags)))
return -EWOULDBLOCK;
}
@@ -652,9 +687,16 @@ static int __try_stop_module(void *_sref)
static int try_stop_module(struct module *mod, int flags, int *forced)
{
- struct stopref sref = { mod, flags, forced };
+ if (flags & O_NONBLOCK) {
+ struct stopref sref = { mod, flags, forced };
- return stop_machine_run(__try_stop_module, &sref, NR_CPUS);
+ return stop_machine_run(__try_stop_module, &sref, NR_CPUS);
+ } else {
+ /* We don't need to stop the machine for this. */
+ mod->state = MODULE_STATE_GOING;
+ synchronize_sched();
+ return 0;
+ }
}
unsigned int module_refcount(struct module *mod)
@@ -1445,8 +1487,10 @@ static int verify_export_symbols(struct module *mod)
{ mod->syms, mod->num_syms },
{ mod->gpl_syms, mod->num_gpl_syms },
{ mod->gpl_future_syms, mod->num_gpl_future_syms },
+#ifdef CONFIG_UNUSED_SYMBOLS
{ mod->unused_syms, mod->num_unused_syms },
{ mod->unused_gpl_syms, mod->num_unused_gpl_syms },
+#endif
};
for (i = 0; i < ARRAY_SIZE(arr); i++) {
@@ -1526,7 +1570,7 @@ static int simplify_symbols(Elf_Shdr *sechdrs,
}
/* Update size with this section: return offset. */
-static long get_offset(unsigned long *size, Elf_Shdr *sechdr)
+static long get_offset(unsigned int *size, Elf_Shdr *sechdr)
{
long ret;
@@ -1738,6 +1782,20 @@ static inline void add_kallsyms(struct module *mod,
}
#endif /* CONFIG_KALLSYMS */
+static void *module_alloc_update_bounds(unsigned long size)
+{
+ void *ret = module_alloc(size);
+
+ if (ret) {
+ /* Update module bounds. */
+ if ((unsigned long)ret < module_addr_min)
+ module_addr_min = (unsigned long)ret;
+ if ((unsigned long)ret + size > module_addr_max)
+ module_addr_max = (unsigned long)ret + size;
+ }
+ return ret;
+}
+
/* Allocate and load the module: note that size of section 0 is always
zero, and we rely on this for optional sections. */
static struct module *load_module(void __user *umod,
@@ -1764,10 +1822,12 @@ static struct module *load_module(void __user *umod,
unsigned int gplfutureindex;
unsigned int gplfuturecrcindex;
unsigned int unwindex = 0;
+#ifdef CONFIG_UNUSED_SYMBOLS
unsigned int unusedindex;
unsigned int unusedcrcindex;
unsigned int unusedgplindex;
unsigned int unusedgplcrcindex;
+#endif
unsigned int markersindex;
unsigned int markersstringsindex;
struct module *mod;
@@ -1850,13 +1910,15 @@ static struct module *load_module(void __user *umod,
exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab");
gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl");
gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future");
- unusedindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused");
- unusedgplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused_gpl");
crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab");
gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl");
gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future");
+#ifdef CONFIG_UNUSED_SYMBOLS
+ unusedindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused");
+ unusedgplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused_gpl");
unusedcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused");
unusedgplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused_gpl");
+#endif
setupindex = find_sec(hdr, sechdrs, secstrings, "__param");
exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table");
obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm");
@@ -1935,7 +1997,7 @@ static struct module *load_module(void __user *umod,
layout_sections(mod, hdr, sechdrs, secstrings);
/* Do the allocs. */
- ptr = module_alloc(mod->core_size);
+ ptr = module_alloc_update_bounds(mod->core_size);
if (!ptr) {
err = -ENOMEM;
goto free_percpu;
@@ -1943,7 +2005,7 @@ static struct module *load_module(void __user *umod,
memset(ptr, 0, mod->core_size);
mod->module_core = ptr;
- ptr = module_alloc(mod->init_size);
+ ptr = module_alloc_update_bounds(mod->init_size);
if (!ptr && mod->init_size) {
err = -ENOMEM;
goto free_core;
@@ -2018,14 +2080,15 @@ static struct module *load_module(void __user *umod,
mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr;
mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size /
sizeof(*mod->gpl_future_syms);
- mod->num_unused_syms = sechdrs[unusedindex].sh_size /
- sizeof(*mod->unused_syms);
- mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size /
- sizeof(*mod->unused_gpl_syms);
mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr;
if (gplfuturecrcindex)
mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr;
+#ifdef CONFIG_UNUSED_SYMBOLS
+ mod->num_unused_syms = sechdrs[unusedindex].sh_size /
+ sizeof(*mod->unused_syms);
+ mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size /
+ sizeof(*mod->unused_gpl_syms);
mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr;
if (unusedcrcindex)
mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr;
@@ -2033,13 +2096,17 @@ static struct module *load_module(void __user *umod,
if (unusedgplcrcindex)
mod->unused_gpl_crcs
= (void *)sechdrs[unusedgplcrcindex].sh_addr;
+#endif
#ifdef CONFIG_MODVERSIONS
- if ((mod->num_syms && !crcindex) ||
- (mod->num_gpl_syms && !gplcrcindex) ||
- (mod->num_gpl_future_syms && !gplfuturecrcindex) ||
- (mod->num_unused_syms && !unusedcrcindex) ||
- (mod->num_unused_gpl_syms && !unusedgplcrcindex)) {
+ if ((mod->num_syms && !crcindex)
+ || (mod->num_gpl_syms && !gplcrcindex)
+ || (mod->num_gpl_future_syms && !gplfuturecrcindex)
+#ifdef CONFIG_UNUSED_SYMBOLS
+ || (mod->num_unused_syms && !unusedcrcindex)
+ || (mod->num_unused_gpl_syms && !unusedgplcrcindex)
+#endif
+ ) {
printk(KERN_WARNING "%s: No versions for exported symbols.\n", mod->name);
err = try_to_force_load(mod, "nocrc");
if (err)
@@ -2512,7 +2579,7 @@ static int m_show(struct seq_file *m, void *p)
struct module *mod = list_entry(p, struct module, list);
char buf[8];
- seq_printf(m, "%s %lu",
+ seq_printf(m, "%s %u",
mod->name, mod->init_size + mod->core_size);
print_unload_info(m, mod);
@@ -2595,6 +2662,9 @@ struct module *__module_text_address(unsigned long addr)
{
struct module *mod;
+ if (addr < module_addr_min || addr > module_addr_max)
+ return NULL;
+
list_for_each_entry(mod, &modules, list)
if (within(addr, mod->module_init, mod->init_text_size)
|| within(addr, mod->module_core, mod->core_text_size))
diff --git a/kernel/ns_cgroup.c b/kernel/ns_cgroup.c
index 48d7ed6fc3a..43c2111cd54 100644
--- a/kernel/ns_cgroup.c
+++ b/kernel/ns_cgroup.c
@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/cgroup.h>
#include <linux/fs.h>
+#include <linux/proc_fs.h>
#include <linux/slab.h>
#include <linux/nsproxy.h>
@@ -24,9 +25,12 @@ static inline struct ns_cgroup *cgroup_to_ns(
struct ns_cgroup, css);
}
-int ns_cgroup_clone(struct task_struct *task)
+int ns_cgroup_clone(struct task_struct *task, struct pid *pid)
{
- return cgroup_clone(task, &ns_subsys);
+ char name[PROC_NUMBUF];
+
+ snprintf(name, PROC_NUMBUF, "%d", pid_vnr(pid));
+ return cgroup_clone(task, &ns_subsys, name);
}
/*
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index adc785146a1..21575fc46d0 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -157,12 +157,6 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
goto out;
}
- err = ns_cgroup_clone(tsk);
- if (err) {
- put_nsproxy(new_ns);
- goto out;
- }
-
tsk->nsproxy = new_ns;
out:
@@ -209,7 +203,7 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags,
goto out;
}
- err = ns_cgroup_clone(current);
+ err = ns_cgroup_clone(current, task_pid(current));
if (err)
put_nsproxy(*new_nsp);
diff --git a/kernel/panic.c b/kernel/panic.c
index 425567f45b9..12c5a0a6c89 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -318,6 +318,28 @@ void warn_on_slowpath(const char *file, int line)
add_taint(TAINT_WARN);
}
EXPORT_SYMBOL(warn_on_slowpath);
+
+
+void warn_slowpath(const char *file, int line, const char *fmt, ...)
+{
+ va_list args;
+ char function[KSYM_SYMBOL_LEN];
+ unsigned long caller = (unsigned long)__builtin_return_address(0);
+ sprint_symbol(function, caller);
+
+ printk(KERN_WARNING "------------[ cut here ]------------\n");
+ printk(KERN_WARNING "WARNING: at %s:%d %s()\n", file,
+ line, function);
+ va_start(args, fmt);
+ vprintk(fmt, args);
+ va_end(args);
+
+ print_modules();
+ dump_stack();
+ print_oops_end_marker();
+ add_taint(TAINT_WARN);
+}
+EXPORT_SYMBOL(warn_slowpath);
#endif
#ifdef CONFIG_CC_STACKPROTECTOR
diff --git a/kernel/pid.c b/kernel/pid.c
index 30bd5d4b2ac..064e76afa50 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -309,12 +309,6 @@ struct pid *find_vpid(int nr)
}
EXPORT_SYMBOL_GPL(find_vpid);
-struct pid *find_pid(int nr)
-{
- return find_pid_ns(nr, &init_pid_ns);
-}
-EXPORT_SYMBOL_GPL(find_pid);
-
/*
* attach_pid() must be called with the tasklist_lock write-held.
*/
@@ -435,6 +429,7 @@ struct pid *find_get_pid(pid_t nr)
return pid;
}
+EXPORT_SYMBOL_GPL(find_get_pid);
pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns)
{
@@ -482,7 +477,7 @@ EXPORT_SYMBOL(task_session_nr_ns);
/*
* Used by proc to find the first pid that is greater then or equal to nr.
*
- * If there is a pid at nr this function is exactly the same as find_pid.
+ * If there is a pid at nr this function is exactly the same as find_pid_ns.
*/
struct pid *find_ge_pid(int nr, struct pid_namespace *ns)
{
@@ -497,7 +492,6 @@ struct pid *find_ge_pid(int nr, struct pid_namespace *ns)
return pid;
}
-EXPORT_SYMBOL_GPL(find_get_pid);
/*
* The pid hash table is scaled according to the amount of memory in the
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index 98702b4b885..ea567b78d1a 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -12,6 +12,7 @@
#include <linux/pid_namespace.h>
#include <linux/syscalls.h>
#include <linux/err.h>
+#include <linux/acct.h>
#define BITS_PER_PAGE (PAGE_SIZE*8)
@@ -71,7 +72,7 @@ static struct pid_namespace *create_pid_namespace(unsigned int level)
struct pid_namespace *ns;
int i;
- ns = kmem_cache_alloc(pid_ns_cachep, GFP_KERNEL);
+ ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL);
if (ns == NULL)
goto out;
@@ -84,17 +85,13 @@ static struct pid_namespace *create_pid_namespace(unsigned int level)
goto out_free_map;
kref_init(&ns->kref);
- ns->last_pid = 0;
- ns->child_reaper = NULL;
ns->level = level;
set_bit(0, ns->pidmap[0].page);
atomic_set(&ns->pidmap[0].nr_free, BITS_PER_PAGE - 1);
- for (i = 1; i < PIDMAP_ENTRIES; i++) {
- ns->pidmap[i].page = NULL;
+ for (i = 1; i < PIDMAP_ENTRIES; i++)
atomic_set(&ns->pidmap[i].nr_free, BITS_PER_PAGE);
- }
return ns;
@@ -185,6 +182,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
/* Child reaper for the pid namespace is going away */
pid_ns->child_reaper = NULL;
+ acct_exit_ns(pid_ns);
return;
}
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index dbd8398ddb0..9a21681aa80 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -449,9 +449,6 @@ static void release_posix_timer(struct k_itimer *tmr, int it_id_set)
spin_unlock_irqrestore(&idr_lock, flags);
}
sigqueue_free(tmr->sigq);
- if (unlikely(tmr->it_process) &&
- tmr->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
- put_task_struct(tmr->it_process);
kmem_cache_free(posix_timers_cache, tmr);
}
@@ -856,11 +853,10 @@ retry_delete:
* This keeps any tasks waiting on the spin lock from thinking
* they got something (see the lock code above).
*/
- if (timer->it_process) {
- if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
- put_task_struct(timer->it_process);
- timer->it_process = NULL;
- }
+ if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
+ put_task_struct(timer->it_process);
+ timer->it_process = NULL;
+
unlock_timer(timer, flags);
release_posix_timer(timer, IT_ID_SET);
return 0;
@@ -885,11 +881,10 @@ retry_delete:
* This keeps any tasks waiting on the spin lock from thinking
* they got something (see the lock code above).
*/
- if (timer->it_process) {
- if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
- put_task_struct(timer->it_process);
- timer->it_process = NULL;
- }
+ if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
+ put_task_struct(timer->it_process);
+ timer->it_process = NULL;
+
unlock_timer(timer, flags);
release_posix_timer(timer, IT_ID_SET);
}
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 59dfdf1e1d2..dcd165f92a8 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -94,6 +94,17 @@ config SUSPEND
powered and thus its contents are preserved, such as the
suspend-to-RAM state (e.g. the ACPI S3 state).
+config PM_TEST_SUSPEND
+ bool "Test suspend/resume and wakealarm during bootup"
+ depends on SUSPEND && PM_DEBUG && RTC_LIB=y
+ ---help---
+ This option will let you suspend your machine during bootup, and
+ make it wake up a few seconds later using an RTC wakeup alarm.
+ Enable this with a kernel parameter like "test_suspend=mem".
+
+ You probably want to have your system's RTC driver statically
+ linked, ensuring that it's available when this test runs.
+
config SUSPEND_FREEZER
bool "Enable freezer for suspend to RAM/standby" \
if ARCH_WANTS_FREEZER_CONTROL || BROKEN
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 3398f4651aa..95bff23ecda 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -132,6 +132,61 @@ static inline int suspend_test(int level) { return 0; }
#ifdef CONFIG_SUSPEND
+#ifdef CONFIG_PM_TEST_SUSPEND
+
+/*
+ * We test the system suspend code by setting an RTC wakealarm a short
+ * time in the future, then suspending. Suspending the devices won't
+ * normally take long ... some systems only need a few milliseconds.
+ *
+ * The time it takes is system-specific though, so when we test this
+ * during system bootup we allow a LOT of time.
+ */
+#define TEST_SUSPEND_SECONDS 5
+
+static unsigned long suspend_test_start_time;
+
+static void suspend_test_start(void)
+{
+ /* FIXME Use better timebase than "jiffies", ideally a clocksource.
+ * What we want is a hardware counter that will work correctly even
+ * during the irqs-are-off stages of the suspend/resume cycle...
+ */
+ suspend_test_start_time = jiffies;
+}
+
+static void suspend_test_finish(const char *label)
+{
+ long nj = jiffies - suspend_test_start_time;
+ unsigned msec;
+
+ msec = jiffies_to_msecs(abs(nj));
+ pr_info("PM: %s took %d.%03d seconds\n", label,
+ msec / 1000, msec % 1000);
+
+ /* Warning on suspend means the RTC alarm period needs to be
+ * larger -- the system was sooo slooowwww to suspend that the
+ * alarm (should have) fired before the system went to sleep!
+ *
+ * Warning on either suspend or resume also means the system
+ * has some performance issues. The stack dump of a WARN_ON
+ * is more likely to get the right attention than a printk...
+ */
+ WARN_ON(msec > (TEST_SUSPEND_SECONDS * 1000));
+}
+
+#else
+
+static void suspend_test_start(void)
+{
+}
+
+static void suspend_test_finish(const char *label)
+{
+}
+
+#endif
+
/* This is just an arbitrary number */
#define FREE_PAGE_NUMBER (100)
@@ -266,12 +321,13 @@ int suspend_devices_and_enter(suspend_state_t state)
goto Close;
}
suspend_console();
+ suspend_test_start();
error = device_suspend(PMSG_SUSPEND);
if (error) {
printk(KERN_ERR "PM: Some devices failed to suspend\n");
goto Recover_platform;
}
-
+ suspend_test_finish("suspend devices");
if (suspend_test(TEST_DEVICES))
goto Recover_platform;
@@ -293,7 +349,9 @@ int suspend_devices_and_enter(suspend_state_t state)
if (suspend_ops->finish)
suspend_ops->finish();
Resume_devices:
+ suspend_test_start();
device_resume(PMSG_RESUME);
+ suspend_test_finish("resume devices");
resume_console();
Close:
if (suspend_ops->end)
@@ -521,3 +579,137 @@ static int __init pm_init(void)
}
core_initcall(pm_init);
+
+
+#ifdef CONFIG_PM_TEST_SUSPEND
+
+#include <linux/rtc.h>
+
+/*
+ * To test system suspend, we need a hands-off mechanism to resume the
+ * system. RTCs wake alarms are a common self-contained mechanism.
+ */
+
+static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state)
+{
+ static char err_readtime[] __initdata =
+ KERN_ERR "PM: can't read %s time, err %d\n";
+ static char err_wakealarm [] __initdata =
+ KERN_ERR "PM: can't set %s wakealarm, err %d\n";
+ static char err_suspend[] __initdata =
+ KERN_ERR "PM: suspend test failed, error %d\n";
+ static char info_test[] __initdata =
+ KERN_INFO "PM: test RTC wakeup from '%s' suspend\n";
+
+ unsigned long now;
+ struct rtc_wkalrm alm;
+ int status;
+
+ /* this may fail if the RTC hasn't been initialized */
+ status = rtc_read_time(rtc, &alm.time);
+ if (status < 0) {
+ printk(err_readtime, rtc->dev.bus_id, status);
+ return;
+ }
+ rtc_tm_to_time(&alm.time, &now);
+
+ memset(&alm, 0, sizeof alm);
+ rtc_time_to_tm(now + TEST_SUSPEND_SECONDS, &alm.time);
+ alm.enabled = true;
+
+ status = rtc_set_alarm(rtc, &alm);
+ if (status < 0) {
+ printk(err_wakealarm, rtc->dev.bus_id, status);
+ return;
+ }
+
+ if (state == PM_SUSPEND_MEM) {
+ printk(info_test, pm_states[state]);
+ status = pm_suspend(state);
+ if (status == -ENODEV)
+ state = PM_SUSPEND_STANDBY;
+ }
+ if (state == PM_SUSPEND_STANDBY) {
+ printk(info_test, pm_states[state]);
+ status = pm_suspend(state);
+ }
+ if (status < 0)
+ printk(err_suspend, status);
+}
+
+static int __init has_wakealarm(struct device *dev, void *name_ptr)
+{
+ struct rtc_device *candidate = to_rtc_device(dev);
+
+ if (!candidate->ops->set_alarm)
+ return 0;
+ if (!device_may_wakeup(candidate->dev.parent))
+ return 0;
+
+ *(char **)name_ptr = dev->bus_id;
+ return 1;
+}
+
+/*
+ * Kernel options like "test_suspend=mem" force suspend/resume sanity tests
+ * at startup time. They're normally disabled, for faster boot and because
+ * we can't know which states really work on this particular system.
+ */
+static suspend_state_t test_state __initdata = PM_SUSPEND_ON;
+
+static char warn_bad_state[] __initdata =
+ KERN_WARNING "PM: can't test '%s' suspend state\n";
+
+static int __init setup_test_suspend(char *value)
+{
+ unsigned i;
+
+ /* "=mem" ==> "mem" */
+ value++;
+ for (i = 0; i < PM_SUSPEND_MAX; i++) {
+ if (!pm_states[i])
+ continue;
+ if (strcmp(pm_states[i], value) != 0)
+ continue;
+ test_state = (__force suspend_state_t) i;
+ return 0;
+ }
+ printk(warn_bad_state, value);
+ return 0;
+}
+__setup("test_suspend", setup_test_suspend);
+
+static int __init test_suspend(void)
+{
+ static char warn_no_rtc[] __initdata =
+ KERN_WARNING "PM: no wakealarm-capable RTC driver is ready\n";
+
+ char *pony = NULL;
+ struct rtc_device *rtc = NULL;
+
+ /* PM is initialized by now; is that state testable? */
+ if (test_state == PM_SUSPEND_ON)
+ goto done;
+ if (!valid_state(test_state)) {
+ printk(warn_bad_state, pm_states[test_state]);
+ goto done;
+ }
+
+ /* RTCs have initialized by now too ... can we use one? */
+ class_find_device(rtc_class, NULL, &pony, has_wakealarm);
+ if (pony)
+ rtc = rtc_class_open(pony);
+ if (!rtc) {
+ printk(warn_no_rtc);
+ goto done;
+ }
+
+ /* go for it */
+ test_wakealarm(rtc, test_state);
+ rtc_class_close(rtc);
+done:
+ return 0;
+}
+late_initcall(test_suspend);
+
+#endif /* CONFIG_PM_TEST_SUSPEND */
diff --git a/kernel/power/poweroff.c b/kernel/power/poweroff.c
index 678ec736076..72016f05147 100644
--- a/kernel/power/poweroff.c
+++ b/kernel/power/poweroff.c
@@ -10,6 +10,7 @@
#include <linux/pm.h>
#include <linux/workqueue.h>
#include <linux/reboot.h>
+#include <linux/cpumask.h>
/*
* When the user hits Sys-Rq o to power down the machine this is the
@@ -25,7 +26,8 @@ static DECLARE_WORK(poweroff_work, do_poweroff);
static void handle_poweroff(int key, struct tty_struct *tty)
{
- schedule_work(&poweroff_work);
+ /* run sysrq poweroff on boot cpu */
+ schedule_work_on(first_cpu(cpu_online_map), &poweroff_work);
}
static struct sysrq_key_op sysrq_poweroff_op = {
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 5fb87652f21..278946aecaf 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -149,7 +149,7 @@ static int try_to_freeze_tasks(bool sig_only)
unsigned long end_time;
unsigned int todo;
struct timeval start, end;
- s64 elapsed_csecs64;
+ u64 elapsed_csecs64;
unsigned int elapsed_csecs;
do_gettimeofday(&start);
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 5f91a07c4ea..5d2ab836e99 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -205,8 +205,7 @@ static void chain_free(struct chain_allocator *ca, int clear_page_nosave)
* objects. The main list's elements are of type struct zone_bitmap
* and each of them corresonds to one zone. For each zone bitmap
* object there is a list of objects of type struct bm_block that
- * represent each blocks of bit chunks in which information is
- * stored.
+ * represent each blocks of bitmap in which information is stored.
*
* struct memory_bitmap contains a pointer to the main list of zone
* bitmap objects, a struct bm_position used for browsing the bitmap,
@@ -224,26 +223,27 @@ static void chain_free(struct chain_allocator *ca, int clear_page_nosave)
* pfns that correspond to the start and end of the represented zone.
*
* struct bm_block contains a pointer to the memory page in which
- * information is stored (in the form of a block of bit chunks
- * of type unsigned long each). It also contains the pfns that
- * correspond to the start and end of the represented memory area and
- * the number of bit chunks in the block.
+ * information is stored (in the form of a block of bitmap)
+ * It also contains the pfns that correspond to the start and end of
+ * the represented memory area.
*/
#define BM_END_OF_MAP (~0UL)
-#define BM_CHUNKS_PER_BLOCK (PAGE_SIZE / sizeof(long))
-#define BM_BITS_PER_CHUNK (sizeof(long) << 3)
#define BM_BITS_PER_BLOCK (PAGE_SIZE << 3)
struct bm_block {
struct bm_block *next; /* next element of the list */
unsigned long start_pfn; /* pfn represented by the first bit */
unsigned long end_pfn; /* pfn represented by the last bit plus 1 */
- unsigned int size; /* number of bit chunks */
- unsigned long *data; /* chunks of bits representing pages */
+ unsigned long *data; /* bitmap representing pages */
};
+static inline unsigned long bm_block_bits(struct bm_block *bb)
+{
+ return bb->end_pfn - bb->start_pfn;
+}
+
struct zone_bitmap {
struct zone_bitmap *next; /* next element of the list */
unsigned long start_pfn; /* minimal pfn in this zone */
@@ -257,7 +257,6 @@ struct zone_bitmap {
struct bm_position {
struct zone_bitmap *zone_bm;
struct bm_block *block;
- int chunk;
int bit;
};
@@ -272,12 +271,6 @@ struct memory_bitmap {
/* Functions that operate on memory bitmaps */
-static inline void memory_bm_reset_chunk(struct memory_bitmap *bm)
-{
- bm->cur.chunk = 0;
- bm->cur.bit = -1;
-}
-
static void memory_bm_position_reset(struct memory_bitmap *bm)
{
struct zone_bitmap *zone_bm;
@@ -285,7 +278,7 @@ static void memory_bm_position_reset(struct memory_bitmap *bm)
zone_bm = bm->zone_bm_list;
bm->cur.zone_bm = zone_bm;
bm->cur.block = zone_bm->bm_blocks;
- memory_bm_reset_chunk(bm);
+ bm->cur.bit = 0;
}
static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free);
@@ -394,12 +387,10 @@ memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask, int safe_needed)
bb->start_pfn = pfn;
if (nr >= BM_BITS_PER_BLOCK) {
pfn += BM_BITS_PER_BLOCK;
- bb->size = BM_CHUNKS_PER_BLOCK;
nr -= BM_BITS_PER_BLOCK;
} else {
/* This is executed only once in the loop */
pfn += nr;
- bb->size = DIV_ROUND_UP(nr, BM_BITS_PER_CHUNK);
}
bb->end_pfn = pfn;
bb = bb->next;
@@ -478,8 +469,8 @@ static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
}
zone_bm->cur_block = bb;
pfn -= bb->start_pfn;
- *bit_nr = pfn % BM_BITS_PER_CHUNK;
- *addr = bb->data + pfn / BM_BITS_PER_CHUNK;
+ *bit_nr = pfn;
+ *addr = bb->data;
return 0;
}
@@ -528,36 +519,6 @@ static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn)
return test_bit(bit, addr);
}
-/* Two auxiliary functions for memory_bm_next_pfn */
-
-/* Find the first set bit in the given chunk, if there is one */
-
-static inline int next_bit_in_chunk(int bit, unsigned long *chunk_p)
-{
- bit++;
- while (bit < BM_BITS_PER_CHUNK) {
- if (test_bit(bit, chunk_p))
- return bit;
-
- bit++;
- }
- return -1;
-}
-
-/* Find a chunk containing some bits set in given block of bits */
-
-static inline int next_chunk_in_block(int n, struct bm_block *bb)
-{
- n++;
- while (n < bb->size) {
- if (bb->data[n])
- return n;
-
- n++;
- }
- return -1;
-}
-
/**
* memory_bm_next_pfn - find the pfn that corresponds to the next set bit
* in the bitmap @bm. If the pfn cannot be found, BM_END_OF_MAP is
@@ -571,40 +532,33 @@ static unsigned long memory_bm_next_pfn(struct memory_bitmap *bm)
{
struct zone_bitmap *zone_bm;
struct bm_block *bb;
- int chunk;
int bit;
do {
bb = bm->cur.block;
do {
- chunk = bm->cur.chunk;
bit = bm->cur.bit;
- do {
- bit = next_bit_in_chunk(bit, bb->data + chunk);
- if (bit >= 0)
- goto Return_pfn;
-
- chunk = next_chunk_in_block(chunk, bb);
- bit = -1;
- } while (chunk >= 0);
+ bit = find_next_bit(bb->data, bm_block_bits(bb), bit);
+ if (bit < bm_block_bits(bb))
+ goto Return_pfn;
+
bb = bb->next;
bm->cur.block = bb;
- memory_bm_reset_chunk(bm);
+ bm->cur.bit = 0;
} while (bb);
zone_bm = bm->cur.zone_bm->next;
if (zone_bm) {
bm->cur.zone_bm = zone_bm;
bm->cur.block = zone_bm->bm_blocks;
- memory_bm_reset_chunk(bm);
+ bm->cur.bit = 0;
}
} while (zone_bm);
memory_bm_position_reset(bm);
return BM_END_OF_MAP;
Return_pfn:
- bm->cur.chunk = chunk;
- bm->cur.bit = bit;
- return bb->start_pfn + chunk * BM_BITS_PER_CHUNK + bit;
+ bm->cur.bit = bit + 1;
+ return bb->start_pfn + bit;
}
/**
diff --git a/kernel/printk.c b/kernel/printk.c
index 07ad9e7f7a6..a7f7559c5f6 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -933,7 +933,7 @@ void suspend_console(void)
{
if (!console_suspend_enabled)
return;
- printk("Suspending console(s)\n");
+ printk("Suspending console(s) (use no_console_suspend to debug)\n");
acquire_console_sem();
console_suspended = 1;
}
@@ -1308,6 +1308,8 @@ void tty_write_message(struct tty_struct *tty, char *msg)
}
#if defined CONFIG_PRINTK
+
+DEFINE_RATELIMIT_STATE(printk_ratelimit_state, 5 * HZ, 10);
/*
* printk rate limiting, lifted from the networking subsystem.
*
@@ -1315,22 +1317,9 @@ void tty_write_message(struct tty_struct *tty, char *msg)
* every printk_ratelimit_jiffies to make a denial-of-service
* attack impossible.
*/
-int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst)
-{
- return __ratelimit(ratelimit_jiffies, ratelimit_burst);
-}
-EXPORT_SYMBOL(__printk_ratelimit);
-
-/* minimum time in jiffies between messages */
-int printk_ratelimit_jiffies = 5 * HZ;
-
-/* number of messages we send before ratelimiting */
-int printk_ratelimit_burst = 10;
-
int printk_ratelimit(void)
{
- return __printk_ratelimit(printk_ratelimit_jiffies,
- printk_ratelimit_burst);
+ return __ratelimit(&printk_ratelimit_state);
}
EXPORT_SYMBOL(printk_ratelimit);
diff --git a/kernel/profile.c b/kernel/profile.c
index 58926411eb2..cd26bed4cc2 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -112,8 +112,6 @@ void __init profile_init(void)
/* Profile event notifications */
-#ifdef CONFIG_PROFILING
-
static BLOCKING_NOTIFIER_HEAD(task_exit_notifier);
static ATOMIC_NOTIFIER_HEAD(task_free_notifier);
static BLOCKING_NOTIFIER_HEAD(munmap_notifier);
@@ -203,8 +201,6 @@ void unregister_timer_hook(int (*hook)(struct pt_regs *))
}
EXPORT_SYMBOL_GPL(unregister_timer_hook);
-#endif /* CONFIG_PROFILING */
-
#ifdef CONFIG_SMP
/*
diff --git a/kernel/rcuclassic.c b/kernel/rcuclassic.c
index 16eeeaa9d61..6f8696c502f 100644
--- a/kernel/rcuclassic.c
+++ b/kernel/rcuclassic.c
@@ -106,7 +106,7 @@ static void force_quiescent_state(struct rcu_data *rdp,
*/
cpus_and(cpumask, rcp->cpumask, cpu_online_map);
cpu_clear(rdp->cpu, cpumask);
- for_each_cpu_mask(cpu, cpumask)
+ for_each_cpu_mask_nr(cpu, cpumask)
smp_send_reschedule(cpu);
}
}
diff --git a/kernel/rcupreempt.c b/kernel/rcupreempt.c
index 6f62b77d93c..27827931ca0 100644
--- a/kernel/rcupreempt.c
+++ b/kernel/rcupreempt.c
@@ -756,7 +756,7 @@ rcu_try_flip_idle(void)
/* Now ask each CPU for acknowledgement of the flip. */
- for_each_cpu_mask(cpu, rcu_cpu_online_map) {
+ for_each_cpu_mask_nr(cpu, rcu_cpu_online_map) {
per_cpu(rcu_flip_flag, cpu) = rcu_flipped;
dyntick_save_progress_counter(cpu);
}
@@ -774,7 +774,7 @@ rcu_try_flip_waitack(void)
int cpu;
RCU_TRACE_ME(rcupreempt_trace_try_flip_a1);
- for_each_cpu_mask(cpu, rcu_cpu_online_map)
+ for_each_cpu_mask_nr(cpu, rcu_cpu_online_map)
if (rcu_try_flip_waitack_needed(cpu) &&
per_cpu(rcu_flip_flag, cpu) != rcu_flip_seen) {
RCU_TRACE_ME(rcupreempt_trace_try_flip_ae1);
@@ -806,7 +806,7 @@ rcu_try_flip_waitzero(void)
/* Check to see if the sum of the "last" counters is zero. */
RCU_TRACE_ME(rcupreempt_trace_try_flip_z1);
- for_each_cpu_mask(cpu, rcu_cpu_online_map)
+ for_each_cpu_mask_nr(cpu, rcu_cpu_online_map)
sum += RCU_DATA_CPU(cpu)->rcu_flipctr[lastidx];
if (sum != 0) {
RCU_TRACE_ME(rcupreempt_trace_try_flip_ze1);
@@ -821,7 +821,7 @@ rcu_try_flip_waitzero(void)
smp_mb(); /* ^^^^^^^^^^^^ */
/* Call for a memory barrier from each CPU. */
- for_each_cpu_mask(cpu, rcu_cpu_online_map) {
+ for_each_cpu_mask_nr(cpu, rcu_cpu_online_map) {
per_cpu(rcu_mb_flag, cpu) = rcu_mb_needed;
dyntick_save_progress_counter(cpu);
}
@@ -841,7 +841,7 @@ rcu_try_flip_waitmb(void)
int cpu;
RCU_TRACE_ME(rcupreempt_trace_try_flip_m1);
- for_each_cpu_mask(cpu, rcu_cpu_online_map)
+ for_each_cpu_mask_nr(cpu, rcu_cpu_online_map)
if (rcu_try_flip_waitmb_needed(cpu) &&
per_cpu(rcu_mb_flag, cpu) != rcu_mb_done) {
RCU_TRACE_ME(rcupreempt_trace_try_flip_me1);
diff --git a/kernel/res_counter.c b/kernel/res_counter.c
index d3c61b4ebef..f275c8eca77 100644
--- a/kernel/res_counter.c
+++ b/kernel/res_counter.c
@@ -13,6 +13,7 @@
#include <linux/slab.h>
#include <linux/res_counter.h>
#include <linux/uaccess.h>
+#include <linux/mm.h>
void res_counter_init(struct res_counter *counter)
{
@@ -102,44 +103,37 @@ u64 res_counter_read_u64(struct res_counter *counter, int member)
return *res_counter_member(counter, member);
}
-ssize_t res_counter_write(struct res_counter *counter, int member,
- const char __user *userbuf, size_t nbytes, loff_t *pos,
- int (*write_strategy)(char *st_buf, unsigned long long *val))
+int res_counter_memparse_write_strategy(const char *buf,
+ unsigned long long *res)
{
- int ret;
- char *buf, *end;
- unsigned long flags;
- unsigned long long tmp, *val;
-
- buf = kmalloc(nbytes + 1, GFP_KERNEL);
- ret = -ENOMEM;
- if (buf == NULL)
- goto out;
+ char *end;
+ /* FIXME - make memparse() take const char* args */
+ *res = memparse((char *)buf, &end);
+ if (*end != '\0')
+ return -EINVAL;
- buf[nbytes] = '\0';
- ret = -EFAULT;
- if (copy_from_user(buf, userbuf, nbytes))
- goto out_free;
+ *res = PAGE_ALIGN(*res);
+ return 0;
+}
- ret = -EINVAL;
+int res_counter_write(struct res_counter *counter, int member,
+ const char *buf, write_strategy_fn write_strategy)
+{
+ char *end;
+ unsigned long flags;
+ unsigned long long tmp, *val;
- strstrip(buf);
if (write_strategy) {
- if (write_strategy(buf, &tmp)) {
- goto out_free;
- }
+ if (write_strategy(buf, &tmp))
+ return -EINVAL;
} else {
tmp = simple_strtoull(buf, &end, 10);
if (*end != '\0')
- goto out_free;
+ return -EINVAL;
}
spin_lock_irqsave(&counter->lock, flags);
val = res_counter_member(counter, member);
*val = tmp;
spin_unlock_irqrestore(&counter->lock, flags);
- ret = nbytes;
-out_free:
- kfree(buf);
-out:
- return ret;
+ return 0;
}
diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c
index 092e4c620af..a56f629b057 100644
--- a/kernel/rtmutex-tester.c
+++ b/kernel/rtmutex-tester.c
@@ -297,8 +297,8 @@ static int test_func(void *data)
*
* opcode:data
*/
-static ssize_t sysfs_test_command(struct sys_device *dev, const char *buf,
- size_t count)
+static ssize_t sysfs_test_command(struct sys_device *dev, struct sysdev_attribute *attr,
+ const char *buf, size_t count)
{
struct sched_param schedpar;
struct test_thread_data *td;
@@ -360,7 +360,8 @@ static ssize_t sysfs_test_command(struct sys_device *dev, const char *buf,
* @dev: thread to query
* @buf: char buffer to be filled with thread status info
*/
-static ssize_t sysfs_test_status(struct sys_device *dev, char *buf)
+static ssize_t sysfs_test_status(struct sys_device *dev, struct sysdev_attribute *attr,
+ char *buf)
{
struct test_thread_data *td;
struct task_struct *tsk;
diff --git a/kernel/sched.c b/kernel/sched.c
index 99e6d850eca..0047bd9b96a 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -571,8 +571,10 @@ struct rq {
#endif
#ifdef CONFIG_SCHED_HRTICK
- unsigned long hrtick_flags;
- ktime_t hrtick_expire;
+#ifdef CONFIG_SMP
+ int hrtick_csd_pending;
+ struct call_single_data hrtick_csd;
+#endif
struct hrtimer hrtick_timer;
#endif
@@ -983,13 +985,6 @@ static struct rq *this_rq_lock(void)
return rq;
}
-static void __resched_task(struct task_struct *p, int tif_bit);
-
-static inline void resched_task(struct task_struct *p)
-{
- __resched_task(p, TIF_NEED_RESCHED);
-}
-
#ifdef CONFIG_SCHED_HRTICK
/*
* Use HR-timers to deliver accurate preemption points.
@@ -1001,25 +996,6 @@ static inline void resched_task(struct task_struct *p)
* When we get rescheduled we reprogram the hrtick_timer outside of the
* rq->lock.
*/
-static inline void resched_hrt(struct task_struct *p)
-{
- __resched_task(p, TIF_HRTICK_RESCHED);
-}
-
-static inline void resched_rq(struct rq *rq)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&rq->lock, flags);
- resched_task(rq->curr);
- spin_unlock_irqrestore(&rq->lock, flags);
-}
-
-enum {
- HRTICK_SET, /* re-programm hrtick_timer */
- HRTICK_RESET, /* not a new slice */
- HRTICK_BLOCK, /* stop hrtick operations */
-};
/*
* Use hrtick when:
@@ -1030,40 +1006,11 @@ static inline int hrtick_enabled(struct rq *rq)
{
if (!sched_feat(HRTICK))
return 0;
- if (unlikely(test_bit(HRTICK_BLOCK, &rq->hrtick_flags)))
+ if (!cpu_active(cpu_of(rq)))
return 0;
return hrtimer_is_hres_active(&rq->hrtick_timer);
}
-/*
- * Called to set the hrtick timer state.
- *
- * called with rq->lock held and irqs disabled
- */
-static void hrtick_start(struct rq *rq, u64 delay, int reset)
-{
- assert_spin_locked(&rq->lock);
-
- /*
- * preempt at: now + delay
- */
- rq->hrtick_expire =
- ktime_add_ns(rq->hrtick_timer.base->get_time(), delay);
- /*
- * indicate we need to program the timer
- */
- __set_bit(HRTICK_SET, &rq->hrtick_flags);
- if (reset)
- __set_bit(HRTICK_RESET, &rq->hrtick_flags);
-
- /*
- * New slices are called from the schedule path and don't need a
- * forced reschedule.
- */
- if (reset)
- resched_hrt(rq->curr);
-}
-
static void hrtick_clear(struct rq *rq)
{
if (hrtimer_active(&rq->hrtick_timer))
@@ -1071,32 +1018,6 @@ static void hrtick_clear(struct rq *rq)
}
/*
- * Update the timer from the possible pending state.
- */
-static void hrtick_set(struct rq *rq)
-{
- ktime_t time;
- int set, reset;
- unsigned long flags;
-
- WARN_ON_ONCE(cpu_of(rq) != smp_processor_id());
-
- spin_lock_irqsave(&rq->lock, flags);
- set = __test_and_clear_bit(HRTICK_SET, &rq->hrtick_flags);
- reset = __test_and_clear_bit(HRTICK_RESET, &rq->hrtick_flags);
- time = rq->hrtick_expire;
- clear_thread_flag(TIF_HRTICK_RESCHED);
- spin_unlock_irqrestore(&rq->lock, flags);
-
- if (set) {
- hrtimer_start(&rq->hrtick_timer, time, HRTIMER_MODE_ABS);
- if (reset && !hrtimer_active(&rq->hrtick_timer))
- resched_rq(rq);
- } else
- hrtick_clear(rq);
-}
-
-/*
* High-resolution timer tick.
* Runs from hardirq context with interrupts disabled.
*/
@@ -1115,27 +1036,37 @@ static enum hrtimer_restart hrtick(struct hrtimer *timer)
}
#ifdef CONFIG_SMP
-static void hotplug_hrtick_disable(int cpu)
+/*
+ * called from hardirq (IPI) context
+ */
+static void __hrtick_start(void *arg)
{
- struct rq *rq = cpu_rq(cpu);
- unsigned long flags;
+ struct rq *rq = arg;
- spin_lock_irqsave(&rq->lock, flags);
- rq->hrtick_flags = 0;
- __set_bit(HRTICK_BLOCK, &rq->hrtick_flags);
- spin_unlock_irqrestore(&rq->lock, flags);
-
- hrtick_clear(rq);
+ spin_lock(&rq->lock);
+ hrtimer_restart(&rq->hrtick_timer);
+ rq->hrtick_csd_pending = 0;
+ spin_unlock(&rq->lock);
}
-static void hotplug_hrtick_enable(int cpu)
+/*
+ * Called to set the hrtick timer state.
+ *
+ * called with rq->lock held and irqs disabled
+ */
+static void hrtick_start(struct rq *rq, u64 delay)
{
- struct rq *rq = cpu_rq(cpu);
- unsigned long flags;
+ struct hrtimer *timer = &rq->hrtick_timer;
+ ktime_t time = ktime_add_ns(timer->base->get_time(), delay);
- spin_lock_irqsave(&rq->lock, flags);
- __clear_bit(HRTICK_BLOCK, &rq->hrtick_flags);
- spin_unlock_irqrestore(&rq->lock, flags);
+ timer->expires = time;
+
+ if (rq == this_rq()) {
+ hrtimer_restart(timer);
+ } else if (!rq->hrtick_csd_pending) {
+ __smp_call_function_single(cpu_of(rq), &rq->hrtick_csd);
+ rq->hrtick_csd_pending = 1;
+ }
}
static int
@@ -1150,16 +1081,7 @@ hotplug_hrtick(struct notifier_block *nfb, unsigned long action, void *hcpu)
case CPU_DOWN_PREPARE_FROZEN:
case CPU_DEAD:
case CPU_DEAD_FROZEN:
- hotplug_hrtick_disable(cpu);
- return NOTIFY_OK;
-
- case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
- case CPU_DOWN_FAILED:
- case CPU_DOWN_FAILED_FROZEN:
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- hotplug_hrtick_enable(cpu);
+ hrtick_clear(cpu_rq(cpu));
return NOTIFY_OK;
}
@@ -1170,46 +1092,45 @@ static void init_hrtick(void)
{
hotcpu_notifier(hotplug_hrtick, 0);
}
-#endif /* CONFIG_SMP */
+#else
+/*
+ * Called to set the hrtick timer state.
+ *
+ * called with rq->lock held and irqs disabled
+ */
+static void hrtick_start(struct rq *rq, u64 delay)
+{
+ hrtimer_start(&rq->hrtick_timer, ns_to_ktime(delay), HRTIMER_MODE_REL);
+}
-static void init_rq_hrtick(struct rq *rq)
+static void init_hrtick(void)
{
- rq->hrtick_flags = 0;
- hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- rq->hrtick_timer.function = hrtick;
- rq->hrtick_timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ;
}
+#endif /* CONFIG_SMP */
-void hrtick_resched(void)
+static void init_rq_hrtick(struct rq *rq)
{
- struct rq *rq;
- unsigned long flags;
+#ifdef CONFIG_SMP
+ rq->hrtick_csd_pending = 0;
- if (!test_thread_flag(TIF_HRTICK_RESCHED))
- return;
+ rq->hrtick_csd.flags = 0;
+ rq->hrtick_csd.func = __hrtick_start;
+ rq->hrtick_csd.info = rq;
+#endif
- local_irq_save(flags);
- rq = cpu_rq(smp_processor_id());
- hrtick_set(rq);
- local_irq_restore(flags);
+ hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ rq->hrtick_timer.function = hrtick;
+ rq->hrtick_timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ;
}
#else
static inline void hrtick_clear(struct rq *rq)
{
}
-static inline void hrtick_set(struct rq *rq)
-{
-}
-
static inline void init_rq_hrtick(struct rq *rq)
{
}
-void hrtick_resched(void)
-{
-}
-
static inline void init_hrtick(void)
{
}
@@ -1228,16 +1149,16 @@ static inline void init_hrtick(void)
#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
#endif
-static void __resched_task(struct task_struct *p, int tif_bit)
+static void resched_task(struct task_struct *p)
{
int cpu;
assert_spin_locked(&task_rq(p)->lock);
- if (unlikely(test_tsk_thread_flag(p, tif_bit)))
+ if (unlikely(test_tsk_thread_flag(p, TIF_NEED_RESCHED)))
return;
- set_tsk_thread_flag(p, tif_bit);
+ set_tsk_thread_flag(p, TIF_NEED_RESCHED);
cpu = task_cpu(p);
if (cpu == smp_processor_id())
@@ -1303,10 +1224,10 @@ void wake_up_idle_cpu(int cpu)
#endif /* CONFIG_NO_HZ */
#else /* !CONFIG_SMP */
-static void __resched_task(struct task_struct *p, int tif_bit)
+static void resched_task(struct task_struct *p)
{
assert_spin_locked(&task_rq(p)->lock);
- set_tsk_thread_flag(p, tif_bit);
+ set_tsk_need_resched(p);
}
#endif /* CONFIG_SMP */
@@ -2108,7 +2029,7 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu)
/* Tally up the load of all CPUs in the group */
avg_load = 0;
- for_each_cpu_mask(i, group->cpumask) {
+ for_each_cpu_mask_nr(i, group->cpumask) {
/* Bias balancing toward cpus of our domain */
if (local_group)
load = source_load(i, load_idx);
@@ -2150,7 +2071,7 @@ find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu,
/* Traverse only the allowed CPUs */
cpus_and(*tmp, group->cpumask, p->cpus_allowed);
- for_each_cpu_mask(i, *tmp) {
+ for_each_cpu_mask_nr(i, *tmp) {
load = weighted_cpuload(i);
if (load < min_load || (load == min_load && i == this_cpu)) {
@@ -2881,7 +2802,7 @@ static void sched_migrate_task(struct task_struct *p, int dest_cpu)
rq = task_rq_lock(p, &flags);
if (!cpu_isset(dest_cpu, p->cpus_allowed)
- || unlikely(cpu_is_offline(dest_cpu)))
+ || unlikely(!cpu_active(dest_cpu)))
goto out;
/* force the process onto the specified CPU */
@@ -3168,7 +3089,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
max_cpu_load = 0;
min_cpu_load = ~0UL;
- for_each_cpu_mask(i, group->cpumask) {
+ for_each_cpu_mask_nr(i, group->cpumask) {
struct rq *rq;
if (!cpu_isset(i, *cpus))
@@ -3447,7 +3368,7 @@ find_busiest_queue(struct sched_group *group, enum cpu_idle_type idle,
unsigned long max_load = 0;
int i;
- for_each_cpu_mask(i, group->cpumask) {
+ for_each_cpu_mask_nr(i, group->cpumask) {
unsigned long wl;
if (!cpu_isset(i, *cpus))
@@ -3849,7 +3770,7 @@ int select_nohz_load_balancer(int stop_tick)
/*
* If we are going offline and still the leader, give up!
*/
- if (cpu_is_offline(cpu) &&
+ if (!cpu_active(cpu) &&
atomic_read(&nohz.load_balancer) == cpu) {
if (atomic_cmpxchg(&nohz.load_balancer, cpu, -1) != cpu)
BUG();
@@ -3989,7 +3910,7 @@ static void run_rebalance_domains(struct softirq_action *h)
int balance_cpu;
cpu_clear(this_cpu, cpus);
- for_each_cpu_mask(balance_cpu, cpus) {
+ for_each_cpu_mask_nr(balance_cpu, cpus) {
/*
* If this cpu gets work to do, stop the load balancing
* work being done for other cpus. Next load
@@ -4125,6 +4046,8 @@ void account_user_time(struct task_struct *p, cputime_t cputime)
cpustat->nice = cputime64_add(cpustat->nice, tmp);
else
cpustat->user = cputime64_add(cpustat->user, tmp);
+ /* Account for user time used */
+ acct_update_integrals(p);
}
/*
@@ -4395,7 +4318,7 @@ asmlinkage void __sched schedule(void)
struct task_struct *prev, *next;
unsigned long *switch_count;
struct rq *rq;
- int cpu, hrtick = sched_feat(HRTICK);
+ int cpu;
need_resched:
preempt_disable();
@@ -4410,7 +4333,7 @@ need_resched_nonpreemptible:
schedule_debug(prev);
- if (hrtick)
+ if (sched_feat(HRTICK))
hrtick_clear(rq);
/*
@@ -4457,9 +4380,6 @@ need_resched_nonpreemptible:
} else
spin_unlock_irq(&rq->lock);
- if (hrtick)
- hrtick_set(rq);
-
if (unlikely(reacquire_kernel_lock(current) < 0))
goto need_resched_nonpreemptible;
@@ -5876,7 +5796,7 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
struct rq *rq_dest, *rq_src;
int ret = 0, on_rq;
- if (unlikely(cpu_is_offline(dest_cpu)))
+ if (unlikely(!cpu_active(dest_cpu)))
return ret;
rq_src = cpu_rq(src_cpu);
@@ -6768,7 +6688,8 @@ static cpumask_t cpu_isolated_map = CPU_MASK_NONE;
/* Setup the mask of cpus configured for isolated domains */
static int __init isolated_cpu_setup(char *str)
{
- int ints[NR_CPUS], i;
+ static int __initdata ints[NR_CPUS];
+ int i;
str = get_options(str, ARRAY_SIZE(ints), ints);
cpus_clear(cpu_isolated_map);
@@ -6802,7 +6723,7 @@ init_sched_build_groups(const cpumask_t *span, const cpumask_t *cpu_map,
cpus_clear(*covered);
- for_each_cpu_mask(i, *span) {
+ for_each_cpu_mask_nr(i, *span) {
struct sched_group *sg;
int group = group_fn(i, cpu_map, &sg, tmpmask);
int j;
@@ -6813,7 +6734,7 @@ init_sched_build_groups(const cpumask_t *span, const cpumask_t *cpu_map,
cpus_clear(sg->cpumask);
sg->__cpu_power = 0;
- for_each_cpu_mask(j, *span) {
+ for_each_cpu_mask_nr(j, *span) {
if (group_fn(j, cpu_map, NULL, tmpmask) != group)
continue;
@@ -7013,7 +6934,7 @@ static void init_numa_sched_groups_power(struct sched_group *group_head)
if (!sg)
return;
do {
- for_each_cpu_mask(j, sg->cpumask) {
+ for_each_cpu_mask_nr(j, sg->cpumask) {
struct sched_domain *sd;
sd = &per_cpu(phys_domains, j);
@@ -7038,7 +6959,7 @@ static void free_sched_groups(const cpumask_t *cpu_map, cpumask_t *nodemask)
{
int cpu, i;
- for_each_cpu_mask(cpu, *cpu_map) {
+ for_each_cpu_mask_nr(cpu, *cpu_map) {
struct sched_group **sched_group_nodes
= sched_group_nodes_bycpu[cpu];
@@ -7277,7 +7198,7 @@ static int __build_sched_domains(const cpumask_t *cpu_map,
/*
* Set up domains for cpus specified by the cpu_map.
*/
- for_each_cpu_mask(i, *cpu_map) {
+ for_each_cpu_mask_nr(i, *cpu_map) {
struct sched_domain *sd = NULL, *p;
SCHED_CPUMASK_VAR(nodemask, allmasks);
@@ -7344,7 +7265,7 @@ static int __build_sched_domains(const cpumask_t *cpu_map,
#ifdef CONFIG_SCHED_SMT
/* Set up CPU (sibling) groups */
- for_each_cpu_mask(i, *cpu_map) {
+ for_each_cpu_mask_nr(i, *cpu_map) {
SCHED_CPUMASK_VAR(this_sibling_map, allmasks);
SCHED_CPUMASK_VAR(send_covered, allmasks);
@@ -7361,7 +7282,7 @@ static int __build_sched_domains(const cpumask_t *cpu_map,
#ifdef CONFIG_SCHED_MC
/* Set up multi-core groups */
- for_each_cpu_mask(i, *cpu_map) {
+ for_each_cpu_mask_nr(i, *cpu_map) {
SCHED_CPUMASK_VAR(this_core_map, allmasks);
SCHED_CPUMASK_VAR(send_covered, allmasks);
@@ -7428,7 +7349,7 @@ static int __build_sched_domains(const cpumask_t *cpu_map,
goto error;
}
sched_group_nodes[i] = sg;
- for_each_cpu_mask(j, *nodemask) {
+ for_each_cpu_mask_nr(j, *nodemask) {
struct sched_domain *sd;
sd = &per_cpu(node_domains, j);
@@ -7474,21 +7395,21 @@ static int __build_sched_domains(const cpumask_t *cpu_map,
/* Calculate CPU power for physical packages and nodes */
#ifdef CONFIG_SCHED_SMT
- for_each_cpu_mask(i, *cpu_map) {
+ for_each_cpu_mask_nr(i, *cpu_map) {
struct sched_domain *sd = &per_cpu(cpu_domains, i);
init_sched_groups_power(i, sd);
}
#endif
#ifdef CONFIG_SCHED_MC
- for_each_cpu_mask(i, *cpu_map) {
+ for_each_cpu_mask_nr(i, *cpu_map) {
struct sched_domain *sd = &per_cpu(core_domains, i);
init_sched_groups_power(i, sd);
}
#endif
- for_each_cpu_mask(i, *cpu_map) {
+ for_each_cpu_mask_nr(i, *cpu_map) {
struct sched_domain *sd = &per_cpu(phys_domains, i);
init_sched_groups_power(i, sd);
@@ -7508,7 +7429,7 @@ static int __build_sched_domains(const cpumask_t *cpu_map,
#endif
/* Attach the domains */
- for_each_cpu_mask(i, *cpu_map) {
+ for_each_cpu_mask_nr(i, *cpu_map) {
struct sched_domain *sd;
#ifdef CONFIG_SCHED_SMT
sd = &per_cpu(cpu_domains, i);
@@ -7553,18 +7474,6 @@ void __attribute__((weak)) arch_update_cpu_topology(void)
}
/*
- * Free current domain masks.
- * Called after all cpus are attached to NULL domain.
- */
-static void free_sched_domains(void)
-{
- ndoms_cur = 0;
- if (doms_cur != &fallback_doms)
- kfree(doms_cur);
- doms_cur = &fallback_doms;
-}
-
-/*
* Set up scheduler domains and groups. Callers must hold the hotplug lock.
* For now this just excludes isolated cpus, but could be used to
* exclude other special cases in the future.
@@ -7603,7 +7512,7 @@ static void detach_destroy_domains(const cpumask_t *cpu_map)
unregister_sched_domain_sysctl();
- for_each_cpu_mask(i, *cpu_map)
+ for_each_cpu_mask_nr(i, *cpu_map)
cpu_attach_domain(NULL, &def_root_domain, i);
synchronize_sched();
arch_destroy_sched_domains(cpu_map, &tmpmask);
@@ -7642,7 +7551,7 @@ static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur,
* ownership of it and will kfree it when done with it. If the caller
* failed the kmalloc call, then it can pass in doms_new == NULL,
* and partition_sched_domains() will fallback to the single partition
- * 'fallback_doms'.
+ * 'fallback_doms', it also forces the domains to be rebuilt.
*
* Call with hotplug lock held
*/
@@ -7656,12 +7565,8 @@ void partition_sched_domains(int ndoms_new, cpumask_t *doms_new,
/* always unregister in case we don't destroy any domains */
unregister_sched_domain_sysctl();
- if (doms_new == NULL) {
- ndoms_new = 1;
- doms_new = &fallback_doms;
- cpus_andnot(doms_new[0], cpu_online_map, cpu_isolated_map);
- dattr_new = NULL;
- }
+ if (doms_new == NULL)
+ ndoms_new = 0;
/* Destroy deleted domains */
for (i = 0; i < ndoms_cur; i++) {
@@ -7676,6 +7581,14 @@ match1:
;
}
+ if (doms_new == NULL) {
+ ndoms_cur = 0;
+ ndoms_new = 1;
+ doms_new = &fallback_doms;
+ cpus_andnot(doms_new[0], cpu_online_map, cpu_isolated_map);
+ dattr_new = NULL;
+ }
+
/* Build new domains */
for (i = 0; i < ndoms_new; i++) {
for (j = 0; j < ndoms_cur; j++) {
@@ -7706,17 +7619,10 @@ match2:
#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
int arch_reinit_sched_domains(void)
{
- int err;
-
get_online_cpus();
- mutex_lock(&sched_domains_mutex);
- detach_destroy_domains(&cpu_online_map);
- free_sched_domains();
- err = arch_init_sched_domains(&cpu_online_map);
- mutex_unlock(&sched_domains_mutex);
+ rebuild_sched_domains();
put_online_cpus();
-
- return err;
+ return 0;
}
static ssize_t sched_power_savings_store(const char *buf, size_t count, int smt)
@@ -7737,11 +7643,13 @@ static ssize_t sched_power_savings_store(const char *buf, size_t count, int smt)
}
#ifdef CONFIG_SCHED_MC
-static ssize_t sched_mc_power_savings_show(struct sys_device *dev, char *page)
+static ssize_t sched_mc_power_savings_show(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *page)
{
return sprintf(page, "%u\n", sched_mc_power_savings);
}
static ssize_t sched_mc_power_savings_store(struct sys_device *dev,
+ struct sysdev_attribute *attr,
const char *buf, size_t count)
{
return sched_power_savings_store(buf, count, 0);
@@ -7751,11 +7659,13 @@ static SYSDEV_ATTR(sched_mc_power_savings, 0644, sched_mc_power_savings_show,
#endif
#ifdef CONFIG_SCHED_SMT
-static ssize_t sched_smt_power_savings_show(struct sys_device *dev, char *page)
+static ssize_t sched_smt_power_savings_show(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *page)
{
return sprintf(page, "%u\n", sched_smt_power_savings);
}
static ssize_t sched_smt_power_savings_store(struct sys_device *dev,
+ struct sysdev_attribute *attr,
const char *buf, size_t count)
{
return sched_power_savings_store(buf, count, 1);
@@ -7782,59 +7692,49 @@ int sched_create_sysfs_power_savings_entries(struct sysdev_class *cls)
}
#endif /* CONFIG_SCHED_MC || CONFIG_SCHED_SMT */
+#ifndef CONFIG_CPUSETS
/*
- * Force a reinitialization of the sched domains hierarchy. The domains
- * and groups cannot be updated in place without racing with the balancing
- * code, so we temporarily attach all running cpus to the NULL domain
- * which will prevent rebalancing while the sched domains are recalculated.
+ * Add online and remove offline CPUs from the scheduler domains.
+ * When cpusets are enabled they take over this function.
*/
static int update_sched_domains(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
+ switch (action) {
+ case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
+ case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
+ partition_sched_domains(0, NULL, NULL);
+ return NOTIFY_OK;
+
+ default:
+ return NOTIFY_DONE;
+ }
+}
+#endif
+
+static int update_runtime(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
int cpu = (int)(long)hcpu;
switch (action) {
case CPU_DOWN_PREPARE:
case CPU_DOWN_PREPARE_FROZEN:
disable_runtime(cpu_rq(cpu));
- /* fall-through */
- case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
- detach_destroy_domains(&cpu_online_map);
- free_sched_domains();
return NOTIFY_OK;
-
case CPU_DOWN_FAILED:
case CPU_DOWN_FAILED_FROZEN:
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
enable_runtime(cpu_rq(cpu));
- /* fall-through */
- case CPU_UP_CANCELED:
- case CPU_UP_CANCELED_FROZEN:
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- /*
- * Fall through and re-initialise the domains.
- */
- break;
+ return NOTIFY_OK;
+
default:
return NOTIFY_DONE;
}
-
-#ifndef CONFIG_CPUSETS
- /*
- * Create default domain partitioning if cpusets are disabled.
- * Otherwise we let cpusets rebuild the domains based on the
- * current setup.
- */
-
- /* The hotplug lock is already held by cpu_up/cpu_down */
- arch_init_sched_domains(&cpu_online_map);
-#endif
-
- return NOTIFY_OK;
}
void __init sched_init_smp(void)
@@ -7854,8 +7754,15 @@ void __init sched_init_smp(void)
cpu_set(smp_processor_id(), non_isolated_cpus);
mutex_unlock(&sched_domains_mutex);
put_online_cpus();
+
+#ifndef CONFIG_CPUSETS
/* XXX: Theoretical race here - CPU may be hotplugged now */
hotcpu_notifier(update_sched_domains, 0);
+#endif
+
+ /* RT runtime code needs to handle some hotplug events */
+ hotcpu_notifier(update_runtime, 0);
+
init_hrtick();
/* Move init over to a non-isolated CPU */
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index f2aa987027d..cf2cd6ce4cb 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -878,7 +878,6 @@ entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued)
#ifdef CONFIG_SCHED_HRTICK
static void hrtick_start_fair(struct rq *rq, struct task_struct *p)
{
- int requeue = rq->curr == p;
struct sched_entity *se = &p->se;
struct cfs_rq *cfs_rq = cfs_rq_of(se);
@@ -899,10 +898,10 @@ static void hrtick_start_fair(struct rq *rq, struct task_struct *p)
* Don't schedule slices shorter than 10000ns, that just
* doesn't make sense. Rely on vruntime for fairness.
*/
- if (!requeue)
+ if (rq->curr != p)
delta = max(10000LL, delta);
- hrtick_start(rq, delta, requeue);
+ hrtick_start(rq, delta);
}
}
#else /* !CONFIG_SCHED_HRTICK */
@@ -1004,6 +1003,8 @@ static void yield_task_fair(struct rq *rq)
* not idle and an idle cpu is available. The span of cpus to
* search starts with cpus closest then further out as needed,
* so we always favor a closer, idle cpu.
+ * Domains may include CPUs that are not usable for migration,
+ * hence we need to mask them out (cpu_active_map)
*
* Returns the CPU we should wake onto.
*/
@@ -1031,7 +1032,8 @@ static int wake_idle(int cpu, struct task_struct *p)
|| ((sd->flags & SD_WAKE_IDLE_FAR)
&& !task_hot(p, task_rq(p)->clock, sd))) {
cpus_and(tmp, sd->span, p->cpus_allowed);
- for_each_cpu_mask(i, tmp) {
+ cpus_and(tmp, tmp, cpu_active_map);
+ for_each_cpu_mask_nr(i, tmp) {
if (idle_cpu(i)) {
if (i != task_cpu(p)) {
schedstat_inc(p,
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index 47ceac9e855..908c04f9dad 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -240,7 +240,7 @@ static int do_balance_runtime(struct rt_rq *rt_rq)
spin_lock(&rt_b->rt_runtime_lock);
rt_period = ktime_to_ns(rt_b->rt_period);
- for_each_cpu_mask(i, rd->span) {
+ for_each_cpu_mask_nr(i, rd->span) {
struct rt_rq *iter = sched_rt_period_rt_rq(rt_b, i);
s64 diff;
@@ -253,7 +253,7 @@ static int do_balance_runtime(struct rt_rq *rt_rq)
diff = iter->rt_runtime - iter->rt_time;
if (diff > 0) {
- do_div(diff, weight);
+ diff = div_u64((u64)diff, weight);
if (rt_rq->rt_runtime + diff > rt_period)
diff = rt_period - rt_rq->rt_runtime;
iter->rt_runtime -= diff;
@@ -505,7 +505,9 @@ void inc_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq)
rt_rq->rt_nr_running++;
#if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED
if (rt_se_prio(rt_se) < rt_rq->highest_prio) {
+#ifdef CONFIG_SMP
struct rq *rq = rq_of_rt_rq(rt_rq);
+#endif
rt_rq->highest_prio = rt_se_prio(rt_se);
#ifdef CONFIG_SMP
@@ -599,11 +601,7 @@ static void __enqueue_rt_entity(struct sched_rt_entity *rt_se)
if (group_rq && (rt_rq_throttled(group_rq) || !group_rq->rt_nr_running))
return;
- if (rt_se->nr_cpus_allowed == 1)
- list_add(&rt_se->run_list, queue);
- else
- list_add_tail(&rt_se->run_list, queue);
-
+ list_add_tail(&rt_se->run_list, queue);
__set_bit(rt_se_prio(rt_se), array->bitmap);
inc_rt_tasks(rt_se, rt_rq);
@@ -688,32 +686,34 @@ static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep)
* Put task to the end of the run list without the overhead of dequeue
* followed by enqueue.
*/
-static
-void requeue_rt_entity(struct rt_rq *rt_rq, struct sched_rt_entity *rt_se)
+static void
+requeue_rt_entity(struct rt_rq *rt_rq, struct sched_rt_entity *rt_se, int head)
{
- struct rt_prio_array *array = &rt_rq->active;
-
if (on_rt_rq(rt_se)) {
- list_del_init(&rt_se->run_list);
- list_add_tail(&rt_se->run_list,
- array->queue + rt_se_prio(rt_se));
+ struct rt_prio_array *array = &rt_rq->active;
+ struct list_head *queue = array->queue + rt_se_prio(rt_se);
+
+ if (head)
+ list_move(&rt_se->run_list, queue);
+ else
+ list_move_tail(&rt_se->run_list, queue);
}
}
-static void requeue_task_rt(struct rq *rq, struct task_struct *p)
+static void requeue_task_rt(struct rq *rq, struct task_struct *p, int head)
{
struct sched_rt_entity *rt_se = &p->rt;
struct rt_rq *rt_rq;
for_each_sched_rt_entity(rt_se) {
rt_rq = rt_rq_of_se(rt_se);
- requeue_rt_entity(rt_rq, rt_se);
+ requeue_rt_entity(rt_rq, rt_se, head);
}
}
static void yield_task_rt(struct rq *rq)
{
- requeue_task_rt(rq, rq->curr);
+ requeue_task_rt(rq, rq->curr, 0);
}
#ifdef CONFIG_SMP
@@ -753,6 +753,30 @@ static int select_task_rq_rt(struct task_struct *p, int sync)
*/
return task_cpu(p);
}
+
+static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p)
+{
+ cpumask_t mask;
+
+ if (rq->curr->rt.nr_cpus_allowed == 1)
+ return;
+
+ if (p->rt.nr_cpus_allowed != 1
+ && cpupri_find(&rq->rd->cpupri, p, &mask))
+ return;
+
+ if (!cpupri_find(&rq->rd->cpupri, rq->curr, &mask))
+ return;
+
+ /*
+ * There appears to be other cpus that can accept
+ * current and none to run 'p', so lets reschedule
+ * to try and push current away:
+ */
+ requeue_task_rt(rq, p, 1);
+ resched_task(rq->curr);
+}
+
#endif /* CONFIG_SMP */
/*
@@ -778,18 +802,8 @@ static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p)
* to move current somewhere else, making room for our non-migratable
* task.
*/
- if((p->prio == rq->curr->prio)
- && p->rt.nr_cpus_allowed == 1
- && rq->curr->rt.nr_cpus_allowed != 1) {
- cpumask_t mask;
-
- if (cpupri_find(&rq->rd->cpupri, rq->curr, &mask))
- /*
- * There appears to be other cpus that can accept
- * current, so lets reschedule to try and push it away
- */
- resched_task(rq->curr);
- }
+ if (p->prio == rq->curr->prio && !need_resched())
+ check_preempt_equal_prio(rq, p);
#endif
}
@@ -922,6 +936,13 @@ static int find_lowest_rq(struct task_struct *task)
return -1; /* No targets found */
/*
+ * Only consider CPUs that are usable for migration.
+ * I guess we might want to change cpupri_find() to ignore those
+ * in the first place.
+ */
+ cpus_and(*lowest_mask, *lowest_mask, cpu_active_map);
+
+ /*
* At this point we have built a mask of cpus representing the
* lowest priority tasks in the system. Now we want to elect
* the best one based on our affinity and topology.
@@ -1107,7 +1128,7 @@ static int pull_rt_task(struct rq *this_rq)
next = pick_next_task_rt(this_rq);
- for_each_cpu_mask(cpu, this_rq->rd->rto_mask) {
+ for_each_cpu_mask_nr(cpu, this_rq->rd->rto_mask) {
if (this_cpu == cpu)
continue;
@@ -1415,7 +1436,7 @@ static void task_tick_rt(struct rq *rq, struct task_struct *p, int queued)
* on the queue:
*/
if (p->rt.run_list.prev != p->rt.run_list.next) {
- requeue_task_rt(rq, p);
+ requeue_task_rt(rq, p, 0);
set_tsk_need_resched(p);
}
}
diff --git a/kernel/signal.c b/kernel/signal.c
index 6c0958e52ea..82c3545596c 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -338,13 +338,9 @@ unblock_all_signals(void)
spin_unlock_irqrestore(&current->sighand->siglock, flags);
}
-static int collect_signal(int sig, struct sigpending *list, siginfo_t *info)
+static void collect_signal(int sig, struct sigpending *list, siginfo_t *info)
{
struct sigqueue *q, *first = NULL;
- int still_pending = 0;
-
- if (unlikely(!sigismember(&list->signal, sig)))
- return 0;
/*
* Collect the siginfo appropriate to this signal. Check if
@@ -352,33 +348,30 @@ static int collect_signal(int sig, struct sigpending *list, siginfo_t *info)
*/
list_for_each_entry(q, &list->list, list) {
if (q->info.si_signo == sig) {
- if (first) {
- still_pending = 1;
- break;
- }
+ if (first)
+ goto still_pending;
first = q;
}
}
+
+ sigdelset(&list->signal, sig);
+
if (first) {
+still_pending:
list_del_init(&first->list);
copy_siginfo(info, &first->info);
__sigqueue_free(first);
- if (!still_pending)
- sigdelset(&list->signal, sig);
} else {
-
/* Ok, it wasn't in the queue. This must be
a fast-pathed signal or we must have been
out of queue space. So zero out the info.
*/
- sigdelset(&list->signal, sig);
info->si_signo = sig;
info->si_errno = 0;
info->si_code = 0;
info->si_pid = 0;
info->si_uid = 0;
}
- return 1;
}
static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
@@ -396,8 +389,7 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
}
}
- if (!collect_signal(sig, pending, info))
- sig = 0;
+ collect_signal(sig, pending, info);
}
return sig;
@@ -462,8 +454,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
* is to alert stop-signal processing code when another
* processor has come along and cleared the flag.
*/
- if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT))
- tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
+ tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
}
if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) {
/*
@@ -1125,7 +1116,7 @@ EXPORT_SYMBOL_GPL(kill_pid_info_as_uid);
* is probably wrong. Should make it like BSD or SYSV.
*/
-static int kill_something_info(int sig, struct siginfo *info, int pid)
+static int kill_something_info(int sig, struct siginfo *info, pid_t pid)
{
int ret;
@@ -1237,17 +1228,6 @@ int kill_pid(struct pid *pid, int sig, int priv)
}
EXPORT_SYMBOL(kill_pid);
-int
-kill_proc(pid_t pid, int sig, int priv)
-{
- int ret;
-
- rcu_read_lock();
- ret = kill_pid_info(sig, __si_special(priv), find_pid(pid));
- rcu_read_unlock();
- return ret;
-}
-
/*
* These functions support sending signals using preallocated sigqueue
* structures. This is needed "because realtime applications cannot
@@ -1379,10 +1359,9 @@ void do_notify_parent(struct task_struct *tsk, int sig)
info.si_uid = tsk->uid;
- /* FIXME: find out whether or not this is supposed to be c*time. */
- info.si_utime = cputime_to_jiffies(cputime_add(tsk->utime,
+ info.si_utime = cputime_to_clock_t(cputime_add(tsk->utime,
tsk->signal->utime));
- info.si_stime = cputime_to_jiffies(cputime_add(tsk->stime,
+ info.si_stime = cputime_to_clock_t(cputime_add(tsk->stime,
tsk->signal->stime));
info.si_status = tsk->exit_code & 0x7f;
@@ -1450,9 +1429,8 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
info.si_uid = tsk->uid;
- /* FIXME: find out whether or not this is supposed to be c*time. */
- info.si_utime = cputime_to_jiffies(tsk->utime);
- info.si_stime = cputime_to_jiffies(tsk->stime);
+ info.si_utime = cputime_to_clock_t(tsk->utime);
+ info.si_stime = cputime_to_clock_t(tsk->stime);
info.si_code = why;
switch (why) {
@@ -1491,10 +1469,10 @@ static inline int may_ptrace_stop(void)
* is a deadlock situation, and pointless because our tracer
* is dead so don't allow us to stop.
* If SIGKILL was already sent before the caller unlocked
- * ->siglock we must see ->core_waiters != 0. Otherwise it
+ * ->siglock we must see ->core_state != NULL. Otherwise it
* is safe to enter schedule().
*/
- if (unlikely(current->mm->core_waiters) &&
+ if (unlikely(current->mm->core_state) &&
unlikely(current->mm == current->parent->mm))
return 0;
@@ -1507,9 +1485,8 @@ static inline int may_ptrace_stop(void)
*/
static int sigkill_pending(struct task_struct *tsk)
{
- return ((sigismember(&tsk->pending.signal, SIGKILL) ||
- sigismember(&tsk->signal->shared_pending.signal, SIGKILL)) &&
- !unlikely(sigismember(&tsk->blocked, SIGKILL)));
+ return sigismember(&tsk->pending.signal, SIGKILL) ||
+ sigismember(&tsk->signal->shared_pending.signal, SIGKILL);
}
/*
@@ -1525,8 +1502,6 @@ static int sigkill_pending(struct task_struct *tsk)
*/
static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info)
{
- int killed = 0;
-
if (arch_ptrace_stop_needed(exit_code, info)) {
/*
* The arch code has something special to do before a
@@ -1542,7 +1517,8 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info)
spin_unlock_irq(&current->sighand->siglock);
arch_ptrace_stop(exit_code, info);
spin_lock_irq(&current->sighand->siglock);
- killed = sigkill_pending(current);
+ if (sigkill_pending(current))
+ return;
}
/*
@@ -1559,7 +1535,7 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info)
__set_current_state(TASK_TRACED);
spin_unlock_irq(&current->sighand->siglock);
read_lock(&tasklist_lock);
- if (!unlikely(killed) && may_ptrace_stop()) {
+ if (may_ptrace_stop()) {
do_notify_parent_cldstop(current, CLD_TRAPPED);
read_unlock(&tasklist_lock);
schedule();
@@ -1658,8 +1634,7 @@ static int do_signal_stop(int signr)
} else {
struct task_struct *t;
- if (unlikely((sig->flags & (SIGNAL_STOP_DEQUEUED | SIGNAL_UNKILLABLE))
- != SIGNAL_STOP_DEQUEUED) ||
+ if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) ||
unlikely(signal_group_exit(sig)))
return 0;
/*
@@ -1920,7 +1895,6 @@ EXPORT_SYMBOL(recalc_sigpending);
EXPORT_SYMBOL_GPL(dequeue_signal);
EXPORT_SYMBOL(flush_signals);
EXPORT_SYMBOL(force_sig);
-EXPORT_SYMBOL(kill_proc);
EXPORT_SYMBOL(ptrace_notify);
EXPORT_SYMBOL(send_sig);
EXPORT_SYMBOL(send_sig_info);
@@ -2196,7 +2170,7 @@ sys_rt_sigtimedwait(const sigset_t __user *uthese,
}
asmlinkage long
-sys_kill(int pid, int sig)
+sys_kill(pid_t pid, int sig)
{
struct siginfo info;
@@ -2209,7 +2183,7 @@ sys_kill(int pid, int sig)
return kill_something_info(sig, &info, pid);
}
-static int do_tkill(int tgid, int pid, int sig)
+static int do_tkill(pid_t tgid, pid_t pid, int sig)
{
int error;
struct siginfo info;
@@ -2255,7 +2229,7 @@ static int do_tkill(int tgid, int pid, int sig)
* exists but it's not belonging to the target process anymore. This
* method solves the problem of threads exiting and PIDs getting reused.
*/
-asmlinkage long sys_tgkill(int tgid, int pid, int sig)
+asmlinkage long sys_tgkill(pid_t tgid, pid_t pid, int sig)
{
/* This is only valid for single tasks */
if (pid <= 0 || tgid <= 0)
@@ -2268,7 +2242,7 @@ asmlinkage long sys_tgkill(int tgid, int pid, int sig)
* Send a signal to only one task, even if it's a CLONE_THREAD task.
*/
asmlinkage long
-sys_tkill(int pid, int sig)
+sys_tkill(pid_t pid, int sig)
{
/* This is only valid for single tasks */
if (pid <= 0)
@@ -2278,7 +2252,7 @@ sys_tkill(int pid, int sig)
}
asmlinkage long
-sys_rt_sigqueueinfo(int pid, int sig, siginfo_t __user *uinfo)
+sys_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t __user *uinfo)
{
siginfo_t info;
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 81e2fe0f983..f6b03d56c2b 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -286,7 +286,7 @@ void irq_exit(void)
#ifdef CONFIG_NO_HZ
/* Make sure that timer wheel updates are propagated */
if (!in_interrupt() && idle_cpu(smp_processor_id()) && !need_resched())
- tick_nohz_stop_sched_tick();
+ tick_nohz_stop_sched_tick(0);
rcu_irq_exit();
#endif
preempt_enable_no_resched();
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index a272d78185e..7bd8d1aadd5 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -13,6 +13,7 @@
#include <linux/delay.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
+#include <linux/lockdep.h>
#include <linux/notifier.h>
#include <linux/module.h>
@@ -25,7 +26,22 @@ static DEFINE_PER_CPU(unsigned long, print_timestamp);
static DEFINE_PER_CPU(struct task_struct *, watchdog_task);
static int __read_mostly did_panic;
-unsigned long __read_mostly softlockup_thresh = 60;
+int __read_mostly softlockup_thresh = 60;
+
+/*
+ * Should we panic (and reboot, if panic_timeout= is set) when a
+ * soft-lockup occurs:
+ */
+unsigned int __read_mostly softlockup_panic =
+ CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE;
+
+static int __init softlockup_panic_setup(char *str)
+{
+ softlockup_panic = simple_strtoul(str, NULL, 0);
+
+ return 1;
+}
+__setup("softlockup_panic=", softlockup_panic_setup);
static int
softlock_panic(struct notifier_block *this, unsigned long event, void *ptr)
@@ -84,6 +100,14 @@ void softlockup_tick(void)
struct pt_regs *regs = get_irq_regs();
unsigned long now;
+ /* Is detection switched off? */
+ if (!per_cpu(watchdog_task, this_cpu) || softlockup_thresh <= 0) {
+ /* Be sure we don't false trigger if switched back on */
+ if (touch_timestamp)
+ per_cpu(touch_timestamp, this_cpu) = 0;
+ return;
+ }
+
if (touch_timestamp == 0) {
__touch_softlockup_watchdog();
return;
@@ -92,11 +116,8 @@ void softlockup_tick(void)
print_timestamp = per_cpu(print_timestamp, this_cpu);
/* report at most once a second */
- if ((print_timestamp >= touch_timestamp &&
- print_timestamp < (touch_timestamp + 1)) ||
- did_panic || !per_cpu(watchdog_task, this_cpu)) {
+ if (print_timestamp == touch_timestamp || did_panic)
return;
- }
/* do not print during early bootup: */
if (unlikely(system_state != SYSTEM_RUNNING)) {
@@ -106,8 +127,11 @@ void softlockup_tick(void)
now = get_timestamp(this_cpu);
- /* Wake up the high-prio watchdog task every second: */
- if (now > (touch_timestamp + 1))
+ /*
+ * Wake up the high-prio watchdog task twice per
+ * threshold timespan.
+ */
+ if (now > touch_timestamp + softlockup_thresh/2)
wake_up_process(per_cpu(watchdog_task, this_cpu));
/* Warn about unreasonable delays: */
@@ -121,11 +145,15 @@ void softlockup_tick(void)
this_cpu, now - touch_timestamp,
current->comm, task_pid_nr(current));
print_modules();
+ print_irqtrace_events(current);
if (regs)
show_regs(regs);
else
dump_stack();
spin_unlock(&print_lock);
+
+ if (softlockup_panic)
+ panic("softlockup: hung tasks");
}
/*
@@ -178,6 +206,9 @@ static void check_hung_task(struct task_struct *t, unsigned long now)
t->last_switch_timestamp = now;
touch_nmi_watchdog();
+
+ if (softlockup_panic)
+ panic("softlockup: blocked tasks");
}
/*
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index ba9b2054ecb..738b411ff2d 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -33,8 +33,9 @@ static int stopmachine(void *cpu)
{
int irqs_disabled = 0;
int prepared = 0;
+ cpumask_of_cpu_ptr(cpumask, (int)(long)cpu);
- set_cpus_allowed_ptr(current, &cpumask_of_cpu((int)(long)cpu));
+ set_cpus_allowed_ptr(current, cpumask);
/* Ack: we are alive */
smp_mb(); /* Theoretically the ack = 0 might not be on this CPU yet. */
diff --git a/kernel/sys.c b/kernel/sys.c
index 14e97282eb6..0c9d3fa1f5f 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1343,8 +1343,6 @@ EXPORT_SYMBOL(in_egroup_p);
DECLARE_RWSEM(uts_sem);
-EXPORT_SYMBOL(uts_sem);
-
asmlinkage long sys_newuname(struct new_utsname __user * name)
{
int errno = 0;
@@ -1795,7 +1793,7 @@ int orderly_poweroff(bool force)
goto out;
}
- info = call_usermodehelper_setup(argv[0], argv, envp);
+ info = call_usermodehelper_setup(argv[0], argv, envp, GFP_ATOMIC);
if (info == NULL) {
argv_free(argv);
goto out;
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 5b9b467de07..08d6e1bb99a 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -31,6 +31,7 @@ cond_syscall(sys_socketpair);
cond_syscall(sys_bind);
cond_syscall(sys_listen);
cond_syscall(sys_accept);
+cond_syscall(sys_paccept);
cond_syscall(sys_connect);
cond_syscall(sys_getsockname);
cond_syscall(sys_getpeername);
@@ -56,9 +57,11 @@ cond_syscall(compat_sys_set_robust_list);
cond_syscall(sys_get_robust_list);
cond_syscall(compat_sys_get_robust_list);
cond_syscall(sys_epoll_create);
+cond_syscall(sys_epoll_create1);
cond_syscall(sys_epoll_ctl);
cond_syscall(sys_epoll_wait);
cond_syscall(sys_epoll_pwait);
+cond_syscall(compat_sys_epoll_pwait);
cond_syscall(sys_semget);
cond_syscall(sys_semop);
cond_syscall(sys_semtimedop);
@@ -94,6 +97,7 @@ cond_syscall(sys_keyctl);
cond_syscall(compat_sys_keyctl);
cond_syscall(compat_sys_socketcall);
cond_syscall(sys_inotify_init);
+cond_syscall(sys_inotify_init1);
cond_syscall(sys_inotify_add_watch);
cond_syscall(sys_inotify_rm_watch);
cond_syscall(sys_migrate_pages);
@@ -154,10 +158,13 @@ cond_syscall(sys_ioprio_get);
/* New file descriptors */
cond_syscall(sys_signalfd);
+cond_syscall(sys_signalfd4);
cond_syscall(compat_sys_signalfd);
+cond_syscall(compat_sys_signalfd4);
cond_syscall(sys_timerfd_create);
cond_syscall(sys_timerfd_settime);
cond_syscall(sys_timerfd_gettime);
cond_syscall(compat_sys_timerfd_settime);
cond_syscall(compat_sys_timerfd_gettime);
cond_syscall(sys_eventfd);
+cond_syscall(sys_eventfd2);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 6b16e16428d..35a50db9b6c 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -43,6 +43,7 @@
#include <linux/limits.h>
#include <linux/dcache.h>
#include <linux/syscalls.h>
+#include <linux/vmstat.h>
#include <linux/nfs_fs.h>
#include <linux/acpi.h>
#include <linux/reboot.h>
@@ -80,7 +81,6 @@ extern int sysctl_drop_caches;
extern int percpu_pagelist_fraction;
extern int compat_log;
extern int maps_protect;
-extern int sysctl_stat_interval;
extern int latencytop_enabled;
extern int sysctl_nr_open_min, sysctl_nr_open_max;
#ifdef CONFIG_RCU_TORTURE_TEST
@@ -88,12 +88,13 @@ extern int rcutorture_runnable;
#endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
/* Constants used for minimum and maximum */
-#if defined(CONFIG_DETECT_SOFTLOCKUP) || defined(CONFIG_HIGHMEM)
+#if defined(CONFIG_HIGHMEM) || defined(CONFIG_DETECT_SOFTLOCKUP)
static int one = 1;
#endif
#ifdef CONFIG_DETECT_SOFTLOCKUP
static int sixty = 60;
+static int neg_one = -1;
#endif
#ifdef CONFIG_MMU
@@ -110,7 +111,7 @@ static int min_percpu_pagelist_fract = 8;
static int ngroups_max = NGROUPS_MAX;
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
extern char modprobe_path[];
#endif
#ifdef CONFIG_CHR_DEV_SG
@@ -475,7 +476,7 @@ static struct ctl_table kern_table[] = {
.proc_handler = &ftrace_enable_sysctl,
},
#endif
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
{
.ctl_name = KERN_MODPROBE,
.procname = "modprobe",
@@ -623,7 +624,7 @@ static struct ctl_table kern_table[] = {
{
.ctl_name = KERN_PRINTK_RATELIMIT,
.procname = "printk_ratelimit",
- .data = &printk_ratelimit_jiffies,
+ .data = &printk_ratelimit_state.interval,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
@@ -632,7 +633,7 @@ static struct ctl_table kern_table[] = {
{
.ctl_name = KERN_PRINTK_RATELIMIT_BURST,
.procname = "printk_ratelimit_burst",
- .data = &printk_ratelimit_burst,
+ .data = &printk_ratelimit_state.burst,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
@@ -739,13 +740,24 @@ static struct ctl_table kern_table[] = {
#ifdef CONFIG_DETECT_SOFTLOCKUP
{
.ctl_name = CTL_UNNUMBERED,
+ .procname = "softlockup_panic",
+ .data = &softlockup_panic,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
.procname = "softlockup_thresh",
.data = &softlockup_thresh,
- .maxlen = sizeof(unsigned long),
+ .maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_doulongvec_minmax,
+ .proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
- .extra1 = &one,
+ .extra1 = &neg_one,
.extra2 = &sixty,
},
{
@@ -947,7 +959,7 @@ static struct ctl_table vm_table[] = {
#ifdef CONFIG_HUGETLB_PAGE
{
.procname = "nr_hugepages",
- .data = &max_huge_pages,
+ .data = NULL,
.maxlen = sizeof(unsigned long),
.mode = 0644,
.proc_handler = &hugetlb_sysctl_handler,
@@ -973,10 +985,12 @@ static struct ctl_table vm_table[] = {
{
.ctl_name = CTL_UNNUMBERED,
.procname = "nr_overcommit_hugepages",
- .data = &sysctl_overcommit_huge_pages,
- .maxlen = sizeof(sysctl_overcommit_huge_pages),
+ .data = NULL,
+ .maxlen = sizeof(unsigned long),
.mode = 0644,
.proc_handler = &hugetlb_overcommit_handler,
+ .extra1 = (void *)&hugetlb_zero,
+ .extra2 = (void *)&hugetlb_infinity,
},
#endif
{
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
index c09350d564f..c35da23ab8f 100644
--- a/kernel/sysctl_check.c
+++ b/kernel/sysctl_check.c
@@ -1532,6 +1532,8 @@ int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table)
sysctl_check_leaf(namespaces, table, &fail);
}
sysctl_check_bin_path(table, &fail);
+ if (table->mode > 0777)
+ set_fail(&fail, table, "bogus .mode");
if (fail) {
set_fail(&fail, table, NULL);
error = -EINVAL;
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index 4a23517169a..bd6be76303c 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -35,7 +35,7 @@
*/
#define TASKSTATS_CPUMASK_MAXLEN (100+6*NR_CPUS)
-static DEFINE_PER_CPU(__u32, taskstats_seqnum) = { 0 };
+static DEFINE_PER_CPU(__u32, taskstats_seqnum);
static int family_registered;
struct kmem_cache *taskstats_cache;
@@ -301,7 +301,7 @@ static int add_del_listener(pid_t pid, cpumask_t *maskp, int isadd)
return -EINVAL;
if (isadd == REGISTER) {
- for_each_cpu_mask(cpu, mask) {
+ for_each_cpu_mask_nr(cpu, mask) {
s = kmalloc_node(sizeof(struct listener), GFP_KERNEL,
cpu_to_node(cpu));
if (!s)
@@ -320,7 +320,7 @@ static int add_del_listener(pid_t pid, cpumask_t *maskp, int isadd)
/* Deregister or cleanup */
cleanup:
- for_each_cpu_mask(cpu, mask) {
+ for_each_cpu_mask_nr(cpu, mask) {
listeners = &per_cpu(listener_array, cpu);
down_write(&listeners->sem);
list_for_each_entry_safe(s, tmp, &listeners->list, list) {
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index dadde5361f3..093d4acf993 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -145,9 +145,9 @@ static void clocksource_watchdog(unsigned long data)
* Cycle through CPUs to check if the CPUs stay
* synchronized to each other.
*/
- int next_cpu = next_cpu(raw_smp_processor_id(), cpu_online_map);
+ int next_cpu = next_cpu_nr(raw_smp_processor_id(), cpu_online_map);
- if (next_cpu >= NR_CPUS)
+ if (next_cpu >= nr_cpu_ids)
next_cpu = first_cpu(cpu_online_map);
watchdog_timer.expires += WATCHDOG_INTERVAL;
add_timer_on(&watchdog_timer, next_cpu);
@@ -376,7 +376,8 @@ void clocksource_unregister(struct clocksource *cs)
* Provides sysfs interface for listing current clocksource.
*/
static ssize_t
-sysfs_show_current_clocksources(struct sys_device *dev, char *buf)
+sysfs_show_current_clocksources(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
ssize_t count = 0;
@@ -397,6 +398,7 @@ sysfs_show_current_clocksources(struct sys_device *dev, char *buf)
* clocksource selction.
*/
static ssize_t sysfs_override_clocksource(struct sys_device *dev,
+ struct sysdev_attribute *attr,
const char *buf, size_t count)
{
struct clocksource *ovr = NULL;
@@ -449,7 +451,9 @@ static ssize_t sysfs_override_clocksource(struct sys_device *dev,
* Provides sysfs interface for listing registered clocksources
*/
static ssize_t
-sysfs_show_available_clocksources(struct sys_device *dev, char *buf)
+sysfs_show_available_clocksources(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ char *buf)
{
struct clocksource *src;
ssize_t count = 0;
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index f48d0f09d32..31463d370b9 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -399,8 +399,7 @@ again:
mask = CPU_MASK_NONE;
now = ktime_get();
/* Find all expired events */
- for (cpu = first_cpu(tick_broadcast_oneshot_mask); cpu != NR_CPUS;
- cpu = next_cpu(cpu, tick_broadcast_oneshot_mask)) {
+ for_each_cpu_mask_nr(cpu, tick_broadcast_oneshot_mask) {
td = &per_cpu(tick_cpu_device, cpu);
if (td->evtdev->next_event.tv64 <= now.tv64)
cpu_set(cpu, mask);
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 4f3886562b8..bf43284d685 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -135,7 +135,7 @@ void tick_setup_periodic(struct clock_event_device *dev, int broadcast)
*/
static void tick_setup_device(struct tick_device *td,
struct clock_event_device *newdev, int cpu,
- cpumask_t cpumask)
+ const cpumask_t *cpumask)
{
ktime_t next_event;
void (*handler)(struct clock_event_device *) = NULL;
@@ -169,8 +169,8 @@ static void tick_setup_device(struct tick_device *td,
* When the device is not per cpu, pin the interrupt to the
* current cpu:
*/
- if (!cpus_equal(newdev->cpumask, cpumask))
- irq_set_affinity(newdev->irq, cpumask);
+ if (!cpus_equal(newdev->cpumask, *cpumask))
+ irq_set_affinity(newdev->irq, *cpumask);
/*
* When global broadcasting is active, check if the current
@@ -196,20 +196,20 @@ static int tick_check_new_device(struct clock_event_device *newdev)
struct tick_device *td;
int cpu, ret = NOTIFY_OK;
unsigned long flags;
- cpumask_t cpumask;
+ cpumask_of_cpu_ptr_declare(cpumask);
spin_lock_irqsave(&tick_device_lock, flags);
cpu = smp_processor_id();
+ cpumask_of_cpu_ptr_next(cpumask, cpu);
if (!cpu_isset(cpu, newdev->cpumask))
goto out_bc;
td = &per_cpu(tick_cpu_device, cpu);
curdev = td->evtdev;
- cpumask = cpumask_of_cpu(cpu);
/* cpu local device ? */
- if (!cpus_equal(newdev->cpumask, cpumask)) {
+ if (!cpus_equal(newdev->cpumask, *cpumask)) {
/*
* If the cpu affinity of the device interrupt can not
@@ -222,7 +222,7 @@ static int tick_check_new_device(struct clock_event_device *newdev)
* If we have a cpu local device already, do not replace it
* by a non cpu local device
*/
- if (curdev && cpus_equal(curdev->cpumask, cpumask))
+ if (curdev && cpus_equal(curdev->cpumask, *cpumask))
goto out_bc;
}
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index beef7ccdf84..825b4c00fe4 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -140,8 +140,6 @@ void tick_nohz_update_jiffies(void)
if (!ts->tick_stopped)
return;
- touch_softlockup_watchdog();
-
cpu_clear(cpu, nohz_cpu_mask);
now = ktime_get();
ts->idle_waketime = now;
@@ -149,6 +147,8 @@ void tick_nohz_update_jiffies(void)
local_irq_save(flags);
tick_do_update_jiffies64(now);
local_irq_restore(flags);
+
+ touch_softlockup_watchdog();
}
void tick_nohz_stop_idle(int cpu)
@@ -195,7 +195,7 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
* Called either from the idle loop or from irq_exit() when an idle period was
* just interrupted by an interrupt which did not cause a reschedule.
*/
-void tick_nohz_stop_sched_tick(void)
+void tick_nohz_stop_sched_tick(int inidle)
{
unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags;
struct tick_sched *ts;
@@ -224,6 +224,11 @@ void tick_nohz_stop_sched_tick(void)
if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
goto end;
+ if (!inidle && !ts->inidle)
+ goto end;
+
+ ts->inidle = 1;
+
if (need_resched())
goto end;
@@ -373,11 +378,14 @@ void tick_nohz_restart_sched_tick(void)
local_irq_disable();
tick_nohz_stop_idle(cpu);
- if (!ts->tick_stopped) {
+ if (!ts->inidle || !ts->tick_stopped) {
+ ts->inidle = 0;
local_irq_enable();
return;
}
+ ts->inidle = 0;
+
rcu_exit_nohz();
/* Update jiffies first */
diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c
index 2301e1e7c60..ce2d723c10e 100644
--- a/kernel/trace/trace_sysprof.c
+++ b/kernel/trace/trace_sysprof.c
@@ -161,7 +161,7 @@ static void timer_notify(struct pt_regs *regs, int cpu)
__trace_special(tr, data, 2, regs->ip, 0);
while (i < sample_max_depth) {
- frame.next_fp = 0;
+ frame.next_fp = NULL;
frame.return_address = 0;
if (!copy_stack_frame(fp, &frame))
break;
@@ -213,7 +213,9 @@ static void start_stack_timers(void)
int cpu;
for_each_online_cpu(cpu) {
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ cpumask_of_cpu_ptr(new_mask, cpu);
+
+ set_cpus_allowed_ptr(current, new_mask);
start_stack_timer(cpu);
}
set_cpus_allowed_ptr(current, &saved_mask);
diff --git a/kernel/tsacct.c b/kernel/tsacct.c
index 4ab1b584961..3da47ccdc5e 100644
--- a/kernel/tsacct.c
+++ b/kernel/tsacct.c
@@ -28,14 +28,14 @@
void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk)
{
struct timespec uptime, ts;
- s64 ac_etime;
+ u64 ac_etime;
BUILD_BUG_ON(TS_COMM_LEN < TASK_COMM_LEN);
/* calculate task elapsed time in timespec */
do_posix_clock_monotonic_gettime(&uptime);
ts = timespec_sub(uptime, tsk->start_time);
- /* rebase elapsed time to usec */
+ /* rebase elapsed time to usec (should never be negative) */
ac_etime = timespec_to_ns(&ts);
do_div(ac_etime, NSEC_PER_USEC);
stats->ac_etime = ac_etime;
@@ -84,9 +84,9 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
{
struct mm_struct *mm;
- /* convert pages-jiffies to Mbyte-usec */
- stats->coremem = jiffies_to_usecs(p->acct_rss_mem1) * PAGE_SIZE / MB;
- stats->virtmem = jiffies_to_usecs(p->acct_vm_mem1) * PAGE_SIZE / MB;
+ /* convert pages-usec to Mbyte-usec */
+ stats->coremem = p->acct_rss_mem1 * PAGE_SIZE / MB;
+ stats->virtmem = p->acct_vm_mem1 * PAGE_SIZE / MB;
mm = get_task_mm(p);
if (mm) {
/* adjust to KB unit */
@@ -118,12 +118,19 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
void acct_update_integrals(struct task_struct *tsk)
{
if (likely(tsk->mm)) {
- long delta = cputime_to_jiffies(
- cputime_sub(tsk->stime, tsk->acct_stimexpd));
+ cputime_t time, dtime;
+ struct timeval value;
+ u64 delta;
+
+ time = tsk->stime + tsk->utime;
+ dtime = cputime_sub(time, tsk->acct_timexpd);
+ jiffies_to_timeval(cputime_to_jiffies(dtime), &value);
+ delta = value.tv_sec;
+ delta = delta * USEC_PER_SEC + value.tv_usec;
if (delta == 0)
return;
- tsk->acct_stimexpd = tsk->stime;
+ tsk->acct_timexpd = time;
tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm);
tsk->acct_vm_mem1 += delta * tsk->mm->total_vm;
}
@@ -135,7 +142,7 @@ void acct_update_integrals(struct task_struct *tsk)
*/
void acct_clear_integrals(struct task_struct *tsk)
{
- tsk->acct_stimexpd = 0;
+ tsk->acct_timexpd = 0;
tsk->acct_rss_mem1 = 0;
tsk->acct_vm_mem1 = 0;
}
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index ce7799540c9..ec7e4f62aaf 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -125,7 +125,7 @@ struct cpu_workqueue_struct *get_wq_data(struct work_struct *work)
}
static void insert_work(struct cpu_workqueue_struct *cwq,
- struct work_struct *work, int tail)
+ struct work_struct *work, struct list_head *head)
{
set_wq_data(work, cwq);
/*
@@ -133,21 +133,17 @@ static void insert_work(struct cpu_workqueue_struct *cwq,
* result of list_add() below, see try_to_grab_pending().
*/
smp_wmb();
- if (tail)
- list_add_tail(&work->entry, &cwq->worklist);
- else
- list_add(&work->entry, &cwq->worklist);
+ list_add_tail(&work->entry, head);
wake_up(&cwq->more_work);
}
-/* Preempt must be disabled. */
static void __queue_work(struct cpu_workqueue_struct *cwq,
struct work_struct *work)
{
unsigned long flags;
spin_lock_irqsave(&cwq->lock, flags);
- insert_work(cwq, work, 1);
+ insert_work(cwq, work, &cwq->worklist);
spin_unlock_irqrestore(&cwq->lock, flags);
}
@@ -163,17 +159,39 @@ static void __queue_work(struct cpu_workqueue_struct *cwq,
*/
int queue_work(struct workqueue_struct *wq, struct work_struct *work)
{
+ int ret;
+
+ ret = queue_work_on(get_cpu(), wq, work);
+ put_cpu();
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(queue_work);
+
+/**
+ * queue_work_on - queue work on specific cpu
+ * @cpu: CPU number to execute work on
+ * @wq: workqueue to use
+ * @work: work to queue
+ *
+ * Returns 0 if @work was already on a queue, non-zero otherwise.
+ *
+ * We queue the work to a specific CPU, the caller must ensure it
+ * can't go away.
+ */
+int
+queue_work_on(int cpu, struct workqueue_struct *wq, struct work_struct *work)
+{
int ret = 0;
if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) {
BUG_ON(!list_empty(&work->entry));
- __queue_work(wq_per_cpu(wq, get_cpu()), work);
- put_cpu();
+ __queue_work(wq_per_cpu(wq, cpu), work);
ret = 1;
}
return ret;
}
-EXPORT_SYMBOL_GPL(queue_work);
+EXPORT_SYMBOL_GPL(queue_work_on);
static void delayed_work_timer_fn(unsigned long __data)
{
@@ -337,14 +355,14 @@ static void wq_barrier_func(struct work_struct *work)
}
static void insert_wq_barrier(struct cpu_workqueue_struct *cwq,
- struct wq_barrier *barr, int tail)
+ struct wq_barrier *barr, struct list_head *head)
{
INIT_WORK(&barr->work, wq_barrier_func);
__set_bit(WORK_STRUCT_PENDING, work_data_bits(&barr->work));
init_completion(&barr->done);
- insert_work(cwq, &barr->work, tail);
+ insert_work(cwq, &barr->work, head);
}
static int flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
@@ -364,7 +382,7 @@ static int flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
active = 0;
spin_lock_irq(&cwq->lock);
if (!list_empty(&cwq->worklist) || cwq->current_work != NULL) {
- insert_wq_barrier(cwq, &barr, 1);
+ insert_wq_barrier(cwq, &barr, &cwq->worklist);
active = 1;
}
spin_unlock_irq(&cwq->lock);
@@ -397,11 +415,62 @@ void flush_workqueue(struct workqueue_struct *wq)
might_sleep();
lock_acquire(&wq->lockdep_map, 0, 0, 0, 2, _THIS_IP_);
lock_release(&wq->lockdep_map, 1, _THIS_IP_);
- for_each_cpu_mask(cpu, *cpu_map)
+ for_each_cpu_mask_nr(cpu, *cpu_map)
flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu));
}
EXPORT_SYMBOL_GPL(flush_workqueue);
+/**
+ * flush_work - block until a work_struct's callback has terminated
+ * @work: the work which is to be flushed
+ *
+ * Returns false if @work has already terminated.
+ *
+ * It is expected that, prior to calling flush_work(), the caller has
+ * arranged for the work to not be requeued, otherwise it doesn't make
+ * sense to use this function.
+ */
+int flush_work(struct work_struct *work)
+{
+ struct cpu_workqueue_struct *cwq;
+ struct list_head *prev;
+ struct wq_barrier barr;
+
+ might_sleep();
+ cwq = get_wq_data(work);
+ if (!cwq)
+ return 0;
+
+ lock_acquire(&cwq->wq->lockdep_map, 0, 0, 0, 2, _THIS_IP_);
+ lock_release(&cwq->wq->lockdep_map, 1, _THIS_IP_);
+
+ prev = NULL;
+ spin_lock_irq(&cwq->lock);
+ if (!list_empty(&work->entry)) {
+ /*
+ * See the comment near try_to_grab_pending()->smp_rmb().
+ * If it was re-queued under us we are not going to wait.
+ */
+ smp_rmb();
+ if (unlikely(cwq != get_wq_data(work)))
+ goto out;
+ prev = &work->entry;
+ } else {
+ if (cwq->current_work != work)
+ goto out;
+ prev = &cwq->worklist;
+ }
+ insert_wq_barrier(cwq, &barr, prev->next);
+out:
+ spin_unlock_irq(&cwq->lock);
+ if (!prev)
+ return 0;
+
+ wait_for_completion(&barr.done);
+ return 1;
+}
+EXPORT_SYMBOL_GPL(flush_work);
+
/*
* Upon a successful return (>= 0), the caller "owns" WORK_STRUCT_PENDING bit,
* so this work can't be re-armed in any way.
@@ -449,7 +518,7 @@ static void wait_on_cpu_work(struct cpu_workqueue_struct *cwq,
spin_lock_irq(&cwq->lock);
if (unlikely(cwq->current_work == work)) {
- insert_wq_barrier(cwq, &barr, 0);
+ insert_wq_barrier(cwq, &barr, cwq->worklist.next);
running = 1;
}
spin_unlock_irq(&cwq->lock);
@@ -477,7 +546,7 @@ static void wait_on_work(struct work_struct *work)
wq = cwq->wq;
cpu_map = wq_cpu_map(wq);
- for_each_cpu_mask(cpu, *cpu_map)
+ for_each_cpu_mask_nr(cpu, *cpu_map)
wait_on_cpu_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
}
@@ -553,6 +622,19 @@ int schedule_work(struct work_struct *work)
}
EXPORT_SYMBOL(schedule_work);
+/*
+ * schedule_work_on - put work task on a specific cpu
+ * @cpu: cpu to put the work task on
+ * @work: job to be done
+ *
+ * This puts a job on a specific cpu
+ */
+int schedule_work_on(int cpu, struct work_struct *work)
+{
+ return queue_work_on(cpu, keventd_wq, work);
+}
+EXPORT_SYMBOL(schedule_work_on);
+
/**
* schedule_delayed_work - put work task in global workqueue after delay
* @dwork: job to be done
@@ -607,10 +689,10 @@ int schedule_on_each_cpu(work_func_t func)
struct work_struct *work = per_cpu_ptr(works, cpu);
INIT_WORK(work, func);
- set_bit(WORK_STRUCT_PENDING, work_data_bits(work));
- __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu), work);
+ schedule_work_on(cpu, work);
}
- flush_workqueue(keventd_wq);
+ for_each_online_cpu(cpu)
+ flush_work(per_cpu_ptr(works, cpu));
put_online_cpus();
free_percpu(works);
return 0;
@@ -747,7 +829,7 @@ struct workqueue_struct *__create_workqueue_key(const char *name,
err = create_workqueue_thread(cwq, singlethread_cpu);
start_workqueue_thread(cwq, -1);
} else {
- get_online_cpus();
+ cpu_maps_update_begin();
spin_lock(&workqueue_lock);
list_add(&wq->list, &workqueues);
spin_unlock(&workqueue_lock);
@@ -759,7 +841,7 @@ struct workqueue_struct *__create_workqueue_key(const char *name,
err = create_workqueue_thread(cwq, cpu);
start_workqueue_thread(cwq, cpu);
}
- put_online_cpus();
+ cpu_maps_update_done();
}
if (err) {
@@ -773,8 +855,8 @@ EXPORT_SYMBOL_GPL(__create_workqueue_key);
static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq)
{
/*
- * Our caller is either destroy_workqueue() or CPU_DEAD,
- * get_online_cpus() protects cwq->thread.
+ * Our caller is either destroy_workqueue() or CPU_POST_DEAD,
+ * cpu_add_remove_lock protects cwq->thread.
*/
if (cwq->thread == NULL)
return;
@@ -784,7 +866,7 @@ static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq)
flush_cpu_workqueue(cwq);
/*
- * If the caller is CPU_DEAD and cwq->worklist was not empty,
+ * If the caller is CPU_POST_DEAD and cwq->worklist was not empty,
* a concurrent flush_workqueue() can insert a barrier after us.
* However, in that case run_workqueue() won't return and check
* kthread_should_stop() until it flushes all work_struct's.
@@ -808,14 +890,14 @@ void destroy_workqueue(struct workqueue_struct *wq)
const cpumask_t *cpu_map = wq_cpu_map(wq);
int cpu;
- get_online_cpus();
+ cpu_maps_update_begin();
spin_lock(&workqueue_lock);
list_del(&wq->list);
spin_unlock(&workqueue_lock);
- for_each_cpu_mask(cpu, *cpu_map)
+ for_each_cpu_mask_nr(cpu, *cpu_map)
cleanup_workqueue_thread(per_cpu_ptr(wq->cpu_wq, cpu));
- put_online_cpus();
+ cpu_maps_update_done();
free_percpu(wq->cpu_wq);
kfree(wq);
@@ -829,6 +911,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
unsigned int cpu = (unsigned long)hcpu;
struct cpu_workqueue_struct *cwq;
struct workqueue_struct *wq;
+ int ret = NOTIFY_OK;
action &= ~CPU_TASKS_FROZEN;
@@ -836,7 +919,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
case CPU_UP_PREPARE:
cpu_set(cpu, cpu_populated_map);
}
-
+undo:
list_for_each_entry(wq, &workqueues, list) {
cwq = per_cpu_ptr(wq->cpu_wq, cpu);
@@ -846,7 +929,9 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
break;
printk(KERN_ERR "workqueue [%s] for %i failed\n",
wq->name, cpu);
- return NOTIFY_BAD;
+ action = CPU_UP_CANCELED;
+ ret = NOTIFY_BAD;
+ goto undo;
case CPU_ONLINE:
start_workqueue_thread(cwq, cpu);
@@ -854,7 +939,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
case CPU_UP_CANCELED:
start_workqueue_thread(cwq, -1);
- case CPU_DEAD:
+ case CPU_POST_DEAD:
cleanup_workqueue_thread(cwq);
break;
}
@@ -862,11 +947,11 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
switch (action) {
case CPU_UP_CANCELED:
- case CPU_DEAD:
+ case CPU_POST_DEAD:
cpu_clear(cpu, cpu_populated_map);
}
- return NOTIFY_OK;
+ return ret;
}
void __init init_workqueues(void)
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index df27132a56f..e1d4764435e 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -74,6 +74,9 @@ config DEBUG_FS
debugging files into. Enable this option to be able to read and
write to these files.
+ For detailed documentation on the debugfs API, see
+ Documentation/DocBook/filesystems.
+
If unsure, say N.
config HEADERS_CHECK
@@ -147,7 +150,7 @@ config DETECT_SOFTLOCKUP
help
Say Y here to enable the kernel to detect "soft lockups",
which are bugs that cause the kernel to loop in kernel
- mode for more than 10 seconds, without giving other tasks a
+ mode for more than 60 seconds, without giving other tasks a
chance to run.
When a soft-lockup is detected, the kernel will print the
@@ -159,6 +162,30 @@ config DETECT_SOFTLOCKUP
can be detected via the NMI-watchdog, on platforms that
support it.)
+config BOOTPARAM_SOFTLOCKUP_PANIC
+ bool "Panic (Reboot) On Soft Lockups"
+ depends on DETECT_SOFTLOCKUP
+ help
+ Say Y here to enable the kernel to panic on "soft lockups",
+ which are bugs that cause the kernel to loop in kernel
+ mode for more than 60 seconds, without giving other tasks a
+ chance to run.
+
+ The panic can be used in combination with panic_timeout,
+ to cause the system to reboot automatically after a
+ lockup has been detected. This feature is useful for
+ high-availability systems that have uptime guarantees and
+ where a lockup must be resolved ASAP.
+
+ Say N if unsure.
+
+config BOOTPARAM_SOFTLOCKUP_PANIC_VALUE
+ int
+ depends on DETECT_SOFTLOCKUP
+ range 0 1
+ default 0 if !BOOTPARAM_SOFTLOCKUP_PANIC
+ default 1 if BOOTPARAM_SOFTLOCKUP_PANIC
+
config SCHED_DEBUG
bool "Collect scheduler debugging info"
depends on DEBUG_KERNEL && PROC_FS
@@ -478,6 +505,18 @@ config DEBUG_WRITECOUNT
If unsure, say N.
+config DEBUG_MEMORY_INIT
+ bool "Debug memory initialisation" if EMBEDDED
+ default !EMBEDDED
+ help
+ Enable this for additional checks during memory initialisation.
+ The sanity checks verify aspects of the VM such as the memory model
+ and other information provided by the architecture. Verbose
+ information will be printed at KERN_DEBUG loglevel depending
+ on the mminit_loglevel= command-line option.
+
+ If unsure, say Y
+
config DEBUG_LIST
bool "Debug linked list manipulation"
depends on DEBUG_KERNEL
diff --git a/lib/Kconfig.kgdb b/lib/Kconfig.kgdb
index a5d4b1dac2a..2cfd2721f7e 100644
--- a/lib/Kconfig.kgdb
+++ b/lib/Kconfig.kgdb
@@ -1,7 +1,4 @@
-config HAVE_ARCH_KGDB_SHADOW_INFO
- bool
-
config HAVE_ARCH_KGDB
bool
diff --git a/lib/Makefile b/lib/Makefile
index 818c4d45551..9085ad6fa53 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -18,7 +18,7 @@ lib-$(CONFIG_SMP) += cpumask.o
lib-y += kobject.o kref.o klist.o
-obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
+obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o
ifeq ($(CONFIG_DEBUG_KOBJECT),y)
diff --git a/lib/bcd.c b/lib/bcd.c
new file mode 100644
index 00000000000..d74257fd0fe
--- /dev/null
+++ b/lib/bcd.c
@@ -0,0 +1,14 @@
+#include <linux/bcd.h>
+#include <linux/module.h>
+
+unsigned bcd2bin(unsigned char val)
+{
+ return (val & 0x0f) + (val >> 4) * 10;
+}
+EXPORT_SYMBOL(bcd2bin);
+
+unsigned char bin2bcd(unsigned val)
+{
+ return ((val / 10) << 4) + val % 10;
+}
+EXPORT_SYMBOL(bin2bcd);
diff --git a/lib/cmdline.c b/lib/cmdline.c
index f596c08d213..5ba8a942a47 100644
--- a/lib/cmdline.c
+++ b/lib/cmdline.c
@@ -116,7 +116,7 @@ char *get_options(const char *str, int nints, int *ints)
/**
* memparse - parse a string with mem suffixes into a number
* @ptr: Where parse begins
- * @retptr: (output) Pointer to next char after parse completes
+ * @retptr: (output) Optional pointer to next char after parse completes
*
* Parses a string into a number. The number stored at @ptr is
* potentially suffixed with %K (for kilobytes, or 1024 bytes),
@@ -126,11 +126,13 @@ char *get_options(const char *str, int nints, int *ints)
* megabyte, or one gigabyte, respectively.
*/
-unsigned long long memparse (char *ptr, char **retptr)
+unsigned long long memparse(char *ptr, char **retptr)
{
- unsigned long long ret = simple_strtoull (ptr, retptr, 0);
+ char *endptr; /* local pointer to end of parsed string */
- switch (**retptr) {
+ unsigned long long ret = simple_strtoull(ptr, &endptr, 0);
+
+ switch (*endptr) {
case 'G':
case 'g':
ret <<= 10;
@@ -140,10 +142,14 @@ unsigned long long memparse (char *ptr, char **retptr)
case 'K':
case 'k':
ret <<= 10;
- (*retptr)++;
+ endptr++;
default:
break;
}
+
+ if (retptr)
+ *retptr = endptr;
+
return ret;
}
diff --git a/lib/cpumask.c b/lib/cpumask.c
index bb4f76d3c3e..5f97dc25ef9 100644
--- a/lib/cpumask.c
+++ b/lib/cpumask.c
@@ -15,6 +15,15 @@ int __next_cpu(int n, const cpumask_t *srcp)
}
EXPORT_SYMBOL(__next_cpu);
+#if NR_CPUS > 64
+int __next_cpu_nr(int n, const cpumask_t *srcp)
+{
+ return min_t(int, nr_cpu_ids,
+ find_next_bit(srcp->bits, nr_cpu_ids, n+1));
+}
+EXPORT_SYMBOL(__next_cpu_nr);
+#endif
+
int __any_online_cpu(const cpumask_t *mask)
{
int cpu;
diff --git a/lib/debugobjects.c b/lib/debugobjects.c
index 85b18d79be8..f86196390cf 100644
--- a/lib/debugobjects.c
+++ b/lib/debugobjects.c
@@ -226,15 +226,13 @@ debug_object_fixup(int (*fixup)(void *addr, enum debug_obj_state state),
static void debug_object_is_on_stack(void *addr, int onstack)
{
- void *stack = current->stack;
int is_on_stack;
static int limit;
if (limit > 4)
return;
- is_on_stack = (addr >= stack && addr < (stack + THREAD_SIZE));
-
+ is_on_stack = object_is_on_stack(addr);
if (is_on_stack == onstack)
return;
diff --git a/lib/idr.c b/lib/idr.c
index 7a02e173f02..3476f8203e9 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -6,6 +6,8 @@
* Modified by George Anzinger to reuse immediately and to use
* find bit instructions. Also removed _irq on spinlocks.
*
+ * Modified by Nadia Derbey to make it RCU safe.
+ *
* Small id to pointer translation service.
*
* It uses a radix tree like structure as a sparse array indexed
@@ -35,7 +37,7 @@
static struct kmem_cache *idr_layer_cache;
-static struct idr_layer *alloc_layer(struct idr *idp)
+static struct idr_layer *get_from_free_list(struct idr *idp)
{
struct idr_layer *p;
unsigned long flags;
@@ -50,15 +52,28 @@ static struct idr_layer *alloc_layer(struct idr *idp)
return(p);
}
+static void idr_layer_rcu_free(struct rcu_head *head)
+{
+ struct idr_layer *layer;
+
+ layer = container_of(head, struct idr_layer, rcu_head);
+ kmem_cache_free(idr_layer_cache, layer);
+}
+
+static inline void free_layer(struct idr_layer *p)
+{
+ call_rcu(&p->rcu_head, idr_layer_rcu_free);
+}
+
/* only called when idp->lock is held */
-static void __free_layer(struct idr *idp, struct idr_layer *p)
+static void __move_to_free_list(struct idr *idp, struct idr_layer *p)
{
p->ary[0] = idp->id_free;
idp->id_free = p;
idp->id_free_cnt++;
}
-static void free_layer(struct idr *idp, struct idr_layer *p)
+static void move_to_free_list(struct idr *idp, struct idr_layer *p)
{
unsigned long flags;
@@ -66,7 +81,7 @@ static void free_layer(struct idr *idp, struct idr_layer *p)
* Depends on the return element being zeroed.
*/
spin_lock_irqsave(&idp->lock, flags);
- __free_layer(idp, p);
+ __move_to_free_list(idp, p);
spin_unlock_irqrestore(&idp->lock, flags);
}
@@ -96,7 +111,7 @@ static void idr_mark_full(struct idr_layer **pa, int id)
* @gfp_mask: memory allocation flags
*
* This function should be called prior to locking and calling the
- * following function. It preallocates enough memory to satisfy
+ * idr_get_new* functions. It preallocates enough memory to satisfy
* the worst possible allocation.
*
* If the system is REALLY out of memory this function returns 0,
@@ -109,7 +124,7 @@ int idr_pre_get(struct idr *idp, gfp_t gfp_mask)
new = kmem_cache_alloc(idr_layer_cache, gfp_mask);
if (new == NULL)
return (0);
- free_layer(idp, new);
+ move_to_free_list(idp, new);
}
return 1;
}
@@ -143,7 +158,7 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
/* if already at the top layer, we need to grow */
if (!(p = pa[l])) {
*starting_id = id;
- return -2;
+ return IDR_NEED_TO_GROW;
}
/* If we need to go up one layer, continue the
@@ -160,16 +175,17 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
id = ((id >> sh) ^ n ^ m) << sh;
}
if ((id >= MAX_ID_BIT) || (id < 0))
- return -3;
+ return IDR_NOMORE_SPACE;
if (l == 0)
break;
/*
* Create the layer below if it is missing.
*/
if (!p->ary[m]) {
- if (!(new = alloc_layer(idp)))
+ new = get_from_free_list(idp);
+ if (!new)
return -1;
- p->ary[m] = new;
+ rcu_assign_pointer(p->ary[m], new);
p->count++;
}
pa[l--] = p;
@@ -192,7 +208,7 @@ build_up:
p = idp->top;
layers = idp->layers;
if (unlikely(!p)) {
- if (!(p = alloc_layer(idp)))
+ if (!(p = get_from_free_list(idp)))
return -1;
layers = 1;
}
@@ -204,7 +220,7 @@ build_up:
layers++;
if (!p->count)
continue;
- if (!(new = alloc_layer(idp))) {
+ if (!(new = get_from_free_list(idp))) {
/*
* The allocation failed. If we built part of
* the structure tear it down.
@@ -214,7 +230,7 @@ build_up:
p = p->ary[0];
new->ary[0] = NULL;
new->bitmap = new->count = 0;
- __free_layer(idp, new);
+ __move_to_free_list(idp, new);
}
spin_unlock_irqrestore(&idp->lock, flags);
return -1;
@@ -225,10 +241,10 @@ build_up:
__set_bit(0, &new->bitmap);
p = new;
}
- idp->top = p;
+ rcu_assign_pointer(idp->top, p);
idp->layers = layers;
v = sub_alloc(idp, &id, pa);
- if (v == -2)
+ if (v == IDR_NEED_TO_GROW)
goto build_up;
return(v);
}
@@ -244,7 +260,8 @@ static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
* Successfully found an empty slot. Install the user
* pointer and mark the slot full.
*/
- pa[0]->ary[id & IDR_MASK] = (struct idr_layer *)ptr;
+ rcu_assign_pointer(pa[0]->ary[id & IDR_MASK],
+ (struct idr_layer *)ptr);
pa[0]->count++;
idr_mark_full(pa, id);
}
@@ -277,12 +294,8 @@ int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
* This is a cheap hack until the IDR code can be fixed to
* return proper error values.
*/
- if (rv < 0) {
- if (rv == -1)
- return -EAGAIN;
- else /* Will be -3 */
- return -ENOSPC;
- }
+ if (rv < 0)
+ return _idr_rc_to_errno(rv);
*id = rv;
return 0;
}
@@ -312,12 +325,8 @@ int idr_get_new(struct idr *idp, void *ptr, int *id)
* This is a cheap hack until the IDR code can be fixed to
* return proper error values.
*/
- if (rv < 0) {
- if (rv == -1)
- return -EAGAIN;
- else /* Will be -3 */
- return -ENOSPC;
- }
+ if (rv < 0)
+ return _idr_rc_to_errno(rv);
*id = rv;
return 0;
}
@@ -325,7 +334,8 @@ EXPORT_SYMBOL(idr_get_new);
static void idr_remove_warning(int id)
{
- printk("idr_remove called for id=%d which is not allocated.\n", id);
+ printk(KERN_WARNING
+ "idr_remove called for id=%d which is not allocated.\n", id);
dump_stack();
}
@@ -334,6 +344,7 @@ static void sub_remove(struct idr *idp, int shift, int id)
struct idr_layer *p = idp->top;
struct idr_layer **pa[MAX_LEVEL];
struct idr_layer ***paa = &pa[0];
+ struct idr_layer *to_free;
int n;
*paa = NULL;
@@ -349,13 +360,18 @@ static void sub_remove(struct idr *idp, int shift, int id)
n = id & IDR_MASK;
if (likely(p != NULL && test_bit(n, &p->bitmap))){
__clear_bit(n, &p->bitmap);
- p->ary[n] = NULL;
+ rcu_assign_pointer(p->ary[n], NULL);
+ to_free = NULL;
while(*paa && ! --((**paa)->count)){
- free_layer(idp, **paa);
+ if (to_free)
+ free_layer(to_free);
+ to_free = **paa;
**paa-- = NULL;
}
if (!*paa)
idp->layers = 0;
+ if (to_free)
+ free_layer(to_free);
} else
idr_remove_warning(id);
}
@@ -368,22 +384,34 @@ static void sub_remove(struct idr *idp, int shift, int id)
void idr_remove(struct idr *idp, int id)
{
struct idr_layer *p;
+ struct idr_layer *to_free;
/* Mask off upper bits we don't use for the search. */
id &= MAX_ID_MASK;
sub_remove(idp, (idp->layers - 1) * IDR_BITS, id);
if (idp->top && idp->top->count == 1 && (idp->layers > 1) &&
- idp->top->ary[0]) { // We can drop a layer
-
+ idp->top->ary[0]) {
+ /*
+ * Single child at leftmost slot: we can shrink the tree.
+ * This level is not needed anymore since when layers are
+ * inserted, they are inserted at the top of the existing
+ * tree.
+ */
+ to_free = idp->top;
p = idp->top->ary[0];
- idp->top->bitmap = idp->top->count = 0;
- free_layer(idp, idp->top);
- idp->top = p;
+ rcu_assign_pointer(idp->top, p);
--idp->layers;
+ to_free->bitmap = to_free->count = 0;
+ free_layer(to_free);
}
while (idp->id_free_cnt >= IDR_FREE_MAX) {
- p = alloc_layer(idp);
+ p = get_from_free_list(idp);
+ /*
+ * Note: we don't call the rcu callback here, since the only
+ * layers that fall into the freelist are those that have been
+ * preallocated.
+ */
kmem_cache_free(idr_layer_cache, p);
}
return;
@@ -424,15 +452,13 @@ void idr_remove_all(struct idr *idp)
id += 1 << n;
while (n < fls(id)) {
- if (p) {
- memset(p, 0, sizeof *p);
- free_layer(idp, p);
- }
+ if (p)
+ free_layer(p);
n += IDR_BITS;
p = *--paa;
}
}
- idp->top = NULL;
+ rcu_assign_pointer(idp->top, NULL);
idp->layers = 0;
}
EXPORT_SYMBOL(idr_remove_all);
@@ -444,7 +470,7 @@ EXPORT_SYMBOL(idr_remove_all);
void idr_destroy(struct idr *idp)
{
while (idp->id_free_cnt) {
- struct idr_layer *p = alloc_layer(idp);
+ struct idr_layer *p = get_from_free_list(idp);
kmem_cache_free(idr_layer_cache, p);
}
}
@@ -459,7 +485,8 @@ EXPORT_SYMBOL(idr_destroy);
* return indicates that @id is not valid or you passed %NULL in
* idr_get_new().
*
- * The caller must serialize idr_find() vs idr_get_new() and idr_remove().
+ * This function can be called under rcu_read_lock(), given that the leaf
+ * pointers lifetimes are correctly managed.
*/
void *idr_find(struct idr *idp, int id)
{
@@ -467,7 +494,7 @@ void *idr_find(struct idr *idp, int id)
struct idr_layer *p;
n = idp->layers * IDR_BITS;
- p = idp->top;
+ p = rcu_dereference(idp->top);
/* Mask off upper bits we don't use for the search. */
id &= MAX_ID_MASK;
@@ -477,7 +504,7 @@ void *idr_find(struct idr *idp, int id)
while (n > 0 && p) {
n -= IDR_BITS;
- p = p->ary[(id >> n) & IDR_MASK];
+ p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
}
return((void *)p);
}
@@ -510,7 +537,7 @@ int idr_for_each(struct idr *idp,
struct idr_layer **paa = &pa[0];
n = idp->layers * IDR_BITS;
- p = idp->top;
+ p = rcu_dereference(idp->top);
max = 1 << n;
id = 0;
@@ -518,7 +545,7 @@ int idr_for_each(struct idr *idp,
while (n > 0 && p) {
n -= IDR_BITS;
*paa++ = p;
- p = p->ary[(id >> n) & IDR_MASK];
+ p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
}
if (p) {
@@ -548,7 +575,7 @@ EXPORT_SYMBOL(idr_for_each);
* A -ENOENT return indicates that @id was not found.
* A -EINVAL return indicates that @id was not within valid constraints.
*
- * The caller must serialize vs idr_find(), idr_get_new(), and idr_remove().
+ * The caller must serialize with writers.
*/
void *idr_replace(struct idr *idp, void *ptr, int id)
{
@@ -574,7 +601,7 @@ void *idr_replace(struct idr *idp, void *ptr, int id)
return ERR_PTR(-ENOENT);
old_p = p->ary[n];
- p->ary[n] = ptr;
+ rcu_assign_pointer(p->ary[n], ptr);
return old_p;
}
@@ -694,12 +721,8 @@ int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
restart:
/* get vacant slot */
t = idr_get_empty_slot(&ida->idr, idr_id, pa);
- if (t < 0) {
- if (t == -1)
- return -EAGAIN;
- else /* will be -3 */
- return -ENOSPC;
- }
+ if (t < 0)
+ return _idr_rc_to_errno(t);
if (t * IDA_BITMAP_BITS >= MAX_ID_BIT)
return -ENOSPC;
@@ -720,7 +743,8 @@ int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
return -EAGAIN;
memset(bitmap, 0, sizeof(struct ida_bitmap));
- pa[0]->ary[idr_id & IDR_MASK] = (void *)bitmap;
+ rcu_assign_pointer(pa[0]->ary[idr_id & IDR_MASK],
+ (void *)bitmap);
pa[0]->count++;
}
@@ -749,7 +773,7 @@ int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
* allocation.
*/
if (ida->idr.id_free_cnt || ida->free_bitmap) {
- struct idr_layer *p = alloc_layer(&ida->idr);
+ struct idr_layer *p = get_from_free_list(&ida->idr);
if (p)
kmem_cache_free(idr_layer_cache, p);
}
diff --git a/lib/inflate.c b/lib/inflate.c
index 9762294be06..1a8e8a97812 100644
--- a/lib/inflate.c
+++ b/lib/inflate.c
@@ -230,6 +230,45 @@ STATIC const ush mask_bits[] = {
#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
#define DUMPBITS(n) {b>>=(n);k-=(n);}
+#ifndef NO_INFLATE_MALLOC
+/* A trivial malloc implementation, adapted from
+ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
+ */
+
+static unsigned long malloc_ptr;
+static int malloc_count;
+
+static void *malloc(int size)
+{
+ void *p;
+
+ if (size < 0)
+ error("Malloc error");
+ if (!malloc_ptr)
+ malloc_ptr = free_mem_ptr;
+
+ malloc_ptr = (malloc_ptr + 3) & ~3; /* Align */
+
+ p = (void *)malloc_ptr;
+ malloc_ptr += size;
+
+ if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr)
+ error("Out of memory");
+
+ malloc_count++;
+ return p;
+}
+
+static void free(void *where)
+{
+ malloc_count--;
+ if (!malloc_count)
+ malloc_ptr = free_mem_ptr;
+}
+#else
+#define malloc(a) kmalloc(a, GFP_KERNEL)
+#define free(a) kfree(a)
+#endif
/*
Huffman code decoding is performed using a multi-level table lookup.
@@ -1045,7 +1084,6 @@ STATIC int INIT inflate(void)
int e; /* last block flag */
int r; /* result code */
unsigned h; /* maximum struct huft's malloc'ed */
- void *ptr;
/* initialize window, bit buffer */
wp = 0;
@@ -1057,12 +1095,12 @@ STATIC int INIT inflate(void)
h = 0;
do {
hufts = 0;
- gzip_mark(&ptr);
- if ((r = inflate_block(&e)) != 0) {
- gzip_release(&ptr);
- return r;
- }
- gzip_release(&ptr);
+#ifdef ARCH_HAS_DECOMP_WDOG
+ arch_decomp_wdog();
+#endif
+ r = inflate_block(&e);
+ if (r)
+ return r;
if (hufts > h)
h = hufts;
} while (!e);
diff --git a/lib/kobject.c b/lib/kobject.c
index dcade0543bd..bd732ffebc8 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -164,9 +164,8 @@ static int kobject_add_internal(struct kobject *kobj)
return -ENOENT;
if (!kobj->name || !kobj->name[0]) {
- pr_debug("kobject: (%p): attempted to be registered with empty "
+ WARN(1, "kobject: (%p): attempted to be registered with empty "
"name!\n", kobj);
- WARN_ON(1);
return -EINVAL;
}
@@ -216,13 +215,19 @@ static int kobject_add_internal(struct kobject *kobj)
static int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
va_list vargs)
{
- /* Free the old name, if necessary. */
- kfree(kobj->name);
+ const char *old_name = kobj->name;
+ char *s;
kobj->name = kvasprintf(GFP_KERNEL, fmt, vargs);
if (!kobj->name)
return -ENOMEM;
+ /* ewww... some of these buggers have '/' in the name ... */
+ s = strchr(kobj->name, '/');
+ if (s)
+ s[0] = '!';
+
+ kfree(old_name);
return 0;
}
@@ -577,12 +582,10 @@ static void kobject_release(struct kref *kref)
void kobject_put(struct kobject *kobj)
{
if (kobj) {
- if (!kobj->state_initialized) {
- printk(KERN_WARNING "kobject: '%s' (%p): is not "
+ if (!kobj->state_initialized)
+ WARN(1, KERN_WARNING "kobject: '%s' (%p): is not "
"initialized, yet kobject_put() is being "
"called.\n", kobject_name(kobj), kobj);
- WARN_ON(1);
- }
kref_put(&kobj->kref, kobject_release);
}
}
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 2fa545a6316..9f8d599459d 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -245,7 +245,8 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
if (retval)
goto exit;
- call_usermodehelper(argv[0], argv, env->envp, UMH_WAIT_EXEC);
+ retval = call_usermodehelper(argv[0], argv,
+ env->envp, UMH_WAIT_EXEC);
}
exit:
diff --git a/lib/list_debug.c b/lib/list_debug.c
index 4350ba9655b..1a39f4e3ae1 100644
--- a/lib/list_debug.c
+++ b/lib/list_debug.c
@@ -20,18 +20,14 @@ void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
- if (unlikely(next->prev != prev)) {
- printk(KERN_ERR "list_add corruption. next->prev should be "
- "prev (%p), but was %p. (next=%p).\n",
- prev, next->prev, next);
- BUG();
- }
- if (unlikely(prev->next != next)) {
- printk(KERN_ERR "list_add corruption. prev->next should be "
- "next (%p), but was %p. (prev=%p).\n",
- next, prev->next, prev);
- BUG();
- }
+ WARN(next->prev != prev,
+ "list_add corruption. next->prev should be "
+ "prev (%p), but was %p. (next=%p).\n",
+ prev, next->prev, next);
+ WARN(prev->next != next,
+ "list_add corruption. prev->next should be "
+ "next (%p), but was %p. (prev=%p).\n",
+ next, prev->next, prev);
next->prev = new;
new->next = next;
new->prev = prev;
@@ -40,20 +36,6 @@ void __list_add(struct list_head *new,
EXPORT_SYMBOL(__list_add);
/**
- * list_add - add a new entry
- * @new: new entry to be added
- * @head: list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-void list_add(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head, head->next);
-}
-EXPORT_SYMBOL(list_add);
-
-/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty on entry does not return true after this, the entry is
@@ -61,16 +43,12 @@ EXPORT_SYMBOL(list_add);
*/
void list_del(struct list_head *entry)
{
- if (unlikely(entry->prev->next != entry)) {
- printk(KERN_ERR "list_del corruption. prev->next should be %p, "
- "but was %p\n", entry, entry->prev->next);
- BUG();
- }
- if (unlikely(entry->next->prev != entry)) {
- printk(KERN_ERR "list_del corruption. next->prev should be %p, "
- "but was %p\n", entry, entry->next->prev);
- BUG();
- }
+ WARN(entry->prev->next != entry,
+ "list_del corruption. prev->next should be %p, "
+ "but was %p\n", entry, entry->prev->next);
+ WARN(entry->next->prev != entry,
+ "list_del corruption. next->prev should be %p, "
+ "but was %p\n", entry, entry->next->prev);
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
diff --git a/lib/lzo/lzo1x_decompress.c b/lib/lzo/lzo1x_decompress.c
index 77f0f9b775a..5dc6b29c157 100644
--- a/lib/lzo/lzo1x_decompress.c
+++ b/lib/lzo/lzo1x_decompress.c
@@ -138,8 +138,7 @@ match:
t += 31 + *ip++;
}
m_pos = op - 1;
- m_pos -= le16_to_cpu(get_unaligned(
- (const unsigned short *)ip)) >> 2;
+ m_pos -= get_unaligned_le16(ip) >> 2;
ip += 2;
} else if (t >= 16) {
m_pos = op;
@@ -157,8 +156,7 @@ match:
}
t += 7 + *ip++;
}
- m_pos -= le16_to_cpu(get_unaligned(
- (const unsigned short *)ip)) >> 2;
+ m_pos -= get_unaligned_le16(ip) >> 2;
ip += 2;
if (m_pos == op)
goto eof_found;
diff --git a/lib/ratelimit.c b/lib/ratelimit.c
index 485e3040dcd..35136671b21 100644
--- a/lib/ratelimit.c
+++ b/lib/ratelimit.c
@@ -3,6 +3,9 @@
*
* Isolated from kernel/printk.c by Dave Young <hidave.darkstar@gmail.com>
*
+ * 2008-05-01 rewrite the function and use a ratelimit_state data struct as
+ * parameter. Now every user can use their own standalone ratelimit_state.
+ *
* This file is released under the GPLv2.
*
*/
@@ -11,41 +14,43 @@
#include <linux/jiffies.h>
#include <linux/module.h>
+static DEFINE_SPINLOCK(ratelimit_lock);
+static unsigned long flags;
+
/*
* __ratelimit - rate limiting
- * @ratelimit_jiffies: minimum time in jiffies between two callbacks
- * @ratelimit_burst: number of callbacks we do before ratelimiting
+ * @rs: ratelimit_state data
*
- * This enforces a rate limit: not more than @ratelimit_burst callbacks
- * in every ratelimit_jiffies
+ * This enforces a rate limit: not more than @rs->ratelimit_burst callbacks
+ * in every @rs->ratelimit_jiffies
*/
-int __ratelimit(int ratelimit_jiffies, int ratelimit_burst)
+int __ratelimit(struct ratelimit_state *rs)
{
- static DEFINE_SPINLOCK(ratelimit_lock);
- static unsigned toks = 10 * 5 * HZ;
- static unsigned long last_msg;
- static int missed;
- unsigned long flags;
- unsigned long now = jiffies;
+ if (!rs->interval)
+ return 1;
spin_lock_irqsave(&ratelimit_lock, flags);
- toks += now - last_msg;
- last_msg = now;
- if (toks > (ratelimit_burst * ratelimit_jiffies))
- toks = ratelimit_burst * ratelimit_jiffies;
- if (toks >= ratelimit_jiffies) {
- int lost = missed;
+ if (!rs->begin)
+ rs->begin = jiffies;
- missed = 0;
- toks -= ratelimit_jiffies;
- spin_unlock_irqrestore(&ratelimit_lock, flags);
- if (lost)
- printk(KERN_WARNING "%s: %d messages suppressed\n",
- __func__, lost);
- return 1;
+ if (time_is_before_jiffies(rs->begin + rs->interval)) {
+ if (rs->missed)
+ printk(KERN_WARNING "%s: %d callbacks suppressed\n",
+ __func__, rs->missed);
+ rs->begin = 0;
+ rs->printed = 0;
+ rs->missed = 0;
}
- missed++;
+ if (rs->burst && rs->burst > rs->printed)
+ goto print;
+
+ rs->missed++;
spin_unlock_irqrestore(&ratelimit_lock, flags);
return 0;
+
+print:
+ rs->printed++;
+ spin_unlock_irqrestore(&ratelimit_lock, flags);
+ return 1;
}
EXPORT_SYMBOL(__ratelimit);
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index b80c21100d7..876ba6d5b67 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -295,6 +295,117 @@ int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask)
EXPORT_SYMBOL(sg_alloc_table);
/**
+ * sg_miter_start - start mapping iteration over a sg list
+ * @miter: sg mapping iter to be started
+ * @sgl: sg list to iterate over
+ * @nents: number of sg entries
+ *
+ * Description:
+ * Starts mapping iterator @miter.
+ *
+ * Context:
+ * Don't care.
+ */
+void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl,
+ unsigned int nents, unsigned int flags)
+{
+ memset(miter, 0, sizeof(struct sg_mapping_iter));
+
+ miter->__sg = sgl;
+ miter->__nents = nents;
+ miter->__offset = 0;
+ miter->__flags = flags;
+}
+EXPORT_SYMBOL(sg_miter_start);
+
+/**
+ * sg_miter_next - proceed mapping iterator to the next mapping
+ * @miter: sg mapping iter to proceed
+ *
+ * Description:
+ * Proceeds @miter@ to the next mapping. @miter@ should have been
+ * started using sg_miter_start(). On successful return,
+ * @miter@->page, @miter@->addr and @miter@->length point to the
+ * current mapping.
+ *
+ * Context:
+ * IRQ disabled if SG_MITER_ATOMIC. IRQ must stay disabled till
+ * @miter@ is stopped. May sleep if !SG_MITER_ATOMIC.
+ *
+ * Returns:
+ * true if @miter contains the next mapping. false if end of sg
+ * list is reached.
+ */
+bool sg_miter_next(struct sg_mapping_iter *miter)
+{
+ unsigned int off, len;
+
+ /* check for end and drop resources from the last iteration */
+ if (!miter->__nents)
+ return false;
+
+ sg_miter_stop(miter);
+
+ /* get to the next sg if necessary. __offset is adjusted by stop */
+ if (miter->__offset == miter->__sg->length && --miter->__nents) {
+ miter->__sg = sg_next(miter->__sg);
+ miter->__offset = 0;
+ }
+
+ /* map the next page */
+ off = miter->__sg->offset + miter->__offset;
+ len = miter->__sg->length - miter->__offset;
+
+ miter->page = nth_page(sg_page(miter->__sg), off >> PAGE_SHIFT);
+ off &= ~PAGE_MASK;
+ miter->length = min_t(unsigned int, len, PAGE_SIZE - off);
+ miter->consumed = miter->length;
+
+ if (miter->__flags & SG_MITER_ATOMIC)
+ miter->addr = kmap_atomic(miter->page, KM_BIO_SRC_IRQ) + off;
+ else
+ miter->addr = kmap(miter->page) + off;
+
+ return true;
+}
+EXPORT_SYMBOL(sg_miter_next);
+
+/**
+ * sg_miter_stop - stop mapping iteration
+ * @miter: sg mapping iter to be stopped
+ *
+ * Description:
+ * Stops mapping iterator @miter. @miter should have been started
+ * started using sg_miter_start(). A stopped iteration can be
+ * resumed by calling sg_miter_next() on it. This is useful when
+ * resources (kmap) need to be released during iteration.
+ *
+ * Context:
+ * IRQ disabled if the SG_MITER_ATOMIC is set. Don't care otherwise.
+ */
+void sg_miter_stop(struct sg_mapping_iter *miter)
+{
+ WARN_ON(miter->consumed > miter->length);
+
+ /* drop resources from the last iteration */
+ if (miter->addr) {
+ miter->__offset += miter->consumed;
+
+ if (miter->__flags & SG_MITER_ATOMIC) {
+ WARN_ON(!irqs_disabled());
+ kunmap_atomic(miter->addr, KM_BIO_SRC_IRQ);
+ } else
+ kunmap(miter->addr);
+
+ miter->page = NULL;
+ miter->addr = NULL;
+ miter->length = 0;
+ miter->consumed = 0;
+ }
+}
+EXPORT_SYMBOL(sg_miter_stop);
+
+/**
* sg_copy_buffer - Copy data between a linear buffer and an SG list
* @sgl: The SG list
* @nents: Number of SG entries
@@ -309,56 +420,29 @@ EXPORT_SYMBOL(sg_alloc_table);
static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents,
void *buf, size_t buflen, int to_buffer)
{
- struct scatterlist *sg;
- size_t buf_off = 0;
- int i;
-
- WARN_ON(!irqs_disabled());
-
- for_each_sg(sgl, sg, nents, i) {
- struct page *page;
- int n = 0;
- unsigned int sg_off = sg->offset;
- unsigned int sg_copy = sg->length;
-
- if (sg_copy > buflen)
- sg_copy = buflen;
- buflen -= sg_copy;
-
- while (sg_copy > 0) {
- unsigned int page_copy;
- void *p;
-
- page_copy = PAGE_SIZE - sg_off;
- if (page_copy > sg_copy)
- page_copy = sg_copy;
-
- page = nth_page(sg_page(sg), n);
- p = kmap_atomic(page, KM_BIO_SRC_IRQ);
-
- if (to_buffer)
- memcpy(buf + buf_off, p + sg_off, page_copy);
- else {
- memcpy(p + sg_off, buf + buf_off, page_copy);
- flush_kernel_dcache_page(page);
- }
-
- kunmap_atomic(p, KM_BIO_SRC_IRQ);
-
- buf_off += page_copy;
- sg_off += page_copy;
- if (sg_off == PAGE_SIZE) {
- sg_off = 0;
- n++;
- }
- sg_copy -= page_copy;
+ unsigned int offset = 0;
+ struct sg_mapping_iter miter;
+
+ sg_miter_start(&miter, sgl, nents, SG_MITER_ATOMIC);
+
+ while (sg_miter_next(&miter) && offset < buflen) {
+ unsigned int len;
+
+ len = min(miter.length, buflen - offset);
+
+ if (to_buffer)
+ memcpy(buf + offset, miter.addr, len);
+ else {
+ memcpy(miter.addr, buf + offset, len);
+ flush_kernel_dcache_page(miter.page);
}
- if (!buflen)
- break;
+ offset += len;
}
- return buf_off;
+ sg_miter_stop(&miter);
+
+ return offset;
}
/**
diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c
index 3b4dc098181..c4381d9516f 100644
--- a/lib/smp_processor_id.c
+++ b/lib/smp_processor_id.c
@@ -11,7 +11,7 @@ notrace unsigned int debug_smp_processor_id(void)
{
unsigned long preempt_count = preempt_count();
int this_cpu = raw_smp_processor_id();
- cpumask_t this_mask;
+ cpumask_of_cpu_ptr_declare(this_mask);
if (likely(preempt_count))
goto out;
@@ -23,9 +23,9 @@ notrace unsigned int debug_smp_processor_id(void)
* Kernel threads bound to a single CPU can safely use
* smp_processor_id():
*/
- this_mask = cpumask_of_cpu(this_cpu);
+ cpumask_of_cpu_ptr_next(this_mask, this_cpu);
- if (cpus_equal(current->cpus_allowed, this_mask))
+ if (cpus_equal(current->cpus_allowed, *this_mask))
goto out;
/*
diff --git a/lib/textsearch.c b/lib/textsearch.c
index 4b7c6075256..9fbcb44c554 100644
--- a/lib/textsearch.c
+++ b/lib/textsearch.c
@@ -267,7 +267,7 @@ struct ts_config *textsearch_prepare(const char *algo, const void *pattern,
return ERR_PTR(-EINVAL);
ops = lookup_ts_algo(algo);
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
/*
* Why not always autoload you may ask. Some users are
* in a situation where requesting a module may deadlock,
diff --git a/mm/Kconfig b/mm/Kconfig
index c4de85285bb..aa799007a11 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -174,7 +174,7 @@ config SPLIT_PTLOCK_CPUS
config MIGRATION
bool "Page migration"
def_bool y
- depends on NUMA
+ depends on NUMA || ARCH_ENABLE_MEMORY_HOTREMOVE
help
Allows the migration of the physical location of pages of processes
while the virtual addresses are not changed. This is useful for
diff --git a/mm/Makefile b/mm/Makefile
index 18c143b3c46..06ca2381fef 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -11,7 +11,7 @@ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
maccess.o page_alloc.o page-writeback.o pdflush.o \
readahead.o swap.o truncate.o vmscan.o \
prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
- page_isolation.o $(mmu-y)
+ page_isolation.o mm_init.o $(mmu-y)
obj-$(CONFIG_PROC_PAGE_MONITOR) += pagewalk.o
obj-$(CONFIG_BOUNCE) += bounce.o
diff --git a/mm/allocpercpu.c b/mm/allocpercpu.c
index 05f2b4009cc..843364594e2 100644
--- a/mm/allocpercpu.c
+++ b/mm/allocpercpu.c
@@ -35,7 +35,7 @@ EXPORT_SYMBOL_GPL(percpu_depopulate);
void __percpu_depopulate_mask(void *__pdata, cpumask_t *mask)
{
int cpu;
- for_each_cpu_mask(cpu, *mask)
+ for_each_cpu_mask_nr(cpu, *mask)
percpu_depopulate(__pdata, cpu);
}
EXPORT_SYMBOL_GPL(__percpu_depopulate_mask);
@@ -86,7 +86,7 @@ int __percpu_populate_mask(void *__pdata, size_t size, gfp_t gfp,
int cpu;
cpus_clear(populated);
- for_each_cpu_mask(cpu, *mask)
+ for_each_cpu_mask_nr(cpu, *mask)
if (unlikely(!percpu_populate(__pdata, size, gfp, cpu))) {
__percpu_depopulate_mask(__pdata, &populated);
return -ENOMEM;
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 8d9f60e06f6..4af15d0340a 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -1,12 +1,12 @@
/*
- * linux/mm/bootmem.c
+ * bootmem - A boot-time physical memory allocator and configurator
*
* Copyright (C) 1999 Ingo Molnar
- * Discontiguous memory support, Kanoj Sarcar, SGI, Nov 1999
+ * 1999 Kanoj Sarcar, SGI
+ * 2008 Johannes Weiner
*
- * simple boot-time physical memory area allocator and
- * free memory collector. It's used to deal with reserved
- * system memory and memory holes as well.
+ * Access to this subsystem has to be serialized externally (which is true
+ * for the boot process anyway).
*/
#include <linux/init.h>
#include <linux/pfn.h>
@@ -19,15 +19,10 @@
#include "internal.h"
-/*
- * Access to this subsystem has to be serialized externally. (this is
- * true for the boot process anyway)
- */
unsigned long max_low_pfn;
unsigned long min_low_pfn;
unsigned long max_pfn;
-static LIST_HEAD(bdata_list);
#ifdef CONFIG_CRASH_DUMP
/*
* If we have booted due to a crash, max_pfn will be a very low value. We need
@@ -36,63 +31,72 @@ static LIST_HEAD(bdata_list);
unsigned long saved_max_pfn;
#endif
-/* return the number of _pages_ that will be allocated for the boot bitmap */
-unsigned long __init bootmem_bootmap_pages(unsigned long pages)
+bootmem_data_t bootmem_node_data[MAX_NUMNODES] __initdata;
+
+static struct list_head bdata_list __initdata = LIST_HEAD_INIT(bdata_list);
+
+static int bootmem_debug;
+
+static int __init bootmem_debug_setup(char *buf)
{
- unsigned long mapsize;
+ bootmem_debug = 1;
+ return 0;
+}
+early_param("bootmem_debug", bootmem_debug_setup);
- mapsize = (pages+7)/8;
- mapsize = (mapsize + ~PAGE_MASK) & PAGE_MASK;
- mapsize >>= PAGE_SHIFT;
+#define bdebug(fmt, args...) ({ \
+ if (unlikely(bootmem_debug)) \
+ printk(KERN_INFO \
+ "bootmem::%s " fmt, \
+ __FUNCTION__, ## args); \
+})
- return mapsize;
+static unsigned long __init bootmap_bytes(unsigned long pages)
+{
+ unsigned long bytes = (pages + 7) / 8;
+
+ return ALIGN(bytes, sizeof(long));
}
-/*
- * link bdata in order
+/**
+ * bootmem_bootmap_pages - calculate bitmap size in pages
+ * @pages: number of pages the bitmap has to represent
*/
-static void __init link_bootmem(bootmem_data_t *bdata)
+unsigned long __init bootmem_bootmap_pages(unsigned long pages)
{
- bootmem_data_t *ent;
+ unsigned long bytes = bootmap_bytes(pages);
- if (list_empty(&bdata_list)) {
- list_add(&bdata->list, &bdata_list);
- return;
- }
- /* insert in order */
- list_for_each_entry(ent, &bdata_list, list) {
- if (bdata->node_boot_start < ent->node_boot_start) {
- list_add_tail(&bdata->list, &ent->list);
- return;
- }
- }
- list_add_tail(&bdata->list, &bdata_list);
+ return PAGE_ALIGN(bytes) >> PAGE_SHIFT;
}
/*
- * Given an initialised bdata, it returns the size of the boot bitmap
+ * link bdata in order
*/
-static unsigned long __init get_mapsize(bootmem_data_t *bdata)
+static void __init link_bootmem(bootmem_data_t *bdata)
{
- unsigned long mapsize;
- unsigned long start = PFN_DOWN(bdata->node_boot_start);
- unsigned long end = bdata->node_low_pfn;
+ struct list_head *iter;
- mapsize = ((end - start) + 7) / 8;
- return ALIGN(mapsize, sizeof(long));
+ list_for_each(iter, &bdata_list) {
+ bootmem_data_t *ent;
+
+ ent = list_entry(iter, bootmem_data_t, list);
+ if (bdata->node_min_pfn < ent->node_min_pfn)
+ break;
+ }
+ list_add_tail(&bdata->list, iter);
}
/*
* Called once to set up the allocator itself.
*/
-static unsigned long __init init_bootmem_core(pg_data_t *pgdat,
+static unsigned long __init init_bootmem_core(bootmem_data_t *bdata,
unsigned long mapstart, unsigned long start, unsigned long end)
{
- bootmem_data_t *bdata = pgdat->bdata;
unsigned long mapsize;
+ mminit_validate_memmodel_limits(&start, &end);
bdata->node_bootmem_map = phys_to_virt(PFN_PHYS(mapstart));
- bdata->node_boot_start = PFN_PHYS(start);
+ bdata->node_min_pfn = start;
bdata->node_low_pfn = end;
link_bootmem(bdata);
@@ -100,429 +104,461 @@ static unsigned long __init init_bootmem_core(pg_data_t *pgdat,
* Initially all pages are reserved - setup_arch() has to
* register free RAM areas explicitly.
*/
- mapsize = get_mapsize(bdata);
+ mapsize = bootmap_bytes(end - start);
memset(bdata->node_bootmem_map, 0xff, mapsize);
+ bdebug("nid=%td start=%lx map=%lx end=%lx mapsize=%lx\n",
+ bdata - bootmem_node_data, start, mapstart, end, mapsize);
+
return mapsize;
}
-/*
- * Marks a particular physical memory range as unallocatable. Usable RAM
- * might be used for boot-time allocations - or it might get added
- * to the free page pool later on.
+/**
+ * init_bootmem_node - register a node as boot memory
+ * @pgdat: node to register
+ * @freepfn: pfn where the bitmap for this node is to be placed
+ * @startpfn: first pfn on the node
+ * @endpfn: first pfn after the node
+ *
+ * Returns the number of bytes needed to hold the bitmap for this node.
*/
-static int __init can_reserve_bootmem_core(bootmem_data_t *bdata,
- unsigned long addr, unsigned long size, int flags)
+unsigned long __init init_bootmem_node(pg_data_t *pgdat, unsigned long freepfn,
+ unsigned long startpfn, unsigned long endpfn)
{
- unsigned long sidx, eidx;
- unsigned long i;
+ return init_bootmem_core(pgdat->bdata, freepfn, startpfn, endpfn);
+}
- BUG_ON(!size);
+/**
+ * init_bootmem - register boot memory
+ * @start: pfn where the bitmap is to be placed
+ * @pages: number of available physical pages
+ *
+ * Returns the number of bytes needed to hold the bitmap.
+ */
+unsigned long __init init_bootmem(unsigned long start, unsigned long pages)
+{
+ max_low_pfn = pages;
+ min_low_pfn = start;
+ return init_bootmem_core(NODE_DATA(0)->bdata, start, 0, pages);
+}
- /* out of range, don't hold other */
- if (addr + size < bdata->node_boot_start ||
- PFN_DOWN(addr) > bdata->node_low_pfn)
+static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
+{
+ int aligned;
+ struct page *page;
+ unsigned long start, end, pages, count = 0;
+
+ if (!bdata->node_bootmem_map)
return 0;
+ start = bdata->node_min_pfn;
+ end = bdata->node_low_pfn;
+
/*
- * Round up to index to the range.
+ * If the start is aligned to the machines wordsize, we might
+ * be able to free pages in bulks of that order.
*/
- if (addr > bdata->node_boot_start)
- sidx= PFN_DOWN(addr - bdata->node_boot_start);
- else
- sidx = 0;
+ aligned = !(start & (BITS_PER_LONG - 1));
- eidx = PFN_UP(addr + size - bdata->node_boot_start);
- if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start))
- eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start);
+ bdebug("nid=%td start=%lx end=%lx aligned=%d\n",
+ bdata - bootmem_node_data, start, end, aligned);
- for (i = sidx; i < eidx; i++) {
- if (test_bit(i, bdata->node_bootmem_map)) {
- if (flags & BOOTMEM_EXCLUSIVE)
- return -EBUSY;
- }
- }
+ while (start < end) {
+ unsigned long *map, idx, vec;
- return 0;
+ map = bdata->node_bootmem_map;
+ idx = start - bdata->node_min_pfn;
+ vec = ~map[idx / BITS_PER_LONG];
-}
+ if (aligned && vec == ~0UL && start + BITS_PER_LONG < end) {
+ int order = ilog2(BITS_PER_LONG);
-static void __init reserve_bootmem_core(bootmem_data_t *bdata,
- unsigned long addr, unsigned long size, int flags)
-{
- unsigned long sidx, eidx;
- unsigned long i;
-
- BUG_ON(!size);
+ __free_pages_bootmem(pfn_to_page(start), order);
+ count += BITS_PER_LONG;
+ } else {
+ unsigned long off = 0;
- /* out of range */
- if (addr + size < bdata->node_boot_start ||
- PFN_DOWN(addr) > bdata->node_low_pfn)
- return;
+ while (vec && off < BITS_PER_LONG) {
+ if (vec & 1) {
+ page = pfn_to_page(start + off);
+ __free_pages_bootmem(page, 0);
+ count++;
+ }
+ vec >>= 1;
+ off++;
+ }
+ }
+ start += BITS_PER_LONG;
+ }
- /*
- * Round up to index to the range.
- */
- if (addr > bdata->node_boot_start)
- sidx= PFN_DOWN(addr - bdata->node_boot_start);
- else
- sidx = 0;
+ page = virt_to_page(bdata->node_bootmem_map);
+ pages = bdata->node_low_pfn - bdata->node_min_pfn;
+ pages = bootmem_bootmap_pages(pages);
+ count += pages;
+ while (pages--)
+ __free_pages_bootmem(page++, 0);
- eidx = PFN_UP(addr + size - bdata->node_boot_start);
- if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start))
- eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start);
+ bdebug("nid=%td released=%lx\n", bdata - bootmem_node_data, count);
- for (i = sidx; i < eidx; i++) {
- if (test_and_set_bit(i, bdata->node_bootmem_map)) {
-#ifdef CONFIG_DEBUG_BOOTMEM
- printk("hm, page %08lx reserved twice.\n", i*PAGE_SIZE);
-#endif
- }
- }
+ return count;
}
-static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr,
- unsigned long size)
+/**
+ * free_all_bootmem_node - release a node's free pages to the buddy allocator
+ * @pgdat: node to be released
+ *
+ * Returns the number of pages actually released.
+ */
+unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
{
- unsigned long sidx, eidx;
- unsigned long i;
-
- BUG_ON(!size);
+ register_page_bootmem_info_node(pgdat);
+ return free_all_bootmem_core(pgdat->bdata);
+}
- /* out range */
- if (addr + size < bdata->node_boot_start ||
- PFN_DOWN(addr) > bdata->node_low_pfn)
- return;
- /*
- * round down end of usable mem, partially free pages are
- * considered reserved.
- */
+/**
+ * free_all_bootmem - release free pages to the buddy allocator
+ *
+ * Returns the number of pages actually released.
+ */
+unsigned long __init free_all_bootmem(void)
+{
+ return free_all_bootmem_core(NODE_DATA(0)->bdata);
+}
- if (addr >= bdata->node_boot_start && addr < bdata->last_success)
- bdata->last_success = addr;
+static void __init __free(bootmem_data_t *bdata,
+ unsigned long sidx, unsigned long eidx)
+{
+ unsigned long idx;
- /*
- * Round up to index to the range.
- */
- if (PFN_UP(addr) > PFN_DOWN(bdata->node_boot_start))
- sidx = PFN_UP(addr) - PFN_DOWN(bdata->node_boot_start);
- else
- sidx = 0;
+ bdebug("nid=%td start=%lx end=%lx\n", bdata - bootmem_node_data,
+ sidx + bdata->node_min_pfn,
+ eidx + bdata->node_min_pfn);
- eidx = PFN_DOWN(addr + size - bdata->node_boot_start);
- if (eidx > bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start))
- eidx = bdata->node_low_pfn - PFN_DOWN(bdata->node_boot_start);
+ if (bdata->hint_idx > sidx)
+ bdata->hint_idx = sidx;
- for (i = sidx; i < eidx; i++) {
- if (unlikely(!test_and_clear_bit(i, bdata->node_bootmem_map)))
+ for (idx = sidx; idx < eidx; idx++)
+ if (!test_and_clear_bit(idx, bdata->node_bootmem_map))
BUG();
- }
}
-/*
- * We 'merge' subsequent allocations to save space. We might 'lose'
- * some fraction of a page if allocations cannot be satisfied due to
- * size constraints on boxes where there is physical RAM space
- * fragmentation - in these cases (mostly large memory boxes) this
- * is not a problem.
- *
- * On low memory boxes we get it right in 100% of the cases.
- *
- * alignment has to be a power of 2 value.
- *
- * NOTE: This function is _not_ reentrant.
- */
-void * __init
-__alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
- unsigned long align, unsigned long goal, unsigned long limit)
+static int __init __reserve(bootmem_data_t *bdata, unsigned long sidx,
+ unsigned long eidx, int flags)
{
- unsigned long areasize, preferred;
- unsigned long i, start = 0, incr, eidx, end_pfn;
- void *ret;
- unsigned long node_boot_start;
- void *node_bootmem_map;
-
- if (!size) {
- printk("__alloc_bootmem_core(): zero-sized request\n");
- BUG();
- }
- BUG_ON(align & (align-1));
-
- /* on nodes without memory - bootmem_map is NULL */
- if (!bdata->node_bootmem_map)
- return NULL;
+ unsigned long idx;
+ int exclusive = flags & BOOTMEM_EXCLUSIVE;
+
+ bdebug("nid=%td start=%lx end=%lx flags=%x\n",
+ bdata - bootmem_node_data,
+ sidx + bdata->node_min_pfn,
+ eidx + bdata->node_min_pfn,
+ flags);
+
+ for (idx = sidx; idx < eidx; idx++)
+ if (test_and_set_bit(idx, bdata->node_bootmem_map)) {
+ if (exclusive) {
+ __free(bdata, sidx, idx);
+ return -EBUSY;
+ }
+ bdebug("silent double reserve of PFN %lx\n",
+ idx + bdata->node_min_pfn);
+ }
+ return 0;
+}
- /* bdata->node_boot_start is supposed to be (12+6)bits alignment on x86_64 ? */
- node_boot_start = bdata->node_boot_start;
- node_bootmem_map = bdata->node_bootmem_map;
- if (align) {
- node_boot_start = ALIGN(bdata->node_boot_start, align);
- if (node_boot_start > bdata->node_boot_start)
- node_bootmem_map = (unsigned long *)bdata->node_bootmem_map +
- PFN_DOWN(node_boot_start - bdata->node_boot_start)/BITS_PER_LONG;
- }
+static int __init mark_bootmem_node(bootmem_data_t *bdata,
+ unsigned long start, unsigned long end,
+ int reserve, int flags)
+{
+ unsigned long sidx, eidx;
- if (limit && node_boot_start >= limit)
- return NULL;
+ bdebug("nid=%td start=%lx end=%lx reserve=%d flags=%x\n",
+ bdata - bootmem_node_data, start, end, reserve, flags);
- end_pfn = bdata->node_low_pfn;
- limit = PFN_DOWN(limit);
- if (limit && end_pfn > limit)
- end_pfn = limit;
+ BUG_ON(start < bdata->node_min_pfn);
+ BUG_ON(end > bdata->node_low_pfn);
- eidx = end_pfn - PFN_DOWN(node_boot_start);
+ sidx = start - bdata->node_min_pfn;
+ eidx = end - bdata->node_min_pfn;
- /*
- * We try to allocate bootmem pages above 'goal'
- * first, then we try to allocate lower pages.
- */
- preferred = 0;
- if (goal && PFN_DOWN(goal) < end_pfn) {
- if (goal > node_boot_start)
- preferred = goal - node_boot_start;
-
- if (bdata->last_success > node_boot_start &&
- bdata->last_success - node_boot_start >= preferred)
- if (!limit || (limit && limit > bdata->last_success))
- preferred = bdata->last_success - node_boot_start;
- }
+ if (reserve)
+ return __reserve(bdata, sidx, eidx, flags);
+ else
+ __free(bdata, sidx, eidx);
+ return 0;
+}
- preferred = PFN_DOWN(ALIGN(preferred, align));
- areasize = (size + PAGE_SIZE-1) / PAGE_SIZE;
- incr = align >> PAGE_SHIFT ? : 1;
+static int __init mark_bootmem(unsigned long start, unsigned long end,
+ int reserve, int flags)
+{
+ unsigned long pos;
+ bootmem_data_t *bdata;
-restart_scan:
- for (i = preferred; i < eidx;) {
- unsigned long j;
+ pos = start;
+ list_for_each_entry(bdata, &bdata_list, list) {
+ int err;
+ unsigned long max;
- i = find_next_zero_bit(node_bootmem_map, eidx, i);
- i = ALIGN(i, incr);
- if (i >= eidx)
- break;
- if (test_bit(i, node_bootmem_map)) {
- i += incr;
+ if (pos < bdata->node_min_pfn ||
+ pos >= bdata->node_low_pfn) {
+ BUG_ON(pos != start);
continue;
}
- for (j = i + 1; j < i + areasize; ++j) {
- if (j >= eidx)
- goto fail_block;
- if (test_bit(j, node_bootmem_map))
- goto fail_block;
- }
- start = i;
- goto found;
- fail_block:
- i = ALIGN(j, incr);
- if (i == j)
- i += incr;
- }
- if (preferred > 0) {
- preferred = 0;
- goto restart_scan;
- }
- return NULL;
+ max = min(bdata->node_low_pfn, end);
-found:
- bdata->last_success = PFN_PHYS(start) + node_boot_start;
- BUG_ON(start >= eidx);
-
- /*
- * Is the next page of the previous allocation-end the start
- * of this allocation's buffer? If yes then we can 'merge'
- * the previous partial page with this allocation.
- */
- if (align < PAGE_SIZE &&
- bdata->last_offset && bdata->last_pos+1 == start) {
- unsigned long offset, remaining_size;
- offset = ALIGN(bdata->last_offset, align);
- BUG_ON(offset > PAGE_SIZE);
- remaining_size = PAGE_SIZE - offset;
- if (size < remaining_size) {
- areasize = 0;
- /* last_pos unchanged */
- bdata->last_offset = offset + size;
- ret = phys_to_virt(bdata->last_pos * PAGE_SIZE +
- offset + node_boot_start);
- } else {
- remaining_size = size - remaining_size;
- areasize = (remaining_size + PAGE_SIZE-1) / PAGE_SIZE;
- ret = phys_to_virt(bdata->last_pos * PAGE_SIZE +
- offset + node_boot_start);
- bdata->last_pos = start + areasize - 1;
- bdata->last_offset = remaining_size;
+ err = mark_bootmem_node(bdata, pos, max, reserve, flags);
+ if (reserve && err) {
+ mark_bootmem(start, pos, 0, 0);
+ return err;
}
- bdata->last_offset &= ~PAGE_MASK;
- } else {
- bdata->last_pos = start + areasize - 1;
- bdata->last_offset = size & ~PAGE_MASK;
- ret = phys_to_virt(start * PAGE_SIZE + node_boot_start);
- }
- /*
- * Reserve the area now:
- */
- for (i = start; i < start + areasize; i++)
- if (unlikely(test_and_set_bit(i, node_bootmem_map)))
- BUG();
- memset(ret, 0, size);
- return ret;
+ if (max == end)
+ return 0;
+ pos = bdata->node_low_pfn;
+ }
+ BUG();
}
-static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat)
+/**
+ * free_bootmem_node - mark a page range as usable
+ * @pgdat: node the range resides on
+ * @physaddr: starting address of the range
+ * @size: size of the range in bytes
+ *
+ * Partial pages will be considered reserved and left as they are.
+ *
+ * The range must reside completely on the specified node.
+ */
+void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
+ unsigned long size)
{
- struct page *page;
- unsigned long pfn;
- bootmem_data_t *bdata = pgdat->bdata;
- unsigned long i, count, total = 0;
- unsigned long idx;
- unsigned long *map;
- int gofast = 0;
-
- BUG_ON(!bdata->node_bootmem_map);
-
- count = 0;
- /* first extant page of the node */
- pfn = PFN_DOWN(bdata->node_boot_start);
- idx = bdata->node_low_pfn - pfn;
- map = bdata->node_bootmem_map;
- /* Check physaddr is O(LOG2(BITS_PER_LONG)) page aligned */
- if (bdata->node_boot_start == 0 ||
- ffs(bdata->node_boot_start) - PAGE_SHIFT > ffs(BITS_PER_LONG))
- gofast = 1;
- for (i = 0; i < idx; ) {
- unsigned long v = ~map[i / BITS_PER_LONG];
-
- if (gofast && v == ~0UL) {
- int order;
-
- page = pfn_to_page(pfn);
- count += BITS_PER_LONG;
- order = ffs(BITS_PER_LONG) - 1;
- __free_pages_bootmem(page, order);
- i += BITS_PER_LONG;
- page += BITS_PER_LONG;
- } else if (v) {
- unsigned long m;
-
- page = pfn_to_page(pfn);
- for (m = 1; m && i < idx; m<<=1, page++, i++) {
- if (v & m) {
- count++;
- __free_pages_bootmem(page, 0);
- }
- }
- } else {
- i += BITS_PER_LONG;
- }
- pfn += BITS_PER_LONG;
- }
- total += count;
+ unsigned long start, end;
- /*
- * Now free the allocator bitmap itself, it's not
- * needed anymore:
- */
- page = virt_to_page(bdata->node_bootmem_map);
- count = 0;
- idx = (get_mapsize(bdata) + PAGE_SIZE-1) >> PAGE_SHIFT;
- for (i = 0; i < idx; i++, page++) {
- __free_pages_bootmem(page, 0);
- count++;
- }
- total += count;
- bdata->node_bootmem_map = NULL;
+ start = PFN_UP(physaddr);
+ end = PFN_DOWN(physaddr + size);
- return total;
+ mark_bootmem_node(pgdat->bdata, start, end, 0, 0);
}
-unsigned long __init init_bootmem_node(pg_data_t *pgdat, unsigned long freepfn,
- unsigned long startpfn, unsigned long endpfn)
-{
- return init_bootmem_core(pgdat, freepfn, startpfn, endpfn);
-}
-
-int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
- unsigned long size, int flags)
+/**
+ * free_bootmem - mark a page range as usable
+ * @addr: starting address of the range
+ * @size: size of the range in bytes
+ *
+ * Partial pages will be considered reserved and left as they are.
+ *
+ * The range must be contiguous but may span node boundaries.
+ */
+void __init free_bootmem(unsigned long addr, unsigned long size)
{
- int ret;
+ unsigned long start, end;
- ret = can_reserve_bootmem_core(pgdat->bdata, physaddr, size, flags);
- if (ret < 0)
- return -ENOMEM;
- reserve_bootmem_core(pgdat->bdata, physaddr, size, flags);
+ start = PFN_UP(addr);
+ end = PFN_DOWN(addr + size);
- return 0;
+ mark_bootmem(start, end, 0, 0);
}
-void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
- unsigned long size)
+/**
+ * reserve_bootmem_node - mark a page range as reserved
+ * @pgdat: node the range resides on
+ * @physaddr: starting address of the range
+ * @size: size of the range in bytes
+ * @flags: reservation flags (see linux/bootmem.h)
+ *
+ * Partial pages will be reserved.
+ *
+ * The range must reside completely on the specified node.
+ */
+int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
+ unsigned long size, int flags)
{
- free_bootmem_core(pgdat->bdata, physaddr, size);
-}
+ unsigned long start, end;
-unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
-{
- register_page_bootmem_info_node(pgdat);
- return free_all_bootmem_core(pgdat);
-}
+ start = PFN_DOWN(physaddr);
+ end = PFN_UP(physaddr + size);
-unsigned long __init init_bootmem(unsigned long start, unsigned long pages)
-{
- max_low_pfn = pages;
- min_low_pfn = start;
- return init_bootmem_core(NODE_DATA(0), start, 0, pages);
+ return mark_bootmem_node(pgdat->bdata, start, end, 1, flags);
}
#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
+/**
+ * reserve_bootmem - mark a page range as usable
+ * @addr: starting address of the range
+ * @size: size of the range in bytes
+ * @flags: reservation flags (see linux/bootmem.h)
+ *
+ * Partial pages will be reserved.
+ *
+ * The range must be contiguous but may span node boundaries.
+ */
int __init reserve_bootmem(unsigned long addr, unsigned long size,
int flags)
{
- bootmem_data_t *bdata;
- int ret;
+ unsigned long start, end;
- list_for_each_entry(bdata, &bdata_list, list) {
- ret = can_reserve_bootmem_core(bdata, addr, size, flags);
- if (ret < 0)
- return ret;
- }
- list_for_each_entry(bdata, &bdata_list, list)
- reserve_bootmem_core(bdata, addr, size, flags);
+ start = PFN_DOWN(addr);
+ end = PFN_UP(addr + size);
- return 0;
+ return mark_bootmem(start, end, 1, flags);
}
#endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
-void __init free_bootmem(unsigned long addr, unsigned long size)
+static void * __init alloc_bootmem_core(struct bootmem_data *bdata,
+ unsigned long size, unsigned long align,
+ unsigned long goal, unsigned long limit)
{
- bootmem_data_t *bdata;
- list_for_each_entry(bdata, &bdata_list, list)
- free_bootmem_core(bdata, addr, size);
-}
+ unsigned long fallback = 0;
+ unsigned long min, max, start, sidx, midx, step;
-unsigned long __init free_all_bootmem(void)
-{
- return free_all_bootmem_core(NODE_DATA(0));
+ BUG_ON(!size);
+ BUG_ON(align & (align - 1));
+ BUG_ON(limit && goal + size > limit);
+
+ if (!bdata->node_bootmem_map)
+ return NULL;
+
+ bdebug("nid=%td size=%lx [%lu pages] align=%lx goal=%lx limit=%lx\n",
+ bdata - bootmem_node_data, size, PAGE_ALIGN(size) >> PAGE_SHIFT,
+ align, goal, limit);
+
+ min = bdata->node_min_pfn;
+ max = bdata->node_low_pfn;
+
+ goal >>= PAGE_SHIFT;
+ limit >>= PAGE_SHIFT;
+
+ if (limit && max > limit)
+ max = limit;
+ if (max <= min)
+ return NULL;
+
+ step = max(align >> PAGE_SHIFT, 1UL);
+
+ if (goal && min < goal && goal < max)
+ start = ALIGN(goal, step);
+ else
+ start = ALIGN(min, step);
+
+ sidx = start - bdata->node_min_pfn;;
+ midx = max - bdata->node_min_pfn;
+
+ if (bdata->hint_idx > sidx) {
+ /*
+ * Handle the valid case of sidx being zero and still
+ * catch the fallback below.
+ */
+ fallback = sidx + 1;
+ sidx = ALIGN(bdata->hint_idx, step);
+ }
+
+ while (1) {
+ int merge;
+ void *region;
+ unsigned long eidx, i, start_off, end_off;
+find_block:
+ sidx = find_next_zero_bit(bdata->node_bootmem_map, midx, sidx);
+ sidx = ALIGN(sidx, step);
+ eidx = sidx + PFN_UP(size);
+
+ if (sidx >= midx || eidx > midx)
+ break;
+
+ for (i = sidx; i < eidx; i++)
+ if (test_bit(i, bdata->node_bootmem_map)) {
+ sidx = ALIGN(i, step);
+ if (sidx == i)
+ sidx += step;
+ goto find_block;
+ }
+
+ if (bdata->last_end_off &&
+ PFN_DOWN(bdata->last_end_off) + 1 == sidx)
+ start_off = ALIGN(bdata->last_end_off, align);
+ else
+ start_off = PFN_PHYS(sidx);
+
+ merge = PFN_DOWN(start_off) < sidx;
+ end_off = start_off + size;
+
+ bdata->last_end_off = end_off;
+ bdata->hint_idx = PFN_UP(end_off);
+
+ /*
+ * Reserve the area now:
+ */
+ if (__reserve(bdata, PFN_DOWN(start_off) + merge,
+ PFN_UP(end_off), BOOTMEM_EXCLUSIVE))
+ BUG();
+
+ region = phys_to_virt(PFN_PHYS(bdata->node_min_pfn) +
+ start_off);
+ memset(region, 0, size);
+ return region;
+ }
+
+ if (fallback) {
+ sidx = ALIGN(fallback - 1, step);
+ fallback = 0;
+ goto find_block;
+ }
+
+ return NULL;
}
-void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align,
- unsigned long goal)
+static void * __init ___alloc_bootmem_nopanic(unsigned long size,
+ unsigned long align,
+ unsigned long goal,
+ unsigned long limit)
{
bootmem_data_t *bdata;
- void *ptr;
+restart:
list_for_each_entry(bdata, &bdata_list, list) {
- ptr = __alloc_bootmem_core(bdata, size, align, goal, 0);
- if (ptr)
- return ptr;
+ void *region;
+
+ if (goal && bdata->node_low_pfn <= PFN_DOWN(goal))
+ continue;
+ if (limit && bdata->node_min_pfn >= PFN_DOWN(limit))
+ break;
+
+ region = alloc_bootmem_core(bdata, size, align, goal, limit);
+ if (region)
+ return region;
+ }
+
+ if (goal) {
+ goal = 0;
+ goto restart;
}
+
return NULL;
}
-void * __init __alloc_bootmem(unsigned long size, unsigned long align,
- unsigned long goal)
+/**
+ * __alloc_bootmem_nopanic - allocate boot memory without panicking
+ * @size: size of the request in bytes
+ * @align: alignment of the region
+ * @goal: preferred starting address of the region
+ *
+ * The goal is dropped if it can not be satisfied and the allocation will
+ * fall back to memory below @goal.
+ *
+ * Allocation may happen on any node in the system.
+ *
+ * Returns NULL on failure.
+ */
+void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align,
+ unsigned long goal)
{
- void *mem = __alloc_bootmem_nopanic(size,align,goal);
+ return ___alloc_bootmem_nopanic(size, align, goal, 0);
+}
+
+static void * __init ___alloc_bootmem(unsigned long size, unsigned long align,
+ unsigned long goal, unsigned long limit)
+{
+ void *mem = ___alloc_bootmem_nopanic(size, align, goal, limit);
if (mem)
return mem;
@@ -534,78 +570,135 @@ void * __init __alloc_bootmem(unsigned long size, unsigned long align,
return NULL;
}
+/**
+ * __alloc_bootmem - allocate boot memory
+ * @size: size of the request in bytes
+ * @align: alignment of the region
+ * @goal: preferred starting address of the region
+ *
+ * The goal is dropped if it can not be satisfied and the allocation will
+ * fall back to memory below @goal.
+ *
+ * Allocation may happen on any node in the system.
+ *
+ * The function panics if the request can not be satisfied.
+ */
+void * __init __alloc_bootmem(unsigned long size, unsigned long align,
+ unsigned long goal)
+{
+ return ___alloc_bootmem(size, align, goal, 0);
+}
-void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
- unsigned long align, unsigned long goal)
+static void * __init ___alloc_bootmem_node(bootmem_data_t *bdata,
+ unsigned long size, unsigned long align,
+ unsigned long goal, unsigned long limit)
{
void *ptr;
- ptr = __alloc_bootmem_core(pgdat->bdata, size, align, goal, 0);
+ ptr = alloc_bootmem_core(bdata, size, align, goal, limit);
if (ptr)
return ptr;
- return __alloc_bootmem(size, align, goal);
+ return ___alloc_bootmem(size, align, goal, limit);
+}
+
+/**
+ * __alloc_bootmem_node - allocate boot memory from a specific node
+ * @pgdat: node to allocate from
+ * @size: size of the request in bytes
+ * @align: alignment of the region
+ * @goal: preferred starting address of the region
+ *
+ * The goal is dropped if it can not be satisfied and the allocation will
+ * fall back to memory below @goal.
+ *
+ * Allocation may fall back to any node in the system if the specified node
+ * can not hold the requested memory.
+ *
+ * The function panics if the request can not be satisfied.
+ */
+void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
+ unsigned long align, unsigned long goal)
+{
+ return ___alloc_bootmem_node(pgdat->bdata, size, align, goal, 0);
}
#ifdef CONFIG_SPARSEMEM
+/**
+ * alloc_bootmem_section - allocate boot memory from a specific section
+ * @size: size of the request in bytes
+ * @section_nr: sparse map section to allocate from
+ *
+ * Return NULL on failure.
+ */
void * __init alloc_bootmem_section(unsigned long size,
unsigned long section_nr)
{
- void *ptr;
- unsigned long limit, goal, start_nr, end_nr, pfn;
- struct pglist_data *pgdat;
+ bootmem_data_t *bdata;
+ unsigned long pfn, goal, limit;
pfn = section_nr_to_pfn(section_nr);
- goal = PFN_PHYS(pfn);
- limit = PFN_PHYS(section_nr_to_pfn(section_nr + 1)) - 1;
- pgdat = NODE_DATA(early_pfn_to_nid(pfn));
- ptr = __alloc_bootmem_core(pgdat->bdata, size, SMP_CACHE_BYTES, goal,
- limit);
+ goal = pfn << PAGE_SHIFT;
+ limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT;
+ bdata = &bootmem_node_data[early_pfn_to_nid(pfn)];
- if (!ptr)
- return NULL;
+ return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, limit);
+}
+#endif
- start_nr = pfn_to_section_nr(PFN_DOWN(__pa(ptr)));
- end_nr = pfn_to_section_nr(PFN_DOWN(__pa(ptr) + size));
- if (start_nr != section_nr || end_nr != section_nr) {
- printk(KERN_WARNING "alloc_bootmem failed on section %ld.\n",
- section_nr);
- free_bootmem_core(pgdat->bdata, __pa(ptr), size);
- ptr = NULL;
- }
+void * __init __alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size,
+ unsigned long align, unsigned long goal)
+{
+ void *ptr;
- return ptr;
+ ptr = alloc_bootmem_core(pgdat->bdata, size, align, goal, 0);
+ if (ptr)
+ return ptr;
+
+ return __alloc_bootmem_nopanic(size, align, goal);
}
-#endif
#ifndef ARCH_LOW_ADDRESS_LIMIT
#define ARCH_LOW_ADDRESS_LIMIT 0xffffffffUL
#endif
+/**
+ * __alloc_bootmem_low - allocate low boot memory
+ * @size: size of the request in bytes
+ * @align: alignment of the region
+ * @goal: preferred starting address of the region
+ *
+ * The goal is dropped if it can not be satisfied and the allocation will
+ * fall back to memory below @goal.
+ *
+ * Allocation may happen on any node in the system.
+ *
+ * The function panics if the request can not be satisfied.
+ */
void * __init __alloc_bootmem_low(unsigned long size, unsigned long align,
unsigned long goal)
{
- bootmem_data_t *bdata;
- void *ptr;
-
- list_for_each_entry(bdata, &bdata_list, list) {
- ptr = __alloc_bootmem_core(bdata, size, align, goal,
- ARCH_LOW_ADDRESS_LIMIT);
- if (ptr)
- return ptr;
- }
-
- /*
- * Whoops, we cannot satisfy the allocation request.
- */
- printk(KERN_ALERT "low bootmem alloc of %lu bytes failed!\n", size);
- panic("Out of low memory");
- return NULL;
+ return ___alloc_bootmem(size, align, goal, ARCH_LOW_ADDRESS_LIMIT);
}
+/**
+ * __alloc_bootmem_low_node - allocate low boot memory from a specific node
+ * @pgdat: node to allocate from
+ * @size: size of the request in bytes
+ * @align: alignment of the region
+ * @goal: preferred starting address of the region
+ *
+ * The goal is dropped if it can not be satisfied and the allocation will
+ * fall back to memory below @goal.
+ *
+ * Allocation may fall back to any node in the system if the specified node
+ * can not hold the requested memory.
+ *
+ * The function panics if the request can not be satisfied.
+ */
void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, unsigned long size,
unsigned long align, unsigned long goal)
{
- return __alloc_bootmem_core(pgdat->bdata, size, align, goal,
- ARCH_LOW_ADDRESS_LIMIT);
+ return ___alloc_bootmem_node(pgdat->bdata, size, align,
+ goal, ARCH_LOW_ADDRESS_LIMIT);
}
diff --git a/mm/filemap.c b/mm/filemap.c
index 65d9d9e2b75..2d3ec1ffc66 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -42,9 +42,6 @@
#include <asm/mman.h>
-static ssize_t
-generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
- loff_t offset, unsigned long nr_segs);
/*
* Shared mappings implemented 30.11.1994. It's not fully working yet,
@@ -118,7 +115,7 @@ void __remove_from_page_cache(struct page *page)
{
struct address_space *mapping = page->mapping;
- mem_cgroup_uncharge_page(page);
+ mem_cgroup_uncharge_cache_page(page);
radix_tree_delete(&mapping->page_tree, page->index);
page->mapping = NULL;
mapping->nrpages--;
@@ -477,12 +474,12 @@ int add_to_page_cache(struct page *page, struct address_space *mapping,
mapping->nrpages++;
__inc_zone_page_state(page, NR_FILE_PAGES);
} else
- mem_cgroup_uncharge_page(page);
+ mem_cgroup_uncharge_cache_page(page);
write_unlock_irq(&mapping->tree_lock);
radix_tree_preload_end();
} else
- mem_cgroup_uncharge_page(page);
+ mem_cgroup_uncharge_cache_page(page);
out:
return error;
}
@@ -1200,42 +1197,41 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
mapping = filp->f_mapping;
inode = mapping->host;
- retval = 0;
if (!count)
goto out; /* skip atime */
size = i_size_read(inode);
if (pos < size) {
- retval = generic_file_direct_IO(READ, iocb,
- iov, pos, nr_segs);
+ retval = filemap_write_and_wait(mapping);
+ if (!retval) {
+ retval = mapping->a_ops->direct_IO(READ, iocb,
+ iov, pos, nr_segs);
+ }
if (retval > 0)
*ppos = pos + retval;
- }
- if (likely(retval != 0)) {
- file_accessed(filp);
- goto out;
+ if (retval) {
+ file_accessed(filp);
+ goto out;
+ }
}
}
- retval = 0;
- if (count) {
- for (seg = 0; seg < nr_segs; seg++) {
- read_descriptor_t desc;
+ for (seg = 0; seg < nr_segs; seg++) {
+ read_descriptor_t desc;
- desc.written = 0;
- desc.arg.buf = iov[seg].iov_base;
- desc.count = iov[seg].iov_len;
- if (desc.count == 0)
- continue;
- desc.error = 0;
- do_generic_file_read(filp,ppos,&desc,file_read_actor);
- retval += desc.written;
- if (desc.error) {
- retval = retval ?: desc.error;
- break;
- }
- if (desc.count > 0)
- break;
+ desc.written = 0;
+ desc.arg.buf = iov[seg].iov_base;
+ desc.count = iov[seg].iov_len;
+ if (desc.count == 0)
+ continue;
+ desc.error = 0;
+ do_generic_file_read(filp, ppos, &desc, file_read_actor);
+ retval += desc.written;
+ if (desc.error) {
+ retval = retval ?: desc.error;
+ break;
}
+ if (desc.count > 0)
+ break;
}
out:
return retval;
@@ -2004,11 +2000,55 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
ssize_t written;
+ size_t write_len;
+ pgoff_t end;
if (count != ocount)
*nr_segs = iov_shorten((struct iovec *)iov, *nr_segs, count);
- written = generic_file_direct_IO(WRITE, iocb, iov, pos, *nr_segs);
+ /*
+ * Unmap all mmappings of the file up-front.
+ *
+ * This will cause any pte dirty bits to be propagated into the
+ * pageframes for the subsequent filemap_write_and_wait().
+ */
+ write_len = iov_length(iov, *nr_segs);
+ end = (pos + write_len - 1) >> PAGE_CACHE_SHIFT;
+ if (mapping_mapped(mapping))
+ unmap_mapping_range(mapping, pos, write_len, 0);
+
+ written = filemap_write_and_wait(mapping);
+ if (written)
+ goto out;
+
+ /*
+ * After a write we want buffered reads to be sure to go to disk to get
+ * the new data. We invalidate clean cached page from the region we're
+ * about to write. We do this *before* the write so that we can return
+ * -EIO without clobbering -EIOCBQUEUED from ->direct_IO().
+ */
+ if (mapping->nrpages) {
+ written = invalidate_inode_pages2_range(mapping,
+ pos >> PAGE_CACHE_SHIFT, end);
+ if (written)
+ goto out;
+ }
+
+ written = mapping->a_ops->direct_IO(WRITE, iocb, iov, pos, *nr_segs);
+
+ /*
+ * Finally, try again to invalidate clean pages which might have been
+ * cached by non-direct readahead, or faulted in by get_user_pages()
+ * if the source of the write was an mmap'ed region of the file
+ * we're writing. Either one is a pretty crazy thing to do,
+ * so we don't support it 100%. If this invalidation
+ * fails, tough, the write still worked...
+ */
+ if (mapping->nrpages) {
+ invalidate_inode_pages2_range(mapping,
+ pos >> PAGE_CACHE_SHIFT, end);
+ }
+
if (written > 0) {
loff_t end = pos + written;
if (end > i_size_read(inode) && !S_ISBLK(inode->i_mode)) {
@@ -2024,6 +2064,7 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
* i_mutex is held, which protects generic_osync_inode() from
* livelocking. AIO O_DIRECT ops attempt to sync metadata here.
*/
+out:
if ((written >= 0 || written == -EIOCBQUEUED) &&
((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
int err = generic_osync_inode(inode, mapping, OSYNC_METADATA);
@@ -2511,66 +2552,6 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
}
EXPORT_SYMBOL(generic_file_aio_write);
-/*
- * Called under i_mutex for writes to S_ISREG files. Returns -EIO if something
- * went wrong during pagecache shootdown.
- */
-static ssize_t
-generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
- loff_t offset, unsigned long nr_segs)
-{
- struct file *file = iocb->ki_filp;
- struct address_space *mapping = file->f_mapping;
- ssize_t retval;
- size_t write_len;
- pgoff_t end = 0; /* silence gcc */
-
- /*
- * If it's a write, unmap all mmappings of the file up-front. This
- * will cause any pte dirty bits to be propagated into the pageframes
- * for the subsequent filemap_write_and_wait().
- */
- if (rw == WRITE) {
- write_len = iov_length(iov, nr_segs);
- end = (offset + write_len - 1) >> PAGE_CACHE_SHIFT;
- if (mapping_mapped(mapping))
- unmap_mapping_range(mapping, offset, write_len, 0);
- }
-
- retval = filemap_write_and_wait(mapping);
- if (retval)
- goto out;
-
- /*
- * After a write we want buffered reads to be sure to go to disk to get
- * the new data. We invalidate clean cached page from the region we're
- * about to write. We do this *before* the write so that we can return
- * -EIO without clobbering -EIOCBQUEUED from ->direct_IO().
- */
- if (rw == WRITE && mapping->nrpages) {
- retval = invalidate_inode_pages2_range(mapping,
- offset >> PAGE_CACHE_SHIFT, end);
- if (retval)
- goto out;
- }
-
- retval = mapping->a_ops->direct_IO(rw, iocb, iov, offset, nr_segs);
-
- /*
- * Finally, try again to invalidate clean pages which might have been
- * cached by non-direct readahead, or faulted in by get_user_pages()
- * if the source of the write was an mmap'ed region of the file
- * we're writing. Either one is a pretty crazy thing to do,
- * so we don't support it 100%. If this invalidation
- * fails, tough, the write still worked...
- */
- if (rw == WRITE && mapping->nrpages) {
- invalidate_inode_pages2_range(mapping, offset >> PAGE_CACHE_SHIFT, end);
- }
-out:
- return retval;
-}
-
/**
* try_to_release_page() - release old fs-specific metadata on a page
*
@@ -2582,9 +2563,8 @@ out:
* Otherwise return zero.
*
* The @gfp_mask argument specifies whether I/O may be performed to release
- * this page (__GFP_IO), and whether the call may block (__GFP_WAIT).
+ * this page (__GFP_IO), and whether the call may block (__GFP_WAIT & __GFP_FS).
*
- * NOTE: @gfp_mask may go away, and this function may become non-blocking.
*/
int try_to_release_page(struct page *page, gfp_t gfp_mask)
{
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index ab171274ef2..a8bf4ab01f8 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -14,6 +14,8 @@
#include <linux/mempolicy.h>
#include <linux/cpuset.h>
#include <linux/mutex.h>
+#include <linux/bootmem.h>
+#include <linux/sysfs.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -22,30 +24,340 @@
#include "internal.h"
const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL;
-static unsigned long nr_huge_pages, free_huge_pages, resv_huge_pages;
-static unsigned long surplus_huge_pages;
-static unsigned long nr_overcommit_huge_pages;
-unsigned long max_huge_pages;
-unsigned long sysctl_overcommit_huge_pages;
-static struct list_head hugepage_freelists[MAX_NUMNODES];
-static unsigned int nr_huge_pages_node[MAX_NUMNODES];
-static unsigned int free_huge_pages_node[MAX_NUMNODES];
-static unsigned int surplus_huge_pages_node[MAX_NUMNODES];
static gfp_t htlb_alloc_mask = GFP_HIGHUSER;
unsigned long hugepages_treat_as_movable;
-static int hugetlb_next_nid;
+
+static int max_hstate;
+unsigned int default_hstate_idx;
+struct hstate hstates[HUGE_MAX_HSTATE];
+
+__initdata LIST_HEAD(huge_boot_pages);
+
+/* for command line parsing */
+static struct hstate * __initdata parsed_hstate;
+static unsigned long __initdata default_hstate_max_huge_pages;
+static unsigned long __initdata default_hstate_size;
+
+#define for_each_hstate(h) \
+ for ((h) = hstates; (h) < &hstates[max_hstate]; (h)++)
/*
* Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages
*/
static DEFINE_SPINLOCK(hugetlb_lock);
-static void clear_huge_page(struct page *page, unsigned long addr)
+/*
+ * Region tracking -- allows tracking of reservations and instantiated pages
+ * across the pages in a mapping.
+ *
+ * The region data structures are protected by a combination of the mmap_sem
+ * and the hugetlb_instantion_mutex. To access or modify a region the caller
+ * must either hold the mmap_sem for write, or the mmap_sem for read and
+ * the hugetlb_instantiation mutex:
+ *
+ * down_write(&mm->mmap_sem);
+ * or
+ * down_read(&mm->mmap_sem);
+ * mutex_lock(&hugetlb_instantiation_mutex);
+ */
+struct file_region {
+ struct list_head link;
+ long from;
+ long to;
+};
+
+static long region_add(struct list_head *head, long f, long t)
+{
+ struct file_region *rg, *nrg, *trg;
+
+ /* Locate the region we are either in or before. */
+ list_for_each_entry(rg, head, link)
+ if (f <= rg->to)
+ break;
+
+ /* Round our left edge to the current segment if it encloses us. */
+ if (f > rg->from)
+ f = rg->from;
+
+ /* Check for and consume any regions we now overlap with. */
+ nrg = rg;
+ list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
+ if (&rg->link == head)
+ break;
+ if (rg->from > t)
+ break;
+
+ /* If this area reaches higher then extend our area to
+ * include it completely. If this is not the first area
+ * which we intend to reuse, free it. */
+ if (rg->to > t)
+ t = rg->to;
+ if (rg != nrg) {
+ list_del(&rg->link);
+ kfree(rg);
+ }
+ }
+ nrg->from = f;
+ nrg->to = t;
+ return 0;
+}
+
+static long region_chg(struct list_head *head, long f, long t)
+{
+ struct file_region *rg, *nrg;
+ long chg = 0;
+
+ /* Locate the region we are before or in. */
+ list_for_each_entry(rg, head, link)
+ if (f <= rg->to)
+ break;
+
+ /* If we are below the current region then a new region is required.
+ * Subtle, allocate a new region at the position but make it zero
+ * size such that we can guarantee to record the reservation. */
+ if (&rg->link == head || t < rg->from) {
+ nrg = kmalloc(sizeof(*nrg), GFP_KERNEL);
+ if (!nrg)
+ return -ENOMEM;
+ nrg->from = f;
+ nrg->to = f;
+ INIT_LIST_HEAD(&nrg->link);
+ list_add(&nrg->link, rg->link.prev);
+
+ return t - f;
+ }
+
+ /* Round our left edge to the current segment if it encloses us. */
+ if (f > rg->from)
+ f = rg->from;
+ chg = t - f;
+
+ /* Check for and consume any regions we now overlap with. */
+ list_for_each_entry(rg, rg->link.prev, link) {
+ if (&rg->link == head)
+ break;
+ if (rg->from > t)
+ return chg;
+
+ /* We overlap with this area, if it extends futher than
+ * us then we must extend ourselves. Account for its
+ * existing reservation. */
+ if (rg->to > t) {
+ chg += rg->to - t;
+ t = rg->to;
+ }
+ chg -= rg->to - rg->from;
+ }
+ return chg;
+}
+
+static long region_truncate(struct list_head *head, long end)
+{
+ struct file_region *rg, *trg;
+ long chg = 0;
+
+ /* Locate the region we are either in or before. */
+ list_for_each_entry(rg, head, link)
+ if (end <= rg->to)
+ break;
+ if (&rg->link == head)
+ return 0;
+
+ /* If we are in the middle of a region then adjust it. */
+ if (end > rg->from) {
+ chg = rg->to - end;
+ rg->to = end;
+ rg = list_entry(rg->link.next, typeof(*rg), link);
+ }
+
+ /* Drop any remaining regions. */
+ list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
+ if (&rg->link == head)
+ break;
+ chg += rg->to - rg->from;
+ list_del(&rg->link);
+ kfree(rg);
+ }
+ return chg;
+}
+
+static long region_count(struct list_head *head, long f, long t)
+{
+ struct file_region *rg;
+ long chg = 0;
+
+ /* Locate each segment we overlap with, and count that overlap. */
+ list_for_each_entry(rg, head, link) {
+ int seg_from;
+ int seg_to;
+
+ if (rg->to <= f)
+ continue;
+ if (rg->from >= t)
+ break;
+
+ seg_from = max(rg->from, f);
+ seg_to = min(rg->to, t);
+
+ chg += seg_to - seg_from;
+ }
+
+ return chg;
+}
+
+/*
+ * Convert the address within this vma to the page offset within
+ * the mapping, in pagecache page units; huge pages here.
+ */
+static pgoff_t vma_hugecache_offset(struct hstate *h,
+ struct vm_area_struct *vma, unsigned long address)
+{
+ return ((address - vma->vm_start) >> huge_page_shift(h)) +
+ (vma->vm_pgoff >> huge_page_order(h));
+}
+
+/*
+ * Flags for MAP_PRIVATE reservations. These are stored in the bottom
+ * bits of the reservation map pointer, which are always clear due to
+ * alignment.
+ */
+#define HPAGE_RESV_OWNER (1UL << 0)
+#define HPAGE_RESV_UNMAPPED (1UL << 1)
+#define HPAGE_RESV_MASK (HPAGE_RESV_OWNER | HPAGE_RESV_UNMAPPED)
+
+/*
+ * These helpers are used to track how many pages are reserved for
+ * faults in a MAP_PRIVATE mapping. Only the process that called mmap()
+ * is guaranteed to have their future faults succeed.
+ *
+ * With the exception of reset_vma_resv_huge_pages() which is called at fork(),
+ * the reserve counters are updated with the hugetlb_lock held. It is safe
+ * to reset the VMA at fork() time as it is not in use yet and there is no
+ * chance of the global counters getting corrupted as a result of the values.
+ *
+ * The private mapping reservation is represented in a subtly different
+ * manner to a shared mapping. A shared mapping has a region map associated
+ * with the underlying file, this region map represents the backing file
+ * pages which have ever had a reservation assigned which this persists even
+ * after the page is instantiated. A private mapping has a region map
+ * associated with the original mmap which is attached to all VMAs which
+ * reference it, this region map represents those offsets which have consumed
+ * reservation ie. where pages have been instantiated.
+ */
+static unsigned long get_vma_private_data(struct vm_area_struct *vma)
+{
+ return (unsigned long)vma->vm_private_data;
+}
+
+static void set_vma_private_data(struct vm_area_struct *vma,
+ unsigned long value)
+{
+ vma->vm_private_data = (void *)value;
+}
+
+struct resv_map {
+ struct kref refs;
+ struct list_head regions;
+};
+
+struct resv_map *resv_map_alloc(void)
+{
+ struct resv_map *resv_map = kmalloc(sizeof(*resv_map), GFP_KERNEL);
+ if (!resv_map)
+ return NULL;
+
+ kref_init(&resv_map->refs);
+ INIT_LIST_HEAD(&resv_map->regions);
+
+ return resv_map;
+}
+
+void resv_map_release(struct kref *ref)
+{
+ struct resv_map *resv_map = container_of(ref, struct resv_map, refs);
+
+ /* Clear out any active regions before we release the map. */
+ region_truncate(&resv_map->regions, 0);
+ kfree(resv_map);
+}
+
+static struct resv_map *vma_resv_map(struct vm_area_struct *vma)
+{
+ VM_BUG_ON(!is_vm_hugetlb_page(vma));
+ if (!(vma->vm_flags & VM_SHARED))
+ return (struct resv_map *)(get_vma_private_data(vma) &
+ ~HPAGE_RESV_MASK);
+ return 0;
+}
+
+static void set_vma_resv_map(struct vm_area_struct *vma, struct resv_map *map)
+{
+ VM_BUG_ON(!is_vm_hugetlb_page(vma));
+ VM_BUG_ON(vma->vm_flags & VM_SHARED);
+
+ set_vma_private_data(vma, (get_vma_private_data(vma) &
+ HPAGE_RESV_MASK) | (unsigned long)map);
+}
+
+static void set_vma_resv_flags(struct vm_area_struct *vma, unsigned long flags)
+{
+ VM_BUG_ON(!is_vm_hugetlb_page(vma));
+ VM_BUG_ON(vma->vm_flags & VM_SHARED);
+
+ set_vma_private_data(vma, get_vma_private_data(vma) | flags);
+}
+
+static int is_vma_resv_set(struct vm_area_struct *vma, unsigned long flag)
+{
+ VM_BUG_ON(!is_vm_hugetlb_page(vma));
+
+ return (get_vma_private_data(vma) & flag) != 0;
+}
+
+/* Decrement the reserved pages in the hugepage pool by one */
+static void decrement_hugepage_resv_vma(struct hstate *h,
+ struct vm_area_struct *vma)
+{
+ if (vma->vm_flags & VM_NORESERVE)
+ return;
+
+ if (vma->vm_flags & VM_SHARED) {
+ /* Shared mappings always use reserves */
+ h->resv_huge_pages--;
+ } else if (is_vma_resv_set(vma, HPAGE_RESV_OWNER)) {
+ /*
+ * Only the process that called mmap() has reserves for
+ * private mappings.
+ */
+ h->resv_huge_pages--;
+ }
+}
+
+/* Reset counters to 0 and clear all HPAGE_RESV_* flags */
+void reset_vma_resv_huge_pages(struct vm_area_struct *vma)
+{
+ VM_BUG_ON(!is_vm_hugetlb_page(vma));
+ if (!(vma->vm_flags & VM_SHARED))
+ vma->vm_private_data = (void *)0;
+}
+
+/* Returns true if the VMA has associated reserve pages */
+static int vma_has_reserves(struct vm_area_struct *vma)
+{
+ if (vma->vm_flags & VM_SHARED)
+ return 1;
+ if (is_vma_resv_set(vma, HPAGE_RESV_OWNER))
+ return 1;
+ return 0;
+}
+
+static void clear_huge_page(struct page *page,
+ unsigned long addr, unsigned long sz)
{
int i;
might_sleep();
- for (i = 0; i < (HPAGE_SIZE/PAGE_SIZE); i++) {
+ for (i = 0; i < sz/PAGE_SIZE; i++) {
cond_resched();
clear_user_highpage(page + i, addr + i * PAGE_SIZE);
}
@@ -55,42 +367,44 @@ static void copy_huge_page(struct page *dst, struct page *src,
unsigned long addr, struct vm_area_struct *vma)
{
int i;
+ struct hstate *h = hstate_vma(vma);
might_sleep();
- for (i = 0; i < HPAGE_SIZE/PAGE_SIZE; i++) {
+ for (i = 0; i < pages_per_huge_page(h); i++) {
cond_resched();
copy_user_highpage(dst + i, src + i, addr + i*PAGE_SIZE, vma);
}
}
-static void enqueue_huge_page(struct page *page)
+static void enqueue_huge_page(struct hstate *h, struct page *page)
{
int nid = page_to_nid(page);
- list_add(&page->lru, &hugepage_freelists[nid]);
- free_huge_pages++;
- free_huge_pages_node[nid]++;
+ list_add(&page->lru, &h->hugepage_freelists[nid]);
+ h->free_huge_pages++;
+ h->free_huge_pages_node[nid]++;
}
-static struct page *dequeue_huge_page(void)
+static struct page *dequeue_huge_page(struct hstate *h)
{
int nid;
struct page *page = NULL;
for (nid = 0; nid < MAX_NUMNODES; ++nid) {
- if (!list_empty(&hugepage_freelists[nid])) {
- page = list_entry(hugepage_freelists[nid].next,
+ if (!list_empty(&h->hugepage_freelists[nid])) {
+ page = list_entry(h->hugepage_freelists[nid].next,
struct page, lru);
list_del(&page->lru);
- free_huge_pages--;
- free_huge_pages_node[nid]--;
+ h->free_huge_pages--;
+ h->free_huge_pages_node[nid]--;
break;
}
}
return page;
}
-static struct page *dequeue_huge_page_vma(struct vm_area_struct *vma,
- unsigned long address)
+static struct page *dequeue_huge_page_vma(struct hstate *h,
+ struct vm_area_struct *vma,
+ unsigned long address, int avoid_reserve)
{
int nid;
struct page *page = NULL;
@@ -101,18 +415,33 @@ static struct page *dequeue_huge_page_vma(struct vm_area_struct *vma,
struct zone *zone;
struct zoneref *z;
+ /*
+ * A child process with MAP_PRIVATE mappings created by their parent
+ * have no page reserves. This check ensures that reservations are
+ * not "stolen". The child may still get SIGKILLed
+ */
+ if (!vma_has_reserves(vma) &&
+ h->free_huge_pages - h->resv_huge_pages == 0)
+ return NULL;
+
+ /* If reserves cannot be used, ensure enough pages are in the pool */
+ if (avoid_reserve && h->free_huge_pages - h->resv_huge_pages == 0)
+ return NULL;
+
for_each_zone_zonelist_nodemask(zone, z, zonelist,
MAX_NR_ZONES - 1, nodemask) {
nid = zone_to_nid(zone);
if (cpuset_zone_allowed_softwall(zone, htlb_alloc_mask) &&
- !list_empty(&hugepage_freelists[nid])) {
- page = list_entry(hugepage_freelists[nid].next,
+ !list_empty(&h->hugepage_freelists[nid])) {
+ page = list_entry(h->hugepage_freelists[nid].next,
struct page, lru);
list_del(&page->lru);
- free_huge_pages--;
- free_huge_pages_node[nid]--;
- if (vma && vma->vm_flags & VM_MAYSHARE)
- resv_huge_pages--;
+ h->free_huge_pages--;
+ h->free_huge_pages_node[nid]--;
+
+ if (!avoid_reserve)
+ decrement_hugepage_resv_vma(h, vma);
+
break;
}
}
@@ -120,12 +449,13 @@ static struct page *dequeue_huge_page_vma(struct vm_area_struct *vma,
return page;
}
-static void update_and_free_page(struct page *page)
+static void update_and_free_page(struct hstate *h, struct page *page)
{
int i;
- nr_huge_pages--;
- nr_huge_pages_node[page_to_nid(page)]--;
- for (i = 0; i < (HPAGE_SIZE / PAGE_SIZE); i++) {
+
+ h->nr_huge_pages--;
+ h->nr_huge_pages_node[page_to_nid(page)]--;
+ for (i = 0; i < pages_per_huge_page(h); i++) {
page[i].flags &= ~(1 << PG_locked | 1 << PG_error | 1 << PG_referenced |
1 << PG_dirty | 1 << PG_active | 1 << PG_reserved |
1 << PG_private | 1<< PG_writeback);
@@ -133,11 +463,27 @@ static void update_and_free_page(struct page *page)
set_compound_page_dtor(page, NULL);
set_page_refcounted(page);
arch_release_hugepage(page);
- __free_pages(page, HUGETLB_PAGE_ORDER);
+ __free_pages(page, huge_page_order(h));
+}
+
+struct hstate *size_to_hstate(unsigned long size)
+{
+ struct hstate *h;
+
+ for_each_hstate(h) {
+ if (huge_page_size(h) == size)
+ return h;
+ }
+ return NULL;
}
static void free_huge_page(struct page *page)
{
+ /*
+ * Can't pass hstate in here because it is called from the
+ * compound page destructor.
+ */
+ struct hstate *h = page_hstate(page);
int nid = page_to_nid(page);
struct address_space *mapping;
@@ -147,12 +493,12 @@ static void free_huge_page(struct page *page)
INIT_LIST_HEAD(&page->lru);
spin_lock(&hugetlb_lock);
- if (surplus_huge_pages_node[nid]) {
- update_and_free_page(page);
- surplus_huge_pages--;
- surplus_huge_pages_node[nid]--;
+ if (h->surplus_huge_pages_node[nid] && huge_page_order(h) < MAX_ORDER) {
+ update_and_free_page(h, page);
+ h->surplus_huge_pages--;
+ h->surplus_huge_pages_node[nid]--;
} else {
- enqueue_huge_page(page);
+ enqueue_huge_page(h, page);
}
spin_unlock(&hugetlb_lock);
if (mapping)
@@ -164,7 +510,7 @@ static void free_huge_page(struct page *page)
* balanced by operating on them in a round-robin fashion.
* Returns 1 if an adjustment was made.
*/
-static int adjust_pool_surplus(int delta)
+static int adjust_pool_surplus(struct hstate *h, int delta)
{
static int prev_nid;
int nid = prev_nid;
@@ -177,15 +523,15 @@ static int adjust_pool_surplus(int delta)
nid = first_node(node_online_map);
/* To shrink on this node, there must be a surplus page */
- if (delta < 0 && !surplus_huge_pages_node[nid])
+ if (delta < 0 && !h->surplus_huge_pages_node[nid])
continue;
/* Surplus cannot exceed the total number of pages */
- if (delta > 0 && surplus_huge_pages_node[nid] >=
- nr_huge_pages_node[nid])
+ if (delta > 0 && h->surplus_huge_pages_node[nid] >=
+ h->nr_huge_pages_node[nid])
continue;
- surplus_huge_pages += delta;
- surplus_huge_pages_node[nid] += delta;
+ h->surplus_huge_pages += delta;
+ h->surplus_huge_pages_node[nid] += delta;
ret = 1;
break;
} while (nid != prev_nid);
@@ -194,59 +540,74 @@ static int adjust_pool_surplus(int delta)
return ret;
}
-static struct page *alloc_fresh_huge_page_node(int nid)
+static void prep_new_huge_page(struct hstate *h, struct page *page, int nid)
+{
+ set_compound_page_dtor(page, free_huge_page);
+ spin_lock(&hugetlb_lock);
+ h->nr_huge_pages++;
+ h->nr_huge_pages_node[nid]++;
+ spin_unlock(&hugetlb_lock);
+ put_page(page); /* free it into the hugepage allocator */
+}
+
+static struct page *alloc_fresh_huge_page_node(struct hstate *h, int nid)
{
struct page *page;
+ if (h->order >= MAX_ORDER)
+ return NULL;
+
page = alloc_pages_node(nid,
htlb_alloc_mask|__GFP_COMP|__GFP_THISNODE|
__GFP_REPEAT|__GFP_NOWARN,
- HUGETLB_PAGE_ORDER);
+ huge_page_order(h));
if (page) {
if (arch_prepare_hugepage(page)) {
__free_pages(page, HUGETLB_PAGE_ORDER);
return NULL;
}
- set_compound_page_dtor(page, free_huge_page);
- spin_lock(&hugetlb_lock);
- nr_huge_pages++;
- nr_huge_pages_node[nid]++;
- spin_unlock(&hugetlb_lock);
- put_page(page); /* free it into the hugepage allocator */
+ prep_new_huge_page(h, page, nid);
}
return page;
}
-static int alloc_fresh_huge_page(void)
+/*
+ * Use a helper variable to find the next node and then
+ * copy it back to hugetlb_next_nid afterwards:
+ * otherwise there's a window in which a racer might
+ * pass invalid nid MAX_NUMNODES to alloc_pages_node.
+ * But we don't need to use a spin_lock here: it really
+ * doesn't matter if occasionally a racer chooses the
+ * same nid as we do. Move nid forward in the mask even
+ * if we just successfully allocated a hugepage so that
+ * the next caller gets hugepages on the next node.
+ */
+static int hstate_next_node(struct hstate *h)
+{
+ int next_nid;
+ next_nid = next_node(h->hugetlb_next_nid, node_online_map);
+ if (next_nid == MAX_NUMNODES)
+ next_nid = first_node(node_online_map);
+ h->hugetlb_next_nid = next_nid;
+ return next_nid;
+}
+
+static int alloc_fresh_huge_page(struct hstate *h)
{
struct page *page;
int start_nid;
int next_nid;
int ret = 0;
- start_nid = hugetlb_next_nid;
+ start_nid = h->hugetlb_next_nid;
do {
- page = alloc_fresh_huge_page_node(hugetlb_next_nid);
+ page = alloc_fresh_huge_page_node(h, h->hugetlb_next_nid);
if (page)
ret = 1;
- /*
- * Use a helper variable to find the next node and then
- * copy it back to hugetlb_next_nid afterwards:
- * otherwise there's a window in which a racer might
- * pass invalid nid MAX_NUMNODES to alloc_pages_node.
- * But we don't need to use a spin_lock here: it really
- * doesn't matter if occasionally a racer chooses the
- * same nid as we do. Move nid forward in the mask even
- * if we just successfully allocated a hugepage so that
- * the next caller gets hugepages on the next node.
- */
- next_nid = next_node(hugetlb_next_nid, node_online_map);
- if (next_nid == MAX_NUMNODES)
- next_nid = first_node(node_online_map);
- hugetlb_next_nid = next_nid;
- } while (!page && hugetlb_next_nid != start_nid);
+ next_nid = hstate_next_node(h);
+ } while (!page && h->hugetlb_next_nid != start_nid);
if (ret)
count_vm_event(HTLB_BUDDY_PGALLOC);
@@ -256,12 +617,15 @@ static int alloc_fresh_huge_page(void)
return ret;
}
-static struct page *alloc_buddy_huge_page(struct vm_area_struct *vma,
- unsigned long address)
+static struct page *alloc_buddy_huge_page(struct hstate *h,
+ struct vm_area_struct *vma, unsigned long address)
{
struct page *page;
unsigned int nid;
+ if (h->order >= MAX_ORDER)
+ return NULL;
+
/*
* Assume we will successfully allocate the surplus page to
* prevent racing processes from causing the surplus to exceed
@@ -286,18 +650,18 @@ static struct page *alloc_buddy_huge_page(struct vm_area_struct *vma,
* per-node value is checked there.
*/
spin_lock(&hugetlb_lock);
- if (surplus_huge_pages >= nr_overcommit_huge_pages) {
+ if (h->surplus_huge_pages >= h->nr_overcommit_huge_pages) {
spin_unlock(&hugetlb_lock);
return NULL;
} else {
- nr_huge_pages++;
- surplus_huge_pages++;
+ h->nr_huge_pages++;
+ h->surplus_huge_pages++;
}
spin_unlock(&hugetlb_lock);
page = alloc_pages(htlb_alloc_mask|__GFP_COMP|
__GFP_REPEAT|__GFP_NOWARN,
- HUGETLB_PAGE_ORDER);
+ huge_page_order(h));
spin_lock(&hugetlb_lock);
if (page) {
@@ -312,12 +676,12 @@ static struct page *alloc_buddy_huge_page(struct vm_area_struct *vma,
/*
* We incremented the global counters already
*/
- nr_huge_pages_node[nid]++;
- surplus_huge_pages_node[nid]++;
+ h->nr_huge_pages_node[nid]++;
+ h->surplus_huge_pages_node[nid]++;
__count_vm_event(HTLB_BUDDY_PGALLOC);
} else {
- nr_huge_pages--;
- surplus_huge_pages--;
+ h->nr_huge_pages--;
+ h->surplus_huge_pages--;
__count_vm_event(HTLB_BUDDY_PGALLOC_FAIL);
}
spin_unlock(&hugetlb_lock);
@@ -329,16 +693,16 @@ static struct page *alloc_buddy_huge_page(struct vm_area_struct *vma,
* Increase the hugetlb pool such that it can accomodate a reservation
* of size 'delta'.
*/
-static int gather_surplus_pages(int delta)
+static int gather_surplus_pages(struct hstate *h, int delta)
{
struct list_head surplus_list;
struct page *page, *tmp;
int ret, i;
int needed, allocated;
- needed = (resv_huge_pages + delta) - free_huge_pages;
+ needed = (h->resv_huge_pages + delta) - h->free_huge_pages;
if (needed <= 0) {
- resv_huge_pages += delta;
+ h->resv_huge_pages += delta;
return 0;
}
@@ -349,7 +713,7 @@ static int gather_surplus_pages(int delta)
retry:
spin_unlock(&hugetlb_lock);
for (i = 0; i < needed; i++) {
- page = alloc_buddy_huge_page(NULL, 0);
+ page = alloc_buddy_huge_page(h, NULL, 0);
if (!page) {
/*
* We were not able to allocate enough pages to
@@ -370,7 +734,8 @@ retry:
* because either resv_huge_pages or free_huge_pages may have changed.
*/
spin_lock(&hugetlb_lock);
- needed = (resv_huge_pages + delta) - (free_huge_pages + allocated);
+ needed = (h->resv_huge_pages + delta) -
+ (h->free_huge_pages + allocated);
if (needed > 0)
goto retry;
@@ -383,7 +748,7 @@ retry:
* before they are reserved.
*/
needed += allocated;
- resv_huge_pages += delta;
+ h->resv_huge_pages += delta;
ret = 0;
free:
/* Free the needed pages to the hugetlb pool */
@@ -391,7 +756,7 @@ free:
if ((--needed) < 0)
break;
list_del(&page->lru);
- enqueue_huge_page(page);
+ enqueue_huge_page(h, page);
}
/* Free unnecessary surplus pages to the buddy allocator */
@@ -419,7 +784,8 @@ free:
* allocated to satisfy the reservation must be explicitly freed if they were
* never used.
*/
-static void return_unused_surplus_pages(unsigned long unused_resv_pages)
+static void return_unused_surplus_pages(struct hstate *h,
+ unsigned long unused_resv_pages)
{
static int nid = -1;
struct page *page;
@@ -434,114 +800,231 @@ static void return_unused_surplus_pages(unsigned long unused_resv_pages)
unsigned long remaining_iterations = num_online_nodes();
/* Uncommit the reservation */
- resv_huge_pages -= unused_resv_pages;
+ h->resv_huge_pages -= unused_resv_pages;
+
+ /* Cannot return gigantic pages currently */
+ if (h->order >= MAX_ORDER)
+ return;
- nr_pages = min(unused_resv_pages, surplus_huge_pages);
+ nr_pages = min(unused_resv_pages, h->surplus_huge_pages);
while (remaining_iterations-- && nr_pages) {
nid = next_node(nid, node_online_map);
if (nid == MAX_NUMNODES)
nid = first_node(node_online_map);
- if (!surplus_huge_pages_node[nid])
+ if (!h->surplus_huge_pages_node[nid])
continue;
- if (!list_empty(&hugepage_freelists[nid])) {
- page = list_entry(hugepage_freelists[nid].next,
+ if (!list_empty(&h->hugepage_freelists[nid])) {
+ page = list_entry(h->hugepage_freelists[nid].next,
struct page, lru);
list_del(&page->lru);
- update_and_free_page(page);
- free_huge_pages--;
- free_huge_pages_node[nid]--;
- surplus_huge_pages--;
- surplus_huge_pages_node[nid]--;
+ update_and_free_page(h, page);
+ h->free_huge_pages--;
+ h->free_huge_pages_node[nid]--;
+ h->surplus_huge_pages--;
+ h->surplus_huge_pages_node[nid]--;
nr_pages--;
remaining_iterations = num_online_nodes();
}
}
}
+/*
+ * Determine if the huge page at addr within the vma has an associated
+ * reservation. Where it does not we will need to logically increase
+ * reservation and actually increase quota before an allocation can occur.
+ * Where any new reservation would be required the reservation change is
+ * prepared, but not committed. Once the page has been quota'd allocated
+ * an instantiated the change should be committed via vma_commit_reservation.
+ * No action is required on failure.
+ */
+static int vma_needs_reservation(struct hstate *h,
+ struct vm_area_struct *vma, unsigned long addr)
+{
+ struct address_space *mapping = vma->vm_file->f_mapping;
+ struct inode *inode = mapping->host;
+
+ if (vma->vm_flags & VM_SHARED) {
+ pgoff_t idx = vma_hugecache_offset(h, vma, addr);
+ return region_chg(&inode->i_mapping->private_list,
+ idx, idx + 1);
+
+ } else if (!is_vma_resv_set(vma, HPAGE_RESV_OWNER)) {
+ return 1;
-static struct page *alloc_huge_page_shared(struct vm_area_struct *vma,
- unsigned long addr)
+ } else {
+ int err;
+ pgoff_t idx = vma_hugecache_offset(h, vma, addr);
+ struct resv_map *reservations = vma_resv_map(vma);
+
+ err = region_chg(&reservations->regions, idx, idx + 1);
+ if (err < 0)
+ return err;
+ return 0;
+ }
+}
+static void vma_commit_reservation(struct hstate *h,
+ struct vm_area_struct *vma, unsigned long addr)
{
- struct page *page;
+ struct address_space *mapping = vma->vm_file->f_mapping;
+ struct inode *inode = mapping->host;
- spin_lock(&hugetlb_lock);
- page = dequeue_huge_page_vma(vma, addr);
- spin_unlock(&hugetlb_lock);
- return page ? page : ERR_PTR(-VM_FAULT_OOM);
+ if (vma->vm_flags & VM_SHARED) {
+ pgoff_t idx = vma_hugecache_offset(h, vma, addr);
+ region_add(&inode->i_mapping->private_list, idx, idx + 1);
+
+ } else if (is_vma_resv_set(vma, HPAGE_RESV_OWNER)) {
+ pgoff_t idx = vma_hugecache_offset(h, vma, addr);
+ struct resv_map *reservations = vma_resv_map(vma);
+
+ /* Mark this page used in the map. */
+ region_add(&reservations->regions, idx, idx + 1);
+ }
}
-static struct page *alloc_huge_page_private(struct vm_area_struct *vma,
- unsigned long addr)
+static struct page *alloc_huge_page(struct vm_area_struct *vma,
+ unsigned long addr, int avoid_reserve)
{
- struct page *page = NULL;
+ struct hstate *h = hstate_vma(vma);
+ struct page *page;
+ struct address_space *mapping = vma->vm_file->f_mapping;
+ struct inode *inode = mapping->host;
+ unsigned int chg;
- if (hugetlb_get_quota(vma->vm_file->f_mapping, 1))
- return ERR_PTR(-VM_FAULT_SIGBUS);
+ /*
+ * Processes that did not create the mapping will have no reserves and
+ * will not have accounted against quota. Check that the quota can be
+ * made before satisfying the allocation
+ * MAP_NORESERVE mappings may also need pages and quota allocated
+ * if no reserve mapping overlaps.
+ */
+ chg = vma_needs_reservation(h, vma, addr);
+ if (chg < 0)
+ return ERR_PTR(chg);
+ if (chg)
+ if (hugetlb_get_quota(inode->i_mapping, chg))
+ return ERR_PTR(-ENOSPC);
spin_lock(&hugetlb_lock);
- if (free_huge_pages > resv_huge_pages)
- page = dequeue_huge_page_vma(vma, addr);
+ page = dequeue_huge_page_vma(h, vma, addr, avoid_reserve);
spin_unlock(&hugetlb_lock);
+
if (!page) {
- page = alloc_buddy_huge_page(vma, addr);
+ page = alloc_buddy_huge_page(h, vma, addr);
if (!page) {
- hugetlb_put_quota(vma->vm_file->f_mapping, 1);
+ hugetlb_put_quota(inode->i_mapping, chg);
return ERR_PTR(-VM_FAULT_OOM);
}
}
+
+ set_page_refcounted(page);
+ set_page_private(page, (unsigned long) mapping);
+
+ vma_commit_reservation(h, vma, addr);
+
return page;
}
-static struct page *alloc_huge_page(struct vm_area_struct *vma,
- unsigned long addr)
+__attribute__((weak)) int alloc_bootmem_huge_page(struct hstate *h)
{
- struct page *page;
- struct address_space *mapping = vma->vm_file->f_mapping;
+ struct huge_bootmem_page *m;
+ int nr_nodes = nodes_weight(node_online_map);
- if (vma->vm_flags & VM_MAYSHARE)
- page = alloc_huge_page_shared(vma, addr);
- else
- page = alloc_huge_page_private(vma, addr);
+ while (nr_nodes) {
+ void *addr;
+
+ addr = __alloc_bootmem_node_nopanic(
+ NODE_DATA(h->hugetlb_next_nid),
+ huge_page_size(h), huge_page_size(h), 0);
+
+ if (addr) {
+ /*
+ * Use the beginning of the huge page to store the
+ * huge_bootmem_page struct (until gather_bootmem
+ * puts them into the mem_map).
+ */
+ m = addr;
+ if (m)
+ goto found;
+ }
+ hstate_next_node(h);
+ nr_nodes--;
+ }
+ return 0;
+
+found:
+ BUG_ON((unsigned long)virt_to_phys(m) & (huge_page_size(h) - 1));
+ /* Put them into a private list first because mem_map is not up yet */
+ list_add(&m->list, &huge_boot_pages);
+ m->hstate = h;
+ return 1;
+}
- if (!IS_ERR(page)) {
- set_page_refcounted(page);
- set_page_private(page, (unsigned long) mapping);
+/* Put bootmem huge pages into the standard lists after mem_map is up */
+static void __init gather_bootmem_prealloc(void)
+{
+ struct huge_bootmem_page *m;
+
+ list_for_each_entry(m, &huge_boot_pages, list) {
+ struct page *page = virt_to_page(m);
+ struct hstate *h = m->hstate;
+ __ClearPageReserved(page);
+ WARN_ON(page_count(page) != 1);
+ prep_compound_page(page, h->order);
+ prep_new_huge_page(h, page, page_to_nid(page));
}
- return page;
}
-static int __init hugetlb_init(void)
+static void __init hugetlb_hstate_alloc_pages(struct hstate *h)
{
unsigned long i;
- if (HPAGE_SHIFT == 0)
- return 0;
-
- for (i = 0; i < MAX_NUMNODES; ++i)
- INIT_LIST_HEAD(&hugepage_freelists[i]);
+ for (i = 0; i < h->max_huge_pages; ++i) {
+ if (h->order >= MAX_ORDER) {
+ if (!alloc_bootmem_huge_page(h))
+ break;
+ } else if (!alloc_fresh_huge_page(h))
+ break;
+ }
+ h->max_huge_pages = i;
+}
- hugetlb_next_nid = first_node(node_online_map);
+static void __init hugetlb_init_hstates(void)
+{
+ struct hstate *h;
- for (i = 0; i < max_huge_pages; ++i) {
- if (!alloc_fresh_huge_page())
- break;
+ for_each_hstate(h) {
+ /* oversize hugepages were init'ed in early boot */
+ if (h->order < MAX_ORDER)
+ hugetlb_hstate_alloc_pages(h);
}
- max_huge_pages = free_huge_pages = nr_huge_pages = i;
- printk("Total HugeTLB memory allocated, %ld\n", free_huge_pages);
- return 0;
}
-module_init(hugetlb_init);
-static int __init hugetlb_setup(char *s)
+static char * __init memfmt(char *buf, unsigned long n)
{
- if (sscanf(s, "%lu", &max_huge_pages) <= 0)
- max_huge_pages = 0;
- return 1;
+ if (n >= (1UL << 30))
+ sprintf(buf, "%lu GB", n >> 30);
+ else if (n >= (1UL << 20))
+ sprintf(buf, "%lu MB", n >> 20);
+ else
+ sprintf(buf, "%lu KB", n >> 10);
+ return buf;
+}
+
+static void __init report_hugepages(void)
+{
+ struct hstate *h;
+
+ for_each_hstate(h) {
+ char buf[32];
+ printk(KERN_INFO "HugeTLB registered %s page size, "
+ "pre-allocated %ld pages\n",
+ memfmt(buf, huge_page_size(h)),
+ h->free_huge_pages);
+ }
}
-__setup("hugepages=", hugetlb_setup);
static unsigned int cpuset_mems_nr(unsigned int *array)
{
@@ -556,35 +1039,42 @@ static unsigned int cpuset_mems_nr(unsigned int *array)
#ifdef CONFIG_SYSCTL
#ifdef CONFIG_HIGHMEM
-static void try_to_free_low(unsigned long count)
+static void try_to_free_low(struct hstate *h, unsigned long count)
{
int i;
+ if (h->order >= MAX_ORDER)
+ return;
+
for (i = 0; i < MAX_NUMNODES; ++i) {
struct page *page, *next;
- list_for_each_entry_safe(page, next, &hugepage_freelists[i], lru) {
- if (count >= nr_huge_pages)
+ struct list_head *freel = &h->hugepage_freelists[i];
+ list_for_each_entry_safe(page, next, freel, lru) {
+ if (count >= h->nr_huge_pages)
return;
if (PageHighMem(page))
continue;
list_del(&page->lru);
- update_and_free_page(page);
- free_huge_pages--;
- free_huge_pages_node[page_to_nid(page)]--;
+ update_and_free_page(h, page);
+ h->free_huge_pages--;
+ h->free_huge_pages_node[page_to_nid(page)]--;
}
}
}
#else
-static inline void try_to_free_low(unsigned long count)
+static inline void try_to_free_low(struct hstate *h, unsigned long count)
{
}
#endif
-#define persistent_huge_pages (nr_huge_pages - surplus_huge_pages)
-static unsigned long set_max_huge_pages(unsigned long count)
+#define persistent_huge_pages(h) (h->nr_huge_pages - h->surplus_huge_pages)
+static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count)
{
unsigned long min_count, ret;
+ if (h->order >= MAX_ORDER)
+ return h->max_huge_pages;
+
/*
* Increase the pool size
* First take pages out of surplus state. Then make up the
@@ -597,20 +1087,19 @@ static unsigned long set_max_huge_pages(unsigned long count)
* within all the constraints specified by the sysctls.
*/
spin_lock(&hugetlb_lock);
- while (surplus_huge_pages && count > persistent_huge_pages) {
- if (!adjust_pool_surplus(-1))
+ while (h->surplus_huge_pages && count > persistent_huge_pages(h)) {
+ if (!adjust_pool_surplus(h, -1))
break;
}
- while (count > persistent_huge_pages) {
- int ret;
+ while (count > persistent_huge_pages(h)) {
/*
* If this allocation races such that we no longer need the
* page, free_huge_page will handle it by freeing the page
* and reducing the surplus.
*/
spin_unlock(&hugetlb_lock);
- ret = alloc_fresh_huge_page();
+ ret = alloc_fresh_huge_page(h);
spin_lock(&hugetlb_lock);
if (!ret)
goto out;
@@ -632,31 +1121,288 @@ static unsigned long set_max_huge_pages(unsigned long count)
* and won't grow the pool anywhere else. Not until one of the
* sysctls are changed, or the surplus pages go out of use.
*/
- min_count = resv_huge_pages + nr_huge_pages - free_huge_pages;
+ min_count = h->resv_huge_pages + h->nr_huge_pages - h->free_huge_pages;
min_count = max(count, min_count);
- try_to_free_low(min_count);
- while (min_count < persistent_huge_pages) {
- struct page *page = dequeue_huge_page();
+ try_to_free_low(h, min_count);
+ while (min_count < persistent_huge_pages(h)) {
+ struct page *page = dequeue_huge_page(h);
if (!page)
break;
- update_and_free_page(page);
+ update_and_free_page(h, page);
}
- while (count < persistent_huge_pages) {
- if (!adjust_pool_surplus(1))
+ while (count < persistent_huge_pages(h)) {
+ if (!adjust_pool_surplus(h, 1))
break;
}
out:
- ret = persistent_huge_pages;
+ ret = persistent_huge_pages(h);
spin_unlock(&hugetlb_lock);
return ret;
}
+#define HSTATE_ATTR_RO(_name) \
+ static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
+
+#define HSTATE_ATTR(_name) \
+ static struct kobj_attribute _name##_attr = \
+ __ATTR(_name, 0644, _name##_show, _name##_store)
+
+static struct kobject *hugepages_kobj;
+static struct kobject *hstate_kobjs[HUGE_MAX_HSTATE];
+
+static struct hstate *kobj_to_hstate(struct kobject *kobj)
+{
+ int i;
+ for (i = 0; i < HUGE_MAX_HSTATE; i++)
+ if (hstate_kobjs[i] == kobj)
+ return &hstates[i];
+ BUG();
+ return NULL;
+}
+
+static ssize_t nr_hugepages_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct hstate *h = kobj_to_hstate(kobj);
+ return sprintf(buf, "%lu\n", h->nr_huge_pages);
+}
+static ssize_t nr_hugepages_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ int err;
+ unsigned long input;
+ struct hstate *h = kobj_to_hstate(kobj);
+
+ err = strict_strtoul(buf, 10, &input);
+ if (err)
+ return 0;
+
+ h->max_huge_pages = set_max_huge_pages(h, input);
+
+ return count;
+}
+HSTATE_ATTR(nr_hugepages);
+
+static ssize_t nr_overcommit_hugepages_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct hstate *h = kobj_to_hstate(kobj);
+ return sprintf(buf, "%lu\n", h->nr_overcommit_huge_pages);
+}
+static ssize_t nr_overcommit_hugepages_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ int err;
+ unsigned long input;
+ struct hstate *h = kobj_to_hstate(kobj);
+
+ err = strict_strtoul(buf, 10, &input);
+ if (err)
+ return 0;
+
+ spin_lock(&hugetlb_lock);
+ h->nr_overcommit_huge_pages = input;
+ spin_unlock(&hugetlb_lock);
+
+ return count;
+}
+HSTATE_ATTR(nr_overcommit_hugepages);
+
+static ssize_t free_hugepages_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct hstate *h = kobj_to_hstate(kobj);
+ return sprintf(buf, "%lu\n", h->free_huge_pages);
+}
+HSTATE_ATTR_RO(free_hugepages);
+
+static ssize_t resv_hugepages_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct hstate *h = kobj_to_hstate(kobj);
+ return sprintf(buf, "%lu\n", h->resv_huge_pages);
+}
+HSTATE_ATTR_RO(resv_hugepages);
+
+static ssize_t surplus_hugepages_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct hstate *h = kobj_to_hstate(kobj);
+ return sprintf(buf, "%lu\n", h->surplus_huge_pages);
+}
+HSTATE_ATTR_RO(surplus_hugepages);
+
+static struct attribute *hstate_attrs[] = {
+ &nr_hugepages_attr.attr,
+ &nr_overcommit_hugepages_attr.attr,
+ &free_hugepages_attr.attr,
+ &resv_hugepages_attr.attr,
+ &surplus_hugepages_attr.attr,
+ NULL,
+};
+
+static struct attribute_group hstate_attr_group = {
+ .attrs = hstate_attrs,
+};
+
+static int __init hugetlb_sysfs_add_hstate(struct hstate *h)
+{
+ int retval;
+
+ hstate_kobjs[h - hstates] = kobject_create_and_add(h->name,
+ hugepages_kobj);
+ if (!hstate_kobjs[h - hstates])
+ return -ENOMEM;
+
+ retval = sysfs_create_group(hstate_kobjs[h - hstates],
+ &hstate_attr_group);
+ if (retval)
+ kobject_put(hstate_kobjs[h - hstates]);
+
+ return retval;
+}
+
+static void __init hugetlb_sysfs_init(void)
+{
+ struct hstate *h;
+ int err;
+
+ hugepages_kobj = kobject_create_and_add("hugepages", mm_kobj);
+ if (!hugepages_kobj)
+ return;
+
+ for_each_hstate(h) {
+ err = hugetlb_sysfs_add_hstate(h);
+ if (err)
+ printk(KERN_ERR "Hugetlb: Unable to add hstate %s",
+ h->name);
+ }
+}
+
+static void __exit hugetlb_exit(void)
+{
+ struct hstate *h;
+
+ for_each_hstate(h) {
+ kobject_put(hstate_kobjs[h - hstates]);
+ }
+
+ kobject_put(hugepages_kobj);
+}
+module_exit(hugetlb_exit);
+
+static int __init hugetlb_init(void)
+{
+ BUILD_BUG_ON(HPAGE_SHIFT == 0);
+
+ if (!size_to_hstate(default_hstate_size)) {
+ default_hstate_size = HPAGE_SIZE;
+ if (!size_to_hstate(default_hstate_size))
+ hugetlb_add_hstate(HUGETLB_PAGE_ORDER);
+ }
+ default_hstate_idx = size_to_hstate(default_hstate_size) - hstates;
+ if (default_hstate_max_huge_pages)
+ default_hstate.max_huge_pages = default_hstate_max_huge_pages;
+
+ hugetlb_init_hstates();
+
+ gather_bootmem_prealloc();
+
+ report_hugepages();
+
+ hugetlb_sysfs_init();
+
+ return 0;
+}
+module_init(hugetlb_init);
+
+/* Should be called on processing a hugepagesz=... option */
+void __init hugetlb_add_hstate(unsigned order)
+{
+ struct hstate *h;
+ unsigned long i;
+
+ if (size_to_hstate(PAGE_SIZE << order)) {
+ printk(KERN_WARNING "hugepagesz= specified twice, ignoring\n");
+ return;
+ }
+ BUG_ON(max_hstate >= HUGE_MAX_HSTATE);
+ BUG_ON(order == 0);
+ h = &hstates[max_hstate++];
+ h->order = order;
+ h->mask = ~((1ULL << (order + PAGE_SHIFT)) - 1);
+ h->nr_huge_pages = 0;
+ h->free_huge_pages = 0;
+ for (i = 0; i < MAX_NUMNODES; ++i)
+ INIT_LIST_HEAD(&h->hugepage_freelists[i]);
+ h->hugetlb_next_nid = first_node(node_online_map);
+ snprintf(h->name, HSTATE_NAME_LEN, "hugepages-%lukB",
+ huge_page_size(h)/1024);
+
+ parsed_hstate = h;
+}
+
+static int __init hugetlb_nrpages_setup(char *s)
+{
+ unsigned long *mhp;
+ static unsigned long *last_mhp;
+
+ /*
+ * !max_hstate means we haven't parsed a hugepagesz= parameter yet,
+ * so this hugepages= parameter goes to the "default hstate".
+ */
+ if (!max_hstate)
+ mhp = &default_hstate_max_huge_pages;
+ else
+ mhp = &parsed_hstate->max_huge_pages;
+
+ if (mhp == last_mhp) {
+ printk(KERN_WARNING "hugepages= specified twice without "
+ "interleaving hugepagesz=, ignoring\n");
+ return 1;
+ }
+
+ if (sscanf(s, "%lu", mhp) <= 0)
+ *mhp = 0;
+
+ /*
+ * Global state is always initialized later in hugetlb_init.
+ * But we need to allocate >= MAX_ORDER hstates here early to still
+ * use the bootmem allocator.
+ */
+ if (max_hstate && parsed_hstate->order >= MAX_ORDER)
+ hugetlb_hstate_alloc_pages(parsed_hstate);
+
+ last_mhp = mhp;
+
+ return 1;
+}
+__setup("hugepages=", hugetlb_nrpages_setup);
+
+static int __init hugetlb_default_setup(char *s)
+{
+ default_hstate_size = memparse(s, &s);
+ return 1;
+}
+__setup("default_hugepagesz=", hugetlb_default_setup);
+
int hugetlb_sysctl_handler(struct ctl_table *table, int write,
struct file *file, void __user *buffer,
size_t *length, loff_t *ppos)
{
+ struct hstate *h = &default_hstate;
+ unsigned long tmp;
+
+ if (!write)
+ tmp = h->max_huge_pages;
+
+ table->data = &tmp;
+ table->maxlen = sizeof(unsigned long);
proc_doulongvec_minmax(table, write, file, buffer, length, ppos);
- max_huge_pages = set_max_huge_pages(max_huge_pages);
+
+ if (write)
+ h->max_huge_pages = set_max_huge_pages(h, tmp);
+
return 0;
}
@@ -676,10 +1422,22 @@ int hugetlb_overcommit_handler(struct ctl_table *table, int write,
struct file *file, void __user *buffer,
size_t *length, loff_t *ppos)
{
+ struct hstate *h = &default_hstate;
+ unsigned long tmp;
+
+ if (!write)
+ tmp = h->nr_overcommit_huge_pages;
+
+ table->data = &tmp;
+ table->maxlen = sizeof(unsigned long);
proc_doulongvec_minmax(table, write, file, buffer, length, ppos);
- spin_lock(&hugetlb_lock);
- nr_overcommit_huge_pages = sysctl_overcommit_huge_pages;
- spin_unlock(&hugetlb_lock);
+
+ if (write) {
+ spin_lock(&hugetlb_lock);
+ h->nr_overcommit_huge_pages = tmp;
+ spin_unlock(&hugetlb_lock);
+ }
+
return 0;
}
@@ -687,34 +1445,118 @@ int hugetlb_overcommit_handler(struct ctl_table *table, int write,
int hugetlb_report_meminfo(char *buf)
{
+ struct hstate *h = &default_hstate;
return sprintf(buf,
"HugePages_Total: %5lu\n"
"HugePages_Free: %5lu\n"
"HugePages_Rsvd: %5lu\n"
"HugePages_Surp: %5lu\n"
"Hugepagesize: %5lu kB\n",
- nr_huge_pages,
- free_huge_pages,
- resv_huge_pages,
- surplus_huge_pages,
- HPAGE_SIZE/1024);
+ h->nr_huge_pages,
+ h->free_huge_pages,
+ h->resv_huge_pages,
+ h->surplus_huge_pages,
+ 1UL << (huge_page_order(h) + PAGE_SHIFT - 10));
}
int hugetlb_report_node_meminfo(int nid, char *buf)
{
+ struct hstate *h = &default_hstate;
return sprintf(buf,
"Node %d HugePages_Total: %5u\n"
"Node %d HugePages_Free: %5u\n"
"Node %d HugePages_Surp: %5u\n",
- nid, nr_huge_pages_node[nid],
- nid, free_huge_pages_node[nid],
- nid, surplus_huge_pages_node[nid]);
+ nid, h->nr_huge_pages_node[nid],
+ nid, h->free_huge_pages_node[nid],
+ nid, h->surplus_huge_pages_node[nid]);
}
/* Return the number pages of memory we physically have, in PAGE_SIZE units. */
unsigned long hugetlb_total_pages(void)
{
- return nr_huge_pages * (HPAGE_SIZE / PAGE_SIZE);
+ struct hstate *h = &default_hstate;
+ return h->nr_huge_pages * pages_per_huge_page(h);
+}
+
+static int hugetlb_acct_memory(struct hstate *h, long delta)
+{
+ int ret = -ENOMEM;
+
+ spin_lock(&hugetlb_lock);
+ /*
+ * When cpuset is configured, it breaks the strict hugetlb page
+ * reservation as the accounting is done on a global variable. Such
+ * reservation is completely rubbish in the presence of cpuset because
+ * the reservation is not checked against page availability for the
+ * current cpuset. Application can still potentially OOM'ed by kernel
+ * with lack of free htlb page in cpuset that the task is in.
+ * Attempt to enforce strict accounting with cpuset is almost
+ * impossible (or too ugly) because cpuset is too fluid that
+ * task or memory node can be dynamically moved between cpusets.
+ *
+ * The change of semantics for shared hugetlb mapping with cpuset is
+ * undesirable. However, in order to preserve some of the semantics,
+ * we fall back to check against current free page availability as
+ * a best attempt and hopefully to minimize the impact of changing
+ * semantics that cpuset has.
+ */
+ if (delta > 0) {
+ if (gather_surplus_pages(h, delta) < 0)
+ goto out;
+
+ if (delta > cpuset_mems_nr(h->free_huge_pages_node)) {
+ return_unused_surplus_pages(h, delta);
+ goto out;
+ }
+ }
+
+ ret = 0;
+ if (delta < 0)
+ return_unused_surplus_pages(h, (unsigned long) -delta);
+
+out:
+ spin_unlock(&hugetlb_lock);
+ return ret;
+}
+
+static void hugetlb_vm_op_open(struct vm_area_struct *vma)
+{
+ struct resv_map *reservations = vma_resv_map(vma);
+
+ /*
+ * This new VMA should share its siblings reservation map if present.
+ * The VMA will only ever have a valid reservation map pointer where
+ * it is being copied for another still existing VMA. As that VMA
+ * has a reference to the reservation map it cannot dissappear until
+ * after this open call completes. It is therefore safe to take a
+ * new reference here without additional locking.
+ */
+ if (reservations)
+ kref_get(&reservations->refs);
+}
+
+static void hugetlb_vm_op_close(struct vm_area_struct *vma)
+{
+ struct hstate *h = hstate_vma(vma);
+ struct resv_map *reservations = vma_resv_map(vma);
+ unsigned long reserve;
+ unsigned long start;
+ unsigned long end;
+
+ if (reservations) {
+ start = vma_hugecache_offset(h, vma, vma->vm_start);
+ end = vma_hugecache_offset(h, vma, vma->vm_end);
+
+ reserve = (end - start) -
+ region_count(&reservations->regions, start, end);
+
+ kref_put(&reservations->refs, resv_map_release);
+
+ if (reserve) {
+ hugetlb_acct_memory(h, -reserve);
+ hugetlb_put_quota(vma->vm_file->f_mapping, reserve);
+ }
+ }
}
/*
@@ -731,6 +1573,8 @@ static int hugetlb_vm_op_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
struct vm_operations_struct hugetlb_vm_ops = {
.fault = hugetlb_vm_op_fault,
+ .open = hugetlb_vm_op_open,
+ .close = hugetlb_vm_op_close,
};
static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page,
@@ -769,14 +1613,16 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
struct page *ptepage;
unsigned long addr;
int cow;
+ struct hstate *h = hstate_vma(vma);
+ unsigned long sz = huge_page_size(h);
cow = (vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
- for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
+ for (addr = vma->vm_start; addr < vma->vm_end; addr += sz) {
src_pte = huge_pte_offset(src, addr);
if (!src_pte)
continue;
- dst_pte = huge_pte_alloc(dst, addr);
+ dst_pte = huge_pte_alloc(dst, addr, sz);
if (!dst_pte)
goto nomem;
@@ -804,7 +1650,7 @@ nomem:
}
void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
- unsigned long end)
+ unsigned long end, struct page *ref_page)
{
struct mm_struct *mm = vma->vm_mm;
unsigned long address;
@@ -812,6 +1658,9 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
pte_t pte;
struct page *page;
struct page *tmp;
+ struct hstate *h = hstate_vma(vma);
+ unsigned long sz = huge_page_size(h);
+
/*
* A page gathering list, protected by per file i_mmap_lock. The
* lock is used to avoid list corruption from multiple unmapping
@@ -820,11 +1669,11 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
LIST_HEAD(page_list);
WARN_ON(!is_vm_hugetlb_page(vma));
- BUG_ON(start & ~HPAGE_MASK);
- BUG_ON(end & ~HPAGE_MASK);
+ BUG_ON(start & ~huge_page_mask(h));
+ BUG_ON(end & ~huge_page_mask(h));
spin_lock(&mm->page_table_lock);
- for (address = start; address < end; address += HPAGE_SIZE) {
+ for (address = start; address < end; address += sz) {
ptep = huge_pte_offset(mm, address);
if (!ptep)
continue;
@@ -832,6 +1681,27 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
if (huge_pmd_unshare(mm, &address, ptep))
continue;
+ /*
+ * If a reference page is supplied, it is because a specific
+ * page is being unmapped, not a range. Ensure the page we
+ * are about to unmap is the actual page of interest.
+ */
+ if (ref_page) {
+ pte = huge_ptep_get(ptep);
+ if (huge_pte_none(pte))
+ continue;
+ page = pte_page(pte);
+ if (page != ref_page)
+ continue;
+
+ /*
+ * Mark the VMA as having unmapped its page so that
+ * future faults in this VMA will fail rather than
+ * looking like data was lost
+ */
+ set_vma_resv_flags(vma, HPAGE_RESV_UNMAPPED);
+ }
+
pte = huge_ptep_get_and_clear(mm, address, ptep);
if (huge_pte_none(pte))
continue;
@@ -850,31 +1720,71 @@ void __unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
}
void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
- unsigned long end)
+ unsigned long end, struct page *ref_page)
{
+ spin_lock(&vma->vm_file->f_mapping->i_mmap_lock);
+ __unmap_hugepage_range(vma, start, end, ref_page);
+ spin_unlock(&vma->vm_file->f_mapping->i_mmap_lock);
+}
+
+/*
+ * This is called when the original mapper is failing to COW a MAP_PRIVATE
+ * mappping it owns the reserve page for. The intention is to unmap the page
+ * from other VMAs and let the children be SIGKILLed if they are faulting the
+ * same region.
+ */
+int unmap_ref_private(struct mm_struct *mm,
+ struct vm_area_struct *vma,
+ struct page *page,
+ unsigned long address)
+{
+ struct vm_area_struct *iter_vma;
+ struct address_space *mapping;
+ struct prio_tree_iter iter;
+ pgoff_t pgoff;
+
/*
- * It is undesirable to test vma->vm_file as it should be non-null
- * for valid hugetlb area. However, vm_file will be NULL in the error
- * cleanup path of do_mmap_pgoff. When hugetlbfs ->mmap method fails,
- * do_mmap_pgoff() nullifies vma->vm_file before calling this function
- * to clean up. Since no pte has actually been setup, it is safe to
- * do nothing in this case.
+ * vm_pgoff is in PAGE_SIZE units, hence the different calculation
+ * from page cache lookup which is in HPAGE_SIZE units.
*/
- if (vma->vm_file) {
- spin_lock(&vma->vm_file->f_mapping->i_mmap_lock);
- __unmap_hugepage_range(vma, start, end);
- spin_unlock(&vma->vm_file->f_mapping->i_mmap_lock);
+ address = address & huge_page_mask(hstate_vma(vma));
+ pgoff = ((address - vma->vm_start) >> PAGE_SHIFT)
+ + (vma->vm_pgoff >> PAGE_SHIFT);
+ mapping = (struct address_space *)page_private(page);
+
+ vma_prio_tree_foreach(iter_vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
+ /* Do not unmap the current VMA */
+ if (iter_vma == vma)
+ continue;
+
+ /*
+ * Unmap the page from other VMAs without their own reserves.
+ * They get marked to be SIGKILLed if they fault in these
+ * areas. This is because a future no-page fault on this VMA
+ * could insert a zeroed page instead of the data existing
+ * from the time of fork. This would look like data corruption
+ */
+ if (!is_vma_resv_set(iter_vma, HPAGE_RESV_OWNER))
+ unmap_hugepage_range(iter_vma,
+ address, address + HPAGE_SIZE,
+ page);
}
+
+ return 1;
}
static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
- unsigned long address, pte_t *ptep, pte_t pte)
+ unsigned long address, pte_t *ptep, pte_t pte,
+ struct page *pagecache_page)
{
+ struct hstate *h = hstate_vma(vma);
struct page *old_page, *new_page;
int avoidcopy;
+ int outside_reserve = 0;
old_page = pte_page(pte);
+retry_avoidcopy:
/* If no-one else is actually using this page, avoid the copy
* and just make the page writable */
avoidcopy = (page_count(old_page) == 1);
@@ -883,11 +1793,43 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
return 0;
}
+ /*
+ * If the process that created a MAP_PRIVATE mapping is about to
+ * perform a COW due to a shared page count, attempt to satisfy
+ * the allocation without using the existing reserves. The pagecache
+ * page is used to determine if the reserve at this address was
+ * consumed or not. If reserves were used, a partial faulted mapping
+ * at the time of fork() could consume its reserves on COW instead
+ * of the full address range.
+ */
+ if (!(vma->vm_flags & VM_SHARED) &&
+ is_vma_resv_set(vma, HPAGE_RESV_OWNER) &&
+ old_page != pagecache_page)
+ outside_reserve = 1;
+
page_cache_get(old_page);
- new_page = alloc_huge_page(vma, address);
+ new_page = alloc_huge_page(vma, address, outside_reserve);
if (IS_ERR(new_page)) {
page_cache_release(old_page);
+
+ /*
+ * If a process owning a MAP_PRIVATE mapping fails to COW,
+ * it is due to references held by a child and an insufficient
+ * huge page pool. To guarantee the original mappers
+ * reliability, unmap the page from child processes. The child
+ * may get SIGKILLed if it later faults.
+ */
+ if (outside_reserve) {
+ BUG_ON(huge_pte_none(pte));
+ if (unmap_ref_private(mm, vma, old_page, address)) {
+ BUG_ON(page_count(old_page) != 1);
+ BUG_ON(huge_pte_none(pte));
+ goto retry_avoidcopy;
+ }
+ WARN_ON_ONCE(1);
+ }
+
return -PTR_ERR(new_page);
}
@@ -896,7 +1838,7 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
__SetPageUptodate(new_page);
spin_lock(&mm->page_table_lock);
- ptep = huge_pte_offset(mm, address & HPAGE_MASK);
+ ptep = huge_pte_offset(mm, address & huge_page_mask(h));
if (likely(pte_same(huge_ptep_get(ptep), pte))) {
/* Break COW */
huge_ptep_clear_flush(vma, address, ptep);
@@ -910,19 +1852,44 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
return 0;
}
+/* Return the pagecache page at a given address within a VMA */
+static struct page *hugetlbfs_pagecache_page(struct hstate *h,
+ struct vm_area_struct *vma, unsigned long address)
+{
+ struct address_space *mapping;
+ pgoff_t idx;
+
+ mapping = vma->vm_file->f_mapping;
+ idx = vma_hugecache_offset(h, vma, address);
+
+ return find_lock_page(mapping, idx);
+}
+
static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long address, pte_t *ptep, int write_access)
{
+ struct hstate *h = hstate_vma(vma);
int ret = VM_FAULT_SIGBUS;
- unsigned long idx;
+ pgoff_t idx;
unsigned long size;
struct page *page;
struct address_space *mapping;
pte_t new_pte;
+ /*
+ * Currently, we are forced to kill the process in the event the
+ * original mapper has unmapped pages from the child due to a failed
+ * COW. Warn that such a situation has occured as it may not be obvious
+ */
+ if (is_vma_resv_set(vma, HPAGE_RESV_UNMAPPED)) {
+ printk(KERN_WARNING
+ "PID %d killed due to inadequate hugepage pool\n",
+ current->pid);
+ return ret;
+ }
+
mapping = vma->vm_file->f_mapping;
- idx = ((address - vma->vm_start) >> HPAGE_SHIFT)
- + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
+ idx = vma_hugecache_offset(h, vma, address);
/*
* Use page lock to guard against racing truncation
@@ -931,15 +1898,15 @@ static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
retry:
page = find_lock_page(mapping, idx);
if (!page) {
- size = i_size_read(mapping->host) >> HPAGE_SHIFT;
+ size = i_size_read(mapping->host) >> huge_page_shift(h);
if (idx >= size)
goto out;
- page = alloc_huge_page(vma, address);
+ page = alloc_huge_page(vma, address, 0);
if (IS_ERR(page)) {
ret = -PTR_ERR(page);
goto out;
}
- clear_huge_page(page, address);
+ clear_huge_page(page, address, huge_page_size(h));
__SetPageUptodate(page);
if (vma->vm_flags & VM_SHARED) {
@@ -955,14 +1922,14 @@ retry:
}
spin_lock(&inode->i_lock);
- inode->i_blocks += BLOCKS_PER_HUGEPAGE;
+ inode->i_blocks += blocks_per_huge_page(h);
spin_unlock(&inode->i_lock);
} else
lock_page(page);
}
spin_lock(&mm->page_table_lock);
- size = i_size_read(mapping->host) >> HPAGE_SHIFT;
+ size = i_size_read(mapping->host) >> huge_page_shift(h);
if (idx >= size)
goto backout;
@@ -976,7 +1943,7 @@ retry:
if (write_access && !(vma->vm_flags & VM_SHARED)) {
/* Optimization, do the COW without a second fault */
- ret = hugetlb_cow(mm, vma, address, ptep, new_pte);
+ ret = hugetlb_cow(mm, vma, address, ptep, new_pte, page);
}
spin_unlock(&mm->page_table_lock);
@@ -998,8 +1965,9 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
pte_t entry;
int ret;
static DEFINE_MUTEX(hugetlb_instantiation_mutex);
+ struct hstate *h = hstate_vma(vma);
- ptep = huge_pte_alloc(mm, address);
+ ptep = huge_pte_alloc(mm, address, huge_page_size(h));
if (!ptep)
return VM_FAULT_OOM;
@@ -1021,14 +1989,30 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
spin_lock(&mm->page_table_lock);
/* Check for a racing update before calling hugetlb_cow */
if (likely(pte_same(entry, huge_ptep_get(ptep))))
- if (write_access && !pte_write(entry))
- ret = hugetlb_cow(mm, vma, address, ptep, entry);
+ if (write_access && !pte_write(entry)) {
+ struct page *page;
+ page = hugetlbfs_pagecache_page(h, vma, address);
+ ret = hugetlb_cow(mm, vma, address, ptep, entry, page);
+ if (page) {
+ unlock_page(page);
+ put_page(page);
+ }
+ }
spin_unlock(&mm->page_table_lock);
mutex_unlock(&hugetlb_instantiation_mutex);
return ret;
}
+/* Can be overriden by architectures */
+__attribute__((weak)) struct page *
+follow_huge_pud(struct mm_struct *mm, unsigned long address,
+ pud_t *pud, int write)
+{
+ BUG();
+ return NULL;
+}
+
int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
struct page **pages, struct vm_area_struct **vmas,
unsigned long *position, int *length, int i,
@@ -1037,6 +2021,7 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long pfn_offset;
unsigned long vaddr = *position;
int remainder = *length;
+ struct hstate *h = hstate_vma(vma);
spin_lock(&mm->page_table_lock);
while (vaddr < vma->vm_end && remainder) {
@@ -1048,7 +2033,7 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
* each hugepage. We have to make * sure we get the
* first, for the page indexing below to work.
*/
- pte = huge_pte_offset(mm, vaddr & HPAGE_MASK);
+ pte = huge_pte_offset(mm, vaddr & huge_page_mask(h));
if (!pte || huge_pte_none(huge_ptep_get(pte)) ||
(write && !pte_write(huge_ptep_get(pte)))) {
@@ -1066,7 +2051,7 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
break;
}
- pfn_offset = (vaddr & ~HPAGE_MASK) >> PAGE_SHIFT;
+ pfn_offset = (vaddr & ~huge_page_mask(h)) >> PAGE_SHIFT;
page = pte_page(huge_ptep_get(pte));
same_page:
if (pages) {
@@ -1082,7 +2067,7 @@ same_page:
--remainder;
++i;
if (vaddr < vma->vm_end && remainder &&
- pfn_offset < HPAGE_SIZE/PAGE_SIZE) {
+ pfn_offset < pages_per_huge_page(h)) {
/*
* We use pfn_offset to avoid touching the pageframes
* of this compound page.
@@ -1104,13 +2089,14 @@ void hugetlb_change_protection(struct vm_area_struct *vma,
unsigned long start = address;
pte_t *ptep;
pte_t pte;
+ struct hstate *h = hstate_vma(vma);
BUG_ON(address >= end);
flush_cache_range(vma, address, end);
spin_lock(&vma->vm_file->f_mapping->i_mmap_lock);
spin_lock(&mm->page_table_lock);
- for (; address < end; address += HPAGE_SIZE) {
+ for (; address < end; address += huge_page_size(h)) {
ptep = huge_pte_offset(mm, address);
if (!ptep)
continue;
@@ -1128,195 +2114,59 @@ void hugetlb_change_protection(struct vm_area_struct *vma,
flush_tlb_range(vma, start, end);
}
-struct file_region {
- struct list_head link;
- long from;
- long to;
-};
-
-static long region_add(struct list_head *head, long f, long t)
-{
- struct file_region *rg, *nrg, *trg;
-
- /* Locate the region we are either in or before. */
- list_for_each_entry(rg, head, link)
- if (f <= rg->to)
- break;
-
- /* Round our left edge to the current segment if it encloses us. */
- if (f > rg->from)
- f = rg->from;
-
- /* Check for and consume any regions we now overlap with. */
- nrg = rg;
- list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
- if (&rg->link == head)
- break;
- if (rg->from > t)
- break;
-
- /* If this area reaches higher then extend our area to
- * include it completely. If this is not the first area
- * which we intend to reuse, free it. */
- if (rg->to > t)
- t = rg->to;
- if (rg != nrg) {
- list_del(&rg->link);
- kfree(rg);
- }
- }
- nrg->from = f;
- nrg->to = t;
- return 0;
-}
-
-static long region_chg(struct list_head *head, long f, long t)
-{
- struct file_region *rg, *nrg;
- long chg = 0;
-
- /* Locate the region we are before or in. */
- list_for_each_entry(rg, head, link)
- if (f <= rg->to)
- break;
-
- /* If we are below the current region then a new region is required.
- * Subtle, allocate a new region at the position but make it zero
- * size such that we can guarantee to record the reservation. */
- if (&rg->link == head || t < rg->from) {
- nrg = kmalloc(sizeof(*nrg), GFP_KERNEL);
- if (!nrg)
- return -ENOMEM;
- nrg->from = f;
- nrg->to = f;
- INIT_LIST_HEAD(&nrg->link);
- list_add(&nrg->link, rg->link.prev);
-
- return t - f;
- }
-
- /* Round our left edge to the current segment if it encloses us. */
- if (f > rg->from)
- f = rg->from;
- chg = t - f;
-
- /* Check for and consume any regions we now overlap with. */
- list_for_each_entry(rg, rg->link.prev, link) {
- if (&rg->link == head)
- break;
- if (rg->from > t)
- return chg;
-
- /* We overlap with this area, if it extends futher than
- * us then we must extend ourselves. Account for its
- * existing reservation. */
- if (rg->to > t) {
- chg += rg->to - t;
- t = rg->to;
- }
- chg -= rg->to - rg->from;
- }
- return chg;
-}
-
-static long region_truncate(struct list_head *head, long end)
+int hugetlb_reserve_pages(struct inode *inode,
+ long from, long to,
+ struct vm_area_struct *vma)
{
- struct file_region *rg, *trg;
- long chg = 0;
+ long ret, chg;
+ struct hstate *h = hstate_inode(inode);
- /* Locate the region we are either in or before. */
- list_for_each_entry(rg, head, link)
- if (end <= rg->to)
- break;
- if (&rg->link == head)
+ if (vma && vma->vm_flags & VM_NORESERVE)
return 0;
- /* If we are in the middle of a region then adjust it. */
- if (end > rg->from) {
- chg = rg->to - end;
- rg->to = end;
- rg = list_entry(rg->link.next, typeof(*rg), link);
- }
-
- /* Drop any remaining regions. */
- list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
- if (&rg->link == head)
- break;
- chg += rg->to - rg->from;
- list_del(&rg->link);
- kfree(rg);
- }
- return chg;
-}
-
-static int hugetlb_acct_memory(long delta)
-{
- int ret = -ENOMEM;
-
- spin_lock(&hugetlb_lock);
/*
- * When cpuset is configured, it breaks the strict hugetlb page
- * reservation as the accounting is done on a global variable. Such
- * reservation is completely rubbish in the presence of cpuset because
- * the reservation is not checked against page availability for the
- * current cpuset. Application can still potentially OOM'ed by kernel
- * with lack of free htlb page in cpuset that the task is in.
- * Attempt to enforce strict accounting with cpuset is almost
- * impossible (or too ugly) because cpuset is too fluid that
- * task or memory node can be dynamically moved between cpusets.
- *
- * The change of semantics for shared hugetlb mapping with cpuset is
- * undesirable. However, in order to preserve some of the semantics,
- * we fall back to check against current free page availability as
- * a best attempt and hopefully to minimize the impact of changing
- * semantics that cpuset has.
+ * Shared mappings base their reservation on the number of pages that
+ * are already allocated on behalf of the file. Private mappings need
+ * to reserve the full area even if read-only as mprotect() may be
+ * called to make the mapping read-write. Assume !vma is a shm mapping
*/
- if (delta > 0) {
- if (gather_surplus_pages(delta) < 0)
- goto out;
-
- if (delta > cpuset_mems_nr(free_huge_pages_node)) {
- return_unused_surplus_pages(delta);
- goto out;
- }
- }
-
- ret = 0;
- if (delta < 0)
- return_unused_surplus_pages((unsigned long) -delta);
+ if (!vma || vma->vm_flags & VM_SHARED)
+ chg = region_chg(&inode->i_mapping->private_list, from, to);
+ else {
+ struct resv_map *resv_map = resv_map_alloc();
+ if (!resv_map)
+ return -ENOMEM;
-out:
- spin_unlock(&hugetlb_lock);
- return ret;
-}
+ chg = to - from;
-int hugetlb_reserve_pages(struct inode *inode, long from, long to)
-{
- long ret, chg;
+ set_vma_resv_map(vma, resv_map);
+ set_vma_resv_flags(vma, HPAGE_RESV_OWNER);
+ }
- chg = region_chg(&inode->i_mapping->private_list, from, to);
if (chg < 0)
return chg;
if (hugetlb_get_quota(inode->i_mapping, chg))
return -ENOSPC;
- ret = hugetlb_acct_memory(chg);
+ ret = hugetlb_acct_memory(h, chg);
if (ret < 0) {
hugetlb_put_quota(inode->i_mapping, chg);
return ret;
}
- region_add(&inode->i_mapping->private_list, from, to);
+ if (!vma || vma->vm_flags & VM_SHARED)
+ region_add(&inode->i_mapping->private_list, from, to);
return 0;
}
void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed)
{
+ struct hstate *h = hstate_inode(inode);
long chg = region_truncate(&inode->i_mapping->private_list, offset);
spin_lock(&inode->i_lock);
- inode->i_blocks -= BLOCKS_PER_HUGEPAGE * freed;
+ inode->i_blocks -= blocks_per_huge_page(h);
spin_unlock(&inode->i_lock);
hugetlb_put_quota(inode->i_mapping, (chg - freed));
- hugetlb_acct_memory(-(chg - freed));
+ hugetlb_acct_memory(h, -(chg - freed));
}
diff --git a/mm/internal.h b/mm/internal.h
index 0034e947e4b..1f43f741697 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -13,6 +13,11 @@
#include <linux/mm.h>
+void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
+ unsigned long floor, unsigned long ceiling);
+
+extern void prep_compound_page(struct page *page, unsigned long order);
+
static inline void set_page_count(struct page *page, int v)
{
atomic_set(&page->_count, v);
@@ -59,4 +64,60 @@ static inline unsigned long page_order(struct page *page)
#define __paginginit __init
#endif
+/* Memory initialisation debug and verification */
+enum mminit_level {
+ MMINIT_WARNING,
+ MMINIT_VERIFY,
+ MMINIT_TRACE
+};
+
+#ifdef CONFIG_DEBUG_MEMORY_INIT
+
+extern int mminit_loglevel;
+
+#define mminit_dprintk(level, prefix, fmt, arg...) \
+do { \
+ if (level < mminit_loglevel) { \
+ printk(level <= MMINIT_WARNING ? KERN_WARNING : KERN_DEBUG); \
+ printk(KERN_CONT "mminit::" prefix " " fmt, ##arg); \
+ } \
+} while (0)
+
+extern void mminit_verify_pageflags_layout(void);
+extern void mminit_verify_page_links(struct page *page,
+ enum zone_type zone, unsigned long nid, unsigned long pfn);
+extern void mminit_verify_zonelist(void);
+
+#else
+
+static inline void mminit_dprintk(enum mminit_level level,
+ const char *prefix, const char *fmt, ...)
+{
+}
+
+static inline void mminit_verify_pageflags_layout(void)
+{
+}
+
+static inline void mminit_verify_page_links(struct page *page,
+ enum zone_type zone, unsigned long nid, unsigned long pfn)
+{
+}
+
+static inline void mminit_verify_zonelist(void)
+{
+}
+#endif /* CONFIG_DEBUG_MEMORY_INIT */
+
+/* mminit_validate_memmodel_limits is independent of CONFIG_DEBUG_MEMORY_INIT */
+#if defined(CONFIG_SPARSEMEM)
+extern void mminit_validate_memmodel_limits(unsigned long *start_pfn,
+ unsigned long *end_pfn);
+#else
+static inline void mminit_validate_memmodel_limits(unsigned long *start_pfn,
+ unsigned long *end_pfn)
+{
+}
+#endif /* CONFIG_SPARSEMEM */
+
#endif
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index e46451e1d9b..fba566c5132 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -35,9 +35,9 @@
#include <asm/uaccess.h>
-struct cgroup_subsys mem_cgroup_subsys;
-static const int MEM_CGROUP_RECLAIM_RETRIES = 5;
-static struct kmem_cache *page_cgroup_cache;
+struct cgroup_subsys mem_cgroup_subsys __read_mostly;
+static struct kmem_cache *page_cgroup_cache __read_mostly;
+#define MEM_CGROUP_RECLAIM_RETRIES 5
/*
* Statistics for memory cgroup.
@@ -166,7 +166,6 @@ struct page_cgroup {
struct list_head lru; /* per cgroup LRU list */
struct page *page;
struct mem_cgroup *mem_cgroup;
- int ref_cnt; /* cached, mapped, migrating */
int flags;
};
#define PAGE_CGROUP_FLAG_CACHE (0x1) /* charged as cache */
@@ -185,6 +184,7 @@ static enum zone_type page_cgroup_zid(struct page_cgroup *pc)
enum charge_type {
MEM_CGROUP_CHARGE_TYPE_CACHE = 0,
MEM_CGROUP_CHARGE_TYPE_MAPPED,
+ MEM_CGROUP_CHARGE_TYPE_FORCE, /* used by force_empty */
};
/*
@@ -296,7 +296,7 @@ static void __mem_cgroup_remove_list(struct mem_cgroup_per_zone *mz,
MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_INACTIVE) -= 1;
mem_cgroup_charge_statistics(pc->mem_cgroup, pc->flags, false);
- list_del_init(&pc->lru);
+ list_del(&pc->lru);
}
static void __mem_cgroup_add_list(struct mem_cgroup_per_zone *mz,
@@ -354,6 +354,9 @@ void mem_cgroup_move_lists(struct page *page, bool active)
struct mem_cgroup_per_zone *mz;
unsigned long flags;
+ if (mem_cgroup_subsys.disabled)
+ return;
+
/*
* We cannot lock_page_cgroup while holding zone's lru_lock,
* because other holders of lock_page_cgroup can be interrupted
@@ -524,7 +527,8 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
* < 0 if the cgroup is over its limit
*/
static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
- gfp_t gfp_mask, enum charge_type ctype)
+ gfp_t gfp_mask, enum charge_type ctype,
+ struct mem_cgroup *memcg)
{
struct mem_cgroup *mem;
struct page_cgroup *pc;
@@ -532,35 +536,8 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
unsigned long nr_retries = MEM_CGROUP_RECLAIM_RETRIES;
struct mem_cgroup_per_zone *mz;
- if (mem_cgroup_subsys.disabled)
- return 0;
-
- /*
- * Should page_cgroup's go to their own slab?
- * One could optimize the performance of the charging routine
- * by saving a bit in the page_flags and using it as a lock
- * to see if the cgroup page already has a page_cgroup associated
- * with it
- */
-retry:
- lock_page_cgroup(page);
- pc = page_get_page_cgroup(page);
- /*
- * The page_cgroup exists and
- * the page has already been accounted.
- */
- if (pc) {
- VM_BUG_ON(pc->page != page);
- VM_BUG_ON(pc->ref_cnt <= 0);
-
- pc->ref_cnt++;
- unlock_page_cgroup(page);
- goto done;
- }
- unlock_page_cgroup(page);
-
- pc = kmem_cache_zalloc(page_cgroup_cache, gfp_mask);
- if (pc == NULL)
+ pc = kmem_cache_alloc(page_cgroup_cache, gfp_mask);
+ if (unlikely(pc == NULL))
goto err;
/*
@@ -569,16 +546,18 @@ retry:
* thread group leader migrates. It's possible that mm is not
* set, if so charge the init_mm (happens for pagecache usage).
*/
- if (!mm)
- mm = &init_mm;
-
- rcu_read_lock();
- mem = mem_cgroup_from_task(rcu_dereference(mm->owner));
- /*
- * For every charge from the cgroup, increment reference count
- */
- css_get(&mem->css);
- rcu_read_unlock();
+ if (likely(!memcg)) {
+ rcu_read_lock();
+ mem = mem_cgroup_from_task(rcu_dereference(mm->owner));
+ /*
+ * For every charge from the cgroup, increment reference count
+ */
+ css_get(&mem->css);
+ rcu_read_unlock();
+ } else {
+ mem = memcg;
+ css_get(&memcg->css);
+ }
while (res_counter_charge(&mem->res, PAGE_SIZE)) {
if (!(gfp_mask & __GFP_WAIT))
@@ -603,25 +582,24 @@ retry:
}
}
- pc->ref_cnt = 1;
pc->mem_cgroup = mem;
pc->page = page;
- pc->flags = PAGE_CGROUP_FLAG_ACTIVE;
+ /*
+ * If a page is accounted as a page cache, insert to inactive list.
+ * If anon, insert to active list.
+ */
if (ctype == MEM_CGROUP_CHARGE_TYPE_CACHE)
pc->flags = PAGE_CGROUP_FLAG_CACHE;
+ else
+ pc->flags = PAGE_CGROUP_FLAG_ACTIVE;
lock_page_cgroup(page);
- if (page_get_page_cgroup(page)) {
+ if (unlikely(page_get_page_cgroup(page))) {
unlock_page_cgroup(page);
- /*
- * Another charge has been added to this page already.
- * We take lock_page_cgroup(page) again and read
- * page->cgroup, increment refcnt.... just retry is OK.
- */
res_counter_uncharge(&mem->res, PAGE_SIZE);
css_put(&mem->css);
kmem_cache_free(page_cgroup_cache, pc);
- goto retry;
+ goto done;
}
page_assign_page_cgroup(page, pc);
@@ -642,24 +620,65 @@ err:
int mem_cgroup_charge(struct page *page, struct mm_struct *mm, gfp_t gfp_mask)
{
+ if (mem_cgroup_subsys.disabled)
+ return 0;
+
+ /*
+ * If already mapped, we don't have to account.
+ * If page cache, page->mapping has address_space.
+ * But page->mapping may have out-of-use anon_vma pointer,
+ * detecit it by PageAnon() check. newly-mapped-anon's page->mapping
+ * is NULL.
+ */
+ if (page_mapped(page) || (page->mapping && !PageAnon(page)))
+ return 0;
+ if (unlikely(!mm))
+ mm = &init_mm;
return mem_cgroup_charge_common(page, mm, gfp_mask,
- MEM_CGROUP_CHARGE_TYPE_MAPPED);
+ MEM_CGROUP_CHARGE_TYPE_MAPPED, NULL);
}
int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
gfp_t gfp_mask)
{
- if (!mm)
+ if (mem_cgroup_subsys.disabled)
+ return 0;
+
+ /*
+ * Corner case handling. This is called from add_to_page_cache()
+ * in usual. But some FS (shmem) precharges this page before calling it
+ * and call add_to_page_cache() with GFP_NOWAIT.
+ *
+ * For GFP_NOWAIT case, the page may be pre-charged before calling
+ * add_to_page_cache(). (See shmem.c) check it here and avoid to call
+ * charge twice. (It works but has to pay a bit larger cost.)
+ */
+ if (!(gfp_mask & __GFP_WAIT)) {
+ struct page_cgroup *pc;
+
+ lock_page_cgroup(page);
+ pc = page_get_page_cgroup(page);
+ if (pc) {
+ VM_BUG_ON(pc->page != page);
+ VM_BUG_ON(!pc->mem_cgroup);
+ unlock_page_cgroup(page);
+ return 0;
+ }
+ unlock_page_cgroup(page);
+ }
+
+ if (unlikely(!mm))
mm = &init_mm;
+
return mem_cgroup_charge_common(page, mm, gfp_mask,
- MEM_CGROUP_CHARGE_TYPE_CACHE);
+ MEM_CGROUP_CHARGE_TYPE_CACHE, NULL);
}
/*
- * Uncharging is always a welcome operation, we never complain, simply
- * uncharge.
+ * uncharge if !page_mapped(page)
*/
-void mem_cgroup_uncharge_page(struct page *page)
+static void
+__mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
{
struct page_cgroup *pc;
struct mem_cgroup *mem;
@@ -674,98 +693,151 @@ void mem_cgroup_uncharge_page(struct page *page)
*/
lock_page_cgroup(page);
pc = page_get_page_cgroup(page);
- if (!pc)
+ if (unlikely(!pc))
goto unlock;
VM_BUG_ON(pc->page != page);
- VM_BUG_ON(pc->ref_cnt <= 0);
- if (--(pc->ref_cnt) == 0) {
- mz = page_cgroup_zoneinfo(pc);
- spin_lock_irqsave(&mz->lru_lock, flags);
- __mem_cgroup_remove_list(mz, pc);
- spin_unlock_irqrestore(&mz->lru_lock, flags);
+ if ((ctype == MEM_CGROUP_CHARGE_TYPE_MAPPED)
+ && ((pc->flags & PAGE_CGROUP_FLAG_CACHE)
+ || page_mapped(page)))
+ goto unlock;
- page_assign_page_cgroup(page, NULL);
- unlock_page_cgroup(page);
+ mz = page_cgroup_zoneinfo(pc);
+ spin_lock_irqsave(&mz->lru_lock, flags);
+ __mem_cgroup_remove_list(mz, pc);
+ spin_unlock_irqrestore(&mz->lru_lock, flags);
- mem = pc->mem_cgroup;
- res_counter_uncharge(&mem->res, PAGE_SIZE);
- css_put(&mem->css);
+ page_assign_page_cgroup(page, NULL);
+ unlock_page_cgroup(page);
- kmem_cache_free(page_cgroup_cache, pc);
- return;
- }
+ mem = pc->mem_cgroup;
+ res_counter_uncharge(&mem->res, PAGE_SIZE);
+ css_put(&mem->css);
+ kmem_cache_free(page_cgroup_cache, pc);
+ return;
unlock:
unlock_page_cgroup(page);
}
+void mem_cgroup_uncharge_page(struct page *page)
+{
+ __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_MAPPED);
+}
+
+void mem_cgroup_uncharge_cache_page(struct page *page)
+{
+ VM_BUG_ON(page_mapped(page));
+ __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE);
+}
+
/*
- * Returns non-zero if a page (under migration) has valid page_cgroup member.
- * Refcnt of page_cgroup is incremented.
+ * Before starting migration, account against new page.
*/
-int mem_cgroup_prepare_migration(struct page *page)
+int mem_cgroup_prepare_migration(struct page *page, struct page *newpage)
{
struct page_cgroup *pc;
+ struct mem_cgroup *mem = NULL;
+ enum charge_type ctype = MEM_CGROUP_CHARGE_TYPE_MAPPED;
+ int ret = 0;
if (mem_cgroup_subsys.disabled)
return 0;
lock_page_cgroup(page);
pc = page_get_page_cgroup(page);
- if (pc)
- pc->ref_cnt++;
+ if (pc) {
+ mem = pc->mem_cgroup;
+ css_get(&mem->css);
+ if (pc->flags & PAGE_CGROUP_FLAG_CACHE)
+ ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
+ }
unlock_page_cgroup(page);
- return pc != NULL;
+ if (mem) {
+ ret = mem_cgroup_charge_common(newpage, NULL, GFP_KERNEL,
+ ctype, mem);
+ css_put(&mem->css);
+ }
+ return ret;
}
-void mem_cgroup_end_migration(struct page *page)
+/* remove redundant charge if migration failed*/
+void mem_cgroup_end_migration(struct page *newpage)
{
- mem_cgroup_uncharge_page(page);
+ /*
+ * At success, page->mapping is not NULL.
+ * special rollback care is necessary when
+ * 1. at migration failure. (newpage->mapping is cleared in this case)
+ * 2. the newpage was moved but not remapped again because the task
+ * exits and the newpage is obsolete. In this case, the new page
+ * may be a swapcache. So, we just call mem_cgroup_uncharge_page()
+ * always for avoiding mess. The page_cgroup will be removed if
+ * unnecessary. File cache pages is still on radix-tree. Don't
+ * care it.
+ */
+ if (!newpage->mapping)
+ __mem_cgroup_uncharge_common(newpage,
+ MEM_CGROUP_CHARGE_TYPE_FORCE);
+ else if (PageAnon(newpage))
+ mem_cgroup_uncharge_page(newpage);
}
/*
- * We know both *page* and *newpage* are now not-on-LRU and PG_locked.
- * And no race with uncharge() routines because page_cgroup for *page*
- * has extra one reference by mem_cgroup_prepare_migration.
+ * A call to try to shrink memory usage under specified resource controller.
+ * This is typically used for page reclaiming for shmem for reducing side
+ * effect of page allocation from shmem, which is used by some mem_cgroup.
*/
-void mem_cgroup_page_migration(struct page *page, struct page *newpage)
+int mem_cgroup_shrink_usage(struct mm_struct *mm, gfp_t gfp_mask)
{
- struct page_cgroup *pc;
- struct mem_cgroup_per_zone *mz;
- unsigned long flags;
+ struct mem_cgroup *mem;
+ int progress = 0;
+ int retry = MEM_CGROUP_RECLAIM_RETRIES;
- lock_page_cgroup(page);
- pc = page_get_page_cgroup(page);
- if (!pc) {
- unlock_page_cgroup(page);
- return;
- }
+ if (mem_cgroup_subsys.disabled)
+ return 0;
- mz = page_cgroup_zoneinfo(pc);
- spin_lock_irqsave(&mz->lru_lock, flags);
- __mem_cgroup_remove_list(mz, pc);
- spin_unlock_irqrestore(&mz->lru_lock, flags);
+ rcu_read_lock();
+ mem = mem_cgroup_from_task(rcu_dereference(mm->owner));
+ css_get(&mem->css);
+ rcu_read_unlock();
- page_assign_page_cgroup(page, NULL);
- unlock_page_cgroup(page);
+ do {
+ progress = try_to_free_mem_cgroup_pages(mem, gfp_mask);
+ } while (!progress && --retry);
- pc->page = newpage;
- lock_page_cgroup(newpage);
- page_assign_page_cgroup(newpage, pc);
+ css_put(&mem->css);
+ if (!retry)
+ return -ENOMEM;
+ return 0;
+}
- mz = page_cgroup_zoneinfo(pc);
- spin_lock_irqsave(&mz->lru_lock, flags);
- __mem_cgroup_add_list(mz, pc);
- spin_unlock_irqrestore(&mz->lru_lock, flags);
+int mem_cgroup_resize_limit(struct mem_cgroup *memcg, unsigned long long val)
+{
+
+ int retry_count = MEM_CGROUP_RECLAIM_RETRIES;
+ int progress;
+ int ret = 0;
- unlock_page_cgroup(newpage);
+ while (res_counter_set_limit(&memcg->res, val)) {
+ if (signal_pending(current)) {
+ ret = -EINTR;
+ break;
+ }
+ if (!retry_count) {
+ ret = -EBUSY;
+ break;
+ }
+ progress = try_to_free_mem_cgroup_pages(memcg, GFP_KERNEL);
+ if (!progress)
+ retry_count--;
+ }
+ return ret;
}
+
/*
* This routine traverse page_cgroup in given list and drop them all.
- * This routine ignores page_cgroup->ref_cnt.
* *And* this routine doesn't reclaim page itself, just removes page_cgroup.
*/
#define FORCE_UNCHARGE_BATCH (128)
@@ -790,12 +862,20 @@ static void mem_cgroup_force_empty_list(struct mem_cgroup *mem,
page = pc->page;
get_page(page);
spin_unlock_irqrestore(&mz->lru_lock, flags);
- mem_cgroup_uncharge_page(page);
- put_page(page);
- if (--count <= 0) {
- count = FORCE_UNCHARGE_BATCH;
+ /*
+ * Check if this page is on LRU. !LRU page can be found
+ * if it's under page migration.
+ */
+ if (PageLRU(page)) {
+ __mem_cgroup_uncharge_common(page,
+ MEM_CGROUP_CHARGE_TYPE_FORCE);
+ put_page(page);
+ if (--count <= 0) {
+ count = FORCE_UNCHARGE_BATCH;
+ cond_resched();
+ }
+ } else
cond_resched();
- }
spin_lock_irqsave(&mz->lru_lock, flags);
}
spin_unlock_irqrestore(&mz->lru_lock, flags);
@@ -810,9 +890,6 @@ static int mem_cgroup_force_empty(struct mem_cgroup *mem)
int ret = -EBUSY;
int node, zid;
- if (mem_cgroup_subsys.disabled)
- return 0;
-
css_get(&mem->css);
/*
* page reclaim code (kswapd etc..) will move pages between
@@ -838,32 +915,34 @@ out:
return ret;
}
-static int mem_cgroup_write_strategy(char *buf, unsigned long long *tmp)
-{
- *tmp = memparse(buf, &buf);
- if (*buf != '\0')
- return -EINVAL;
-
- /*
- * Round up the value to the closest page size
- */
- *tmp = ((*tmp + PAGE_SIZE - 1) >> PAGE_SHIFT) << PAGE_SHIFT;
- return 0;
-}
-
static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft)
{
return res_counter_read_u64(&mem_cgroup_from_cont(cont)->res,
cft->private);
}
-
-static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
- struct file *file, const char __user *userbuf,
- size_t nbytes, loff_t *ppos)
+/*
+ * The user of this function is...
+ * RES_LIMIT.
+ */
+static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
+ const char *buffer)
{
- return res_counter_write(&mem_cgroup_from_cont(cont)->res,
- cft->private, userbuf, nbytes, ppos,
- mem_cgroup_write_strategy);
+ struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
+ unsigned long long val;
+ int ret;
+
+ switch (cft->private) {
+ case RES_LIMIT:
+ /* This function does all necessary parse...reuse it */
+ ret = res_counter_memparse_write_strategy(buffer, &val);
+ if (!ret)
+ ret = mem_cgroup_resize_limit(memcg, val);
+ break;
+ default:
+ ret = -EINVAL; /* should be BUG() ? */
+ break;
+ }
+ return ret;
}
static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
@@ -940,7 +1019,7 @@ static struct cftype mem_cgroup_files[] = {
{
.name = "limit_in_bytes",
.private = RES_LIMIT,
- .write = mem_cgroup_write,
+ .write_string = mem_cgroup_write,
.read_u64 = mem_cgroup_read,
},
{
@@ -1070,8 +1149,6 @@ static void mem_cgroup_destroy(struct cgroup_subsys *ss,
static int mem_cgroup_populate(struct cgroup_subsys *ss,
struct cgroup *cont)
{
- if (mem_cgroup_subsys.disabled)
- return 0;
return cgroup_add_files(cont, ss, mem_cgroup_files,
ARRAY_SIZE(mem_cgroup_files));
}
@@ -1084,9 +1161,6 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss,
struct mm_struct *mm;
struct mem_cgroup *mem, *old_mem;
- if (mem_cgroup_subsys.disabled)
- return;
-
mm = get_task_mm(p);
if (mm == NULL)
return;
diff --git a/mm/memory.c b/mm/memory.c
index 2302d228fe0..262e3eb6601 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -61,6 +61,8 @@
#include <linux/swapops.h>
#include <linux/elf.h>
+#include "internal.h"
+
#ifndef CONFIG_NEED_MULTIPLE_NODES
/* use the per-pgdat data instead for discontigmem - mbligh */
unsigned long max_mapnr;
@@ -211,7 +213,7 @@ static inline void free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
*
* Must be called with pagetable lock held.
*/
-void free_pgd_range(struct mmu_gather **tlb,
+void free_pgd_range(struct mmu_gather *tlb,
unsigned long addr, unsigned long end,
unsigned long floor, unsigned long ceiling)
{
@@ -262,16 +264,16 @@ void free_pgd_range(struct mmu_gather **tlb,
return;
start = addr;
- pgd = pgd_offset((*tlb)->mm, addr);
+ pgd = pgd_offset(tlb->mm, addr);
do {
next = pgd_addr_end(addr, end);
if (pgd_none_or_clear_bad(pgd))
continue;
- free_pud_range(*tlb, pgd, addr, next, floor, ceiling);
+ free_pud_range(tlb, pgd, addr, next, floor, ceiling);
} while (pgd++, addr = next, addr != end);
}
-void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *vma,
+void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *vma,
unsigned long floor, unsigned long ceiling)
{
while (vma) {
@@ -899,9 +901,23 @@ unsigned long unmap_vmas(struct mmu_gather **tlbp,
}
if (unlikely(is_vm_hugetlb_page(vma))) {
- unmap_hugepage_range(vma, start, end);
- zap_work -= (end - start) /
- (HPAGE_SIZE / PAGE_SIZE);
+ /*
+ * It is undesirable to test vma->vm_file as it
+ * should be non-null for valid hugetlb area.
+ * However, vm_file will be NULL in the error
+ * cleanup path of do_mmap_pgoff. When
+ * hugetlbfs ->mmap method fails,
+ * do_mmap_pgoff() nullifies vma->vm_file
+ * before calling this function to clean up.
+ * Since no pte has actually been setup, it is
+ * safe to do nothing in this case.
+ */
+ if (vma->vm_file) {
+ unmap_hugepage_range(vma, start, end, NULL);
+ zap_work -= (end - start) /
+ pages_per_huge_page(hstate_vma(vma));
+ }
+
start = end;
} else
start = unmap_page_range(*tlbp, vma,
@@ -982,19 +998,24 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
goto no_page_table;
pud = pud_offset(pgd, address);
- if (pud_none(*pud) || unlikely(pud_bad(*pud)))
+ if (pud_none(*pud))
goto no_page_table;
-
+ if (pud_huge(*pud)) {
+ BUG_ON(flags & FOLL_GET);
+ page = follow_huge_pud(mm, address, pud, flags & FOLL_WRITE);
+ goto out;
+ }
+ if (unlikely(pud_bad(*pud)))
+ goto no_page_table;
+
pmd = pmd_offset(pud, address);
if (pmd_none(*pmd))
goto no_page_table;
-
if (pmd_huge(*pmd)) {
BUG_ON(flags & FOLL_GET);
page = follow_huge_pmd(mm, address, pmd, flags & FOLL_WRITE);
goto out;
}
-
if (unlikely(pmd_bad(*pmd)))
goto no_page_table;
@@ -1058,11 +1079,9 @@ static inline int use_zero_page(struct vm_area_struct *vma)
if (vma->vm_flags & (VM_LOCKED | VM_SHARED))
return 0;
/*
- * And if we have a fault or a nopfn routine, it's not an
- * anonymous region.
+ * And if we have a fault routine, it's not an anonymous region.
*/
- return !vma->vm_ops ||
- (!vma->vm_ops->fault && !vma->vm_ops->nopfn);
+ return !vma->vm_ops || !vma->vm_ops->fault;
}
int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
@@ -1338,6 +1357,11 @@ out:
*
* This function should only be called from a vm_ops->fault handler, and
* in that case the handler should return NULL.
+ *
+ * vma cannot be a COW mapping.
+ *
+ * As this is called only for pages that do not currently exist, we
+ * do not need to flush old virtual caches or the TLB.
*/
int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
unsigned long pfn)
@@ -1548,6 +1572,8 @@ static int apply_to_pmd_range(struct mm_struct *mm, pud_t *pud,
unsigned long next;
int err;
+ BUG_ON(pud_huge(*pud));
+
pmd = pmd_alloc(mm, pud, addr);
if (!pmd)
return -ENOMEM;
@@ -2501,59 +2527,6 @@ static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte);
}
-
-/*
- * do_no_pfn() tries to create a new page mapping for a page without
- * a struct_page backing it
- *
- * As this is called only for pages that do not currently exist, we
- * do not need to flush old virtual caches or the TLB.
- *
- * We enter with non-exclusive mmap_sem (to exclude vma changes,
- * but allow concurrent faults), and pte mapped but not yet locked.
- * We return with mmap_sem still held, but pte unmapped and unlocked.
- *
- * It is expected that the ->nopfn handler always returns the same pfn
- * for a given virtual mapping.
- *
- * Mark this `noinline' to prevent it from bloating the main pagefault code.
- */
-static noinline int do_no_pfn(struct mm_struct *mm, struct vm_area_struct *vma,
- unsigned long address, pte_t *page_table, pmd_t *pmd,
- int write_access)
-{
- spinlock_t *ptl;
- pte_t entry;
- unsigned long pfn;
-
- pte_unmap(page_table);
- BUG_ON(!(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)));
- BUG_ON((vma->vm_flags & VM_PFNMAP) && is_cow_mapping(vma->vm_flags));
-
- pfn = vma->vm_ops->nopfn(vma, address & PAGE_MASK);
-
- BUG_ON((vma->vm_flags & VM_MIXEDMAP) && pfn_valid(pfn));
-
- if (unlikely(pfn == NOPFN_OOM))
- return VM_FAULT_OOM;
- else if (unlikely(pfn == NOPFN_SIGBUS))
- return VM_FAULT_SIGBUS;
- else if (unlikely(pfn == NOPFN_REFAULT))
- return 0;
-
- page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
-
- /* Only go through if we didn't race with anybody else... */
- if (pte_none(*page_table)) {
- entry = pfn_pte(pfn, vma->vm_page_prot);
- if (write_access)
- entry = maybe_mkwrite(pte_mkdirty(entry), vma);
- set_pte_at(mm, address, page_table, entry);
- }
- pte_unmap_unlock(page_table, ptl);
- return 0;
-}
-
/*
* Fault of a previously existing named mapping. Repopulate the pte
* from the encoded file_pte if possible. This enables swappable
@@ -2614,9 +2587,6 @@ static inline int handle_pte_fault(struct mm_struct *mm,
if (likely(vma->vm_ops->fault))
return do_linear_fault(mm, vma, address,
pte, pmd, write_access, entry);
- if (unlikely(vma->vm_ops->nopfn))
- return do_no_pfn(mm, vma, address, pte,
- pmd, write_access);
}
return do_anonymous_page(mm, vma, address,
pte, pmd, write_access);
@@ -2804,6 +2774,86 @@ int in_gate_area_no_task(unsigned long addr)
#endif /* __HAVE_ARCH_GATE_AREA */
+#ifdef CONFIG_HAVE_IOREMAP_PROT
+static resource_size_t follow_phys(struct vm_area_struct *vma,
+ unsigned long address, unsigned int flags,
+ unsigned long *prot)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *ptep, pte;
+ spinlock_t *ptl;
+ resource_size_t phys_addr = 0;
+ struct mm_struct *mm = vma->vm_mm;
+
+ VM_BUG_ON(!(vma->vm_flags & (VM_IO | VM_PFNMAP)));
+
+ pgd = pgd_offset(mm, address);
+ if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
+ goto no_page_table;
+
+ pud = pud_offset(pgd, address);
+ if (pud_none(*pud) || unlikely(pud_bad(*pud)))
+ goto no_page_table;
+
+ pmd = pmd_offset(pud, address);
+ if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
+ goto no_page_table;
+
+ /* We cannot handle huge page PFN maps. Luckily they don't exist. */
+ if (pmd_huge(*pmd))
+ goto no_page_table;
+
+ ptep = pte_offset_map_lock(mm, pmd, address, &ptl);
+ if (!ptep)
+ goto out;
+
+ pte = *ptep;
+ if (!pte_present(pte))
+ goto unlock;
+ if ((flags & FOLL_WRITE) && !pte_write(pte))
+ goto unlock;
+ phys_addr = pte_pfn(pte);
+ phys_addr <<= PAGE_SHIFT; /* Shift here to avoid overflow on PAE */
+
+ *prot = pgprot_val(pte_pgprot(pte));
+
+unlock:
+ pte_unmap_unlock(ptep, ptl);
+out:
+ return phys_addr;
+no_page_table:
+ return 0;
+}
+
+int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
+ void *buf, int len, int write)
+{
+ resource_size_t phys_addr;
+ unsigned long prot = 0;
+ void *maddr;
+ int offset = addr & (PAGE_SIZE-1);
+
+ if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
+ return -EINVAL;
+
+ phys_addr = follow_phys(vma, addr, write, &prot);
+
+ if (!phys_addr)
+ return -EINVAL;
+
+ maddr = ioremap_prot(phys_addr, PAGE_SIZE, prot);
+ if (write)
+ memcpy_toio(maddr + offset, buf, len);
+ else
+ memcpy_fromio(buf, maddr + offset, len);
+ iounmap(maddr);
+
+ return len;
+}
+#endif
+
/*
* Access another process' address space.
* Source/target buffer must be kernel space,
@@ -2813,7 +2863,6 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
{
struct mm_struct *mm;
struct vm_area_struct *vma;
- struct page *page;
void *old_buf = buf;
mm = get_task_mm(tsk);
@@ -2825,28 +2874,44 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
while (len) {
int bytes, ret, offset;
void *maddr;
+ struct page *page = NULL;
ret = get_user_pages(tsk, mm, addr, 1,
write, 1, &page, &vma);
- if (ret <= 0)
- break;
-
- bytes = len;
- offset = addr & (PAGE_SIZE-1);
- if (bytes > PAGE_SIZE-offset)
- bytes = PAGE_SIZE-offset;
-
- maddr = kmap(page);
- if (write) {
- copy_to_user_page(vma, page, addr,
- maddr + offset, buf, bytes);
- set_page_dirty_lock(page);
+ if (ret <= 0) {
+ /*
+ * Check if this is a VM_IO | VM_PFNMAP VMA, which
+ * we can access using slightly different code.
+ */
+#ifdef CONFIG_HAVE_IOREMAP_PROT
+ vma = find_vma(mm, addr);
+ if (!vma)
+ break;
+ if (vma->vm_ops && vma->vm_ops->access)
+ ret = vma->vm_ops->access(vma, addr, buf,
+ len, write);
+ if (ret <= 0)
+#endif
+ break;
+ bytes = ret;
} else {
- copy_from_user_page(vma, page, addr,
- buf, maddr + offset, bytes);
+ bytes = len;
+ offset = addr & (PAGE_SIZE-1);
+ if (bytes > PAGE_SIZE-offset)
+ bytes = PAGE_SIZE-offset;
+
+ maddr = kmap(page);
+ if (write) {
+ copy_to_user_page(vma, page, addr,
+ maddr + offset, buf, bytes);
+ set_page_dirty_lock(page);
+ } else {
+ copy_from_user_page(vma, page, addr,
+ buf, maddr + offset, bytes);
+ }
+ kunmap(page);
+ page_cache_release(page);
}
- kunmap(page);
- page_cache_release(page);
len -= bytes;
buf += bytes;
addr += bytes;
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 833f854eabe..89fee2dcb03 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -62,9 +62,9 @@ static void release_memory_resource(struct resource *res)
#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
#ifndef CONFIG_SPARSEMEM_VMEMMAP
-static void get_page_bootmem(unsigned long info, struct page *page, int magic)
+static void get_page_bootmem(unsigned long info, struct page *page, int type)
{
- atomic_set(&page->_mapcount, magic);
+ atomic_set(&page->_mapcount, type);
SetPagePrivate(page);
set_page_private(page, info);
atomic_inc(&page->_count);
@@ -72,10 +72,10 @@ static void get_page_bootmem(unsigned long info, struct page *page, int magic)
void put_page_bootmem(struct page *page)
{
- int magic;
+ int type;
- magic = atomic_read(&page->_mapcount);
- BUG_ON(magic >= -1);
+ type = atomic_read(&page->_mapcount);
+ BUG_ON(type >= -1);
if (atomic_dec_return(&page->_count) == 1) {
ClearPagePrivate(page);
@@ -86,7 +86,7 @@ void put_page_bootmem(struct page *page)
}
-void register_page_bootmem_info_section(unsigned long start_pfn)
+static void register_page_bootmem_info_section(unsigned long start_pfn)
{
unsigned long *usemap, mapsize, section_nr, i;
struct mem_section *ms;
@@ -119,7 +119,7 @@ void register_page_bootmem_info_section(unsigned long start_pfn)
mapsize = PAGE_ALIGN(usemap_size()) >> PAGE_SHIFT;
for (i = 0; i < mapsize; i++, page++)
- get_page_bootmem(section_nr, page, MIX_INFO);
+ get_page_bootmem(section_nr, page, MIX_SECTION_INFO);
}
@@ -429,7 +429,9 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
if (need_zonelists_rebuild)
build_all_zonelists();
- vm_total_pages = nr_free_pagecache_pages();
+ else
+ vm_total_pages = nr_free_pagecache_pages();
+
writeback_set_ratelimit();
if (onlined_pages)
@@ -455,7 +457,7 @@ static pg_data_t *hotadd_new_pgdat(int nid, u64 start)
/* we can use NODE_DATA(nid) from here */
/* init node's zones as empty zones, we don't have any present pages.*/
- free_area_init_node(nid, pgdat, zones_size, start_pfn, zholes_size);
+ free_area_init_node(nid, zones_size, start_pfn, zholes_size);
return pgdat;
}
@@ -521,6 +523,66 @@ EXPORT_SYMBOL_GPL(add_memory);
#ifdef CONFIG_MEMORY_HOTREMOVE
/*
+ * A free page on the buddy free lists (not the per-cpu lists) has PageBuddy
+ * set and the size of the free page is given by page_order(). Using this,
+ * the function determines if the pageblock contains only free pages.
+ * Due to buddy contraints, a free page at least the size of a pageblock will
+ * be located at the start of the pageblock
+ */
+static inline int pageblock_free(struct page *page)
+{
+ return PageBuddy(page) && page_order(page) >= pageblock_order;
+}
+
+/* Return the start of the next active pageblock after a given page */
+static struct page *next_active_pageblock(struct page *page)
+{
+ int pageblocks_stride;
+
+ /* Ensure the starting page is pageblock-aligned */
+ BUG_ON(page_to_pfn(page) & (pageblock_nr_pages - 1));
+
+ /* Move forward by at least 1 * pageblock_nr_pages */
+ pageblocks_stride = 1;
+
+ /* If the entire pageblock is free, move to the end of free page */
+ if (pageblock_free(page))
+ pageblocks_stride += page_order(page) - pageblock_order;
+
+ return page + (pageblocks_stride * pageblock_nr_pages);
+}
+
+/* Checks if this range of memory is likely to be hot-removable. */
+int is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages)
+{
+ int type;
+ struct page *page = pfn_to_page(start_pfn);
+ struct page *end_page = page + nr_pages;
+
+ /* Check the starting page of each pageblock within the range */
+ for (; page < end_page; page = next_active_pageblock(page)) {
+ type = get_pageblock_migratetype(page);
+
+ /*
+ * A pageblock containing MOVABLE or free pages is considered
+ * removable
+ */
+ if (type != MIGRATE_MOVABLE && !pageblock_free(page))
+ return 0;
+
+ /*
+ * A pageblock starting with a PageReserved page is not
+ * considered removable.
+ */
+ if (PageReserved(page))
+ return 0;
+ }
+
+ /* All pageblocks in the memory block are likely to be hot-removable */
+ return 1;
+}
+
+/*
* Confirm all pages in a range [start, end) is belongs to the same zone.
*/
static int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn)
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index c94e58b192c..e550bec2058 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1481,7 +1481,7 @@ struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr,
if (unlikely((*mpol)->mode == MPOL_INTERLEAVE)) {
zl = node_zonelist(interleave_nid(*mpol, vma, addr,
- HPAGE_SHIFT), gfp_flags);
+ huge_page_shift(hstate_vma(vma))), gfp_flags);
} else {
zl = policy_zonelist(gfp_flags, *mpol);
if ((*mpol)->mode == MPOL_BIND)
@@ -2220,9 +2220,12 @@ static void check_huge_range(struct vm_area_struct *vma,
{
unsigned long addr;
struct page *page;
+ struct hstate *h = hstate_vma(vma);
+ unsigned long sz = huge_page_size(h);
- for (addr = start; addr < end; addr += HPAGE_SIZE) {
- pte_t *ptep = huge_pte_offset(vma->vm_mm, addr & HPAGE_MASK);
+ for (addr = start; addr < end; addr += sz) {
+ pte_t *ptep = huge_pte_offset(vma->vm_mm,
+ addr & huge_page_mask(h));
pte_t pte;
if (!ptep)
diff --git a/mm/migrate.c b/mm/migrate.c
index 55bd355d170..d8c65a65c61 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -30,6 +30,7 @@
#include <linux/vmalloc.h>
#include <linux/security.h>
#include <linux/memcontrol.h>
+#include <linux/syscalls.h>
#include "internal.h"
@@ -357,6 +358,9 @@ static int migrate_page_move_mapping(struct address_space *mapping,
__inc_zone_page_state(newpage, NR_FILE_PAGES);
write_unlock_irq(&mapping->tree_lock);
+ if (!PageSwapCache(newpage)) {
+ mem_cgroup_uncharge_cache_page(page);
+ }
return 0;
}
@@ -610,7 +614,6 @@ static int move_to_new_page(struct page *newpage, struct page *page)
rc = fallback_migrate_page(mapping, newpage, page);
if (!rc) {
- mem_cgroup_page_migration(page, newpage);
remove_migration_ptes(page, newpage);
} else
newpage->mapping = NULL;
@@ -640,6 +643,14 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
/* page was freed from under us. So we are done. */
goto move_newpage;
+ charge = mem_cgroup_prepare_migration(page, newpage);
+ if (charge == -ENOMEM) {
+ rc = -ENOMEM;
+ goto move_newpage;
+ }
+ /* prepare cgroup just returns 0 or -ENOMEM */
+ BUG_ON(charge);
+
rc = -EAGAIN;
if (TestSetPageLocked(page)) {
if (!force)
@@ -691,19 +702,14 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
goto rcu_unlock;
}
- charge = mem_cgroup_prepare_migration(page);
/* Establish migration ptes or remove ptes */
try_to_unmap(page, 1);
if (!page_mapped(page))
rc = move_to_new_page(newpage, page);
- if (rc) {
+ if (rc)
remove_migration_ptes(page, page);
- if (charge)
- mem_cgroup_end_migration(page);
- } else if (charge)
- mem_cgroup_end_migration(newpage);
rcu_unlock:
if (rcu_locked)
rcu_read_unlock();
@@ -724,6 +730,8 @@ unlock:
}
move_newpage:
+ if (!charge)
+ mem_cgroup_end_migration(newpage);
/*
* Move the new page to the LRU. If migration was not successful
* then this will free the page.
@@ -1070,7 +1078,6 @@ out2:
mmput(mm);
return err;
}
-#endif
/*
* Call migration functions in the vma_ops that may prepare
@@ -1092,3 +1099,4 @@ int migrate_vmas(struct mm_struct *mm, const nodemask_t *to,
}
return err;
}
+#endif
diff --git a/mm/mm_init.c b/mm/mm_init.c
new file mode 100644
index 00000000000..c6af41ea999
--- /dev/null
+++ b/mm/mm_init.c
@@ -0,0 +1,152 @@
+/*
+ * mm_init.c - Memory initialisation verification and debugging
+ *
+ * Copyright 2008 IBM Corporation, 2008
+ * Author Mel Gorman <mel@csn.ul.ie>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
+#include "internal.h"
+
+#ifdef CONFIG_DEBUG_MEMORY_INIT
+int __meminitdata mminit_loglevel;
+
+/* The zonelists are simply reported, validation is manual. */
+void mminit_verify_zonelist(void)
+{
+ int nid;
+
+ if (mminit_loglevel < MMINIT_VERIFY)
+ return;
+
+ for_each_online_node(nid) {
+ pg_data_t *pgdat = NODE_DATA(nid);
+ struct zone *zone;
+ struct zoneref *z;
+ struct zonelist *zonelist;
+ int i, listid, zoneid;
+
+ BUG_ON(MAX_ZONELISTS > 2);
+ for (i = 0; i < MAX_ZONELISTS * MAX_NR_ZONES; i++) {
+
+ /* Identify the zone and nodelist */
+ zoneid = i % MAX_NR_ZONES;
+ listid = i / MAX_NR_ZONES;
+ zonelist = &pgdat->node_zonelists[listid];
+ zone = &pgdat->node_zones[zoneid];
+ if (!populated_zone(zone))
+ continue;
+
+ /* Print information about the zonelist */
+ printk(KERN_DEBUG "mminit::zonelist %s %d:%s = ",
+ listid > 0 ? "thisnode" : "general", nid,
+ zone->name);
+
+ /* Iterate the zonelist */
+ for_each_zone_zonelist(zone, z, zonelist, zoneid) {
+#ifdef CONFIG_NUMA
+ printk(KERN_CONT "%d:%s ",
+ zone->node, zone->name);
+#else
+ printk(KERN_CONT "0:%s ", zone->name);
+#endif /* CONFIG_NUMA */
+ }
+ printk(KERN_CONT "\n");
+ }
+ }
+}
+
+void __init mminit_verify_pageflags_layout(void)
+{
+ int shift, width;
+ unsigned long or_mask, add_mask;
+
+ shift = 8 * sizeof(unsigned long);
+ width = shift - SECTIONS_WIDTH - NODES_WIDTH - ZONES_WIDTH;
+ mminit_dprintk(MMINIT_TRACE, "pageflags_layout_widths",
+ "Section %d Node %d Zone %d Flags %d\n",
+ SECTIONS_WIDTH,
+ NODES_WIDTH,
+ ZONES_WIDTH,
+ NR_PAGEFLAGS);
+ mminit_dprintk(MMINIT_TRACE, "pageflags_layout_shifts",
+ "Section %d Node %d Zone %d\n",
+#ifdef SECTIONS_SHIFT
+ SECTIONS_SHIFT,
+#else
+ 0,
+#endif
+ NODES_SHIFT,
+ ZONES_SHIFT);
+ mminit_dprintk(MMINIT_TRACE, "pageflags_layout_offsets",
+ "Section %lu Node %lu Zone %lu\n",
+ (unsigned long)SECTIONS_PGSHIFT,
+ (unsigned long)NODES_PGSHIFT,
+ (unsigned long)ZONES_PGSHIFT);
+ mminit_dprintk(MMINIT_TRACE, "pageflags_layout_zoneid",
+ "Zone ID: %lu -> %lu\n",
+ (unsigned long)ZONEID_PGOFF,
+ (unsigned long)(ZONEID_PGOFF + ZONEID_SHIFT));
+ mminit_dprintk(MMINIT_TRACE, "pageflags_layout_usage",
+ "location: %d -> %d unused %d -> %d flags %d -> %d\n",
+ shift, width, width, NR_PAGEFLAGS, NR_PAGEFLAGS, 0);
+#ifdef NODE_NOT_IN_PAGE_FLAGS
+ mminit_dprintk(MMINIT_TRACE, "pageflags_layout_nodeflags",
+ "Node not in page flags");
+#endif
+
+ if (SECTIONS_WIDTH) {
+ shift -= SECTIONS_WIDTH;
+ BUG_ON(shift != SECTIONS_PGSHIFT);
+ }
+ if (NODES_WIDTH) {
+ shift -= NODES_WIDTH;
+ BUG_ON(shift != NODES_PGSHIFT);
+ }
+ if (ZONES_WIDTH) {
+ shift -= ZONES_WIDTH;
+ BUG_ON(shift != ZONES_PGSHIFT);
+ }
+
+ /* Check for bitmask overlaps */
+ or_mask = (ZONES_MASK << ZONES_PGSHIFT) |
+ (NODES_MASK << NODES_PGSHIFT) |
+ (SECTIONS_MASK << SECTIONS_PGSHIFT);
+ add_mask = (ZONES_MASK << ZONES_PGSHIFT) +
+ (NODES_MASK << NODES_PGSHIFT) +
+ (SECTIONS_MASK << SECTIONS_PGSHIFT);
+ BUG_ON(or_mask != add_mask);
+}
+
+void __meminit mminit_verify_page_links(struct page *page, enum zone_type zone,
+ unsigned long nid, unsigned long pfn)
+{
+ BUG_ON(page_to_nid(page) != nid);
+ BUG_ON(page_zonenum(page) != zone);
+ BUG_ON(page_to_pfn(page) != pfn);
+}
+
+static __init int set_mminit_loglevel(char *str)
+{
+ get_option(&str, &mminit_loglevel);
+ return 0;
+}
+early_param("mminit_loglevel", set_mminit_loglevel);
+#endif /* CONFIG_DEBUG_MEMORY_INIT */
+
+struct kobject *mm_kobj;
+EXPORT_SYMBOL_GPL(mm_kobj);
+
+static int __init mm_sysfs_init(void)
+{
+ mm_kobj = kobject_create_and_add("mm", kernel_kobj);
+ if (!mm_kobj)
+ return -ENOMEM;
+
+ return 0;
+}
+
+__initcall(mm_sysfs_init);
diff --git a/mm/mmap.c b/mm/mmap.c
index 1d102b956fd..5e0cc99e9cd 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -32,6 +32,8 @@
#include <asm/tlb.h>
#include <asm/mmu_context.h>
+#include "internal.h"
+
#ifndef arch_mmap_check
#define arch_mmap_check(addr, len, flags) (0)
#endif
@@ -1108,6 +1110,9 @@ munmap_back:
if (!may_expand_vm(mm, len >> PAGE_SHIFT))
return -ENOMEM;
+ if (flags & MAP_NORESERVE)
+ vm_flags |= VM_NORESERVE;
+
if (accountable && (!(flags & MAP_NORESERVE) ||
sysctl_overcommit_memory == OVERCOMMIT_NEVER)) {
if (vm_flags & VM_SHARED) {
@@ -1763,7 +1768,7 @@ static void unmap_region(struct mm_struct *mm,
update_hiwater_rss(mm);
unmap_vmas(&tlb, vma, start, end, &nr_accounted, NULL);
vm_unacct_memory(nr_accounted);
- free_pgtables(&tlb, vma, prev? prev->vm_end: FIRST_USER_ADDRESS,
+ free_pgtables(tlb, vma, prev? prev->vm_end: FIRST_USER_ADDRESS,
next? next->vm_start: 0);
tlb_finish_mmu(tlb, start, end);
}
@@ -1807,7 +1812,8 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
struct mempolicy *pol;
struct vm_area_struct *new;
- if (is_vm_hugetlb_page(vma) && (addr & ~HPAGE_MASK))
+ if (is_vm_hugetlb_page(vma) && (addr &
+ ~(huge_page_mask(hstate_vma(vma)))))
return -EINVAL;
if (mm->map_count >= sysctl_max_map_count)
@@ -2063,7 +2069,7 @@ void exit_mmap(struct mm_struct *mm)
/* Use -1 here to ensure all VMAs in the mm are unmapped */
end = unmap_vmas(&tlb, vma, 0, -1, &nr_accounted, NULL);
vm_unacct_memory(nr_accounted);
- free_pgtables(&tlb, vma, FIRST_USER_ADDRESS, 0);
+ free_pgtables(tlb, vma, FIRST_USER_ADDRESS, 0);
tlb_finish_mmu(tlb, 0, end);
/*
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 360d9cc8b38..abd645a3b0a 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -153,12 +153,10 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
* If we make a private mapping writable we increase our commit;
* but (without finer accounting) cannot reduce our commit if we
* make it unwritable again.
- *
- * FIXME? We haven't defined a VM_NORESERVE flag, so mprotecting
- * a MAP_NORESERVE private mapping to writable will now reserve.
*/
if (newflags & VM_WRITE) {
- if (!(oldflags & (VM_ACCOUNT|VM_WRITE|VM_SHARED))) {
+ if (!(oldflags & (VM_ACCOUNT|VM_WRITE|
+ VM_SHARED|VM_NORESERVE))) {
charged = nrpages;
if (security_vm_enough_memory(charged))
return -ENOMEM;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 79ac4afc908..6da667274df 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -153,9 +153,9 @@ static unsigned long __meminitdata dma_reserve;
static unsigned long __meminitdata node_boundary_start_pfn[MAX_NUMNODES];
static unsigned long __meminitdata node_boundary_end_pfn[MAX_NUMNODES];
#endif /* CONFIG_MEMORY_HOTPLUG_RESERVE */
- unsigned long __initdata required_kernelcore;
+ static unsigned long __initdata required_kernelcore;
static unsigned long __initdata required_movablecore;
- unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES];
+ static unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES];
/* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */
int movable_zone;
@@ -264,7 +264,7 @@ static void free_compound_page(struct page *page)
__free_pages_ok(page, compound_order(page));
}
-static void prep_compound_page(struct page *page, unsigned long order)
+void prep_compound_page(struct page *page, unsigned long order)
{
int i;
int nr_pages = 1 << order;
@@ -432,8 +432,9 @@ static inline void __free_one_page(struct page *page,
buddy = __page_find_buddy(page, page_idx, order);
if (!page_is_buddy(page, buddy, order))
- break; /* Move the buddy up one level. */
+ break;
+ /* Our buddy is free, merge with it and move up one order. */
list_del(&buddy->lru);
zone->free_area[order].nr_free--;
rmv_page_order(buddy);
@@ -532,7 +533,7 @@ static void __free_pages_ok(struct page *page, unsigned int order)
/*
* permit the bootmem allocator to evade page validation on high-order frees
*/
-void __free_pages_bootmem(struct page *page, unsigned int order)
+void __meminit __free_pages_bootmem(struct page *page, unsigned int order)
{
if (order == 0) {
__ClearPageReserved(page);
@@ -673,9 +674,9 @@ static int fallbacks[MIGRATE_TYPES][MIGRATE_TYPES-1] = {
* Note that start_page and end_pages are not aligned on a pageblock
* boundary. If alignment is required, use move_freepages_block()
*/
-int move_freepages(struct zone *zone,
- struct page *start_page, struct page *end_page,
- int migratetype)
+static int move_freepages(struct zone *zone,
+ struct page *start_page, struct page *end_page,
+ int migratetype)
{
struct page *page;
unsigned long order;
@@ -714,7 +715,8 @@ int move_freepages(struct zone *zone,
return pages_moved;
}
-int move_freepages_block(struct zone *zone, struct page *page, int migratetype)
+static int move_freepages_block(struct zone *zone, struct page *page,
+ int migratetype)
{
unsigned long start_pfn, end_pfn;
struct page *start_page, *end_page;
@@ -1429,7 +1431,7 @@ try_next_zone:
/*
* This is the 'heart' of the zoned buddy allocator.
*/
-static struct page *
+struct page *
__alloc_pages_internal(gfp_t gfp_mask, unsigned int order,
struct zonelist *zonelist, nodemask_t *nodemask)
{
@@ -1632,22 +1634,7 @@ nopage:
got_pg:
return page;
}
-
-struct page *
-__alloc_pages(gfp_t gfp_mask, unsigned int order,
- struct zonelist *zonelist)
-{
- return __alloc_pages_internal(gfp_mask, order, zonelist, NULL);
-}
-
-struct page *
-__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
- struct zonelist *zonelist, nodemask_t *nodemask)
-{
- return __alloc_pages_internal(gfp_mask, order, zonelist, nodemask);
-}
-
-EXPORT_SYMBOL(__alloc_pages);
+EXPORT_SYMBOL(__alloc_pages_internal);
/*
* Common helper functions.
@@ -1711,6 +1698,59 @@ void free_pages(unsigned long addr, unsigned int order)
EXPORT_SYMBOL(free_pages);
+/**
+ * alloc_pages_exact - allocate an exact number physically-contiguous pages.
+ * @size: the number of bytes to allocate
+ * @gfp_mask: GFP flags for the allocation
+ *
+ * This function is similar to alloc_pages(), except that it allocates the
+ * minimum number of pages to satisfy the request. alloc_pages() can only
+ * allocate memory in power-of-two pages.
+ *
+ * This function is also limited by MAX_ORDER.
+ *
+ * Memory allocated by this function must be released by free_pages_exact().
+ */
+void *alloc_pages_exact(size_t size, gfp_t gfp_mask)
+{
+ unsigned int order = get_order(size);
+ unsigned long addr;
+
+ addr = __get_free_pages(gfp_mask, order);
+ if (addr) {
+ unsigned long alloc_end = addr + (PAGE_SIZE << order);
+ unsigned long used = addr + PAGE_ALIGN(size);
+
+ split_page(virt_to_page(addr), order);
+ while (used < alloc_end) {
+ free_page(used);
+ used += PAGE_SIZE;
+ }
+ }
+
+ return (void *)addr;
+}
+EXPORT_SYMBOL(alloc_pages_exact);
+
+/**
+ * free_pages_exact - release memory allocated via alloc_pages_exact()
+ * @virt: the value returned by alloc_pages_exact.
+ * @size: size of allocation, same value as passed to alloc_pages_exact().
+ *
+ * Release the memory allocated by a previous call to alloc_pages_exact.
+ */
+void free_pages_exact(void *virt, size_t size)
+{
+ unsigned long addr = (unsigned long)virt;
+ unsigned long end = addr + PAGE_ALIGN(size);
+
+ while (addr < end) {
+ free_page(addr);
+ addr += PAGE_SIZE;
+ }
+}
+EXPORT_SYMBOL(free_pages_exact);
+
static unsigned int nr_free_zone_pages(int offset)
{
struct zoneref *z;
@@ -2352,6 +2392,7 @@ void build_all_zonelists(void)
if (system_state == SYSTEM_BOOTING) {
__build_all_zonelists(NULL);
+ mminit_verify_zonelist();
cpuset_init_current_mems_allowed();
} else {
/* we have to stop all cpus to guarantee there is no user
@@ -2534,6 +2575,7 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
}
page = pfn_to_page(pfn);
set_page_links(page, zone, nid, pfn);
+ mminit_verify_page_links(page, zone, nid, pfn);
init_page_count(page);
reset_page_mapcount(page);
SetPageReserved(page);
@@ -2611,7 +2653,7 @@ static int zone_batchsize(struct zone *zone)
return batch;
}
-inline void setup_pageset(struct per_cpu_pageset *p, unsigned long batch)
+static void setup_pageset(struct per_cpu_pageset *p, unsigned long batch)
{
struct per_cpu_pages *pcp;
@@ -2836,6 +2878,12 @@ __meminit int init_currently_empty_zone(struct zone *zone,
zone->zone_start_pfn = zone_start_pfn;
+ mminit_dprintk(MMINIT_TRACE, "memmap_init",
+ "Initialising map node %d zone %lu pfns %lu -> %lu\n",
+ pgdat->node_id,
+ (unsigned long)zone_idx(zone),
+ zone_start_pfn, (zone_start_pfn + size));
+
zone_init_free_lists(zone);
return 0;
@@ -2975,7 +3023,8 @@ void __init sparse_memory_present_with_active_regions(int nid)
void __init push_node_boundaries(unsigned int nid,
unsigned long start_pfn, unsigned long end_pfn)
{
- printk(KERN_DEBUG "Entering push_node_boundaries(%u, %lu, %lu)\n",
+ mminit_dprintk(MMINIT_TRACE, "zoneboundary",
+ "Entering push_node_boundaries(%u, %lu, %lu)\n",
nid, start_pfn, end_pfn);
/* Initialise the boundary for this node if necessary */
@@ -2993,7 +3042,8 @@ void __init push_node_boundaries(unsigned int nid,
static void __meminit account_node_boundary(unsigned int nid,
unsigned long *start_pfn, unsigned long *end_pfn)
{
- printk(KERN_DEBUG "Entering account_node_boundary(%u, %lu, %lu)\n",
+ mminit_dprintk(MMINIT_TRACE, "zoneboundary",
+ "Entering account_node_boundary(%u, %lu, %lu)\n",
nid, *start_pfn, *end_pfn);
/* Return if boundary information has not been provided */
@@ -3050,7 +3100,7 @@ void __meminit get_pfn_range_for_nid(unsigned int nid,
* assumption is made that zones within a node are ordered in monotonic
* increasing memory addresses so that the "highest" populated zone is used
*/
-void __init find_usable_zone_for_movable(void)
+static void __init find_usable_zone_for_movable(void)
{
int zone_index;
for (zone_index = MAX_NR_ZONES - 1; zone_index >= 0; zone_index--) {
@@ -3076,7 +3126,7 @@ void __init find_usable_zone_for_movable(void)
* highest usable zone for ZONE_MOVABLE. This preserves the assumption that
* zones within a node are in order of monotonic increases memory addresses
*/
-void __meminit adjust_zone_range_for_zone_movable(int nid,
+static void __meminit adjust_zone_range_for_zone_movable(int nid,
unsigned long zone_type,
unsigned long node_start_pfn,
unsigned long node_end_pfn,
@@ -3137,7 +3187,7 @@ static unsigned long __meminit zone_spanned_pages_in_node(int nid,
* Return the number of holes in a range on a node. If nid is MAX_NUMNODES,
* then all holes in the requested range will be accounted for.
*/
-unsigned long __meminit __absent_pages_in_range(int nid,
+static unsigned long __meminit __absent_pages_in_range(int nid,
unsigned long range_start_pfn,
unsigned long range_end_pfn)
{
@@ -3368,8 +3418,8 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
PAGE_ALIGN(size * sizeof(struct page)) >> PAGE_SHIFT;
if (realsize >= memmap_pages) {
realsize -= memmap_pages;
- printk(KERN_DEBUG
- " %s zone: %lu pages used for memmap\n",
+ mminit_dprintk(MMINIT_TRACE, "memmap_init",
+ "%s zone: %lu pages used for memmap\n",
zone_names[j], memmap_pages);
} else
printk(KERN_WARNING
@@ -3379,7 +3429,8 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
/* Account for reserved pages */
if (j == 0 && realsize > dma_reserve) {
realsize -= dma_reserve;
- printk(KERN_DEBUG " %s zone: %lu pages reserved\n",
+ mminit_dprintk(MMINIT_TRACE, "memmap_init",
+ "%s zone: %lu pages reserved\n",
zone_names[0], dma_reserve);
}
@@ -3464,10 +3515,11 @@ static void __init_refok alloc_node_mem_map(struct pglist_data *pgdat)
#endif /* CONFIG_FLAT_NODE_MEM_MAP */
}
-void __paginginit free_area_init_node(int nid, struct pglist_data *pgdat,
- unsigned long *zones_size, unsigned long node_start_pfn,
- unsigned long *zholes_size)
+void __paginginit free_area_init_node(int nid, unsigned long *zones_size,
+ unsigned long node_start_pfn, unsigned long *zholes_size)
{
+ pg_data_t *pgdat = NODE_DATA(nid);
+
pgdat->node_id = nid;
pgdat->node_start_pfn = node_start_pfn;
calculate_node_totalpages(pgdat, zones_size, zholes_size);
@@ -3520,10 +3572,13 @@ void __init add_active_range(unsigned int nid, unsigned long start_pfn,
{
int i;
- printk(KERN_DEBUG "Entering add_active_range(%d, %#lx, %#lx) "
- "%d entries of %d used\n",
- nid, start_pfn, end_pfn,
- nr_nodemap_entries, MAX_ACTIVE_REGIONS);
+ mminit_dprintk(MMINIT_TRACE, "memory_register",
+ "Entering add_active_range(%d, %#lx, %#lx) "
+ "%d entries of %d used\n",
+ nid, start_pfn, end_pfn,
+ nr_nodemap_entries, MAX_ACTIVE_REGIONS);
+
+ mminit_validate_memmodel_limits(&start_pfn, &end_pfn);
/* Merge with existing active regions if possible */
for (i = 0; i < nr_nodemap_entries; i++) {
@@ -3669,7 +3724,7 @@ static void __init sort_node_map(void)
}
/* Find the lowest pfn for a node */
-unsigned long __init find_min_pfn_for_node(int nid)
+static unsigned long __init find_min_pfn_for_node(int nid)
{
int i;
unsigned long min_pfn = ULONG_MAX;
@@ -3741,7 +3796,7 @@ static unsigned long __init early_calculate_totalpages(void)
* memory. When they don't, some nodes will have more kernelcore than
* others
*/
-void __init find_zone_movable_pfns_for_nodes(unsigned long *movable_pfn)
+static void __init find_zone_movable_pfns_for_nodes(unsigned long *movable_pfn)
{
int i, nid;
unsigned long usable_startpfn;
@@ -3957,10 +4012,11 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
early_node_map[i].end_pfn);
/* Initialise every node */
+ mminit_verify_pageflags_layout();
setup_nr_node_ids();
for_each_online_node(nid) {
pg_data_t *pgdat = NODE_DATA(nid);
- free_area_init_node(nid, pgdat, NULL,
+ free_area_init_node(nid, NULL,
find_min_pfn_for_node(nid), NULL);
/* Any memory on that node */
@@ -4025,15 +4081,13 @@ void __init set_dma_reserve(unsigned long new_dma_reserve)
}
#ifndef CONFIG_NEED_MULTIPLE_NODES
-static bootmem_data_t contig_bootmem_data;
-struct pglist_data contig_page_data = { .bdata = &contig_bootmem_data };
-
+struct pglist_data contig_page_data = { .bdata = &bootmem_node_data[0] };
EXPORT_SYMBOL(contig_page_data);
#endif
void __init free_area_init(unsigned long *zones_size)
{
- free_area_init_node(0, NODE_DATA(0), zones_size,
+ free_area_init_node(0, zones_size,
__pa(PAGE_OFFSET) >> PAGE_SHIFT, NULL);
}
diff --git a/mm/pdflush.c b/mm/pdflush.c
index 9d834aa4b97..0cbe0c60c6b 100644
--- a/mm/pdflush.c
+++ b/mm/pdflush.c
@@ -130,7 +130,7 @@ static int __pdflush(struct pdflush_work *my_work)
* Thread creation: For how long have there been zero
* available threads?
*/
- if (jiffies - last_empty_jifs > 1 * HZ) {
+ if (time_after(jiffies, last_empty_jifs + 1 * HZ)) {
/* unlocked list_empty() test is OK here */
if (list_empty(&pdflush_list)) {
/* unlocked test is OK here */
@@ -151,7 +151,7 @@ static int __pdflush(struct pdflush_work *my_work)
if (nr_pdflush_threads <= MIN_PDFLUSH_THREADS)
continue;
pdf = list_entry(pdflush_list.prev, struct pdflush_work, list);
- if (jiffies - pdf->when_i_went_to_sleep > 1 * HZ) {
+ if (time_after(jiffies, pdf->when_i_went_to_sleep + 1 * HZ)) {
/* Limit exit rate */
pdf->when_i_went_to_sleep = jiffies;
break; /* exeunt */
diff --git a/mm/rmap.c b/mm/rmap.c
index bf0a5b7cfb8..abbd29f7c43 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -576,14 +576,8 @@ void page_add_anon_rmap(struct page *page,
VM_BUG_ON(address < vma->vm_start || address >= vma->vm_end);
if (atomic_inc_and_test(&page->_mapcount))
__page_set_anon_rmap(page, vma, address);
- else {
+ else
__page_check_anon_rmap(page, vma, address);
- /*
- * We unconditionally charged during prepare, we uncharge here
- * This takes care of balancing the reference counts
- */
- mem_cgroup_uncharge_page(page);
- }
}
/**
@@ -614,12 +608,6 @@ void page_add_file_rmap(struct page *page)
{
if (atomic_inc_and_test(&page->_mapcount))
__inc_zone_page_state(page, NR_FILE_MAPPED);
- else
- /*
- * We unconditionally charged during prepare, we uncharge here
- * This takes care of balancing the reference counts
- */
- mem_cgroup_uncharge_page(page);
}
#ifdef CONFIG_DEBUG_VM
diff --git a/mm/shmem.c b/mm/shmem.c
index e2a6ae1a44e..f92fea94d03 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -922,20 +922,26 @@ found:
error = 1;
if (!inode)
goto out;
- /* Precharge page while we can wait, compensate afterwards */
+ /* Precharge page using GFP_KERNEL while we can wait */
error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL);
if (error)
goto out;
error = radix_tree_preload(GFP_KERNEL);
- if (error)
- goto uncharge;
+ if (error) {
+ mem_cgroup_uncharge_cache_page(page);
+ goto out;
+ }
error = 1;
spin_lock(&info->lock);
ptr = shmem_swp_entry(info, idx, NULL);
- if (ptr && ptr->val == entry.val)
+ if (ptr && ptr->val == entry.val) {
error = add_to_page_cache(page, inode->i_mapping,
idx, GFP_NOWAIT);
+ /* does mem_cgroup_uncharge_cache_page on error */
+ } else /* we must compensate for our precharge above */
+ mem_cgroup_uncharge_cache_page(page);
+
if (error == -EEXIST) {
struct page *filepage = find_get_page(inode->i_mapping, idx);
error = 1;
@@ -961,8 +967,6 @@ found:
shmem_swp_unmap(ptr);
spin_unlock(&info->lock);
radix_tree_preload_end();
-uncharge:
- mem_cgroup_uncharge_page(page);
out:
unlock_page(page);
page_cache_release(page);
@@ -1311,17 +1315,14 @@ repeat:
shmem_swp_unmap(entry);
spin_unlock(&info->lock);
unlock_page(swappage);
+ page_cache_release(swappage);
if (error == -ENOMEM) {
/* allow reclaim from this memory cgroup */
- error = mem_cgroup_cache_charge(swappage,
- current->mm, gfp & ~__GFP_HIGHMEM);
- if (error) {
- page_cache_release(swappage);
+ error = mem_cgroup_shrink_usage(current->mm,
+ gfp);
+ if (error)
goto failed;
- }
- mem_cgroup_uncharge_page(swappage);
}
- page_cache_release(swappage);
goto repeat;
}
} else if (sgp == SGP_READ && !filepage) {
@@ -1358,6 +1359,8 @@ repeat:
}
if (!filepage) {
+ int ret;
+
spin_unlock(&info->lock);
filepage = shmem_alloc_page(gfp, info, idx);
if (!filepage) {
@@ -1386,10 +1389,18 @@ repeat:
swap = *entry;
shmem_swp_unmap(entry);
}
- if (error || swap.val || 0 != add_to_page_cache_lru(
- filepage, mapping, idx, GFP_NOWAIT)) {
+ ret = error || swap.val;
+ if (ret)
+ mem_cgroup_uncharge_cache_page(filepage);
+ else
+ ret = add_to_page_cache_lru(filepage, mapping,
+ idx, GFP_NOWAIT);
+ /*
+ * At add_to_page_cache_lru() failure, uncharge will
+ * be done automatically.
+ */
+ if (ret) {
spin_unlock(&info->lock);
- mem_cgroup_uncharge_page(filepage);
page_cache_release(filepage);
shmem_unacct_blocks(info->flags, 1);
shmem_free_blocks(inode, 1);
@@ -1398,7 +1409,6 @@ repeat:
goto failed;
goto repeat;
}
- mem_cgroup_uncharge_page(filepage);
info->flags |= SHMEM_PAGEIN;
}
@@ -1690,26 +1700,38 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_
file_accessed(filp);
}
-static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
+static ssize_t shmem_file_aio_read(struct kiocb *iocb,
+ const struct iovec *iov, unsigned long nr_segs, loff_t pos)
{
- read_descriptor_t desc;
+ struct file *filp = iocb->ki_filp;
+ ssize_t retval;
+ unsigned long seg;
+ size_t count;
+ loff_t *ppos = &iocb->ki_pos;
- if ((ssize_t) count < 0)
- return -EINVAL;
- if (!access_ok(VERIFY_WRITE, buf, count))
- return -EFAULT;
- if (!count)
- return 0;
+ retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);
+ if (retval)
+ return retval;
- desc.written = 0;
- desc.count = count;
- desc.arg.buf = buf;
- desc.error = 0;
+ for (seg = 0; seg < nr_segs; seg++) {
+ read_descriptor_t desc;
- do_shmem_file_read(filp, ppos, &desc, file_read_actor);
- if (desc.written)
- return desc.written;
- return desc.error;
+ desc.written = 0;
+ desc.arg.buf = iov[seg].iov_base;
+ desc.count = iov[seg].iov_len;
+ if (desc.count == 0)
+ continue;
+ desc.error = 0;
+ do_shmem_file_read(filp, ppos, &desc, file_read_actor);
+ retval += desc.written;
+ if (desc.error) {
+ retval = retval ?: desc.error;
+ break;
+ }
+ if (desc.count > 0)
+ break;
+ }
+ return retval;
}
static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -2369,8 +2391,9 @@ static const struct file_operations shmem_file_operations = {
.mmap = shmem_mmap,
#ifdef CONFIG_TMPFS
.llseek = generic_file_llseek,
- .read = shmem_file_read,
+ .read = do_sync_read,
.write = do_sync_write,
+ .aio_read = shmem_file_aio_read,
.aio_write = generic_file_aio_write,
.fsync = simple_sync_file,
.splice_read = generic_file_splice_read,
diff --git a/mm/slob.c b/mm/slob.c
index a3ad6671adf..de268eb7ac7 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -130,17 +130,17 @@ static LIST_HEAD(free_slob_large);
*/
static inline int slob_page(struct slob_page *sp)
{
- return test_bit(PG_active, &sp->flags);
+ return PageSlobPage((struct page *)sp);
}
static inline void set_slob_page(struct slob_page *sp)
{
- __set_bit(PG_active, &sp->flags);
+ __SetPageSlobPage((struct page *)sp);
}
static inline void clear_slob_page(struct slob_page *sp)
{
- __clear_bit(PG_active, &sp->flags);
+ __ClearPageSlobPage((struct page *)sp);
}
/*
@@ -148,19 +148,19 @@ static inline void clear_slob_page(struct slob_page *sp)
*/
static inline int slob_page_free(struct slob_page *sp)
{
- return test_bit(PG_private, &sp->flags);
+ return PageSlobFree((struct page *)sp);
}
static void set_slob_page_free(struct slob_page *sp, struct list_head *list)
{
list_add(&sp->list, list);
- __set_bit(PG_private, &sp->flags);
+ __SetPageSlobFree((struct page *)sp);
}
static inline void clear_slob_page_free(struct slob_page *sp)
{
list_del(&sp->list);
- __clear_bit(PG_private, &sp->flags);
+ __ClearPageSlobFree((struct page *)sp);
}
#define SLOB_UNIT sizeof(slob_t)
diff --git a/mm/slub.c b/mm/slub.c
index 6d4a49c1ff2..77c21cf53ff 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -102,44 +102,12 @@
* the fast path and disables lockless freelists.
*/
-#define FROZEN (1 << PG_active)
-
#ifdef CONFIG_SLUB_DEBUG
-#define SLABDEBUG (1 << PG_error)
+#define SLABDEBUG 1
#else
#define SLABDEBUG 0
#endif
-static inline int SlabFrozen(struct page *page)
-{
- return page->flags & FROZEN;
-}
-
-static inline void SetSlabFrozen(struct page *page)
-{
- page->flags |= FROZEN;
-}
-
-static inline void ClearSlabFrozen(struct page *page)
-{
- page->flags &= ~FROZEN;
-}
-
-static inline int SlabDebug(struct page *page)
-{
- return page->flags & SLABDEBUG;
-}
-
-static inline void SetSlabDebug(struct page *page)
-{
- page->flags |= SLABDEBUG;
-}
-
-static inline void ClearSlabDebug(struct page *page)
-{
- page->flags &= ~SLABDEBUG;
-}
-
/*
* Issues still to be resolved:
*
@@ -971,7 +939,7 @@ static int free_debug_processing(struct kmem_cache *s, struct page *page,
}
/* Special debug activities for freeing objects */
- if (!SlabFrozen(page) && !page->freelist)
+ if (!PageSlubFrozen(page) && !page->freelist)
remove_full(s, page);
if (s->flags & SLAB_STORE_USER)
set_track(s, object, TRACK_FREE, addr);
@@ -1157,7 +1125,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
page->flags |= 1 << PG_slab;
if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON |
SLAB_STORE_USER | SLAB_TRACE))
- SetSlabDebug(page);
+ __SetPageSlubDebug(page);
start = page_address(page);
@@ -1184,14 +1152,14 @@ static void __free_slab(struct kmem_cache *s, struct page *page)
int order = compound_order(page);
int pages = 1 << order;
- if (unlikely(SlabDebug(page))) {
+ if (unlikely(SLABDEBUG && PageSlubDebug(page))) {
void *p;
slab_pad_check(s, page);
for_each_object(p, s, page_address(page),
page->objects)
check_object(s, page, p, 0);
- ClearSlabDebug(page);
+ __ClearPageSlubDebug(page);
}
mod_zone_page_state(page_zone(page),
@@ -1288,7 +1256,7 @@ static inline int lock_and_freeze_slab(struct kmem_cache_node *n,
if (slab_trylock(page)) {
list_del(&page->lru);
n->nr_partial--;
- SetSlabFrozen(page);
+ __SetPageSlubFrozen(page);
return 1;
}
return 0;
@@ -1398,7 +1366,7 @@ static void unfreeze_slab(struct kmem_cache *s, struct page *page, int tail)
struct kmem_cache_node *n = get_node(s, page_to_nid(page));
struct kmem_cache_cpu *c = get_cpu_slab(s, smp_processor_id());
- ClearSlabFrozen(page);
+ __ClearPageSlubFrozen(page);
if (page->inuse) {
if (page->freelist) {
@@ -1406,7 +1374,8 @@ static void unfreeze_slab(struct kmem_cache *s, struct page *page, int tail)
stat(c, tail ? DEACTIVATE_TO_TAIL : DEACTIVATE_TO_HEAD);
} else {
stat(c, DEACTIVATE_FULL);
- if (SlabDebug(page) && (s->flags & SLAB_STORE_USER))
+ if (SLABDEBUG && PageSlubDebug(page) &&
+ (s->flags & SLAB_STORE_USER))
add_full(n, page);
}
slab_unlock(page);
@@ -1551,7 +1520,7 @@ load_freelist:
object = c->page->freelist;
if (unlikely(!object))
goto another_slab;
- if (unlikely(SlabDebug(c->page)))
+ if (unlikely(SLABDEBUG && PageSlubDebug(c->page)))
goto debug;
c->freelist = object[c->offset];
@@ -1588,7 +1557,7 @@ new_slab:
if (c->page)
flush_slab(s, c);
slab_lock(new);
- SetSlabFrozen(new);
+ __SetPageSlubFrozen(new);
c->page = new;
goto load_freelist;
}
@@ -1674,7 +1643,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
stat(c, FREE_SLOWPATH);
slab_lock(page);
- if (unlikely(SlabDebug(page)))
+ if (unlikely(SLABDEBUG && PageSlubDebug(page)))
goto debug;
checks_ok:
@@ -1682,7 +1651,7 @@ checks_ok:
page->freelist = object;
page->inuse--;
- if (unlikely(SlabFrozen(page))) {
+ if (unlikely(PageSlubFrozen(page))) {
stat(c, FREE_FROZEN);
goto out_unlock;
}
@@ -3317,12 +3286,12 @@ static void validate_slab_slab(struct kmem_cache *s, struct page *page,
s->name, page);
if (s->flags & DEBUG_DEFAULT_FLAGS) {
- if (!SlabDebug(page))
- printk(KERN_ERR "SLUB %s: SlabDebug not set "
+ if (!PageSlubDebug(page))
+ printk(KERN_ERR "SLUB %s: SlubDebug not set "
"on slab 0x%p\n", s->name, page);
} else {
- if (SlabDebug(page))
- printk(KERN_ERR "SLUB %s: SlabDebug set on "
+ if (PageSlubDebug(page))
+ printk(KERN_ERR "SLUB %s: SlubDebug set on "
"slab 0x%p\n", s->name, page);
}
}
diff --git a/mm/sparse.c b/mm/sparse.c
index 36511c7b5e2..8ffc0899000 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -12,6 +12,7 @@
#include <asm/dma.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
+#include "internal.h"
/*
* Permanent SPARSEMEM data:
@@ -147,22 +148,41 @@ static inline int sparse_early_nid(struct mem_section *section)
return (section->section_mem_map >> SECTION_NID_SHIFT);
}
-/* Record a memory area against a node. */
-void __init memory_present(int nid, unsigned long start, unsigned long end)
+/* Validate the physical addressing limitations of the model */
+void __meminit mminit_validate_memmodel_limits(unsigned long *start_pfn,
+ unsigned long *end_pfn)
{
- unsigned long max_arch_pfn = 1UL << (MAX_PHYSMEM_BITS-PAGE_SHIFT);
- unsigned long pfn;
+ unsigned long max_sparsemem_pfn = 1UL << (MAX_PHYSMEM_BITS-PAGE_SHIFT);
/*
* Sanity checks - do not allow an architecture to pass
* in larger pfns than the maximum scope of sparsemem:
*/
- if (start >= max_arch_pfn)
- return;
- if (end >= max_arch_pfn)
- end = max_arch_pfn;
+ if (*start_pfn > max_sparsemem_pfn) {
+ mminit_dprintk(MMINIT_WARNING, "pfnvalidation",
+ "Start of range %lu -> %lu exceeds SPARSEMEM max %lu\n",
+ *start_pfn, *end_pfn, max_sparsemem_pfn);
+ WARN_ON_ONCE(1);
+ *start_pfn = max_sparsemem_pfn;
+ *end_pfn = max_sparsemem_pfn;
+ }
+
+ if (*end_pfn > max_sparsemem_pfn) {
+ mminit_dprintk(MMINIT_WARNING, "pfnvalidation",
+ "End of range %lu -> %lu exceeds SPARSEMEM max %lu\n",
+ *start_pfn, *end_pfn, max_sparsemem_pfn);
+ WARN_ON_ONCE(1);
+ *end_pfn = max_sparsemem_pfn;
+ }
+}
+
+/* Record a memory area against a node. */
+void __init memory_present(int nid, unsigned long start, unsigned long end)
+{
+ unsigned long pfn;
start &= PAGE_SECTION_MASK;
+ mminit_validate_memmodel_limits(&start, &end);
for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) {
unsigned long section = pfn_to_section_nr(pfn);
struct mem_section *ms;
@@ -187,6 +207,7 @@ unsigned long __init node_memmap_size_bytes(int nid, unsigned long start_pfn,
unsigned long pfn;
unsigned long nr_pages = 0;
+ mminit_validate_memmodel_limits(&start_pfn, &end_pfn);
for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
if (nid != early_pfn_to_nid(pfn))
continue;
@@ -248,16 +269,92 @@ static unsigned long *__kmalloc_section_usemap(void)
}
#endif /* CONFIG_MEMORY_HOTPLUG */
+#ifdef CONFIG_MEMORY_HOTREMOVE
+static unsigned long * __init
+sparse_early_usemap_alloc_pgdat_section(struct pglist_data *pgdat)
+{
+ unsigned long section_nr;
+
+ /*
+ * A page may contain usemaps for other sections preventing the
+ * page being freed and making a section unremovable while
+ * other sections referencing the usemap retmain active. Similarly,
+ * a pgdat can prevent a section being removed. If section A
+ * contains a pgdat and section B contains the usemap, both
+ * sections become inter-dependent. This allocates usemaps
+ * from the same section as the pgdat where possible to avoid
+ * this problem.
+ */
+ section_nr = pfn_to_section_nr(__pa(pgdat) >> PAGE_SHIFT);
+ return alloc_bootmem_section(usemap_size(), section_nr);
+}
+
+static void __init check_usemap_section_nr(int nid, unsigned long *usemap)
+{
+ unsigned long usemap_snr, pgdat_snr;
+ static unsigned long old_usemap_snr = NR_MEM_SECTIONS;
+ static unsigned long old_pgdat_snr = NR_MEM_SECTIONS;
+ struct pglist_data *pgdat = NODE_DATA(nid);
+ int usemap_nid;
+
+ usemap_snr = pfn_to_section_nr(__pa(usemap) >> PAGE_SHIFT);
+ pgdat_snr = pfn_to_section_nr(__pa(pgdat) >> PAGE_SHIFT);
+ if (usemap_snr == pgdat_snr)
+ return;
+
+ if (old_usemap_snr == usemap_snr && old_pgdat_snr == pgdat_snr)
+ /* skip redundant message */
+ return;
+
+ old_usemap_snr = usemap_snr;
+ old_pgdat_snr = pgdat_snr;
+
+ usemap_nid = sparse_early_nid(__nr_to_section(usemap_snr));
+ if (usemap_nid != nid) {
+ printk(KERN_INFO
+ "node %d must be removed before remove section %ld\n",
+ nid, usemap_snr);
+ return;
+ }
+ /*
+ * There is a circular dependency.
+ * Some platforms allow un-removable section because they will just
+ * gather other removable sections for dynamic partitioning.
+ * Just notify un-removable section's number here.
+ */
+ printk(KERN_INFO "Section %ld and %ld (node %d)", usemap_snr,
+ pgdat_snr, nid);
+ printk(KERN_CONT
+ " have a circular dependency on usemap and pgdat allocations\n");
+}
+#else
+static unsigned long * __init
+sparse_early_usemap_alloc_pgdat_section(struct pglist_data *pgdat)
+{
+ return NULL;
+}
+
+static void __init check_usemap_section_nr(int nid, unsigned long *usemap)
+{
+}
+#endif /* CONFIG_MEMORY_HOTREMOVE */
+
static unsigned long *__init sparse_early_usemap_alloc(unsigned long pnum)
{
unsigned long *usemap;
struct mem_section *ms = __nr_to_section(pnum);
int nid = sparse_early_nid(ms);
- usemap = alloc_bootmem_node(NODE_DATA(nid), usemap_size());
+ usemap = sparse_early_usemap_alloc_pgdat_section(NODE_DATA(nid));
if (usemap)
return usemap;
+ usemap = alloc_bootmem_node(NODE_DATA(nid), usemap_size());
+ if (usemap) {
+ check_usemap_section_nr(nid, usemap);
+ return usemap;
+ }
+
/* Stupid: suppress gcc warning for SPARSEMEM && !NUMA */
nid = 0;
diff --git a/mm/swap.c b/mm/swap.c
index 45c9f25a8a3..dd89234ee51 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -34,9 +34,9 @@
/* How many pages do we try to swap or page in/out together? */
int page_cluster;
-static DEFINE_PER_CPU(struct pagevec, lru_add_pvecs) = { 0, };
-static DEFINE_PER_CPU(struct pagevec, lru_add_active_pvecs) = { 0, };
-static DEFINE_PER_CPU(struct pagevec, lru_rotate_pvecs) = { 0, };
+static DEFINE_PER_CPU(struct pagevec, lru_add_pvecs);
+static DEFINE_PER_CPU(struct pagevec, lru_add_active_pvecs);
+static DEFINE_PER_CPU(struct pagevec, lru_rotate_pvecs);
/*
* This path almost never happens for VM activity - pages are normally
@@ -493,7 +493,7 @@ EXPORT_SYMBOL(pagevec_lookup_tag);
*/
#define ACCT_THRESHOLD max(16, NR_CPUS * 2)
-static DEFINE_PER_CPU(long, committed_space) = 0;
+static DEFINE_PER_CPU(long, committed_space);
void vm_acct_memory(long pages)
{
diff --git a/mm/swapfile.c b/mm/swapfile.c
index bd1bb592030..2f33edb8bee 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -37,6 +37,7 @@ DEFINE_SPINLOCK(swap_lock);
unsigned int nr_swapfiles;
long total_swap_pages;
static int swap_overflow;
+static int least_priority;
static const char Bad_file[] = "Bad swap file entry ";
static const char Unused_file[] = "Unused swap file entry ";
@@ -1260,6 +1261,11 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
/* just pick something that's safe... */
swap_list.next = swap_list.head;
}
+ if (p->prio < 0) {
+ for (i = p->next; i >= 0; i = swap_info[i].next)
+ swap_info[i].prio = p->prio--;
+ least_priority++;
+ }
nr_swap_pages -= p->pages;
total_swap_pages -= p->pages;
p->flags &= ~SWP_WRITEOK;
@@ -1272,9 +1278,14 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
if (err) {
/* re-insert swap space back into swap_list */
spin_lock(&swap_lock);
- for (prev = -1, i = swap_list.head; i >= 0; prev = i, i = swap_info[i].next)
+ if (p->prio < 0)
+ p->prio = --least_priority;
+ prev = -1;
+ for (i = swap_list.head; i >= 0; i = swap_info[i].next) {
if (p->prio >= swap_info[i].prio)
break;
+ prev = i;
+ }
p->next = i;
if (prev < 0)
swap_list.head = swap_list.next = p - swap_info;
@@ -1447,7 +1458,6 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
unsigned int type;
int i, prev;
int error;
- static int least_priority;
union swap_header *swap_header = NULL;
int swap_header_version;
unsigned int nr_good_pages = 0;
@@ -1455,7 +1465,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
sector_t span;
unsigned long maxpages = 1;
int swapfilesize;
- unsigned short *swap_map;
+ unsigned short *swap_map = NULL;
struct page *page = NULL;
struct inode *inode = NULL;
int did_down = 0;
@@ -1474,22 +1484,10 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
}
if (type >= nr_swapfiles)
nr_swapfiles = type+1;
+ memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->extent_list);
p->flags = SWP_USED;
- p->swap_file = NULL;
- p->old_block_size = 0;
- p->swap_map = NULL;
- p->lowest_bit = 0;
- p->highest_bit = 0;
- p->cluster_nr = 0;
- p->inuse_pages = 0;
p->next = -1;
- if (swap_flags & SWAP_FLAG_PREFER) {
- p->prio =
- (swap_flags & SWAP_FLAG_PRIO_MASK)>>SWAP_FLAG_PRIO_SHIFT;
- } else {
- p->prio = --least_priority;
- }
spin_unlock(&swap_lock);
name = getname(specialfile);
error = PTR_ERR(name);
@@ -1632,19 +1630,20 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
goto bad_swap;
/* OK, set up the swap map and apply the bad block list */
- if (!(p->swap_map = vmalloc(maxpages * sizeof(short)))) {
+ swap_map = vmalloc(maxpages * sizeof(short));
+ if (!swap_map) {
error = -ENOMEM;
goto bad_swap;
}
error = 0;
- memset(p->swap_map, 0, maxpages * sizeof(short));
+ memset(swap_map, 0, maxpages * sizeof(short));
for (i = 0; i < swap_header->info.nr_badpages; i++) {
int page_nr = swap_header->info.badpages[i];
if (page_nr <= 0 || page_nr >= swap_header->info.last_page)
error = -EINVAL;
else
- p->swap_map[page_nr] = SWAP_MAP_BAD;
+ swap_map[page_nr] = SWAP_MAP_BAD;
}
nr_good_pages = swap_header->info.last_page -
swap_header->info.nr_badpages -
@@ -1654,7 +1653,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
}
if (nr_good_pages) {
- p->swap_map[0] = SWAP_MAP_BAD;
+ swap_map[0] = SWAP_MAP_BAD;
p->max = maxpages;
p->pages = nr_good_pages;
nr_extents = setup_swap_extents(p, &span);
@@ -1672,6 +1671,12 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
mutex_lock(&swapon_mutex);
spin_lock(&swap_lock);
+ if (swap_flags & SWAP_FLAG_PREFER)
+ p->prio =
+ (swap_flags & SWAP_FLAG_PRIO_MASK) >> SWAP_FLAG_PRIO_SHIFT;
+ else
+ p->prio = --least_priority;
+ p->swap_map = swap_map;
p->flags = SWP_ACTIVE;
nr_swap_pages += nr_good_pages;
total_swap_pages += nr_good_pages;
@@ -1707,12 +1712,8 @@ bad_swap:
destroy_swap_extents(p);
bad_swap_2:
spin_lock(&swap_lock);
- swap_map = p->swap_map;
p->swap_file = NULL;
- p->swap_map = NULL;
p->flags = 0;
- if (!(swap_flags & SWAP_FLAG_PREFER))
- ++least_priority;
spin_unlock(&swap_lock);
vfree(swap_map);
if (swap_file)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 6e45b0f3d12..35f29381629 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -931,6 +931,25 @@ static void s_stop(struct seq_file *m, void *p)
read_unlock(&vmlist_lock);
}
+static void show_numa_info(struct seq_file *m, struct vm_struct *v)
+{
+ if (NUMA_BUILD) {
+ unsigned int nr, *counters = m->private;
+
+ if (!counters)
+ return;
+
+ memset(counters, 0, nr_node_ids * sizeof(unsigned int));
+
+ for (nr = 0; nr < v->nr_pages; nr++)
+ counters[page_to_nid(v->pages[nr])]++;
+
+ for_each_node_state(nr, N_HIGH_MEMORY)
+ if (counters[nr])
+ seq_printf(m, " N%u=%u", nr, counters[nr]);
+ }
+}
+
static int s_show(struct seq_file *m, void *p)
{
struct vm_struct *v = p;
@@ -967,6 +986,7 @@ static int s_show(struct seq_file *m, void *p)
if (v->flags & VM_VPAGES)
seq_printf(m, " vpages");
+ show_numa_info(m, v);
seq_putc(m, '\n');
return 0;
}
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 967d30ccd92..26672c6cd3c 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -38,6 +38,7 @@
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/memcontrol.h>
+#include <linux/delayacct.h>
#include <asm/tlbflush.h>
#include <asm/div64.h>
@@ -1316,6 +1317,8 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
struct zone *zone;
enum zone_type high_zoneidx = gfp_zone(sc->gfp_mask);
+ delayacct_freepages_start();
+
if (scan_global_lru(sc))
count_vm_event(ALLOCSTALL);
/*
@@ -1396,6 +1399,8 @@ out:
} else
mem_cgroup_record_reclaim_priority(sc->mem_cgroup, priority);
+ delayacct_freepages_end();
+
return ret;
}
diff --git a/mm/vmstat.c b/mm/vmstat.c
index db9eabb2c5b..b0d08e667ec 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -13,6 +13,7 @@
#include <linux/err.h>
#include <linux/module.h>
#include <linux/cpu.h>
+#include <linux/vmstat.h>
#include <linux/sched.h>
#ifdef CONFIG_VM_EVENT_COUNTERS
@@ -26,7 +27,7 @@ static void sum_vm_events(unsigned long *ret, cpumask_t *cpumask)
memset(ret, 0, NR_VM_EVENT_ITEMS * sizeof(unsigned long));
- for_each_cpu_mask(cpu, *cpumask) {
+ for_each_cpu_mask_nr(cpu, *cpumask) {
struct vm_event_state *this = &per_cpu(vm_event_states, cpu);
for (i = 0; i < NR_VM_EVENT_ITEMS; i++)
diff --git a/net/802/psnap.c b/net/802/psnap.c
index ea464393144..b3cfe5a14fc 100644
--- a/net/802/psnap.c
+++ b/net/802/psnap.c
@@ -31,11 +31,9 @@ static struct llc_sap *snap_sap;
*/
static struct datalink_proto *find_snap_client(unsigned char *desc)
{
- struct list_head *entry;
struct datalink_proto *proto = NULL, *p;
- list_for_each_rcu(entry, &snap_list) {
- p = list_entry(entry, struct datalink_proto, node);
+ list_for_each_entry_rcu(p, &snap_list, node) {
if (!memcmp(p->type, desc, 5)) {
proto = p;
break;
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index f42bc2b26b8..4bf014e51f8 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -569,6 +569,7 @@ static void vlan_dev_set_rx_mode(struct net_device *vlan_dev)
* separate class since they always nest.
*/
static struct lock_class_key vlan_netdev_xmit_lock_key;
+static struct lock_class_key vlan_netdev_addr_lock_key;
static void vlan_dev_set_lockdep_one(struct net_device *dev,
struct netdev_queue *txq,
@@ -581,6 +582,9 @@ static void vlan_dev_set_lockdep_one(struct net_device *dev,
static void vlan_dev_set_lockdep_class(struct net_device *dev, int subclass)
{
+ lockdep_set_class_and_subclass(&dev->addr_list_lock,
+ &vlan_netdev_addr_lock_key,
+ subclass);
netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass);
}
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index 4507f744f44..cdf137af7ad 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -1285,7 +1285,7 @@ static int p9_socket_open(struct p9_trans *trans, struct socket *csocket)
int fd, ret;
csocket->sk->sk_allocation = GFP_NOIO;
- fd = sock_map_fd(csocket);
+ fd = sock_map_fd(csocket, 0);
if (fd < 0) {
P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n");
return fd;
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 844ca5f1b2d..c85bf8f678d 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -398,10 +398,6 @@ int hci_register_sysfs(struct hci_dev *hdev)
if (device_create_file(dev, bt_attrs[i]) < 0)
BT_ERR("Failed to create device attribute");
- if (sysfs_create_link(&bt_class->subsys.kobj,
- &dev->kobj, kobject_name(&dev->kobj)) < 0)
- BT_ERR("Failed to create class symlink");
-
return 0;
}
@@ -409,9 +405,6 @@ void hci_unregister_sysfs(struct hci_dev *hdev)
{
BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
- sysfs_remove_link(&bt_class->subsys.kobj,
- kobject_name(&hdev->dev.kobj));
-
device_del(&hdev->dev);
}
diff --git a/net/compat.c b/net/compat.c
index 6e1b03b5193..67fb6a3834a 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -722,9 +722,10 @@ EXPORT_SYMBOL(compat_mc_getsockopt);
/* Argument list sizes for compat_sys_socketcall */
#define AL(x) ((x) * sizeof(u32))
-static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
+static unsigned char nas[19]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
- AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
+ AL(6),AL(2),AL(5),AL(5),AL(3),AL(3),
+ AL(6)};
#undef AL
asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags)
@@ -737,13 +738,52 @@ asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, uns
return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
}
+asmlinkage long compat_sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr,
+ int __user *upeer_addrlen,
+ const compat_sigset_t __user *sigmask,
+ compat_size_t sigsetsize, int flags)
+{
+ compat_sigset_t ss32;
+ sigset_t ksigmask, sigsaved;
+ int ret;
+
+ if (sigmask) {
+ if (sigsetsize != sizeof(compat_sigset_t))
+ return -EINVAL;
+ if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
+ return -EFAULT;
+ sigset_from_compat(&ksigmask, &ss32);
+
+ sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+ }
+
+ ret = do_accept(fd, upeer_sockaddr, upeer_addrlen, flags);
+
+ if (ret == -ERESTARTNOHAND) {
+ /*
+ * Don't restore the signal mask yet. Let do_signal() deliver
+ * the signal on the way back to userspace, before the signal
+ * mask is restored.
+ */
+ if (sigmask) {
+ memcpy(&current->saved_sigmask, &sigsaved,
+ sizeof(sigsaved));
+ set_restore_sigmask();
+ }
+ } else if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+ return ret;
+}
+
asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
{
int ret;
u32 a[6];
u32 a0, a1;
- if (call < SYS_SOCKET || call > SYS_RECVMSG)
+ if (call < SYS_SOCKET || call > SYS_PACCEPT)
return -EINVAL;
if (copy_from_user(a, args, nas[call]))
return -EFAULT;
@@ -764,7 +804,7 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
ret = sys_listen(a0, a1);
break;
case SYS_ACCEPT:
- ret = sys_accept(a0, compat_ptr(a1), compat_ptr(a[2]));
+ ret = do_accept(a0, compat_ptr(a1), compat_ptr(a[2]), 0);
break;
case SYS_GETSOCKNAME:
ret = sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2]));
@@ -804,6 +844,10 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
case SYS_RECVMSG:
ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]);
break;
+ case SYS_PACCEPT:
+ ret = compat_sys_paccept(a0, compat_ptr(a1), compat_ptr(a[2]),
+ compat_ptr(a[3]), a[4], a[5]);
+ break;
default:
ret = -EINVAL;
break;
diff --git a/net/core/dev.c b/net/core/dev.c
index cbc34c0db37..53af7841018 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -261,7 +261,7 @@ static RAW_NOTIFIER_HEAD(netdev_chain);
DEFINE_PER_CPU(struct softnet_data, softnet_data);
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
+#ifdef CONFIG_LOCKDEP
/*
* register_netdevice() inits txq->_xmit_lock and sets lockdep class
* according to dev->type
@@ -301,6 +301,7 @@ static const char *netdev_lock_name[] =
"_xmit_NONE"};
static struct lock_class_key netdev_xmit_lock_key[ARRAY_SIZE(netdev_lock_type)];
+static struct lock_class_key netdev_addr_lock_key[ARRAY_SIZE(netdev_lock_type)];
static inline unsigned short netdev_lock_pos(unsigned short dev_type)
{
@@ -313,8 +314,8 @@ static inline unsigned short netdev_lock_pos(unsigned short dev_type)
return ARRAY_SIZE(netdev_lock_type) - 1;
}
-static inline void netdev_set_lockdep_class(spinlock_t *lock,
- unsigned short dev_type)
+static inline void netdev_set_xmit_lockdep_class(spinlock_t *lock,
+ unsigned short dev_type)
{
int i;
@@ -322,9 +323,22 @@ static inline void netdev_set_lockdep_class(spinlock_t *lock,
lockdep_set_class_and_name(lock, &netdev_xmit_lock_key[i],
netdev_lock_name[i]);
}
+
+static inline void netdev_set_addr_lockdep_class(struct net_device *dev)
+{
+ int i;
+
+ i = netdev_lock_pos(dev->type);
+ lockdep_set_class_and_name(&dev->addr_list_lock,
+ &netdev_addr_lock_key[i],
+ netdev_lock_name[i]);
+}
#else
-static inline void netdev_set_lockdep_class(spinlock_t *lock,
- unsigned short dev_type)
+static inline void netdev_set_xmit_lockdep_class(spinlock_t *lock,
+ unsigned short dev_type)
+{
+}
+static inline void netdev_set_addr_lockdep_class(struct net_device *dev)
{
}
#endif
@@ -1327,9 +1341,6 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
void __netif_schedule(struct Qdisc *q)
{
- if (WARN_ON_ONCE(q == &noop_qdisc))
- return;
-
if (!test_and_set_bit(__QDISC_STATE_SCHED, &q->state)) {
struct softnet_data *sd;
unsigned long flags;
@@ -1645,32 +1656,6 @@ out_kfree_skb:
return 0;
}
-/**
- * dev_queue_xmit - transmit a buffer
- * @skb: buffer to transmit
- *
- * Queue a buffer for transmission to a network device. The caller must
- * have set the device and priority and built the buffer before calling
- * this function. The function can be called from an interrupt.
- *
- * A negative errno code is returned on a failure. A success does not
- * guarantee the frame will be transmitted as it may be dropped due
- * to congestion or traffic shaping.
- *
- * -----------------------------------------------------------------------------------
- * I notice this method can also return errors from the queue disciplines,
- * including NET_XMIT_DROP, which is a positive value. So, errors can also
- * be positive.
- *
- * Regardless of the return value, the skb is consumed, so it is currently
- * difficult to retry a send to this method. (You can bump the ref count
- * before sending to hold a reference for retry if you are careful.)
- *
- * When calling this method, interrupts MUST be enabled. This is because
- * the BH enable code must have IRQs enabled so that it will not deadlock.
- * --BLG
- */
-
static u32 simple_tx_hashrnd;
static int simple_tx_hashrnd_initialized = 0;
@@ -1738,6 +1723,31 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,
return netdev_get_tx_queue(dev, queue_index);
}
+/**
+ * dev_queue_xmit - transmit a buffer
+ * @skb: buffer to transmit
+ *
+ * Queue a buffer for transmission to a network device. The caller must
+ * have set the device and priority and built the buffer before calling
+ * this function. The function can be called from an interrupt.
+ *
+ * A negative errno code is returned on a failure. A success does not
+ * guarantee the frame will be transmitted as it may be dropped due
+ * to congestion or traffic shaping.
+ *
+ * -----------------------------------------------------------------------------------
+ * I notice this method can also return errors from the queue disciplines,
+ * including NET_XMIT_DROP, which is a positive value. So, errors can also
+ * be positive.
+ *
+ * Regardless of the return value, the skb is consumed, so it is currently
+ * difficult to retry a send to this method. (You can bump the ref count
+ * before sending to hold a reference for retry if you are careful.)
+ *
+ * When calling this method, interrupts MUST be enabled. This is because
+ * the BH enable code must have IRQs enabled so that it will not deadlock.
+ * --BLG
+ */
int dev_queue_xmit(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
@@ -2385,7 +2395,7 @@ out:
*/
if (!cpus_empty(net_dma.channel_mask)) {
int chan_idx;
- for_each_cpu_mask(chan_idx, net_dma.channel_mask) {
+ for_each_cpu_mask_nr(chan_idx, net_dma.channel_mask) {
struct dma_chan *chan = net_dma.channels[chan_idx];
if (chan)
dma_async_memcpy_issue_pending(chan);
@@ -3852,7 +3862,7 @@ static void __netdev_init_queue_locks_one(struct net_device *dev,
void *_unused)
{
spin_lock_init(&dev_queue->_xmit_lock);
- netdev_set_lockdep_class(&dev_queue->_xmit_lock, dev->type);
+ netdev_set_xmit_lockdep_class(&dev_queue->_xmit_lock, dev->type);
dev_queue->xmit_lock_owner = -1;
}
@@ -3897,6 +3907,7 @@ int register_netdevice(struct net_device *dev)
net = dev_net(dev);
spin_lock_init(&dev->addr_list_lock);
+ netdev_set_addr_lockdep_class(dev);
netdev_init_queue_locks(dev);
dev->iflink = -1;
@@ -4207,7 +4218,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
{
struct netdev_queue *tx;
struct net_device *dev;
- int alloc_size;
+ size_t alloc_size;
void *p;
BUG_ON(strlen(name) >= sizeof(dev->name));
@@ -4227,7 +4238,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
return NULL;
}
- tx = kzalloc(sizeof(struct netdev_queue) * queue_count, GFP_KERNEL);
+ tx = kcalloc(queue_count, sizeof(struct netdev_queue), GFP_KERNEL);
if (!tx) {
printk(KERN_ERR "alloc_netdev: Unable to allocate "
"tx qdiscs.\n");
@@ -4519,7 +4530,7 @@ static void net_dma_rebalance(struct net_dma *net_dma)
i = 0;
cpu = first_cpu(cpu_online_map);
- for_each_cpu_mask(chan_idx, net_dma->channel_mask) {
+ for_each_cpu_mask_nr(chan_idx, net_dma->channel_mask) {
chan = net_dma->channels[chan_idx];
n = ((num_online_cpus() / cpus_weight(net_dma->channel_mask))
@@ -4686,6 +4697,26 @@ err_name:
return -ENOMEM;
}
+char *netdev_drivername(struct net_device *dev, char *buffer, int len)
+{
+ struct device_driver *driver;
+ struct device *parent;
+
+ if (len <= 0 || !buffer)
+ return buffer;
+ buffer[0] = 0;
+
+ parent = dev->dev.parent;
+
+ if (!parent)
+ return buffer;
+
+ driver = parent->driver;
+ if (driver && driver->name)
+ strlcpy(buffer, driver->name, len);
+ return buffer;
+}
+
static void __net_exit netdev_exit(struct net *net)
{
kfree(net->dev_name_head);
diff --git a/net/core/sock.c b/net/core/sock.c
index 10a64d57078..91f8bbc9352 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -180,7 +180,7 @@ static const char *af_family_clock_key_strings[AF_MAX+1] = {
"clock-AF_ASH" , "clock-AF_ECONET" , "clock-AF_ATMSVC" ,
"clock-21" , "clock-AF_SNA" , "clock-AF_IRDA" ,
"clock-AF_PPPOX" , "clock-AF_WANPIPE" , "clock-AF_LLC" ,
- "clock-27" , "clock-28" , "clock-29" ,
+ "clock-27" , "clock-28" , "clock-AF_CAN" ,
"clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" ,
"clock-AF_RXRPC" , "clock-AF_MAX"
};
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index a570e2af22c..f686467ff12 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -67,7 +67,7 @@ static struct ctl_table net_core_table[] = {
{
.ctl_name = NET_CORE_MSG_COST,
.procname = "message_cost",
- .data = &net_msg_cost,
+ .data = &net_ratelimit_state.interval,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
@@ -76,7 +76,7 @@ static struct ctl_table net_core_table[] = {
{
.ctl_name = NET_CORE_MSG_BURST,
.procname = "message_burst",
- .data = &net_msg_burst,
+ .data = &net_ratelimit_state.burst,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
diff --git a/net/core/user_dma.c b/net/core/user_dma.c
index c77aff9c6eb..8c6b706963f 100644
--- a/net/core/user_dma.c
+++ b/net/core/user_dma.c
@@ -34,6 +34,7 @@
#define NET_DMA_DEFAULT_COPYBREAK 4096
int sysctl_tcp_dma_copybreak = NET_DMA_DEFAULT_COPYBREAK;
+EXPORT_SYMBOL(sysctl_tcp_dma_copybreak);
/**
* dma_skb_copy_datagram_iovec - Copy a datagram to an iovec.
diff --git a/net/core/utils.c b/net/core/utils.c
index 8031eb59054..72e0ebe964a 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -31,17 +31,16 @@
#include <asm/system.h>
#include <asm/uaccess.h>
-int net_msg_cost __read_mostly = 5*HZ;
-int net_msg_burst __read_mostly = 10;
int net_msg_warn __read_mostly = 1;
EXPORT_SYMBOL(net_msg_warn);
+DEFINE_RATELIMIT_STATE(net_ratelimit_state, 5 * HZ, 10);
/*
* All net warning printk()s should be guarded by this function.
*/
int net_ratelimit(void)
{
- return __printk_ratelimit(net_msg_cost, net_msg_burst);
+ return __ratelimit(&net_ratelimit_state);
}
EXPORT_SYMBOL(net_ratelimit);
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 4670683b468..591ea23639c 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -356,10 +356,8 @@ config INET_ESP
config INET_IPCOMP
tristate "IP: IPComp transformation"
- select XFRM
select INET_XFRM_TUNNEL
- select CRYPTO
- select CRYPTO_DEFLATE
+ select XFRM_IPCOMP
---help---
Support for IP Payload Compression Protocol (IPComp) (RFC3173),
typically needed for IPsec.
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index dd919d84285..f440a9f5492 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -264,7 +264,6 @@ static inline int inet_netns_ok(struct net *net, int protocol)
static int inet_create(struct net *net, struct socket *sock, int protocol)
{
struct sock *sk;
- struct list_head *p;
struct inet_protosw *answer;
struct inet_sock *inet;
struct proto *answer_prot;
@@ -281,13 +280,12 @@ static int inet_create(struct net *net, struct socket *sock, int protocol)
sock->state = SS_UNCONNECTED;
/* Look for the requested type/protocol pair. */
- answer = NULL;
lookup_protocol:
err = -ESOCKTNOSUPPORT;
rcu_read_lock();
- list_for_each_rcu(p, &inetsw[sock->type]) {
- answer = list_entry(p, struct inet_protosw, list);
+ list_for_each_entry_rcu(answer, &inetsw[sock->type], list) {
+ err = 0;
/* Check the non-wild match. */
if (protocol == answer->protocol) {
if (protocol != IPPROTO_IP)
@@ -302,10 +300,9 @@ lookup_protocol:
break;
}
err = -EPROTONOSUPPORT;
- answer = NULL;
}
- if (unlikely(answer == NULL)) {
+ if (unlikely(err)) {
if (try_loading_module < 2) {
rcu_read_unlock();
/*
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index a75807b971b..a42b64d040c 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -14,153 +14,14 @@
* - Adaptive compression.
*/
#include <linux/module.h>
-#include <linux/crypto.h>
#include <linux/err.h>
-#include <linux/pfkeyv2.h>
-#include <linux/percpu.h>
-#include <linux/smp.h>
-#include <linux/list.h>
-#include <linux/vmalloc.h>
#include <linux/rtnetlink.h>
-#include <linux/mutex.h>
#include <net/ip.h>
#include <net/xfrm.h>
#include <net/icmp.h>
#include <net/ipcomp.h>
#include <net/protocol.h>
-
-struct ipcomp_tfms {
- struct list_head list;
- struct crypto_comp **tfms;
- int users;
-};
-
-static DEFINE_MUTEX(ipcomp_resource_mutex);
-static void **ipcomp_scratches;
-static int ipcomp_scratch_users;
-static LIST_HEAD(ipcomp_tfms_list);
-
-static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
-{
- struct ipcomp_data *ipcd = x->data;
- const int plen = skb->len;
- int dlen = IPCOMP_SCRATCH_SIZE;
- const u8 *start = skb->data;
- const int cpu = get_cpu();
- u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
- struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu);
- int err = crypto_comp_decompress(tfm, start, plen, scratch, &dlen);
-
- if (err)
- goto out;
-
- if (dlen < (plen + sizeof(struct ip_comp_hdr))) {
- err = -EINVAL;
- goto out;
- }
-
- err = pskb_expand_head(skb, 0, dlen - plen, GFP_ATOMIC);
- if (err)
- goto out;
-
- skb->truesize += dlen - plen;
- __skb_put(skb, dlen - plen);
- skb_copy_to_linear_data(skb, scratch, dlen);
-out:
- put_cpu();
- return err;
-}
-
-static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
-{
- int nexthdr;
- int err = -ENOMEM;
- struct ip_comp_hdr *ipch;
-
- if (skb_linearize_cow(skb))
- goto out;
-
- skb->ip_summed = CHECKSUM_NONE;
-
- /* Remove ipcomp header and decompress original payload */
- ipch = (void *)skb->data;
- nexthdr = ipch->nexthdr;
-
- skb->transport_header = skb->network_header + sizeof(*ipch);
- __skb_pull(skb, sizeof(*ipch));
- err = ipcomp_decompress(x, skb);
- if (err)
- goto out;
-
- err = nexthdr;
-
-out:
- return err;
-}
-
-static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb)
-{
- struct ipcomp_data *ipcd = x->data;
- const int plen = skb->len;
- int dlen = IPCOMP_SCRATCH_SIZE;
- u8 *start = skb->data;
- const int cpu = get_cpu();
- u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
- struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu);
- int err;
-
- local_bh_disable();
- err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
- local_bh_enable();
- if (err)
- goto out;
-
- if ((dlen + sizeof(struct ip_comp_hdr)) >= plen) {
- err = -EMSGSIZE;
- goto out;
- }
-
- memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
- put_cpu();
-
- pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr));
- return 0;
-
-out:
- put_cpu();
- return err;
-}
-
-static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
-{
- int err;
- struct ip_comp_hdr *ipch;
- struct ipcomp_data *ipcd = x->data;
-
- if (skb->len < ipcd->threshold) {
- /* Don't bother compressing */
- goto out_ok;
- }
-
- if (skb_linearize_cow(skb))
- goto out_ok;
-
- err = ipcomp_compress(x, skb);
-
- if (err) {
- goto out_ok;
- }
-
- /* Install ipcomp header, convert into ipcomp datagram. */
- ipch = ip_comp_hdr(skb);
- ipch->nexthdr = *skb_mac_header(skb);
- ipch->flags = 0;
- ipch->cpi = htons((u16 )ntohl(x->id.spi));
- *skb_mac_header(skb) = IPPROTO_COMP;
-out_ok:
- skb_push(skb, -skb_network_offset(skb));
- return 0;
-}
+#include <net/sock.h>
static void ipcomp4_err(struct sk_buff *skb, u32 info)
{
@@ -241,156 +102,12 @@ out:
return err;
}
-static void ipcomp_free_scratches(void)
-{
- int i;
- void **scratches;
-
- if (--ipcomp_scratch_users)
- return;
-
- scratches = ipcomp_scratches;
- if (!scratches)
- return;
-
- for_each_possible_cpu(i)
- vfree(*per_cpu_ptr(scratches, i));
-
- free_percpu(scratches);
-}
-
-static void **ipcomp_alloc_scratches(void)
-{
- int i;
- void **scratches;
-
- if (ipcomp_scratch_users++)
- return ipcomp_scratches;
-
- scratches = alloc_percpu(void *);
- if (!scratches)
- return NULL;
-
- ipcomp_scratches = scratches;
-
- for_each_possible_cpu(i) {
- void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
- if (!scratch)
- return NULL;
- *per_cpu_ptr(scratches, i) = scratch;
- }
-
- return scratches;
-}
-
-static void ipcomp_free_tfms(struct crypto_comp **tfms)
-{
- struct ipcomp_tfms *pos;
- int cpu;
-
- list_for_each_entry(pos, &ipcomp_tfms_list, list) {
- if (pos->tfms == tfms)
- break;
- }
-
- BUG_TRAP(pos);
-
- if (--pos->users)
- return;
-
- list_del(&pos->list);
- kfree(pos);
-
- if (!tfms)
- return;
-
- for_each_possible_cpu(cpu) {
- struct crypto_comp *tfm = *per_cpu_ptr(tfms, cpu);
- crypto_free_comp(tfm);
- }
- free_percpu(tfms);
-}
-
-static struct crypto_comp **ipcomp_alloc_tfms(const char *alg_name)
-{
- struct ipcomp_tfms *pos;
- struct crypto_comp **tfms;
- int cpu;
-
- /* This can be any valid CPU ID so we don't need locking. */
- cpu = raw_smp_processor_id();
-
- list_for_each_entry(pos, &ipcomp_tfms_list, list) {
- struct crypto_comp *tfm;
-
- tfms = pos->tfms;
- tfm = *per_cpu_ptr(tfms, cpu);
-
- if (!strcmp(crypto_comp_name(tfm), alg_name)) {
- pos->users++;
- return tfms;
- }
- }
-
- pos = kmalloc(sizeof(*pos), GFP_KERNEL);
- if (!pos)
- return NULL;
-
- pos->users = 1;
- INIT_LIST_HEAD(&pos->list);
- list_add(&pos->list, &ipcomp_tfms_list);
-
- pos->tfms = tfms = alloc_percpu(struct crypto_comp *);
- if (!tfms)
- goto error;
-
- for_each_possible_cpu(cpu) {
- struct crypto_comp *tfm = crypto_alloc_comp(alg_name, 0,
- CRYPTO_ALG_ASYNC);
- if (IS_ERR(tfm))
- goto error;
- *per_cpu_ptr(tfms, cpu) = tfm;
- }
-
- return tfms;
-
-error:
- ipcomp_free_tfms(tfms);
- return NULL;
-}
-
-static void ipcomp_free_data(struct ipcomp_data *ipcd)
-{
- if (ipcd->tfms)
- ipcomp_free_tfms(ipcd->tfms);
- ipcomp_free_scratches();
-}
-
-static void ipcomp_destroy(struct xfrm_state *x)
-{
- struct ipcomp_data *ipcd = x->data;
- if (!ipcd)
- return;
- xfrm_state_delete_tunnel(x);
- mutex_lock(&ipcomp_resource_mutex);
- ipcomp_free_data(ipcd);
- mutex_unlock(&ipcomp_resource_mutex);
- kfree(ipcd);
-}
-
-static int ipcomp_init_state(struct xfrm_state *x)
+static int ipcomp4_init_state(struct xfrm_state *x)
{
int err;
struct ipcomp_data *ipcd;
struct xfrm_algo_desc *calg_desc;
- err = -EINVAL;
- if (!x->calg)
- goto out;
-
- if (x->encap)
- goto out;
-
x->props.header_len = 0;
switch (x->props.mode) {
case XFRM_MODE_TRANSPORT:
@@ -402,40 +119,22 @@ static int ipcomp_init_state(struct xfrm_state *x)
goto out;
}
- err = -ENOMEM;
- ipcd = kzalloc(sizeof(*ipcd), GFP_KERNEL);
- if (!ipcd)
+ err = ipcomp_init_state(x);
+ if (err)
goto out;
- mutex_lock(&ipcomp_resource_mutex);
- if (!ipcomp_alloc_scratches())
- goto error;
-
- ipcd->tfms = ipcomp_alloc_tfms(x->calg->alg_name);
- if (!ipcd->tfms)
- goto error;
- mutex_unlock(&ipcomp_resource_mutex);
-
if (x->props.mode == XFRM_MODE_TUNNEL) {
err = ipcomp_tunnel_attach(x);
if (err)
goto error_tunnel;
}
- calg_desc = xfrm_calg_get_byname(x->calg->alg_name, 0);
- BUG_ON(!calg_desc);
- ipcd->threshold = calg_desc->uinfo.comp.threshold;
- x->data = ipcd;
err = 0;
out:
return err;
error_tunnel:
- mutex_lock(&ipcomp_resource_mutex);
-error:
- ipcomp_free_data(ipcd);
- mutex_unlock(&ipcomp_resource_mutex);
- kfree(ipcd);
+ ipcomp_destroy(x);
goto out;
}
@@ -443,7 +142,7 @@ static const struct xfrm_type ipcomp_type = {
.description = "IPCOMP4",
.owner = THIS_MODULE,
.proto = IPPROTO_COMP,
- .init_state = ipcomp_init_state,
+ .init_state = ipcomp4_init_state,
.destructor = ipcomp_destroy,
.input = ipcomp_input,
.output = ipcomp_output
@@ -481,7 +180,7 @@ module_init(ipcomp4_init);
module_exit(ipcomp4_fini);
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) - RFC3173");
+MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp/IPv4) - RFC3173");
MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_COMP);
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index f23e60c93ef..90eb7cb47e7 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -369,7 +369,7 @@ config IP_NF_SECURITY
tristate "Security table"
depends on IP_NF_IPTABLES
depends on SECURITY
- default m if NETFILTER_ADVANCED=n
+ depends on NETFILTER_ADVANCED
help
This option adds a `security' table to iptables, for use
with Mandatory Access Control (MAC) policy.
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 1f5e6049883..75efd244f2a 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3292,6 +3292,7 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
* log. Something worked...
*/
sk->sk_err_soft = 0;
+ icsk->icsk_probes_out = 0;
tp->rcv_tstamp = tcp_time_stamp;
prior_packets = tp->packets_out;
if (!prior_packets)
@@ -3324,8 +3325,6 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
return 1;
no_queue:
- icsk->icsk_probes_out = 0;
-
/* If this ack opens up a zero window, clear backoff. It was
* being used to time the probes, and is probably far higher than
* it needs to be for normal retransmission.
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 1fa683c0ba9..a00532de2a8 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -472,7 +472,7 @@ static unsigned tcp_syn_options(struct sock *sk, struct sk_buff *skb,
}
if (likely(sysctl_tcp_sack)) {
opts->options |= OPTION_SACK_ADVERTISE;
- if (unlikely(!OPTION_TS & opts->options))
+ if (unlikely(!(OPTION_TS & opts->options)))
size += TCPOLEN_SACKPERM_ALIGNED;
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index a751770947a..383d17359d0 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1325,6 +1325,8 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
return -ENOPROTOOPT;
if (val != 0 && val < 8) /* Illegal coverage: use default (8) */
val = 8;
+ else if (val > USHORT_MAX)
+ val = USHORT_MAX;
up->pcslen = val;
up->pcflag |= UDPLITE_SEND_CC;
break;
@@ -1337,6 +1339,8 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
return -ENOPROTOOPT;
if (val != 0 && val < 8) /* Avoid silly minimal values. */
val = 8;
+ else if (val > USHORT_MAX)
+ val = USHORT_MAX;
up->pcrlen = val;
up->pcflag |= UDPLITE_RECV_CC;
break;
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 42814a2ec9d..ec992159b5f 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -96,10 +96,8 @@ config INET6_ESP
config INET6_IPCOMP
tristate "IPv6: IPComp transformation"
- select XFRM
select INET6_XFRM_TUNNEL
- select CRYPTO
- select CRYPTO_DEFLATE
+ select XFRM_IPCOMP
---help---
Support for IP Payload Compression Protocol (IPComp) (RFC3173),
typically needed for IPsec.
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 9f4fcce6379..74d543d504a 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -153,7 +153,7 @@ static int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
-struct ipv6_devconf ipv6_devconf __read_mostly = {
+static struct ipv6_devconf ipv6_devconf __read_mostly = {
.forwarding = 0,
.hop_limit = IPV6_DEFAULT_HOPLIMIT,
.mtu6 = IPV6_MIN_MTU,
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 3d828bc4b1c..60461ad7fa6 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -83,7 +83,6 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol)
struct inet_sock *inet;
struct ipv6_pinfo *np;
struct sock *sk;
- struct list_head *p;
struct inet_protosw *answer;
struct proto *answer_prot;
unsigned char answer_flags;
@@ -97,13 +96,12 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol)
build_ehash_secret();
/* Look for the requested type/protocol pair. */
- answer = NULL;
lookup_protocol:
err = -ESOCKTNOSUPPORT;
rcu_read_lock();
- list_for_each_rcu(p, &inetsw6[sock->type]) {
- answer = list_entry(p, struct inet_protosw, list);
+ list_for_each_entry_rcu(answer, &inetsw6[sock->type], list) {
+ err = 0;
/* Check the non-wild match. */
if (protocol == answer->protocol) {
if (protocol != IPPROTO_IP)
@@ -118,10 +116,9 @@ lookup_protocol:
break;
}
err = -EPROTONOSUPPORT;
- answer = NULL;
}
- if (!answer) {
+ if (err) {
if (try_loading_module < 2) {
rcu_read_unlock();
/*
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 4de2b9efcac..08ea2de28d6 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -661,17 +661,17 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
static __inline__ void fib6_start_gc(struct net *net, struct rt6_info *rt)
{
- if (net->ipv6.ip6_fib_timer->expires == 0 &&
+ if (!timer_pending(&net->ipv6.ip6_fib_timer) &&
(rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE)))
- mod_timer(net->ipv6.ip6_fib_timer, jiffies +
- net->ipv6.sysctl.ip6_rt_gc_interval);
+ mod_timer(&net->ipv6.ip6_fib_timer,
+ jiffies + net->ipv6.sysctl.ip6_rt_gc_interval);
}
void fib6_force_start_gc(struct net *net)
{
- if (net->ipv6.ip6_fib_timer->expires == 0)
- mod_timer(net->ipv6.ip6_fib_timer, jiffies +
- net->ipv6.sysctl.ip6_rt_gc_interval);
+ if (!timer_pending(&net->ipv6.ip6_fib_timer))
+ mod_timer(&net->ipv6.ip6_fib_timer,
+ jiffies + net->ipv6.sysctl.ip6_rt_gc_interval);
}
/*
@@ -1447,27 +1447,23 @@ void fib6_run_gc(unsigned long expires, struct net *net)
gc_args.timeout = expires ? (int)expires :
net->ipv6.sysctl.ip6_rt_gc_interval;
} else {
- local_bh_disable();
- if (!spin_trylock(&fib6_gc_lock)) {
- mod_timer(net->ipv6.ip6_fib_timer, jiffies + HZ);
- local_bh_enable();
+ if (!spin_trylock_bh(&fib6_gc_lock)) {
+ mod_timer(&net->ipv6.ip6_fib_timer, jiffies + HZ);
return;
}
gc_args.timeout = net->ipv6.sysctl.ip6_rt_gc_interval;
}
- gc_args.more = 0;
- icmp6_dst_gc(&gc_args.more);
+ gc_args.more = icmp6_dst_gc();
fib6_clean_all(net, fib6_age, 0, NULL);
if (gc_args.more)
- mod_timer(net->ipv6.ip6_fib_timer, jiffies +
- net->ipv6.sysctl.ip6_rt_gc_interval);
- else {
- del_timer(net->ipv6.ip6_fib_timer);
- net->ipv6.ip6_fib_timer->expires = 0;
- }
+ mod_timer(&net->ipv6.ip6_fib_timer,
+ round_jiffies(jiffies
+ + net->ipv6.sysctl.ip6_rt_gc_interval));
+ else
+ del_timer(&net->ipv6.ip6_fib_timer);
spin_unlock_bh(&fib6_gc_lock);
}
@@ -1478,24 +1474,15 @@ static void fib6_gc_timer_cb(unsigned long arg)
static int fib6_net_init(struct net *net)
{
- int ret;
- struct timer_list *timer;
-
- ret = -ENOMEM;
- timer = kzalloc(sizeof(*timer), GFP_KERNEL);
- if (!timer)
- goto out;
-
- setup_timer(timer, fib6_gc_timer_cb, (unsigned long)net);
- net->ipv6.ip6_fib_timer = timer;
+ setup_timer(&net->ipv6.ip6_fib_timer, fib6_gc_timer_cb, (unsigned long)net);
net->ipv6.rt6_stats = kzalloc(sizeof(*net->ipv6.rt6_stats), GFP_KERNEL);
if (!net->ipv6.rt6_stats)
goto out_timer;
- net->ipv6.fib_table_hash =
- kzalloc(sizeof(*net->ipv6.fib_table_hash)*FIB_TABLE_HASHSZ,
- GFP_KERNEL);
+ net->ipv6.fib_table_hash = kcalloc(FIB_TABLE_HASHSZ,
+ sizeof(*net->ipv6.fib_table_hash),
+ GFP_KERNEL);
if (!net->ipv6.fib_table_hash)
goto out_rt6_stats;
@@ -1521,9 +1508,7 @@ static int fib6_net_init(struct net *net)
#endif
fib6_tables_init(net);
- ret = 0;
-out:
- return ret;
+ return 0;
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
out_fib6_main_tbl:
@@ -1534,15 +1519,14 @@ out_fib_table_hash:
out_rt6_stats:
kfree(net->ipv6.rt6_stats);
out_timer:
- kfree(timer);
- goto out;
+ return -ENOMEM;
}
static void fib6_net_exit(struct net *net)
{
rt6_ifdown(net, NULL);
- del_timer_sync(net->ipv6.ip6_fib_timer);
- kfree(net->ipv6.ip6_fib_timer);
+ del_timer_sync(&net->ipv6.ip6_fib_timer);
+
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
kfree(net->ipv6.fib6_local_tbl);
#endif
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index ee6de425ce6..0cfcea42153 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -50,125 +50,6 @@
#include <linux/icmpv6.h>
#include <linux/mutex.h>
-struct ipcomp6_tfms {
- struct list_head list;
- struct crypto_comp **tfms;
- int users;
-};
-
-static DEFINE_MUTEX(ipcomp6_resource_mutex);
-static void **ipcomp6_scratches;
-static int ipcomp6_scratch_users;
-static LIST_HEAD(ipcomp6_tfms_list);
-
-static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
-{
- int nexthdr;
- int err = -ENOMEM;
- struct ip_comp_hdr *ipch;
- int plen, dlen;
- struct ipcomp_data *ipcd = x->data;
- u8 *start, *scratch;
- struct crypto_comp *tfm;
- int cpu;
-
- if (skb_linearize_cow(skb))
- goto out;
-
- skb->ip_summed = CHECKSUM_NONE;
-
- /* Remove ipcomp header and decompress original payload */
- ipch = (void *)skb->data;
- nexthdr = ipch->nexthdr;
-
- skb->transport_header = skb->network_header + sizeof(*ipch);
- __skb_pull(skb, sizeof(*ipch));
-
- /* decompression */
- plen = skb->len;
- dlen = IPCOMP_SCRATCH_SIZE;
- start = skb->data;
-
- cpu = get_cpu();
- scratch = *per_cpu_ptr(ipcomp6_scratches, cpu);
- tfm = *per_cpu_ptr(ipcd->tfms, cpu);
-
- err = crypto_comp_decompress(tfm, start, plen, scratch, &dlen);
- if (err)
- goto out_put_cpu;
-
- if (dlen < (plen + sizeof(*ipch))) {
- err = -EINVAL;
- goto out_put_cpu;
- }
-
- err = pskb_expand_head(skb, 0, dlen - plen, GFP_ATOMIC);
- if (err) {
- goto out_put_cpu;
- }
-
- skb->truesize += dlen - plen;
- __skb_put(skb, dlen - plen);
- skb_copy_to_linear_data(skb, scratch, dlen);
- err = nexthdr;
-
-out_put_cpu:
- put_cpu();
-out:
- return err;
-}
-
-static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
-{
- int err;
- struct ip_comp_hdr *ipch;
- struct ipcomp_data *ipcd = x->data;
- int plen, dlen;
- u8 *start, *scratch;
- struct crypto_comp *tfm;
- int cpu;
-
- /* check whether datagram len is larger than threshold */
- if (skb->len < ipcd->threshold) {
- goto out_ok;
- }
-
- if (skb_linearize_cow(skb))
- goto out_ok;
-
- /* compression */
- plen = skb->len;
- dlen = IPCOMP_SCRATCH_SIZE;
- start = skb->data;
-
- cpu = get_cpu();
- scratch = *per_cpu_ptr(ipcomp6_scratches, cpu);
- tfm = *per_cpu_ptr(ipcd->tfms, cpu);
-
- local_bh_disable();
- err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
- local_bh_enable();
- if (err || (dlen + sizeof(*ipch)) >= plen) {
- put_cpu();
- goto out_ok;
- }
- memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
- put_cpu();
- pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr));
-
- /* insert ipcomp header and replace datagram */
- ipch = ip_comp_hdr(skb);
- ipch->nexthdr = *skb_mac_header(skb);
- ipch->flags = 0;
- ipch->cpi = htons((u16 )ntohl(x->id.spi));
- *skb_mac_header(skb) = IPPROTO_COMP;
-
-out_ok:
- skb_push(skb, -skb_network_offset(skb));
-
- return 0;
-}
-
static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
int type, int code, int offset, __be32 info)
{
@@ -251,161 +132,12 @@ out:
return err;
}
-static void ipcomp6_free_scratches(void)
-{
- int i;
- void **scratches;
-
- if (--ipcomp6_scratch_users)
- return;
-
- scratches = ipcomp6_scratches;
- if (!scratches)
- return;
-
- for_each_possible_cpu(i) {
- void *scratch = *per_cpu_ptr(scratches, i);
-
- vfree(scratch);
- }
-
- free_percpu(scratches);
-}
-
-static void **ipcomp6_alloc_scratches(void)
-{
- int i;
- void **scratches;
-
- if (ipcomp6_scratch_users++)
- return ipcomp6_scratches;
-
- scratches = alloc_percpu(void *);
- if (!scratches)
- return NULL;
-
- ipcomp6_scratches = scratches;
-
- for_each_possible_cpu(i) {
- void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
- if (!scratch)
- return NULL;
- *per_cpu_ptr(scratches, i) = scratch;
- }
-
- return scratches;
-}
-
-static void ipcomp6_free_tfms(struct crypto_comp **tfms)
-{
- struct ipcomp6_tfms *pos;
- int cpu;
-
- list_for_each_entry(pos, &ipcomp6_tfms_list, list) {
- if (pos->tfms == tfms)
- break;
- }
-
- BUG_TRAP(pos);
-
- if (--pos->users)
- return;
-
- list_del(&pos->list);
- kfree(pos);
-
- if (!tfms)
- return;
-
- for_each_possible_cpu(cpu) {
- struct crypto_comp *tfm = *per_cpu_ptr(tfms, cpu);
- crypto_free_comp(tfm);
- }
- free_percpu(tfms);
-}
-
-static struct crypto_comp **ipcomp6_alloc_tfms(const char *alg_name)
-{
- struct ipcomp6_tfms *pos;
- struct crypto_comp **tfms;
- int cpu;
-
- /* This can be any valid CPU ID so we don't need locking. */
- cpu = raw_smp_processor_id();
-
- list_for_each_entry(pos, &ipcomp6_tfms_list, list) {
- struct crypto_comp *tfm;
-
- tfms = pos->tfms;
- tfm = *per_cpu_ptr(tfms, cpu);
-
- if (!strcmp(crypto_comp_name(tfm), alg_name)) {
- pos->users++;
- return tfms;
- }
- }
-
- pos = kmalloc(sizeof(*pos), GFP_KERNEL);
- if (!pos)
- return NULL;
-
- pos->users = 1;
- INIT_LIST_HEAD(&pos->list);
- list_add(&pos->list, &ipcomp6_tfms_list);
-
- pos->tfms = tfms = alloc_percpu(struct crypto_comp *);
- if (!tfms)
- goto error;
-
- for_each_possible_cpu(cpu) {
- struct crypto_comp *tfm = crypto_alloc_comp(alg_name, 0,
- CRYPTO_ALG_ASYNC);
- if (IS_ERR(tfm))
- goto error;
- *per_cpu_ptr(tfms, cpu) = tfm;
- }
-
- return tfms;
-
-error:
- ipcomp6_free_tfms(tfms);
- return NULL;
-}
-
-static void ipcomp6_free_data(struct ipcomp_data *ipcd)
-{
- if (ipcd->tfms)
- ipcomp6_free_tfms(ipcd->tfms);
- ipcomp6_free_scratches();
-}
-
-static void ipcomp6_destroy(struct xfrm_state *x)
-{
- struct ipcomp_data *ipcd = x->data;
- if (!ipcd)
- return;
- xfrm_state_delete_tunnel(x);
- mutex_lock(&ipcomp6_resource_mutex);
- ipcomp6_free_data(ipcd);
- mutex_unlock(&ipcomp6_resource_mutex);
- kfree(ipcd);
-
- xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr);
-}
-
static int ipcomp6_init_state(struct xfrm_state *x)
{
int err;
struct ipcomp_data *ipcd;
struct xfrm_algo_desc *calg_desc;
- err = -EINVAL;
- if (!x->calg)
- goto out;
-
- if (x->encap)
- goto out;
-
x->props.header_len = 0;
switch (x->props.mode) {
case XFRM_MODE_TRANSPORT:
@@ -417,39 +149,21 @@ static int ipcomp6_init_state(struct xfrm_state *x)
goto out;
}
- err = -ENOMEM;
- ipcd = kzalloc(sizeof(*ipcd), GFP_KERNEL);
- if (!ipcd)
+ err = ipcomp_init_state(x);
+ if (err)
goto out;
- mutex_lock(&ipcomp6_resource_mutex);
- if (!ipcomp6_alloc_scratches())
- goto error;
-
- ipcd->tfms = ipcomp6_alloc_tfms(x->calg->alg_name);
- if (!ipcd->tfms)
- goto error;
- mutex_unlock(&ipcomp6_resource_mutex);
-
if (x->props.mode == XFRM_MODE_TUNNEL) {
err = ipcomp6_tunnel_attach(x);
if (err)
goto error_tunnel;
}
- calg_desc = xfrm_calg_get_byname(x->calg->alg_name, 0);
- BUG_ON(!calg_desc);
- ipcd->threshold = calg_desc->uinfo.comp.threshold;
- x->data = ipcd;
err = 0;
out:
return err;
error_tunnel:
- mutex_lock(&ipcomp6_resource_mutex);
-error:
- ipcomp6_free_data(ipcd);
- mutex_unlock(&ipcomp6_resource_mutex);
- kfree(ipcd);
+ ipcomp_destroy(x);
goto out;
}
@@ -460,9 +174,9 @@ static const struct xfrm_type ipcomp6_type =
.owner = THIS_MODULE,
.proto = IPPROTO_COMP,
.init_state = ipcomp6_init_state,
- .destructor = ipcomp6_destroy,
- .input = ipcomp6_input,
- .output = ipcomp6_output,
+ .destructor = ipcomp_destroy,
+ .input = ipcomp_input,
+ .output = ipcomp_output,
.hdr_offset = xfrm6_find_1stfragopt,
};
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 689dec899c5..0cfcce7b18d 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -213,7 +213,7 @@ config IP6_NF_SECURITY
tristate "Security table"
depends on IP6_NF_IPTABLES
depends on SECURITY
- default m if NETFILTER_ADVANCED=n
+ depends on NETFILTER_ADVANCED
help
This option adds a `security' table to iptables, for use
with Mandatory Access Control (MAC) policy.
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 615b328de25..86540b24b27 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -978,13 +978,12 @@ out:
return &rt->u.dst;
}
-int icmp6_dst_gc(int *more)
+int icmp6_dst_gc(void)
{
struct dst_entry *dst, *next, **pprev;
- int freed;
+ int more = 0;
next = NULL;
- freed = 0;
spin_lock_bh(&icmp6_dst_lock);
pprev = &icmp6_dst_gc_list;
@@ -993,16 +992,15 @@ int icmp6_dst_gc(int *more)
if (!atomic_read(&dst->__refcnt)) {
*pprev = dst->next;
dst_free(dst);
- freed++;
} else {
pprev = &dst->next;
- (*more)++;
+ ++more;
}
}
spin_unlock_bh(&icmp6_dst_lock);
- return freed;
+ return more;
}
static int ip6_dst_gc(struct dst_ops *ops)
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index 265b1b289a3..705959b31e2 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -497,7 +497,7 @@ static void iucv_setmask_up(void)
/* Disable all cpu but the first in cpu_irq_cpumask. */
cpumask = iucv_irq_cpumask;
cpu_clear(first_cpu(iucv_irq_cpumask), cpumask);
- for_each_cpu_mask(cpu, cpumask)
+ for_each_cpu_mask_nr(cpu, cpumask)
smp_call_function_single(cpu, iucv_block_cpu, NULL, 1);
}
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index fccc250f95f..532e4faa29f 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -73,6 +73,7 @@ static const struct proto_ops nr_proto_ops;
* separate class since they always nest.
*/
static struct lock_class_key nr_netdev_xmit_lock_key;
+static struct lock_class_key nr_netdev_addr_lock_key;
static void nr_set_lockdep_one(struct net_device *dev,
struct netdev_queue *txq,
@@ -83,6 +84,7 @@ static void nr_set_lockdep_one(struct net_device *dev,
static void nr_set_lockdep_key(struct net_device *dev)
{
+ lockdep_set_class(&dev->addr_list_lock, &nr_netdev_addr_lock_key);
netdev_for_each_tx_queue(dev, nr_set_lockdep_one, NULL);
}
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index dbc963b4f5f..a7f1ce11bc2 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -74,6 +74,7 @@ ax25_address rose_callsign;
* separate class since they always nest.
*/
static struct lock_class_key rose_netdev_xmit_lock_key;
+static struct lock_class_key rose_netdev_addr_lock_key;
static void rose_set_lockdep_one(struct net_device *dev,
struct netdev_queue *txq,
@@ -84,6 +85,7 @@ static void rose_set_lockdep_one(struct net_device *dev,
static void rose_set_lockdep_key(struct net_device *dev)
{
+ lockdep_set_class(&dev->addr_list_lock, &rose_netdev_addr_lock_key);
netdev_for_each_tx_queue(dev, rose_set_lockdep_one, NULL);
}
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 5219d5f9d75..b0601642e22 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -447,7 +447,7 @@ void qdisc_watchdog_cancel(struct qdisc_watchdog *wd)
}
EXPORT_SYMBOL(qdisc_watchdog_cancel);
-struct hlist_head *qdisc_class_hash_alloc(unsigned int n)
+static struct hlist_head *qdisc_class_hash_alloc(unsigned int n)
{
unsigned int size = n * sizeof(struct hlist_head), i;
struct hlist_head *h;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index cb625b4d6da..43abd4d27ea 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -212,9 +212,9 @@ static void dev_watchdog(unsigned long arg)
if (some_queue_stopped &&
time_after(jiffies, (dev->trans_start +
dev->watchdog_timeo))) {
- printk(KERN_INFO "NETDEV WATCHDOG: %s: "
- "transmit timed out\n",
- dev->name);
+ char drivername[64];
+ printk(KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit timed out\n",
+ dev->name, netdev_drivername(dev, drivername, 64));
dev->tx_timeout(dev);
WARN_ON_ONCE(1);
}
@@ -736,9 +736,9 @@ static void shutdown_scheduler_queue(struct net_device *dev,
dev_queue->qdisc = qdisc_default;
dev_queue->qdisc_sleeping = qdisc_default;
- spin_lock(root_lock);
+ spin_lock_bh(root_lock);
qdisc_destroy(qdisc);
- spin_unlock(root_lock);
+ spin_unlock_bh(root_lock);
}
}
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 8589da66656..73f53844ce9 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -536,7 +536,14 @@ static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb)
opt.limit = q->limit;
opt.divisor = SFQ_HASH_DIVISOR;
- opt.flows = q->limit;
+ opt.flows = 0;
+ if (q->tail != SFQ_DEPTH) {
+ unsigned int i;
+
+ for (i = 0; i < SFQ_HASH_DIVISOR; i++)
+ if (q->ht[i] != SFQ_DEPTH)
+ opt.flows++;
+ }
NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 70ead8dc348..4328ad5439c 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -71,6 +71,8 @@ static void sctp_mark_missing(struct sctp_outq *q,
static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 sack_ctsn);
+static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout);
+
/* Add data to the front of the queue. */
static inline void sctp_outq_head_data(struct sctp_outq *q,
struct sctp_chunk *ch)
@@ -712,7 +714,7 @@ int sctp_outq_uncork(struct sctp_outq *q)
* locking concerns must be made. Today we use the sock lock to protect
* this function.
*/
-int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
+static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
{
struct sctp_packet *packet;
struct sctp_packet singleton;
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 5dd89831ece..f268910620b 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -519,8 +519,3 @@ int __init sctp_remaddr_proc_init(void)
return 0;
}
-
-void sctp_assoc_proc_exit(void)
-{
- remove_proc_entry("remaddr", proc_net_sctp);
-}
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 79bece16aed..dbb79adf8f3 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3910,7 +3910,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval
goto out;
/* Map the socket to an unused fd that can be returned to the user. */
- retval = sock_map_fd(newsock);
+ retval = sock_map_fd(newsock, 0);
if (retval < 0) {
sock_release(newsock);
goto out;
diff --git a/net/socket.c b/net/socket.c
index 1ba57d88898..1310a82cbba 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -63,11 +63,13 @@
#include <linux/file.h>
#include <linux/net.h>
#include <linux/interrupt.h>
+#include <linux/thread_info.h>
#include <linux/rcupdate.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/mutex.h>
+#include <linux/thread_info.h>
#include <linux/wanrouter.h>
#include <linux/if_bridge.h>
#include <linux/if_frad.h>
@@ -349,11 +351,11 @@ static struct dentry_operations sockfs_dentry_operations = {
* but we take care of internal coherence yet.
*/
-static int sock_alloc_fd(struct file **filep)
+static int sock_alloc_fd(struct file **filep, int flags)
{
int fd;
- fd = get_unused_fd();
+ fd = get_unused_fd_flags(flags);
if (likely(fd >= 0)) {
struct file *file = get_empty_filp();
@@ -367,7 +369,7 @@ static int sock_alloc_fd(struct file **filep)
return fd;
}
-static int sock_attach_fd(struct socket *sock, struct file *file)
+static int sock_attach_fd(struct socket *sock, struct file *file, int flags)
{
struct dentry *dentry;
struct qstr name = { .name = "" };
@@ -389,20 +391,20 @@ static int sock_attach_fd(struct socket *sock, struct file *file)
init_file(file, sock_mnt, dentry, FMODE_READ | FMODE_WRITE,
&socket_file_ops);
SOCK_INODE(sock)->i_fop = &socket_file_ops;
- file->f_flags = O_RDWR;
+ file->f_flags = O_RDWR | (flags & O_NONBLOCK);
file->f_pos = 0;
file->private_data = sock;
return 0;
}
-int sock_map_fd(struct socket *sock)
+int sock_map_fd(struct socket *sock, int flags)
{
struct file *newfile;
- int fd = sock_alloc_fd(&newfile);
+ int fd = sock_alloc_fd(&newfile, flags);
if (likely(fd >= 0)) {
- int err = sock_attach_fd(sock, newfile);
+ int err = sock_attach_fd(sock, newfile, flags);
if (unlikely(err < 0)) {
put_filp(newfile);
@@ -1218,12 +1220,27 @@ asmlinkage long sys_socket(int family, int type, int protocol)
{
int retval;
struct socket *sock;
+ int flags;
+
+ /* Check the SOCK_* constants for consistency. */
+ BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
+ BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
+ BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
+ BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
+
+ flags = type & ~SOCK_TYPE_MASK;
+ if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
+ return -EINVAL;
+ type &= SOCK_TYPE_MASK;
+
+ if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
+ flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
retval = sock_create(family, type, protocol, &sock);
if (retval < 0)
goto out;
- retval = sock_map_fd(sock);
+ retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
if (retval < 0)
goto out_release;
@@ -1246,6 +1263,15 @@ asmlinkage long sys_socketpair(int family, int type, int protocol,
struct socket *sock1, *sock2;
int fd1, fd2, err;
struct file *newfile1, *newfile2;
+ int flags;
+
+ flags = type & ~SOCK_TYPE_MASK;
+ if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
+ return -EINVAL;
+ type &= SOCK_TYPE_MASK;
+
+ if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
+ flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
/*
* Obtain the first socket and check if the underlying protocol
@@ -1264,13 +1290,13 @@ asmlinkage long sys_socketpair(int family, int type, int protocol,
if (err < 0)
goto out_release_both;
- fd1 = sock_alloc_fd(&newfile1);
+ fd1 = sock_alloc_fd(&newfile1, flags & O_CLOEXEC);
if (unlikely(fd1 < 0)) {
err = fd1;
goto out_release_both;
}
- fd2 = sock_alloc_fd(&newfile2);
+ fd2 = sock_alloc_fd(&newfile2, flags & O_CLOEXEC);
if (unlikely(fd2 < 0)) {
err = fd2;
put_filp(newfile1);
@@ -1278,12 +1304,12 @@ asmlinkage long sys_socketpair(int family, int type, int protocol,
goto out_release_both;
}
- err = sock_attach_fd(sock1, newfile1);
+ err = sock_attach_fd(sock1, newfile1, flags & O_NONBLOCK);
if (unlikely(err < 0)) {
goto out_fd2;
}
- err = sock_attach_fd(sock2, newfile2);
+ err = sock_attach_fd(sock2, newfile2, flags & O_NONBLOCK);
if (unlikely(err < 0)) {
fput(newfile1);
goto out_fd1;
@@ -1401,14 +1427,20 @@ asmlinkage long sys_listen(int fd, int backlog)
* clean when we restucture accept also.
*/
-asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
- int __user *upeer_addrlen)
+long do_accept(int fd, struct sockaddr __user *upeer_sockaddr,
+ int __user *upeer_addrlen, int flags)
{
struct socket *sock, *newsock;
struct file *newfile;
int err, len, newfd, fput_needed;
struct sockaddr_storage address;
+ if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
+ return -EINVAL;
+
+ if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
+ flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
+
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock)
goto out;
@@ -1426,14 +1458,14 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
*/
__module_get(newsock->ops->owner);
- newfd = sock_alloc_fd(&newfile);
+ newfd = sock_alloc_fd(&newfile, flags & O_CLOEXEC);
if (unlikely(newfd < 0)) {
err = newfd;
sock_release(newsock);
goto out_put;
}
- err = sock_attach_fd(newsock, newfile);
+ err = sock_attach_fd(newsock, newfile, flags & O_NONBLOCK);
if (err < 0)
goto out_fd_simple;
@@ -1479,6 +1511,66 @@ out_fd:
goto out_put;
}
+#ifdef HAVE_SET_RESTORE_SIGMASK
+asmlinkage long sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr,
+ int __user *upeer_addrlen,
+ const sigset_t __user *sigmask,
+ size_t sigsetsize, int flags)
+{
+ sigset_t ksigmask, sigsaved;
+ int ret;
+
+ if (sigmask) {
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+ if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
+ return -EFAULT;
+
+ sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+ }
+
+ ret = do_accept(fd, upeer_sockaddr, upeer_addrlen, flags);
+
+ if (ret < 0 && signal_pending(current)) {
+ /*
+ * Don't restore the signal mask yet. Let do_signal() deliver
+ * the signal on the way back to userspace, before the signal
+ * mask is restored.
+ */
+ if (sigmask) {
+ memcpy(&current->saved_sigmask, &sigsaved,
+ sizeof(sigsaved));
+ set_restore_sigmask();
+ }
+ } else if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+ return ret;
+}
+#else
+asmlinkage long sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr,
+ int __user *upeer_addrlen,
+ const sigset_t __user *sigmask,
+ size_t sigsetsize, int flags)
+{
+ /* The platform does not support restoring the signal mask in the
+ * return path. So we do not allow using paccept() with a signal
+ * mask. */
+ if (sigmask)
+ return -EINVAL;
+
+ return do_accept(fd, upeer_sockaddr, upeer_addrlen, flags);
+}
+#endif
+
+asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
+ int __user *upeer_addrlen)
+{
+ return do_accept(fd, upeer_sockaddr, upeer_addrlen, 0);
+}
+
/*
* Attempt to connect to a socket with the server address. The address
* is in user space so we verify it is OK and move it to kernel space.
@@ -1999,10 +2091,11 @@ out:
/* Argument list sizes for sys_socketcall */
#define AL(x) ((x) * sizeof(unsigned long))
-static const unsigned char nargs[18]={
+static const unsigned char nargs[19]={
AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
- AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)
+ AL(6),AL(2),AL(5),AL(5),AL(3),AL(3),
+ AL(6)
};
#undef AL
@@ -2021,7 +2114,7 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args)
unsigned long a0, a1;
int err;
- if (call < 1 || call > SYS_RECVMSG)
+ if (call < 1 || call > SYS_PACCEPT)
return -EINVAL;
/* copy_from_user should be SMP safe. */
@@ -2050,8 +2143,8 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args)
break;
case SYS_ACCEPT:
err =
- sys_accept(a0, (struct sockaddr __user *)a1,
- (int __user *)a[2]);
+ do_accept(a0, (struct sockaddr __user *)a1,
+ (int __user *)a[2], 0);
break;
case SYS_GETSOCKNAME:
err =
@@ -2098,6 +2191,13 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args)
case SYS_RECVMSG:
err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
break;
+ case SYS_PACCEPT:
+ err =
+ sys_paccept(a0, (struct sockaddr __user *)a1,
+ (int __user *)a[2],
+ (const sigset_t __user *) a[3],
+ a[4], a[5]);
+ break;
default:
err = -EINVAL;
break;
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 5a32cb7c4bb..835d2741308 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -310,7 +310,8 @@ svc_pool_map_set_cpumask(struct task_struct *task, unsigned int pidx)
switch (m->mode) {
case SVC_POOL_PERCPU:
{
- set_cpus_allowed_ptr(task, &cpumask_of_cpu(node));
+ cpumask_of_cpu_ptr(cpumask, node);
+ set_cpus_allowed_ptr(task, cpumask);
break;
}
case SVC_POOL_PERNODE:
diff --git a/net/sysctl_net.c b/net/sysctl_net.c
index 007c1a6708e..63ada437fc2 100644
--- a/net/sysctl_net.c
+++ b/net/sysctl_net.c
@@ -35,8 +35,22 @@ net_ctl_header_lookup(struct ctl_table_root *root, struct nsproxy *namespaces)
return &namespaces->net_ns->sysctl_table_headers;
}
+/* Return standard mode bits for table entry. */
+static int net_ctl_permissions(struct ctl_table_root *root,
+ struct nsproxy *nsproxy,
+ struct ctl_table *table)
+{
+ /* Allow network administrator to have same access as root. */
+ if (capable(CAP_NET_ADMIN)) {
+ int mode = (table->mode >> 6) & 7;
+ return (mode << 6) | (mode << 3) | mode;
+ }
+ return table->mode;
+}
+
static struct ctl_table_root net_sysctl_root = {
.lookup = net_ctl_header_lookup,
+ .permissions = net_ctl_permissions,
};
static LIST_HEAD(net_sysctl_ro_tables);
diff --git a/net/xfrm/Kconfig b/net/xfrm/Kconfig
index 9201ef8ad90..6d081674515 100644
--- a/net/xfrm/Kconfig
+++ b/net/xfrm/Kconfig
@@ -46,6 +46,12 @@ config XFRM_STATISTICS
If unsure, say N.
+config XFRM_IPCOMP
+ tristate
+ select XFRM
+ select CRYPTO
+ select CRYPTO_DEFLATE
+
config NET_KEY
tristate "PF_KEY sockets"
select XFRM
diff --git a/net/xfrm/Makefile b/net/xfrm/Makefile
index 332cfb0ff56..0f439a72cca 100644
--- a/net/xfrm/Makefile
+++ b/net/xfrm/Makefile
@@ -6,4 +6,5 @@ obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \
xfrm_input.o xfrm_output.o xfrm_algo.o
obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o
obj-$(CONFIG_XFRM_USER) += xfrm_user.o
+obj-$(CONFIG_XFRM_IPCOMP) += xfrm_ipcomp.o
diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c
new file mode 100644
index 00000000000..800f669083f
--- /dev/null
+++ b/net/xfrm/xfrm_ipcomp.c
@@ -0,0 +1,385 @@
+/*
+ * IP Payload Compression Protocol (IPComp) - RFC3173.
+ *
+ * Copyright (c) 2003 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2003-2008 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * 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.
+ *
+ * Todo:
+ * - Tunable compression parameters.
+ * - Compression stats.
+ * - Adaptive compression.
+ */
+
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <linux/gfp.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/percpu.h>
+#include <linux/rtnetlink.h>
+#include <linux/smp.h>
+#include <linux/vmalloc.h>
+#include <net/ip.h>
+#include <net/ipcomp.h>
+#include <net/xfrm.h>
+
+struct ipcomp_tfms {
+ struct list_head list;
+ struct crypto_comp **tfms;
+ int users;
+};
+
+static DEFINE_MUTEX(ipcomp_resource_mutex);
+static void **ipcomp_scratches;
+static int ipcomp_scratch_users;
+static LIST_HEAD(ipcomp_tfms_list);
+
+static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
+{
+ struct ipcomp_data *ipcd = x->data;
+ const int plen = skb->len;
+ int dlen = IPCOMP_SCRATCH_SIZE;
+ const u8 *start = skb->data;
+ const int cpu = get_cpu();
+ u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
+ struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu);
+ int err = crypto_comp_decompress(tfm, start, plen, scratch, &dlen);
+ int len;
+
+ if (err)
+ goto out;
+
+ if (dlen < (plen + sizeof(struct ip_comp_hdr))) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ len = dlen - plen;
+ if (len > skb_tailroom(skb))
+ len = skb_tailroom(skb);
+
+ skb->truesize += len;
+ __skb_put(skb, len);
+
+ len += plen;
+ skb_copy_to_linear_data(skb, scratch, len);
+
+ while ((scratch += len, dlen -= len) > 0) {
+ skb_frag_t *frag;
+
+ err = -EMSGSIZE;
+ if (WARN_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS))
+ goto out;
+
+ frag = skb_shinfo(skb)->frags + skb_shinfo(skb)->nr_frags;
+ frag->page = alloc_page(GFP_ATOMIC);
+
+ err = -ENOMEM;
+ if (!frag->page)
+ goto out;
+
+ len = PAGE_SIZE;
+ if (dlen < len)
+ len = dlen;
+
+ memcpy(page_address(frag->page), scratch, len);
+
+ frag->page_offset = 0;
+ frag->size = len;
+ skb->truesize += len;
+ skb->data_len += len;
+ skb->len += len;
+
+ skb_shinfo(skb)->nr_frags++;
+ }
+
+ err = 0;
+
+out:
+ put_cpu();
+ return err;
+}
+
+int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+ int nexthdr;
+ int err = -ENOMEM;
+ struct ip_comp_hdr *ipch;
+
+ if (skb_linearize_cow(skb))
+ goto out;
+
+ skb->ip_summed = CHECKSUM_NONE;
+
+ /* Remove ipcomp header and decompress original payload */
+ ipch = (void *)skb->data;
+ nexthdr = ipch->nexthdr;
+
+ skb->transport_header = skb->network_header + sizeof(*ipch);
+ __skb_pull(skb, sizeof(*ipch));
+ err = ipcomp_decompress(x, skb);
+ if (err)
+ goto out;
+
+ err = nexthdr;
+
+out:
+ return err;
+}
+EXPORT_SYMBOL_GPL(ipcomp_input);
+
+static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb)
+{
+ struct ipcomp_data *ipcd = x->data;
+ const int plen = skb->len;
+ int dlen = IPCOMP_SCRATCH_SIZE;
+ u8 *start = skb->data;
+ const int cpu = get_cpu();
+ u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
+ struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu);
+ int err;
+
+ local_bh_disable();
+ err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
+ local_bh_enable();
+ if (err)
+ goto out;
+
+ if ((dlen + sizeof(struct ip_comp_hdr)) >= plen) {
+ err = -EMSGSIZE;
+ goto out;
+ }
+
+ memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
+ put_cpu();
+
+ pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr));
+ return 0;
+
+out:
+ put_cpu();
+ return err;
+}
+
+int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
+{
+ int err;
+ struct ip_comp_hdr *ipch;
+ struct ipcomp_data *ipcd = x->data;
+
+ if (skb->len < ipcd->threshold) {
+ /* Don't bother compressing */
+ goto out_ok;
+ }
+
+ if (skb_linearize_cow(skb))
+ goto out_ok;
+
+ err = ipcomp_compress(x, skb);
+
+ if (err) {
+ goto out_ok;
+ }
+
+ /* Install ipcomp header, convert into ipcomp datagram. */
+ ipch = ip_comp_hdr(skb);
+ ipch->nexthdr = *skb_mac_header(skb);
+ ipch->flags = 0;
+ ipch->cpi = htons((u16 )ntohl(x->id.spi));
+ *skb_mac_header(skb) = IPPROTO_COMP;
+out_ok:
+ skb_push(skb, -skb_network_offset(skb));
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipcomp_output);
+
+static void ipcomp_free_scratches(void)
+{
+ int i;
+ void **scratches;
+
+ if (--ipcomp_scratch_users)
+ return;
+
+ scratches = ipcomp_scratches;
+ if (!scratches)
+ return;
+
+ for_each_possible_cpu(i)
+ vfree(*per_cpu_ptr(scratches, i));
+
+ free_percpu(scratches);
+}
+
+static void **ipcomp_alloc_scratches(void)
+{
+ int i;
+ void **scratches;
+
+ if (ipcomp_scratch_users++)
+ return ipcomp_scratches;
+
+ scratches = alloc_percpu(void *);
+ if (!scratches)
+ return NULL;
+
+ ipcomp_scratches = scratches;
+
+ for_each_possible_cpu(i) {
+ void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
+ if (!scratch)
+ return NULL;
+ *per_cpu_ptr(scratches, i) = scratch;
+ }
+
+ return scratches;
+}
+
+static void ipcomp_free_tfms(struct crypto_comp **tfms)
+{
+ struct ipcomp_tfms *pos;
+ int cpu;
+
+ list_for_each_entry(pos, &ipcomp_tfms_list, list) {
+ if (pos->tfms == tfms)
+ break;
+ }
+
+ BUG_TRAP(pos);
+
+ if (--pos->users)
+ return;
+
+ list_del(&pos->list);
+ kfree(pos);
+
+ if (!tfms)
+ return;
+
+ for_each_possible_cpu(cpu) {
+ struct crypto_comp *tfm = *per_cpu_ptr(tfms, cpu);
+ crypto_free_comp(tfm);
+ }
+ free_percpu(tfms);
+}
+
+static struct crypto_comp **ipcomp_alloc_tfms(const char *alg_name)
+{
+ struct ipcomp_tfms *pos;
+ struct crypto_comp **tfms;
+ int cpu;
+
+ /* This can be any valid CPU ID so we don't need locking. */
+ cpu = raw_smp_processor_id();
+
+ list_for_each_entry(pos, &ipcomp_tfms_list, list) {
+ struct crypto_comp *tfm;
+
+ tfms = pos->tfms;
+ tfm = *per_cpu_ptr(tfms, cpu);
+
+ if (!strcmp(crypto_comp_name(tfm), alg_name)) {
+ pos->users++;
+ return tfms;
+ }
+ }
+
+ pos = kmalloc(sizeof(*pos), GFP_KERNEL);
+ if (!pos)
+ return NULL;
+
+ pos->users = 1;
+ INIT_LIST_HEAD(&pos->list);
+ list_add(&pos->list, &ipcomp_tfms_list);
+
+ pos->tfms = tfms = alloc_percpu(struct crypto_comp *);
+ if (!tfms)
+ goto error;
+
+ for_each_possible_cpu(cpu) {
+ struct crypto_comp *tfm = crypto_alloc_comp(alg_name, 0,
+ CRYPTO_ALG_ASYNC);
+ if (IS_ERR(tfm))
+ goto error;
+ *per_cpu_ptr(tfms, cpu) = tfm;
+ }
+
+ return tfms;
+
+error:
+ ipcomp_free_tfms(tfms);
+ return NULL;
+}
+
+static void ipcomp_free_data(struct ipcomp_data *ipcd)
+{
+ if (ipcd->tfms)
+ ipcomp_free_tfms(ipcd->tfms);
+ ipcomp_free_scratches();
+}
+
+void ipcomp_destroy(struct xfrm_state *x)
+{
+ struct ipcomp_data *ipcd = x->data;
+ if (!ipcd)
+ return;
+ xfrm_state_delete_tunnel(x);
+ mutex_lock(&ipcomp_resource_mutex);
+ ipcomp_free_data(ipcd);
+ mutex_unlock(&ipcomp_resource_mutex);
+ kfree(ipcd);
+}
+EXPORT_SYMBOL_GPL(ipcomp_destroy);
+
+int ipcomp_init_state(struct xfrm_state *x)
+{
+ int err;
+ struct ipcomp_data *ipcd;
+ struct xfrm_algo_desc *calg_desc;
+
+ err = -EINVAL;
+ if (!x->calg)
+ goto out;
+
+ if (x->encap)
+ goto out;
+
+ err = -ENOMEM;
+ ipcd = kzalloc(sizeof(*ipcd), GFP_KERNEL);
+ if (!ipcd)
+ goto out;
+
+ mutex_lock(&ipcomp_resource_mutex);
+ if (!ipcomp_alloc_scratches())
+ goto error;
+
+ ipcd->tfms = ipcomp_alloc_tfms(x->calg->alg_name);
+ if (!ipcd->tfms)
+ goto error;
+ mutex_unlock(&ipcomp_resource_mutex);
+
+ calg_desc = xfrm_calg_get_byname(x->calg->alg_name, 0);
+ BUG_ON(!calg_desc);
+ ipcd->threshold = calg_desc->uinfo.comp.threshold;
+ x->data = ipcd;
+ err = 0;
+out:
+ return err;
+
+error:
+ ipcomp_free_data(ipcd);
+ mutex_unlock(&ipcomp_resource_mutex);
+ kfree(ipcd);
+ goto out;
+}
+EXPORT_SYMBOL_GPL(ipcomp_init_state);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) - RFC3173");
+MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
diff --git a/samples/firmware_class/firmware_sample_firmware_class.c b/samples/firmware_class/firmware_sample_firmware_class.c
index 9392116e47b..e6cf7a43a29 100644
--- a/samples/firmware_class/firmware_sample_firmware_class.c
+++ b/samples/firmware_class/firmware_sample_firmware_class.c
@@ -124,7 +124,7 @@ static int fw_setup_class_device(struct class_device *class_dev,
class_dev->class_id[BUS_ID_SIZE-1] = '\0';
class_dev->dev = device;
- class_dev->class = &firmware_class,
+ class_dev->class = &firmware_class;
class_set_devdata(class_dev, fw_priv);
retval = class_device_register(class_dev);
if (retval) {
diff --git a/samples/kobject/kset-example.c b/samples/kobject/kset-example.c
index b0a1b4fe658..7395c0bbae1 100644
--- a/samples/kobject/kset-example.c
+++ b/samples/kobject/kset-example.c
@@ -211,7 +211,7 @@ static struct foo_obj *create_foo_obj(const char *name)
*/
retval = kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s", name);
if (retval) {
- kfree(foo);
+ kobject_put(&foo->kobj);
return NULL;
}
diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst
index c972c0f54ce..f63a663de15 100644
--- a/scripts/Makefile.fwinst
+++ b/scripts/Makefile.fwinst
@@ -17,14 +17,15 @@ include $(srctree)/$(obj)/Makefile
include scripts/Makefile.host
-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-m))
-
+mod-fw := $(fw-shipped-m)
# If CONFIG_FIRMWARE_IN_KERNEL isn't set, then install the
# firmware for in-kernel drivers too.
ifndef CONFIG_FIRMWARE_IN_KERNEL
-mod-fw += $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-y))
+mod-fw += $(fw-shipped-y)
endif
+installed-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(mod-fw))
+
installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all))
installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/.
@@ -49,7 +50,8 @@ PHONY += __fw_install __fw_modinst FORCE
.PHONY: $(PHONY)
__fw_install: $(installed-fw)
-__fw_modinst: $(mod-fw)
+__fw_modinst: $(installed-mod-fw)
+__fw_modbuild: $(addprefix $(obj)/,$(mod-fw))
FORCE:
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 17092d6c7db..9ee9783aea5 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -101,6 +101,7 @@ quiet_cmd_kernel-mod = MODPOST $@
cmd_kernel-mod = $(modpost) $@
vmlinux.o: FORCE
+ @rm -fr $(kernelmarkersfile)
$(call cmd,kernel-mod)
# Declare generated files as targets for modpost
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 6971bf078d1..bc677939822 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -9,7 +9,7 @@ use strict;
my $P = $0;
$P =~ s@.*/@@g;
-my $V = '0.19';
+my $V = '0.21';
use Getopt::Long qw(:config no_auto_abbrev);
@@ -17,7 +17,6 @@ my $quiet = 0;
my $tree = 1;
my $chk_signoff = 1;
my $chk_patch = 1;
-my $tst_type = 0;
my $tst_only;
my $emacs = 0;
my $terse = 0;
@@ -44,7 +43,6 @@ GetOptions(
'summary-file!' => \$summary_file,
'debug=s' => \%debug,
- 'test-type!' => \$tst_type,
'test-only=s' => \$tst_only,
) or exit;
@@ -67,6 +65,7 @@ if ($#ARGV < 0) {
my $dbg_values = 0;
my $dbg_possible = 0;
+my $dbg_type = 0;
for my $key (keys %debug) {
eval "\${dbg_$key} = '$debug{$key}';"
}
@@ -169,24 +168,23 @@ our @modifierList = (
);
sub build_types {
- my $mods = "(?: \n" . join("|\n ", @modifierList) . "\n)";
- my $all = "(?: \n" . join("|\n ", @typeList) . "\n)";
+ my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)";
+ my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)";
+ $Modifier = qr{(?:$Attribute|$Sparse|$mods)};
$NonptrType = qr{
- (?:const\s+)?
- (?:$mods\s+)?
+ (?:$Modifier\s+|const\s+)*
(?:
(?:typeof|__typeof__)\s*\(\s*\**\s*$Ident\s*\)|
(?:${all}\b)
)
- (?:\s+$Sparse|\s+const)*
+ (?:\s+$Modifier|\s+const)*
}x;
$Type = qr{
$NonptrType
(?:\s*\*+\s*const|\s*\*+|(?:\s*\[\s*\])+)?
- (?:\s+$Inline|\s+$Sparse|\s+$Attribute|\s+$mods)*
+ (?:\s+$Inline|\s+$Modifier)*
}x;
$Declare = qr{(?:$Storage\s+)?$Type};
- $Modifier = qr{(?:$Attribute|$Sparse|$mods)};
}
build_types();
@@ -470,7 +468,9 @@ sub ctx_statement_block {
}
$off++;
}
+ # We are truly at the end, so shuffle to the next line.
if ($off == $len) {
+ $loff = $len + 1;
$line++;
$remain--;
}
@@ -631,7 +631,7 @@ sub ctx_locate_comment {
my ($first_line, $end_line) = @_;
# Catch a comment on the end of the line itself.
- my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*$@);
+ my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@);
return $current_comment if (defined $current_comment);
# Look through the context and try and figure out if there is a
@@ -689,17 +689,20 @@ sub cat_vet {
my $av_preprocessor = 0;
my $av_pending;
my @av_paren_type;
+my $av_pend_colon;
sub annotate_reset {
$av_preprocessor = 0;
$av_pending = '_';
@av_paren_type = ('E');
+ $av_pend_colon = 'O';
}
sub annotate_values {
my ($stream, $type) = @_;
my $res;
+ my $var = '_' x length($stream);
my $cur = $stream;
print "$stream\n" if ($dbg_values > 1);
@@ -715,10 +718,14 @@ sub annotate_values {
$av_preprocessor = 0;
}
- } elsif ($cur =~ /^($Type)/) {
+ } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\()/) {
print "DECLARE($1)\n" if ($dbg_values > 1);
$type = 'T';
+ } elsif ($cur =~ /^($Modifier)\s*/) {
+ print "MODIFIER($1)\n" if ($dbg_values > 1);
+ $type = 'T';
+
} elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) {
print "DEFINE($1,$2)\n" if ($dbg_values > 1);
$av_preprocessor = 1;
@@ -780,7 +787,12 @@ sub annotate_values {
$av_pending = 'N';
$type = 'N';
- } elsif ($cur =~/^(return|case|else)/o) {
+ } elsif ($cur =~/^(case)/o) {
+ print "CASE($1)\n" if ($dbg_values > 1);
+ $av_pend_colon = 'C';
+ $type = 'N';
+
+ } elsif ($cur =~/^(return|else|goto)/o) {
print "KEYWORD($1)\n" if ($dbg_values > 1);
$type = 'N';
@@ -800,10 +812,20 @@ sub annotate_values {
print "PAREN('$1')\n" if ($dbg_values > 1);
}
- } elsif ($cur =~ /^($Ident)\(/o) {
+ } elsif ($cur =~ /^($Ident)\s*\(/o) {
print "FUNC($1)\n" if ($dbg_values > 1);
+ $type = 'V';
$av_pending = 'V';
+ } elsif ($cur =~ /^($Ident\s*):/) {
+ if ($type eq 'E') {
+ $av_pend_colon = 'L';
+ } elsif ($type eq 'T') {
+ $av_pend_colon = 'B';
+ }
+ print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1);
+ $type = 'V';
+
} elsif ($cur =~ /^($Ident|$Constant)/o) {
print "IDENT($1)\n" if ($dbg_values > 1);
$type = 'V';
@@ -815,11 +837,40 @@ sub annotate_values {
} elsif ($cur =~/^(;|{|})/) {
print "END($1)\n" if ($dbg_values > 1);
$type = 'E';
+ $av_pend_colon = 'O';
+
+ } elsif ($cur =~ /^(\?)/o) {
+ print "QUESTION($1)\n" if ($dbg_values > 1);
+ $type = 'N';
- } elsif ($cur =~ /^(;|\?|:|\[)/o) {
+ } elsif ($cur =~ /^(:)/o) {
+ print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1);
+
+ substr($var, length($res), 1, $av_pend_colon);
+ if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') {
+ $type = 'E';
+ } else {
+ $type = 'N';
+ }
+ $av_pend_colon = 'O';
+
+ } elsif ($cur =~ /^(;|\[)/o) {
print "CLOSE($1)\n" if ($dbg_values > 1);
$type = 'N';
+ } elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&(?!\&))/o) {
+ my $variant;
+
+ print "OPV($1)\n" if ($dbg_values > 1);
+ if ($type eq 'V') {
+ $variant = 'B';
+ } else {
+ $variant = 'U';
+ }
+
+ substr($var, length($res), 1, $variant);
+ $type = 'N';
+
} elsif ($cur =~ /^($Operators)/o) {
print "OP($1)\n" if ($dbg_values > 1);
if ($1 ne '++' && $1 ne '--') {
@@ -835,17 +886,17 @@ sub annotate_values {
}
}
- return $res;
+ return ($res, $var);
}
sub possible {
my ($possible, $line) = @_;
print "CHECK<$possible> ($line)\n" if ($dbg_possible > 1);
- if ($possible !~ /^(?:$Storage|$Type|DEFINE_\S+)$/ &&
+ if ($possible !~ /^(?:$Modifier|$Storage|$Type|DEFINE_\S+)$/ &&
$possible ne 'goto' && $possible ne 'return' &&
$possible ne 'case' && $possible ne 'else' &&
- $possible ne 'asm' &&
+ $possible ne 'asm' && $possible ne '__asm__' &&
$possible !~ /^(typedef|struct|enum)\b/) {
# Check for modifiers.
$possible =~ s/\s*$Storage\s*//g;
@@ -854,8 +905,10 @@ sub possible {
} elsif ($possible =~ /\s/) {
$possible =~ s/\s*$Type\s*//g;
- warn "MODIFIER: $possible ($line)\n" if ($dbg_possible);
- push(@modifierList, $possible);
+ for my $modifier (split(' ', $possible)) {
+ warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
+ push(@modifierList, $modifier);
+ }
} else {
warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible);
@@ -1135,7 +1188,9 @@ sub process {
}
#80 column limit
if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
- $rawline !~ /^.\s*\*\s*\@$Ident\s/ && $length > 80)
+ $rawline !~ /^.\s*\*\s*\@$Ident\s/ &&
+ $line !~ /^\+\s*printk\s*\(\s*(?:KERN_\S+\s*)?"[X\t]*"\s*(?:,|\)\s*;)\s*$/ &&
+ $length > 80)
{
WARN("line over 80 characters\n" . $herecurr);
}
@@ -1162,10 +1217,10 @@ sub process {
}
# Check for potential 'bare' types
- my ($stat, $cond);
+ my ($stat, $cond, $line_nr_next, $remain_next);
if ($realcnt && $line =~ /.\s*\S/) {
- ($stat, $cond) = ctx_statement_block($linenr,
- $realcnt, 0);
+ ($stat, $cond, $line_nr_next, $remain_next) =
+ ctx_statement_block($linenr, $realcnt, 0);
$stat =~ s/\n./\n /g;
$cond =~ s/\n./\n /g;
@@ -1179,7 +1234,7 @@ sub process {
} elsif ($s =~ /^.\s*$Ident\s*\(/s) {
# declarations always start with types
- } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))\s*(?:;|=|,|\()/s) {
+ } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=|,|\()/s) {
my $type = $1;
$type =~ s/\s+/ /g;
possible($type, "A:" . $s);
@@ -1239,6 +1294,10 @@ sub process {
ERROR("switch and case should be at the same indent\n$hereline$err");
}
}
+ if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g &&
+ $line !~ /\G(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$/g) {
+ ERROR("trailing statements should be on next line\n" . $herecurr);
+ }
# if/while/etc brace do not go on next line, unless defining a do while loop,
# or if that brace on the next line is for something else
@@ -1246,17 +1305,22 @@ sub process {
my $pre_ctx = "$1$2";
my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
- my $ctx_ln = $linenr + $#ctx + 1;
my $ctx_cnt = $realcnt - $#ctx - 1;
my $ctx = join("\n", @ctx);
- ##warn "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
+ my $ctx_ln = $linenr;
+ my $ctx_skip = $realcnt;
- # Skip over any removed lines in the context following statement.
- while (defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^-/) {
+ while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt &&
+ defined $lines[$ctx_ln - 1] &&
+ $lines[$ctx_ln - 1] =~ /^-/)) {
+ ##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n";
+ $ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/);
$ctx_ln++;
}
- ##warn "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
+
+ #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
+ #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
ERROR("that open brace { should be on the previous line\n" .
@@ -1276,12 +1340,14 @@ sub process {
# Track the 'values' across context and added lines.
my $opline = $line; $opline =~ s/^./ /;
- my $curr_values = annotate_values($opline . "\n", $prev_values);
+ my ($curr_values, $curr_vars) =
+ annotate_values($opline . "\n", $prev_values);
$curr_values = $prev_values . $curr_values;
if ($dbg_values) {
my $outline = $opline; $outline =~ s/\t/ /g;
print "$linenr > .$outline\n";
print "$linenr > $curr_values\n";
+ print "$linenr > $curr_vars\n";
}
$prev_values = substr($curr_values, -1);
@@ -1289,8 +1355,12 @@ sub process {
if ($line=~/^[^\+]/) {next;}
# TEST: allow direct testing of the type matcher.
- if ($tst_type && $line =~ /^.$Declare$/) {
- ERROR("TEST: is type $Declare\n" . $herecurr);
+ if ($dbg_type) {
+ if ($line =~ /^.\s*$Declare\s*$/) {
+ ERROR("TEST: is type\n" . $herecurr);
+ } elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) {
+ ERROR("TEST: is not type ($1 is)\n". $herecurr);
+ }
next;
}
@@ -1365,11 +1435,11 @@ sub process {
ERROR("\"(foo $1 )\" should be \"(foo $1)\"\n" .
$herecurr);
- } elsif ($line =~ m{$NonptrType(\*+)(?:\s+(?:$Attribute|$Sparse))?\s+[A-Za-z\d_]+}) {
+ } elsif ($line =~ m{\b$NonptrType(\*+)(?:\s+(?:$Attribute|$Sparse))?\s+[A-Za-z\d_]+}) {
ERROR("\"foo$1 bar\" should be \"foo $1bar\"\n" .
$herecurr);
- } elsif ($line =~ m{$NonptrType\s+(\*+)(?!\s+(?:$Attribute|$Sparse))\s+[A-Za-z\d_]+}) {
+ } elsif ($line =~ m{\b$NonptrType\s+(\*+)(?!\s+(?:$Attribute|$Sparse))\s+[A-Za-z\d_]+}) {
ERROR("\"foo $1 bar\" should be \"foo $1bar\"\n" .
$herecurr);
}
@@ -1421,6 +1491,17 @@ sub process {
ERROR("open brace '{' following $1 go on the same line\n" . $hereprev);
}
+# check for spacing round square brackets; allowed:
+# 1. with a type on the left -- int [] a;
+# 2. at the beginning of a line for slice initialisers -- [0..10] = 5,
+ while ($line =~ /(.*?\s)\[/g) {
+ my ($where, $prefix) = ($-[1], $1);
+ if ($prefix !~ /$Type\s+$/ &&
+ ($where != 0 || $prefix !~ /^.\s+$/)) {
+ ERROR("space prohibited before open square bracket '['\n" . $herecurr);
+ }
+ }
+
# check for spaces between functions and their parentheses.
while ($line =~ /($Ident)\s+\(/g) {
my $name = $1;
@@ -1457,7 +1538,8 @@ sub process {
<<=|>>=|<=|>=|==|!=|
\+=|-=|\*=|\/=|%=|\^=|\|=|&=|
=>|->|<<|>>|<|>|=|!|~|
- &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%
+ &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%|
+ \?|:
}x;
my @elements = split(/($ops|;)/, $opline);
my $off = 0;
@@ -1504,22 +1586,11 @@ sub process {
my $ptr = substr($blank, 0, $off) . "^";
my $hereptr = "$hereline$ptr\n";
- # Classify operators into binary, unary, or
- # definitions (* only) where they have more
- # than one mode.
+ # Pull out the value of this operator.
my $op_type = substr($curr_values, $off + 1, 1);
- my $op_left = substr($curr_values, $off, 1);
- my $is_unary;
- if ($op_type eq 'T') {
- $is_unary = 2;
- } elsif ($op_left eq 'V') {
- $is_unary = 0;
- } else {
- $is_unary = 1;
- }
- #if ($op eq '-' || $op eq '&' || $op eq '*') {
- # print "UNARY: <$op_left$op_type $is_unary $a:$op:$c> <$ca:$op:$cc> <$unary_ctx>\n";
- #}
+
+ # Get the full operator variant.
+ my $opv = $op . substr($curr_vars, $off, 1);
# Ignore operators passed as parameters.
if ($op_type ne 'V' &&
@@ -1538,8 +1609,10 @@ sub process {
# // is a comment
} elsif ($op eq '//') {
- # -> should have no spaces
- } elsif ($op eq '->') {
+ # No spaces for:
+ # ->
+ # : when part of a bitfield
+ } elsif ($op eq '->' || $opv eq ':B') {
if ($ctx =~ /Wx.|.xW/) {
ERROR("spaces prohibited around that '$op' $at\n" . $hereptr);
}
@@ -1551,18 +1624,19 @@ sub process {
}
# '*' as part of a type definition -- reported already.
- } elsif ($op eq '*' && $is_unary == 2) {
+ } elsif ($opv eq '*_') {
#warn "'*' is part of type\n";
# unary operators should have a space before and
# none after. May be left adjacent to another
# unary operator, or a cast
} elsif ($op eq '!' || $op eq '~' ||
- ($is_unary && ($op eq '*' || $op eq '-' || $op eq '&'))) {
+ $opv eq '*U' || $opv eq '-U' ||
+ $opv eq '&U') {
if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
ERROR("space required before that '$op' $at\n" . $hereptr);
}
- if ($op eq '*' && $cc =~/\s*const\b/) {
+ if ($op eq '*' && $cc =~/\s*const\b/) {
# A unary '*' may be const
} elsif ($ctx =~ /.xW/) {
@@ -1595,11 +1669,33 @@ sub process {
$hereptr);
}
+ # A colon needs no spaces before when it is
+ # terminating a case value or a label.
+ } elsif ($opv eq ':C' || $opv eq ':L') {
+ if ($ctx =~ /Wx./) {
+ ERROR("space prohibited before that '$op' $at\n" . $hereptr);
+ }
+
# All the others need spaces both sides.
} elsif ($ctx !~ /[EWC]x[CWE]/) {
+ my $ok = 0;
+
# Ignore email addresses <foo@bar>
- if (!($op eq '<' && $cb =~ /$;\S+\@\S+>/) &&
- !($op eq '>' && $cb =~ /<\S+\@\S+$;/)) {
+ if (($op eq '<' &&
+ $cc =~ /^\S+\@\S+>/) ||
+ ($op eq '>' &&
+ $ca =~ /<\S+\@\S+$/))
+ {
+ $ok = 1;
+ }
+
+ # Ignore ?:
+ if (($opv eq ':O' && $ca =~ /\?$/) ||
+ ($op eq '?' && $cc =~ /^:/)) {
+ $ok = 1;
+ }
+
+ if ($ok == 0) {
ERROR("spaces required around that '$op' $at\n" . $hereptr);
}
}
@@ -1670,6 +1766,7 @@ sub process {
my $value = $2;
# Flatten any parentheses and braces
+ $value =~ s/\)\(/\) \(/g;
while ($value =~ s/\([^\(\)]*\)/1/) {
}
@@ -1686,8 +1783,9 @@ sub process {
ERROR("space required before the open parenthesis '('\n" . $herecurr);
}
-# Check for illegal assignment in if conditional.
- if ($line =~ /\bif\s*\(/) {
+# Check for illegal assignment in if conditional -- and check for trailing
+# statements after the conditional.
+ if ($line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) {
my ($s, $c) = ($stat, $cond);
if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/) {
@@ -1699,13 +1797,63 @@ sub process {
substr($s, 0, length($c), '');
$s =~ s/\n.*//g;
$s =~ s/$;//g; # Remove any comments
- if (length($c) && $s !~ /^\s*({|;|)\s*\\*\s*$/ &&
- $c !~ /^.\s*\#\s*if/)
+ if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ &&
+ $c !~ /}\s*while\s*/)
{
ERROR("trailing statements should be on next line\n" . $herecurr);
}
}
+# Check relative indent for conditionals and blocks.
+ if ($line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
+ my ($s, $c) = ($stat, $cond);
+
+ substr($s, 0, length($c), '');
+
+ # Make sure we remove the line prefixes as we have
+ # none on the first line, and are going to readd them
+ # where necessary.
+ $s =~ s/\n./\n/gs;
+
+ # We want to check the first line inside the block
+ # starting at the end of the conditional, so remove:
+ # 1) any blank line termination
+ # 2) any opening brace { on end of the line
+ # 3) any do (...) {
+ my $continuation = 0;
+ my $check = 0;
+ $s =~ s/^.*\bdo\b//;
+ $s =~ s/^\s*{//;
+ if ($s =~ s/^\s*\\//) {
+ $continuation = 1;
+ }
+ if ($s =~ s/^\s*\n//) {
+ $check = 1;
+ }
+
+ # Also ignore a loop construct at the end of a
+ # preprocessor statement.
+ if (($prevline =~ /^.\s*#\s*define\s/ ||
+ $prevline =~ /\\\s*$/) && $continuation == 0) {
+ $check = 0;
+ }
+
+ # Ignore the current line if its is a preprocessor
+ # line.
+ if ($s =~ /^\s*#\s*/) {
+ $check = 0;
+ }
+
+ my (undef, $sindent) = line_stats("+" . $s);
+
+ ##print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s>\n";
+
+ if ($check && (($sindent % 8) != 0 ||
+ ($sindent <= $indent && $s ne ''))) {
+ WARN("suspect code indent for conditional statements\n" . $herecurr);
+ }
+ }
+
# Check for bitwise tests written as boolean
if ($line =~ /
(?:
@@ -1777,7 +1925,8 @@ sub process {
# multi-statement macros should be enclosed in a do while loop, grab the
# first statement and ensure its the whole macro if its not enclosed
# in a known good container
- if ($line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
+ if ($realfile !~ m@/vmlinux.lds.h$@ &&
+ $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
my $ln = $linenr;
my $cnt = $realcnt;
my ($off, $dstat, $dcond, $rest);
@@ -1791,30 +1940,26 @@ sub process {
$lines[$ln - 1] =~ /^(?:-|..*\\$)/)
{
$ctx .= $rawlines[$ln - 1] . "\n";
+ $cnt-- if ($lines[$ln - 1] !~ /^-/);
$ln++;
- $cnt--;
}
$ctx .= $rawlines[$ln - 1];
($dstat, $dcond, $ln, $cnt, $off) =
ctx_statement_block($linenr, $ln - $linenr + 1, 0);
#print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
- #print "LINE<$lines[$ln]> len<" . length($lines[$ln]) . "\n";
+ #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
# Extract the remainder of the define (if any) and
# rip off surrounding spaces, and trailing \'s.
$rest = '';
- if (defined $lines[$ln - 1] &&
- $off > length($lines[$ln - 1]))
- {
- $ln++;
- $cnt--;
- $off = 0;
- }
- while ($cnt > 0) {
- $rest .= substr($lines[$ln - 1], $off) . "\n";
+ while ($off != 0 || ($cnt > 0 && $rest =~ /(?:^|\\)\s*$/)) {
+ #print "ADDING $off <" . substr($lines[$ln - 1], $off) . ">\n";
+ if ($off != 0 || $lines[$ln - 1] !~ /^-/) {
+ $rest .= substr($lines[$ln - 1], $off) . "\n";
+ $cnt--;
+ }
$ln++;
- $cnt--;
$off = 0;
}
$rest =~ s/\\\n.//g;
@@ -1827,6 +1972,7 @@ sub process {
} else {
$dstat =~ s/^.\s*\#\s*define\s+$Ident\s*//;
}
+ $dstat =~ s/$;//g;
$dstat =~ s/\\\n.//g;
$dstat =~ s/^\s*//s;
$dstat =~ s/\s*$//s;
@@ -1845,6 +1991,7 @@ sub process {
DEFINE_PER_CPU|
__typeof__\(
}x;
+ #print "REST<$rest>\n";
if ($rest ne '') {
if ($rest !~ /while\s*\(/ &&
$dstat !~ /$exceptions/)
@@ -2001,7 +2148,14 @@ sub process {
if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
my $expr = $1;
if ($line =~ /\bkfree\(\Q$expr\E\);/) {
- WARN("kfree(NULL) is safe this check is probabally not required\n" . $hereprev);
+ WARN("kfree(NULL) is safe this check is probably not required\n" . $hereprev);
+ }
+ }
+# check for needless usb_free_urb() checks
+ if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
+ my $expr = $1;
+ if ($line =~ /\busb_free_urb\(\Q$expr\E\);/) {
+ WARN("usb_free_urb(NULL) is safe this check is probably not required\n" . $hereprev);
}
}
@@ -2106,6 +2260,10 @@ sub process {
if ($line =~ /\bsimple_(strto.*?)\s*\(/) {
WARN("consider using strict_$1 in preference to simple_$1\n" . $herecurr);
}
+# check for __initcall(), use device_initcall() explicitly please
+ if ($line =~ /^.\s*__initcall\s*\(/) {
+ WARN("please use device_initcall() instead of __initcall()\n" . $herecurr);
+ }
# use of NR_CPUS is usually wrong
# ignore definitions of NR_CPUS and usage to define arrays as likely right
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl
index 340ad692051..3eca62566d6 100755
--- a/scripts/checkstack.pl
+++ b/scripts/checkstack.pl
@@ -26,12 +26,17 @@
# $& (whole re) matches the complete objdump line with the stack growth
# $1 (first bracket) matches the size of the stack growth
#
+# $dre is similar, but for dynamic stack redutions:
+# $& (whole re) matches the complete objdump line with the stack growth
+# $1 (first bracket) matches the dynamic amount of the stack growth
+#
# use anything else and feel the pain ;)
-my (@stack, $re, $x, $xs);
+my (@stack, $re, $dre, $x, $xs);
{
my $arch = shift;
if ($arch eq "") {
$arch = `uname -m`;
+ chomp($arch);
}
$x = "[0-9a-f]"; # hex character
@@ -46,9 +51,11 @@ my (@stack, $re, $x, $xs);
} elsif ($arch =~ /^i[3456]86$/) {
#c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp
$re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%esp$/o;
+ $dre = qr/^.*[as][du][db] (%.*),\%esp$/o;
} elsif ($arch eq 'x86_64') {
# 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp
$re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%rsp$/o;
+ $dre = qr/^.*[as][du][db] (\%.*),\%rsp$/o;
} elsif ($arch eq 'ia64') {
#e0000000044011fc: 01 0f fc 8c adds r12=-384,r12
$re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o;
@@ -85,7 +92,7 @@ my (@stack, $re, $x, $xs);
# 0: 00 e8 38 01 LINK 0x4e0;
$re = qr/.*[[:space:]]LINK[[:space:]]*(0x$x{1,8})/o;
} else {
- print("wrong or unknown architecture\n");
+ print("wrong or unknown architecture \"$arch\"\n");
exit
}
}
@@ -141,6 +148,22 @@ while (my $line = <STDIN>) {
next if ($size < 100);
push @stack, "$intro$size\n";
}
+ elsif (defined $dre && $line =~ m/$dre/) {
+ my $size = "Dynamic ($1)";
+
+ next if $line !~ m/^($xs*)/;
+ my $addr = $1;
+ $addr =~ s/ /0/g;
+ $addr = "0x$addr";
+
+ my $intro = "$addr $func [$file]:";
+ my $padlen = 56 - length($intro);
+ while ($padlen > 0) {
+ $intro .= ' ';
+ $padlen -= 8;
+ }
+ push @stack, "$intro$size\n";
+ }
}
print sort bysize @stack;
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
index dca5e0dd09b..4f8a3007e45 100644
--- a/scripts/genksyms/genksyms.c
+++ b/scripts/genksyms/genksyms.c
@@ -520,8 +520,7 @@ int main(int argc, char **argv)
genksyms_usage();
return 1;
}
- if ((strcmp(arch, "v850") == 0) || (strcmp(arch, "h8300") == 0)
- || (strcmp(arch, "blackfin") == 0))
+ if ((strcmp(arch, "h8300") == 0) || (strcmp(arch, "blackfin") == 0))
mod_prefix = "_";
{
extern int yydebug;
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 37d5c363fbc..4fa1f3ad251 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -340,11 +340,18 @@ static int do_acpi_entry(const char *filename,
}
/* looks like: "pnp:dD" */
-static int do_pnp_entry(const char *filename,
- struct pnp_device_id *id, char *alias)
+static void do_pnp_device_entry(void *symval, unsigned long size,
+ struct module *mod)
{
- sprintf(alias, "pnp:d%s*", id->id);
- return 1;
+ const unsigned long id_size = sizeof(struct pnp_device_id);
+ const struct pnp_device_id *id = symval;
+
+ device_id_check(mod->name, "pnp", size, id_size, symval);
+
+ buf_printf(&mod->dev_table_buf,
+ "MODULE_ALIAS(\"pnp:d%s*\");\n", id->id);
+ buf_printf(&mod->dev_table_buf,
+ "MODULE_ALIAS(\"acpi*:%s:*\");\n", id->id);
}
/* looks like: "pnp:dD" for every device of the card */
@@ -388,9 +395,12 @@ static void do_pnp_card_entries(void *symval, unsigned long size,
}
/* add an individual alias for every device entry */
- if (!dup)
+ if (!dup) {
buf_printf(&mod->dev_table_buf,
"MODULE_ALIAS(\"pnp:d%s*\");\n", id);
+ buf_printf(&mod->dev_table_buf,
+ "MODULE_ALIAS(\"acpi*:%s:*\");\n", id);
+ }
}
}
}
@@ -613,7 +623,7 @@ static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
return 1;
}
-/* Ignore any prefix, eg. v850 prepends _ */
+/* Ignore any prefix, eg. some architectures prepend _ */
static inline int sym_is(const char *symbol, const char *name)
{
const char *match;
@@ -701,9 +711,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
sizeof(struct acpi_device_id), "acpi",
do_acpi_entry, mod);
else if (sym_is(symname, "__mod_pnp_device_table"))
- do_table(symval, sym->st_size,
- sizeof(struct pnp_device_id), "pnp",
- do_pnp_entry, mod);
+ do_pnp_device_entry(symval, sym->st_size, mod);
else if (sym_is(symname, "__mod_pnp_card_device_table"))
do_pnp_card_entries(symval, sym->st_size, mod);
else if (sym_is(symname, "__mod_pcmcia_device_table"))
diff --git a/scripts/mod/mk_elfconfig.c b/scripts/mod/mk_elfconfig.c
index db3881f14c2..6a96d47bd1e 100644
--- a/scripts/mod/mk_elfconfig.c
+++ b/scripts/mod/mk_elfconfig.c
@@ -55,7 +55,7 @@ main(int argc, char **argv)
else
exit(1);
- if ((strcmp(argv[1], "v850") == 0) || (strcmp(argv[1], "h8300") == 0)
+ if ((strcmp(argv[1], "h8300") == 0)
|| (strcmp(argv[1], "blackfin") == 0))
printf("#define MODULE_SYMBOL_PREFIX \"_\"\n");
else
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index a07f91aac92..8f038e6d5f9 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1992,7 +1992,8 @@ static void read_markers(const char *fname)
mod->skip = 1;
}
- add_marker(mod, marker, fmt);
+ if (!mod->skip)
+ add_marker(mod, marker, fmt);
}
return;
fail:
diff --git a/security/Kconfig b/security/Kconfig
index 62ed4717d33..559293922a4 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -74,8 +74,7 @@ config SECURITY_NETWORK_XFRM
If you are unsure how to answer this question, answer N.
config SECURITY_FILE_CAPABILITIES
- bool "File POSIX Capabilities (EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ bool "File POSIX Capabilities"
default n
help
This enables filesystem capabilities, allowing you to give
diff --git a/security/commoncap.c b/security/commoncap.c
index 0b6537a3672..4afbece37a0 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -162,8 +162,7 @@ void cap_capset_set (struct task_struct *target, kernel_cap_t *effective,
static inline void bprm_clear_caps(struct linux_binprm *bprm)
{
- cap_clear(bprm->cap_inheritable);
- cap_clear(bprm->cap_permitted);
+ cap_clear(bprm->cap_post_exec_permitted);
bprm->cap_effective = false;
}
@@ -198,6 +197,7 @@ static inline int cap_from_disk(struct vfs_cap_data *caps,
{
__u32 magic_etc;
unsigned tocopy, i;
+ int ret;
if (size < sizeof(magic_etc))
return -EINVAL;
@@ -225,19 +225,40 @@ static inline int cap_from_disk(struct vfs_cap_data *caps,
bprm->cap_effective = false;
}
- for (i = 0; i < tocopy; ++i) {
- bprm->cap_permitted.cap[i] =
- le32_to_cpu(caps->data[i].permitted);
- bprm->cap_inheritable.cap[i] =
- le32_to_cpu(caps->data[i].inheritable);
- }
- while (i < VFS_CAP_U32) {
- bprm->cap_permitted.cap[i] = 0;
- bprm->cap_inheritable.cap[i] = 0;
- i++;
+ ret = 0;
+
+ CAP_FOR_EACH_U32(i) {
+ __u32 value_cpu;
+
+ if (i >= tocopy) {
+ /*
+ * Legacy capability sets have no upper bits
+ */
+ bprm->cap_post_exec_permitted.cap[i] = 0;
+ continue;
+ }
+ /*
+ * pP' = (X & fP) | (pI & fI)
+ */
+ value_cpu = le32_to_cpu(caps->data[i].permitted);
+ bprm->cap_post_exec_permitted.cap[i] =
+ (current->cap_bset.cap[i] & value_cpu) |
+ (current->cap_inheritable.cap[i] &
+ le32_to_cpu(caps->data[i].inheritable));
+ if (value_cpu & ~bprm->cap_post_exec_permitted.cap[i]) {
+ /*
+ * insufficient to execute correctly
+ */
+ ret = -EPERM;
+ }
}
- return 0;
+ /*
+ * For legacy apps, with no internal support for recognizing they
+ * do not have enough capabilities, we return an error if they are
+ * missing some "forced" (aka file-permitted) capabilities.
+ */
+ return bprm->cap_effective ? ret : 0;
}
/* Locate any VFS capabilities: */
@@ -269,9 +290,9 @@ static int get_file_caps(struct linux_binprm *bprm)
goto out;
rc = cap_from_disk(&vcaps, bprm, rc);
- if (rc)
+ if (rc == -EINVAL)
printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
- __func__, rc, bprm->filename);
+ __func__, rc, bprm->filename);
out:
dput(dentry);
@@ -304,25 +325,24 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
int ret;
ret = get_file_caps(bprm);
- if (ret)
- printk(KERN_NOTICE "%s: get_file_caps returned %d for %s\n",
- __func__, ret, bprm->filename);
-
- /* To support inheritance of root-permissions and suid-root
- * executables under compatibility mode, we raise all three
- * capability sets for the file.
- *
- * If only the real uid is 0, we only raise the inheritable
- * and permitted sets of the executable file.
- */
- if (!issecure (SECURE_NOROOT)) {
+ if (!issecure(SECURE_NOROOT)) {
+ /*
+ * To support inheritance of root-permissions and suid-root
+ * executables under compatibility mode, we override the
+ * capability sets for the file.
+ *
+ * If only the real uid is 0, we do not set the effective
+ * bit.
+ */
if (bprm->e_uid == 0 || current->uid == 0) {
- cap_set_full (bprm->cap_inheritable);
- cap_set_full (bprm->cap_permitted);
+ /* pP' = (cap_bset & ~0) | (pI & ~0) */
+ bprm->cap_post_exec_permitted = cap_combine(
+ current->cap_bset, current->cap_inheritable
+ );
+ bprm->cap_effective = (bprm->e_uid == 0);
+ ret = 0;
}
- if (bprm->e_uid == 0)
- bprm->cap_effective = true;
}
return ret;
@@ -330,17 +350,9 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
{
- /* Derived from fs/exec.c:compute_creds. */
- kernel_cap_t new_permitted, working;
-
- new_permitted = cap_intersect(bprm->cap_permitted,
- current->cap_bset);
- working = cap_intersect(bprm->cap_inheritable,
- current->cap_inheritable);
- new_permitted = cap_combine(new_permitted, working);
-
if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
- !cap_issubset (new_permitted, current->cap_permitted)) {
+ !cap_issubset(bprm->cap_post_exec_permitted,
+ current->cap_permitted)) {
set_dumpable(current->mm, suid_dumpable);
current->pdeath_signal = 0;
@@ -350,9 +362,9 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
bprm->e_gid = current->gid;
}
if (cap_limit_ptraced_target()) {
- new_permitted =
- cap_intersect(new_permitted,
- current->cap_permitted);
+ bprm->cap_post_exec_permitted = cap_intersect(
+ bprm->cap_post_exec_permitted,
+ current->cap_permitted);
}
}
}
@@ -364,9 +376,9 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
* in the init_task struct. Thus we skip the usual
* capability rules */
if (!is_global_init(current)) {
- current->cap_permitted = new_permitted;
+ current->cap_permitted = bprm->cap_post_exec_permitted;
if (bprm->cap_effective)
- current->cap_effective = new_permitted;
+ current->cap_effective = bprm->cap_post_exec_permitted;
else
cap_clear(current->cap_effective);
}
@@ -381,9 +393,7 @@ int cap_bprm_secureexec (struct linux_binprm *bprm)
if (current->uid != 0) {
if (bprm->cap_effective)
return 1;
- if (!cap_isclear(bprm->cap_permitted))
- return 1;
- if (!cap_isclear(bprm->cap_inheritable))
+ if (!cap_isclear(bprm->cap_post_exec_permitted))
return 1;
}
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index ddd92cec78e..7bd296cca04 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -41,6 +41,7 @@ struct dev_whitelist_item {
short type;
short access;
struct list_head list;
+ struct rcu_head rcu;
};
struct dev_cgroup {
@@ -59,6 +60,11 @@ static inline struct dev_cgroup *cgroup_to_devcgroup(struct cgroup *cgroup)
return css_to_devcgroup(cgroup_subsys_state(cgroup, devices_subsys_id));
}
+static inline struct dev_cgroup *task_devcgroup(struct task_struct *task)
+{
+ return css_to_devcgroup(task_subsys_state(task, devices_subsys_id));
+}
+
struct cgroup_subsys devices_subsys;
static int devcgroup_can_attach(struct cgroup_subsys *ss,
@@ -128,11 +134,19 @@ static int dev_whitelist_add(struct dev_cgroup *dev_cgroup,
}
if (whcopy != NULL)
- list_add_tail(&whcopy->list, &dev_cgroup->whitelist);
+ list_add_tail_rcu(&whcopy->list, &dev_cgroup->whitelist);
spin_unlock(&dev_cgroup->lock);
return 0;
}
+static void whitelist_item_free(struct rcu_head *rcu)
+{
+ struct dev_whitelist_item *item;
+
+ item = container_of(rcu, struct dev_whitelist_item, rcu);
+ kfree(item);
+}
+
/*
* called under cgroup_lock()
* since the list is visible to other tasks, we need the spinlock also
@@ -156,8 +170,8 @@ static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup,
remove:
walk->access &= ~wh->access;
if (!walk->access) {
- list_del(&walk->list);
- kfree(walk);
+ list_del_rcu(&walk->list);
+ call_rcu(&walk->rcu, whitelist_item_free);
}
}
spin_unlock(&dev_cgroup->lock);
@@ -188,7 +202,7 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup_subsys *ss,
}
wh->minor = wh->major = ~0;
wh->type = DEV_ALL;
- wh->access = ACC_MKNOD | ACC_READ | ACC_WRITE;
+ wh->access = ACC_MASK;
list_add(&wh->list, &dev_cgroup->whitelist);
} else {
parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);
@@ -250,11 +264,10 @@ static char type_to_char(short type)
static void set_majmin(char *str, unsigned m)
{
- memset(str, 0, MAJMINLEN);
if (m == ~0)
- sprintf(str, "*");
+ strcpy(str, "*");
else
- snprintf(str, MAJMINLEN, "%u", m);
+ sprintf(str, "%u", m);
}
static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
@@ -264,15 +277,15 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
struct dev_whitelist_item *wh;
char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN];
- spin_lock(&devcgroup->lock);
- list_for_each_entry(wh, &devcgroup->whitelist, list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(wh, &devcgroup->whitelist, list) {
set_access(acc, wh->access);
set_majmin(maj, wh->major);
set_majmin(min, wh->minor);
seq_printf(m, "%c %s:%s %s\n", type_to_char(wh->type),
maj, min, acc);
}
- spin_unlock(&devcgroup->lock);
+ rcu_read_unlock();
return 0;
}
@@ -312,10 +325,10 @@ static int may_access_whitelist(struct dev_cgroup *c,
* when adding a new allow rule to a device whitelist, the rule
* must be allowed in the parent device
*/
-static int parent_has_perm(struct cgroup *childcg,
+static int parent_has_perm(struct dev_cgroup *childcg,
struct dev_whitelist_item *wh)
{
- struct cgroup *pcg = childcg->parent;
+ struct cgroup *pcg = childcg->css.cgroup->parent;
struct dev_cgroup *parent;
int ret;
@@ -341,39 +354,19 @@ static int parent_has_perm(struct cgroup *childcg,
* new access is only allowed if you're in the top-level cgroup, or your
* parent cgroup has the access you're asking for.
*/
-static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
- struct file *file, const char __user *userbuf,
- size_t nbytes, loff_t *ppos)
+static int devcgroup_update_access(struct dev_cgroup *devcgroup,
+ int filetype, const char *buffer)
{
- struct cgroup *cur_cgroup;
- struct dev_cgroup *devcgroup, *cur_devcgroup;
- int filetype = cft->private;
- char *buffer, *b;
+ struct dev_cgroup *cur_devcgroup;
+ const char *b;
+ char *endp;
int retval = 0, count;
struct dev_whitelist_item wh;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- devcgroup = cgroup_to_devcgroup(cgroup);
- cur_cgroup = task_cgroup(current, devices_subsys.subsys_id);
- cur_devcgroup = cgroup_to_devcgroup(cur_cgroup);
-
- buffer = kmalloc(nbytes+1, GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
-
- if (copy_from_user(buffer, userbuf, nbytes)) {
- retval = -EFAULT;
- goto out1;
- }
- buffer[nbytes] = 0; /* nul-terminate */
-
- cgroup_lock();
- if (cgroup_is_removed(cgroup)) {
- retval = -ENODEV;
- goto out2;
- }
+ cur_devcgroup = task_devcgroup(current);
memset(&wh, 0, sizeof(wh));
b = buffer;
@@ -392,32 +385,23 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
wh.type = DEV_CHAR;
break;
default:
- retval = -EINVAL;
- goto out2;
+ return -EINVAL;
}
b++;
- if (!isspace(*b)) {
- retval = -EINVAL;
- goto out2;
- }
+ if (!isspace(*b))
+ return -EINVAL;
b++;
if (*b == '*') {
wh.major = ~0;
b++;
} else if (isdigit(*b)) {
- wh.major = 0;
- while (isdigit(*b)) {
- wh.major = wh.major*10+(*b-'0');
- b++;
- }
+ wh.major = simple_strtoul(b, &endp, 10);
+ b = endp;
} else {
- retval = -EINVAL;
- goto out2;
- }
- if (*b != ':') {
- retval = -EINVAL;
- goto out2;
+ return -EINVAL;
}
+ if (*b != ':')
+ return -EINVAL;
b++;
/* read minor */
@@ -425,19 +409,13 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
wh.minor = ~0;
b++;
} else if (isdigit(*b)) {
- wh.minor = 0;
- while (isdigit(*b)) {
- wh.minor = wh.minor*10+(*b-'0');
- b++;
- }
+ wh.minor = simple_strtoul(b, &endp, 10);
+ b = endp;
} else {
- retval = -EINVAL;
- goto out2;
- }
- if (!isspace(*b)) {
- retval = -EINVAL;
- goto out2;
+ return -EINVAL;
}
+ if (!isspace(*b))
+ return -EINVAL;
for (b++, count = 0; count < 3; count++, b++) {
switch (*b) {
case 'r':
@@ -454,8 +432,7 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
count = 3;
break;
default:
- retval = -EINVAL;
- goto out2;
+ return -EINVAL;
}
}
@@ -463,38 +440,39 @@ handle:
retval = 0;
switch (filetype) {
case DEVCG_ALLOW:
- if (!parent_has_perm(cgroup, &wh))
- retval = -EPERM;
- else
- retval = dev_whitelist_add(devcgroup, &wh);
- break;
+ if (!parent_has_perm(devcgroup, &wh))
+ return -EPERM;
+ return dev_whitelist_add(devcgroup, &wh);
case DEVCG_DENY:
dev_whitelist_rm(devcgroup, &wh);
break;
default:
- retval = -EINVAL;
- goto out2;
+ return -EINVAL;
}
+ return 0;
+}
- if (retval == 0)
- retval = nbytes;
-
-out2:
+static int devcgroup_access_write(struct cgroup *cgrp, struct cftype *cft,
+ const char *buffer)
+{
+ int retval;
+ if (!cgroup_lock_live_group(cgrp))
+ return -ENODEV;
+ retval = devcgroup_update_access(cgroup_to_devcgroup(cgrp),
+ cft->private, buffer);
cgroup_unlock();
-out1:
- kfree(buffer);
return retval;
}
static struct cftype dev_cgroup_files[] = {
{
.name = "allow",
- .write = devcgroup_access_write,
+ .write_string = devcgroup_access_write,
.private = DEVCG_ALLOW,
},
{
.name = "deny",
- .write = devcgroup_access_write,
+ .write_string = devcgroup_access_write,
.private = DEVCG_DENY,
},
{
@@ -535,8 +513,8 @@ int devcgroup_inode_permission(struct inode *inode, int mask)
if (!dev_cgroup)
return 0;
- spin_lock(&dev_cgroup->lock);
- list_for_each_entry(wh, &dev_cgroup->whitelist, list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(wh, &dev_cgroup->whitelist, list) {
if (wh->type & DEV_ALL)
goto acc_check;
if ((wh->type & DEV_BLOCK) && !S_ISBLK(inode->i_mode))
@@ -552,10 +530,10 @@ acc_check:
continue;
if ((mask & MAY_READ) && !(wh->access & ACC_READ))
continue;
- spin_unlock(&dev_cgroup->lock);
+ rcu_read_unlock();
return 0;
}
- spin_unlock(&dev_cgroup->lock);
+ rcu_read_unlock();
return -EPERM;
}
@@ -570,7 +548,7 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
if (!dev_cgroup)
return 0;
- spin_lock(&dev_cgroup->lock);
+ rcu_read_lock();
list_for_each_entry(wh, &dev_cgroup->whitelist, list) {
if (wh->type & DEV_ALL)
goto acc_check;
@@ -585,9 +563,9 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
acc_check:
if (!(wh->access & ACC_MKNOD))
continue;
- spin_unlock(&dev_cgroup->lock);
+ rcu_read_unlock();
return 0;
}
- spin_unlock(&dev_cgroup->lock);
+ rcu_read_unlock();
return -EPERM;
}
diff --git a/sound/core/info.c b/sound/core/info.c
index cb5ead3e202..c67773ad929 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/time.h>
+#include <linux/mm.h>
#include <linux/smp_lock.h>
#include <linux/string.h>
#include <sound/core.h>
diff --git a/sound/core/init.c b/sound/core/init.c
index 5c254d498ae..df46bbc25dc 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -548,8 +548,9 @@ int snd_card_register(struct snd_card *card)
snd_assert(card != NULL, return -EINVAL);
#ifndef CONFIG_SYSFS_DEPRECATED
if (!card->card_dev) {
- card->card_dev = device_create(sound_class, card->dev, 0,
- "card%i", card->number);
+ card->card_dev = device_create_drvdata(sound_class, card->dev,
+ MKDEV(0, 0), NULL,
+ "card%i", card->number);
if (IS_ERR(card->card_dev))
card->card_dev = NULL;
}
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 33940139844..d4fafb6eec6 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -35,47 +35,6 @@ config SOUND_AU1550_AC97
tristate "Au1550/Au1200 AC97 Sound"
depends on SOC_AU1550 || SOC_AU1200
-config SOUND_TRIDENT
- tristate "Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core"
- depends on PCI
- ---help---
- Say Y or M if you have a PCI sound card utilizing the Trident
- 4DWave-DX/NX chipset or your mother board chipset has SiS 7018
- or ALi 5451 built-in. The SiS 7018 PCI Audio Core is embedded
- in SiS960 Super South Bridge and SiS540/630 Single Chipset.
- The ALi 5451 PCI Audio Core is embedded in ALi M1535, M1535D,
- M1535+ or M1535D+ South Bridge.
-
- Use lspci -n to find out if your sound card or chipset uses
- Trident 4DWave or SiS 7018. PCI ID 1023:2000 or 1023:2001 stands
- for Trident 4Dwave. PCI ID 1039:7018 stands for SiS7018. PCI ID
- 10B9:5451 stands for ALi5451.
-
- This driver supports S/PDIF in/out (record/playback) for ALi 5451
- embedded in ALi M1535+ and M1535D+. Note that they aren't all
- enabled by default; you can enable them by saying Y to "/proc file
- system support" and "Sysctl support", and after the /proc file
- system has been mounted, executing the command
-
- command what is enabled
-
- echo 0>/proc/ALi5451 pcm out is also set to S/PDIF out. (Default).
-
- echo 1>/proc/ALi5451 use S/PDIF out to output pcm data.
-
- echo 2>/proc/ALi5451 use S/PDIF out to output non-pcm data.
- (AC3...).
-
- echo 3>/proc/ALi5451 record from Ac97 in(MIC, Line in...).
- (Default).
-
- echo 4>/proc/ALi5451 no matter Ac97 settings, record from S/PDIF
- in.
-
-
- This driver differs slightly from OSS/Free, so PLEASE READ the
- comments at the top of <file:sound/oss/trident.c>.
-
config SOUND_MSNDCLAS
tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey"
depends on (m || !STANDALONE) && ISA
diff --git a/sound/oss/Makefile b/sound/oss/Makefile
index 1f86299fae4..c611514f7ff 100644
--- a/sound/oss/Makefile
+++ b/sound/oss/Makefile
@@ -29,11 +29,8 @@ obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o
obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o
obj-$(CONFIG_SOUND_VWSND) += vwsnd.o
obj-$(CONFIG_SOUND_AU1550_AC97) += au1550_ac97.o ac97_codec.o
-obj-$(CONFIG_SOUND_TRIDENT) += trident.o ac97_codec.o
obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o
-obj-$(CONFIG_SOUND_WM97XX) += ac97_plugin_wm97xx.o
-
obj-$(CONFIG_DMASOUND) += dmasound/
# Declare multi-part drivers.
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index a9c23b2502a..7d89c081a08 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -560,17 +560,19 @@ static int __init oss_init(void)
sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
- device_create(sound_class, NULL,
- MKDEV(SOUND_MAJOR, dev_list[i].minor),
- "%s", dev_list[i].name);
+ device_create_drvdata(sound_class, NULL,
+ MKDEV(SOUND_MAJOR, dev_list[i].minor),
+ NULL, "%s", dev_list[i].name);
if (!dev_list[i].num)
continue;
for (j = 1; j < *dev_list[i].num; j++)
- device_create(sound_class, NULL,
- MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)),
- "%s%d", dev_list[i].name, j);
+ device_create_drvdata(sound_class, NULL,
+ MKDEV(SOUND_MAJOR,
+ dev_list[i].minor + (j*0x10)),
+ NULL,
+ "%s%d", dev_list[i].name, j);
}
if (sound_nblocks >= 1024)
diff --git a/sound/oss/trident.c b/sound/oss/trident.c
deleted file mode 100644
index f43f91ef86c..00000000000
--- a/sound/oss/trident.c
+++ /dev/null
@@ -1,4654 +0,0 @@
-/*
- * OSS driver for Linux 2.[46].x for
- *
- * Trident 4D-Wave
- * SiS 7018
- * ALi 5451
- * Tvia/IGST CyberPro 5050
- *
- * Driver: Alan Cox <alan@redhat.com>
- *
- * Built from:
- * Low level code: <audio@tridentmicro.com> from ALSA
- * Framework: Thomas Sailer <sailer@ife.ee.ethz.ch>
- * Extended by: Zach Brown <zab@redhat.com>
- *
- * Hacked up by:
- * Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
- * Ollie Lho <ollie@sis.com.tw> SiS 7018 Audio Core Support
- * Ching-Ling Lee <cling-li@ali.com.tw> ALi 5451 Audio Core Support
- * Matt Wu <mattwu@acersoftech.com.cn> ALi 5451 Audio Core Support
- * Peter Wächtler <pwaechtler@loewe-komp.de> CyberPro5050 support
- * Muli Ben-Yehuda <mulix@mulix.org>
- *
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * History
- * v0.14.10j
- * January 3 2004 Eugene Teo <eugeneteo@eugeneteo.net>
- * minor cleanup to use pr_debug instead of TRDBG since it is already
- * defined in linux/kernel.h.
- * v0.14.10i
- * December 29 2003 Muli Ben-Yehuda <mulix@mulix.org>
- * major cleanup for 2.6, fix a few error patch buglets
- * with returning without properly cleaning up first,
- * get rid of lock_kernel().
- * v0.14.10h
- * Sept 10 2002 Pascal Schmidt <der.eremit@email.de>
- * added support for ALi 5451 joystick port
- * v0.14.10g
- * Sept 05 2002 Alan Cox <alan@redhat.com>
- * adapt to new pci joystick attachment interface
- * v0.14.10f
- * July 24 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- * patch from Eric Lemar (via Ian Soboroff): in suspend and resume,
- * fix wrong cast from pci_dev* to struct trident_card*.
- * v0.14.10e
- * July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- * rewrite the DMA buffer allocation/deallcoation functions, to make it
- * modular and fix a bug where we would call free_pages on memory
- * obtained with pci_alloc_consistent. Also remove unnecessary #ifdef
- * CONFIG_PROC_FS and various other cleanups.
- * v0.14.10d
- * July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- * made several printk(KERN_NOTICE...) into TRDBG(...), to avoid spamming
- * my syslog with hundreds of messages.
- * v0.14.10c
- * July 16 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- * Cleaned up Lei Hu's 0.4.10 driver to conform to Documentation/CodingStyle
- * and the coding style used in the rest of the file.
- * v0.14.10b
- * June 23 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- * add a missing unlock_set_fmt, remove a superflous lock/unlock pair
- * with nothing in between.
- * v0.14.10a
- * June 21 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
- * use a debug macro instead of #ifdef CONFIG_DEBUG, trim to 80 columns
- * per line, use 'do {} while (0)' in statement macros.
- * v0.14.10
- * June 6 2002 Lei Hu <Lei_hu@ali.com.tw>
- * rewrite the part to read/write registers of audio codec for Ali5451
- * v0.14.9e
- * January 2 2002 Vojtech Pavlik <vojtech@ucw.cz> added gameport
- * support to avoid resource conflict with pcigame.c
- * v0.14.9d
- * October 8 2001 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- * use set_current_state, properly release resources on failure in
- * trident_probe, get rid of check_region
- * v0.14.9c
- * August 10 2001 Peter Wächtler <pwaechtler@loewe-komp.de>
- * added support for Tvia (formerly Integraphics/IGST) CyberPro5050
- * this chip is often found in settop boxes (combined video+audio)
- * v0.14.9b
- * Switch to static inline not extern inline (gcc 3)
- * v0.14.9a
- * Aug 6 2001 Alan Cox
- * 0.14.9 crashed on rmmod due to a timer/bh left running. Simplified
- * the existing logic (the BH doesn't help as ac97 is lock_irqsave)
- * and used del_timer_sync to clean up
- * Fixed a problem where the ALi change broke my generic card
- * v0.14.9
- * Jul 10 2001 Matt Wu
- * Add H/W Volume Control
- * v0.14.8a
- * July 7 2001 Alan Cox
- * Moved Matt Wu's ac97 register cache into the card structure
- * v0.14.8
- * Apr 30 2001 Matt Wu
- * Set EBUF1 and EBUF2 to still mode
- * Add dc97/ac97 reset function
- * Fix power management: ali_restore_regs
- * unreleased
- * Mar 09 2001 Matt Wu
- * Add cache for ac97 access
- * v0.14.7
- * Feb 06 2001 Matt Wu
- * Fix ac97 initialization
- * Fix bug: an extra tail will be played when playing
- * Jan 05 2001 Matt Wu
- * Implement multi-channels and S/PDIF in support for ALi 1535+
- * v0.14.6
- * Nov 1 2000 Ching-Ling Lee
- * Fix the bug of memory leak when switching 5.1-channels to 2 channels.
- * Add lock protection into dynamic changing format of data.
- * Oct 18 2000 Ching-Ling Lee
- * 5.1-channels support for ALi
- * June 28 2000 Ching-Ling Lee
- * S/PDIF out/in(playback/record) support for ALi 1535+, using /proc to be selected by user
- * Simple Power Management support for ALi
- * v0.14.5 May 23 2000 Ollie Lho
- * Misc bug fix from the Net
- * v0.14.4 May 20 2000 Aaron Holtzman
- * Fix kfree'd memory access in release
- * Fix race in open while looking for a free virtual channel slot
- * remove open_wait wq (which appears to be unused)
- * v0.14.3 May 10 2000 Ollie Lho
- * fixed a small bug in trident_update_ptr, xmms 1.0.1 no longer uses 100% CPU
- * v0.14.2 Mar 29 2000 Ching-Ling Lee
- * Add clear to silence advance in trident_update_ptr
- * fix invalid data of the end of the sound
- * v0.14.1 Mar 24 2000 Ching-Ling Lee
- * ALi 5451 support added, playback and recording O.K.
- * ALi 5451 originally developed and structured based on sonicvibes, and
- * suggested to merge into this file by Alan Cox.
- * v0.14 Mar 15 2000 Ollie Lho
- * 5.1 channel output support with channel binding. What's the Matrix ?
- * v0.13.1 Mar 10 2000 Ollie Lho
- * few minor bugs on dual codec support, needs more testing
- * v0.13 Mar 03 2000 Ollie Lho
- * new pci_* for 2.4 kernel, back ported to 2.2
- * v0.12 Feb 23 2000 Ollie Lho
- * Preliminary Recording support
- * v0.11.2 Feb 19 2000 Ollie Lho
- * removed incomplete full-dulplex support
- * v0.11.1 Jan 28 2000 Ollie Lho
- * small bug in setting sample rate for 4d-nx (reported by Aaron)
- * v0.11 Jan 27 2000 Ollie Lho
- * DMA bug, scheduler latency, second try
- * v0.10 Jan 24 2000 Ollie Lho
- * DMA bug fixed, found kernel scheduling problem
- * v0.09 Jan 20 2000 Ollie Lho
- * Clean up of channel register access routine (prepare for channel binding)
- * v0.08 Jan 14 2000 Ollie Lho
- * Isolation of AC97 codec code
- * v0.07 Jan 13 2000 Ollie Lho
- * Get rid of ugly old low level access routines (e.g. CHRegs.lp****)
- * v0.06 Jan 11 2000 Ollie Lho
- * Preliminary support for dual (more ?) AC97 codecs
- * v0.05 Jan 08 2000 Luca Montecchiani <m.luca@iname.com>
- * adapt to 2.3.x new __setup/__init call
- * v0.04 Dec 31 1999 Ollie Lho
- * Multiple Open, using Middle Loop Interrupt to smooth playback
- * v0.03 Dec 24 1999 Ollie Lho
- * mem leak in prog_dmabuf and dealloc_dmabuf removed
- * v0.02 Dec 15 1999 Ollie Lho
- * SiS 7018 support added, playback O.K.
- * v0.01 Alan Cox et. al.
- * Initial Release in kernel 2.3.30, does not work
- *
- * ToDo
- * Clean up of low level channel register access code. (done)
- * Fix the bug on dma buffer management in update_ptr, read/write, drain_dac (done)
- * Dual AC97 codecs support (done)
- * Recording support (done)
- * Mmap support
- * "Channel Binding" ioctl extension (done)
- * new pci device driver interface for 2.4 kernel (done)
- *
- * Lock order (high->low)
- * lock - hardware lock
- * open_mutex - guard opens
- * sem - guard dmabuf, write re-entry etc
- */
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/sound.h>
-#include <linux/slab.h>
-#include <linux/soundcard.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/spinlock.h>
-#include <linux/ac97_codec.h>
-#include <linux/bitops.h>
-#include <linux/proc_fs.h>
-#include <linux/interrupt.h>
-#include <linux/pm.h>
-#include <linux/gameport.h>
-#include <linux/kernel.h>
-#include <linux/mutex.h>
-#include <linux/mm.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#if defined(CONFIG_ALPHA_NAUTILUS) || defined(CONFIG_ALPHA_GENERIC)
-#include <asm/hwrpb.h>
-#endif
-
-#include "trident.h"
-
-#define DRIVER_VERSION "0.14.10j-2.6"
-
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-#define SUPPORT_JOYSTICK 1
-#endif
-
-/* magic numbers to protect our data structures */
-#define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */
-#define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */
-
-#define TRIDENT_DMA_MASK 0x3fffffff /* DMA buffer mask for pci_alloc_consist */
-#define ALI_DMA_MASK 0x7fffffff /* ALI Tridents have 31-bit DMA. Wow. */
-
-#define NR_HW_CH 32
-
-/* maximum number of AC97 codecs connected, AC97 2.0 defined 4, but 7018 and 4D-NX only
- have 2 SDATA_IN lines (currently) */
-#define NR_AC97 2
-
-/* minor number of /dev/swmodem (temporary, experimental) */
-#define SND_DEV_SWMODEM 7
-
-static const unsigned ali_multi_channels_5_1[] = {
- /*ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL, */
- ALI_CENTER_CHANNEL,
- ALI_LEF_CHANNEL,
- ALI_SURR_LEFT_CHANNEL,
- ALI_SURR_RIGHT_CHANNEL
-};
-
-static const unsigned sample_size[] = { 1, 2, 2, 4 };
-static const unsigned sample_shift[] = { 0, 1, 1, 2 };
-
-static const char invalid_magic[] = KERN_CRIT "trident: invalid magic value in %s\n";
-
-enum {
- TRIDENT_4D_DX = 0,
- TRIDENT_4D_NX,
- SIS_7018,
- ALI_5451,
- CYBER5050
-};
-
-static char *card_names[] = {
- "Trident 4DWave DX",
- "Trident 4DWave NX",
- "SiS 7018 PCI Audio",
- "ALi Audio Accelerator",
- "Tvia/IGST CyberPro 5050"
-};
-
-static struct pci_device_id trident_pci_tbl[] = {
- {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX),
- PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TRIDENT_4D_DX},
- {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX),
- 0, 0, TRIDENT_4D_NX},
- {PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018), 0, 0, SIS_7018},
- {PCI_DEVICE(PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451), 0, 0, ALI_5451},
- {PCI_DEVICE(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050),
- 0, 0, CYBER5050},
- {0,}
-};
-
-MODULE_DEVICE_TABLE(pci, trident_pci_tbl);
-
-/* "software" or virtual channel, an instance of opened /dev/dsp */
-struct trident_state {
- unsigned int magic;
- struct trident_card *card; /* Card info */
-
- /* file mode */
- mode_t open_mode;
-
- /* virtual channel number */
- int virt;
-
- struct dmabuf {
- /* wave sample stuff */
- unsigned int rate;
- unsigned char fmt, enable;
-
- /* hardware channel */
- struct trident_channel *channel;
-
- /* OSS buffer management stuff */
- void *rawbuf;
- dma_addr_t dma_handle;
- unsigned buforder;
- unsigned numfrag;
- unsigned fragshift;
-
- /* our buffer acts like a circular ring */
- unsigned hwptr; /* where dma last started, updated by update_ptr */
- unsigned swptr; /* where driver last clear/filled, updated by read/write */
- int count; /* bytes to be comsumed or been generated by dma machine */
- unsigned total_bytes; /* total bytes dmaed by hardware */
-
- unsigned error; /* number of over/underruns */
- /* put process on wait queue when no more space in buffer */
- wait_queue_head_t wait;
-
- /* redundant, but makes calculations easier */
- unsigned fragsize;
- unsigned dmasize;
- unsigned fragsamples;
-
- /* OSS stuff */
- unsigned mapped:1;
- unsigned ready:1;
- unsigned endcleared:1;
- unsigned update_flag;
- unsigned ossfragshift;
- int ossmaxfrags;
- unsigned subdivision;
-
- } dmabuf;
-
- /* 5.1 channels */
- struct trident_state *other_states[4];
- int multi_channels_adjust_count;
- unsigned chans_num;
- unsigned long fmt_flag;
- /* Guard against mmap/write/read races */
- struct mutex sem;
-
-};
-
-/* hardware channels */
-struct trident_channel {
- int num; /* channel number */
- u32 lba; /* Loop Begine Address, where dma buffer starts */
- u32 eso; /* End Sample Offset, wehre dma buffer ends */
- /* (in the unit of samples) */
- u32 delta; /* delta value, sample rate / 48k for playback, */
- /* 48k/sample rate for recording */
- u16 attribute; /* control where PCM data go and come */
- u16 fm_vol;
- u32 control; /* signed/unsigned, 8/16 bits, mono/stereo */
-};
-
-struct trident_pcm_bank_address {
- u32 start;
- u32 stop;
- u32 aint;
- u32 aint_en;
-};
-
-static struct trident_pcm_bank_address bank_a_addrs = {
- T4D_START_A,
- T4D_STOP_A,
- T4D_AINT_A,
- T4D_AINTEN_A
-};
-
-static struct trident_pcm_bank_address bank_b_addrs = {
- T4D_START_B,
- T4D_STOP_B,
- T4D_AINT_B,
- T4D_AINTEN_B
-};
-
-struct trident_pcm_bank {
- /* register addresses to control bank operations */
- struct trident_pcm_bank_address *addresses;
- /* each bank has 32 channels */
- u32 bitmap; /* channel allocation bitmap */
- struct trident_channel channels[32];
-};
-
-struct trident_card {
- unsigned int magic;
-
- /* We keep trident cards in a linked list */
- struct trident_card *next;
-
- /* single open lock mechanism, only used for recording */
- struct mutex open_mutex;
-
- /* The trident has a certain amount of cross channel interaction
- so we use a single per card lock */
- spinlock_t lock;
-
- /* PCI device stuff */
- struct pci_dev *pci_dev;
- u16 pci_id;
- u8 revision;
-
- /* soundcore stuff */
- int dev_audio;
-
- /* structures for abstraction of hardware facilities, codecs, */
- /* banks and channels */
- struct ac97_codec *ac97_codec[NR_AC97];
- struct trident_pcm_bank banks[NR_BANKS];
- struct trident_state *states[NR_HW_CH];
-
- /* hardware resources */
- unsigned long iobase;
- u32 irq;
-
- /* Function support */
- struct trident_channel *(*alloc_pcm_channel) (struct trident_card *);
- struct trident_channel *(*alloc_rec_pcm_channel) (struct trident_card *);
- void (*free_pcm_channel) (struct trident_card *, unsigned int chan);
- void (*address_interrupt) (struct trident_card *);
-
- /* Added by Matt Wu 01-05-2001 for spdif in */
- int multi_channel_use_count;
- int rec_channel_use_count;
- u16 mixer_regs[64][NR_AC97]; /* Made card local by Alan */
- int mixer_regs_ready;
-
- /* Added for hardware volume control */
- int hwvolctl;
- struct timer_list timer;
-
- /* Game port support */
- struct gameport *gameport;
-};
-
-enum dmabuf_mode {
- DM_PLAYBACK = 0,
- DM_RECORD
-};
-
-/* table to map from CHANNELMASK to channel attribute for SiS 7018 */
-static u16 mask2attr[] = {
- PCM_LR, PCM_LR, SURR_LR, CENTER_LFE,
- HSET, MIC, MODEM_LINE1, MODEM_LINE2,
- I2S_LR, SPDIF_LR
-};
-
-/* table to map from channel attribute to CHANNELMASK for SiS 7018 */
-static int attr2mask[] = {
- DSP_BIND_MODEM1, DSP_BIND_MODEM2, DSP_BIND_FRONT, DSP_BIND_HANDSET,
- DSP_BIND_I2S, DSP_BIND_CENTER_LFE, DSP_BIND_SURR, DSP_BIND_SPDIF
-};
-
-/* Added by Matt Wu 01-05-2001 for spdif in */
-static int ali_close_multi_channels(void);
-static void ali_delay(struct trident_card *card, int interval);
-static void ali_detect_spdif_rate(struct trident_card *card);
-
-static void ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val);
-static u16 ali_ac97_read(struct ac97_codec *codec, u8 reg);
-
-static struct trident_card *devs;
-
-static void trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val);
-static u16 trident_ac97_get(struct ac97_codec *codec, u8 reg);
-
-static int trident_open_mixdev(struct inode *inode, struct file *file);
-static int trident_ioctl_mixdev(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
-
-static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val);
-static u16 ali_ac97_get(struct trident_card *card, int secondary, u8 reg);
-static void ali_set_spdif_out_rate(struct trident_card *card, unsigned int rate);
-static void ali_enable_special_channel(struct trident_state *stat);
-static struct trident_channel *ali_alloc_rec_pcm_channel(struct trident_card *card);
-static struct trident_channel *ali_alloc_pcm_channel(struct trident_card *card);
-static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel);
-static int ali_setup_multi_channels(struct trident_card *card, int chan_nums);
-static unsigned int ali_get_spdif_in_rate(struct trident_card *card);
-static void ali_setup_spdif_in(struct trident_card *card);
-static void ali_disable_spdif_in(struct trident_card *card);
-static void ali_disable_special_channel(struct trident_card *card, int ch);
-static void ali_setup_spdif_out(struct trident_card *card, int flag);
-static int ali_write_5_1(struct trident_state *state,
- const char __user *buffer,
- int cnt_for_multi_channel, unsigned int *copy_count,
- unsigned int *state_cnt);
-static int ali_allocate_other_states_resources(struct trident_state *state,
- int chan_nums);
-static void ali_free_other_states_resources(struct trident_state *state);
-
-#define seek_offset(dma_ptr, buffer, cnt, offset, copy_count) do { \
- (dma_ptr) += (offset); \
- (buffer) += (offset); \
- (cnt) -= (offset); \
- (copy_count) += (offset); \
-} while (0)
-
-static inline int lock_set_fmt(struct trident_state* state)
-{
- if (test_and_set_bit(0, &state->fmt_flag))
- return -EFAULT;
-
- return 0;
-}
-
-static inline void unlock_set_fmt(struct trident_state* state)
-{
- clear_bit(0, &state->fmt_flag);
-}
-
-static int
-trident_enable_loop_interrupts(struct trident_card *card)
-{
- u32 global_control;
-
- global_control = inl(TRID_REG(card, T4D_LFO_GC_CIR));
-
- switch (card->pci_id) {
- case PCI_DEVICE_ID_SI_7018:
- global_control |= (ENDLP_IE | MIDLP_IE | BANK_B_EN);
- break;
- case PCI_DEVICE_ID_ALI_5451:
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- case PCI_DEVICE_ID_INTERG_5050:
- global_control |= (ENDLP_IE | MIDLP_IE);
- break;
- default:
- return 0;
- }
-
- outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR));
-
- pr_debug("trident: Enable Loop Interrupts, globctl = 0x%08X\n",
- inl(TRID_REG(card, T4D_LFO_GC_CIR)));
-
- return 1;
-}
-
-static int
-trident_disable_loop_interrupts(struct trident_card *card)
-{
- u32 global_control;
-
- global_control = inl(TRID_REG(card, T4D_LFO_GC_CIR));
- global_control &= ~(ENDLP_IE | MIDLP_IE);
- outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR));
-
- pr_debug("trident: Disabled Loop Interrupts, globctl = 0x%08X\n",
- global_control);
-
- return 1;
-}
-
-static void
-trident_enable_voice_irq(struct trident_card *card, unsigned int channel)
-{
- unsigned int mask = 1 << (channel & 0x1f);
- struct trident_pcm_bank *bank = &card->banks[channel >> 5];
- u32 reg, addr = bank->addresses->aint_en;
-
- reg = inl(TRID_REG(card, addr));
- reg |= mask;
- outl(reg, TRID_REG(card, addr));
-
-#ifdef DEBUG
- reg = inl(TRID_REG(card, addr));
- pr_debug("trident: enabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n",
- channel, addr == T4D_AINTEN_B ? "AINTEN_B" : "AINTEN_A",
- reg, addr);
-#endif /* DEBUG */
-}
-
-static void
-trident_disable_voice_irq(struct trident_card *card, unsigned int channel)
-{
- unsigned int mask = 1 << (channel & 0x1f);
- struct trident_pcm_bank *bank = &card->banks[channel >> 5];
- u32 reg, addr = bank->addresses->aint_en;
-
- reg = inl(TRID_REG(card, addr));
- reg &= ~mask;
- outl(reg, TRID_REG(card, addr));
-
- /* Ack the channel in case the interrupt was set before we disable it. */
- outl(mask, TRID_REG(card, bank->addresses->aint));
-
-#ifdef DEBUG
- reg = inl(TRID_REG(card, addr));
- pr_debug("trident: disabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n",
- channel, addr == T4D_AINTEN_B ? "AINTEN_B" : "AINTEN_A",
- reg, addr);
-#endif /* DEBUG */
-}
-
-static void
-trident_start_voice(struct trident_card *card, unsigned int channel)
-{
- unsigned int mask = 1 << (channel & 0x1f);
- struct trident_pcm_bank *bank = &card->banks[channel >> 5];
- u32 addr = bank->addresses->start;
-
-#ifdef DEBUG
- u32 reg;
-#endif /* DEBUG */
-
- outl(mask, TRID_REG(card, addr));
-
-#ifdef DEBUG
- reg = inl(TRID_REG(card, addr));
- pr_debug("trident: start voice on channel %d, %s = 0x%08x(addr:%X)\n",
- channel, addr == T4D_START_B ? "START_B" : "START_A",
- reg, addr);
-#endif /* DEBUG */
-}
-
-static void
-trident_stop_voice(struct trident_card *card, unsigned int channel)
-{
- unsigned int mask = 1 << (channel & 0x1f);
- struct trident_pcm_bank *bank = &card->banks[channel >> 5];
- u32 addr = bank->addresses->stop;
-
-#ifdef DEBUG
- u32 reg;
-#endif /* DEBUG */
-
- outl(mask, TRID_REG(card, addr));
-
-#ifdef DEBUG
- reg = inl(TRID_REG(card, addr));
- pr_debug("trident: stop voice on channel %d, %s = 0x%08x(addr:%X)\n",
- channel, addr == T4D_STOP_B ? "STOP_B" : "STOP_A",
- reg, addr);
-#endif /* DEBUG */
-}
-
-static u32
-trident_get_interrupt_mask(struct trident_card *card, unsigned int channel)
-{
- struct trident_pcm_bank *bank = &card->banks[channel];
- u32 addr = bank->addresses->aint;
- return inl(TRID_REG(card, addr));
-}
-
-static int
-trident_check_channel_interrupt(struct trident_card *card, unsigned int channel)
-{
- unsigned int mask = 1 << (channel & 0x1f);
- u32 reg = trident_get_interrupt_mask(card, channel >> 5);
-
-#ifdef DEBUG
- if (reg & mask)
- pr_debug("trident: channel %d has interrupt, %s = 0x%08x\n",
- channel, reg == T4D_AINT_B ? "AINT_B" : "AINT_A",
- reg);
-#endif /* DEBUG */
- return (reg & mask) ? 1 : 0;
-}
-
-static void
-trident_ack_channel_interrupt(struct trident_card *card, unsigned int channel)
-{
- unsigned int mask = 1 << (channel & 0x1f);
- struct trident_pcm_bank *bank = &card->banks[channel >> 5];
- u32 reg, addr = bank->addresses->aint;
-
- reg = inl(TRID_REG(card, addr));
- reg &= mask;
- outl(reg, TRID_REG(card, addr));
-
-#ifdef DEBUG
- reg = inl(TRID_REG(card, T4D_AINT_B));
- pr_debug("trident: Ack channel %d interrupt, AINT_B = 0x%08x\n",
- channel, reg);
-#endif /* DEBUG */
-}
-
-static struct trident_channel *
-trident_alloc_pcm_channel(struct trident_card *card)
-{
- struct trident_pcm_bank *bank;
- int idx;
-
- bank = &card->banks[BANK_B];
-
- for (idx = 31; idx >= 0; idx--) {
- if (!(bank->bitmap & (1 << idx))) {
- struct trident_channel *channel = &bank->channels[idx];
- bank->bitmap |= 1 << idx;
- channel->num = idx + 32;
- return channel;
- }
- }
-
- /* no more free channels available */
- printk(KERN_ERR "trident: no more channels available on Bank B.\n");
- return NULL;
-}
-
-static void
-trident_free_pcm_channel(struct trident_card *card, unsigned int channel)
-{
- int bank;
- unsigned char b;
-
- if (channel < 31 || channel > 63)
- return;
-
- if (card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_DX ||
- card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_NX) {
- b = inb(TRID_REG(card, T4D_REC_CH));
- if ((b & ~0x80) == channel)
- outb(0x0, TRID_REG(card, T4D_REC_CH));
- }
-
- bank = channel >> 5;
- channel = channel & 0x1f;
-
- card->banks[bank].bitmap &= ~(1 << (channel));
-}
-
-static struct trident_channel *
-cyber_alloc_pcm_channel(struct trident_card *card)
-{
- struct trident_pcm_bank *bank;
- int idx;
-
- /* The cyberpro 5050 has only 32 voices and one bank */
- /* .. at least they are not documented (if you want to call that
- * crap documentation), perhaps broken ? */
-
- bank = &card->banks[BANK_A];
-
- for (idx = 31; idx >= 0; idx--) {
- if (!(bank->bitmap & (1 << idx))) {
- struct trident_channel *channel = &bank->channels[idx];
- bank->bitmap |= 1 << idx;
- channel->num = idx;
- return channel;
- }
- }
-
- /* no more free channels available */
- printk(KERN_ERR "cyberpro5050: no more channels available on Bank A.\n");
- return NULL;
-}
-
-static void
-cyber_free_pcm_channel(struct trident_card *card, unsigned int channel)
-{
- if (channel > 31)
- return;
- card->banks[BANK_A].bitmap &= ~(1 << (channel));
-}
-
-static inline void
-cyber_outidx(int port, int idx, int data)
-{
- outb(idx, port);
- outb(data, port + 1);
-}
-
-static inline int
-cyber_inidx(int port, int idx)
-{
- outb(idx, port);
- return inb(port + 1);
-}
-
-static int
-cyber_init_ritual(struct trident_card *card)
-{
- /* some black magic, taken from SDK samples */
- /* remove this and nothing will work */
- int portDat;
- int ret = 0;
- unsigned long flags;
-
- /*
- * Keep interrupts off for the configure - we don't want to
- * clash with another cyberpro config event
- */
-
- spin_lock_irqsave(&card->lock, flags);
- portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE);
- /* enable, if it was disabled */
- if ((portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE) {
- printk(KERN_INFO "cyberpro5050: enabling audio controller\n");
- cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE,
- portDat | CYBER_BMSK_AUENZ_ENABLE);
- /* check again if hardware is enabled now */
- portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE);
- }
- if ((portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE) {
- printk(KERN_ERR "cyberpro5050: initAudioAccess: no success\n");
- ret = -1;
- } else {
- cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_IRQ_ENABLE,
- CYBER_BMSK_AUDIO_INT_ENABLE);
- cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x01);
- cyber_outidx(CYBER_PORT_AUDIO, 0xba, 0x20);
- cyber_outidx(CYBER_PORT_AUDIO, 0xbb, 0x08);
- cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x02);
- cyber_outidx(CYBER_PORT_AUDIO, 0xb3, 0x06);
- cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x00);
- }
- spin_unlock_irqrestore(&card->lock, flags);
- return ret;
-}
-
-/* called with spin lock held */
-
-static int
-trident_load_channel_registers(struct trident_card *card, u32 * data,
- unsigned int channel)
-{
- int i;
-
- if (channel > 63)
- return 0;
-
- /* select hardware channel to write */
- outb(channel, TRID_REG(card, T4D_LFO_GC_CIR));
-
- /* Output the channel registers, but don't write register
- three to an ALI chip. */
- for (i = 0; i < CHANNEL_REGS; i++) {
- if (i == 3 && card->pci_id == PCI_DEVICE_ID_ALI_5451)
- continue;
- outl(data[i], TRID_REG(card, CHANNEL_START + 4 * i));
- }
- if (card->pci_id == PCI_DEVICE_ID_ALI_5451 ||
- card->pci_id == PCI_DEVICE_ID_INTERG_5050) {
- outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF1));
- outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF2));
- }
- return 1;
-}
-
-/* called with spin lock held */
-static int
-trident_write_voice_regs(struct trident_state *state)
-{
- unsigned int data[CHANNEL_REGS + 1];
- struct trident_channel *channel;
-
- channel = state->dmabuf.channel;
-
- data[1] = channel->lba;
- data[4] = channel->control;
-
- switch (state->card->pci_id) {
- case PCI_DEVICE_ID_ALI_5451:
- data[0] = 0; /* Current Sample Offset */
- data[2] = (channel->eso << 16) | (channel->delta & 0xffff);
- data[3] = 0;
- break;
- case PCI_DEVICE_ID_SI_7018:
- case PCI_DEVICE_ID_INTERG_5050:
- data[0] = 0; /* Current Sample Offset */
- data[2] = (channel->eso << 16) | (channel->delta & 0xffff);
- data[3] = (channel->attribute << 16) | (channel->fm_vol & 0xffff);
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
- data[0] = 0; /* Current Sample Offset */
- data[2] = (channel->eso << 16) | (channel->delta & 0xffff);
- data[3] = channel->fm_vol & 0xffff;
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- data[0] = (channel->delta << 24);
- data[2] = ((channel->delta << 16) & 0xff000000) |
- (channel->eso & 0x00ffffff);
- data[3] = channel->fm_vol & 0xffff;
- break;
- default:
- return 0;
- }
-
- return trident_load_channel_registers(state->card, data, channel->num);
-}
-
-static int
-compute_rate_play(u32 rate)
-{
- int delta;
- /* We special case 44100 and 8000 since rounding with the equation
- does not give us an accurate enough value. For 11025 and 22050
- the equation gives us the best answer. All other frequencies will
- also use the equation. JDW */
- if (rate == 44100)
- delta = 0xeb3;
- else if (rate == 8000)
- delta = 0x2ab;
- else if (rate == 48000)
- delta = 0x1000;
- else
- delta = (((rate << 12) + rate) / 48000) & 0x0000ffff;
- return delta;
-}
-
-static int
-compute_rate_rec(u32 rate)
-{
- int delta;
-
- if (rate == 44100)
- delta = 0x116a;
- else if (rate == 8000)
- delta = 0x6000;
- else if (rate == 48000)
- delta = 0x1000;
- else
- delta = ((48000 << 12) / rate) & 0x0000ffff;
-
- return delta;
-}
-
-/* set playback sample rate */
-static unsigned int
-trident_set_dac_rate(struct trident_state *state, unsigned int rate)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
-
- if (rate > 48000)
- rate = 48000;
- if (rate < 4000)
- rate = 4000;
-
- dmabuf->rate = rate;
- dmabuf->channel->delta = compute_rate_play(rate);
-
- trident_write_voice_regs(state);
-
- pr_debug("trident: called trident_set_dac_rate : rate = %d\n", rate);
-
- return rate;
-}
-
-/* set recording sample rate */
-static unsigned int
-trident_set_adc_rate(struct trident_state *state, unsigned int rate)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
-
- if (rate > 48000)
- rate = 48000;
- if (rate < 4000)
- rate = 4000;
-
- dmabuf->rate = rate;
- dmabuf->channel->delta = compute_rate_rec(rate);
-
- trident_write_voice_regs(state);
-
- pr_debug("trident: called trident_set_adc_rate : rate = %d\n", rate);
-
- return rate;
-}
-
-/* prepare channel attributes for playback */
-static void
-trident_play_setup(struct trident_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- struct trident_channel *channel = dmabuf->channel;
-
- channel->lba = dmabuf->dma_handle;
- channel->delta = compute_rate_play(dmabuf->rate);
-
- channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt];
- channel->eso -= 1;
-
- if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) {
- channel->attribute = 0;
- if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451) {
- if ((channel->num == ALI_SPDIF_IN_CHANNEL) ||
- (channel->num == ALI_PCM_IN_CHANNEL))
- ali_disable_special_channel(state->card, channel->num);
- else if ((inl(TRID_REG(state->card, ALI_GLOBAL_CONTROL))
- & ALI_SPDIF_OUT_CH_ENABLE)
- && (channel->num == ALI_SPDIF_OUT_CHANNEL)) {
- ali_set_spdif_out_rate(state->card,
- state->dmabuf.rate);
- state->dmabuf.channel->delta = 0x1000;
- }
- }
- }
-
- channel->fm_vol = 0x0;
-
- channel->control = CHANNEL_LOOP;
- if (dmabuf->fmt & TRIDENT_FMT_16BIT) {
- /* 16-bits */
- channel->control |= CHANNEL_16BITS;
- /* signed */
- channel->control |= CHANNEL_SIGNED;
- }
- if (dmabuf->fmt & TRIDENT_FMT_STEREO)
- /* stereo */
- channel->control |= CHANNEL_STEREO;
-
- pr_debug("trident: trident_play_setup, LBA = 0x%08x, Delta = 0x%08x, "
- "ESO = 0x%08x, Control = 0x%08x\n", channel->lba,
- channel->delta, channel->eso, channel->control);
-
- trident_write_voice_regs(state);
-}
-
-/* prepare channel attributes for recording */
-static void
-trident_rec_setup(struct trident_state *state)
-{
- u16 w;
- u8 bval;
-
- struct trident_card *card = state->card;
- struct dmabuf *dmabuf = &state->dmabuf;
- struct trident_channel *channel = dmabuf->channel;
- unsigned int rate;
-
- /* Enable AC-97 ADC (capture) */
- switch (card->pci_id) {
- case PCI_DEVICE_ID_ALI_5451:
- ali_enable_special_channel(state);
- break;
- case PCI_DEVICE_ID_SI_7018:
- /* for 7018, the ac97 is always in playback/record (duplex) mode */
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
- w = inb(TRID_REG(card, DX_ACR2_AC97_COM_STAT));
- outb(w | 0x48, TRID_REG(card, DX_ACR2_AC97_COM_STAT));
- /* enable and set record channel */
- outb(0x80 | channel->num, TRID_REG(card, T4D_REC_CH));
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- w = inw(TRID_REG(card, T4D_MISCINT));
- outw(w | 0x1000, TRID_REG(card, T4D_MISCINT));
- /* enable and set record channel */
- outb(0x80 | channel->num, TRID_REG(card, T4D_REC_CH));
- break;
- case PCI_DEVICE_ID_INTERG_5050:
- /* don't know yet, using special channel 22 in GC1(0xd4)? */
- break;
- default:
- return;
- }
-
- channel->lba = dmabuf->dma_handle;
- channel->delta = compute_rate_rec(dmabuf->rate);
- if ((card->pci_id == PCI_DEVICE_ID_ALI_5451) &&
- (channel->num == ALI_SPDIF_IN_CHANNEL)) {
- rate = ali_get_spdif_in_rate(card);
- if (rate == 0) {
- printk(KERN_WARNING "trident: ALi 5451 "
- "S/PDIF input setup error!\n");
- rate = 48000;
- }
- bval = inb(TRID_REG(card, ALI_SPDIF_CTRL));
- if (bval & 0x10) {
- outb(bval, TRID_REG(card, ALI_SPDIF_CTRL));
- printk(KERN_WARNING "trident: cleared ALi "
- "5451 S/PDIF parity error flag.\n");
- }
-
- if (rate != 48000)
- channel->delta = ((rate << 12) / dmabuf->rate) & 0x0000ffff;
- }
-
- channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt];
- channel->eso -= 1;
-
- if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) {
- channel->attribute = 0;
- }
-
- channel->fm_vol = 0x0;
-
- channel->control = CHANNEL_LOOP;
- if (dmabuf->fmt & TRIDENT_FMT_16BIT) {
- /* 16-bits */
- channel->control |= CHANNEL_16BITS;
- /* signed */
- channel->control |= CHANNEL_SIGNED;
- }
- if (dmabuf->fmt & TRIDENT_FMT_STEREO)
- /* stereo */
- channel->control |= CHANNEL_STEREO;
-
- pr_debug("trident: trident_rec_setup, LBA = 0x%08x, Delat = 0x%08x, "
- "ESO = 0x%08x, Control = 0x%08x\n", channel->lba,
- channel->delta, channel->eso, channel->control);
-
- trident_write_voice_regs(state);
-}
-
-/* get current playback/recording dma buffer pointer (byte offset from LBA),
- called with spinlock held! */
-static inline unsigned
-trident_get_dma_addr(struct trident_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- u32 cso;
-
- if (!dmabuf->enable)
- return 0;
-
- outb(dmabuf->channel->num, TRID_REG(state->card, T4D_LFO_GC_CIR));
-
- switch (state->card->pci_id) {
- case PCI_DEVICE_ID_ALI_5451:
- case PCI_DEVICE_ID_SI_7018:
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
- case PCI_DEVICE_ID_INTERG_5050:
- /* 16 bits ESO, CSO for 7018 and DX */
- cso = inw(TRID_REG(state->card, CH_DX_CSO_ALPHA_FMS + 2));
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- /* 24 bits ESO, CSO for NX */
- cso = inl(TRID_REG(state->card, CH_NX_DELTA_CSO)) & 0x00ffffff;
- break;
- default:
- return 0;
- }
-
- pr_debug("trident: trident_get_dma_addr: chip reported channel: %d, "
- "cso = 0x%04x\n", dmabuf->channel->num, cso);
-
- /* ESO and CSO are in units of Samples, convert to byte offset */
- cso <<= sample_shift[dmabuf->fmt];
-
- return (cso % dmabuf->dmasize);
-}
-
-/* Stop recording (lock held) */
-static inline void
-__stop_adc(struct trident_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- unsigned int chan_num = dmabuf->channel->num;
- struct trident_card *card = state->card;
-
- dmabuf->enable &= ~ADC_RUNNING;
- trident_stop_voice(card, chan_num);
- trident_disable_voice_irq(card, chan_num);
-}
-
-static void
-stop_adc(struct trident_state *state)
-{
- struct trident_card *card = state->card;
- unsigned long flags;
-
- spin_lock_irqsave(&card->lock, flags);
- __stop_adc(state);
- spin_unlock_irqrestore(&card->lock, flags);
-}
-
-static void
-start_adc(struct trident_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- unsigned int chan_num = dmabuf->channel->num;
- struct trident_card *card = state->card;
- unsigned long flags;
-
- spin_lock_irqsave(&card->lock, flags);
- if ((dmabuf->mapped ||
- dmabuf->count < (signed) dmabuf->dmasize) &&
- dmabuf->ready) {
- dmabuf->enable |= ADC_RUNNING;
- trident_enable_voice_irq(card, chan_num);
- trident_start_voice(card, chan_num);
- }
- spin_unlock_irqrestore(&card->lock, flags);
-}
-
-/* stop playback (lock held) */
-static inline void
-__stop_dac(struct trident_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- unsigned int chan_num = dmabuf->channel->num;
- struct trident_card *card = state->card;
-
- dmabuf->enable &= ~DAC_RUNNING;
- trident_stop_voice(card, chan_num);
- if (state->chans_num == 6) {
- trident_stop_voice(card, state->other_states[0]->
- dmabuf.channel->num);
- trident_stop_voice(card, state->other_states[1]->
- dmabuf.channel->num);
- trident_stop_voice(card, state->other_states[2]->
- dmabuf.channel->num);
- trident_stop_voice(card, state->other_states[3]->
- dmabuf.channel->num);
- }
- trident_disable_voice_irq(card, chan_num);
-}
-
-static void
-stop_dac(struct trident_state *state)
-{
- struct trident_card *card = state->card;
- unsigned long flags;
-
- spin_lock_irqsave(&card->lock, flags);
- __stop_dac(state);
- spin_unlock_irqrestore(&card->lock, flags);
-}
-
-static void
-start_dac(struct trident_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- unsigned int chan_num = dmabuf->channel->num;
- struct trident_card *card = state->card;
- unsigned long flags;
-
- spin_lock_irqsave(&card->lock, flags);
- if ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready) {
- dmabuf->enable |= DAC_RUNNING;
- trident_enable_voice_irq(card, chan_num);
- trident_start_voice(card, chan_num);
- if (state->chans_num == 6) {
- trident_start_voice(card, state->other_states[0]->
- dmabuf.channel->num);
- trident_start_voice(card, state->other_states[1]->
- dmabuf.channel->num);
- trident_start_voice(card, state->other_states[2]->
- dmabuf.channel->num);
- trident_start_voice(card, state->other_states[3]->
- dmabuf.channel->num);
- }
- }
- spin_unlock_irqrestore(&card->lock, flags);
-}
-
-#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)
-#define DMABUF_MINORDER 1
-
-/* alloc a DMA buffer of with a buffer of this order */
-static int
-alloc_dmabuf(struct dmabuf *dmabuf, struct pci_dev *pci_dev, int order)
-{
- void *rawbuf = NULL;
- struct page *page, *pend;
-
- if (!(rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order,
- &dmabuf->dma_handle)))
- return -ENOMEM;
-
- pr_debug("trident: allocated %ld (order = %d) bytes at %p\n",
- PAGE_SIZE << order, order, rawbuf);
-
- dmabuf->ready = dmabuf->mapped = 0;
- dmabuf->rawbuf = rawbuf;
- dmabuf->buforder = order;
-
- /* now mark the pages as reserved; otherwise */
- /* remap_pfn_range doesn't do what we want */
- pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1);
- for (page = virt_to_page(rawbuf); page <= pend; page++)
- SetPageReserved(page);
-
- return 0;
-}
-
-/* allocate the main DMA buffer, playback and recording buffer should be */
-/* allocated separately */
-static int
-alloc_main_dmabuf(struct trident_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- int order;
- int ret = -ENOMEM;
-
- /* alloc as big a chunk as we can, FIXME: is this necessary ?? */
- for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) {
- if (!(ret = alloc_dmabuf(dmabuf, state->card->pci_dev, order)))
- return 0;
- /* else try again */
- }
- return ret;
-}
-
-/* deallocate a DMA buffer */
-static void
-dealloc_dmabuf(struct dmabuf *dmabuf, struct pci_dev *pci_dev)
-{
- struct page *page, *pend;
-
- if (dmabuf->rawbuf) {
- /* undo marking the pages as reserved */
- pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1);
- for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++)
- ClearPageReserved(page);
- pci_free_consistent(pci_dev, PAGE_SIZE << dmabuf->buforder,
- dmabuf->rawbuf, dmabuf->dma_handle);
- dmabuf->rawbuf = NULL;
- }
- dmabuf->mapped = dmabuf->ready = 0;
-}
-
-static int
-prog_dmabuf(struct trident_state *state, enum dmabuf_mode rec)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- unsigned bytepersec;
- struct trident_state *s = state;
- unsigned bufsize, dma_nums;
- unsigned long flags;
- int ret, i, order;
-
- if ((ret = lock_set_fmt(state)) < 0)
- return ret;
-
- if (state->chans_num == 6)
- dma_nums = 5;
- else
- dma_nums = 1;
-
- for (i = 0; i < dma_nums; i++) {
- if (i > 0) {
- s = state->other_states[i - 1];
- dmabuf = &s->dmabuf;
- dmabuf->fmt = state->dmabuf.fmt;
- dmabuf->rate = state->dmabuf.rate;
- }
-
- spin_lock_irqsave(&s->card->lock, flags);
- dmabuf->hwptr = dmabuf->swptr = dmabuf->total_bytes = 0;
- dmabuf->count = dmabuf->error = 0;
- spin_unlock_irqrestore(&s->card->lock, flags);
-
- /* allocate DMA buffer if not allocated yet */
- if (!dmabuf->rawbuf) {
- if (i == 0) {
- if ((ret = alloc_main_dmabuf(state))) {
- unlock_set_fmt(state);
- return ret;
- }
- } else {
- ret = -ENOMEM;
- order = state->dmabuf.buforder - 1;
- if (order >= DMABUF_MINORDER) {
- ret = alloc_dmabuf(dmabuf,
- state->card->pci_dev,
- order);
- }
- if (ret) {
- /* release the main DMA buffer */
- dealloc_dmabuf(&state->dmabuf, state->card->pci_dev);
- /* release the auxiliary DMA buffers */
- for (i -= 2; i >= 0; i--)
- dealloc_dmabuf(&state->other_states[i]->dmabuf,
- state->card->pci_dev);
- unlock_set_fmt(state);
- return ret;
- }
- }
- }
- /* FIXME: figure out all this OSS fragment stuff */
- bytepersec = dmabuf->rate << sample_shift[dmabuf->fmt];
- bufsize = PAGE_SIZE << dmabuf->buforder;
- if (dmabuf->ossfragshift) {
- if ((1000 << dmabuf->ossfragshift) < bytepersec)
- dmabuf->fragshift = ld2(bytepersec / 1000);
- else
- dmabuf->fragshift = dmabuf->ossfragshift;
- } else {
- /* lets hand out reasonable big ass buffers by default */
- dmabuf->fragshift = (dmabuf->buforder + PAGE_SHIFT - 2);
- }
- dmabuf->numfrag = bufsize >> dmabuf->fragshift;
- while (dmabuf->numfrag < 4 && dmabuf->fragshift > 3) {
- dmabuf->fragshift--;
- dmabuf->numfrag = bufsize >> dmabuf->fragshift;
- }
- dmabuf->fragsize = 1 << dmabuf->fragshift;
- if (dmabuf->ossmaxfrags >= 4 && dmabuf->ossmaxfrags < dmabuf->numfrag)
- dmabuf->numfrag = dmabuf->ossmaxfrags;
- dmabuf->fragsamples = dmabuf->fragsize >> sample_shift[dmabuf->fmt];
- dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift;
-
- memset(dmabuf->rawbuf, (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80,
- dmabuf->dmasize);
-
- spin_lock_irqsave(&s->card->lock, flags);
- if (rec == DM_RECORD)
- trident_rec_setup(s);
- else /* DM_PLAYBACK */
- trident_play_setup(s);
-
- spin_unlock_irqrestore(&s->card->lock, flags);
-
- /* set the ready flag for the dma buffer */
- dmabuf->ready = 1;
-
- pr_debug("trident: prog_dmabuf(%d), sample rate = %d, "
- "format = %d, numfrag = %d, fragsize = %d "
- "dmasize = %d\n", dmabuf->channel->num,
- dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,
- dmabuf->fragsize, dmabuf->dmasize);
- }
- unlock_set_fmt(state);
- return 0;
-}
-
-
-static inline int prog_dmabuf_record(struct trident_state* state)
-{
- return prog_dmabuf(state, DM_RECORD);
-}
-
-static inline int prog_dmabuf_playback(struct trident_state* state)
-{
- return prog_dmabuf(state, DM_PLAYBACK);
-}
-
-/* we are doing quantum mechanics here, the buffer can only be empty, half or full filled i.e.
- |------------|------------| or |xxxxxxxxxxxx|------------| or |xxxxxxxxxxxx|xxxxxxxxxxxx|
- but we almost always get this
- |xxxxxx------|------------| or |xxxxxxxxxxxx|xxxxx-------|
- so we have to clear the tail space to "silence"
- |xxxxxx000000|------------| or |xxxxxxxxxxxx|xxxxxx000000|
-*/
-static void
-trident_clear_tail(struct trident_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- unsigned swptr;
- unsigned char silence = (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80;
- unsigned int len;
- unsigned long flags;
-
- spin_lock_irqsave(&state->card->lock, flags);
- swptr = dmabuf->swptr;
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- if (swptr == 0 || swptr == dmabuf->dmasize / 2 ||
- swptr == dmabuf->dmasize)
- return;
-
- if (swptr < dmabuf->dmasize / 2)
- len = dmabuf->dmasize / 2 - swptr;
- else
- len = dmabuf->dmasize - swptr;
-
- memset(dmabuf->rawbuf + swptr, silence, len);
- if (state->card->pci_id != PCI_DEVICE_ID_ALI_5451) {
- spin_lock_irqsave(&state->card->lock, flags);
- dmabuf->swptr += len;
- dmabuf->count += len;
- spin_unlock_irqrestore(&state->card->lock, flags);
- }
-
- /* restart the dma machine in case it is halted */
- start_dac(state);
-}
-
-static int
-drain_dac(struct trident_state *state, int nonblock)
-{
- DECLARE_WAITQUEUE(wait, current);
- struct dmabuf *dmabuf = &state->dmabuf;
- unsigned long flags;
- unsigned long tmo;
- int count;
- unsigned long diff = 0;
-
- if (dmabuf->mapped || !dmabuf->ready)
- return 0;
-
- add_wait_queue(&dmabuf->wait, &wait);
- for (;;) {
- /* It seems that we have to set the current state to TASK_INTERRUPTIBLE
- every time to make the process really go to sleep */
- set_current_state(TASK_INTERRUPTIBLE);
-
- spin_lock_irqsave(&state->card->lock, flags);
- count = dmabuf->count;
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- if (count <= 0)
- break;
-
- if (signal_pending(current))
- break;
-
- if (nonblock) {
- remove_wait_queue(&dmabuf->wait, &wait);
- set_current_state(TASK_RUNNING);
- return -EBUSY;
- }
-
- /* No matter how much data is left in the buffer, we have to wait until
- CSO == ESO/2 or CSO == ESO when address engine interrupts */
- if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451 ||
- state->card->pci_id == PCI_DEVICE_ID_INTERG_5050) {
- diff = dmabuf->swptr - trident_get_dma_addr(state) + dmabuf->dmasize;
- diff = diff % (dmabuf->dmasize);
- tmo = (diff * HZ) / dmabuf->rate;
- } else {
- tmo = (dmabuf->dmasize * HZ) / dmabuf->rate;
- }
- tmo >>= sample_shift[dmabuf->fmt];
- if (!schedule_timeout(tmo ? tmo : 1) && tmo) {
- break;
- }
- }
- remove_wait_queue(&dmabuf->wait, &wait);
- set_current_state(TASK_RUNNING);
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- return 0;
-}
-
-/* update buffer manangement pointers, especially, */
-/* dmabuf->count and dmabuf->hwptr */
-static void
-trident_update_ptr(struct trident_state *state)
-{
- struct dmabuf *dmabuf = &state->dmabuf;
- unsigned hwptr, swptr;
- int clear_cnt = 0;
- int diff;
- unsigned char silence;
- unsigned half_dmasize;
-
- /* update hardware pointer */
- hwptr = trident_get_dma_addr(state);
- diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
- dmabuf->hwptr = hwptr;
- dmabuf->total_bytes += diff;
-
- /* error handling and process wake up for ADC */
- if (dmabuf->enable == ADC_RUNNING) {
- if (dmabuf->mapped) {
- dmabuf->count -= diff;
- if (dmabuf->count >= (signed) dmabuf->fragsize)
- wake_up(&dmabuf->wait);
- } else {
- dmabuf->count += diff;
-
- if (dmabuf->count < 0 ||
- dmabuf->count > dmabuf->dmasize) {
- /* buffer underrun or buffer overrun, */
- /* we have no way to recover it here, just */
- /* stop the machine and let the process */
- /* force hwptr and swptr to sync */
- __stop_adc(state);
- dmabuf->error++;
- }
- if (dmabuf->count < (signed) dmabuf->dmasize / 2)
- wake_up(&dmabuf->wait);
- }
- }
-
- /* error handling and process wake up for DAC */
- if (dmabuf->enable == DAC_RUNNING) {
- if (dmabuf->mapped) {
- dmabuf->count += diff;
- if (dmabuf->count >= (signed) dmabuf->fragsize)
- wake_up(&dmabuf->wait);
- } else {
- dmabuf->count -= diff;
-
- if (dmabuf->count < 0 ||
- dmabuf->count > dmabuf->dmasize) {
- /* buffer underrun or buffer overrun, we have no way to recover
- it here, just stop the machine and let the process force hwptr
- and swptr to sync */
- __stop_dac(state);
- dmabuf->error++;
- } else if (!dmabuf->endcleared) {
- swptr = dmabuf->swptr;
- silence = (dmabuf->fmt & TRIDENT_FMT_16BIT ? 0 : 0x80);
- if (dmabuf->update_flag & ALI_ADDRESS_INT_UPDATE) {
- /* We must clear end data of 1/2 dmabuf if needed.
- According to 1/2 algorithm of Address Engine Interrupt,
- check the validation of the data of half dmasize. */
- half_dmasize = dmabuf->dmasize / 2;
- if ((diff = hwptr - half_dmasize) < 0)
- diff = hwptr;
- if ((dmabuf->count + diff) < half_dmasize) {
- //there is invalid data in the end of half buffer
- if ((clear_cnt = half_dmasize - swptr) < 0)
- clear_cnt += half_dmasize;
- //clear the invalid data
- memset(dmabuf->rawbuf + swptr, silence, clear_cnt);
- if (state->chans_num == 6) {
- clear_cnt = clear_cnt / 2;
- swptr = swptr / 2;
- memset(state->other_states[0]->dmabuf.rawbuf + swptr,
- silence, clear_cnt);
- memset(state->other_states[1]->dmabuf.rawbuf + swptr,
- silence, clear_cnt);
- memset(state->other_states[2]->dmabuf.rawbuf + swptr,
- silence, clear_cnt);
- memset(state->other_states[3]->dmabuf.rawbuf + swptr,
- silence, clear_cnt);
- }
- dmabuf->endcleared = 1;
- }
- } else if (dmabuf->count < (signed) dmabuf->fragsize) {
- clear_cnt = dmabuf->fragsize;
- if ((swptr + clear_cnt) > dmabuf->dmasize)
- clear_cnt = dmabuf->dmasize - swptr;
- memset(dmabuf->rawbuf + swptr, silence, clear_cnt);
- if (state->chans_num == 6) {
- clear_cnt = clear_cnt / 2;
- swptr = swptr / 2;
- memset(state->other_states[0]->dmabuf.rawbuf + swptr,
- silence, clear_cnt);
- memset(state->other_states[1]->dmabuf.rawbuf + swptr,
- silence, clear_cnt);
- memset(state->other_states[2]->dmabuf.rawbuf + swptr,
- silence, clear_cnt);
- memset(state->other_states[3]->dmabuf.rawbuf + swptr,
- silence, clear_cnt);
- }
- dmabuf->endcleared = 1;
- }
- }
- /* trident_update_ptr is called by interrupt handler or by process via
- ioctl/poll, we only wake up the waiting process when we have more
- than 1/2 buffer free (always true for interrupt handler) */
- if (dmabuf->count < (signed) dmabuf->dmasize / 2)
- wake_up(&dmabuf->wait);
- }
- }
- dmabuf->update_flag &= ~ALI_ADDRESS_INT_UPDATE;
-}
-
-static void
-trident_address_interrupt(struct trident_card *card)
-{
- int i;
- struct trident_state *state;
- unsigned int channel;
-
- /* Update the pointers for all channels we are running. */
- /* FIXME: should read interrupt status only once */
- for (i = 0; i < NR_HW_CH; i++) {
- channel = 63 - i;
- if (trident_check_channel_interrupt(card, channel)) {
- trident_ack_channel_interrupt(card, channel);
- if ((state = card->states[i]) != NULL) {
- trident_update_ptr(state);
- } else {
- printk(KERN_WARNING "trident: spurious channel "
- "irq %d.\n", channel);
- trident_stop_voice(card, channel);
- trident_disable_voice_irq(card, channel);
- }
- }
- }
-}
-
-static void
-ali_hwvol_control(struct trident_card *card, int opt)
-{
- u16 dwTemp, volume[2], mute, diff, *pVol[2];
-
- dwTemp = ali_ac97_read(card->ac97_codec[0], 0x02);
- mute = dwTemp & 0x8000;
- volume[0] = dwTemp & 0x001f;
- volume[1] = (dwTemp & 0x1f00) >> 8;
- if (volume[0] < volume[1]) {
- pVol[0] = &volume[0];
- pVol[1] = &volume[1];
- } else {
- pVol[1] = &volume[0];
- pVol[0] = &volume[1];
- }
- diff = *(pVol[1]) - *(pVol[0]);
-
- if (opt == 1) { // MUTE
- dwTemp ^= 0x8000;
- ali_ac97_write(card->ac97_codec[0],
- 0x02, dwTemp);
- } else if (opt == 2) { // Down
- if (mute)
- return;
- if (*(pVol[1]) < 0x001f) {
- (*pVol[1])++;
- *(pVol[0]) = *(pVol[1]) - diff;
- }
- dwTemp &= 0xe0e0;
- dwTemp |= (volume[0]) | (volume[1] << 8);
- ali_ac97_write(card->ac97_codec[0], 0x02, dwTemp);
- card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) |
- (((32 - volume[1]) * 25 / 8) << 8);
- } else if (opt == 4) { // Up
- if (mute)
- return;
- if (*(pVol[0]) > 0) {
- (*pVol[0])--;
- *(pVol[1]) = *(pVol[0]) + diff;
- }
- dwTemp &= 0xe0e0;
- dwTemp |= (volume[0]) | (volume[1] << 8);
- ali_ac97_write(card->ac97_codec[0], 0x02, dwTemp);
- card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) |
- (((32 - volume[1]) * 25 / 8) << 8);
- } else {
- /* Nothing needs doing */
- }
-}
-
-/*
- * Re-enable reporting of vol change after 0.1 seconds
- */
-
-static void
-ali_timeout(unsigned long ptr)
-{
- struct trident_card *card = (struct trident_card *) ptr;
- u16 temp = 0;
-
- /* Enable GPIO IRQ (MISCINT bit 18h) */
- temp = inw(TRID_REG(card, T4D_MISCINT + 2));
- temp |= 0x0004;
- outw(temp, TRID_REG(card, T4D_MISCINT + 2));
-}
-
-/*
- * Set up the timer to clear the vol change notification
- */
-
-static void
-ali_set_timer(struct trident_card *card)
-{
- /* Add Timer Routine to Enable GPIO IRQ */
- del_timer(&card->timer); /* Never queue twice */
- card->timer.function = ali_timeout;
- card->timer.data = (unsigned long) card;
- card->timer.expires = jiffies + HZ / 10;
- add_timer(&card->timer);
-}
-
-/*
- * Process a GPIO event
- */
-
-static void
-ali_queue_task(struct trident_card *card, int opt)
-{
- u16 temp;
-
- /* Disable GPIO IRQ (MISCINT bit 18h) */
- temp = inw(TRID_REG(card, T4D_MISCINT + 2));
- temp &= (u16) (~0x0004);
- outw(temp, TRID_REG(card, T4D_MISCINT + 2));
-
- /* Adjust the volume */
- ali_hwvol_control(card, opt);
-
- /* Set the timer for 1/10th sec */
- ali_set_timer(card);
-}
-
-static void
-cyber_address_interrupt(struct trident_card *card)
-{
- int i, irq_status;
- struct trident_state *state;
- unsigned int channel;
-
- /* Update the pointers for all channels we are running. */
- /* FIXED: read interrupt status only once */
- irq_status = inl(TRID_REG(card, T4D_AINT_A));
-
- pr_debug("cyber_address_interrupt: irq_status 0x%X\n", irq_status);
-
- for (i = 0; i < NR_HW_CH; i++) {
- channel = 31 - i;
- if (irq_status & (1 << channel)) {
- /* clear bit by writing a 1, zeroes are ignored */
- outl((1 << channel), TRID_REG(card, T4D_AINT_A));
-
- pr_debug("cyber_interrupt: channel %d\n", channel);
-
- if ((state = card->states[i]) != NULL) {
- trident_update_ptr(state);
- } else {
- printk(KERN_WARNING "cyber5050: spurious "
- "channel irq %d.\n", channel);
- trident_stop_voice(card, channel);
- trident_disable_voice_irq(card, channel);
- }
- }
- }
-}
-
-static irqreturn_t
-trident_interrupt(int irq, void *dev_id)
-{
- struct trident_card *card = (struct trident_card *) dev_id;
- u32 event;
- u32 gpio;
-
- spin_lock(&card->lock);
- event = inl(TRID_REG(card, T4D_MISCINT));
-
- pr_debug("trident: trident_interrupt called, MISCINT = 0x%08x\n",
- event);
-
- if (event & ADDRESS_IRQ) {
- card->address_interrupt(card);
- }
-
- if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
- /* GPIO IRQ (H/W Volume Control) */
- event = inl(TRID_REG(card, T4D_MISCINT));
- if (event & (1 << 25)) {
- gpio = inl(TRID_REG(card, ALI_GPIO));
- if (!timer_pending(&card->timer))
- ali_queue_task(card, gpio & 0x07);
- }
- event = inl(TRID_REG(card, T4D_MISCINT));
- outl(event | (ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW),
- TRID_REG(card, T4D_MISCINT));
- spin_unlock(&card->lock);
- return IRQ_HANDLED;
- }
-
- /* manually clear interrupt status, bad hardware design, blame T^2 */
- outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW),
- TRID_REG(card, T4D_MISCINT));
- spin_unlock(&card->lock);
- return IRQ_HANDLED;
-}
-
-/* in this loop, dmabuf.count signifies the amount of data that is waiting */
-/* to be copied to the user's buffer. it is filled by the dma machine and */
-/* drained by this loop. */
-static ssize_t
-trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
-{
- struct trident_state *state = (struct trident_state *)file->private_data;
- struct dmabuf *dmabuf = &state->dmabuf;
- ssize_t ret = 0;
- unsigned long flags;
- unsigned swptr;
- int cnt;
-
- pr_debug("trident: trident_read called, count = %zd\n", count);
-
- VALIDATE_STATE(state);
-
- if (dmabuf->mapped)
- return -ENXIO;
- if (!access_ok(VERIFY_WRITE, buffer, count))
- return -EFAULT;
-
- mutex_lock(&state->sem);
- if (!dmabuf->ready && (ret = prog_dmabuf_record(state)))
- goto out;
-
- while (count > 0) {
- spin_lock_irqsave(&state->card->lock, flags);
- if (dmabuf->count > (signed) dmabuf->dmasize) {
- /* buffer overrun, we are recovering from */
- /* sleep_on_timeout, resync hwptr and swptr, */
- /* make process flush the buffer */
- dmabuf->count = dmabuf->dmasize;
- dmabuf->swptr = dmabuf->hwptr;
- }
- swptr = dmabuf->swptr;
- cnt = dmabuf->dmasize - swptr;
- if (dmabuf->count < cnt)
- cnt = dmabuf->count;
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- if (cnt > count)
- cnt = count;
- if (cnt <= 0) {
- unsigned long tmo;
- /* buffer is empty, start the dma machine and */
- /* wait for data to be recorded */
- start_adc(state);
- if (file->f_flags & O_NONBLOCK) {
- if (!ret)
- ret = -EAGAIN;
- goto out;
- }
-
- mutex_unlock(&state->sem);
- /* No matter how much space left in the buffer, */
- /* we have to wait until CSO == ESO/2 or CSO == ESO */
- /* when address engine interrupts */
- tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
- tmo >>= sample_shift[dmabuf->fmt];
- /* There are two situations when sleep_on_timeout returns, one is when
- the interrupt is serviced correctly and the process is waked up by
- ISR ON TIME. Another is when timeout is expired, which means that
- either interrupt is NOT serviced correctly (pending interrupt) or it
- is TOO LATE for the process to be scheduled to run (scheduler latency)
- which results in a (potential) buffer overrun. And worse, there is
- NOTHING we can do to prevent it. */
- if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) {
- pr_debug(KERN_ERR "trident: recording schedule timeout, "
- "dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
- dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
- dmabuf->hwptr, dmabuf->swptr);
-
- /* a buffer overrun, we delay the recovery until next time the
- while loop begin and we REALLY have space to record */
- }
- if (signal_pending(current)) {
- if (!ret)
- ret = -ERESTARTSYS;
- goto out;
- }
- mutex_lock(&state->sem);
- if (dmabuf->mapped) {
- if (!ret)
- ret = -ENXIO;
- goto out;
- }
- continue;
- }
-
- if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) {
- if (!ret)
- ret = -EFAULT;
- goto out;
- }
-
- swptr = (swptr + cnt) % dmabuf->dmasize;
-
- spin_lock_irqsave(&state->card->lock, flags);
- dmabuf->swptr = swptr;
- dmabuf->count -= cnt;
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- count -= cnt;
- buffer += cnt;
- ret += cnt;
- start_adc(state);
- }
-out:
- mutex_unlock(&state->sem);
- return ret;
-}
-
-/* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to
- the soundcard. it is drained by the dma machine and filled by this loop. */
-
-static ssize_t
-trident_write(struct file *file, const char __user *buffer, size_t count, loff_t * ppos)
-{
- struct trident_state *state = (struct trident_state *)file->private_data;
- struct dmabuf *dmabuf = &state->dmabuf;
- ssize_t ret;
- unsigned long flags;
- unsigned swptr;
- int cnt;
- unsigned int state_cnt;
- unsigned int copy_count;
- int lret; /* for lock_set_fmt */
-
- pr_debug("trident: trident_write called, count = %zd\n", count);
-
- VALIDATE_STATE(state);
-
- /*
- * Guard against an mmap or ioctl while writing
- */
-
- mutex_lock(&state->sem);
-
- if (dmabuf->mapped) {
- ret = -ENXIO;
- goto out;
- }
- if (!dmabuf->ready && (ret = prog_dmabuf_playback(state)))
- goto out;
-
- if (!access_ok(VERIFY_READ, buffer, count)) {
- ret = -EFAULT;
- goto out;
- }
-
- ret = 0;
-
- while (count > 0) {
- spin_lock_irqsave(&state->card->lock, flags);
- if (dmabuf->count < 0) {
- /* buffer underrun, we are recovering from */
- /* sleep_on_timeout, resync hwptr and swptr */
- dmabuf->count = 0;
- dmabuf->swptr = dmabuf->hwptr;
- }
- swptr = dmabuf->swptr;
- cnt = dmabuf->dmasize - swptr;
- if (dmabuf->count + cnt > dmabuf->dmasize)
- cnt = dmabuf->dmasize - dmabuf->count;
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- if (cnt > count)
- cnt = count;
- if (cnt <= 0) {
- unsigned long tmo;
- /* buffer is full, start the dma machine and */
- /* wait for data to be played */
- start_dac(state);
- if (file->f_flags & O_NONBLOCK) {
- if (!ret)
- ret = -EAGAIN;
- goto out;
- }
- /* No matter how much data left in the buffer, */
- /* we have to wait until CSO == ESO/2 or CSO == ESO */
- /* when address engine interrupts */
- lock_set_fmt(state);
- tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
- tmo >>= sample_shift[dmabuf->fmt];
- unlock_set_fmt(state);
- mutex_unlock(&state->sem);
-
- /* There are two situations when sleep_on_timeout */
- /* returns, one is when the interrupt is serviced */
- /* correctly and the process is waked up by ISR */
- /* ON TIME. Another is when timeout is expired, which */
- /* means that either interrupt is NOT serviced */
- /* correctly (pending interrupt) or it is TOO LATE */
- /* for the process to be scheduled to run */
- /* (scheduler latency) which results in a (potential) */
- /* buffer underrun. And worse, there is NOTHING we */
- /* can do to prevent it. */
- if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) {
- pr_debug(KERN_ERR "trident: playback schedule "
- "timeout, dmasz %u fragsz %u count %i "
- "hwptr %u swptr %u\n", dmabuf->dmasize,
- dmabuf->fragsize, dmabuf->count,
- dmabuf->hwptr, dmabuf->swptr);
-
- /* a buffer underrun, we delay the recovery */
- /* until next time the while loop begin and */
- /* we REALLY have data to play */
- }
- if (signal_pending(current)) {
- if (!ret)
- ret = -ERESTARTSYS;
- goto out_nolock;
- }
- mutex_lock(&state->sem);
- if (dmabuf->mapped) {
- if (!ret)
- ret = -ENXIO;
- goto out;
- }
- continue;
- }
- if ((lret = lock_set_fmt(state)) < 0) {
- ret = lret;
- goto out;
- }
-
- if (state->chans_num == 6) {
- copy_count = 0;
- state_cnt = 0;
- if (ali_write_5_1(state, buffer, cnt, &copy_count,
- &state_cnt) == -EFAULT) {
- if (state_cnt) {
- swptr = (swptr + state_cnt) % dmabuf->dmasize;
- spin_lock_irqsave(&state->card->lock, flags);
- dmabuf->swptr = swptr;
- dmabuf->count += state_cnt;
- dmabuf->endcleared = 0;
- spin_unlock_irqrestore(&state->card->lock, flags);
- }
- ret += copy_count;
- if (!ret)
- ret = -EFAULT;
- unlock_set_fmt(state);
- goto out;
- }
- } else {
- if (copy_from_user(dmabuf->rawbuf + swptr,
- buffer, cnt)) {
- if (!ret)
- ret = -EFAULT;
- unlock_set_fmt(state);
- goto out;
- }
- state_cnt = cnt;
- }
- unlock_set_fmt(state);
-
- swptr = (swptr + state_cnt) % dmabuf->dmasize;
-
- spin_lock_irqsave(&state->card->lock, flags);
- dmabuf->swptr = swptr;
- dmabuf->count += state_cnt;
- dmabuf->endcleared = 0;
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- count -= cnt;
- buffer += cnt;
- ret += cnt;
- start_dac(state);
- }
-out:
- mutex_unlock(&state->sem);
-out_nolock:
- return ret;
-}
-
-/* No kernel lock - we have our own spinlock */
-static unsigned int
-trident_poll(struct file *file, struct poll_table_struct *wait)
-{
- struct trident_state *state = (struct trident_state *)file->private_data;
- struct dmabuf *dmabuf = &state->dmabuf;
- unsigned long flags;
- unsigned int mask = 0;
-
- VALIDATE_STATE(state);
-
- /*
- * Guard against a parallel poll and write causing multiple
- * prog_dmabuf events
- */
-
- mutex_lock(&state->sem);
-
- if (file->f_mode & FMODE_WRITE) {
- if (!dmabuf->ready && prog_dmabuf_playback(state)) {
- mutex_unlock(&state->sem);
- return 0;
- }
- poll_wait(file, &dmabuf->wait, wait);
- }
- if (file->f_mode & FMODE_READ) {
- if (!dmabuf->ready && prog_dmabuf_record(state)) {
- mutex_unlock(&state->sem);
- return 0;
- }
- poll_wait(file, &dmabuf->wait, wait);
- }
-
- mutex_unlock(&state->sem);
-
- spin_lock_irqsave(&state->card->lock, flags);
- trident_update_ptr(state);
- if (file->f_mode & FMODE_READ) {
- if (dmabuf->count >= (signed) dmabuf->fragsize)
- mask |= POLLIN | POLLRDNORM;
- }
- if (file->f_mode & FMODE_WRITE) {
- if (dmabuf->mapped) {
- if (dmabuf->count >= (signed) dmabuf->fragsize)
- mask |= POLLOUT | POLLWRNORM;
- } else {
- if ((signed) dmabuf->dmasize >= dmabuf->count +
- (signed) dmabuf->fragsize)
- mask |= POLLOUT | POLLWRNORM;
- }
- }
- spin_unlock_irqrestore(&state->card->lock, flags);
-
- return mask;
-}
-
-static int
-trident_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct trident_state *state = (struct trident_state *)file->private_data;
- struct dmabuf *dmabuf = &state->dmabuf;
- int ret = -EINVAL;
- unsigned long size;
-
- VALIDATE_STATE(state);
-
- /*
- * Lock against poll read write or mmap creating buffers. Also lock
- * a read or write against an mmap.
- */
-
- mutex_lock(&state->sem);
-
- if (vma->vm_flags & VM_WRITE) {
- if ((ret = prog_dmabuf_playback(state)) != 0)
- goto out;
- } else if (vma->vm_flags & VM_READ) {
- if ((ret = prog_dmabuf_record(state)) != 0)
- goto out;
- } else
- goto out;
-
- ret = -EINVAL;
- if (vma->vm_pgoff != 0)
- goto out;
- size = vma->vm_end - vma->vm_start;
- if (size > (PAGE_SIZE << dmabuf->buforder))
- goto out;
- ret = -EAGAIN;
- if (remap_pfn_range(vma, vma->vm_start,
- virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT,
- size, vma->vm_page_prot))
- goto out;
- dmabuf->mapped = 1;
- ret = 0;
-out:
- mutex_unlock(&state->sem);
- return ret;
-}
-
-static int
-trident_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct trident_state *state = (struct trident_state *)file->private_data;
- struct dmabuf *dmabuf = &state->dmabuf;
- unsigned long flags;
- audio_buf_info abinfo;
- count_info cinfo;
- int val, mapped, ret = 0;
- struct trident_card *card = state->card;
- void __user *argp = (void __user *)arg;
- int __user *p = argp;
-
- VALIDATE_STATE(state);
-
-
- mapped = ((file->f_mode & (FMODE_WRITE | FMODE_READ)) && dmabuf->mapped);
-
- pr_debug("trident: trident_ioctl, command = %2d, arg = 0x%08x\n",
- _IOC_NR(cmd), arg ? *p : 0);
-
- switch (cmd) {
- case OSS_GETVERSION:
- ret = put_user(SOUND_VERSION, p);
- break;
-
- case SNDCTL_DSP_RESET:
- /* FIXME: spin_lock ? */
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(state);
- synchronize_irq(card->irq);
- dmabuf->ready = 0;
- dmabuf->swptr = dmabuf->hwptr = 0;
- dmabuf->count = dmabuf->total_bytes = 0;
- }
- if (file->f_mode & FMODE_READ) {
- stop_adc(state);
- synchronize_irq(card->irq);
- dmabuf->ready = 0;
- dmabuf->swptr = dmabuf->hwptr = 0;
- dmabuf->count = dmabuf->total_bytes = 0;
- }
- break;
-
- case SNDCTL_DSP_SYNC:
- if (file->f_mode & FMODE_WRITE)
- ret = drain_dac(state, file->f_flags & O_NONBLOCK);
- break;
-
- case SNDCTL_DSP_SPEED: /* set smaple rate */
- if (get_user(val, p)) {
- ret = -EFAULT;
- break;
- }
- if (val >= 0) {
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(state);
- dmabuf->ready = 0;
- spin_lock_irqsave(&state->card->lock, flags);
- trident_set_dac_rate(state, val);
- spin_unlock_irqrestore(&state->card->lock, flags);
- }
- if (file->f_mode & FMODE_READ) {
- stop_adc(state);
- dmabuf->ready = 0;
- spin_lock_irqsave(&state->card->lock, flags);
- trident_set_adc_rate(state, val);
- spin_unlock_irqrestore(&state->card->lock, flags);
- }
- }
- ret = put_user(dmabuf->rate, p);
- break;
-
- case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
- if (get_user(val, p)) {
- ret = -EFAULT;
- break;
- }
- if ((ret = lock_set_fmt(state)) < 0)
- return ret;
-
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(state);
- dmabuf->ready = 0;
- if (val)
- dmabuf->fmt |= TRIDENT_FMT_STEREO;
- else
- dmabuf->fmt &= ~TRIDENT_FMT_STEREO;
- }
- if (file->f_mode & FMODE_READ) {
- stop_adc(state);
- dmabuf->ready = 0;
- if (val)
- dmabuf->fmt |= TRIDENT_FMT_STEREO;
- else
- dmabuf->fmt &= ~TRIDENT_FMT_STEREO;
- }
- unlock_set_fmt(state);
- break;
-
- case SNDCTL_DSP_GETBLKSIZE:
- if (file->f_mode & FMODE_WRITE) {
- if ((val = prog_dmabuf_playback(state)))
- ret = val;
- else
- ret = put_user(dmabuf->fragsize, p);
- break;
- }
- if (file->f_mode & FMODE_READ) {
- if ((val = prog_dmabuf_record(state)))
- ret = val;
- else
- ret = put_user(dmabuf->fragsize, p);
- break;
- }
- /* neither READ nor WRITE? is this even possible? */
- ret = -EINVAL;
- break;
-
-
- case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format */
- ret = put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 |
- AFMT_U8, p);
- break;
-
- case SNDCTL_DSP_SETFMT: /* Select sample format */
- if (get_user(val, p)) {
- ret = -EFAULT;
- break;
- }
- if ((ret = lock_set_fmt(state)) < 0)
- return ret;
-
- if (val != AFMT_QUERY) {
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(state);
- dmabuf->ready = 0;
- if (val == AFMT_S16_LE)
- dmabuf->fmt |= TRIDENT_FMT_16BIT;
- else
- dmabuf->fmt &= ~TRIDENT_FMT_16BIT;
- }
- if (file->f_mode & FMODE_READ) {
- stop_adc(state);
- dmabuf->ready = 0;
- if (val == AFMT_S16_LE)
- dmabuf->fmt |= TRIDENT_FMT_16BIT;
- else
- dmabuf->fmt &= ~TRIDENT_FMT_16BIT;
- }
- }
- unlock_set_fmt(state);
- ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE :
- AFMT_U8, p);
- break;
-
- case SNDCTL_DSP_CHANNELS:
- if (get_user(val, p)) {
- ret = -EFAULT;
- break;
- }
- if (val != 0) {
- if ((ret = lock_set_fmt(state)) < 0)
- return ret;
-
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(state);
- dmabuf->ready = 0;
-
- //prevent from memory leak
- if ((state->chans_num > 2) && (state->chans_num != val)) {
- ali_free_other_states_resources(state);
- state->chans_num = 1;
- }
-
- if (val >= 2) {
-
- dmabuf->fmt |= TRIDENT_FMT_STEREO;
- if ((val == 6) && (state->card->pci_id == PCI_DEVICE_ID_ALI_5451)) {
- if (card->rec_channel_use_count > 0) {
- printk(KERN_ERR "trident: Record is "
- "working on the card!\n");
- ret = -EBUSY;
- unlock_set_fmt(state);
- break;
- }
-
- ret = ali_setup_multi_channels(state->card, 6);
- if (ret < 0) {
- unlock_set_fmt(state);
- break;
- }
- mutex_lock(&state->card->open_mutex);
- ret = ali_allocate_other_states_resources(state, 6);
- if (ret < 0) {
- mutex_unlock(&state->card->open_mutex);
- unlock_set_fmt(state);
- break;
- }
- state->card->multi_channel_use_count++;
- mutex_unlock(&state->card->open_mutex);
- } else
- val = 2; /*yield to 2-channels */
- } else
- dmabuf->fmt &= ~TRIDENT_FMT_STEREO;
- state->chans_num = val;
- }
- if (file->f_mode & FMODE_READ) {
- stop_adc(state);
- dmabuf->ready = 0;
- if (val >= 2) {
- if (!((file->f_mode & FMODE_WRITE) &&
- (val == 6)))
- val = 2;
- dmabuf->fmt |= TRIDENT_FMT_STEREO;
- } else
- dmabuf->fmt &= ~TRIDENT_FMT_STEREO;
- state->chans_num = val;
- }
- unlock_set_fmt(state);
- }
- ret = put_user(val, p);
- break;
-
- case SNDCTL_DSP_POST:
- /* Cause the working fragment to be output */
- break;
-
- case SNDCTL_DSP_SUBDIVIDE:
- if (dmabuf->subdivision) {
- ret = -EINVAL;
- break;
- }
- if (get_user(val, p)) {
- ret = -EFAULT;
- break;
- }
- if (val != 1 && val != 2 && val != 4) {
- ret = -EINVAL;
- break;
- }
- dmabuf->subdivision = val;
- break;
-
- case SNDCTL_DSP_SETFRAGMENT:
- if (get_user(val, p)) {
- ret = -EFAULT;
- break;
- }
-
- dmabuf->ossfragshift = val & 0xffff;
- dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
- if (dmabuf->ossfragshift < 4)
- dmabuf->ossfragshift = 4;
- if (dmabuf->ossfragshift > 15)
- dmabuf->ossfragshift = 15;
- if (dmabuf->ossmaxfrags < 4)
- dmabuf->ossmaxfrags = 4;
-
- break;
-
- case SNDCTL_DSP_GETOSPACE:
- if (!(file->f_mode & FMODE_WRITE)) {
- ret = -EINVAL;
- break;
- }
- if (!dmabuf->ready && (val = prog_dmabuf_playback(state)) != 0) {
- ret = val;
- break;
- }
- spin_lock_irqsave(&state->card->lock, flags);
- trident_update_ptr(state);
- abinfo.fragsize = dmabuf->fragsize;
- abinfo.bytes = dmabuf->dmasize - dmabuf->count;
- abinfo.fragstotal = dmabuf->numfrag;
- abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
- spin_unlock_irqrestore(&state->card->lock, flags);
- ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ?
- -EFAULT : 0;
- break;
-
- case SNDCTL_DSP_GETISPACE:
- if (!(file->f_mode & FMODE_READ)) {
- ret = -EINVAL;
- break;
- }
- if (!dmabuf->ready && (val = prog_dmabuf_record(state)) != 0) {
- ret = val;
- break;
- }
- spin_lock_irqsave(&state->card->lock, flags);
- trident_update_ptr(state);
- abinfo.fragsize = dmabuf->fragsize;
- abinfo.bytes = dmabuf->count;
- abinfo.fragstotal = dmabuf->numfrag;
- abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
- spin_unlock_irqrestore(&state->card->lock, flags);
- ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ?
- -EFAULT : 0;
- break;
-
- case SNDCTL_DSP_NONBLOCK:
- file->f_flags |= O_NONBLOCK;
- break;
-
- case SNDCTL_DSP_GETCAPS:
- ret = put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER |
- DSP_CAP_MMAP | DSP_CAP_BIND, p);
- break;
-
- case SNDCTL_DSP_GETTRIGGER:
- val = 0;
- if ((file->f_mode & FMODE_READ) && dmabuf->enable)
- val |= PCM_ENABLE_INPUT;
- if ((file->f_mode & FMODE_WRITE) && dmabuf->enable)
- val |= PCM_ENABLE_OUTPUT;
- ret = put_user(val, p);
- break;
-
- case SNDCTL_DSP_SETTRIGGER:
- if (get_user(val, p)) {
- ret = -EFAULT;
- break;
- }
- if (file->f_mode & FMODE_READ) {
- if (val & PCM_ENABLE_INPUT) {
- if (!dmabuf->ready &&
- (ret = prog_dmabuf_record(state)))
- break;
- start_adc(state);
- } else
- stop_adc(state);
- }
- if (file->f_mode & FMODE_WRITE) {
- if (val & PCM_ENABLE_OUTPUT) {
- if (!dmabuf->ready &&
- (ret = prog_dmabuf_playback(state)))
- break;
- start_dac(state);
- } else
- stop_dac(state);
- }
- break;
-
- case SNDCTL_DSP_GETIPTR:
- if (!(file->f_mode & FMODE_READ)) {
- ret = -EINVAL;
- break;
- }
- if (!dmabuf->ready && (val = prog_dmabuf_record(state))
- != 0) {
- ret = val;
- break;
- }
- spin_lock_irqsave(&state->card->lock, flags);
- trident_update_ptr(state);
- cinfo.bytes = dmabuf->total_bytes;
- cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
- cinfo.ptr = dmabuf->hwptr;
- if (dmabuf->mapped)
- dmabuf->count &= dmabuf->fragsize - 1;
- spin_unlock_irqrestore(&state->card->lock, flags);
- ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ?
- -EFAULT : 0;
- break;
-
- case SNDCTL_DSP_GETOPTR:
- if (!(file->f_mode & FMODE_WRITE)) {
- ret = -EINVAL;
- break;
- }
- if (!dmabuf->ready && (val = prog_dmabuf_playback(state))
- != 0) {
- ret = val;
- break;
- }
-
- spin_lock_irqsave(&state->card->lock, flags);
- trident_update_ptr(state);
- cinfo.bytes = dmabuf->total_bytes;
- cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
- cinfo.ptr = dmabuf->hwptr;
- if (dmabuf->mapped)
- dmabuf->count &= dmabuf->fragsize - 1;
- spin_unlock_irqrestore(&state->card->lock, flags);
- ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ?
- -EFAULT : 0;
- break;
-
- case SNDCTL_DSP_SETDUPLEX:
- ret = -EINVAL;
- break;
-
- case SNDCTL_DSP_GETODELAY:
- if (!(file->f_mode & FMODE_WRITE)) {
- ret = -EINVAL;
- break;
- }
- if (!dmabuf->ready && (val = prog_dmabuf_playback(state)) != 0) {
- ret = val;
- break;
- }
- spin_lock_irqsave(&state->card->lock, flags);
- trident_update_ptr(state);
- val = dmabuf->count;
- spin_unlock_irqrestore(&state->card->lock, flags);
- ret = put_user(val, p);
- break;
-
- case SOUND_PCM_READ_RATE:
- ret = put_user(dmabuf->rate, p);
- break;
-
- case SOUND_PCM_READ_CHANNELS:
- ret = put_user((dmabuf->fmt & TRIDENT_FMT_STEREO) ? 2 : 1,
- p);
- break;
-
- case SOUND_PCM_READ_BITS:
- ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE :
- AFMT_U8, p);
- break;
-
- case SNDCTL_DSP_GETCHANNELMASK:
- ret = put_user(DSP_BIND_FRONT | DSP_BIND_SURR |
- DSP_BIND_CENTER_LFE, p);
- break;
-
- case SNDCTL_DSP_BIND_CHANNEL:
- if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) {
- ret = -EINVAL;
- break;
- }
-
- if (get_user(val, p)) {
- ret = -EFAULT;
- break;
- }
- if (val == DSP_BIND_QUERY) {
- val = dmabuf->channel->attribute | 0x3c00;
- val = attr2mask[val >> 8];
- } else {
- dmabuf->ready = 0;
- if (file->f_mode & FMODE_READ)
- dmabuf->channel->attribute = (CHANNEL_REC |
- SRC_ENABLE);
- if (file->f_mode & FMODE_WRITE)
- dmabuf->channel->attribute = (CHANNEL_SPC_PB |
- SRC_ENABLE);
- dmabuf->channel->attribute |= mask2attr[ffs(val)];
- }
- ret = put_user(val, p);
- break;
-
- case SNDCTL_DSP_MAPINBUF:
- case SNDCTL_DSP_MAPOUTBUF:
- case SNDCTL_DSP_SETSYNCRO:
- case SOUND_PCM_WRITE_FILTER:
- case SOUND_PCM_READ_FILTER:
- default:
- ret = -EINVAL;
- break;
-
- }
- return ret;
-}
-
-static int
-trident_open(struct inode *inode, struct file *file)
-{
- int i = 0;
- int minor = iminor(inode);
- struct trident_card *card = devs;
- struct trident_state *state = NULL;
- struct dmabuf *dmabuf = NULL;
- unsigned long flags;
-
- /* Added by Matt Wu 01-05-2001 */
- /* TODO: there's some redundacy here wrt the check below */
- /* for multi_use_count > 0. Should we return -EBUSY or find */
- /* a different card? for now, don't break current behaviour */
- /* -- mulix */
- if (file->f_mode & FMODE_READ) {
- if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
- if (card->multi_channel_use_count > 0)
- return -EBUSY;
- }
- }
-
- /* find an available virtual channel (instance of /dev/dsp) */
- while (card != NULL) {
- mutex_lock(&card->open_mutex);
- if (file->f_mode & FMODE_READ) {
- /* Skip opens on cards that are in 6 channel mode */
- if (card->multi_channel_use_count > 0) {
- mutex_unlock(&card->open_mutex);
- card = card->next;
- continue;
- }
- }
- for (i = 0; i < NR_HW_CH; i++) {
- if (card->states[i] == NULL) {
- state = card->states[i] = kzalloc(sizeof(*state), GFP_KERNEL);
- if (state == NULL) {
- mutex_unlock(&card->open_mutex);
- return -ENOMEM;
- }
- mutex_init(&state->sem);
- dmabuf = &state->dmabuf;
- goto found_virt;
- }
- }
- mutex_unlock(&card->open_mutex);
- card = card->next;
- }
- /* no more virtual channel avaiable */
- if (!state) {
- return -ENODEV;
- }
- found_virt:
- /* found a free virtual channel, allocate hardware channels */
- if (file->f_mode & FMODE_READ)
- dmabuf->channel = card->alloc_rec_pcm_channel(card);
- else
- dmabuf->channel = card->alloc_pcm_channel(card);
-
- if (dmabuf->channel == NULL) {
- kfree(card->states[i]);
- card->states[i] = NULL;
- return -ENODEV;
- }
-
- /* initialize the virtual channel */
- state->virt = i;
- state->card = card;
- state->magic = TRIDENT_STATE_MAGIC;
- init_waitqueue_head(&dmabuf->wait);
- file->private_data = state;
-
- /* set default sample format. According to OSS Programmer's */
- /* Guide /dev/dsp should be default to unsigned 8-bits, mono, */
- /* with sample rate 8kHz and /dev/dspW will accept 16-bits sample */
- if (file->f_mode & FMODE_WRITE) {
- dmabuf->fmt &= ~TRIDENT_FMT_MASK;
- if ((minor & 0x0f) == SND_DEV_DSP16)
- dmabuf->fmt |= TRIDENT_FMT_16BIT;
- dmabuf->ossfragshift = 0;
- dmabuf->ossmaxfrags = 0;
- dmabuf->subdivision = 0;
- if (card->pci_id == PCI_DEVICE_ID_SI_7018) {
- /* set default channel attribute to normal playback */
- dmabuf->channel->attribute = CHANNEL_PB;
- }
- spin_lock_irqsave(&card->lock, flags);
- trident_set_dac_rate(state, 8000);
- spin_unlock_irqrestore(&card->lock, flags);
- }
-
- if (file->f_mode & FMODE_READ) {
- /* FIXME: Trident 4d can only record in signed 16-bits stereo, */
- /* 48kHz sample, to be dealed with in trident_set_adc_rate() ?? */
- dmabuf->fmt &= ~TRIDENT_FMT_MASK;
- if ((minor & 0x0f) == SND_DEV_DSP16)
- dmabuf->fmt |= TRIDENT_FMT_16BIT;
- dmabuf->ossfragshift = 0;
- dmabuf->ossmaxfrags = 0;
- dmabuf->subdivision = 0;
- if (card->pci_id == PCI_DEVICE_ID_SI_7018) {
- /* set default channel attribute to 0x8a80, record from
- PCM L/R FIFO and mono = (left + right + 1)/2 */
- dmabuf->channel->attribute = (CHANNEL_REC | PCM_LR |
- MONO_MIX);
- }
- spin_lock_irqsave(&card->lock, flags);
- trident_set_adc_rate(state, 8000);
- spin_unlock_irqrestore(&card->lock, flags);
-
- /* Added by Matt Wu 01-05-2001 */
- if (card->pci_id == PCI_DEVICE_ID_ALI_5451)
- card->rec_channel_use_count++;
- }
-
- state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
- mutex_unlock(&card->open_mutex);
-
- pr_debug("trident: open virtual channel %d, hard channel %d\n",
- state->virt, dmabuf->channel->num);
-
- return nonseekable_open(inode, file);
-}
-
-static int
-trident_release(struct inode *inode, struct file *file)
-{
- struct trident_state *state = (struct trident_state *)file->private_data;
- struct trident_card *card;
- struct dmabuf *dmabuf;
-
- VALIDATE_STATE(state);
-
- card = state->card;
- dmabuf = &state->dmabuf;
-
- if (file->f_mode & FMODE_WRITE) {
- trident_clear_tail(state);
- drain_dac(state, file->f_flags & O_NONBLOCK);
- }
-
- pr_debug("trident: closing virtual channel %d, hard channel %d\n",
- state->virt, dmabuf->channel->num);
-
- /* stop DMA state machine and free DMA buffers/channels */
- mutex_lock(&card->open_mutex);
-
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(state);
- dealloc_dmabuf(&state->dmabuf, state->card->pci_dev);
- state->card->free_pcm_channel(state->card, dmabuf->channel->num);
-
- /* Added by Matt Wu */
- if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
- if (state->chans_num > 2) {
- if (card->multi_channel_use_count-- < 0)
- card->multi_channel_use_count = 0;
- if (card->multi_channel_use_count == 0)
- ali_close_multi_channels();
- ali_free_other_states_resources(state);
- }
- }
- }
- if (file->f_mode & FMODE_READ) {
- stop_adc(state);
- dealloc_dmabuf(&state->dmabuf, state->card->pci_dev);
- state->card->free_pcm_channel(state->card, dmabuf->channel->num);
-
- /* Added by Matt Wu */
- if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
- if (card->rec_channel_use_count-- < 0)
- card->rec_channel_use_count = 0;
- }
- }
-
- card->states[state->virt] = NULL;
- kfree(state);
-
- /* we're covered by the open_mutex */
- mutex_unlock(&card->open_mutex);
-
- return 0;
-}
-
-static const struct file_operations trident_audio_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .read = trident_read,
- .write = trident_write,
- .poll = trident_poll,
- .ioctl = trident_ioctl,
- .mmap = trident_mmap,
- .open = trident_open,
- .release = trident_release,
-};
-
-/* trident specific AC97 functions */
-/* Write AC97 codec registers */
-static void
-trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val)
-{
- struct trident_card *card = (struct trident_card *)codec->private_data;
- unsigned int address, mask, busy;
- unsigned short count = 0xffff;
- unsigned long flags;
- u32 data;
-
- data = ((u32) val) << 16;
-
- switch (card->pci_id) {
- default:
- case PCI_DEVICE_ID_SI_7018:
- address = SI_AC97_WRITE;
- mask = SI_AC97_BUSY_WRITE | SI_AC97_AUDIO_BUSY;
- if (codec->id)
- mask |= SI_AC97_SECONDARY;
- busy = SI_AC97_BUSY_WRITE;
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
- address = DX_ACR0_AC97_W;
- mask = busy = DX_AC97_BUSY_WRITE;
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- address = NX_ACR1_AC97_W;
- mask = NX_AC97_BUSY_WRITE;
- if (codec->id)
- mask |= NX_AC97_WRITE_SECONDARY;
- busy = NX_AC97_BUSY_WRITE;
- break;
- case PCI_DEVICE_ID_INTERG_5050:
- address = SI_AC97_WRITE;
- mask = busy = SI_AC97_BUSY_WRITE;
- if (codec->id)
- mask |= SI_AC97_SECONDARY;
- break;
- }
-
- spin_lock_irqsave(&card->lock, flags);
- do {
- if ((inw(TRID_REG(card, address)) & busy) == 0)
- break;
- } while (--count);
-
- data |= (mask | (reg & AC97_REG_ADDR));
-
- if (count == 0) {
- printk(KERN_ERR "trident: AC97 CODEC write timed out.\n");
- spin_unlock_irqrestore(&card->lock, flags);
- return;
- }
-
- outl(data, TRID_REG(card, address));
- spin_unlock_irqrestore(&card->lock, flags);
-}
-
-/* Read AC97 codec registers */
-static u16
-trident_ac97_get(struct ac97_codec *codec, u8 reg)
-{
- struct trident_card *card = (struct trident_card *)codec->private_data;
- unsigned int address, mask, busy;
- unsigned short count = 0xffff;
- unsigned long flags;
- u32 data;
-
- switch (card->pci_id) {
- default:
- case PCI_DEVICE_ID_SI_7018:
- address = SI_AC97_READ;
- mask = SI_AC97_BUSY_READ | SI_AC97_AUDIO_BUSY;
- if (codec->id)
- mask |= SI_AC97_SECONDARY;
- busy = SI_AC97_BUSY_READ;
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
- address = DX_ACR1_AC97_R;
- mask = busy = DX_AC97_BUSY_READ;
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- if (codec->id)
- address = NX_ACR3_AC97_R_SECONDARY;
- else
- address = NX_ACR2_AC97_R_PRIMARY;
- mask = NX_AC97_BUSY_READ;
- busy = NX_AC97_BUSY_READ | NX_AC97_BUSY_DATA;
- break;
- case PCI_DEVICE_ID_INTERG_5050:
- address = SI_AC97_READ;
- mask = busy = SI_AC97_BUSY_READ;
- if (codec->id)
- mask |= SI_AC97_SECONDARY;
- break;
- }
-
- data = (mask | (reg & AC97_REG_ADDR));
-
- spin_lock_irqsave(&card->lock, flags);
- outl(data, TRID_REG(card, address));
- do {
- data = inl(TRID_REG(card, address));
- if ((data & busy) == 0)
- break;
- } while (--count);
- spin_unlock_irqrestore(&card->lock, flags);
-
- if (count == 0) {
- printk(KERN_ERR "trident: AC97 CODEC read timed out.\n");
- data = 0;
- }
- return ((u16) (data >> 16));
-}
-
-/* rewrite ac97 read and write mixer register by hulei for ALI*/
-static int
-acquirecodecaccess(struct trident_card *card)
-{
- u16 wsemamask = 0x6000; /* bit 14..13 */
- u16 wsemabits;
- u16 wcontrol;
- int block = 0;
- int ncount = 25;
- while (1) {
- wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE));
- wsemabits = wcontrol & wsemamask;
-
- if (wsemabits == 0x4000)
- return 1; /* 0x4000 is audio ,then success */
- if (ncount-- < 0)
- break;
- if (wsemabits == 0) {
- unlock:
- outl(((u32) (wcontrol & 0x1eff) | 0x00004000),
- TRID_REG(card, ALI_AC97_WRITE));
- continue;
- }
- udelay(20);
- }
- if (!block) {
- pr_debug("accesscodecsemaphore: try unlock\n");
- block = 1;
- goto unlock;
- }
- return 0;
-}
-
-static void
-releasecodecaccess(struct trident_card *card)
-{
- unsigned long wcontrol;
- wcontrol = inl(TRID_REG(card, ALI_AC97_WRITE));
- outl((wcontrol & 0xffff1eff), TRID_REG(card, ALI_AC97_WRITE));
-}
-
-static int
-waitforstimertick(struct trident_card *card)
-{
- unsigned long chk1, chk2;
- unsigned int wcount = 0xffff;
- chk1 = inl(TRID_REG(card, ALI_STIMER));
-
- while (1) {
- chk2 = inl(TRID_REG(card, ALI_STIMER));
- if ((wcount > 0) && chk1 != chk2)
- return 1;
- if (wcount <= 0)
- break;
- udelay(50);
- }
- return 0;
-}
-
-/* Read AC97 codec registers for ALi*/
-static u16
-ali_ac97_get(struct trident_card *card, int secondary, u8 reg)
-{
- unsigned int address, mask;
- unsigned int ncount;
- unsigned long aud_reg;
- u32 data;
- u16 wcontrol;
- unsigned long flags;
-
- BUG_ON(!card);
-
- address = ALI_AC97_READ;
- if (card->revision == ALI_5451_V02) {
- address = ALI_AC97_WRITE;
- }
- mask = ALI_AC97_READ_ACTION | ALI_AC97_AUDIO_BUSY;
- if (secondary)
- mask |= ALI_AC97_SECONDARY;
-
- spin_lock_irqsave(&card->lock, flags);
-
- if (!acquirecodecaccess(card))
- printk(KERN_ERR "access codec fail\n");
-
- wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE));
- wcontrol &= 0xfe00;
- wcontrol |= (0x8000 | reg);
- outw(wcontrol, TRID_REG(card, ALI_AC97_WRITE));
-
- data = (mask | (reg & AC97_REG_ADDR));
-
- if (!waitforstimertick(card)) {
- printk(KERN_ERR "ali_ac97_read: BIT_CLOCK is dead\n");
- goto releasecodec;
- }
-
- udelay(20);
-
- ncount = 10;
-
- while (1) {
- if ((inw(TRID_REG(card, ALI_AC97_WRITE)) & ALI_AC97_BUSY_READ)
- != 0)
- break;
- if (ncount <= 0)
- break;
- if (ncount-- == 1) {
- pr_debug("ali_ac97_read :try clear busy flag\n");
- aud_reg = inl(TRID_REG(card, ALI_AC97_WRITE));
- outl((aud_reg & 0xffff7fff),
- TRID_REG(card, ALI_AC97_WRITE));
- }
- udelay(10);
- }
-
- data = inl(TRID_REG(card, address));
-
- spin_unlock_irqrestore(&card->lock, flags);
-
- return ((u16) (data >> 16));
-
- releasecodec:
- releasecodecaccess(card);
- spin_unlock_irqrestore(&card->lock, flags);
- printk(KERN_ERR "ali_ac97_read: AC97 CODEC read timed out.\n");
- return 0;
-}
-
-/* Write AC97 codec registers for hulei*/
-static void
-ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val)
-{
- unsigned int address, mask;
- unsigned int ncount;
- u32 data;
- u16 wcontrol;
- unsigned long flags;
-
- data = ((u32) val) << 16;
-
- BUG_ON(!card);
-
- address = ALI_AC97_WRITE;
- mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY;
- if (secondary)
- mask |= ALI_AC97_SECONDARY;
- if (card->revision == ALI_5451_V02)
- mask |= ALI_AC97_WRITE_MIXER_REGISTER;
-
- spin_lock_irqsave(&card->lock, flags);
- if (!acquirecodecaccess(card))
- printk(KERN_ERR "ali_ac97_write: access codec fail\n");
-
- wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE));
- wcontrol &= 0xff00;
- wcontrol |= (0x8100 | reg); /* bit 8=1: (ali1535 )reserved/ */
- /* ali1535+ write */
- outl((data | wcontrol), TRID_REG(card, ALI_AC97_WRITE));
-
- if (!waitforstimertick(card)) {
- printk(KERN_ERR "BIT_CLOCK is dead\n");
- goto releasecodec;
- }
-
- ncount = 10;
- while (1) {
- wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE));
- if (!(wcontrol & 0x8000))
- break;
- if (ncount <= 0)
- break;
- if (ncount-- == 1) {
- pr_debug("ali_ac97_set :try clear busy flag!!\n");
- outw(wcontrol & 0x7fff,
- TRID_REG(card, ALI_AC97_WRITE));
- }
- udelay(10);
- }
-
- releasecodec:
- releasecodecaccess(card);
- spin_unlock_irqrestore(&card->lock, flags);
- return;
-}
-
-static void
-ali_enable_special_channel(struct trident_state *stat)
-{
- struct trident_card *card = stat->card;
- unsigned long s_channels;
-
- s_channels = inl(TRID_REG(card, ALI_GLOBAL_CONTROL));
- s_channels |= (1 << stat->dmabuf.channel->num);
- outl(s_channels, TRID_REG(card, ALI_GLOBAL_CONTROL));
-}
-
-static u16
-ali_ac97_read(struct ac97_codec *codec, u8 reg)
-{
- int id;
- u16 data;
- struct trident_card *card = NULL;
-
- /* Added by Matt Wu */
- BUG_ON(!codec);
-
- card = (struct trident_card *) codec->private_data;
-
- if (!card->mixer_regs_ready)
- return ali_ac97_get(card, codec->id, reg);
-
- /*
- * FIXME: need to stop this caching some registers
- */
- if (codec->id)
- id = 1;
- else
- id = 0;
-
- data = card->mixer_regs[reg / 2][id];
- return data;
-}
-
-static void
-ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val)
-{
- int id;
- struct trident_card *card;
-
- /* Added by Matt Wu */
- BUG_ON(!codec);
-
- card = (struct trident_card *) codec->private_data;
-
- if (!card->mixer_regs_ready) {
- ali_ac97_set(card, codec->id, reg, val);
- return;
- }
-
- if (codec->id)
- id = 1;
- else
- id = 0;
-
- card->mixer_regs[reg / 2][id] = val;
- ali_ac97_set(card, codec->id, reg, val);
-}
-
-/*
-flag: ALI_SPDIF_OUT_TO_SPDIF_OUT
- ALI_PCM_TO_SPDIF_OUT
-*/
-
-static void
-ali_setup_spdif_out(struct trident_card *card, int flag)
-{
- unsigned long spdif;
- unsigned char ch;
-
- char temp;
- struct pci_dev *pci_dev = NULL;
-
- pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
- pci_dev);
- if (pci_dev == NULL)
- return;
- pci_read_config_byte(pci_dev, 0x61, &temp);
- temp |= 0x40;
- pci_write_config_byte(pci_dev, 0x61, temp);
- pci_read_config_byte(pci_dev, 0x7d, &temp);
- temp |= 0x01;
- pci_write_config_byte(pci_dev, 0x7d, temp);
- pci_read_config_byte(pci_dev, 0x7e, &temp);
- temp &= (~0x20);
- temp |= 0x10;
- pci_write_config_byte(pci_dev, 0x7e, temp);
-
- pci_dev_put(pci_dev);
-
- ch = inb(TRID_REG(card, ALI_SCTRL));
- outb(ch | ALI_SPDIF_OUT_ENABLE, TRID_REG(card, ALI_SCTRL));
- ch = inb(TRID_REG(card, ALI_SPDIF_CTRL));
- outb(ch & ALI_SPDIF_OUT_CH_STATUS, TRID_REG(card, ALI_SPDIF_CTRL));
-
- if (flag & ALI_SPDIF_OUT_TO_SPDIF_OUT) {
- spdif = inw(TRID_REG(card, ALI_GLOBAL_CONTROL));
- spdif |= ALI_SPDIF_OUT_CH_ENABLE;
- spdif &= ALI_SPDIF_OUT_SEL_SPDIF;
- outw(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL));
- spdif = inw(TRID_REG(card, ALI_SPDIF_CS));
- if (flag & ALI_SPDIF_OUT_NON_PCM)
- spdif |= 0x0002;
- else
- spdif &= (~0x0002);
- outw(spdif, TRID_REG(card, ALI_SPDIF_CS));
- } else {
- spdif = inw(TRID_REG(card, ALI_GLOBAL_CONTROL));
- spdif |= ALI_SPDIF_OUT_SEL_PCM;
- outw(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL));
- }
-}
-
-static void
-ali_disable_special_channel(struct trident_card *card, int ch)
-{
- unsigned long sc;
-
- sc = inl(TRID_REG(card, ALI_GLOBAL_CONTROL));
- sc &= ~(1 << ch);
- outl(sc, TRID_REG(card, ALI_GLOBAL_CONTROL));
-}
-
-static void
-ali_disable_spdif_in(struct trident_card *card)
-{
- unsigned long spdif;
-
- spdif = inl(TRID_REG(card, ALI_GLOBAL_CONTROL));
- spdif &= (~ALI_SPDIF_IN_SUPPORT);
- outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL));
-
- ali_disable_special_channel(card, ALI_SPDIF_IN_CHANNEL);
-}
-
-static void
-ali_setup_spdif_in(struct trident_card *card)
-{
- unsigned long spdif;
-
- //Set SPDIF IN Supported
- spdif = inl(TRID_REG(card, ALI_GLOBAL_CONTROL));
- spdif |= ALI_SPDIF_IN_SUPPORT;
- outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL));
-
- //Set SPDIF IN Rec
- spdif = inl(TRID_REG(card, ALI_GLOBAL_CONTROL));
- spdif |= ALI_SPDIF_IN_CH_ENABLE;
- outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL));
-
- spdif = inb(TRID_REG(card, ALI_SPDIF_CTRL));
- spdif |= ALI_SPDIF_IN_CH_STATUS;
- outb(spdif, TRID_REG(card, ALI_SPDIF_CTRL));
-/*
- spdif = inb(TRID_REG(card, ALI_SPDIF_CTRL));
- spdif |= ALI_SPDIF_IN_FUNC_ENABLE;
- outb(spdif, TRID_REG(card, ALI_SPDIF_CTRL));
-*/
-}
-
-static void
-ali_delay(struct trident_card *card, int interval)
-{
- unsigned long begintimer, currenttimer;
-
- begintimer = inl(TRID_REG(card, ALI_STIMER));
- currenttimer = inl(TRID_REG(card, ALI_STIMER));
-
- while (currenttimer < begintimer + interval)
- currenttimer = inl(TRID_REG(card, ALI_STIMER));
-}
-
-static void
-ali_detect_spdif_rate(struct trident_card *card)
-{
- u16 wval = 0;
- u16 count = 0;
- u8 bval = 0, R1 = 0, R2 = 0;
-
- bval = inb(TRID_REG(card, ALI_SPDIF_CTRL));
- bval |= 0x02;
- outb(bval, TRID_REG(card, ALI_SPDIF_CTRL));
-
- bval = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1));
- bval |= 0x1F;
- outb(bval, TRID_REG(card, ALI_SPDIF_CTRL + 1));
-
- while (((R1 < 0x0B) || (R1 > 0x0E)) && (R1 != 0x12) &&
- count <= 50000) {
- count++;
-
- ali_delay(card, 6);
-
- bval = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1));
- R1 = bval & 0x1F;
- }
-
- if (count > 50000) {
- printk(KERN_WARNING "trident: Error in "
- "ali_detect_spdif_rate!\n");
- return;
- }
-
- count = 0;
-
- while (count <= 50000) {
- count++;
-
- ali_delay(card, 6);
-
- bval = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1));
- R2 = bval & 0x1F;
-
- if (R2 != R1)
- R1 = R2;
- else
- break;
- }
-
- if (count > 50000) {
- printk(KERN_WARNING "trident: Error in "
- "ali_detect_spdif_rate!\n");
- return;
- }
-
- switch (R2) {
- case 0x0b:
- case 0x0c:
- case 0x0d:
- case 0x0e:
- wval = inw(TRID_REG(card, ALI_SPDIF_CTRL + 2));
- wval &= 0xE0F0;
- wval |= (u16) 0x09 << 8 | (u16) 0x05;
- outw(wval, TRID_REG(card, ALI_SPDIF_CTRL + 2));
-
- bval = inb(TRID_REG(card, ALI_SPDIF_CS + 3)) & 0xF0;
- outb(bval | 0x02, TRID_REG(card, ALI_SPDIF_CS + 3));
- break;
-
- case 0x12:
- wval = inw(TRID_REG(card, ALI_SPDIF_CTRL + 2));
- wval &= 0xE0F0;
- wval |= (u16) 0x0E << 8 | (u16) 0x08;
- outw(wval, TRID_REG(card, ALI_SPDIF_CTRL + 2));
-
- bval = inb(TRID_REG(card, ALI_SPDIF_CS + 3)) & 0xF0;
- outb(bval | 0x03, TRID_REG(card, ALI_SPDIF_CS + 3));
- break;
-
- default:
- break;
- }
-
-}
-
-static unsigned int
-ali_get_spdif_in_rate(struct trident_card *card)
-{
- u32 dwRate = 0;
- u8 bval = 0;
-
- ali_detect_spdif_rate(card);
-
- bval = inb(TRID_REG(card, ALI_SPDIF_CTRL));
- bval &= 0x7F;
- bval |= 0x40;
- outb(bval, TRID_REG(card, ALI_SPDIF_CTRL));
-
- bval = inb(TRID_REG(card, ALI_SPDIF_CS + 3));
- bval &= 0x0F;
-
- switch (bval) {
- case 0:
- dwRate = 44100;
- break;
- case 1:
- dwRate = 48000;
- break;
- case 2:
- dwRate = 32000;
- break;
- default:
- // Error occurs
- break;
- }
-
- return dwRate;
-
-}
-
-static int
-ali_close_multi_channels(void)
-{
- char temp = 0;
- struct pci_dev *pci_dev = NULL;
-
- pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
- pci_dev);
- if (pci_dev == NULL)
- return -1;
-
- pci_read_config_byte(pci_dev, 0x59, &temp);
- temp &= ~0x80;
- pci_write_config_byte(pci_dev, 0x59, temp);
-
- pci_dev_put(pci_dev);
-
- pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
- NULL);
- if (pci_dev == NULL)
- return -1;
-
- pci_read_config_byte(pci_dev, 0xB8, &temp);
- temp &= ~0x20;
- pci_write_config_byte(pci_dev, 0xB8, temp);
-
- pci_dev_put(pci_dev);
-
- return 0;
-}
-
-static int
-ali_setup_multi_channels(struct trident_card *card, int chan_nums)
-{
- unsigned long dwValue;
- char temp = 0;
- struct pci_dev *pci_dev = NULL;
-
- pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
- pci_dev);
- if (pci_dev == NULL)
- return -1;
- pci_read_config_byte(pci_dev, 0x59, &temp);
- temp |= 0x80;
- pci_write_config_byte(pci_dev, 0x59, temp);
-
- pci_dev_put(pci_dev);
-
- pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
- NULL);
- if (pci_dev == NULL)
- return -1;
- pci_read_config_byte(pci_dev, (int) 0xB8, &temp);
- temp |= 0x20;
- pci_write_config_byte(pci_dev, (int) 0xB8, (u8) temp);
-
- pci_dev_put(pci_dev);
-
- if (chan_nums == 6) {
- dwValue = inl(TRID_REG(card, ALI_SCTRL)) | 0x000f0000;
- outl(dwValue, TRID_REG(card, ALI_SCTRL));
- mdelay(4);
- dwValue = inl(TRID_REG(card, ALI_SCTRL));
- if (dwValue & 0x2000000) {
- ali_ac97_write(card->ac97_codec[0], 0x02, 8080);
- ali_ac97_write(card->ac97_codec[0], 0x36, 0);
- ali_ac97_write(card->ac97_codec[0], 0x38, 0);
- /*
- * On a board with a single codec you won't get the
- * surround. On other boards configure it.
- */
- if (card->ac97_codec[1] != NULL) {
- ali_ac97_write(card->ac97_codec[1], 0x36, 0);
- ali_ac97_write(card->ac97_codec[1], 0x38, 0);
- ali_ac97_write(card->ac97_codec[1], 0x02, 0x0606);
- ali_ac97_write(card->ac97_codec[1], 0x18, 0x0303);
- ali_ac97_write(card->ac97_codec[1], 0x74, 0x3);
- }
- return 1;
- }
- }
- return -EINVAL;
-}
-
-static void
-ali_free_pcm_channel(struct trident_card *card, unsigned int channel)
-{
- int bank;
-
- if (channel > 31)
- return;
-
- bank = channel >> 5;
- channel = channel & 0x1f;
-
- card->banks[bank].bitmap &= ~(1 << (channel));
-}
-
-static int
-ali_allocate_other_states_resources(struct trident_state *state, int chan_nums)
-{
- struct trident_card *card = state->card;
- struct trident_state *s;
- int i, state_count = 0;
- struct trident_pcm_bank *bank;
- struct trident_channel *channel;
- unsigned long num;
-
- bank = &card->banks[BANK_A];
-
- if (chan_nums != 6)
- return 0;
-
- for (i = 0; (i < ALI_CHANNELS) && (state_count != 4); i++) {
- if (card->states[i])
- continue;
-
- num = ali_multi_channels_5_1[state_count];
- if (!(bank->bitmap & (1 << num))) {
- bank->bitmap |= 1 << num;
- channel = &bank->channels[num];
- channel->num = num;
- } else {
- state_count--;
- for (; state_count >= 0; state_count--) {
- kfree(state->other_states[state_count]);
- num = ali_multi_channels_5_1[state_count];
- ali_free_pcm_channel(card, num);
- }
- return -EBUSY;
- }
- s = card->states[i] = kzalloc(sizeof(*state), GFP_KERNEL);
- if (!s) {
- num = ali_multi_channels_5_1[state_count];
- ali_free_pcm_channel(card, num);
- state_count--;
- for (; state_count >= 0; state_count--) {
- num = ali_multi_channels_5_1[state_count];
- ali_free_pcm_channel(card, num);
- kfree(state->other_states[state_count]);
- }
- return -ENOMEM;
- }
-
- s->dmabuf.channel = channel;
- s->dmabuf.ossfragshift = s->dmabuf.ossmaxfrags =
- s->dmabuf.subdivision = 0;
- init_waitqueue_head(&s->dmabuf.wait);
- s->magic = card->magic;
- s->card = card;
- s->virt = i;
- ali_enable_special_channel(s);
- state->other_states[state_count++] = s;
- }
-
- if (state_count != 4) {
- state_count--;
- for (; state_count >= 0; state_count--) {
- kfree(state->other_states[state_count]);
- num = ali_multi_channels_5_1[state_count];
- ali_free_pcm_channel(card, num);
- }
- return -EBUSY;
- }
- return 0;
-}
-
-#ifdef CONFIG_PM
-/* save registers for ALi Power Management */
-static struct ali_saved_registers {
- unsigned long global_regs[ALI_GLOBAL_REGS];
- unsigned long channel_regs[ALI_CHANNELS][ALI_CHANNEL_REGS];
- unsigned mixer_regs[ALI_MIXER_REGS];
-} ali_registers;
-
-static void
-ali_save_regs(struct trident_card *card)
-{
- unsigned long flags;
- int i, j;
-
- spin_lock_irqsave(&card->lock, flags);
-
- ali_registers.global_regs[0x2c] = inl(TRID_REG(card, T4D_MISCINT));
- //ali_registers.global_regs[0x20] = inl(TRID_REG(card,T4D_START_A));
- ali_registers.global_regs[0x21] = inl(TRID_REG(card, T4D_STOP_A));
-
- //disable all IRQ bits
- outl(ALI_DISABLE_ALL_IRQ, TRID_REG(card, T4D_MISCINT));
-
- for (i = 1; i < ALI_MIXER_REGS; i++)
- ali_registers.mixer_regs[i] = ali_ac97_read(card->ac97_codec[0],
- i * 2);
-
- for (i = 0; i < ALI_GLOBAL_REGS; i++) {
- if ((i * 4 == T4D_MISCINT) || (i * 4 == T4D_STOP_A))
- continue;
- ali_registers.global_regs[i] = inl(TRID_REG(card, i * 4));
- }
-
- for (i = 0; i < ALI_CHANNELS; i++) {
- outb(i, TRID_REG(card, T4D_LFO_GC_CIR));
- for (j = 0; j < ALI_CHANNEL_REGS; j++)
- ali_registers.channel_regs[i][j] = inl(TRID_REG(card,
- j * 4 + 0xe0));
- }
-
- //Stop all HW channel
- outl(ALI_STOP_ALL_CHANNELS, TRID_REG(card, T4D_STOP_A));
-
- spin_unlock_irqrestore(&card->lock, flags);
-}
-
-static void
-ali_restore_regs(struct trident_card *card)
-{
- unsigned long flags;
- int i, j;
-
- spin_lock_irqsave(&card->lock, flags);
-
- for (i = 1; i < ALI_MIXER_REGS; i++)
- ali_ac97_write(card->ac97_codec[0], i * 2,
- ali_registers.mixer_regs[i]);
-
- for (i = 0; i < ALI_CHANNELS; i++) {
- outb(i, TRID_REG(card, T4D_LFO_GC_CIR));
- for (j = 0; j < ALI_CHANNEL_REGS; j++)
- outl(ali_registers.channel_regs[i][j],
- TRID_REG(card, j * 4 + 0xe0));
- }
-
- for (i = 0; i < ALI_GLOBAL_REGS; i++) {
- if ((i * 4 == T4D_MISCINT) || (i * 4 == T4D_STOP_A) ||
- (i * 4 == T4D_START_A))
- continue;
- outl(ali_registers.global_regs[i], TRID_REG(card, i * 4));
- }
-
- //start HW channel
- outl(ali_registers.global_regs[0x20], TRID_REG(card, T4D_START_A));
- //restore IRQ enable bits
- outl(ali_registers.global_regs[0x2c], TRID_REG(card, T4D_MISCINT));
-
- spin_unlock_irqrestore(&card->lock, flags);
-}
-
-static int
-trident_suspend(struct pci_dev *dev, pm_message_t unused)
-{
- struct trident_card *card = pci_get_drvdata(dev);
-
- if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
- ali_save_regs(card);
- }
- return 0;
-}
-
-static int
-trident_resume(struct pci_dev *dev)
-{
- struct trident_card *card = pci_get_drvdata(dev);
-
- if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
- ali_restore_regs(card);
- }
- return 0;
-}
-#endif
-
-static struct trident_channel *
-ali_alloc_pcm_channel(struct trident_card *card)
-{
- struct trident_pcm_bank *bank;
- int idx;
-
- bank = &card->banks[BANK_A];
-
- if (inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) &
- (ALI_SPDIF_OUT_CH_ENABLE)) {
- idx = ALI_SPDIF_OUT_CHANNEL;
- if (!(bank->bitmap & (1 << idx))) {
- struct trident_channel *channel = &bank->channels[idx];
- bank->bitmap |= 1 << idx;
- channel->num = idx;
- return channel;
- }
- }
-
- for (idx = ALI_PCM_OUT_CHANNEL_FIRST; idx <= ALI_PCM_OUT_CHANNEL_LAST;
- idx++) {
- if (!(bank->bitmap & (1 << idx))) {
- struct trident_channel *channel = &bank->channels[idx];
- bank->bitmap |= 1 << idx;
- channel->num = idx;
- return channel;
- }
- }
-
- /* no more free channels avaliable */
-#if 0
- printk(KERN_ERR "ali: no more channels available on Bank A.\n");
-#endif /* 0 */
- return NULL;
-}
-
-static struct trident_channel *
-ali_alloc_rec_pcm_channel(struct trident_card *card)
-{
- struct trident_pcm_bank *bank;
- int idx;
-
- if (inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) & ALI_SPDIF_IN_SUPPORT)
- idx = ALI_SPDIF_IN_CHANNEL;
- else
- idx = ALI_PCM_IN_CHANNEL;
-
- bank = &card->banks[BANK_A];
-
- if (!(bank->bitmap & (1 << idx))) {
- struct trident_channel *channel = &bank->channels[idx];
- bank->bitmap |= 1 << idx;
- channel->num = idx;
- return channel;
- }
-
- /* no free recordable channels avaliable */
-#if 0
- printk(KERN_ERR "ali: no recordable channels available on Bank A.\n");
-#endif /* 0 */
- return NULL;
-}
-
-static void
-ali_set_spdif_out_rate(struct trident_card *card, unsigned int rate)
-{
- unsigned char ch_st_sel;
- unsigned short status_rate;
-
- switch (rate) {
- case 44100:
- status_rate = 0;
- break;
- case 32000:
- status_rate = 0x300;
- break;
- case 48000:
- default:
- status_rate = 0x200;
- break;
- }
-
- /* select spdif_out */
- ch_st_sel = inb(TRID_REG(card, ALI_SPDIF_CTRL)) & ALI_SPDIF_OUT_CH_STATUS;
-
- ch_st_sel |= 0x80; /* select right */
- outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL));
- outb(status_rate | 0x20, TRID_REG(card, ALI_SPDIF_CS + 2));
-
- ch_st_sel &= (~0x80); /* select left */
- outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL));
- outw(status_rate | 0x10, TRID_REG(card, ALI_SPDIF_CS + 2));
-}
-
-static void
-ali_address_interrupt(struct trident_card *card)
-{
- int i, channel;
- struct trident_state *state;
- u32 mask, channel_mask;
-
- mask = trident_get_interrupt_mask(card, 0);
- for (i = 0; i < NR_HW_CH; i++) {
- if ((state = card->states[i]) == NULL)
- continue;
- channel = state->dmabuf.channel->num;
- if ((channel_mask = 1 << channel) & mask) {
- mask &= ~channel_mask;
- trident_ack_channel_interrupt(card, channel);
- udelay(100);
- state->dmabuf.update_flag |= ALI_ADDRESS_INT_UPDATE;
- trident_update_ptr(state);
- }
- }
- if (mask) {
- for (i = 0; i < NR_HW_CH; i++) {
- if (mask & (1 << i)) {
- printk("ali: spurious channel irq %d.\n", i);
- trident_ack_channel_interrupt(card, i);
- trident_stop_voice(card, i);
- trident_disable_voice_irq(card, i);
- }
- }
- }
-}
-
-/* Updating the values of counters of other_states' DMAs without lock
-protection is no harm because all DMAs of multi-channels and interrupt
-depend on a master state's DMA, and changing the counters of the master
-state DMA is protected by a spinlock.
-*/
-static int
-ali_write_5_1(struct trident_state *state, const char __user *buf,
- int cnt_for_multi_channel, unsigned int *copy_count,
- unsigned int *state_cnt)
-{
-
- struct dmabuf *dmabuf = &state->dmabuf;
- struct dmabuf *dmabuf_temp;
- const char __user *buffer = buf;
- unsigned swptr, other_dma_nums, sample_s;
- unsigned int i, loop;
-
- other_dma_nums = 4;
- sample_s = sample_size[dmabuf->fmt] >> 1;
- swptr = dmabuf->swptr;
-
- if ((i = state->multi_channels_adjust_count) > 0) {
- if (i == 1) {
- if (copy_from_user(dmabuf->rawbuf + swptr,
- buffer, sample_s))
- return -EFAULT;
- seek_offset(swptr, buffer, cnt_for_multi_channel,
- sample_s, *copy_count);
- i--;
- (*state_cnt) += sample_s;
- state->multi_channels_adjust_count++;
- } else
- i = i - (state->chans_num - other_dma_nums);
- for (; (i < other_dma_nums) && (cnt_for_multi_channel > 0); i++) {
- dmabuf_temp = &state->other_states[i]->dmabuf;
- if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
- buffer, sample_s))
- return -EFAULT;
- seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
- sample_s, *copy_count);
- }
- if (cnt_for_multi_channel == 0)
- state->multi_channels_adjust_count += i;
- }
- if (cnt_for_multi_channel > 0) {
- loop = cnt_for_multi_channel / (state->chans_num * sample_s);
- for (i = 0; i < loop; i++) {
- if (copy_from_user(dmabuf->rawbuf + swptr, buffer,
- sample_s * 2))
- return -EFAULT;
- seek_offset(swptr, buffer, cnt_for_multi_channel,
- sample_s * 2, *copy_count);
- (*state_cnt) += (sample_s * 2);
-
- dmabuf_temp = &state->other_states[0]->dmabuf;
- if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
- buffer, sample_s))
- return -EFAULT;
- seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
- sample_s, *copy_count);
-
- dmabuf_temp = &state->other_states[1]->dmabuf;
- if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
- buffer, sample_s))
- return -EFAULT;
- seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
- sample_s, *copy_count);
-
- dmabuf_temp = &state->other_states[2]->dmabuf;
- if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
- buffer, sample_s))
- return -EFAULT;
- seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
- sample_s, *copy_count);
-
- dmabuf_temp = &state->other_states[3]->dmabuf;
- if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr,
- buffer, sample_s))
- return -EFAULT;
- seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel,
- sample_s, *copy_count);
- }
-
- if (cnt_for_multi_channel > 0) {
- state->multi_channels_adjust_count = cnt_for_multi_channel / sample_s;
-
- if (copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s))
- return -EFAULT;
- seek_offset(swptr, buffer, cnt_for_multi_channel,
- sample_s, *copy_count);
- (*state_cnt) += sample_s;
-
- if (cnt_for_multi_channel > 0) {
- if (copy_from_user(dmabuf->rawbuf + swptr,
- buffer, sample_s))
- return -EFAULT;
- seek_offset(swptr, buffer, cnt_for_multi_channel,
- sample_s, *copy_count);
- (*state_cnt) += sample_s;
-
- if (cnt_for_multi_channel > 0) {
- int diff = state->chans_num - other_dma_nums;
- loop = state->multi_channels_adjust_count - diff;
- for (i = 0; i < loop; i++) {
- dmabuf_temp = &state->other_states[i]->dmabuf;
- if (copy_from_user(dmabuf_temp->rawbuf +
- dmabuf_temp->swptr,
- buffer, sample_s))
- return -EFAULT;
- seek_offset(dmabuf_temp->swptr, buffer,
- cnt_for_multi_channel,
- sample_s, *copy_count);
- }
- }
- }
- } else
- state->multi_channels_adjust_count = 0;
- }
- for (i = 0; i < other_dma_nums; i++) {
- dmabuf_temp = &state->other_states[i]->dmabuf;
- dmabuf_temp->swptr = dmabuf_temp->swptr % dmabuf_temp->dmasize;
- }
- return *state_cnt;
-}
-
-static void
-ali_free_other_states_resources(struct trident_state *state)
-{
- int i;
- struct trident_card *card = state->card;
- struct trident_state *s;
- unsigned other_states_count;
-
- other_states_count = state->chans_num - 2; /* except PCM L/R channels */
- for (i = 0; i < other_states_count; i++) {
- s = state->other_states[i];
- dealloc_dmabuf(&s->dmabuf, card->pci_dev);
- ali_disable_special_channel(s->card, s->dmabuf.channel->num);
- state->card->free_pcm_channel(s->card, s->dmabuf.channel->num);
- card->states[s->virt] = NULL;
- kfree(s);
- }
-}
-
-static struct proc_dir_entry *res;
-
-static int
-ali_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data)
-{
- struct trident_card *card = (struct trident_card *) data;
- unsigned long flags;
- char c;
-
- if (count < 0)
- return -EINVAL;
- if (count == 0)
- return 0;
- if (get_user(c, buffer))
- return -EFAULT;
-
- spin_lock_irqsave(&card->lock, flags);
- switch (c) {
- case '0':
- ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT);
- ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL);
- break;
- case '1':
- ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT |
- ALI_SPDIF_OUT_PCM);
- break;
- case '2':
- ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT |
- ALI_SPDIF_OUT_NON_PCM);
- break;
- case '3':
- ali_disable_spdif_in(card); //default
- break;
- case '4':
- ali_setup_spdif_in(card);
- break;
- }
- spin_unlock_irqrestore(&card->lock, flags);
-
- return count;
-}
-
-/* OSS /dev/mixer file operation methods */
-static int
-trident_open_mixdev(struct inode *inode, struct file *file)
-{
- int i = 0;
- int minor = iminor(inode);
- struct trident_card *card = devs;
-
- for (card = devs; card != NULL; card = card->next)
- for (i = 0; i < NR_AC97; i++)
- if (card->ac97_codec[i] != NULL &&
- card->ac97_codec[i]->dev_mixer == minor)
- goto match;
-
- if (!card) {
- return -ENODEV;
- }
- match:
- file->private_data = card->ac97_codec[i];
-
- return nonseekable_open(inode, file);
-}
-
-static int
-trident_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct ac97_codec *codec = (struct ac97_codec *) file->private_data;
-
- return codec->mixer_ioctl(codec, cmd, arg);
-}
-
-static const struct file_operations trident_mixer_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .ioctl = trident_ioctl_mixdev,
- .open = trident_open_mixdev,
-};
-
-static int
-ali_reset_5451(struct trident_card *card)
-{
- struct pci_dev *pci_dev = NULL;
- unsigned int dwVal;
- unsigned short wCount, wReg;
-
- pci_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
- pci_dev);
- if (pci_dev == NULL)
- return -1;
-
- pci_read_config_dword(pci_dev, 0x7c, &dwVal);
- pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000);
- udelay(5000);
- pci_read_config_dword(pci_dev, 0x7c, &dwVal);
- pci_write_config_dword(pci_dev, 0x7c, dwVal & 0xf7ffffff);
- udelay(5000);
- pci_dev_put(pci_dev);
-
- pci_dev = card->pci_dev;
- if (pci_dev == NULL)
- return -1;
-
- pci_read_config_dword(pci_dev, 0x44, &dwVal);
- pci_write_config_dword(pci_dev, 0x44, dwVal | 0x000c0000);
- udelay(500);
- pci_read_config_dword(pci_dev, 0x44, &dwVal);
- pci_write_config_dword(pci_dev, 0x44, dwVal & 0xfffbffff);
- udelay(5000);
-
- /* TODO: recognize if we have a PM capable codec and only do this */
- /* if the codec is PM capable */
- wCount = 2000;
- while (wCount--) {
- wReg = ali_ac97_get(card, 0, AC97_POWER_CONTROL);
- if ((wReg & 0x000f) == 0x000f)
- return 0;
- udelay(5000);
- }
- /* This is non fatal if you have a non PM capable codec.. */
- return 0;
-}
-
-/* AC97 codec initialisation. */
-static int __devinit
-trident_ac97_init(struct trident_card *card)
-{
- int num_ac97 = 0;
- unsigned long ready_2nd = 0;
- struct ac97_codec *codec;
- int i = 0;
-
- /* initialize controller side of AC link, and find out if secondary codes
- really exist */
- switch (card->pci_id) {
- case PCI_DEVICE_ID_ALI_5451:
- if (ali_reset_5451(card)) {
- printk(KERN_ERR "trident_ac97_init: error "
- "resetting 5451.\n");
- return -1;
- }
- outl(0x80000001, TRID_REG(card, ALI_GLOBAL_CONTROL));
- outl(0x00000000, TRID_REG(card, T4D_AINTEN_A));
- outl(0xffffffff, TRID_REG(card, T4D_AINT_A));
- outl(0x00000000, TRID_REG(card, T4D_MUSICVOL_WAVEVOL));
- outb(0x10, TRID_REG(card, ALI_MPUR2));
- ready_2nd = inl(TRID_REG(card, ALI_SCTRL));
- ready_2nd &= 0x3fff;
- outl(ready_2nd | PCMOUT | 0x8000, TRID_REG(card, ALI_SCTRL));
- ready_2nd = inl(TRID_REG(card, ALI_SCTRL));
- ready_2nd &= SI_AC97_SECONDARY_READY;
- if (card->revision < ALI_5451_V02)
- ready_2nd = 0;
- break;
- case PCI_DEVICE_ID_SI_7018:
- /* disable AC97 GPIO interrupt */
- outl(0x00, TRID_REG(card, SI_AC97_GPIO));
- /* when power up the AC link is in cold reset mode so stop it */
- outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT | SECONDARY_ID,
- TRID_REG(card, SI_SERIAL_INTF_CTRL));
- /* it take a long time to recover from a cold reset */
- /* (especially when you have more than one codec) */
- udelay(2000);
- ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL));
- ready_2nd &= SI_AC97_SECONDARY_READY;
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
- /* playback on */
- outl(DX_AC97_PLAYBACK, TRID_REG(card, DX_ACR2_AC97_COM_STAT));
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- /* enable AC97 Output Slot 3,4 (PCM Left/Right Playback) */
- outl(NX_AC97_PCM_OUTPUT, TRID_REG(card, NX_ACR0_AC97_COM_STAT));
- ready_2nd = inl(TRID_REG(card, NX_ACR0_AC97_COM_STAT));
- ready_2nd &= NX_AC97_SECONDARY_READY;
- break;
- case PCI_DEVICE_ID_INTERG_5050:
- /* disable AC97 GPIO interrupt */
- outl(0x00, TRID_REG(card, SI_AC97_GPIO));
- /* when power up, the AC link is in cold reset mode, so stop it */
- outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT,
- TRID_REG(card, SI_SERIAL_INTF_CTRL));
- /* it take a long time to recover from a cold reset (especially */
- /* when you have more than one codec) */
- udelay(2000);
- ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL));
- ready_2nd &= SI_AC97_SECONDARY_READY;
- break;
- }
-
- for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
- if ((codec = ac97_alloc_codec()) == NULL)
- return -ENOMEM;
-
- /* initialize some basic codec information, other fields */
- /* will be filled in ac97_probe_codec */
- codec->private_data = card;
- codec->id = num_ac97;
-
- if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
- codec->codec_read = ali_ac97_read;
- codec->codec_write = ali_ac97_write;
- } else {
- codec->codec_read = trident_ac97_get;
- codec->codec_write = trident_ac97_set;
- }
-
- if (ac97_probe_codec(codec) == 0)
- break;
-
- codec->dev_mixer = register_sound_mixer(&trident_mixer_fops, -1);
- if (codec->dev_mixer < 0) {
- printk(KERN_ERR "trident: couldn't register mixer!\n");
- ac97_release_codec(codec);
- break;
- }
-
- card->ac97_codec[num_ac97] = codec;
-
- /* if there is no secondary codec at all, don't probe any more */
- if (!ready_2nd)
- break;
- }
-
- if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
- for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
- if (card->ac97_codec[num_ac97] == NULL)
- break;
- for (i = 0; i < 64; i++) {
- u16 reg = ali_ac97_get(card, num_ac97, i * 2);
- card->mixer_regs[i][num_ac97] = reg;
- }
- }
- }
- return num_ac97 + 1;
-}
-
-#ifdef SUPPORT_JOYSTICK
-/* Gameport functions for the cards ADC gameport */
-
-static unsigned char trident_game_read(struct gameport *gameport)
-{
- struct trident_card *card = gameport->port_data;
-
- return inb(TRID_REG(card, T4D_GAME_LEG));
-}
-
-static void trident_game_trigger(struct gameport *gameport)
-{
- struct trident_card *card = gameport->port_data;
-
- outb(0xff, TRID_REG(card, T4D_GAME_LEG));
-}
-
-static int trident_game_cooked_read(struct gameport *gameport,
- int *axes, int *buttons)
-{
- struct trident_card *card = gameport->port_data;
- int i;
-
- *buttons = (~inb(TRID_REG(card, T4D_GAME_LEG)) >> 4) & 0xf;
-
- for (i = 0; i < 4; i++) {
- axes[i] = inw(TRID_REG(card, T4D_GAME_AXD) + i * sizeof (u16));
- if (axes[i] == 0xffff)
- axes[i] = -1;
- }
-
- return 0;
-}
-
-static int trident_game_open(struct gameport *gameport, int mode)
-{
- struct trident_card *card = gameport->port_data;
-
- switch (mode) {
- case GAMEPORT_MODE_COOKED:
- outb(0x80, TRID_REG(card, T4D_GAME_CR));
- msleep(20);
- return 0;
- case GAMEPORT_MODE_RAW:
- outb(0x00, TRID_REG(card, T4D_GAME_CR));
- return 0;
- default:
- return -1;
- }
-
- return 0;
-}
-
-static int __devinit trident_register_gameport(struct trident_card *card)
-{
- struct gameport *gp;
-
- card->gameport = gp = gameport_allocate_port();
- if (!gp) {
- printk(KERN_ERR "trident: can not allocate memory for gameport\n");
- return -ENOMEM;
- }
-
- gameport_set_name(gp, "Trident 4DWave");
- gameport_set_phys(gp, "pci%s/gameport0", pci_name(card->pci_dev));
- gp->read = trident_game_read;
- gp->trigger = trident_game_trigger;
- gp->cooked_read = trident_game_cooked_read;
- gp->open = trident_game_open;
- gp->fuzz = 64;
- gp->port_data = card;
-
- gameport_register_port(gp);
-
- return 0;
-}
-
-static inline void trident_unregister_gameport(struct trident_card *card)
-{
- if (card->gameport)
- gameport_unregister_port(card->gameport);
-}
-
-#else
-static inline int trident_register_gameport(struct trident_card *card) { return -ENOSYS; }
-static inline void trident_unregister_gameport(struct trident_card *card) { }
-#endif /* SUPPORT_JOYSTICK */
-
-/* install the driver, we do not allocate hardware channel nor DMA buffer */
-/* now, they are defered until "ACCESS" time (in prog_dmabuf called by */
-/* open/read/write/ioctl/mmap) */
-static int __devinit
-trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
-{
- unsigned long iobase;
- struct trident_card *card;
- u8 bits;
- u8 revision;
- int i = 0;
- u16 temp;
- struct pci_dev *pci_dev_m1533 = NULL;
- int rc = -ENODEV;
- u64 dma_mask;
-
- if (pci_enable_device(pci_dev))
- goto out;
-
- if (pci_dev->device == PCI_DEVICE_ID_ALI_5451)
- dma_mask = ALI_DMA_MASK;
- else
- dma_mask = TRIDENT_DMA_MASK;
- if (pci_set_dma_mask(pci_dev, dma_mask)) {
- printk(KERN_ERR "trident: architecture does not support"
- " %s PCI busmaster DMA\n",
- pci_dev->device == PCI_DEVICE_ID_ALI_5451 ?
- "32-bit" : "30-bit");
- goto out;
- }
- pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
-
- if (pci_id->device == PCI_DEVICE_ID_INTERG_5050)
- iobase = pci_resource_start(pci_dev, 1);
- else
- iobase = pci_resource_start(pci_dev, 0);
-
- if (!request_region(iobase, 256, card_names[pci_id->driver_data])) {
- printk(KERN_ERR "trident: can't allocate I/O space at "
- "0x%4.4lx\n", iobase);
- goto out;
- }
-
- rc = -ENOMEM;
- if ((card = kzalloc(sizeof(*card), GFP_KERNEL)) == NULL) {
- printk(KERN_ERR "trident: out of memory\n");
- goto out_release_region;
- }
-
- init_timer(&card->timer);
- card->iobase = iobase;
- card->pci_dev = pci_dev_get(pci_dev);
- card->pci_id = pci_id->device;
- card->revision = revision;
- card->irq = pci_dev->irq;
- card->next = devs;
- card->magic = TRIDENT_CARD_MAGIC;
- card->banks[BANK_A].addresses = &bank_a_addrs;
- card->banks[BANK_A].bitmap = 0UL;
- card->banks[BANK_B].addresses = &bank_b_addrs;
- card->banks[BANK_B].bitmap = 0UL;
-
- mutex_init(&card->open_mutex);
- spin_lock_init(&card->lock);
- init_timer(&card->timer);
-
- devs = card;
-
- pci_set_master(pci_dev);
-
- printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n",
- card_names[pci_id->driver_data], card->iobase, card->irq);
-
- if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
- /* ALi channel Management */
- card->alloc_pcm_channel = ali_alloc_pcm_channel;
- card->alloc_rec_pcm_channel = ali_alloc_rec_pcm_channel;
- card->free_pcm_channel = ali_free_pcm_channel;
-
- card->address_interrupt = ali_address_interrupt;
-
- /* Added by Matt Wu 01-05-2001 for spdif in */
- card->multi_channel_use_count = 0;
- card->rec_channel_use_count = 0;
-
- /* ALi SPDIF OUT function */
- if (card->revision == ALI_5451_V02) {
- ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT);
- res = create_proc_entry("ALi5451", 0, NULL);
- if (res) {
- res->write_proc = ali_write_proc;
- res->data = card;
- }
- }
-
- /* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */
- card->hwvolctl = 0;
- pci_dev_m1533 = pci_get_device(PCI_VENDOR_ID_AL,
- PCI_DEVICE_ID_AL_M1533,
- pci_dev_m1533);
- rc = -ENODEV;
- if (pci_dev_m1533 == NULL)
- goto out_proc_fs;
- pci_read_config_byte(pci_dev_m1533, 0x63, &bits);
- if (bits & (1 << 5))
- card->hwvolctl = 1;
- if (card->hwvolctl) {
- /* Clear m1533 pci cfg 78h bit 30 to zero, which makes
- GPIO11/12/13 work as ACGP_UP/DOWN/MUTE. */
- pci_read_config_byte(pci_dev_m1533, 0x7b, &bits);
- bits &= 0xbf; /*clear bit 6 */
- pci_write_config_byte(pci_dev_m1533, 0x7b, bits);
- }
- pci_dev_put(pci_dev_m1533);
-
- } else if (card->pci_id == PCI_DEVICE_ID_INTERG_5050) {
- card->alloc_pcm_channel = cyber_alloc_pcm_channel;
- card->alloc_rec_pcm_channel = cyber_alloc_pcm_channel;
- card->free_pcm_channel = cyber_free_pcm_channel;
- card->address_interrupt = cyber_address_interrupt;
- cyber_init_ritual(card);
- } else {
- card->alloc_pcm_channel = trident_alloc_pcm_channel;
- card->alloc_rec_pcm_channel = trident_alloc_pcm_channel;
- card->free_pcm_channel = trident_free_pcm_channel;
- card->address_interrupt = trident_address_interrupt;
- }
-
- /* claim our irq */
- rc = -ENODEV;
- if (request_irq(card->irq, &trident_interrupt, IRQF_SHARED,
- card_names[pci_id->driver_data], card)) {
- printk(KERN_ERR "trident: unable to allocate irq %d\n",
- card->irq);
- goto out_proc_fs;
- }
- /* register /dev/dsp */
- if ((card->dev_audio = register_sound_dsp(&trident_audio_fops, -1)) < 0) {
- printk(KERN_ERR "trident: couldn't register DSP device!\n");
- goto out_free_irq;
- }
- card->mixer_regs_ready = 0;
- /* initialize AC97 codec and register /dev/mixer */
- if (trident_ac97_init(card) <= 0) {
- /* unregister audio devices */
- for (i = 0; i < NR_AC97; i++) {
- if (card->ac97_codec[i] != NULL) {
- struct ac97_codec* codec = card->ac97_codec[i];
- unregister_sound_mixer(codec->dev_mixer);
- ac97_release_codec(codec);
- }
- }
- goto out_unregister_sound_dsp;
- }
- card->mixer_regs_ready = 1;
- outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL));
-
- if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
- /* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */
- if (card->hwvolctl) {
- /* Enable GPIO IRQ (MISCINT bit 18h) */
- temp = inw(TRID_REG(card, T4D_MISCINT + 2));
- temp |= 0x0004;
- outw(temp, TRID_REG(card, T4D_MISCINT + 2));
-
- /* Enable H/W Volume Control GLOVAL CONTROL bit 0 */
- temp = inw(TRID_REG(card, ALI_GLOBAL_CONTROL));
- temp |= 0x0001;
- outw(temp, TRID_REG(card, ALI_GLOBAL_CONTROL));
-
- }
- if (card->revision == ALI_5451_V02)
- ali_close_multi_channels();
- /* edited by HMSEO for GT sound */
-#if defined(CONFIG_ALPHA_NAUTILUS) || defined(CONFIG_ALPHA_GENERIC)
- {
- u16 ac97_data;
- extern struct hwrpb_struct *hwrpb;
-
- if ((hwrpb->sys_type) == 201) {
- printk(KERN_INFO "trident: Running on Alpha system "
- "type Nautilus\n");
- ac97_data = ali_ac97_get(card, 0, AC97_POWER_CONTROL);
- ali_ac97_set(card, 0, AC97_POWER_CONTROL,
- ac97_data | ALI_EAPD_POWER_DOWN);
- }
- }
-#endif /* CONFIG_ALPHA_NAUTILUS || CONFIG_ALPHA_GENERIC */
- /* edited by HMSEO for GT sound */
- }
- rc = 0;
- pci_set_drvdata(pci_dev, card);
-
- /* Enable Address Engine Interrupts */
- trident_enable_loop_interrupts(card);
-
- /* Register gameport */
- trident_register_gameport(card);
-
-out:
- return rc;
-
-out_unregister_sound_dsp:
- unregister_sound_dsp(card->dev_audio);
-out_free_irq:
- free_irq(card->irq, card);
-out_proc_fs:
- pci_dev_put(card->pci_dev);
- if (res) {
- remove_proc_entry("ALi5451", NULL);
- res = NULL;
- }
- kfree(card);
- devs = NULL;
-out_release_region:
- release_region(iobase, 256);
- return rc;
-}
-
-static void __devexit
-trident_remove(struct pci_dev *pci_dev)
-{
- int i;
- struct trident_card *card = pci_get_drvdata(pci_dev);
-
- /*
- * Kill running timers before unload. We can't have them
- * going off after rmmod!
- */
- if (card->hwvolctl)
- del_timer_sync(&card->timer);
-
- /* ALi S/PDIF and Power Management */
- if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
- ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT);
- ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL);
- ali_disable_spdif_in(card);
- remove_proc_entry("ALi5451", NULL);
- }
-
- /* Unregister gameport */
- trident_unregister_gameport(card);
-
- /* Kill interrupts, and SP/DIF */
- trident_disable_loop_interrupts(card);
-
- /* free hardware resources */
- free_irq(card->irq, card);
- release_region(card->iobase, 256);
-
- /* unregister audio devices */
- for (i = 0; i < NR_AC97; i++)
- if (card->ac97_codec[i] != NULL) {
- unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
- ac97_release_codec(card->ac97_codec[i]);
- }
- unregister_sound_dsp(card->dev_audio);
-
- pci_set_drvdata(pci_dev, NULL);
- pci_dev_put(card->pci_dev);
- kfree(card);
-}
-
-MODULE_AUTHOR("Alan Cox, Aaron Holtzman, Ollie Lho, Ching Ling Lee, Muli Ben-Yehuda");
-MODULE_DESCRIPTION("Trident 4DWave/SiS 7018/ALi 5451 and Tvia/IGST CyberPro5050 PCI "
- "Audio Driver");
-MODULE_LICENSE("GPL");
-
-#define TRIDENT_MODULE_NAME "trident"
-
-static struct pci_driver trident_pci_driver = {
- .name = TRIDENT_MODULE_NAME,
- .id_table = trident_pci_tbl,
- .probe = trident_probe,
- .remove = __devexit_p(trident_remove),
-#ifdef CONFIG_PM
- .suspend = trident_suspend,
- .resume = trident_resume
-#endif
-};
-
-static int __init
-trident_init_module(void)
-{
- printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro "
- "5050 PCI Audio, version " DRIVER_VERSION ", " __TIME__ " "
- __DATE__ "\n");
-
- return pci_register_driver(&trident_pci_driver);
-}
-
-static void __exit
-trident_cleanup_module(void)
-{
- pci_unregister_driver(&trident_pci_driver);
-}
-
-module_init(trident_init_module);
-module_exit(trident_cleanup_module);
diff --git a/sound/oss/trident.h b/sound/oss/trident.h
deleted file mode 100644
index ff30a1d7c2f..00000000000
--- a/sound/oss/trident.h
+++ /dev/null
@@ -1,358 +0,0 @@
-#ifndef __TRID4DWAVE_H
-#define __TRID4DWAVE_H
-
-/*
- * audio@tridentmicro.com
- * Fri Feb 19 15:55:28 MST 1999
- * Definitions for Trident 4DWave DX/NX chips
- *
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-/* PCI vendor and device ID */
-#ifndef PCI_VENDOR_ID_TRIDENT
-#define PCI_VENDOR_ID_TRIDENT 0x1023
-#endif
-
-#ifndef PCI_VENDOR_ID_SI
-#define PCI_VENDOR_ID_SI 0x1039
-#endif
-
-#ifndef PCI_VENDOR_ID_ALI
-#define PCI_VENDOR_ID_ALI 0x10b9
-#endif
-
-#ifndef PCI_DEVICE_ID_TRIDENT_4DWAVE_DX
-#define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000
-#endif
-
-#ifndef PCI_DEVICE_ID_TRIDENT_4DWAVE_NX
-#define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX 0x2001
-#endif
-
-#ifndef PCI_DEVICE_ID_SI_7018
-#define PCI_DEVICE_ID_SI_7018 0x7018
-#endif
-
-#ifndef PCI_DEVICE_ID_ALI_5451
-#define PCI_DEVICE_ID_ALI_5451 0x5451
-#endif
-
-#ifndef PCI_DEVICE_ID_ALI_1533
-#define PCI_DEVICE_ID_ALI_1533 0x1533
-#endif
-
-#define CHANNEL_REGS 5
-#define CHANNEL_START 0xe0 // The first bytes of the contiguous register space.
-
-#define BANK_A 0
-#define BANK_B 1
-#define NR_BANKS 2
-
-#define TRIDENT_FMT_STEREO 0x01
-#define TRIDENT_FMT_16BIT 0x02
-#define TRIDENT_FMT_MASK 0x03
-
-#define DAC_RUNNING 0x01
-#define ADC_RUNNING 0x02
-
-/* Register Addresses */
-
-/* operational registers common to DX, NX, 7018 */
-enum trident_op_registers {
- T4D_GAME_CR = 0x30, T4D_GAME_LEG = 0x31,
- T4D_GAME_AXD = 0x34,
- T4D_REC_CH = 0x70,
- T4D_START_A = 0x80, T4D_STOP_A = 0x84,
- T4D_DLY_A = 0x88, T4D_SIGN_CSO_A = 0x8c,
- T4D_CSPF_A = 0x90, T4D_CEBC_A = 0x94,
- T4D_AINT_A = 0x98, T4D_EINT_A = 0x9c,
- T4D_LFO_GC_CIR = 0xa0, T4D_AINTEN_A = 0xa4,
- T4D_MUSICVOL_WAVEVOL = 0xa8, T4D_SBDELTA_DELTA_R = 0xac,
- T4D_MISCINT = 0xb0, T4D_START_B = 0xb4,
- T4D_STOP_B = 0xb8, T4D_CSPF_B = 0xbc,
- T4D_SBBL_SBCL = 0xc0, T4D_SBCTRL_SBE2R_SBDD = 0xc4,
- T4D_STIMER = 0xc8, T4D_LFO_B_I2S_DELTA = 0xcc,
- T4D_AINT_B = 0xd8, T4D_AINTEN_B = 0xdc,
- ALI_MPUR2 = 0x22, ALI_GPIO = 0x7c,
- ALI_EBUF1 = 0xf4,
- ALI_EBUF2 = 0xf8
-};
-
-enum ali_op_registers {
- ALI_SCTRL = 0x48,
- ALI_GLOBAL_CONTROL = 0xd4,
- ALI_STIMER = 0xc8,
- ALI_SPDIF_CS = 0x70,
- ALI_SPDIF_CTRL = 0x74
-};
-
-enum ali_registers_number {
- ALI_GLOBAL_REGS = 56,
- ALI_CHANNEL_REGS = 8,
- ALI_MIXER_REGS = 20
-};
-
-enum ali_sctrl_control_bit {
- ALI_SPDIF_OUT_ENABLE = 0x20
-};
-
-enum ali_global_control_bit {
- ALI_SPDIF_OUT_SEL_PCM = 0x00000400,
- ALI_SPDIF_IN_SUPPORT = 0x00000800,
- ALI_SPDIF_OUT_CH_ENABLE = 0x00008000,
- ALI_SPDIF_IN_CH_ENABLE = 0x00080000,
- ALI_PCM_IN_DISABLE = 0x7fffffff,
- ALI_PCM_IN_ENABLE = 0x80000000,
- ALI_SPDIF_IN_CH_DISABLE = 0xfff7ffff,
- ALI_SPDIF_OUT_CH_DISABLE = 0xffff7fff,
- ALI_SPDIF_OUT_SEL_SPDIF = 0xfffffbff
-
-};
-
-enum ali_spdif_control_bit {
- ALI_SPDIF_IN_FUNC_ENABLE = 0x02,
- ALI_SPDIF_IN_CH_STATUS = 0x40,
- ALI_SPDIF_OUT_CH_STATUS = 0xbf
-
-};
-
-enum ali_control_all {
- ALI_DISABLE_ALL_IRQ = 0,
- ALI_CHANNELS = 32,
- ALI_STOP_ALL_CHANNELS = 0xffffffff,
- ALI_MULTI_CHANNELS_START_STOP = 0x07800000
-};
-
-enum ali_EMOD_control_bit {
- ALI_EMOD_DEC = 0x00000000,
- ALI_EMOD_INC = 0x10000000,
- ALI_EMOD_Delay = 0x20000000,
- ALI_EMOD_Still = 0x30000000
-};
-
-enum ali_pcm_in_channel_num {
- ALI_NORMAL_CHANNEL = 0,
- ALI_SPDIF_OUT_CHANNEL = 15,
- ALI_SPDIF_IN_CHANNEL = 19,
- ALI_LEF_CHANNEL = 23,
- ALI_CENTER_CHANNEL = 24,
- ALI_SURR_RIGHT_CHANNEL = 25,
- ALI_SURR_LEFT_CHANNEL = 26,
- ALI_PCM_IN_CHANNEL = 31
-};
-
-enum ali_pcm_out_channel_num {
- ALI_PCM_OUT_CHANNEL_FIRST = 0,
- ALI_PCM_OUT_CHANNEL_LAST = 31
-};
-
-enum ali_ac97_power_control_bit {
- ALI_EAPD_POWER_DOWN = 0x8000
-};
-
-enum ali_update_ptr_flags {
- ALI_ADDRESS_INT_UPDATE = 0x01
-};
-
-enum ali_revision {
- ALI_5451_V02 = 0x02
-};
-
-enum ali_spdif_out_control {
- ALI_PCM_TO_SPDIF_OUT = 0,
- ALI_SPDIF_OUT_TO_SPDIF_OUT = 1,
- ALI_SPDIF_OUT_PCM = 0,
- ALI_SPDIF_OUT_NON_PCM = 2
-};
-
-/* S/PDIF Operational Registers for 4D-NX */
-enum nx_spdif_registers {
- NX_SPCTRL_SPCSO = 0x24, NX_SPLBA = 0x28,
- NX_SPESO = 0x2c, NX_SPCSTATUS = 0x64
-};
-
-/* OP registers to access each hardware channel */
-enum channel_registers {
- CH_DX_CSO_ALPHA_FMS = 0xe0, CH_DX_ESO_DELTA = 0xe8,
- CH_DX_FMC_RVOL_CVOL = 0xec,
- CH_NX_DELTA_CSO = 0xe0, CH_NX_DELTA_ESO = 0xe8,
- CH_NX_ALPHA_FMS_FMC_RVOL_CVOL = 0xec,
- CH_LBA = 0xe4,
- CH_GVSEL_PAN_VOL_CTRL_EC = 0xf0
-};
-
-/* registers to read/write/control AC97 codec */
-enum dx_ac97_registers {
- DX_ACR0_AC97_W = 0x40, DX_ACR1_AC97_R = 0x44,
- DX_ACR2_AC97_COM_STAT = 0x48
-};
-
-enum nx_ac97_registers {
- NX_ACR0_AC97_COM_STAT = 0x40, NX_ACR1_AC97_W = 0x44,
- NX_ACR2_AC97_R_PRIMARY = 0x48, NX_ACR3_AC97_R_SECONDARY = 0x4c
-};
-
-enum si_ac97_registers {
- SI_AC97_WRITE = 0x40, SI_AC97_READ = 0x44,
- SI_SERIAL_INTF_CTRL = 0x48, SI_AC97_GPIO = 0x4c
-};
-
-enum ali_ac97_registers {
- ALI_AC97_WRITE = 0x40, ALI_AC97_READ = 0x44
-};
-
-/* Bit mask for operational registers */
-#define AC97_REG_ADDR 0x000000ff
-
-enum ali_ac97_bits {
- ALI_AC97_BUSY_WRITE = 0x8000, ALI_AC97_BUSY_READ = 0x8000,
- ALI_AC97_WRITE_ACTION = 0x8000, ALI_AC97_READ_ACTION = 0x8000,
- ALI_AC97_AUDIO_BUSY = 0x4000, ALI_AC97_SECONDARY = 0x0080,
- ALI_AC97_READ_MIXER_REGISTER = 0xfeff,
- ALI_AC97_WRITE_MIXER_REGISTER = 0x0100
-};
-
-enum sis7018_ac97_bits {
- SI_AC97_BUSY_WRITE = 0x8000, SI_AC97_BUSY_READ = 0x8000,
- SI_AC97_AUDIO_BUSY = 0x4000, SI_AC97_MODEM_BUSY = 0x2000,
- SI_AC97_SECONDARY = 0x0080
-};
-
-enum trident_dx_ac97_bits {
- DX_AC97_BUSY_WRITE = 0x8000, DX_AC97_BUSY_READ = 0x8000,
- DX_AC97_READY = 0x0010, DX_AC97_RECORD = 0x0008,
- DX_AC97_PLAYBACK = 0x0002
-};
-
-enum trident_nx_ac97_bits {
- /* ACR1-3 */
- NX_AC97_BUSY_WRITE = 0x0800, NX_AC97_BUSY_READ = 0x0800,
- NX_AC97_BUSY_DATA = 0x0400, NX_AC97_WRITE_SECONDARY = 0x0100,
- /* ACR0 */
- NX_AC97_SECONDARY_READY = 0x0040, NX_AC97_SECONDARY_RECORD = 0x0020,
- NX_AC97_SURROUND_OUTPUT = 0x0010,
- NX_AC97_PRIMARY_READY = 0x0008, NX_AC97_PRIMARY_RECORD = 0x0004,
- NX_AC97_PCM_OUTPUT = 0x0002,
- NX_AC97_WARM_RESET = 0x0001
-};
-
-enum serial_intf_ctrl_bits {
- WARM_REST = 0x00000001, COLD_RESET = 0x00000002,
- I2S_CLOCK = 0x00000004, PCM_SEC_AC97= 0x00000008,
- AC97_DBL_RATE = 0x00000010, SPDIF_EN = 0x00000020,
- I2S_OUTPUT_EN = 0x00000040, I2S_INPUT_EN = 0x00000080,
- PCMIN = 0x00000100, LINE1IN = 0x00000200,
- MICIN = 0x00000400, LINE2IN = 0x00000800,
- HEAD_SET_IN = 0x00001000, GPIOIN = 0x00002000,
- /* 7018 spec says id = 01 but the demo board routed to 10
- SECONDARY_ID= 0x00004000, */
- SECONDARY_ID= 0x00004000,
- PCMOUT = 0x00010000, SURROUT = 0x00020000,
- CENTEROUT = 0x00040000, LFEOUT = 0x00080000,
- LINE1OUT = 0x00100000, LINE2OUT = 0x00200000,
- GPIOOUT = 0x00400000,
- SI_AC97_PRIMARY_READY = 0x01000000,
- SI_AC97_SECONDARY_READY = 0x02000000,
-};
-
-enum global_control_bits {
- CHANNLE_IDX = 0x0000003f, PB_RESET = 0x00000100,
- PAUSE_ENG = 0x00000200,
- OVERRUN_IE = 0x00000400, UNDERRUN_IE = 0x00000800,
- ENDLP_IE = 0x00001000, MIDLP_IE = 0x00002000,
- ETOG_IE = 0x00004000,
- EDROP_IE = 0x00008000, BANK_B_EN = 0x00010000
-};
-
-enum channel_control_bits {
- CHANNEL_LOOP = 0x00001000, CHANNEL_SIGNED = 0x00002000,
- CHANNEL_STEREO = 0x00004000, CHANNEL_16BITS = 0x00008000,
-};
-
-enum channel_attribute {
- /* playback/record select */
- CHANNEL_PB = 0x0000, CHANNEL_SPC_PB = 0x4000,
- CHANNEL_REC = 0x8000, CHANNEL_REC_PB = 0xc000,
- /* playback destination/record source select */
- MODEM_LINE1 = 0x0000, MODEM_LINE2 = 0x0400,
- PCM_LR = 0x0800, HSET = 0x0c00,
- I2S_LR = 0x1000, CENTER_LFE = 0x1400,
- SURR_LR = 0x1800, SPDIF_LR = 0x1c00,
- MIC = 0x1400,
- /* mist stuff */
- MONO_LEFT = 0x0000, MONO_RIGHT = 0x0100,
- MONO_MIX = 0x0200, SRC_ENABLE = 0x0080,
-};
-
-enum miscint_bits {
- PB_UNDERRUN_IRO = 0x00000001, REC_OVERRUN_IRQ = 0x00000002,
- SB_IRQ = 0x00000004, MPU401_IRQ = 0x00000008,
- OPL3_IRQ = 0x00000010, ADDRESS_IRQ = 0x00000020,
- ENVELOPE_IRQ = 0x00000040, ST_IRQ = 0x00000080,
- PB_UNDERRUN = 0x00000100, REC_OVERRUN = 0x00000200,
- MIXER_UNDERFLOW = 0x00000400, MIXER_OVERFLOW = 0x00000800,
- ST_TARGET_REACHED = 0x00008000, PB_24K_MODE = 0x00010000,
- ST_IRQ_EN = 0x00800000, ACGPIO_IRQ = 0x01000000
-};
-
-#define TRID_REG( trident, x ) ( (trident) -> iobase + (x) )
-
-#define CYBER_PORT_AUDIO 0x3CE
-#define CYBER_IDX_AUDIO_ENABLE 0x7B
-#define CYBER_BMSK_AUDIO_INT_ENABLE 0x09
-#define CYBER_BMSK_AUENZ 0x01
-#define CYBER_BMSK_AUENZ_ENABLE 0x00
-#define CYBER_IDX_IRQ_ENABLE 0x12
-
-#define VALIDATE_MAGIC(FOO,MAG) \
-({ \
- if (!(FOO) || (FOO)->magic != MAG) { \
- printk(invalid_magic,__func__); \
- return -ENXIO; \
- } \
-})
-
-#define VALIDATE_STATE(a) VALIDATE_MAGIC(a,TRIDENT_STATE_MAGIC)
-#define VALIDATE_CARD(a) VALIDATE_MAGIC(a,TRIDENT_CARD_MAGIC)
-
-static inline unsigned ld2(unsigned int x)
-{
- unsigned r = 0;
-
- if (x >= 0x10000) {
- x >>= 16;
- r += 16;
- }
- if (x >= 0x100) {
- x >>= 8;
- r += 8;
- }
- if (x >= 0x10) {
- x >>= 4;
- r += 4;
- }
- if (x >= 4) {
- x >>= 2;
- r += 2;
- }
- if (x >= 2)
- r++;
- return r;
-}
-
-#endif /* __TRID4DWAVE_H */
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index 12f6ac99b04..9212c37a33b 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -48,6 +48,7 @@ config SND_PXA2XX_SOC_POODLE
config SND_PXA2XX_SOC_TOSA
tristate "SoC AC97 Audio support for Tosa"
depends on SND_PXA2XX_SOC && MACH_TOSA
+ depends on MFD_TC6393XB
select SND_PXA2XX_SOC_AC97
select SND_SOC_WM9712
help
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index b6edb61a3a3..fe6cca9c9e7 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -21,6 +21,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/device.h>
+#include <linux/gpio.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -28,7 +29,7 @@
#include <sound/soc-dapm.h>
#include <asm/mach-types.h>
-#include <asm/hardware/tmio.h>
+#include <asm/arch/tosa.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/hardware.h>
#include <asm/arch/audio.h>
@@ -137,10 +138,7 @@ static int tosa_set_spk(struct snd_kcontrol *kcontrol,
static int tosa_hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
{
- if (SND_SOC_DAPM_EVENT_ON(event))
- set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_L_MUTE);
- else
- reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_L_MUTE);
+ gpio_set_value(TOSA_GPIO_L_MUTE, SND_SOC_DAPM_EVENT_ON(event) ? 1 :0);
return 0;
}
@@ -254,16 +252,28 @@ static int __init tosa_init(void)
if (!machine_is_tosa())
return -ENODEV;
+ ret = gpio_request(TOSA_GPIO_L_MUTE, "Headphone Jack");
+ if (ret)
+ return ret;
+ gpio_direction_output(TOSA_GPIO_L_MUTE, 0);
+
tosa_snd_device = platform_device_alloc("soc-audio", -1);
- if (!tosa_snd_device)
- return -ENOMEM;
+ if (!tosa_snd_device) {
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
platform_set_drvdata(tosa_snd_device, &tosa_snd_devdata);
tosa_snd_devdata.dev = &tosa_snd_device->dev;
ret = platform_device_add(tosa_snd_device);
- if (ret)
- platform_device_put(tosa_snd_device);
+ if (!ret)
+ return 0;
+
+ platform_device_put(tosa_snd_device);
+
+err_alloc:
+ gpio_free(TOSA_GPIO_L_MUTE);
return ret;
}
@@ -271,6 +281,7 @@ static int __init tosa_init(void)
static void __exit tosa_exit(void)
{
platform_device_unregister(tosa_snd_device);
+ gpio_free(TOSA_GPIO_L_MUTE);
}
module_init(tosa_init);
diff --git a/sound/sound_core.c b/sound/sound_core.c
index dcfc1d5ce63..1b04259a432 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -171,8 +171,9 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati
else
sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
- device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
- s->name+6);
+ device_create_drvdata(sound_class, dev,
+ MKDEV(SOUND_MAJOR, s->unit_minor),
+ NULL, s->name+6);
return r;
fail:
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 904d7b7bd78..a845890b680 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -902,7 +902,7 @@ static const struct file_operations kvm_vcpu_fops = {
*/
static int create_vcpu_fd(struct kvm_vcpu *vcpu)
{
- int fd = anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu);
+ int fd = anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, 0);
if (fd < 0)
kvm_put_kvm(vcpu->kvm);
return fd;
@@ -1261,7 +1261,7 @@ static int kvm_dev_ioctl_create_vm(void)
kvm = kvm_create_vm();
if (IS_ERR(kvm))
return PTR_ERR(kvm);
- fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm);
+ fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, 0);
if (fd < 0)
kvm_put_kvm(kvm);